@ailuracode/alpine-accordion 0.1.0 → 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +2 -2
- package/dist/global.d.ts +6 -4
- package/dist/index.d.ts +116 -21
- package/dist/index.js +275 -151
- package/package.json +6 -2
- package/dist/index.js.map +0 -1
package/README.md
CHANGED
|
@@ -7,12 +7,12 @@ Headless accessible accordion store for Alpine.js — single or multiple open pa
|
|
|
7
7
|
## Install
|
|
8
8
|
|
|
9
9
|
```bash
|
|
10
|
-
|
|
10
|
+
pnpm add @ailuracode/alpine-accordion alpinejs
|
|
11
11
|
```
|
|
12
12
|
|
|
13
13
|
## Store API
|
|
14
14
|
|
|
15
|
-
```
|
|
15
|
+
```ts
|
|
16
16
|
$store.accordion.register("faq", { mode: "single", defaultOpen: "item-1" });
|
|
17
17
|
$store.accordion.open("faq", "item-1");
|
|
18
18
|
$store.accordion.toggle("faq", "item-1");
|
package/dist/global.d.ts
CHANGED
|
@@ -1,10 +1,12 @@
|
|
|
1
1
|
/// <reference types="@types/alpinejs" />
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
import type { AccordionGroup, AccordionGroupOptions } from "./types";
|
|
4
|
+
|
|
5
|
+
export type { AccordionGroup, AccordionGroupOptions, AccordionMode } from "./types";
|
|
4
6
|
|
|
5
7
|
export interface AccordionStore {
|
|
6
|
-
groups: Record<string,
|
|
7
|
-
register(accordionId: string, options?:
|
|
8
|
+
readonly groups: Record<string, AccordionGroup>;
|
|
9
|
+
register(accordionId: string, options?: AccordionGroupOptions): void;
|
|
8
10
|
unregister(accordionId: string): void;
|
|
9
11
|
registerItem(accordionId: string, itemId: string, disabled?: boolean): void;
|
|
10
12
|
unregisterItem(accordionId: string, itemId: string): void;
|
|
@@ -24,7 +26,7 @@ export interface AccordionStore {
|
|
|
24
26
|
destroy(): void;
|
|
25
27
|
}
|
|
26
28
|
|
|
27
|
-
export function
|
|
29
|
+
export function createAccordionController(id?: string): import("./types").AccordionController;
|
|
28
30
|
|
|
29
31
|
export default function accordionPlugin(): import("alpinejs").PluginCallback;
|
|
30
32
|
|
package/dist/index.d.ts
CHANGED
|
@@ -1,16 +1,29 @@
|
|
|
1
|
-
import
|
|
1
|
+
import { Alpine, PluginCallback, BaseController } from '@ailuracode/alpine-core';
|
|
2
|
+
export { Unsubscribe } from '@ailuracode/alpine-core';
|
|
3
|
+
import { Alpine as Alpine$1 } from 'alpinejs';
|
|
2
4
|
|
|
5
|
+
/**
|
|
6
|
+
* Public type contracts for `@ailuracode/alpine-accordion`.
|
|
7
|
+
*
|
|
8
|
+
* Every public type lives in a `types.ts` module so consumers can import
|
|
9
|
+
* them without pulling the implementation. The shape IS the contract.
|
|
10
|
+
*/
|
|
11
|
+
|
|
12
|
+
/** Accordion display mode. */
|
|
3
13
|
type AccordionMode = "single" | "multiple";
|
|
14
|
+
/** An accordion item's registration state. */
|
|
4
15
|
type AccordionItem = {
|
|
5
16
|
id: string;
|
|
6
17
|
disabled: boolean;
|
|
7
18
|
};
|
|
19
|
+
/** Options passed when registering an accordion group. */
|
|
8
20
|
type AccordionGroupOptions = {
|
|
9
|
-
mode?: AccordionMode;
|
|
21
|
+
readonly mode?: AccordionMode;
|
|
10
22
|
/** Item id or ids open on init. In `single` mode only the first id is used. */
|
|
11
|
-
defaultOpen?: string | string[];
|
|
12
|
-
onChange?: (openIds: string[]) => void;
|
|
23
|
+
readonly defaultOpen?: string | string[];
|
|
24
|
+
readonly onChange?: (openIds: string[]) => void;
|
|
13
25
|
};
|
|
26
|
+
/** Internal representation of an accordion group. */
|
|
14
27
|
type AccordionGroup = {
|
|
15
28
|
mode: AccordionMode;
|
|
16
29
|
open: Record<string, boolean>;
|
|
@@ -19,9 +32,17 @@ type AccordionGroup = {
|
|
|
19
32
|
defaultOpen: string[];
|
|
20
33
|
onChange?: (openIds: string[]) => void;
|
|
21
34
|
};
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
35
|
+
/** Discriminator for change events. */
|
|
36
|
+
type AccordionChangeSource = "user" | "initialization";
|
|
37
|
+
/** Detail payload for the `change` event. */
|
|
38
|
+
interface AccordionChangeDetail {
|
|
39
|
+
readonly groupId: string;
|
|
40
|
+
readonly openIds: string[];
|
|
41
|
+
readonly source: AccordionChangeSource;
|
|
42
|
+
}
|
|
43
|
+
/** Alpine-facing store surface. */
|
|
44
|
+
interface AccordionStore {
|
|
45
|
+
readonly groups: Record<string, AccordionGroup>;
|
|
25
46
|
register(accordionId: string, options?: AccordionGroupOptions): void;
|
|
26
47
|
unregister(accordionId: string): void;
|
|
27
48
|
registerItem(accordionId: string, itemId: string, disabled?: boolean): void;
|
|
@@ -37,21 +58,95 @@ type AccordionStore = {
|
|
|
37
58
|
triggerProps(accordionId: string, itemId: string): Record<string, string | number | boolean | undefined>;
|
|
38
59
|
panelProps(accordionId: string, itemId: string): Record<string, string | boolean | undefined>;
|
|
39
60
|
destroy(): void;
|
|
61
|
+
}
|
|
62
|
+
/** Options accepted by the accordion plugin factory. */
|
|
63
|
+
interface CreateAccordionOptions {
|
|
64
|
+
readonly id?: string;
|
|
65
|
+
}
|
|
66
|
+
/** Typed view of `Alpine` the accordion plugin uses internally. */
|
|
67
|
+
type AccordionAlpine = Alpine<{
|
|
68
|
+
accordion: AccordionStore;
|
|
69
|
+
}> & {
|
|
70
|
+
cleanup?(callback: () => void): void;
|
|
40
71
|
};
|
|
41
|
-
/**
|
|
42
|
-
|
|
72
|
+
/** `Alpine.plugin()` callback signature. */
|
|
73
|
+
type AccordionPluginCallback = PluginCallback<Alpine$1>;
|
|
74
|
+
|
|
75
|
+
/**
|
|
76
|
+
* Strongly-typed event map for the accordion controller.
|
|
77
|
+
*/
|
|
43
78
|
|
|
44
|
-
/**
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
interface Magics<T> {
|
|
52
|
-
$accordion: AccordionStore;
|
|
53
|
-
}
|
|
54
|
-
}
|
|
79
|
+
/**
|
|
80
|
+
* Event map for accordion state changes. Single-key contract:
|
|
81
|
+
* every transition emits `change` with the same
|
|
82
|
+
* {@link AccordionChangeDetail} payload.
|
|
83
|
+
*/
|
|
84
|
+
interface AccordionEvents extends Record<string, unknown> {
|
|
85
|
+
change: AccordionChangeDetail;
|
|
55
86
|
}
|
|
56
87
|
|
|
57
|
-
|
|
88
|
+
/**
|
|
89
|
+
* Accordion controller — the framework-agnostic core of
|
|
90
|
+
* `@ailuracode/alpine-accordion`. Manages accordion groups with
|
|
91
|
+
* open/close state, keyboard navigation, and ARIA props.
|
|
92
|
+
*
|
|
93
|
+
* Emits a typed `change` event on every open/close transition so
|
|
94
|
+
* consumers can react programmatically.
|
|
95
|
+
*/
|
|
96
|
+
|
|
97
|
+
/**
|
|
98
|
+
* Headless accordion controller. Manages multiple accordion groups
|
|
99
|
+
* with open/close state, keyboard navigation, and ARIA props.
|
|
100
|
+
*/
|
|
101
|
+
declare class AccordionController extends BaseController<AccordionEvents> {
|
|
102
|
+
#private;
|
|
103
|
+
constructor(id?: string);
|
|
104
|
+
get groups(): Readonly<Record<string, AccordionGroup>>;
|
|
105
|
+
register(accordionId: string, options?: AccordionGroupOptions): void;
|
|
106
|
+
unregister(accordionId: string): void;
|
|
107
|
+
registerItem(accordionId: string, itemId: string, disabled?: boolean): void;
|
|
108
|
+
unregisterItem(accordionId: string, itemId: string): void;
|
|
109
|
+
open(accordionId: string, itemId: string): void;
|
|
110
|
+
close(accordionId: string, itemId: string): void;
|
|
111
|
+
toggle(accordionId: string, itemId: string): void;
|
|
112
|
+
isOpen(accordionId: string, itemId: string): boolean;
|
|
113
|
+
openIds(accordionId: string): string[];
|
|
114
|
+
activeItem(accordionId: string): string | null;
|
|
115
|
+
setActiveItem(accordionId: string, itemId: string | null): void;
|
|
116
|
+
handleKeydown(accordionId: string, event: KeyboardEvent): void;
|
|
117
|
+
triggerProps(accordionId: string, itemId: string): Record<string, string | number | boolean | undefined>;
|
|
118
|
+
panelProps(accordionId: string, itemId: string): Record<string, string | boolean | undefined>;
|
|
119
|
+
/**
|
|
120
|
+
* Returns a store-shaped object for Alpine's `$store.accordion`.
|
|
121
|
+
* The store delegates to this controller.
|
|
122
|
+
*/
|
|
123
|
+
toStore(): AccordionStore;
|
|
124
|
+
}
|
|
125
|
+
/**
|
|
126
|
+
* Creates an AccordionController and returns a store-shaped object.
|
|
127
|
+
* Convenience for non-Alpine consumers.
|
|
128
|
+
*/
|
|
129
|
+
declare function createAccordionController(id?: string): AccordionController;
|
|
130
|
+
/**
|
|
131
|
+
* Creates an AccordionStore (store-shaped object) directly.
|
|
132
|
+
* Backward-compatible alias.
|
|
133
|
+
*/
|
|
134
|
+
declare function createAccordionStore(): AccordionStore;
|
|
135
|
+
|
|
136
|
+
/**
|
|
137
|
+
* Alpine.js integration for `@ailuracode/alpine-accordion`.
|
|
138
|
+
*
|
|
139
|
+
* Thin adapter that wires {@link AccordionController} into
|
|
140
|
+
* `$store.accordion` and the `$accordion` magic.
|
|
141
|
+
*/
|
|
142
|
+
|
|
143
|
+
/**
|
|
144
|
+
* Plugin factory — returns the `Alpine.plugin()` callback. Pass
|
|
145
|
+
* {@link CreateAccordionOptions} to configure the controller,
|
|
146
|
+
* or `{}` for the package defaults.
|
|
147
|
+
*/
|
|
148
|
+
declare function accordionPlugin(options?: CreateAccordionOptions): AccordionPluginCallback;
|
|
149
|
+
/** Builds typed accordion plugin options. */
|
|
150
|
+
declare function accordionOptions<const T extends CreateAccordionOptions>(options: T): T;
|
|
151
|
+
|
|
152
|
+
export { type AccordionAlpine, type AccordionChangeDetail, type AccordionChangeSource, AccordionController, type AccordionEvents, type AccordionGroup, type AccordionGroupOptions, type AccordionItem, type AccordionMode, type AccordionPluginCallback, type AccordionStore, type CreateAccordionOptions, accordionOptions, accordionPlugin, createAccordionController, createAccordionStore, accordionPlugin as default };
|
package/dist/index.js
CHANGED
|
@@ -1,15 +1,11 @@
|
|
|
1
|
-
// src/
|
|
1
|
+
// src/controller.ts
|
|
2
|
+
import { BaseController, generateId } from "@ailuracode/alpine-core";
|
|
2
3
|
function enabledItems(group) {
|
|
3
4
|
return group.items.filter((item) => !item.disabled);
|
|
4
5
|
}
|
|
5
6
|
function itemIndex(group, itemId) {
|
|
6
7
|
return enabledItems(group).findIndex((item) => item.id === itemId);
|
|
7
8
|
}
|
|
8
|
-
function notify(group) {
|
|
9
|
-
group.onChange?.(
|
|
10
|
-
Object.entries(group.open).filter(([, isOpen]) => isOpen).map(([id]) => id)
|
|
11
|
-
);
|
|
12
|
-
}
|
|
13
9
|
function normalizeDefaultOpen(mode, value) {
|
|
14
10
|
if (!value) {
|
|
15
11
|
return [];
|
|
@@ -28,167 +24,295 @@ function createGroup(options = {}) {
|
|
|
28
24
|
onChange: options.onChange
|
|
29
25
|
};
|
|
30
26
|
}
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
}
|
|
36
|
-
|
|
37
|
-
groups
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
27
|
+
var AccordionController = class extends BaseController {
|
|
28
|
+
#groups = {};
|
|
29
|
+
constructor(id) {
|
|
30
|
+
super(id ?? generateId("accordion"));
|
|
31
|
+
}
|
|
32
|
+
get groups() {
|
|
33
|
+
return this.#groups;
|
|
34
|
+
}
|
|
35
|
+
register(accordionId, options = {}) {
|
|
36
|
+
if (this.isDestroyed) {
|
|
37
|
+
return;
|
|
38
|
+
}
|
|
39
|
+
this.#groups[accordionId] = createGroup(options);
|
|
40
|
+
}
|
|
41
|
+
unregister(accordionId) {
|
|
42
|
+
if (this.isDestroyed) {
|
|
43
|
+
return;
|
|
44
|
+
}
|
|
45
|
+
delete this.#groups[accordionId];
|
|
46
|
+
}
|
|
47
|
+
registerItem(accordionId, itemId, disabled = false) {
|
|
48
|
+
if (this.isDestroyed) {
|
|
49
|
+
return;
|
|
50
|
+
}
|
|
51
|
+
const group = this.#getOrCreate(accordionId);
|
|
52
|
+
const existing = group.items.find((item) => item.id === itemId);
|
|
53
|
+
if (existing) {
|
|
54
|
+
existing.disabled = disabled;
|
|
55
|
+
return;
|
|
56
|
+
}
|
|
57
|
+
group.items.push({ id: itemId, disabled });
|
|
58
|
+
if (group.defaultOpen.includes(itemId) && !disabled) {
|
|
59
|
+
this.open(accordionId, itemId);
|
|
60
|
+
group.activeItemId ??= itemId;
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
unregisterItem(accordionId, itemId) {
|
|
64
|
+
if (this.isDestroyed) {
|
|
65
|
+
return;
|
|
66
|
+
}
|
|
67
|
+
const group = this.#groups[accordionId];
|
|
68
|
+
if (!group) {
|
|
69
|
+
return;
|
|
70
|
+
}
|
|
71
|
+
group.items = group.items.filter((item) => item.id !== itemId);
|
|
72
|
+
delete group.open[itemId];
|
|
73
|
+
}
|
|
74
|
+
open(accordionId, itemId) {
|
|
75
|
+
if (this.isDestroyed) {
|
|
76
|
+
return;
|
|
77
|
+
}
|
|
78
|
+
const group = this.#groups[accordionId];
|
|
79
|
+
const item = group?.items.find((entry) => entry.id === itemId);
|
|
80
|
+
if (!(group && item) || item.disabled) {
|
|
81
|
+
return;
|
|
82
|
+
}
|
|
83
|
+
if (group.mode === "single") {
|
|
84
|
+
for (const id of Object.keys(group.open)) {
|
|
85
|
+
if (group.open[id]) {
|
|
86
|
+
group.open[id] = false;
|
|
76
87
|
}
|
|
77
|
-
group.open[itemId] = true;
|
|
78
|
-
} else {
|
|
79
|
-
group.open[itemId] = true;
|
|
80
|
-
}
|
|
81
|
-
notify(group);
|
|
82
|
-
},
|
|
83
|
-
close(accordionId, itemId) {
|
|
84
|
-
const group = this.groups[accordionId];
|
|
85
|
-
if (!group?.open[itemId]) {
|
|
86
|
-
return;
|
|
87
|
-
}
|
|
88
|
-
group.open[itemId] = false;
|
|
89
|
-
notify(group);
|
|
90
|
-
},
|
|
91
|
-
toggle(accordionId, itemId) {
|
|
92
|
-
if (this.isOpen(accordionId, itemId)) {
|
|
93
|
-
this.close(accordionId, itemId);
|
|
94
|
-
} else {
|
|
95
|
-
this.open(accordionId, itemId);
|
|
96
|
-
}
|
|
97
|
-
},
|
|
98
|
-
isOpen(accordionId, itemId) {
|
|
99
|
-
return this.groups[accordionId]?.open[itemId] ?? false;
|
|
100
|
-
},
|
|
101
|
-
openIds(accordionId) {
|
|
102
|
-
const open = this.groups[accordionId]?.open ?? {};
|
|
103
|
-
return Object.entries(open).filter(([, isOpen]) => isOpen).map(([id]) => id);
|
|
104
|
-
},
|
|
105
|
-
activeItem(accordionId) {
|
|
106
|
-
return this.groups[accordionId]?.activeItemId ?? null;
|
|
107
|
-
},
|
|
108
|
-
setActiveItem(accordionId, itemId) {
|
|
109
|
-
const group = this.groups[accordionId];
|
|
110
|
-
if (!group) {
|
|
111
|
-
return;
|
|
112
|
-
}
|
|
113
|
-
if (itemId === null) {
|
|
114
|
-
group.activeItemId = null;
|
|
115
|
-
return;
|
|
116
88
|
}
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
89
|
+
group.open[itemId] = true;
|
|
90
|
+
} else {
|
|
91
|
+
group.open[itemId] = true;
|
|
92
|
+
}
|
|
93
|
+
this.#emitChange(accordionId, "user");
|
|
94
|
+
group.onChange?.(this.openIds(accordionId));
|
|
95
|
+
}
|
|
96
|
+
close(accordionId, itemId) {
|
|
97
|
+
if (this.isDestroyed) {
|
|
98
|
+
return;
|
|
99
|
+
}
|
|
100
|
+
const group = this.#groups[accordionId];
|
|
101
|
+
if (!group?.open[itemId]) {
|
|
102
|
+
return;
|
|
103
|
+
}
|
|
104
|
+
group.open[itemId] = false;
|
|
105
|
+
this.#emitChange(accordionId, "user");
|
|
106
|
+
group.onChange?.(this.openIds(accordionId));
|
|
107
|
+
}
|
|
108
|
+
toggle(accordionId, itemId) {
|
|
109
|
+
if (this.isOpen(accordionId, itemId)) {
|
|
110
|
+
this.close(accordionId, itemId);
|
|
111
|
+
} else {
|
|
112
|
+
this.open(accordionId, itemId);
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
isOpen(accordionId, itemId) {
|
|
116
|
+
return this.#groups[accordionId]?.open[itemId] ?? false;
|
|
117
|
+
}
|
|
118
|
+
openIds(accordionId) {
|
|
119
|
+
const open = this.#groups[accordionId]?.open ?? {};
|
|
120
|
+
return Object.entries(open).filter(([, isOpen]) => isOpen).map(([id]) => id);
|
|
121
|
+
}
|
|
122
|
+
activeItem(accordionId) {
|
|
123
|
+
return this.#groups[accordionId]?.activeItemId ?? null;
|
|
124
|
+
}
|
|
125
|
+
setActiveItem(accordionId, itemId) {
|
|
126
|
+
if (this.isDestroyed) {
|
|
127
|
+
return;
|
|
128
|
+
}
|
|
129
|
+
const group = this.#groups[accordionId];
|
|
130
|
+
if (!group) {
|
|
131
|
+
return;
|
|
132
|
+
}
|
|
133
|
+
if (itemId === null) {
|
|
134
|
+
group.activeItemId = null;
|
|
135
|
+
return;
|
|
136
|
+
}
|
|
137
|
+
const item = group.items.find((entry) => entry.id === itemId);
|
|
138
|
+
if (item && !item.disabled) {
|
|
139
|
+
group.activeItemId = itemId;
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
handleKeydown(accordionId, event) {
|
|
143
|
+
const group = this.#groups[accordionId];
|
|
144
|
+
if (!group) {
|
|
145
|
+
return;
|
|
146
|
+
}
|
|
147
|
+
const items = enabledItems(group);
|
|
148
|
+
if (items.length === 0) {
|
|
149
|
+
return;
|
|
150
|
+
}
|
|
151
|
+
if (!group.activeItemId) {
|
|
152
|
+
group.activeItemId = items[0]?.id ?? null;
|
|
153
|
+
}
|
|
154
|
+
const currentIndex = group.activeItemId ? itemIndex(group, group.activeItemId) : 0;
|
|
155
|
+
switch (event.key) {
|
|
156
|
+
case "ArrowDown":
|
|
157
|
+
event.preventDefault();
|
|
158
|
+
group.activeItemId = items[(currentIndex + 1) % items.length]?.id ?? null;
|
|
159
|
+
break;
|
|
160
|
+
case "ArrowUp":
|
|
161
|
+
event.preventDefault();
|
|
162
|
+
group.activeItemId = items[(currentIndex - 1 + items.length) % items.length]?.id ?? null;
|
|
163
|
+
break;
|
|
164
|
+
case "Home":
|
|
165
|
+
event.preventDefault();
|
|
132
166
|
group.activeItemId = items[0]?.id ?? null;
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
167
|
+
break;
|
|
168
|
+
case "End":
|
|
169
|
+
event.preventDefault();
|
|
170
|
+
group.activeItemId = items[items.length - 1]?.id ?? null;
|
|
171
|
+
break;
|
|
172
|
+
default:
|
|
173
|
+
break;
|
|
174
|
+
}
|
|
175
|
+
}
|
|
176
|
+
triggerProps(accordionId, itemId) {
|
|
177
|
+
const open = this.isOpen(accordionId, itemId);
|
|
178
|
+
const active = this.activeItem(accordionId) === itemId;
|
|
179
|
+
return {
|
|
180
|
+
"aria-expanded": open,
|
|
181
|
+
"aria-controls": `${accordionId}-panel-${itemId}`,
|
|
182
|
+
id: `${accordionId}-trigger-${itemId}`,
|
|
183
|
+
tabindex: active ? 0 : -1
|
|
184
|
+
};
|
|
185
|
+
}
|
|
186
|
+
panelProps(accordionId, itemId) {
|
|
187
|
+
const open = this.isOpen(accordionId, itemId);
|
|
188
|
+
return {
|
|
189
|
+
id: `${accordionId}-panel-${itemId}`,
|
|
190
|
+
role: "region",
|
|
191
|
+
"aria-labelledby": `${accordionId}-trigger-${itemId}`,
|
|
192
|
+
"aria-hidden": open ? void 0 : true
|
|
193
|
+
};
|
|
194
|
+
}
|
|
195
|
+
/**
|
|
196
|
+
* Returns a store-shaped object for Alpine's `$store.accordion`.
|
|
197
|
+
* The store delegates to this controller.
|
|
198
|
+
*/
|
|
199
|
+
toStore() {
|
|
200
|
+
return {
|
|
201
|
+
groups: this.#groups,
|
|
202
|
+
register: (id, opts) => this.register(id, opts),
|
|
203
|
+
unregister: (id) => this.unregister(id),
|
|
204
|
+
registerItem: (id, itemId, disabled) => this.registerItem(id, itemId, disabled),
|
|
205
|
+
unregisterItem: (id, itemId) => this.unregisterItem(id, itemId),
|
|
206
|
+
open: (id, itemId) => this.open(id, itemId),
|
|
207
|
+
close: (id, itemId) => this.close(id, itemId),
|
|
208
|
+
toggle: (id, itemId) => this.toggle(id, itemId),
|
|
209
|
+
isOpen: (id, itemId) => this.isOpen(id, itemId),
|
|
210
|
+
openIds: (id) => this.openIds(id),
|
|
211
|
+
activeItem: (id) => this.activeItem(id),
|
|
212
|
+
setActiveItem: (id, itemId) => this.setActiveItem(id, itemId),
|
|
213
|
+
handleKeydown: (id, event) => this.handleKeydown(id, event),
|
|
214
|
+
triggerProps: (id, itemId) => this.triggerProps(id, itemId),
|
|
215
|
+
panelProps: (id, itemId) => this.panelProps(id, itemId),
|
|
216
|
+
destroy: () => this.destroy()
|
|
217
|
+
};
|
|
218
|
+
}
|
|
219
|
+
#getOrCreate(accordionId) {
|
|
220
|
+
this.#groups[accordionId] ??= createGroup();
|
|
221
|
+
return this.#groups[accordionId];
|
|
222
|
+
}
|
|
223
|
+
#emitChange(accordionId, source) {
|
|
224
|
+
this.emit("change", {
|
|
225
|
+
groupId: accordionId,
|
|
226
|
+
openIds: this.openIds(accordionId),
|
|
227
|
+
source
|
|
228
|
+
});
|
|
229
|
+
}
|
|
230
|
+
};
|
|
231
|
+
function createAccordionController(id) {
|
|
232
|
+
return new AccordionController(id);
|
|
233
|
+
}
|
|
234
|
+
function createAccordionStore() {
|
|
235
|
+
return new AccordionController().toStore();
|
|
236
|
+
}
|
|
237
|
+
|
|
238
|
+
// src/plugin.ts
|
|
239
|
+
var ACCORDION_STORE_KEY = "accordion";
|
|
240
|
+
function accordionPlugin(options = {}) {
|
|
241
|
+
return function registerAccordion(alpine) {
|
|
242
|
+
const Alpine = alpine;
|
|
243
|
+
const controller = new AccordionController(options.id);
|
|
244
|
+
const store = {
|
|
245
|
+
groups: {},
|
|
246
|
+
register: (id, opts) => controller.register(id, opts),
|
|
247
|
+
unregister: (id) => controller.unregister(id),
|
|
248
|
+
registerItem: (id, itemId, disabled) => controller.registerItem(id, itemId, disabled),
|
|
249
|
+
unregisterItem: (id, itemId) => controller.unregisterItem(id, itemId),
|
|
250
|
+
open: (id, itemId) => controller.open(id, itemId),
|
|
251
|
+
close: (id, itemId) => controller.close(id, itemId),
|
|
252
|
+
toggle: (id, itemId) => controller.toggle(id, itemId),
|
|
253
|
+
isOpen: () => false,
|
|
254
|
+
openIds: () => [],
|
|
255
|
+
activeItem: () => null,
|
|
256
|
+
setActiveItem: (id, itemId) => controller.setActiveItem(id, itemId),
|
|
257
|
+
handleKeydown: (id, event) => controller.handleKeydown(id, event),
|
|
258
|
+
triggerProps: () => ({}),
|
|
259
|
+
panelProps: () => ({}),
|
|
260
|
+
destroy: () => controller.destroy()
|
|
261
|
+
};
|
|
262
|
+
Alpine.store(ACCORDION_STORE_KEY, store);
|
|
263
|
+
const reactive = () => Alpine.store(ACCORDION_STORE_KEY);
|
|
264
|
+
store.isOpen = (id, itemId) => reactive().groups[id]?.open[itemId] ?? false;
|
|
265
|
+
store.openIds = (id) => {
|
|
266
|
+
const open = reactive().groups[id]?.open ?? {};
|
|
267
|
+
return Object.entries(open).filter(([, isOpen]) => isOpen).map(([gid]) => gid);
|
|
268
|
+
};
|
|
269
|
+
store.activeItem = (id) => reactive().groups[id]?.activeItemId ?? null;
|
|
270
|
+
store.triggerProps = (id, itemId) => {
|
|
271
|
+
const r = reactive();
|
|
272
|
+
const open = r.isOpen(id, itemId);
|
|
273
|
+
const active = r.activeItem(id) === itemId;
|
|
159
274
|
return {
|
|
160
275
|
"aria-expanded": open,
|
|
161
|
-
"aria-controls": `${
|
|
162
|
-
id: `${
|
|
276
|
+
"aria-controls": `${id}-panel-${itemId}`,
|
|
277
|
+
id: `${id}-trigger-${itemId}`,
|
|
163
278
|
tabindex: active ? 0 : -1
|
|
164
279
|
};
|
|
165
|
-
}
|
|
166
|
-
panelProps(
|
|
167
|
-
const open =
|
|
280
|
+
};
|
|
281
|
+
store.panelProps = (id, itemId) => {
|
|
282
|
+
const open = reactive().isOpen(id, itemId);
|
|
168
283
|
return {
|
|
169
|
-
id: `${
|
|
284
|
+
id: `${id}-panel-${itemId}`,
|
|
170
285
|
role: "region",
|
|
171
|
-
"aria-labelledby": `${
|
|
286
|
+
"aria-labelledby": `${id}-trigger-${itemId}`,
|
|
172
287
|
"aria-hidden": open ? void 0 : true
|
|
173
288
|
};
|
|
174
|
-
}
|
|
175
|
-
|
|
176
|
-
|
|
289
|
+
};
|
|
290
|
+
controller.on("change", () => {
|
|
291
|
+
const r = reactive();
|
|
292
|
+
const controllerGroups = controller.groups;
|
|
293
|
+
for (const key of Object.keys(controllerGroups)) {
|
|
294
|
+
r.groups[key] = controllerGroups[key];
|
|
295
|
+
}
|
|
296
|
+
for (const key of Object.keys(r.groups)) {
|
|
297
|
+
if (!(key in controllerGroups)) {
|
|
298
|
+
delete r.groups[key];
|
|
299
|
+
}
|
|
300
|
+
}
|
|
301
|
+
});
|
|
302
|
+
Alpine.magic(ACCORDION_STORE_KEY, () => reactive());
|
|
303
|
+
if (typeof Alpine.cleanup === "function") {
|
|
304
|
+
Alpine.cleanup(() => controller.destroy());
|
|
177
305
|
}
|
|
178
306
|
};
|
|
179
|
-
return store;
|
|
180
307
|
}
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
function accordionPlugin() {
|
|
184
|
-
return function registerAccordion(Alpine) {
|
|
185
|
-
const store = createAccordionStore();
|
|
186
|
-
Alpine.store("accordion", store);
|
|
187
|
-
Alpine.magic("accordion", () => Alpine.store("accordion"));
|
|
188
|
-
};
|
|
308
|
+
function accordionOptions(options) {
|
|
309
|
+
return options;
|
|
189
310
|
}
|
|
190
311
|
export {
|
|
312
|
+
AccordionController,
|
|
313
|
+
accordionOptions,
|
|
314
|
+
accordionPlugin,
|
|
315
|
+
createAccordionController,
|
|
191
316
|
createAccordionStore,
|
|
192
317
|
accordionPlugin as default
|
|
193
318
|
};
|
|
194
|
-
//# sourceMappingURL=index.js.map
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@ailuracode/alpine-accordion",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "1.0.0",
|
|
4
4
|
"description": "Alpine.js headless accessible accordion store",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "MIT",
|
|
@@ -31,7 +31,11 @@
|
|
|
31
31
|
}
|
|
32
32
|
},
|
|
33
33
|
"types": "./dist/global.d.ts",
|
|
34
|
+
"devDependencies": {
|
|
35
|
+
"@ailuracode/alpine-core": "0.2.0"
|
|
36
|
+
},
|
|
34
37
|
"peerDependencies": {
|
|
38
|
+
"@ailuracode/alpine-core": "^0.2.0",
|
|
35
39
|
"alpinejs": "^3.0.0",
|
|
36
40
|
"@types/alpinejs": "^3.13.11"
|
|
37
41
|
},
|
|
@@ -49,7 +53,7 @@
|
|
|
49
53
|
"headless"
|
|
50
54
|
],
|
|
51
55
|
"scripts": {
|
|
52
|
-
"build": "tsup src/index.ts --format esm --dts --clean --
|
|
56
|
+
"build": "tsup src/index.ts --format esm --dts --clean --out-dir dist && cp src/global.d.ts dist/global.d.ts",
|
|
53
57
|
"test": "vitest run --config ../../vitest.config.ts test"
|
|
54
58
|
}
|
|
55
59
|
}
|
package/dist/index.js.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/store.ts","../src/index.ts"],"sourcesContent":["export type AccordionMode = \"single\" | \"multiple\";\n\nexport type AccordionItem = {\n id: string;\n disabled: boolean;\n};\n\nexport type AccordionGroupOptions = {\n mode?: AccordionMode;\n /** Item id or ids open on init. In `single` mode only the first id is used. */\n defaultOpen?: string | string[];\n onChange?: (openIds: string[]) => void;\n};\n\nexport type AccordionGroup = {\n mode: AccordionMode;\n open: Record<string, boolean>;\n activeItemId: string | null;\n items: AccordionItem[];\n defaultOpen: string[];\n onChange?: (openIds: string[]) => void;\n};\n\nexport type AccordionStore = {\n /** Reactive registry of accordion groups. */\n groups: Record<string, AccordionGroup>;\n register(accordionId: string, options?: AccordionGroupOptions): void;\n unregister(accordionId: string): void;\n registerItem(accordionId: string, itemId: string, disabled?: boolean): void;\n unregisterItem(accordionId: string, itemId: string): void;\n open(accordionId: string, itemId: string): void;\n close(accordionId: string, itemId: string): void;\n toggle(accordionId: string, itemId: string): void;\n isOpen(accordionId: string, itemId: string): boolean;\n openIds(accordionId: string): string[];\n activeItem(accordionId: string): string | null;\n setActiveItem(accordionId: string, itemId: string | null): void;\n handleKeydown(accordionId: string, event: KeyboardEvent): void;\n triggerProps(\n accordionId: string,\n itemId: string\n ): Record<string, string | number | boolean | undefined>;\n panelProps(accordionId: string, itemId: string): Record<string, string | boolean | undefined>;\n destroy(): void;\n};\n\nfunction enabledItems(group: AccordionGroup): AccordionItem[] {\n return group.items.filter((item) => !item.disabled);\n}\n\nfunction itemIndex(group: AccordionGroup, itemId: string): number {\n return enabledItems(group).findIndex((item) => item.id === itemId);\n}\n\nfunction notify(group: AccordionGroup): void {\n group.onChange?.(\n Object.entries(group.open)\n .filter(([, isOpen]) => isOpen)\n .map(([id]) => id)\n );\n}\n\nfunction normalizeDefaultOpen(mode: AccordionMode, value?: string | string[]): string[] {\n if (!value) {\n return [];\n }\n\n const ids = Array.isArray(value) ? value : [value];\n return mode === \"single\" && ids.length > 0 ? [ids[0]] : ids;\n}\n\nfunction createGroup(options: AccordionGroupOptions = {}): AccordionGroup {\n const mode = options.mode ?? \"single\";\n return {\n mode,\n open: {},\n activeItemId: null,\n items: [],\n defaultOpen: normalizeDefaultOpen(mode, options.defaultOpen),\n onChange: options.onChange,\n };\n}\n\n/** Creates the headless accordion store. */\nexport function createAccordionStore(): AccordionStore {\n function getOrCreate(store: AccordionStore, accordionId: string): AccordionGroup {\n store.groups[accordionId] ??= createGroup();\n return store.groups[accordionId];\n }\n\n const store: AccordionStore = {\n groups: {},\n\n register(accordionId, options = {}) {\n this.groups[accordionId] = createGroup(options);\n },\n\n unregister(accordionId) {\n delete this.groups[accordionId];\n },\n\n registerItem(accordionId, itemId, disabled = false) {\n const group = getOrCreate(this, accordionId);\n const existing = group.items.find((item) => item.id === itemId);\n if (existing) {\n existing.disabled = disabled;\n return;\n }\n group.items.push({ id: itemId, disabled });\n\n if (group.defaultOpen.includes(itemId) && !disabled) {\n this.open(accordionId, itemId);\n group.activeItemId ??= itemId;\n }\n },\n\n unregisterItem(accordionId, itemId) {\n const group = this.groups[accordionId];\n if (!group) {\n return;\n }\n\n group.items = group.items.filter((item) => item.id !== itemId);\n delete group.open[itemId];\n },\n\n open(accordionId, itemId) {\n const group = this.groups[accordionId];\n const item = group?.items.find((entry) => entry.id === itemId);\n if (!(group && item) || item.disabled) {\n return;\n }\n\n if (group.mode === \"single\") {\n for (const id of Object.keys(group.open)) {\n if (group.open[id]) {\n group.open[id] = false;\n }\n }\n group.open[itemId] = true;\n } else {\n group.open[itemId] = true;\n }\n\n notify(group);\n },\n\n close(accordionId, itemId) {\n const group = this.groups[accordionId];\n if (!group?.open[itemId]) {\n return;\n }\n\n group.open[itemId] = false;\n notify(group);\n },\n\n toggle(accordionId, itemId) {\n if (this.isOpen(accordionId, itemId)) {\n this.close(accordionId, itemId);\n } else {\n this.open(accordionId, itemId);\n }\n },\n\n isOpen(accordionId, itemId) {\n return this.groups[accordionId]?.open[itemId] ?? false;\n },\n\n openIds(accordionId) {\n const open = this.groups[accordionId]?.open ?? {};\n return Object.entries(open)\n .filter(([, isOpen]) => isOpen)\n .map(([id]) => id);\n },\n\n activeItem(accordionId) {\n return this.groups[accordionId]?.activeItemId ?? null;\n },\n\n setActiveItem(accordionId, itemId) {\n const group = this.groups[accordionId];\n if (!group) {\n return;\n }\n\n if (itemId === null) {\n group.activeItemId = null;\n return;\n }\n\n const item = group.items.find((entry) => entry.id === itemId);\n if (item && !item.disabled) {\n group.activeItemId = itemId;\n }\n },\n\n handleKeydown(accordionId, event) {\n const group = this.groups[accordionId];\n if (!group) {\n return;\n }\n\n const items = enabledItems(group);\n if (items.length === 0) {\n return;\n }\n\n if (!group.activeItemId) {\n group.activeItemId = items[0]?.id ?? null;\n }\n\n const currentIndex = group.activeItemId ? itemIndex(group, group.activeItemId) : 0;\n\n switch (event.key) {\n case \"ArrowDown\":\n event.preventDefault();\n group.activeItemId = items[(currentIndex + 1) % items.length]?.id ?? null;\n break;\n case \"ArrowUp\":\n event.preventDefault();\n group.activeItemId = items[(currentIndex - 1 + items.length) % items.length]?.id ?? null;\n break;\n case \"Home\":\n event.preventDefault();\n group.activeItemId = items[0]?.id ?? null;\n break;\n case \"End\":\n event.preventDefault();\n group.activeItemId = items[items.length - 1]?.id ?? null;\n break;\n default:\n break;\n }\n },\n\n triggerProps(accordionId, itemId) {\n const open = this.isOpen(accordionId, itemId);\n const active = this.activeItem(accordionId) === itemId;\n return {\n \"aria-expanded\": open,\n \"aria-controls\": `${accordionId}-panel-${itemId}`,\n id: `${accordionId}-trigger-${itemId}`,\n tabindex: active ? 0 : -1,\n };\n },\n\n panelProps(accordionId, itemId) {\n const open = this.isOpen(accordionId, itemId);\n return {\n id: `${accordionId}-panel-${itemId}`,\n role: \"region\",\n \"aria-labelledby\": `${accordionId}-trigger-${itemId}`,\n \"aria-hidden\": open ? undefined : true,\n };\n },\n\n destroy() {\n this.groups = {};\n },\n };\n\n return store;\n}\n","import type AlpineType from \"alpinejs\";\nimport { type AccordionStore, createAccordionStore } from \"./store.js\";\n\nexport {\n type AccordionGroupOptions,\n type AccordionMode,\n type AccordionStore,\n createAccordionStore,\n} from \"./store.js\";\n\n/** Alpine.js accordion plugin. Registers `$store.accordion`. */\nexport default function accordionPlugin(): AlpineType.PluginCallback {\n return function registerAccordion(Alpine) {\n const store = createAccordionStore();\n Alpine.store(\"accordion\", store);\n Alpine.magic(\"accordion\", () => Alpine.store(\"accordion\"));\n };\n}\n\ndeclare global {\n namespace Alpine {\n interface Stores {\n accordion: AccordionStore;\n }\n interface Magics<T> {\n $accordion: AccordionStore;\n }\n }\n}\n"],"mappings":"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","names":["store"]}
|