Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
81 changes: 46 additions & 35 deletions core/src/components/accordion/accordion.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,10 @@ function createItems(accordion: AccordionWidget, n = 3): AccordionItemWidget[] {
for (let i = 0; i < n; i++) {
items.push(accordion.api.registerItem());
}
items.forEach((i) => i.directives.itemDirective(el));
items.forEach((i) => {
i.directives.itemDirective(el);
i.directives.bodyContainerDirective(el);
});
return items;
}

Expand Down Expand Up @@ -125,38 +128,44 @@ describe(`Accordion`, () => {
button.click();
});

test(`should expand all the items and close them`, () => {
test(`should expand all the items and close them`, async () => {
const el = document.createElement('div');
accordion.api.registerItem().directives.itemDirective(el);
accordion.api.registerItem().directives.itemDirective(el);
accordion.api.registerItem().directives.itemDirective(el);
const item1 = accordion.api.registerItem();
const item2 = accordion.api.registerItem();
const item3 = accordion.api.registerItem();
item1.directives.itemDirective(el);
item1.directives.bodyContainerDirective(el);
item2.directives.itemDirective(el);
item2.directives.bodyContainerDirective(el);
item3.directives.itemDirective(el);
item3.directives.bodyContainerDirective(el);
expectOpenItems(state, [false, false, false]);
accordion.api.expandAll();
await accordion.api.expandAll();
expectOpenItems(state, [true, true, true]);
accordion.api.collapseAll();
await accordion.api.collapseAll();
expectOpenItems(state, [false, false, false]);
});

test(`should toggle items from accordion api`, () => {
test(`should toggle items from accordion api`, async () => {
const items = createItems(accordion);
const itemIds = items.map((i) => i.state$().id);
expectOpenItems(state, [false, false, false]);
accordion.api.expand(itemIds[0]);
accordion.api.expand(itemIds[2]);
await accordion.api.expand(itemIds[0]);
await accordion.api.expand(itemIds[2]);
expectOpenItems(state, [true, false, true]);
accordion.api.toggle(itemIds[1]);
accordion.api.collapse(itemIds[2]);
await accordion.api.toggle(itemIds[1]);
await accordion.api.collapse(itemIds[2]);
expectOpenItems(state, [true, true, false]);
});

test(`should toggle items with item api`, () => {
test(`should toggle items with item api`, async () => {
const items = createItems(accordion);
expectOpenItems(state, [false, false, false]);
items[0].api.expand();
items[2].api.expand();
await items[0].api.expand();
await items[2].api.expand();
expectOpenItems(state, [true, false, true]);
items[1].api.toggle();
items[2].api.collapse();
await items[1].api.toggle();
await items[2].api.collapse();
expectOpenItems(state, [true, true, false]);
});

Expand All @@ -167,12 +176,12 @@ describe(`Accordion`, () => {
i.directives.bodyContainerDirective(element);
expectOpenItems(state, [false]);
//calling it twice to ensure only one event is fired
i.api.toggle();
i.api.expand();
void i.api.toggle();
void i.api.expand();
await promiseOnShownItem.promise;
expectOpenItems(state, [true]);
i.api.toggle();
i.api.collapse();
void i.api.toggle();
void i.api.collapse();
await promiseOnHiddenItem.promise;
expectOpenItems(state, [false]);
expect(itemShown).toBe(1);
Expand All @@ -188,10 +197,10 @@ describe(`Accordion`, () => {
bodyContainerDirective(element);
itemDirective(element);
expectOpenItems(state, [false]);
accordion.api.toggle(id$());
accordion.api.expand(id$());
void accordion.api.toggle(id$());
void accordion.api.expand(id$());
await promiseOnShown.promise;
accordion.api.collapse(id$());
void accordion.api.collapse(id$());
await promiseOnHidden.promise;
expect(showns).toMatchObject([id$()]);
expect(hiddens).toMatchObject([id$()]);
Expand All @@ -208,7 +217,7 @@ describe(`Accordion`, () => {
expectOpenItems(state, [true, true, false]);
});

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

// item api
items[1].api.expand();
await items[1].api.expand();
expectOpenItems(state, [false, true]);

// accordion api
accordion.api.expand(items[0].state$().id);
await accordion.api.expand(items[0].state$().id);
expectOpenItems(state, [true, false]);
});

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

test(`should have correct value for shouldBeInDOM`, () => {
test(`should have correct value for shouldBeInDOM`, async () => {
const el = document.createElement('div');
const i = accordion.api.registerItem({props: {visible: true}});
i.directives.bodyContainerDirective(el);
expect(i.state$().shouldBeInDOM).toBe(true);
i.api.collapse();
await i.api.collapse();
expect(i.state$().shouldBeInDOM).toBe(false);
i.patch({destroyOnHide: false});
expect(i.state$().shouldBeInDOM).toBe(true);
});

test(`should closeOthers work when oldOpen is undefined`, () => {
test(`should closeOthers work when oldOpen is undefined`, async () => {
const element = document.createElement('div');
accordion.directives.accordionDirective(element);
const items = createItems(accordion, 4);
items[0].api.expand();
items[1].api.expand();
await items[0].api.expand();
await items[1].api.expand();
expectOpenItems(state, [true, true, false, false]);
//oldOpenItem is undefined because initially openItems was [] and the first value of
//oldOpenItem is openItems[0]
accordion.patch({closeOthers: true});
expectOpenItems(state, [false, true, false, false]);
});

test(`should call initDone to enable the transition on item`, () => {
test(`should call initDone to enable the transition on item`, async () => {
const el = document.createElement('div');
const transition = vi.fn();
const itemWidget = accordion.api.registerItem({props: {transition}});
itemWidget.directives.itemDirective(el);
itemWidget.directives.bodyContainerDirective(el);
expectOpenItems(state, [false]);
itemWidget.api.expand();
await itemWidget.api.expand();
expectOpenItems(state, [true]);
expect(transition.mock.calls[transition.mock.calls.length - 1].slice(1, 3)).toEqual(['show', false]);
itemWidget.api.initDone();
itemWidget.api.collapse();
await itemWidget.api.collapse();
expectOpenItems(state, [false]);
expect(transition.mock.calls[transition.mock.calls.length - 1].slice(1, 3)).toEqual(['hide', true]);
});
Expand Down
60 changes: 32 additions & 28 deletions core/src/components/accordion/accordion.ts
Original file line number Diff line number Diff line change
Expand Up @@ -160,34 +160,41 @@ export interface AccordionApi {
* Given the itemId, will expand the corresponding accordion-item.
*
* If the itemId is not valid, nothing will happen.
* @returns A promise that resolves when the expand operation is completed.
*/
expand(itemId: string): void;
expand(itemId: string): Promise<void>;

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

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

/**
* It will expand all the items in the accordion.
*
* If `closeOthers` is `true` it will expand only the last accordion-item.
*
* @returns A promise that resolves when all the expand operations are completed.
*/
expandAll(): void;
expandAll(): Promise<void>;

/**
* It will collapse all the accordion-items in the accordion.
*
* @returns A promise that resolves when all the collapse operations are completed.
*/
collapseAll(): void;
collapseAll(): Promise<void>;

/**
* Creates a new accordionItem.
Expand Down Expand Up @@ -216,18 +223,21 @@ export type AccordionWidget = Widget<AccordionProps, AccordionState, AccordionAp
export interface AccordionItemApi {
/**
* It will collapse the accordion-item.
* @returns A promise that resolves when the collapse operation is completed.
*/
collapse(): void;
collapse(): Promise<void>;

/**
* It will expand the accordion-item.
* @returns A promise that resolves when the expand operation is completed.
*/
expand(): void;
expand(): Promise<void>;

/**
* It will toggle the accordion-item.
* @returns A promise that resolves when the toggle operation is completed.
*/
toggle(): void;
toggle(): Promise<void>;

/**
* Method to be called after the initialization to allow animations.
Expand Down Expand Up @@ -498,7 +508,7 @@ export function createAccordionItem(config?: PropsConfig<AccordionItemProps>): A
events: {
click: () => {
if (!disabled$()) {
visible$.update((c: boolean) => !c);
void transition.api.toggle();
}
},
},
Expand Down Expand Up @@ -530,15 +540,9 @@ export function createAccordionItem(config?: PropsConfig<AccordionItemProps>): A
initDone: () => {
initDone$.set(true);
},
collapse: () => {
visible$.set(false);
},
expand: () => {
visible$.set(true);
},
toggle: () => {
visible$.update((c: boolean) => !c);
},
collapse: transition.api.hide,
expand: transition.api.show,
toggle: transition.api.toggle,
},
directives: {
toggleDirective,
Expand Down Expand Up @@ -610,20 +614,20 @@ export function factoryCreateAccordion(
...stateStores({itemWidgets$, className$}),
patch,
api: {
expand: (id: string) => {
getItem(itemWidgets$(), id)?.api.expand();
expand: async (id: string) => {
await getItem(itemWidgets$(), id)?.api.expand();
},
collapse: (id: string) => {
getItem(itemWidgets$(), id)?.api.collapse();
collapse: async (id: string) => {
await getItem(itemWidgets$(), id)?.api.collapse();
},
toggle: (id: string) => {
getItem(itemWidgets$(), id)?.api.toggle();
toggle: async (id: string) => {
await getItem(itemWidgets$(), id)?.api.toggle();
},
expandAll: () => {
itemWidgets$().forEach((i) => i.api.expand());
expandAll: async () => {
await Promise.all(itemWidgets$().map((i) => i.api.expand()));
},
collapseAll: () => {
itemWidgets$().forEach((i) => i.api.collapse());
collapseAll: async () => {
await Promise.all(itemWidgets$().map((i) => i.api.collapse()));
},
registerItem: (propsConfig?: PropsConfig<AccordionItemProps>) => {
const itemProps = accordionItemProps as (keyof AccordionItemProps)[];
Expand Down
2 changes: 1 addition & 1 deletion react/demo/src/daisyui/samples/accordion/Accordion.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ export const AccordionItem = (
useEffect(() => api.initDone(), [api]);
const onEnter = (e: KeyboardEvent<HTMLDivElement>) => {
if (e.key === 'Enter') {
api.toggle();
void api.toggle();
}
};

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@

const onkeydown = (e: KeyboardEvent) => {
if (e.key === 'Enter') {
toggle();
void toggle();
}
};
onMount(widget.api.initDone);
Expand Down
Loading