Skip to content

Feat: Toolbelt methods #2

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Draft
wants to merge 6 commits into
base: main
Choose a base branch
from
Draft
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
6 changes: 6 additions & 0 deletions src/lib/__tests__/utils.js
Original file line number Diff line number Diff line change
Expand Up @@ -35,3 +35,9 @@ export function initializeAlpine() {
export function createMockCustomEventListener() {
return vi.fn((e) => [e.target, e.detail]);
}

export const scopes = {
CUSTOM_EVENTS: "custom events",
KEYBOARD_NAVIGATION: "keyboard navigation",
JAVASCRIPT_METHODS: "javascript methods",
};
53 changes: 47 additions & 6 deletions src/lib/__tests__/x-accordion.test.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,12 @@
import { expect, describe, beforeAll, beforeEach, test } from "vitest";
import { fireEvent, screen, waitFor } from "@testing-library/dom";

import { createMockCustomEventListener, html, initializeAlpine } from "./utils";
import {
createMockCustomEventListener,
html,
initializeAlpine,
scopes,
} from "./utils";

describe("x-accordion", () => {
beforeAll(initializeAlpine);
Expand Down Expand Up @@ -85,7 +90,7 @@ describe("x-accordion", () => {
});
});

describe("custom events", () => {
describe(scopes.CUSTOM_EVENTS, () => {
test("should indicate item is open", async () => {
const item = screen.getByTestId("item-1");
const trigger = screen.getByTestId("trigger-1");
Expand Down Expand Up @@ -132,7 +137,7 @@ describe("x-accordion", () => {
});
});

describe("keyboard navigation", () => {
describe(scopes.KEYBOARD_NAVIGATION, () => {
let trigger1, trigger2;

beforeEach(() => {
Expand Down Expand Up @@ -194,6 +199,42 @@ describe("x-accordion", () => {
});
});
});

describe(scopes.JAVASCRIPT_METHODS, () => {
test("(item.toolbelt.toggle) should open and close an item", async () => {
const item = screen.getByTestId("item-1");
const trigger = screen.getByTestId("trigger-1");
const content = screen.getByTestId("content-1");

item.toolbelt.toggle();

await waitFor(() => {
expectItemToBeOpen({ item, trigger, content }, true);
item.toolbelt.toggle();
});

await waitFor(() => {
expectItemToBeOpen({ item, trigger, content }, false);
});
});

test("(item.toolbelt.toggle) should open and close an item when override is given", async () => {
const item = screen.getByTestId("item-1");
const trigger = screen.getByTestId("trigger-1");
const content = screen.getByTestId("content-1");

item.toolbelt.toggle(true);

await waitFor(() => {
expectItemToBeOpen({ item, trigger, content }, true);
item.toolbelt.toggle(false);
});

await waitFor(() => {
expectItemToBeOpen({ item, trigger, content }, false);
});
});
});
});

describe("(x-accordion.single) single item only configuration", () => {
Expand Down Expand Up @@ -253,7 +294,7 @@ describe("x-accordion", () => {
});
});

describe("custom events", () => {
describe(scopes.CUSTOM_EVENTS, () => {
test("should trigger separate events for opened and closed items.", async () => {
const item1 = screen.getByTestId("item-1");
const trigger1 = screen.getByTestId("trigger-1");
Expand Down Expand Up @@ -311,7 +352,7 @@ describe("x-accordion", () => {
`;
});

describe("keyboard navigation", () => {
describe(scopes.KEYBOARD_NAVIGATION, () => {
let trigger1, trigger2;

beforeEach(() => {
Expand Down Expand Up @@ -356,7 +397,7 @@ describe("x-accordion", () => {
`;
});

describe("keyboard navigation", () => {
describe(scopes.KEYBOARD_NAVIGATION, () => {
let trigger1, trigger2;

beforeEach(() => {
Expand Down
9 changes: 7 additions & 2 deletions src/lib/__tests__/x-checkbox.test.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,12 @@
import { expect, describe, beforeAll, beforeEach, test } from "vitest";
import { fireEvent, screen, waitFor } from "@testing-library/dom";

import { createMockCustomEventListener, html, initializeAlpine } from "./utils";
import {
createMockCustomEventListener,
html,
initializeAlpine,
scopes,
} from "./utils";

describe("x-checkbox", () => {
beforeAll(initializeAlpine);
Expand Down Expand Up @@ -97,7 +102,7 @@ describe("x-checkbox", () => {
});
});

describe("custom events", () => {
describe(scopes.CUSTOM_EVENTS, () => {
test("should indicate checkbox is open", async () => {
const root = screen.getByTestId("root");
const indicator = screen.getByTestId("indicator");
Expand Down
9 changes: 7 additions & 2 deletions src/lib/__tests__/x-dialog.test.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,12 @@
import { expect, describe, beforeAll, beforeEach, test } from "vitest";
import { fireEvent, screen, waitFor } from "@testing-library/dom";

import { createMockCustomEventListener, html, initializeAlpine } from "./utils";
import {
createMockCustomEventListener,
html,
initializeAlpine,
scopes,
} from "./utils";

describe("x-dialog", () => {
beforeAll(initializeAlpine);
Expand Down Expand Up @@ -117,7 +122,7 @@ describe("x-dialog", () => {
});
});

describe("custom events", () => {
describe(scopes.CUSTOM_EVENTS, () => {
test("should indicate dialog is open", async () => {
const listener = createMockCustomEventListener();

Expand Down
9 changes: 7 additions & 2 deletions src/lib/__tests__/x-flyout.test.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,12 @@
import { expect, describe, beforeAll, beforeEach, test } from "vitest";
import { fireEvent, screen, waitFor } from "@testing-library/dom";

import { createMockCustomEventListener, html, initializeAlpine } from "./utils";
import {
createMockCustomEventListener,
html,
initializeAlpine,
scopes,
} from "./utils";

describe("x-flyout", () => {
beforeAll(initializeAlpine);
Expand Down Expand Up @@ -90,7 +95,7 @@ describe("x-flyout", () => {
});
});

describe("custom events", () => {
describe(scopes.CUSTOM_EVENTS, () => {
test("should indicate flyout is open", async () => {
const listener = createMockCustomEventListener();

Expand Down
17 changes: 11 additions & 6 deletions src/lib/__tests__/x-tabs.test.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,12 @@
import { expect, describe, beforeAll, beforeEach, test } from "vitest";
import { fireEvent, screen, waitFor } from "@testing-library/dom";

import { createMockCustomEventListener, html, initializeAlpine } from "./utils";
import {
createMockCustomEventListener,
html,
initializeAlpine,
scopes,
} from "./utils";

describe("x-tabs", () => {
beforeAll(initializeAlpine);
Expand Down Expand Up @@ -78,7 +83,7 @@ describe("x-tabs", () => {
});
});

describe("custom events", () => {
describe(scopes.CUSTOM_EVENTS, () => {
test("should indicate tab is open", async () => {
const listener = createMockCustomEventListener();

Expand Down Expand Up @@ -108,7 +113,7 @@ describe("x-tabs", () => {
});
});

describe("keyboard navigation", () => {
describe(scopes.KEYBOARD_NAVIGATION, () => {
test("pressing right arrow should move focus to the next tab", async () => {
fireEvent.keyDown(tab1, { key: "ArrowRight" });

Expand Down Expand Up @@ -179,7 +184,7 @@ describe("x-tabs", () => {
tab2 = screen.getByTestId("tab2");
});

describe("keyboard navigation", () => {
describe(scopes.KEYBOARD_NAVIGATION, () => {
test("pressing right arrow on the last tab should loop", async () => {
fireEvent.keyDown(tab2, { key: "ArrowRight" });

Expand Down Expand Up @@ -220,7 +225,7 @@ describe("x-tabs", () => {
panel2 = screen.getByTestId("panel2");
});

describe("keyboard navigation", () => {
describe(scopes.KEYBOARD_NAVIGATION, () => {
test("pressing right arrow should automatically open the next tab", async () => {
fireEvent.keyDown(tab1, { key: "ArrowRight" });

Expand Down Expand Up @@ -281,7 +286,7 @@ describe("x-tabs", () => {
panel2 = screen.getByTestId("panel2");
});

describe("keyboard navigation", () => {
describe(scopes.KEYBOARD_NAVIGATION, () => {
test("pressing down arrow should move focus to the next tab", async () => {
fireEvent.keyDown(tab1, { key: "ArrowDown" });

Expand Down
19 changes: 14 additions & 5 deletions src/lib/toolbelt/x-accordion.js
Original file line number Diff line number Diff line change
Expand Up @@ -43,15 +43,18 @@ function handleRoot(el, Alpine, config) {
triggers: [],
openItems: new Set(),

toggleItem(el) {
if (config.type === "single" && this.openItems.has(el)) {
toggleItem(el, open) {
const shouldOpen =
open === undefined ? !this.openItems.has(el) : open;

if (config.type === "single" && !shouldOpen) {
this.openItems.delete(el);
} else if (config.type === "single" && !this.openItems.has(el)) {
} else if (config.type === "single" && shouldOpen) {
this.openItems.clear();
this.openItems.add(el);
} else if (config.type === "multiple" && this.openItems.has(el)) {
} else if (config.type === "multiple" && !shouldOpen) {
this.openItems.delete(el);
} else if (config.type === "multiple" && !this.openItems.has(el)) {
} else if (config.type === "multiple" && shouldOpen) {
this.openItems.add(el);
}

Expand Down Expand Up @@ -101,6 +104,12 @@ function handleItem(el, Alpine, config) {
if (config.open) {
this.openItems.add(el);
}

el.toolbelt = {
toggle: (open) => {
this.toggleItem(this.__item, open);
},
};
},

"x-id"() {
Expand Down