@zomako/elearning-components 2.0.5 → 2.0.6
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/Accordion/README.md +74 -0
- package/DragAndDropActivity/README.md +124 -0
- package/DragAndDropActivity/index.tsx +343 -0
- package/DragAndDropActivity/style.module.css +216 -0
- package/README.md +16 -0
- package/dist/elearning-components.css +1 -1
- package/dist/elearning-components.es.js +6358 -563
- package/dist/elearning-components.umd.js +12 -8
- package/package.json +2 -1
- package/src/App.jsx +85 -5
- package/src/index.ts +19 -2
- package/src/components/Accordion/README.md +0 -164
- /package/{src/components/Accordion → Accordion}/index.tsx +0 -0
- /package/{src/components/Accordion → Accordion}/style.module.css +0 -0
package/src/App.jsx
CHANGED
|
@@ -1,9 +1,16 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
|
-
import {
|
|
2
|
+
import {
|
|
3
|
+
Accordion,
|
|
4
|
+
FlashcardDeck,
|
|
5
|
+
InteractiveTimeline,
|
|
6
|
+
MatchingActivity,
|
|
7
|
+
SortingActivity,
|
|
8
|
+
DragAndDropActivity,
|
|
9
|
+
} from './index';
|
|
3
10
|
|
|
4
11
|
const accordionItems = [
|
|
5
12
|
{ id: 'getting-started', title: 'Getting started', content: 'Install the package and import the components you need.' },
|
|
6
|
-
{ id: 'components', title: 'Components', content: '
|
|
13
|
+
{ id: 'components', title: 'Components', content: 'Accordion, FlashcardDeck, InteractiveTimeline, MatchingActivity, SortingActivity, and DragAndDropActivity are available.' },
|
|
7
14
|
{ id: 'support', title: 'Support', content: 'Check the repository for documentation and issues.' },
|
|
8
15
|
];
|
|
9
16
|
|
|
@@ -12,18 +19,91 @@ const sampleCards = [
|
|
|
12
19
|
{ front: 'Front 2', back: 'Back 2' },
|
|
13
20
|
];
|
|
14
21
|
|
|
22
|
+
const timelineEvents = [
|
|
23
|
+
{ id: '1', year: '2020', title: 'Project kickoff', content: <p>The project started with a small team and a clear roadmap.</p> },
|
|
24
|
+
{ id: '2', year: '2021', title: 'First release', content: <p>We shipped the first public version and gathered feedback.</p> },
|
|
25
|
+
{ id: '3', year: '2022', title: 'Scale and grow', content: <p>Focus shifted to performance and scaling for enterprise.</p> },
|
|
26
|
+
];
|
|
27
|
+
|
|
28
|
+
const matchingItems = [
|
|
29
|
+
{ id: 'a', content: 'Paris', matchId: 'capital-france' },
|
|
30
|
+
{ id: 'b', content: 'Berlin', matchId: 'capital-germany' },
|
|
31
|
+
{ id: 'c', content: 'Madrid', matchId: 'capital-spain' },
|
|
32
|
+
];
|
|
33
|
+
|
|
34
|
+
const matchingTargets = [
|
|
35
|
+
{ id: 'capital-france', content: 'France' },
|
|
36
|
+
{ id: 'capital-germany', content: 'Germany' },
|
|
37
|
+
{ id: 'capital-spain', content: 'Spain' },
|
|
38
|
+
];
|
|
39
|
+
|
|
40
|
+
const sortableItems = [
|
|
41
|
+
{ id: '1', content: 'First step: Plan the project' },
|
|
42
|
+
{ id: '2', content: 'Second step: Build the prototype' },
|
|
43
|
+
{ id: '3', content: 'Third step: Test and iterate' },
|
|
44
|
+
{ id: '4', content: 'Fourth step: Launch' },
|
|
45
|
+
];
|
|
46
|
+
|
|
47
|
+
const correctOrder = ['1', '2', '3', '4'];
|
|
48
|
+
|
|
49
|
+
const dragDropItems = [
|
|
50
|
+
{ id: 'paris', content: 'Paris' },
|
|
51
|
+
{ id: 'berlin', content: 'Berlin' },
|
|
52
|
+
{ id: 'madrid', content: 'Madrid' },
|
|
53
|
+
];
|
|
54
|
+
|
|
55
|
+
const dragDropTargets = [
|
|
56
|
+
{ id: 'target-fr', accepts: ['paris'], label: 'Capital of France' },
|
|
57
|
+
{ id: 'target-de', accepts: ['berlin'], label: 'Capital of Germany' },
|
|
58
|
+
{ id: 'target-es', accepts: ['madrid'], label: 'Capital of Spain' },
|
|
59
|
+
];
|
|
60
|
+
|
|
15
61
|
export default function App() {
|
|
16
62
|
return (
|
|
17
|
-
<div style={{ padding: '2rem', maxWidth:
|
|
63
|
+
<div style={{ padding: '2rem', maxWidth: 800, margin: '0 auto' }}>
|
|
18
64
|
<h1>E-learning Components</h1>
|
|
19
|
-
|
|
65
|
+
|
|
66
|
+
<section style={{ marginBottom: '2.5rem' }}>
|
|
20
67
|
<h2>Accordion</h2>
|
|
21
68
|
<Accordion items={accordionItems} />
|
|
22
69
|
</section>
|
|
23
|
-
|
|
70
|
+
|
|
71
|
+
<section style={{ marginBottom: '2.5rem' }}>
|
|
24
72
|
<h2>FlashcardDeck</h2>
|
|
25
73
|
<FlashcardDeck cards={sampleCards} />
|
|
26
74
|
</section>
|
|
75
|
+
|
|
76
|
+
<section style={{ marginBottom: '2.5rem' }}>
|
|
77
|
+
<h2>InteractiveTimeline</h2>
|
|
78
|
+
<InteractiveTimeline events={timelineEvents} />
|
|
79
|
+
</section>
|
|
80
|
+
|
|
81
|
+
<section style={{ marginBottom: '2.5rem' }}>
|
|
82
|
+
<h2>MatchingActivity</h2>
|
|
83
|
+
<MatchingActivity
|
|
84
|
+
items={matchingItems}
|
|
85
|
+
targets={matchingTargets}
|
|
86
|
+
onComplete={(result) => console.log('Matching result:', result)}
|
|
87
|
+
/>
|
|
88
|
+
</section>
|
|
89
|
+
|
|
90
|
+
<section style={{ marginBottom: '2.5rem' }}>
|
|
91
|
+
<h2>SortingActivity</h2>
|
|
92
|
+
<SortingActivity
|
|
93
|
+
items={sortableItems}
|
|
94
|
+
correctOrder={correctOrder}
|
|
95
|
+
onComplete={(result) => console.log('Sorting result:', result)}
|
|
96
|
+
/>
|
|
97
|
+
</section>
|
|
98
|
+
|
|
99
|
+
<section>
|
|
100
|
+
<h2>DragAndDropActivity</h2>
|
|
101
|
+
<DragAndDropActivity
|
|
102
|
+
items={dragDropItems}
|
|
103
|
+
targets={dragDropTargets}
|
|
104
|
+
onComplete={(result) => console.log('Drag and drop result:', result)}
|
|
105
|
+
/>
|
|
106
|
+
</section>
|
|
27
107
|
</div>
|
|
28
108
|
);
|
|
29
109
|
}
|
package/src/index.ts
CHANGED
|
@@ -1,8 +1,25 @@
|
|
|
1
1
|
// src/index.ts
|
|
2
2
|
export { default as FlashcardDeck } from './components/FlashcardDeck';
|
|
3
|
-
export { default as Accordion, type AccordionProps, type AccordionItem } from '
|
|
3
|
+
export { default as Accordion, type AccordionProps, type AccordionItem } from '../Accordion';
|
|
4
4
|
export {
|
|
5
5
|
default as InteractiveTimeline,
|
|
6
6
|
type TimelineEvent,
|
|
7
7
|
type InteractiveTimelineProps,
|
|
8
|
-
} from './components/InteractiveTimeline';
|
|
8
|
+
} from './components/InteractiveTimeline';
|
|
9
|
+
export {
|
|
10
|
+
default as MatchingActivity,
|
|
11
|
+
type MatchItem,
|
|
12
|
+
type MatchTarget,
|
|
13
|
+
type MatchingActivityProps,
|
|
14
|
+
} from '../MatchingActivity';
|
|
15
|
+
export {
|
|
16
|
+
default as SortingActivity,
|
|
17
|
+
type SortableItem,
|
|
18
|
+
type SortingActivityProps,
|
|
19
|
+
} from '../SortingActivity';
|
|
20
|
+
export {
|
|
21
|
+
default as DragAndDropActivity,
|
|
22
|
+
type DraggableItem,
|
|
23
|
+
type DropTarget,
|
|
24
|
+
type DragAndDropProps,
|
|
25
|
+
} from '../DragAndDropActivity';
|
|
@@ -1,164 +0,0 @@
|
|
|
1
|
-
# Accordion Component
|
|
2
|
-
|
|
3
|
-
A fully accessible React accordion using **pure CSS** for animations and CSS Modules for styling. It renders a list of collapsible items with smooth expand/collapse and supports either single or multiple open panels. No Framer Motion or other animation library is required.
|
|
4
|
-
|
|
5
|
-
## Purpose
|
|
6
|
-
|
|
7
|
-
The `Accordion` component is designed for e-learning and content-heavy UIs where you need to reveal content on demand without leaving the page. Use it for FAQs, course modules, step-by-step instructions, or any list of titled sections with collapsible bodies.
|
|
8
|
-
|
|
9
|
-
## Features
|
|
10
|
-
|
|
11
|
-
- **Pure CSS expand/collapse** – Smooth animations without Framer Motion; consistent with a CSS-first approach and smaller bundle size
|
|
12
|
-
- **Single or multiple open panels** – Controlled by the `allowMultiple` prop
|
|
13
|
-
- **Id-based API** – Items use required `id`; initial open state is set via `defaultOpenId` (string or string[])
|
|
14
|
-
- **Keyboard accessible** – Enter/Space to toggle, Arrow keys to move focus, Home/End for first/last
|
|
15
|
-
- **ARIA-compliant** – Correct `aria-expanded`, `aria-controls`, `aria-labelledby`, and `aria-hidden` for screen readers
|
|
16
|
-
- **Clean, modern styling** – CSS Modules with a clear header/content distinction
|
|
17
|
-
- **TypeScript** – Exported `AccordionProps` and `AccordionItem` interfaces
|
|
18
|
-
|
|
19
|
-
## Installation
|
|
20
|
-
|
|
21
|
-
### Prerequisites
|
|
22
|
-
|
|
23
|
-
- React 16.8+ (hooks)
|
|
24
|
-
- Node.js and npm (or yarn/pnpm)
|
|
25
|
-
|
|
26
|
-
### Dependencies
|
|
27
|
-
|
|
28
|
-
```bash
|
|
29
|
-
npm install react react-dom
|
|
30
|
-
```
|
|
31
|
-
|
|
32
|
-
No animation library is required.
|
|
33
|
-
|
|
34
|
-
## Props
|
|
35
|
-
|
|
36
|
-
The component accepts props as defined in the `AccordionProps` interface.
|
|
37
|
-
|
|
38
|
-
| Prop | Type | Required | Default | Description |
|
|
39
|
-
|------|------|----------|---------|-------------|
|
|
40
|
-
| `items` | `AccordionItem[]` | Yes | — | List of accordion items. Each must have `id`, `title`, and `content`. |
|
|
41
|
-
| `allowMultiple` | `boolean` | No | `false` | If `true`, multiple panels can be open at once. If `false`, opening one closes the others. |
|
|
42
|
-
| `defaultOpenId` | `string \| string[]` | No | — | Id(s) of item(s) to open initially. Single string or array of strings. |
|
|
43
|
-
|
|
44
|
-
### AccordionItem
|
|
45
|
-
|
|
46
|
-
| Property | Type | Required | Description |
|
|
47
|
-
|----------|------|----------|-------------|
|
|
48
|
-
| `id` | `string` | Yes | Unique id for the item (used for state and as React `key`). |
|
|
49
|
-
| `title` | `string` | Yes | Label for the accordion header. |
|
|
50
|
-
| `content` | `React.ReactNode` | Yes | Content shown when the panel is expanded. |
|
|
51
|
-
|
|
52
|
-
### TypeScript interfaces
|
|
53
|
-
|
|
54
|
-
```typescript
|
|
55
|
-
import Accordion, { AccordionProps, AccordionItem } from './Accordion';
|
|
56
|
-
|
|
57
|
-
interface AccordionItem {
|
|
58
|
-
id: string;
|
|
59
|
-
title: string;
|
|
60
|
-
content: React.ReactNode;
|
|
61
|
-
}
|
|
62
|
-
|
|
63
|
-
interface AccordionProps {
|
|
64
|
-
items: AccordionItem[];
|
|
65
|
-
allowMultiple?: boolean;
|
|
66
|
-
defaultOpenId?: string | string[];
|
|
67
|
-
}
|
|
68
|
-
```
|
|
69
|
-
|
|
70
|
-
## Usage
|
|
71
|
-
|
|
72
|
-
### Basic example (single open panel)
|
|
73
|
-
|
|
74
|
-
Only one panel is open at a time. No panel is open initially.
|
|
75
|
-
|
|
76
|
-
```tsx
|
|
77
|
-
import Accordion, { AccordionItem } from './components/Accordion';
|
|
78
|
-
|
|
79
|
-
const items: AccordionItem[] = [
|
|
80
|
-
{
|
|
81
|
-
id: 'included',
|
|
82
|
-
title: 'What is included?',
|
|
83
|
-
content: 'Access to all lessons, quizzes, and downloadable resources for 12 months.',
|
|
84
|
-
},
|
|
85
|
-
{
|
|
86
|
-
id: 'refund',
|
|
87
|
-
title: 'Can I get a refund?',
|
|
88
|
-
content: 'Yes. You can request a full refund within 14 days of purchase if you have not completed more than 2 lessons.',
|
|
89
|
-
},
|
|
90
|
-
{
|
|
91
|
-
id: 'support',
|
|
92
|
-
title: 'How do I get support?',
|
|
93
|
-
content: 'Use the Help button in the course dashboard or email support@example.com.',
|
|
94
|
-
},
|
|
95
|
-
];
|
|
96
|
-
|
|
97
|
-
function FAQ() {
|
|
98
|
-
return <Accordion items={items} />;
|
|
99
|
-
}
|
|
100
|
-
```
|
|
101
|
-
|
|
102
|
-
### Multiple panels open
|
|
103
|
-
|
|
104
|
-
Allow several panels to be open at once, with specific items open by id:
|
|
105
|
-
|
|
106
|
-
```tsx
|
|
107
|
-
<Accordion
|
|
108
|
-
items={items}
|
|
109
|
-
allowMultiple
|
|
110
|
-
defaultOpenId={['included', 'support']}
|
|
111
|
-
/>
|
|
112
|
-
```
|
|
113
|
-
|
|
114
|
-
### One panel open by default (single mode)
|
|
115
|
-
|
|
116
|
-
Open a single item initially by id:
|
|
117
|
-
|
|
118
|
-
```tsx
|
|
119
|
-
<Accordion
|
|
120
|
-
items={items}
|
|
121
|
-
defaultOpenId="refund"
|
|
122
|
-
/>
|
|
123
|
-
```
|
|
124
|
-
|
|
125
|
-
### Rich content
|
|
126
|
-
|
|
127
|
-
`content` can be any `React.ReactNode` (e.g. lists, links, components):
|
|
128
|
-
|
|
129
|
-
```tsx
|
|
130
|
-
const items: AccordionItem[] = [
|
|
131
|
-
{
|
|
132
|
-
id: 'module-1',
|
|
133
|
-
title: 'Module 1: Introduction',
|
|
134
|
-
content: (
|
|
135
|
-
<>
|
|
136
|
-
<p>Welcome to the course. In this module you will:</p>
|
|
137
|
-
<ul>
|
|
138
|
-
<li>Learn the key concepts</li>
|
|
139
|
-
<li>Complete a short quiz</li>
|
|
140
|
-
</ul>
|
|
141
|
-
</>
|
|
142
|
-
),
|
|
143
|
-
},
|
|
144
|
-
];
|
|
145
|
-
```
|
|
146
|
-
|
|
147
|
-
## Accessibility
|
|
148
|
-
|
|
149
|
-
- **Keyboard**: Each header is focusable. Enter or Space toggles the panel. Arrow Down/Right moves to the next header, Arrow Up/Left to the previous. Home focuses the first header, End the last.
|
|
150
|
-
- **ARIA**: The root has `role="region"` and `aria-label="Accordion"`. Each trigger has `aria-expanded` and `aria-controls` pointing to its panel. Each panel has `role="region"`, `aria-labelledby` pointing to its header, and `aria-hidden` when collapsed.
|
|
151
|
-
- **Focus**: Focus is not trapped; keyboard users can tab in and out of the accordion and use the arrow keys to move between headers.
|
|
152
|
-
|
|
153
|
-
## Styling
|
|
154
|
-
|
|
155
|
-
Styles are in `style.module.css`. Expand/collapse and chevron rotation use CSS transitions (no JavaScript animation library). You can override by targeting the accordion’s container in your own CSS. The design uses a light gray header background and white content area with a clear border between header and content.
|
|
156
|
-
|
|
157
|
-
## File structure
|
|
158
|
-
|
|
159
|
-
```
|
|
160
|
-
Accordion/
|
|
161
|
-
index.tsx # Component and TypeScript interfaces
|
|
162
|
-
style.module.css # Component styles (pure CSS animations)
|
|
163
|
-
README.md # This file
|
|
164
|
-
```
|
|
File without changes
|
|
File without changes
|