@torpor/ui 0.0.1
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/LICENSE.md +5 -0
- package/README.md +16 -0
- package/dist/Accordion/Accordion.torp +208 -0
- package/dist/Accordion/AccordionContent.torp +36 -0
- package/dist/Accordion/AccordionHeader.torp +33 -0
- package/dist/Accordion/AccordionItem.torp +75 -0
- package/dist/Accordion/AccordionTrigger.torp +59 -0
- package/dist/Accordion/AccordionTypes.ts +32 -0
- package/dist/Accordion/index.cjs +53 -0
- package/dist/Accordion/index.cjs.map +1 -0
- package/dist/Accordion/index.js +22 -0
- package/dist/Accordion/index.js.map +1 -0
- package/dist/metafile-cjs.json +1 -0
- package/dist/metafile-esm.json +1 -0
- package/dist/motion.cjs +34 -0
- package/dist/motion.cjs.map +1 -0
- package/dist/motion.d.cts +5 -0
- package/dist/motion.d.ts +5 -0
- package/dist/motion.js +7 -0
- package/dist/motion.js.map +1 -0
- package/dist/utils/getId.ts +6 -0
- package/package.json +52 -0
- package/scripts/postbuild.ts +62 -0
- package/src/Accordion/Accordion.torp +208 -0
- package/src/Accordion/AccordionContent.torp +36 -0
- package/src/Accordion/AccordionHeader.torp +33 -0
- package/src/Accordion/AccordionItem.torp +75 -0
- package/src/Accordion/AccordionTrigger.torp +59 -0
- package/src/Accordion/AccordionTypes.ts +32 -0
- package/src/Accordion/index.ts +7 -0
- package/src/Accordion.ts +7 -0
- package/src/motion/fade.ts +2 -0
- package/src/motion.ts +3 -0
- package/src/utils/getId.ts +6 -0
- package/test/Accordion/accessibility.test.ts +62 -0
- package/test/Accordion/components/AccordionAccessibility.torp +44 -0
- package/test/Accordion/components/AccordionKeyboard.torp +32 -0
- package/test/Accordion/components/AccordionList.torp +23 -0
- package/test/Accordion/components/AccordionMultiple.torp +32 -0
- package/test/Accordion/components/AccordionSingle.torp +32 -0
- package/test/Accordion/for-items.test.ts +54 -0
- package/test/Accordion/keyboard.test.ts +67 -0
- package/test/Accordion/multiple-item-toggle.test.ts +34 -0
- package/test/Accordion/multiple-item-value.test.ts +17 -0
- package/test/Accordion/single-item-toggle.test.ts +33 -0
- package/test/Accordion/single-item-value.test.ts +17 -0
- package/tsconfig.json +4 -0
- package/tsup.config.ts +14 -0
- package/vitest.config.ts +12 -0
package/LICENSE.md
ADDED
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
Copyright 2024 <OWNER>
|
|
2
|
+
|
|
3
|
+
Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted, provided that the above copyright notice and this permission notice appear in all copies.
|
|
4
|
+
|
|
5
|
+
THE SOFTWARE IS PROVIDED “AS IS” AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
# torpor/ui
|
|
2
|
+
|
|
3
|
+
Accessible, unstyled components for use in your Torpor front-end.
|
|
4
|
+
|
|
5
|
+
🚧 WARNING: WORK IN PROGRESS 🚧
|
|
6
|
+
|
|
7
|
+
## Features
|
|
8
|
+
|
|
9
|
+
- Accordion
|
|
10
|
+
- motion
|
|
11
|
+
- fade
|
|
12
|
+
|
|
13
|
+
## Not yet
|
|
14
|
+
|
|
15
|
+
- Forms, validation etc
|
|
16
|
+
- Utility functions e.g. intersection observer
|
|
@@ -0,0 +1,208 @@
|
|
|
1
|
+
import { AccordionContextName, type AccordionContext, type ItemState } from './AccordionTypes';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* A vertically stacked set of interactive headings that enable users to reveal
|
|
5
|
+
* or hide associated sections of content.
|
|
6
|
+
*
|
|
7
|
+
* See [the WAI ARIA guidelines for Accordions](https://www.w3.org/WAI/ARIA/apg/patterns/accordion/).
|
|
8
|
+
*
|
|
9
|
+
* The structure of an Accordion is:
|
|
10
|
+
*
|
|
11
|
+
* ```
|
|
12
|
+
* <Accordion>
|
|
13
|
+
* <AccordionItem>
|
|
14
|
+
* <AccordionHeader>
|
|
15
|
+
* <AccordionTrigger />
|
|
16
|
+
* </AccordionHeader>
|
|
17
|
+
* <AccordionContent />
|
|
18
|
+
* </AccordionItem>
|
|
19
|
+
* </Accordion>
|
|
20
|
+
* ```
|
|
21
|
+
*
|
|
22
|
+
* @prop {'single' | 'multiple'} type -- Whether a single AccordionItem or multiple AccordionItems can be expanded at the same time
|
|
23
|
+
* @prop {string | string[]} value -- The value of the expanded AccordionItem, or an array of values if the type is 'multiple'
|
|
24
|
+
* @prop {boolean} disabled -- If set to true, the user cannot interact with any items in the Accordion
|
|
25
|
+
* @prop {(value: string | string[]) => void} [onchange] -- Raised when the expanded item(s) have changed
|
|
26
|
+
*/
|
|
27
|
+
export default function ($props: any) {
|
|
28
|
+
$props.type ||= 'single';
|
|
29
|
+
$props.value ||= $props.type === 'single' ? '' : [];
|
|
30
|
+
|
|
31
|
+
interface State {
|
|
32
|
+
value: string | string[];
|
|
33
|
+
itemStates: ItemState[];
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
let $state: State = $watch({
|
|
37
|
+
value: $props.value,
|
|
38
|
+
itemStates: []
|
|
39
|
+
})
|
|
40
|
+
|
|
41
|
+
// This is used to assign automatic indexes to items where needed
|
|
42
|
+
let nextIndex = 0;
|
|
43
|
+
|
|
44
|
+
// Set the context to pass down to items, with functions for each item to call
|
|
45
|
+
let context: AccordionContext = {
|
|
46
|
+
registerItem,
|
|
47
|
+
removeItem,
|
|
48
|
+
toggleItem,
|
|
49
|
+
handleHeaderKey
|
|
50
|
+
};
|
|
51
|
+
$context[AccordionContextName] = context;
|
|
52
|
+
|
|
53
|
+
$run(() => {
|
|
54
|
+
// HACK: This should probably be done with setters?
|
|
55
|
+
let newValue = $state.value;
|
|
56
|
+
|
|
57
|
+
// Get the value
|
|
58
|
+
switch ($props.type) {
|
|
59
|
+
case 'single': {
|
|
60
|
+
// Ensure the value passed in was a string (in case e.g. the user has set values to ints)
|
|
61
|
+
newValue = newValue?.toString();
|
|
62
|
+
for (let item of $state.itemStates) {
|
|
63
|
+
item.expanded = item.value === newValue;
|
|
64
|
+
}
|
|
65
|
+
break;
|
|
66
|
+
}
|
|
67
|
+
case 'multiple': {
|
|
68
|
+
// Ensure the value passed in is an array
|
|
69
|
+
if (!Array.isArray(newValue)) {
|
|
70
|
+
newValue = [newValue];
|
|
71
|
+
}
|
|
72
|
+
for (let item of $state.itemStates) {
|
|
73
|
+
item.expanded = newValue.indexOf(item.value) !== -1;
|
|
74
|
+
}
|
|
75
|
+
break;
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
// Set the value
|
|
80
|
+
$state.value = newValue;
|
|
81
|
+
})
|
|
82
|
+
|
|
83
|
+
$run(() => {
|
|
84
|
+
$state.itemStates.forEach((s) => s.parentDisabled = $props.disabled);
|
|
85
|
+
});
|
|
86
|
+
|
|
87
|
+
// Dispatch the change event when the value changes
|
|
88
|
+
// TODO: Should this be a setter instead?
|
|
89
|
+
$run(() => {
|
|
90
|
+
if ($props.onchange) {
|
|
91
|
+
$props.onchange($state.value);
|
|
92
|
+
}
|
|
93
|
+
})
|
|
94
|
+
|
|
95
|
+
function registerItem(itemState: ItemState) {
|
|
96
|
+
// If an index wasn't set for the item, set it automatically
|
|
97
|
+
if (itemState.index === -1) {
|
|
98
|
+
itemState.index = nextIndex++;
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
// If a value wasn't set for the item, set it to the index
|
|
102
|
+
if (!itemState.value) {
|
|
103
|
+
itemState.value = itemState.index.toString();
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
// If we have a value, set whether the item should be expanded
|
|
107
|
+
if ($state.value) {
|
|
108
|
+
switch ($props.type) {
|
|
109
|
+
case 'single': {
|
|
110
|
+
itemState.expanded = $state.value === itemState.value;
|
|
111
|
+
break;
|
|
112
|
+
}
|
|
113
|
+
case 'multiple': {
|
|
114
|
+
itemState.expanded = $state.value.includes(itemState.value);
|
|
115
|
+
break;
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
// Set whether the Accordion itself is disabled
|
|
121
|
+
$state.parentDisabled = $props.disabled
|
|
122
|
+
|
|
123
|
+
// Add the item's state to the array
|
|
124
|
+
$state.itemStates.splice(itemState.index, 0, itemState);
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
// TODO: I think this should be done by value
|
|
128
|
+
function removeItem(itemIndex: number) {
|
|
129
|
+
// Remove the item and re-index
|
|
130
|
+
let index = $state.itemStates.findIndex((item) => item.index === itemIndex);
|
|
131
|
+
if (index !== -1) {
|
|
132
|
+
$state.itemStates.splice(itemIndex, 1);
|
|
133
|
+
}
|
|
134
|
+
$state.itemStates.forEach((item, i) => (item.index = i));
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
function toggleItem(toggleValue: string) {
|
|
138
|
+
switch ($props.type) {
|
|
139
|
+
case 'single': {
|
|
140
|
+
for (let item of $state.itemStates) {
|
|
141
|
+
// The item is expanded if it has the supplied value (i.e. if it was clicked) and if it
|
|
142
|
+
// wasn't already expanded (i.e. we collapse it if it was expanded and clicked)
|
|
143
|
+
if (item.value === toggleValue) {
|
|
144
|
+
$state.value = item.expanded ? '' : item.value;
|
|
145
|
+
break;
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
break;
|
|
149
|
+
}
|
|
150
|
+
case 'multiple': {
|
|
151
|
+
let newValue = [];
|
|
152
|
+
for (let item of $state.itemStates) {
|
|
153
|
+
// The item is expanded if it has the supplied value (i.e. if it was clicked) or if it
|
|
154
|
+
// was already expanded
|
|
155
|
+
if (
|
|
156
|
+
(item.value === toggleValue && !item.expanded) ||
|
|
157
|
+
(item.value !== toggleValue && item.expanded)
|
|
158
|
+
) {
|
|
159
|
+
newValue.push(item.value);
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
$state.value = newValue.sort();
|
|
163
|
+
break;
|
|
164
|
+
}
|
|
165
|
+
}
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
function handleHeaderKey(headerIndex: number, e: KeyboardEvent) {
|
|
169
|
+
switch (e.key) {
|
|
170
|
+
case 'Up':
|
|
171
|
+
case 'ArrowUp': {
|
|
172
|
+
if (headerIndex > 0) {
|
|
173
|
+
e.preventDefault();
|
|
174
|
+
$state.itemStates[headerIndex - 1].setFocused();
|
|
175
|
+
}
|
|
176
|
+
break;
|
|
177
|
+
}
|
|
178
|
+
case 'Down':
|
|
179
|
+
case 'ArrowDown': {
|
|
180
|
+
if (headerIndex < $state.itemStates.length - 1) {
|
|
181
|
+
e.preventDefault();
|
|
182
|
+
$state.itemStates[headerIndex + 1].setFocused();
|
|
183
|
+
}
|
|
184
|
+
break;
|
|
185
|
+
}
|
|
186
|
+
case 'Home': {
|
|
187
|
+
if (headerIndex > 0) {
|
|
188
|
+
e.preventDefault();
|
|
189
|
+
$state.itemStates[0].setFocused();
|
|
190
|
+
}
|
|
191
|
+
break;
|
|
192
|
+
}
|
|
193
|
+
case 'End': {
|
|
194
|
+
if (headerIndex < $state.itemStates.length - 1) {
|
|
195
|
+
e.preventDefault();
|
|
196
|
+
$state.itemStates[$state.itemStates.length - 1].setFocused();
|
|
197
|
+
}
|
|
198
|
+
break;
|
|
199
|
+
}
|
|
200
|
+
}
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
@render {
|
|
204
|
+
<div class="torp-accordion">
|
|
205
|
+
<:slot />
|
|
206
|
+
</div>
|
|
207
|
+
}
|
|
208
|
+
}
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import getId from '../utils/getId';
|
|
2
|
+
import { AccordionItemContextName, type AccordionItemContext } from './AccordionTypes';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Content for an AccordionItem, which can be revealed or hidden by an associated AccordionTrigger.
|
|
6
|
+
*
|
|
7
|
+
* @prop {string} [id] -- An ID for the AccordionContent's div container
|
|
8
|
+
* @prop {boolean} [ariaRegion] -- Whether this content should act as a region. Set this when the content contains heading elements or a nested Accordion
|
|
9
|
+
*/
|
|
10
|
+
export default function AccordionContent($props: any) {
|
|
11
|
+
$props.id ||= getId();
|
|
12
|
+
|
|
13
|
+
const context = $context[AccordionItemContextName] as AccordionItemContext;
|
|
14
|
+
if (!context) {
|
|
15
|
+
throw new Error('AccordionContent must be contained within an AccordionItem');
|
|
16
|
+
}
|
|
17
|
+
let $state = $context[AccordionItemContextName].state
|
|
18
|
+
|
|
19
|
+
// Set the content ID so that it can be used with aria-controls in AccordionTrigger
|
|
20
|
+
$state.contentId = $props.id;
|
|
21
|
+
|
|
22
|
+
@render {
|
|
23
|
+
<div
|
|
24
|
+
id={$props.id}
|
|
25
|
+
class='torp-accordion-content'
|
|
26
|
+
role={$props.ariaRegion ? 'region' : undefined}
|
|
27
|
+
aria-labelledby={$state.headerId}
|
|
28
|
+
data-state={$state.dataState}
|
|
29
|
+
data-disabled={$state.dataDisabled}
|
|
30
|
+
>
|
|
31
|
+
@if ($state.expanded) {
|
|
32
|
+
<:slot />
|
|
33
|
+
}
|
|
34
|
+
</div>
|
|
35
|
+
}
|
|
36
|
+
}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import { AccordionItemContextName, type AccordionItemContext } from './AccordionTypes';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* The header for an AccordionItem, which contains the AccordionTrigger.
|
|
5
|
+
*
|
|
6
|
+
* The structure of an AccordionHeader is:
|
|
7
|
+
*
|
|
8
|
+
* ```
|
|
9
|
+
* <AccordionHeader>
|
|
10
|
+
* <AccordionTrigger />
|
|
11
|
+
* </AccordionHeader>
|
|
12
|
+
* ```
|
|
13
|
+
*
|
|
14
|
+
* @prop {'h1' | 'h2' | 'h3' | 'h4' | 'h5' | 'h6'} as -- The type of HTML header to use
|
|
15
|
+
*/
|
|
16
|
+
export default function ($props: any) {
|
|
17
|
+
const context = $context[AccordionItemContextName] as AccordionItemContext;
|
|
18
|
+
if (!context) {
|
|
19
|
+
throw new Error('AccordionHeader must be contained within an AccordionItem');
|
|
20
|
+
}
|
|
21
|
+
let $state = $context[AccordionItemContextName].state
|
|
22
|
+
|
|
23
|
+
@render {
|
|
24
|
+
@// TODO: $props.as
|
|
25
|
+
<h4
|
|
26
|
+
class='torp-accordion-header'
|
|
27
|
+
data-state={$state.dataState}
|
|
28
|
+
data-disabled={$state.dataDisabled}
|
|
29
|
+
>
|
|
30
|
+
<:slot />
|
|
31
|
+
</h4>
|
|
32
|
+
}
|
|
33
|
+
}
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
import { AccordionContextName, AccordionItemContextName, type AccordionContext, type AccordionItemContext } from './AccordionTypes';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* An item in an Accordion, which must consist of an AccordionTrigger and an AccordionContent.
|
|
5
|
+
*
|
|
6
|
+
* The structure of an AccordionItem is:
|
|
7
|
+
*
|
|
8
|
+
* ```
|
|
9
|
+
* <AccordionItem>
|
|
10
|
+
* <AccordionHeader>
|
|
11
|
+
* <AccordionTrigger />
|
|
12
|
+
* </AccordionHeader>
|
|
13
|
+
* <AccordionContent />
|
|
14
|
+
* </AccordionItem>
|
|
15
|
+
* ```
|
|
16
|
+
*
|
|
17
|
+
* @prop {number} [index] -- The index of this item in the Accordion. Set this if you will be inserting, removing or sorting items. If you don't set this, it will be set automatically
|
|
18
|
+
* @prop {string} [value] -- A value for the item. Set this if you need more control over which item(s) are expanded. If you don't set this, the value will be set to the item's initial index
|
|
19
|
+
* @prop {boolean} [disabled] -- If set to true, the user cannot interact with this AccordionItem
|
|
20
|
+
* @prop {(boolean) => void} [ontoggle] -- Raised when this item is opened or closed
|
|
21
|
+
*/
|
|
22
|
+
export default function AccordionItem($props: any) {
|
|
23
|
+
let $state: ItemState = $watch({
|
|
24
|
+
index: -1,
|
|
25
|
+
value: "",
|
|
26
|
+
expanded: false,
|
|
27
|
+
disabled: $props.disabled,
|
|
28
|
+
parentDisabled: false,
|
|
29
|
+
get dataState() {
|
|
30
|
+
return this.expanded ? 'open' : 'closed';
|
|
31
|
+
},
|
|
32
|
+
})
|
|
33
|
+
|
|
34
|
+
// Get stuff out of the AccordionContext
|
|
35
|
+
const context = $context[AccordionContextName] as AccordionContext;
|
|
36
|
+
if (!context) {
|
|
37
|
+
throw new Error('AccordionItem must be contained within an Accordion');
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
// Put stuff into an AccordionItemContext
|
|
41
|
+
const itemContext: AccordionItemContext = {
|
|
42
|
+
toggleItem: context.toggleItem,
|
|
43
|
+
handleHeaderKey: context.handleHeaderKey,
|
|
44
|
+
state: $state,
|
|
45
|
+
};
|
|
46
|
+
$context[AccordionItemContextName] = itemContext;
|
|
47
|
+
|
|
48
|
+
// Register this item with the parent Accordion, which will handle toggling expanded for all items
|
|
49
|
+
context.registerItem($state);
|
|
50
|
+
|
|
51
|
+
// Remove the item from the parent Accordion when this item is destroyed
|
|
52
|
+
$run(() => {
|
|
53
|
+
return () => {
|
|
54
|
+
context.removeItem($state.index);
|
|
55
|
+
}
|
|
56
|
+
});
|
|
57
|
+
|
|
58
|
+
// Dispatch the toggle event when the value of expanded changes
|
|
59
|
+
// TODO: Should this be a setter instead?
|
|
60
|
+
$run(() => {
|
|
61
|
+
if ($props.ontoggle) {
|
|
62
|
+
$props.ontoggle($state.expanded);
|
|
63
|
+
}
|
|
64
|
+
})
|
|
65
|
+
|
|
66
|
+
@render {
|
|
67
|
+
<div
|
|
68
|
+
class='torp-accordion-item'
|
|
69
|
+
data-state={$state.dataState}
|
|
70
|
+
data-disabled={$state.dataDisabled}
|
|
71
|
+
>
|
|
72
|
+
<:slot />
|
|
73
|
+
</div>
|
|
74
|
+
}
|
|
75
|
+
}
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
import getId from '../utils/getId';
|
|
2
|
+
import { AccordionItemContextName, type AccordionItemContext } from './AccordionTypes';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* A header button for an AccordionItem, which can be used to reveal or hide an associated AccordionContent.
|
|
6
|
+
*/
|
|
7
|
+
export default function AccordionTrigger() {
|
|
8
|
+
let button: HTMLButtonElement;
|
|
9
|
+
|
|
10
|
+
$props.id ||= getId();
|
|
11
|
+
|
|
12
|
+
// Get stuff out of the AccordionItemContext
|
|
13
|
+
const context = $context[AccordionItemContextName] as AccordionItemContext;
|
|
14
|
+
if (!context) {
|
|
15
|
+
throw new Error('AccordionTrigger must be contained within an AccordionItem');
|
|
16
|
+
}
|
|
17
|
+
let $state = $context[AccordionItemContextName].state;
|
|
18
|
+
|
|
19
|
+
// Set the header ID so that it can be used with aria-labelledby in AccordionContent
|
|
20
|
+
$state.headerId = $props.id;
|
|
21
|
+
|
|
22
|
+
// Let the item know how to set the button's focus
|
|
23
|
+
$state.setFocused = setFocused;
|
|
24
|
+
|
|
25
|
+
// This function is called by the parent Accordion to focus this item's button
|
|
26
|
+
function setFocused() {
|
|
27
|
+
button.focus();
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
function handleClick() {
|
|
31
|
+
// Pass the value to the toggleItem method in the parent Accordion which will handle toggling
|
|
32
|
+
// the value of expanded for all items (e.g. to close other items if necessary)
|
|
33
|
+
context.toggleItem($state.value);
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
function handleKey(e: KeyboardEvent) {
|
|
37
|
+
// Pass the key press up to the parent Accordion which will handle setting the focused button
|
|
38
|
+
context.handleHeaderKey($state.index, e);
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
@render {
|
|
42
|
+
<button
|
|
43
|
+
type="button"
|
|
44
|
+
id={$props.id}
|
|
45
|
+
class='torp-accordion-button'
|
|
46
|
+
disabled={$state.disabled || $state.parentDisabled}
|
|
47
|
+
aria-expanded={$state.expanded.toString()}
|
|
48
|
+
aria-disabled={$state.disabled}
|
|
49
|
+
aria-controls={$state.contentId}
|
|
50
|
+
data-state={$state.dataState}
|
|
51
|
+
data-disabled={$state.disabled}
|
|
52
|
+
:self={button}
|
|
53
|
+
onclick={handleClick}
|
|
54
|
+
onkeydown={handleKey}
|
|
55
|
+
>
|
|
56
|
+
<:slot />
|
|
57
|
+
</button>
|
|
58
|
+
}
|
|
59
|
+
}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
export const AccordionContextName = "Accordion";
|
|
2
|
+
export const AccordionItemContextName = "AccordionItem";
|
|
3
|
+
|
|
4
|
+
export interface AccordionContext {
|
|
5
|
+
/** Called from an AccordionItem when it is added */
|
|
6
|
+
registerItem: (state: ItemState, setFocused: () => void) => void;
|
|
7
|
+
/** Called from an AccordionItem when it is removed */
|
|
8
|
+
removeItem: (index: number) => void;
|
|
9
|
+
/** Called from an AccordionItem when it is toggled */
|
|
10
|
+
toggleItem: (value: string) => void;
|
|
11
|
+
/** Called from an AccordionHeader when it receives a keyboard event */
|
|
12
|
+
handleHeaderKey: (index: number, e: KeyboardEvent) => void;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
export interface AccordionItemContext {
|
|
16
|
+
/** Called when an AccordionItem is toggled */
|
|
17
|
+
toggleItem: (value: string) => void;
|
|
18
|
+
/** Called when an AccordionHeader receives a keyboard event */
|
|
19
|
+
handleHeaderKey: (index: number, e: KeyboardEvent) => void;
|
|
20
|
+
/** The reactive state for an AccordionItem */
|
|
21
|
+
state: ItemState;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
export interface ItemState {
|
|
25
|
+
index: number;
|
|
26
|
+
value: string;
|
|
27
|
+
expanded: boolean;
|
|
28
|
+
disabled: boolean;
|
|
29
|
+
parentDisabled: boolean;
|
|
30
|
+
/** Called in the Accordion when a header needs to be focused */
|
|
31
|
+
setFocused: () => void;
|
|
32
|
+
}
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __defProp = Object.defineProperty;
|
|
3
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
4
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
5
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
6
|
+
var __export = (target, all) => {
|
|
7
|
+
for (var name in all)
|
|
8
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
9
|
+
};
|
|
10
|
+
var __copyProps = (to, from, except, desc) => {
|
|
11
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
12
|
+
for (let key of __getOwnPropNames(from))
|
|
13
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
14
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
15
|
+
}
|
|
16
|
+
return to;
|
|
17
|
+
};
|
|
18
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
19
|
+
|
|
20
|
+
// src/Accordion/index.ts
|
|
21
|
+
var Accordion_exports = {};
|
|
22
|
+
__export(Accordion_exports, {
|
|
23
|
+
Accordion: () => Accordion_default,
|
|
24
|
+
AccordionContent: () => AccordionContent_default,
|
|
25
|
+
AccordionHeader: () => AccordionHeader_default,
|
|
26
|
+
AccordionItem: () => AccordionItem_default,
|
|
27
|
+
AccordionTrigger: () => AccordionTrigger_default
|
|
28
|
+
});
|
|
29
|
+
module.exports = __toCommonJS(Accordion_exports);
|
|
30
|
+
|
|
31
|
+
// src/Accordion/Accordion.torp
|
|
32
|
+
import Accordion_default from "./Accordion.torp";
|
|
33
|
+
|
|
34
|
+
// src/Accordion/AccordionContent.torp
|
|
35
|
+
import AccordionContent_default from "./AccordionContent.torp";
|
|
36
|
+
|
|
37
|
+
// src/Accordion/AccordionHeader.torp
|
|
38
|
+
import AccordionHeader_default from "./AccordionHeader.torp";
|
|
39
|
+
|
|
40
|
+
// src/Accordion/AccordionItem.torp
|
|
41
|
+
import AccordionItem_default from "./AccordionItem.torp";
|
|
42
|
+
|
|
43
|
+
// src/Accordion/AccordionTrigger.torp
|
|
44
|
+
import AccordionTrigger_default from "./AccordionTrigger.torp";
|
|
45
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
46
|
+
0 && (module.exports = {
|
|
47
|
+
Accordion,
|
|
48
|
+
AccordionContent,
|
|
49
|
+
AccordionHeader,
|
|
50
|
+
AccordionItem,
|
|
51
|
+
AccordionTrigger
|
|
52
|
+
});
|
|
53
|
+
//# sourceMappingURL=index.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../src/Accordion/index.ts"],"sourcesContent":["import Accordion from \"./Accordion.torp\";\nimport AccordionContent from \"./AccordionContent.torp\";\nimport AccordionHeader from \"./AccordionHeader.torp\";\nimport AccordionItem from \"./AccordionItem.torp\";\nimport AccordionTrigger from \"./AccordionTrigger.torp\";\n\nexport { Accordion, AccordionItem, AccordionHeader, AccordionTrigger, AccordionContent };\n"],"mappings":";;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;","names":[]}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
// src/Accordion/Accordion.torp
|
|
2
|
+
import Accordion_default from "./Accordion.torp";
|
|
3
|
+
|
|
4
|
+
// src/Accordion/AccordionContent.torp
|
|
5
|
+
import AccordionContent_default from "./AccordionContent.torp";
|
|
6
|
+
|
|
7
|
+
// src/Accordion/AccordionHeader.torp
|
|
8
|
+
import AccordionHeader_default from "./AccordionHeader.torp";
|
|
9
|
+
|
|
10
|
+
// src/Accordion/AccordionItem.torp
|
|
11
|
+
import AccordionItem_default from "./AccordionItem.torp";
|
|
12
|
+
|
|
13
|
+
// src/Accordion/AccordionTrigger.torp
|
|
14
|
+
import AccordionTrigger_default from "./AccordionTrigger.torp";
|
|
15
|
+
export {
|
|
16
|
+
Accordion_default as Accordion,
|
|
17
|
+
AccordionContent_default as AccordionContent,
|
|
18
|
+
AccordionHeader_default as AccordionHeader,
|
|
19
|
+
AccordionItem_default as AccordionItem,
|
|
20
|
+
AccordionTrigger_default as AccordionTrigger
|
|
21
|
+
};
|
|
22
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":[],"sourcesContent":[],"mappings":"","names":[]}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"inputs":{"src/motion/fade.ts":{"bytes":90,"imports":[],"format":"esm"},"src/motion.ts":{"bytes":52,"imports":[{"path":"src/motion/fade.ts","kind":"import-statement","original":"./motion/fade"}],"format":"esm"},"src/Accordion/Accordion.torp":{"bytes":5516,"imports":[]},"src/Accordion/AccordionContent.torp":{"bytes":1189,"imports":[]},"src/Accordion/AccordionHeader.torp":{"bytes":840,"imports":[]},"src/Accordion/AccordionItem.torp":{"bytes":2331,"imports":[]},"src/Accordion/AccordionTrigger.torp":{"bytes":1815,"imports":[]},"src/Accordion/index.ts":{"bytes":349,"imports":[{"path":"src/Accordion/Accordion.torp","kind":"import-statement","original":"./Accordion.torp"},{"path":"src/Accordion/AccordionContent.torp","kind":"import-statement","original":"./AccordionContent.torp"},{"path":"src/Accordion/AccordionHeader.torp","kind":"import-statement","original":"./AccordionHeader.torp"},{"path":"src/Accordion/AccordionItem.torp","kind":"import-statement","original":"./AccordionItem.torp"},{"path":"src/Accordion/AccordionTrigger.torp","kind":"import-statement","original":"./AccordionTrigger.torp"}],"format":"esm"}},"outputs":{"dist/motion.cjs.map":{"imports":[],"exports":[],"inputs":{},"bytes":416},"dist/motion.cjs":{"imports":[],"exports":[],"entryPoint":"src/motion.ts","inputs":{"src/motion.ts":{"bytesInOutput":130},"src/motion/fade.ts":{"bytesInOutput":92}},"bytes":1160},"dist/Accordion-BRYACVW7.torp":{"imports":[],"exports":[],"inputs":{"src/Accordion/Accordion.torp":{"bytesInOutput":5516}},"bytes":5516},"dist/AccordionContent-HGVMBVT6.torp":{"imports":[],"exports":[],"inputs":{"src/Accordion/AccordionContent.torp":{"bytesInOutput":1189}},"bytes":1189},"dist/AccordionHeader-MCFK663B.torp":{"imports":[],"exports":[],"inputs":{"src/Accordion/AccordionHeader.torp":{"bytesInOutput":840}},"bytes":840},"dist/AccordionItem-RQ6AWHXL.torp":{"imports":[],"exports":[],"inputs":{"src/Accordion/AccordionItem.torp":{"bytesInOutput":2331}},"bytes":2331},"dist/AccordionTrigger-7OBA72E2.torp":{"imports":[],"exports":[],"inputs":{"src/Accordion/AccordionTrigger.torp":{"bytesInOutput":1815}},"bytes":1815},"dist/Accordion/index.cjs.map":{"imports":[],"exports":[],"inputs":{},"bytes":556},"dist/Accordion/index.cjs":{"imports":[{"path":"dist/Accordion-BRYACVW7.torp","kind":"file-loader"},{"path":"dist/AccordionContent-HGVMBVT6.torp","kind":"file-loader"},{"path":"dist/AccordionHeader-MCFK663B.torp","kind":"file-loader"},{"path":"dist/AccordionItem-RQ6AWHXL.torp","kind":"file-loader"},{"path":"dist/AccordionTrigger-7OBA72E2.torp","kind":"file-loader"}],"exports":[],"entryPoint":"src/Accordion/index.ts","inputs":{"src/Accordion/index.ts":{"bytesInOutput":349},"src/Accordion/Accordion.torp":{"bytesInOutput":54},"src/Accordion/AccordionContent.torp":{"bytesInOutput":68},"src/Accordion/AccordionHeader.torp":{"bytesInOutput":66},"src/Accordion/AccordionItem.torp":{"bytesInOutput":62},"src/Accordion/AccordionTrigger.torp":{"bytesInOutput":68}},"bytes":1861}}}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"inputs":{"src/motion/fade.ts":{"bytes":90,"imports":[],"format":"esm"},"src/motion.ts":{"bytes":52,"imports":[{"path":"src/motion/fade.ts","kind":"import-statement","original":"./motion/fade"}],"format":"esm"},"src/Accordion/Accordion.torp":{"bytes":5516,"imports":[]},"src/Accordion/AccordionContent.torp":{"bytes":1189,"imports":[]},"src/Accordion/AccordionHeader.torp":{"bytes":840,"imports":[]},"src/Accordion/AccordionItem.torp":{"bytes":2331,"imports":[]},"src/Accordion/AccordionTrigger.torp":{"bytes":1815,"imports":[]},"src/Accordion/index.ts":{"bytes":349,"imports":[{"path":"src/Accordion/Accordion.torp","kind":"import-statement","original":"./Accordion.torp"},{"path":"src/Accordion/AccordionContent.torp","kind":"import-statement","original":"./AccordionContent.torp"},{"path":"src/Accordion/AccordionHeader.torp","kind":"import-statement","original":"./AccordionHeader.torp"},{"path":"src/Accordion/AccordionItem.torp","kind":"import-statement","original":"./AccordionItem.torp"},{"path":"src/Accordion/AccordionTrigger.torp","kind":"import-statement","original":"./AccordionTrigger.torp"}],"format":"esm"}},"outputs":{"dist/motion.js.map":{"imports":[],"exports":[],"inputs":{},"bytes":289},"dist/motion.js":{"imports":[],"exports":["fade"],"entryPoint":"src/motion.ts","inputs":{"src/motion/fade.ts":{"bytesInOutput":92},"src/motion.ts":{"bytesInOutput":0}},"bytes":149},"dist/Accordion-BRYACVW7.torp":{"imports":[],"exports":[],"inputs":{"src/Accordion/Accordion.torp":{"bytesInOutput":5516}},"bytes":5516},"dist/AccordionContent-HGVMBVT6.torp":{"imports":[],"exports":[],"inputs":{"src/Accordion/AccordionContent.torp":{"bytesInOutput":1189}},"bytes":1189},"dist/AccordionHeader-MCFK663B.torp":{"imports":[],"exports":[],"inputs":{"src/Accordion/AccordionHeader.torp":{"bytesInOutput":840}},"bytes":840},"dist/AccordionItem-RQ6AWHXL.torp":{"imports":[],"exports":[],"inputs":{"src/Accordion/AccordionItem.torp":{"bytesInOutput":2331}},"bytes":2331},"dist/AccordionTrigger-7OBA72E2.torp":{"imports":[],"exports":[],"inputs":{"src/Accordion/AccordionTrigger.torp":{"bytesInOutput":1815}},"bytes":1815},"dist/Accordion/index.js.map":{"imports":[],"exports":[],"inputs":{},"bytes":93},"dist/Accordion/index.js":{"imports":[{"path":"dist/Accordion-BRYACVW7.torp","kind":"file-loader"},{"path":"dist/AccordionContent-HGVMBVT6.torp","kind":"file-loader"},{"path":"dist/AccordionHeader-MCFK663B.torp","kind":"file-loader"},{"path":"dist/AccordionItem-RQ6AWHXL.torp","kind":"file-loader"},{"path":"dist/AccordionTrigger-7OBA72E2.torp","kind":"file-loader"}],"exports":["Accordion","AccordionContent","AccordionHeader","AccordionItem","AccordionTrigger"],"entryPoint":"src/Accordion/index.ts","inputs":{"src/Accordion/Accordion.torp":{"bytesInOutput":54},"src/Accordion/AccordionContent.torp":{"bytesInOutput":68},"src/Accordion/AccordionHeader.torp":{"bytesInOutput":66},"src/Accordion/AccordionItem.torp":{"bytesInOutput":62},"src/Accordion/AccordionTrigger.torp":{"bytesInOutput":68},"src/Accordion/index.ts":{"bytesInOutput":0}},"bytes":735}}}
|
package/dist/motion.cjs
ADDED
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __defProp = Object.defineProperty;
|
|
3
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
4
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
5
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
6
|
+
var __export = (target, all) => {
|
|
7
|
+
for (var name in all)
|
|
8
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
9
|
+
};
|
|
10
|
+
var __copyProps = (to, from, except, desc) => {
|
|
11
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
12
|
+
for (let key of __getOwnPropNames(from))
|
|
13
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
14
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
15
|
+
}
|
|
16
|
+
return to;
|
|
17
|
+
};
|
|
18
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
19
|
+
|
|
20
|
+
// src/motion.ts
|
|
21
|
+
var motion_exports = {};
|
|
22
|
+
__export(motion_exports, {
|
|
23
|
+
fade: () => fade_default
|
|
24
|
+
});
|
|
25
|
+
module.exports = __toCommonJS(motion_exports);
|
|
26
|
+
|
|
27
|
+
// src/motion/fade.ts
|
|
28
|
+
var animationFrames = [{ opacity: 0 }, { opacity: 1 }];
|
|
29
|
+
var fade_default = animationFrames;
|
|
30
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
31
|
+
0 && (module.exports = {
|
|
32
|
+
fade
|
|
33
|
+
});
|
|
34
|
+
//# sourceMappingURL=motion.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/motion.ts","../src/motion/fade.ts"],"sourcesContent":["import fade from \"./motion/fade\";\n\nexport { fade };\n","const animationFrames = [{ opacity: 0 }, { opacity: 1 }];\nexport default animationFrames;\n"],"mappings":";;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;;;ACAA,IAAM,kBAAkB,CAAC,EAAE,SAAS,EAAE,GAAG,EAAE,SAAS,EAAE,CAAC;AACvD,IAAO,eAAQ;","names":[]}
|
package/dist/motion.d.ts
ADDED
package/dist/motion.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/motion/fade.ts"],"sourcesContent":["const animationFrames = [{ opacity: 0 }, { opacity: 1 }];\nexport default animationFrames;\n"],"mappings":";AAAA,IAAM,kBAAkB,CAAC,EAAE,SAAS,EAAE,GAAG,EAAE,SAAS,EAAE,CAAC;AACvD,IAAO,eAAQ;","names":[]}
|