@sp-days-framework/docusaurus-plugin-interactive-tasks 1.0.3 → 1.0.4
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/lib/index.d.ts +2 -4
- package/lib/index.d.ts.map +1 -1
- package/lib/index.js +1 -1
- package/lib/index.js.map +1 -1
- package/lib/plugin/remarkTaskDirective.d.ts +3 -1
- package/lib/plugin/remarkTaskDirective.d.ts.map +1 -1
- package/lib/plugin/remarkTaskDirective.js +48 -14
- package/lib/plugin/remarkTaskDirective.js.map +1 -1
- package/lib/theme/Task/Text/styles.module.css +0 -5
- package/lib/theme/Task/index.d.ts +2 -1
- package/lib/theme/Task/index.d.ts.map +1 -1
- package/lib/theme/Task/index.js +68 -94
- package/lib/theme/Task/index.js.map +1 -1
- package/lib/theme/Task/styles.module.css +91 -163
- package/lib/theme/TaskExample/index.d.ts +2 -1
- package/lib/theme/TaskExample/index.d.ts.map +1 -1
- package/lib/theme/TaskExample/index.js +67 -88
- package/lib/theme/TaskExample/index.js.map +1 -1
- package/lib/theme/TaskPlaceholder/index.d.ts.map +1 -1
- package/lib/theme/TaskPlaceholder/index.js +66 -92
- package/lib/theme/TaskPlaceholder/index.js.map +1 -1
- package/lib/theme/TaskProgressionOverview/styles.module.css +2 -2
- package/package.json +1 -1
|
@@ -1,12 +1,30 @@
|
|
|
1
1
|
/* ===================== TASK COMPONENT ===================== */
|
|
2
2
|
|
|
3
|
+
/* Style all heading levels that appear right before a task or task-example */
|
|
4
|
+
/* The heading is injected by the remark plugin for TOC integration */
|
|
5
|
+
:global(.theme-doc-markdown) > h2:has(+ div[class*="taskContainer"]),
|
|
6
|
+
:global(.theme-doc-markdown) > h3:has(+ div[class*="taskContainer"]),
|
|
7
|
+
:global(.theme-doc-markdown) > h4:has(+ div[class*="taskContainer"]),
|
|
8
|
+
:global(.theme-doc-markdown) > h5:has(+ div[class*="taskContainer"]),
|
|
9
|
+
:global(.theme-doc-markdown) > h6:has(+ div[class*="taskContainer"]) {
|
|
10
|
+
/* Visually hide the heading but keep it for TOC and accessibility */
|
|
11
|
+
position: absolute;
|
|
12
|
+
width: 1px;
|
|
13
|
+
height: 1px;
|
|
14
|
+
padding: 0;
|
|
15
|
+
margin: -1px;
|
|
16
|
+
overflow: hidden;
|
|
17
|
+
clip: rect(0, 0, 0, 0);
|
|
18
|
+
white-space: nowrap;
|
|
19
|
+
border: 0;
|
|
20
|
+
}
|
|
21
|
+
|
|
3
22
|
.taskContainer {
|
|
4
23
|
margin-bottom: 1.5rem;
|
|
5
24
|
border: 2px solid var(--ifm-color-emphasis-300);
|
|
6
25
|
border-radius: 8px;
|
|
7
26
|
background-color: var(--ifm-background-surface-color);
|
|
8
|
-
transition: border-color 0.2s ease, box-shadow 0.2s ease
|
|
9
|
-
max-height 0.3s ease-out;
|
|
27
|
+
transition: border-color 0.2s ease, box-shadow 0.2s ease;
|
|
10
28
|
overflow: hidden;
|
|
11
29
|
}
|
|
12
30
|
|
|
@@ -47,35 +65,12 @@
|
|
|
47
65
|
justify-content: space-between;
|
|
48
66
|
gap: 1rem;
|
|
49
67
|
padding: 1rem 1.25rem;
|
|
50
|
-
cursor: pointer;
|
|
51
68
|
user-select: none;
|
|
52
69
|
position: relative;
|
|
53
70
|
background: var(--ifm-background-surface-color);
|
|
54
71
|
transition: background 0.3s ease;
|
|
55
72
|
}
|
|
56
73
|
|
|
57
|
-
.taskHeader::before {
|
|
58
|
-
content: "";
|
|
59
|
-
position: absolute;
|
|
60
|
-
top: 0;
|
|
61
|
-
left: 0;
|
|
62
|
-
right: 0;
|
|
63
|
-
bottom: 0;
|
|
64
|
-
background: linear-gradient(
|
|
65
|
-
to bottom,
|
|
66
|
-
var(--ifm-color-emphasis-200) 0%,
|
|
67
|
-
transparent 80%
|
|
68
|
-
);
|
|
69
|
-
opacity: 0;
|
|
70
|
-
transition: opacity 0.3s ease;
|
|
71
|
-
pointer-events: none;
|
|
72
|
-
z-index: 0;
|
|
73
|
-
}
|
|
74
|
-
|
|
75
|
-
.taskHeader:hover::before {
|
|
76
|
-
opacity: 1;
|
|
77
|
-
}
|
|
78
|
-
|
|
79
74
|
.taskHeaderLeft {
|
|
80
75
|
display: flex;
|
|
81
76
|
align-items: center;
|
|
@@ -100,21 +95,23 @@
|
|
|
100
95
|
flex-shrink: 0;
|
|
101
96
|
}
|
|
102
97
|
|
|
103
|
-
.
|
|
104
|
-
margin: 0;
|
|
105
|
-
font-size: 1.1rem;
|
|
106
|
-
font-weight: 600;
|
|
107
|
-
color: var(--ifm-font-color-base);
|
|
98
|
+
.taskNameWrapper {
|
|
108
99
|
display: flex;
|
|
109
100
|
align-items: center;
|
|
110
101
|
gap: 0.5rem;
|
|
111
102
|
flex: 1;
|
|
112
103
|
min-width: 0;
|
|
113
|
-
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
.taskNameText {
|
|
107
|
+
margin: 0;
|
|
108
|
+
font-size: 1.1rem;
|
|
109
|
+
font-weight: 600;
|
|
110
|
+
color: var(--ifm-font-color-base);
|
|
114
111
|
transition: color 0.6s ease-out;
|
|
115
112
|
}
|
|
116
113
|
|
|
117
|
-
.taskCompleted .
|
|
114
|
+
.taskCompleted .taskNameText {
|
|
118
115
|
color: var(--ifm-color-success);
|
|
119
116
|
}
|
|
120
117
|
|
|
@@ -173,21 +170,30 @@
|
|
|
173
170
|
|
|
174
171
|
.expandButton {
|
|
175
172
|
background: none;
|
|
176
|
-
border:
|
|
173
|
+
border: 1px solid transparent;
|
|
177
174
|
padding: 0.25rem;
|
|
178
175
|
cursor: pointer;
|
|
179
176
|
display: flex;
|
|
180
177
|
align-items: center;
|
|
181
178
|
justify-content: center;
|
|
182
179
|
color: var(--ifm-color-emphasis-700);
|
|
183
|
-
transition: color 0.2s ease;
|
|
180
|
+
transition: color 0.2s ease, background-color 0.2s ease, border-color 0.2s ease;
|
|
184
181
|
flex-shrink: 0;
|
|
185
182
|
position: relative;
|
|
186
183
|
z-index: 1;
|
|
184
|
+
border-radius: 4px;
|
|
187
185
|
}
|
|
188
186
|
|
|
189
187
|
.expandButton:hover {
|
|
190
188
|
color: var(--ifm-color-primary);
|
|
189
|
+
background-color: var(--ifm-color-emphasis-200);
|
|
190
|
+
border-color: var(--ifm-color-emphasis-300);
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
.expandButton:active {
|
|
194
|
+
color: var(--ifm-color-primary);
|
|
195
|
+
background-color: var(--ifm-color-primary-lightest);
|
|
196
|
+
border-color: var(--ifm-color-primary);
|
|
191
197
|
}
|
|
192
198
|
|
|
193
199
|
.chevron {
|
|
@@ -204,42 +210,22 @@
|
|
|
204
210
|
|
|
205
211
|
/* ===================== TASK BODY ===================== */
|
|
206
212
|
|
|
207
|
-
.
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
213
|
+
.taskContentWrapper {
|
|
214
|
+
display: grid;
|
|
215
|
+
grid-template-rows: 0fr;
|
|
216
|
+
transition: grid-template-rows 0.3s ease-out;
|
|
211
217
|
}
|
|
212
218
|
|
|
213
|
-
.
|
|
214
|
-
|
|
219
|
+
.taskContentExpanded {
|
|
220
|
+
grid-template-rows: 1fr;
|
|
215
221
|
}
|
|
216
222
|
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
opacity: 0;
|
|
220
|
-
max-height: 0;
|
|
221
|
-
transform: translateY(-8px);
|
|
222
|
-
}
|
|
223
|
-
|
|
224
|
-
to {
|
|
225
|
-
opacity: 1;
|
|
226
|
-
max-height: 2000px;
|
|
227
|
-
transform: translateY(0);
|
|
228
|
-
}
|
|
223
|
+
.taskContentInner {
|
|
224
|
+
overflow: hidden;
|
|
229
225
|
}
|
|
230
226
|
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
opacity: 1;
|
|
234
|
-
max-height: 2000px;
|
|
235
|
-
transform: translateY(0);
|
|
236
|
-
}
|
|
237
|
-
|
|
238
|
-
to {
|
|
239
|
-
opacity: 0;
|
|
240
|
-
max-height: 0;
|
|
241
|
-
transform: translateY(-8px);
|
|
242
|
-
}
|
|
227
|
+
.taskBody {
|
|
228
|
+
padding: 0 1.25rem 1rem 1.25rem;
|
|
243
229
|
}
|
|
244
230
|
|
|
245
231
|
/* ===================== TASK FOOTER ===================== */
|
|
@@ -252,12 +238,6 @@
|
|
|
252
238
|
gap: 0.75rem;
|
|
253
239
|
flex-wrap: wrap;
|
|
254
240
|
position: relative;
|
|
255
|
-
animation: slideDown 0.3s ease-out;
|
|
256
|
-
overflow: hidden;
|
|
257
|
-
}
|
|
258
|
-
|
|
259
|
-
.taskFooterCollapsing {
|
|
260
|
-
animation: slideUp 0.3s ease-out;
|
|
261
241
|
}
|
|
262
242
|
|
|
263
243
|
.taskFooter::before {
|
|
@@ -356,136 +336,84 @@
|
|
|
356
336
|
/* ===================== PANELS (Hint/Solution) ===================== */
|
|
357
337
|
|
|
358
338
|
.panelWrapper {
|
|
359
|
-
|
|
360
|
-
margin: 0 1.25rem 0rem 1.25rem;
|
|
339
|
+
margin: 0 1.25rem;
|
|
361
340
|
}
|
|
362
341
|
|
|
363
|
-
.
|
|
364
|
-
/* Invisible spacer that maintains layout space */
|
|
365
|
-
width: 100%;
|
|
342
|
+
.panelGridWrapper {
|
|
366
343
|
overflow: hidden;
|
|
344
|
+
height: 0;
|
|
345
|
+
transition: height 0.3s ease-out;
|
|
346
|
+
}
|
|
347
|
+
|
|
348
|
+
/* Collapsing state - animates back to 0 while content fades out */
|
|
349
|
+
.panelGridCollapsing {
|
|
350
|
+
height: 0 !important;
|
|
351
|
+
}
|
|
352
|
+
|
|
353
|
+
/* Shared container for both panels - they overlap using positioning */
|
|
354
|
+
.panelSharedContainer {
|
|
355
|
+
position: relative;
|
|
367
356
|
}
|
|
368
357
|
|
|
369
358
|
.panelContainer {
|
|
370
359
|
border-radius: 6px;
|
|
371
360
|
overflow: hidden;
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
.
|
|
361
|
+
opacity: 0;
|
|
362
|
+
visibility: hidden;
|
|
363
|
+
pointer-events: none;
|
|
364
|
+
transition: opacity 0.3s ease-out, visibility 0.3s ease-out;
|
|
365
|
+
/* Hidden panels use absolute positioning to not affect layout */
|
|
376
366
|
position: absolute;
|
|
377
367
|
top: 0;
|
|
378
368
|
left: 0;
|
|
379
369
|
right: 0;
|
|
380
|
-
opacity: 0;
|
|
381
|
-
pointer-events: none;
|
|
382
|
-
visibility: hidden;
|
|
383
|
-
transform: translateX(0);
|
|
384
370
|
}
|
|
385
371
|
|
|
386
372
|
.panelVisible {
|
|
387
|
-
|
|
388
|
-
pointer-events: auto;
|
|
373
|
+
opacity: 1;
|
|
389
374
|
visibility: visible;
|
|
375
|
+
pointer-events: auto;
|
|
376
|
+
/* Visible panel stays in document flow */
|
|
377
|
+
position: relative;
|
|
390
378
|
}
|
|
391
379
|
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
.hintPanelContainerExpandingSwitching {
|
|
401
|
-
animation: expandLeftToRight 0.3s ease-out forwards;
|
|
402
|
-
}
|
|
403
|
-
|
|
404
|
-
.hintPanelContainerCollapsingSwitching {
|
|
405
|
-
animation: collapseRightToLeft 0.3s ease-out forwards;
|
|
406
|
-
}
|
|
407
|
-
|
|
408
|
-
.solutionPanelContainerExpandingSwitching {
|
|
409
|
-
animation: expandRightToLeft 0.3s ease-out forwards;
|
|
410
|
-
}
|
|
411
|
-
|
|
412
|
-
.solutionPanelContainerCollapsingSwitching {
|
|
413
|
-
animation: collapseLeftToRight 0.3s ease-out forwards;
|
|
414
|
-
}
|
|
415
|
-
|
|
416
|
-
@keyframes expandPanel {
|
|
417
|
-
from {
|
|
418
|
-
opacity: 0;
|
|
419
|
-
transform: translateY(-8px);
|
|
420
|
-
}
|
|
421
|
-
|
|
422
|
-
to {
|
|
423
|
-
opacity: 1;
|
|
424
|
-
transform: translateY(0);
|
|
425
|
-
}
|
|
426
|
-
}
|
|
427
|
-
|
|
428
|
-
@keyframes collapsePanel {
|
|
429
|
-
from {
|
|
430
|
-
opacity: 1;
|
|
431
|
-
transform: translateY(0);
|
|
432
|
-
}
|
|
433
|
-
|
|
434
|
-
to {
|
|
435
|
-
opacity: 0;
|
|
436
|
-
transform: translateY(-8px);
|
|
437
|
-
}
|
|
380
|
+
/* When switching panels, both use absolute positioning and crossfade */
|
|
381
|
+
.panelSwitching {
|
|
382
|
+
visibility: visible;
|
|
383
|
+
position: absolute;
|
|
384
|
+
top: 0;
|
|
385
|
+
left: 0;
|
|
386
|
+
right: 0;
|
|
438
387
|
}
|
|
439
388
|
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
}
|
|
446
|
-
|
|
447
|
-
to {
|
|
448
|
-
opacity: 1;
|
|
449
|
-
transform: translateX(0);
|
|
450
|
-
}
|
|
389
|
+
/* Sequential fade animations for panel switching */
|
|
390
|
+
.panelFadingIn {
|
|
391
|
+
animation: fadeIn 0.30s ease-out 0.30s forwards;
|
|
392
|
+
/* Start invisible and let animation handle the fade */
|
|
393
|
+
opacity: 0 !important;
|
|
451
394
|
}
|
|
452
395
|
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
transform: translateX(0);
|
|
458
|
-
}
|
|
459
|
-
|
|
460
|
-
to {
|
|
461
|
-
opacity: 0;
|
|
462
|
-
transform: translateX(-30px);
|
|
463
|
-
}
|
|
396
|
+
.panelFadingOut {
|
|
397
|
+
animation: fadeOut 0.30s ease-out forwards;
|
|
398
|
+
/* Start visible and animate to invisible */
|
|
399
|
+
opacity: 1 !important;
|
|
464
400
|
}
|
|
465
401
|
|
|
466
|
-
@keyframes
|
|
467
|
-
/* Appears from the LEFT, slides to center (used when showing solution from hint) */
|
|
402
|
+
@keyframes fadeIn {
|
|
468
403
|
from {
|
|
469
404
|
opacity: 0;
|
|
470
|
-
transform: translateX(-30px);
|
|
471
405
|
}
|
|
472
|
-
|
|
473
406
|
to {
|
|
474
407
|
opacity: 1;
|
|
475
|
-
transform: translateX(0);
|
|
476
408
|
}
|
|
477
409
|
}
|
|
478
410
|
|
|
479
|
-
@keyframes
|
|
480
|
-
/* Disappears to the RIGHT (used when hiding solution to show hint) */
|
|
411
|
+
@keyframes fadeOut {
|
|
481
412
|
from {
|
|
482
413
|
opacity: 1;
|
|
483
|
-
transform: translateX(0);
|
|
484
414
|
}
|
|
485
|
-
|
|
486
415
|
to {
|
|
487
416
|
opacity: 0;
|
|
488
|
-
transform: translateX(30px);
|
|
489
417
|
}
|
|
490
418
|
}
|
|
491
419
|
|
|
@@ -11,6 +11,7 @@ import { type ReactNode, type ReactElement } from 'react';
|
|
|
11
11
|
export interface TaskExampleProps {
|
|
12
12
|
name: string;
|
|
13
13
|
children?: ReactNode;
|
|
14
|
+
id?: string;
|
|
14
15
|
}
|
|
15
|
-
export default function TaskExample({ name, children }: TaskExampleProps): ReactElement;
|
|
16
|
+
export default function TaskExample({ name, children, id }: TaskExampleProps): ReactElement;
|
|
16
17
|
//# sourceMappingURL=index.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/theme/TaskExample/index.tsx"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAc,EAAE,KAAK,SAAS,EAAY,KAAK,YAAY,EAAqB,MAAM,OAAO,CAAC;AAM9F,MAAM,WAAW,gBAAgB;IAC/B,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,CAAC,EAAE,SAAS,CAAC;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/theme/TaskExample/index.tsx"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAc,EAAE,KAAK,SAAS,EAAY,KAAK,YAAY,EAAqB,MAAM,OAAO,CAAC;AAM9F,MAAM,WAAW,gBAAgB;IAC/B,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,CAAC,EAAE,SAAS,CAAC;IACrB,EAAE,CAAC,EAAE,MAAM,CAAC;CACb;AAED,MAAM,CAAC,OAAO,UAAU,WAAW,CAAC,EAAE,IAAI,EAAE,QAAQ,EAAE,EAAE,EAAE,EAAE,gBAAgB,GAAG,YAAY,CAoS1F"}
|
|
@@ -51,7 +51,7 @@ const clsx_1 = __importDefault(require("clsx"));
|
|
|
51
51
|
const DocTaskCounterProvider_1 = require("../DocTaskCounterProvider");
|
|
52
52
|
const icons_1 = require("../../utils/icons");
|
|
53
53
|
const styles_module_css_1 = __importDefault(require("../Task/styles.module.css")); // Reuse Task styles
|
|
54
|
-
function TaskExample({ name, children }) {
|
|
54
|
+
function TaskExample({ name, children, id }) {
|
|
55
55
|
// Get auto-incremented example number
|
|
56
56
|
const exampleNumber = (0, DocTaskCounterProvider_1.useTaskExampleNumber)();
|
|
57
57
|
// Local state only (no persistence)
|
|
@@ -61,16 +61,28 @@ function TaskExample({ name, children }) {
|
|
|
61
61
|
const [showSolution, setShowSolution] = (0, react_1.useState)(false);
|
|
62
62
|
const [isAnimatingCompletion, setIsAnimatingCompletion] = (0, react_1.useState)(false);
|
|
63
63
|
const [isRemovingCheckmark, setIsRemovingCheckmark] = (0, react_1.useState)(false);
|
|
64
|
-
const [isCollapsingHint, setIsCollapsingHint] = (0, react_1.useState)(false);
|
|
65
|
-
const [isCollapsingSolution, setIsCollapsingSolution] = (0, react_1.useState)(false);
|
|
66
64
|
const [isSwitchingPanels, setIsSwitchingPanels] = (0, react_1.useState)(false);
|
|
67
|
-
const [
|
|
68
|
-
const [
|
|
69
|
-
|
|
65
|
+
const [isClosingHint, setIsClosingHint] = (0, react_1.useState)(false);
|
|
66
|
+
const [isClosingSolution, setIsClosingSolution] = (0, react_1.useState)(false);
|
|
67
|
+
const [containerHeight, setContainerHeight] = (0, react_1.useState)(null);
|
|
68
|
+
// Refs for switching animations
|
|
70
69
|
const hintRef = (0, react_1.useRef)(null);
|
|
71
70
|
const solutionRef = (0, react_1.useRef)(null);
|
|
72
71
|
// Track previous completion state
|
|
73
72
|
const prevIsCompleted = (0, react_1.useRef)(isCompleted);
|
|
73
|
+
// Measure panel heights and update container height for smooth transitions
|
|
74
|
+
(0, react_1.useEffect)(() => {
|
|
75
|
+
if (showHint || showSolution || isSwitchingPanels) {
|
|
76
|
+
const activeRef = showHint ? hintRef : solutionRef;
|
|
77
|
+
if (activeRef.current) {
|
|
78
|
+
const height = activeRef.current.scrollHeight;
|
|
79
|
+
setContainerHeight(height + 16); // Add small buffer for padding/margin
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
else {
|
|
83
|
+
setContainerHeight(null);
|
|
84
|
+
}
|
|
85
|
+
}, [showHint, showSolution, isSwitchingPanels]);
|
|
74
86
|
// Detect when completion state changes
|
|
75
87
|
(0, react_1.useEffect)(() => {
|
|
76
88
|
if (prevIsCompleted.current !== isCompleted) {
|
|
@@ -89,38 +101,14 @@ function TaskExample({ name, children }) {
|
|
|
89
101
|
prevIsCompleted.current = isCompleted;
|
|
90
102
|
}
|
|
91
103
|
}, [isCompleted]);
|
|
92
|
-
// Measure panel heights and update spacer
|
|
93
|
-
(0, react_1.useEffect)(() => {
|
|
94
|
-
const updateSpacerHeight = () => {
|
|
95
|
-
if (showHint && hintRef.current) {
|
|
96
|
-
setPanelSpacerHeight(hintRef.current.offsetHeight);
|
|
97
|
-
}
|
|
98
|
-
else if (showSolution && solutionRef.current) {
|
|
99
|
-
setPanelSpacerHeight(solutionRef.current.offsetHeight);
|
|
100
|
-
}
|
|
101
|
-
else {
|
|
102
|
-
setPanelSpacerHeight(0);
|
|
103
|
-
}
|
|
104
|
-
};
|
|
105
|
-
// Update immediately
|
|
106
|
-
updateSpacerHeight();
|
|
107
|
-
// Also update on window resize (for responsive content)
|
|
108
|
-
window.addEventListener('resize', updateSpacerHeight);
|
|
109
|
-
return () => window.removeEventListener('resize', updateSpacerHeight);
|
|
110
|
-
}, [showHint, showSolution]);
|
|
111
104
|
const toggleExpanded = () => {
|
|
112
|
-
// When collapsing, start animation then remove from DOM
|
|
113
105
|
if (isExpanded) {
|
|
114
|
-
|
|
106
|
+
// Close panels when collapsing
|
|
115
107
|
setShowHint(false);
|
|
116
108
|
setShowSolution(false);
|
|
117
|
-
|
|
118
|
-
setIsExpanded(false);
|
|
119
|
-
setIsCollapsingBody(false);
|
|
120
|
-
}, 300); // Match animation duration
|
|
109
|
+
setIsExpanded(false);
|
|
121
110
|
}
|
|
122
111
|
else {
|
|
123
|
-
// When expanding, add to DOM immediately
|
|
124
112
|
setIsExpanded(true);
|
|
125
113
|
}
|
|
126
114
|
};
|
|
@@ -130,62 +118,54 @@ function TaskExample({ name, children }) {
|
|
|
130
118
|
};
|
|
131
119
|
const toggleHint = () => {
|
|
132
120
|
if (showHint) {
|
|
133
|
-
// Closing hint
|
|
134
|
-
|
|
135
|
-
|
|
121
|
+
// Closing hint - fade out while grid collapses
|
|
122
|
+
setIsClosingHint(true);
|
|
123
|
+
setShowHint(false);
|
|
124
|
+
// Remove from DOM after animation completes
|
|
136
125
|
setTimeout(() => {
|
|
137
|
-
|
|
138
|
-
setIsCollapsingHint(false);
|
|
126
|
+
setIsClosingHint(false);
|
|
139
127
|
}, 300);
|
|
140
128
|
}
|
|
141
129
|
else {
|
|
142
130
|
// Opening hint
|
|
143
131
|
if (showSolution) {
|
|
144
|
-
// Switching from solution to hint
|
|
132
|
+
// Switching from solution to hint - sequential fade
|
|
145
133
|
setIsSwitchingPanels(true);
|
|
146
|
-
|
|
134
|
+
setShowHint(true);
|
|
135
|
+
// Wait for sequential fade animation before hiding solution
|
|
147
136
|
setTimeout(() => {
|
|
148
137
|
setShowSolution(false);
|
|
149
|
-
|
|
150
|
-
// Delay before showing hint panel
|
|
151
|
-
setTimeout(() => {
|
|
152
|
-
setShowHint(true);
|
|
153
|
-
}, 25);
|
|
138
|
+
setIsSwitchingPanels(false);
|
|
154
139
|
}, 300);
|
|
155
140
|
}
|
|
156
141
|
else {
|
|
157
|
-
setIsSwitchingPanels(false);
|
|
158
142
|
setShowHint(true);
|
|
159
143
|
}
|
|
160
144
|
}
|
|
161
145
|
};
|
|
162
146
|
const toggleSolution = () => {
|
|
163
147
|
if (showSolution) {
|
|
164
|
-
// Closing solution
|
|
165
|
-
|
|
166
|
-
|
|
148
|
+
// Closing solution - fade out while grid collapses
|
|
149
|
+
setIsClosingSolution(true);
|
|
150
|
+
setShowSolution(false);
|
|
151
|
+
// Remove from DOM after animation completes
|
|
167
152
|
setTimeout(() => {
|
|
168
|
-
|
|
169
|
-
setIsCollapsingSolution(false);
|
|
153
|
+
setIsClosingSolution(false);
|
|
170
154
|
}, 300);
|
|
171
155
|
}
|
|
172
156
|
else {
|
|
173
157
|
// Opening solution
|
|
174
158
|
if (showHint) {
|
|
175
|
-
// Switching from hint to solution
|
|
159
|
+
// Switching from hint to solution - sequential fade
|
|
176
160
|
setIsSwitchingPanels(true);
|
|
177
|
-
|
|
161
|
+
setShowSolution(true);
|
|
162
|
+
// Wait for sequential fade animation before hiding hint
|
|
178
163
|
setTimeout(() => {
|
|
179
164
|
setShowHint(false);
|
|
180
|
-
|
|
181
|
-
// Delay before showing solution panel
|
|
182
|
-
setTimeout(() => {
|
|
183
|
-
setShowSolution(true);
|
|
184
|
-
}, 25);
|
|
165
|
+
setIsSwitchingPanels(false);
|
|
185
166
|
}, 300);
|
|
186
167
|
}
|
|
187
168
|
else {
|
|
188
|
-
setIsSwitchingPanels(false);
|
|
189
169
|
setShowSolution(true);
|
|
190
170
|
}
|
|
191
171
|
}
|
|
@@ -210,40 +190,39 @@ function TaskExample({ name, children }) {
|
|
|
210
190
|
});
|
|
211
191
|
// Build task identifier badge
|
|
212
192
|
const taskBadge = `Example ${exampleNumber}`;
|
|
213
|
-
return (react_1.default.createElement("div", { className: (0, clsx_1.default)(styles_module_css_1.default.taskContainer, isCompleted && styles_module_css_1.default.taskCompleted, isAnimatingCompletion && styles_module_css_1.default.taskCompletedAnimating) },
|
|
214
|
-
react_1.default.createElement("div", { className: styles_module_css_1.default.taskHeader
|
|
193
|
+
return (react_1.default.createElement("div", { id: id, className: (0, clsx_1.default)(styles_module_css_1.default.taskContainer, isCompleted && styles_module_css_1.default.taskCompleted, isAnimatingCompletion && styles_module_css_1.default.taskCompletedAnimating) },
|
|
194
|
+
react_1.default.createElement("div", { className: styles_module_css_1.default.taskHeader },
|
|
215
195
|
react_1.default.createElement("div", { className: styles_module_css_1.default.taskHeaderLeft },
|
|
216
196
|
react_1.default.createElement("span", { className: styles_module_css_1.default.taskBadge }, taskBadge),
|
|
217
|
-
react_1.default.createElement("
|
|
218
|
-
name,
|
|
197
|
+
react_1.default.createElement("div", { className: styles_module_css_1.default.taskNameWrapper },
|
|
198
|
+
react_1.default.createElement("span", { className: styles_module_css_1.default.taskNameText }, name),
|
|
219
199
|
react_1.default.createElement("span", { className: (0, clsx_1.default)(styles_module_css_1.default.checkmark, isCompleted && !isAnimatingCompletion && !isRemovingCheckmark && styles_module_css_1.default.checkmarkVisible, isAnimatingCompletion && styles_module_css_1.default.checkmarkAnimating, isRemovingCheckmark && styles_module_css_1.default.checkmarkRemoving) }, icons_1.CHECKMARK_CIRCLE_FILL_ICON))),
|
|
220
|
-
react_1.default.createElement("button", { type: "button", className: styles_module_css_1.default.expandButton, "aria-expanded": isExpanded, "aria-label": isExpanded ? 'Collapse task' : 'Expand task' },
|
|
200
|
+
react_1.default.createElement("button", { type: "button", className: styles_module_css_1.default.expandButton, onClick: toggleExpanded, "aria-expanded": isExpanded, "aria-label": isExpanded ? 'Collapse task' : 'Expand task' },
|
|
221
201
|
react_1.default.createElement("span", { className: (0, clsx_1.default)(styles_module_css_1.default.chevron, !isExpanded && styles_module_css_1.default.chevronCollapsed) }, icons_1.CHEVRON_DOWN_ICON))),
|
|
222
|
-
(
|
|
223
|
-
react_1.default.createElement("div", { className:
|
|
224
|
-
|
|
225
|
-
react_1.default.createElement("div", { className: styles_module_css_1.default.
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
202
|
+
react_1.default.createElement("div", { className: (0, clsx_1.default)(styles_module_css_1.default.taskContentWrapper, isExpanded && styles_module_css_1.default.taskContentExpanded) },
|
|
203
|
+
react_1.default.createElement("div", { className: styles_module_css_1.default.taskContentInner },
|
|
204
|
+
react_1.default.createElement("div", { className: styles_module_css_1.default.taskBody }, textComponent),
|
|
205
|
+
react_1.default.createElement("div", { className: styles_module_css_1.default.taskFooter },
|
|
206
|
+
react_1.default.createElement("div", { className: styles_module_css_1.default.taskActions },
|
|
207
|
+
hintComponent && (react_1.default.createElement("button", { type: "button", className: (0, clsx_1.default)(styles_module_css_1.default.taskButton, styles_module_css_1.default.hintButton, showHint && styles_module_css_1.default.active), onClick: (e) => {
|
|
208
|
+
e.stopPropagation();
|
|
209
|
+
toggleHint();
|
|
210
|
+
} }, "Hint")),
|
|
211
|
+
solutionComponent && (react_1.default.createElement("button", { type: "button", className: (0, clsx_1.default)(styles_module_css_1.default.taskButton, styles_module_css_1.default.solutionButton, showSolution && styles_module_css_1.default.active), onClick: (e) => {
|
|
212
|
+
e.stopPropagation();
|
|
213
|
+
toggleSolution();
|
|
214
|
+
} }, "Solution"))),
|
|
215
|
+
react_1.default.createElement("button", { type: "button", className: (0, clsx_1.default)(styles_module_css_1.default.taskButton, styles_module_css_1.default.completeButton, isCompleted && styles_module_css_1.default.completedButton), onClick: (e) => {
|
|
231
216
|
e.stopPropagation();
|
|
232
|
-
|
|
233
|
-
} },
|
|
234
|
-
react_1.default.createElement("
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
react_1.default.createElement("div", { className: styles_module_css_1.default.panelSpacer, style: {
|
|
243
|
-
height: panelSpacerHeight > 0 ? `${panelSpacerHeight}px` : 0,
|
|
244
|
-
transition: 'height 0.3s ease-out'
|
|
245
|
-
} }),
|
|
246
|
-
hintComponent && (react_1.default.createElement("div", { ref: hintRef, className: (0, clsx_1.default)(styles_module_css_1.default.panelContainer, styles_module_css_1.default.panelAbsolute, (showHint || isCollapsingHint) && styles_module_css_1.default.panelVisible, showHint && !isCollapsingHint && !isSwitchingPanels && styles_module_css_1.default.panelContainerExpanding, showHint && !isCollapsingHint && isSwitchingPanels && styles_module_css_1.default.hintPanelContainerExpandingSwitching, isCollapsingHint && !isSwitchingPanels && styles_module_css_1.default.panelContainerCollapsing, isCollapsingHint && isSwitchingPanels && styles_module_css_1.default.hintPanelContainerCollapsingSwitching) }, hintComponent)),
|
|
247
|
-
solutionComponent && (react_1.default.createElement("div", { ref: solutionRef, className: (0, clsx_1.default)(styles_module_css_1.default.panelContainer, styles_module_css_1.default.panelAbsolute, (showSolution || isCollapsingSolution) && styles_module_css_1.default.panelVisible, showSolution && !isCollapsingSolution && !isSwitchingPanels && styles_module_css_1.default.panelContainerExpanding, showSolution && !isCollapsingSolution && isSwitchingPanels && styles_module_css_1.default.solutionPanelContainerExpandingSwitching, isCollapsingSolution && !isSwitchingPanels && styles_module_css_1.default.panelContainerCollapsing, isCollapsingSolution && isSwitchingPanels && styles_module_css_1.default.solutionPanelContainerCollapsingSwitching) }, solutionComponent))))))));
|
|
217
|
+
toggleCompleted();
|
|
218
|
+
} }, isCompleted ? 'Undo Task' : 'Mark as Done')),
|
|
219
|
+
(hintComponent || solutionComponent) && (react_1.default.createElement("div", { className: styles_module_css_1.default.panelWrapper },
|
|
220
|
+
react_1.default.createElement("div", { className: (0, clsx_1.default)(styles_module_css_1.default.panelGridWrapper, (showHint || showSolution || isSwitchingPanels) && styles_module_css_1.default.panelGridExpanded, (isClosingHint || isClosingSolution) && !isSwitchingPanels && styles_module_css_1.default.panelGridCollapsing), style: {
|
|
221
|
+
height: containerHeight !== null ? `${containerHeight}px` : undefined
|
|
222
|
+
} },
|
|
223
|
+
react_1.default.createElement("div", { className: styles_module_css_1.default.panelGridInner },
|
|
224
|
+
react_1.default.createElement("div", { className: styles_module_css_1.default.panelSharedContainer },
|
|
225
|
+
hintComponent && (react_1.default.createElement("div", { ref: hintRef, className: (0, clsx_1.default)(styles_module_css_1.default.panelContainer, showHint && !isSwitchingPanels && styles_module_css_1.default.panelVisible, showHint && isSwitchingPanels && styles_module_css_1.default.panelFadingIn, !showHint && isSwitchingPanels && styles_module_css_1.default.panelFadingOut, isClosingHint && styles_module_css_1.default.panelFadingOut, isSwitchingPanels && styles_module_css_1.default.panelSwitching) }, hintComponent)),
|
|
226
|
+
solutionComponent && (react_1.default.createElement("div", { ref: solutionRef, className: (0, clsx_1.default)(styles_module_css_1.default.panelContainer, showSolution && !isSwitchingPanels && styles_module_css_1.default.panelVisible, showSolution && isSwitchingPanels && styles_module_css_1.default.panelFadingIn, !showSolution && isSwitchingPanels && styles_module_css_1.default.panelFadingOut, isClosingSolution && styles_module_css_1.default.panelFadingOut, isSwitchingPanels && styles_module_css_1.default.panelSwitching) }, solutionComponent)))))))))));
|
|
248
227
|
}
|
|
249
228
|
//# sourceMappingURL=index.js.map
|