Skip to content

Commit 913ad0c

Browse files
feat: Add toggle group support (#2195)
* Add toggle group support * Update version and changelog * Fix * Simplify * Update test/cypress/tests/utils/popover.spec.ts Co-authored-by: Peter Savchenko <specc.dev@gmail.com> Co-authored-by: Peter Savchenko <specc.dev@gmail.com>
1 parent 320a30a commit 913ad0c

File tree

5 files changed

+125
-7
lines changed

5 files changed

+125
-7
lines changed

docs/CHANGELOG.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,9 @@
11
# Changelog
22

33

4+
### 2.26.1
5+
- `Improvement`*Menu Config* — Now it becomes possible to create toggle groups.
6+
47
### 2.26.0
58

69
- `New`*UI* — Block Tunes became vertical just like the Toolbox 🤩

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "@editorjs/editorjs",
3-
"version": "2.26.0",
3+
"version": "2.26.1",
44
"description": "Editor.js — Native JS, based on API and Open Source",
55
"main": "dist/editor.js",
66
"types": "./types/index.d.ts",

src/components/utils/popover.ts

Lines changed: 42 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -491,16 +491,54 @@ export default class Popover extends EventsDispatcher<PopoverEvent> {
491491
}
492492
clickedItem.onActivate(clickedItem, event);
493493

494-
if (clickedItem.toggle) {
495-
clickedItem.isActive = !clickedItem.isActive;
496-
itemEl.classList.toggle(Popover.CSS.itemActive);
497-
}
494+
this.toggleIfNeeded(itemIndex, allItems);
498495

499496
if (clickedItem.closeOnActivate) {
500497
this.hide();
501498
}
502499
}
503500

501+
/**
502+
* - Toggles item active state, if the item has property 'toggle' set to true.
503+
*
504+
* - Performs radiobutton-like behavior if the item has property 'toggle' set to string key.
505+
* (All the other items with the same key get unactive, and the item gets active)
506+
*
507+
* @param index - clicked item index
508+
* @param itemEls - array of html elements representing popover items
509+
*/
510+
private toggleIfNeeded(index: number, itemEls: Element[]): void {
511+
const clickedItem = this.items[index];
512+
513+
if (clickedItem.toggle === true) {
514+
clickedItem.isActive = !clickedItem.isActive;
515+
itemEls[index].classList.toggle(Popover.CSS.itemActive);
516+
517+
return;
518+
}
519+
520+
if (typeof clickedItem.toggle === 'string') {
521+
const itemsInToggleGroup = this.items.filter(item => item.toggle === clickedItem.toggle);
522+
523+
/** If there's only one item in toggle group, toggle it */
524+
if (itemsInToggleGroup.length === 1) {
525+
clickedItem.isActive = !clickedItem.isActive;
526+
itemEls[index].classList.toggle(Popover.CSS.itemActive);
527+
528+
return;
529+
}
530+
531+
/** Set clicked item as active and the rest items with same toggle key value as inactive */
532+
itemsInToggleGroup.forEach((item: PopoverItem) => {
533+
const i = this.items.indexOf(item);
534+
const newState = item === clickedItem;
535+
536+
item.isActive = newState;
537+
itemEls[i].classList.toggle(Popover.CSS.itemActive, newState);
538+
});
539+
}
540+
}
541+
504542
/**
505543
* Enables confirmation state for specified item.
506544
* Replaces item element in popover so that is becomes highlighted in a special way

test/cypress/tests/utils/popover.spec.ts

Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -185,4 +185,79 @@ describe('Popover', () => {
185185
.should('have.class', 'ce-popover__item--active');
186186
});
187187
});
188+
189+
it('should perform radiobutton-like behavior among the items that have toggle property value set to the same string value', () => {
190+
const items: PopoverItem[] = [
191+
{
192+
icon: 'Icon 1',
193+
label: 'Label 1',
194+
toggle: 'group-name',
195+
name: 'testItem1',
196+
isActive: true,
197+
onActivate: (): void => {},
198+
},
199+
{
200+
icon: 'Icon 2',
201+
label: 'Label 2',
202+
toggle: 'group-name',
203+
name: 'testItem2',
204+
onActivate: (): void => {},
205+
},
206+
];
207+
208+
const popover = new Popover({
209+
items,
210+
filterLabel: '',
211+
nothingFoundLabel: '',
212+
scopeElement: null,
213+
});
214+
215+
cy.document().then(doc => {
216+
doc.body.append(popover.getElement());
217+
218+
/** Check first item is active */
219+
cy.get('[data-item-name=testItem1]')
220+
.should('have.class', 'ce-popover__item--active');
221+
222+
/** Check second item is not active */
223+
cy.get('[data-item-name=testItem2]')
224+
.should('not.have.class', 'ce-popover__item--active');
225+
226+
/* Click second item and check it became active */
227+
cy.get('[data-item-name=testItem2]')
228+
.click()
229+
.should('have.class', 'ce-popover__item--active');
230+
231+
/** Check first item became not active */
232+
cy.get('[data-item-name=testItem1]')
233+
.should('not.have.class', 'ce-popover__item--active');
234+
});
235+
});
236+
237+
it('should toggle item if it is the only item in toggle group', () => {
238+
const items: PopoverItem[] = [
239+
{
240+
icon: 'Icon',
241+
label: 'Label',
242+
toggle: 'key',
243+
name: 'testItem',
244+
onActivate: (): void => {},
245+
},
246+
];
247+
const popover = new Popover({
248+
items,
249+
filterLabel: '',
250+
nothingFoundLabel: '',
251+
scopeElement: null,
252+
});
253+
254+
cy.document().then(doc => {
255+
doc.body.append(popover.getElement());
256+
257+
/* Check item has active class */
258+
cy.get('[data-item-name=testItem]')
259+
.click()
260+
.should('have.class', 'ce-popover__item--active');
261+
});
262+
});
188263
});

types/configs/popover.d.ts

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -39,9 +39,11 @@ interface PopoverItemBase {
3939
name?: string;
4040

4141
/**
42-
* True if item should be highlighted once activated
42+
* Defines whether item should toggle on click.
43+
* Can be represented as boolean value or a string key.
44+
* In case of string, works like radio buttons group and highlights as inactive any other item that has same toggle key value.
4345
*/
44-
toggle?: boolean;
46+
toggle?: boolean | string;
4547
}
4648

4749
/**

0 commit comments

Comments
 (0)