learningfoundry 0.52.0__tar.gz → 0.55.0__tar.gz

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.
Files changed (151) hide show
  1. {learningfoundry-0.52.0 → learningfoundry-0.55.0}/CHANGELOG.md +34 -0
  2. {learningfoundry-0.52.0 → learningfoundry-0.55.0}/PKG-INFO +1 -1
  3. {learningfoundry-0.52.0 → learningfoundry-0.55.0}/pyproject.toml +1 -1
  4. {learningfoundry-0.52.0 → learningfoundry-0.55.0}/src/learningfoundry/__init__.py +1 -1
  5. {learningfoundry-0.52.0 → learningfoundry-0.55.0}/src/learningfoundry/sveltekit_template/pnpm-lock.yaml +231 -0
  6. learningfoundry-0.55.0/src/learningfoundry/sveltekit_template/src/lib/components/LessonList.test.ts +154 -0
  7. learningfoundry-0.55.0/src/learningfoundry/sveltekit_template/src/lib/components/LessonView.test.ts +539 -0
  8. learningfoundry-0.55.0/src/learningfoundry/sveltekit_template/src/lib/components/ModuleList.test.ts +144 -0
  9. {learningfoundry-0.52.0 → learningfoundry-0.55.0}/src/learningfoundry/sveltekit_template/src/lib/components/ProgressDashboard.svelte +5 -9
  10. learningfoundry-0.55.0/src/learningfoundry/sveltekit_template/src/lib/components/ProgressDashboard.test.ts +315 -0
  11. learningfoundry-0.55.0/src/learningfoundry/sveltekit_template/src/lib/components/ResetCourseButton.test.ts +164 -0
  12. learningfoundry-0.55.0/src/learningfoundry/sveltekit_template/src/lib/components/TextBlock.observer.test.ts +184 -0
  13. learningfoundry-0.55.0/src/learningfoundry/sveltekit_template/src/lib/components/VideoBlock.test.ts +277 -0
  14. learningfoundry-0.55.0/src/learningfoundry/sveltekit_template/src/lib/components/navigation.test.ts +184 -0
  15. learningfoundry-0.55.0/src/learningfoundry/sveltekit_template/src/lib/components/progress-dashboard.helpers.ts +71 -0
  16. learningfoundry-0.55.0/src/learningfoundry/sveltekit_template/test-results/.last-run.json +7 -0
  17. learningfoundry-0.55.0/src/learningfoundry/sveltekit_template/test-results/navigation-lesson-navigati-c531e-le-deep-links-into-a-lesson-chromium/error-context.md +75 -0
  18. learningfoundry-0.55.0/src/learningfoundry/sveltekit_template/test-results/navigation-lesson-navigati-c531e-le-deep-links-into-a-lesson-chromium/trace.zip +0 -0
  19. learningfoundry-0.55.0/src/learningfoundry/sveltekit_template/test-results/navigation-lesson-navigati-dc2f3-ar-lesson-click-updates-URL-chromium/error-context.md +75 -0
  20. learningfoundry-0.55.0/src/learningfoundry/sveltekit_template/test-results/navigation-lesson-navigati-dc2f3-ar-lesson-click-updates-URL-chromium/trace.zip +0 -0
  21. {learningfoundry-0.52.0 → learningfoundry-0.55.0}/src/learningfoundry/sveltekit_template/vite.config.ts +8 -1
  22. learningfoundry-0.52.0/src/learningfoundry/sveltekit_template/src/lib/components/LessonView.test.ts +0 -227
  23. learningfoundry-0.52.0/src/learningfoundry/sveltekit_template/src/lib/components/ProgressDashboard.test.ts +0 -118
  24. learningfoundry-0.52.0/src/learningfoundry/sveltekit_template/src/lib/components/ResetCourseButton.test.ts +0 -95
  25. learningfoundry-0.52.0/src/learningfoundry/sveltekit_template/src/lib/components/TextBlock.observer.test.ts +0 -93
  26. learningfoundry-0.52.0/src/learningfoundry/sveltekit_template/src/lib/components/VideoBlock.test.ts +0 -96
  27. learningfoundry-0.52.0/src/learningfoundry/sveltekit_template/src/lib/components/navigation.test.ts +0 -52
  28. learningfoundry-0.52.0/src/learningfoundry/sveltekit_template/src/lib/components/progress-dashboard.helpers.ts +0 -39
  29. learningfoundry-0.52.0/sveltekit_template/e2e/README.md +0 -47
  30. learningfoundry-0.52.0/sveltekit_template/src/app.css +0 -3
  31. learningfoundry-0.52.0/sveltekit_template/src/app.html +0 -12
  32. learningfoundry-0.52.0/sveltekit_template/src/lib/components/ContentBlock.svelte +0 -53
  33. learningfoundry-0.52.0/sveltekit_template/src/lib/components/ExerciseBlock.svelte +0 -35
  34. learningfoundry-0.52.0/sveltekit_template/src/lib/components/LessonList.svelte +0 -69
  35. learningfoundry-0.52.0/sveltekit_template/src/lib/components/LessonView.svelte +0 -145
  36. learningfoundry-0.52.0/sveltekit_template/src/lib/components/LessonView.test.ts +0 -227
  37. learningfoundry-0.52.0/sveltekit_template/src/lib/components/ModuleList.svelte +0 -106
  38. learningfoundry-0.52.0/sveltekit_template/src/lib/components/Navigation.svelte +0 -56
  39. learningfoundry-0.52.0/sveltekit_template/src/lib/components/PlaceholderBlock.svelte +0 -13
  40. learningfoundry-0.52.0/sveltekit_template/src/lib/components/ProgressBar.svelte +0 -29
  41. learningfoundry-0.52.0/sveltekit_template/src/lib/components/ProgressDashboard.svelte +0 -113
  42. learningfoundry-0.52.0/sveltekit_template/src/lib/components/QuizBlock.svelte +0 -60
  43. learningfoundry-0.52.0/sveltekit_template/src/lib/components/ResetCourseButton.svelte +0 -46
  44. learningfoundry-0.52.0/sveltekit_template/src/lib/components/ResetCourseButton.test.ts +0 -95
  45. learningfoundry-0.52.0/sveltekit_template/src/lib/components/TextBlock.observer.test.ts +0 -93
  46. learningfoundry-0.52.0/sveltekit_template/src/lib/components/TextBlock.svelte +0 -61
  47. learningfoundry-0.52.0/sveltekit_template/src/lib/components/TextBlock.test.ts +0 -127
  48. learningfoundry-0.52.0/sveltekit_template/src/lib/components/VideoBlock.svelte +0 -136
  49. learningfoundry-0.52.0/sveltekit_template/src/lib/components/VisualizationBlock.svelte +0 -42
  50. learningfoundry-0.52.0/sveltekit_template/src/lib/components/lesson-view.helpers.ts +0 -63
  51. learningfoundry-0.52.0/sveltekit_template/src/lib/components/module-list.helpers.ts +0 -124
  52. learningfoundry-0.52.0/sveltekit_template/src/lib/components/module-list.test.ts +0 -109
  53. learningfoundry-0.52.0/sveltekit_template/src/lib/components/mount.test.ts +0 -26
  54. learningfoundry-0.52.0/sveltekit_template/src/lib/components/navigation.helpers.ts +0 -43
  55. learningfoundry-0.52.0/sveltekit_template/src/lib/components/navigation.test.ts +0 -52
  56. learningfoundry-0.52.0/sveltekit_template/src/lib/components/progress-dashboard.helpers.ts +0 -39
  57. learningfoundry-0.52.0/sveltekit_template/src/lib/db/database.ts +0 -118
  58. learningfoundry-0.52.0/sveltekit_template/src/lib/db/index.ts +0 -14
  59. learningfoundry-0.52.0/sveltekit_template/src/lib/db/progress.test.ts +0 -107
  60. learningfoundry-0.52.0/sveltekit_template/src/lib/db/progress.ts +0 -212
  61. learningfoundry-0.52.0/sveltekit_template/src/lib/stores/curriculum.ts +0 -138
  62. learningfoundry-0.52.0/sveltekit_template/src/lib/stores/progress.ts +0 -28
  63. learningfoundry-0.52.0/sveltekit_template/src/lib/types/index.ts +0 -161
  64. learningfoundry-0.52.0/sveltekit_template/src/lib/utils/locking.ts +0 -151
  65. learningfoundry-0.52.0/sveltekit_template/src/lib/utils/markdown.ts +0 -13
  66. learningfoundry-0.52.0/sveltekit_template/src/lib/utils/progress.test.ts +0 -81
  67. learningfoundry-0.52.0/sveltekit_template/src/lib/utils/progress.ts +0 -26
  68. learningfoundry-0.52.0/sveltekit_template/src/lib/utils/viewport-completion.ts +0 -64
  69. learningfoundry-0.52.0/sveltekit_template/src/routes/+layout.svelte +0 -50
  70. learningfoundry-0.52.0/sveltekit_template/src/routes/+page.svelte +0 -24
  71. learningfoundry-0.52.0/sveltekit_template/src/routes/[module]/[lesson]/+page.svelte +0 -45
  72. learningfoundry-0.52.0/sveltekit_template/src/routes/layout.test.ts +0 -102
  73. {learningfoundry-0.52.0 → learningfoundry-0.55.0}/.gitignore +0 -0
  74. {learningfoundry-0.52.0 → learningfoundry-0.55.0}/LICENSE +0 -0
  75. {learningfoundry-0.52.0 → learningfoundry-0.55.0}/README.md +0 -0
  76. {learningfoundry-0.52.0 → learningfoundry-0.55.0}/docs/project-guide/README.md +0 -0
  77. {learningfoundry-0.52.0 → learningfoundry-0.55.0}/src/learningfoundry/__main__.py +0 -0
  78. {learningfoundry-0.52.0 → learningfoundry-0.55.0}/src/learningfoundry/asset_resolver.py +0 -0
  79. {learningfoundry-0.52.0 → learningfoundry-0.55.0}/src/learningfoundry/cli.py +0 -0
  80. {learningfoundry-0.52.0 → learningfoundry-0.55.0}/src/learningfoundry/config.py +0 -0
  81. {learningfoundry-0.52.0 → learningfoundry-0.55.0}/src/learningfoundry/exceptions.py +0 -0
  82. {learningfoundry-0.52.0 → learningfoundry-0.55.0}/src/learningfoundry/generator.py +0 -0
  83. {learningfoundry-0.52.0 → learningfoundry-0.55.0}/src/learningfoundry/integrations/__init__.py +0 -0
  84. {learningfoundry-0.52.0 → learningfoundry-0.55.0}/src/learningfoundry/integrations/d3foundry_stub.py +0 -0
  85. {learningfoundry-0.52.0 → learningfoundry-0.55.0}/src/learningfoundry/integrations/nbfoundry_stub.py +0 -0
  86. {learningfoundry-0.52.0 → learningfoundry-0.55.0}/src/learningfoundry/integrations/protocols.py +0 -0
  87. {learningfoundry-0.52.0 → learningfoundry-0.55.0}/src/learningfoundry/integrations/quizazz.py +0 -0
  88. {learningfoundry-0.52.0 → learningfoundry-0.55.0}/src/learningfoundry/logging_config.py +0 -0
  89. {learningfoundry-0.52.0 → learningfoundry-0.55.0}/src/learningfoundry/parser.py +0 -0
  90. {learningfoundry-0.52.0 → learningfoundry-0.55.0}/src/learningfoundry/pipeline.py +0 -0
  91. {learningfoundry-0.52.0 → learningfoundry-0.55.0}/src/learningfoundry/py.typed +0 -0
  92. {learningfoundry-0.52.0 → learningfoundry-0.55.0}/src/learningfoundry/resolver.py +0 -0
  93. {learningfoundry-0.52.0 → learningfoundry-0.55.0}/src/learningfoundry/schema_v1.py +0 -0
  94. {learningfoundry-0.52.0 → learningfoundry-0.55.0}/src/learningfoundry/sveltekit_template/e2e/README.md +0 -0
  95. {learningfoundry-0.52.0 → learningfoundry-0.55.0}/src/learningfoundry/sveltekit_template/e2e/finish.spec.ts +0 -0
  96. {learningfoundry-0.52.0 → learningfoundry-0.55.0}/src/learningfoundry/sveltekit_template/e2e/fixtures/curriculum.json +0 -0
  97. {learningfoundry-0.52.0 → learningfoundry-0.55.0}/src/learningfoundry/sveltekit_template/e2e/lifecycle.spec.ts +0 -0
  98. {learningfoundry-0.52.0 → learningfoundry-0.55.0}/src/learningfoundry/sveltekit_template/e2e/navigation.spec.ts +0 -0
  99. {learningfoundry-0.52.0 → learningfoundry-0.55.0}/src/learningfoundry/sveltekit_template/e2e/progress.spec.ts +0 -0
  100. {learningfoundry-0.52.0 → learningfoundry-0.55.0}/src/learningfoundry/sveltekit_template/e2e/reset.spec.ts +0 -0
  101. {learningfoundry-0.52.0 → learningfoundry-0.55.0}/src/learningfoundry/sveltekit_template/e2e/text-block-bottom.spec.ts +0 -0
  102. {learningfoundry-0.52.0 → learningfoundry-0.55.0}/src/learningfoundry/sveltekit_template/e2e/video.spec.ts +0 -0
  103. {learningfoundry-0.52.0 → learningfoundry-0.55.0}/src/learningfoundry/sveltekit_template/package.json +0 -0
  104. {learningfoundry-0.52.0 → learningfoundry-0.55.0}/src/learningfoundry/sveltekit_template/playwright.config.ts +0 -0
  105. {learningfoundry-0.52.0 → learningfoundry-0.55.0}/src/learningfoundry/sveltekit_template/src/app.css +0 -0
  106. {learningfoundry-0.52.0 → learningfoundry-0.55.0}/src/learningfoundry/sveltekit_template/src/app.html +0 -0
  107. {learningfoundry-0.52.0 → learningfoundry-0.55.0}/src/learningfoundry/sveltekit_template/src/lib/components/ContentBlock.svelte +0 -0
  108. {learningfoundry-0.52.0 → learningfoundry-0.55.0}/src/learningfoundry/sveltekit_template/src/lib/components/ExerciseBlock.svelte +0 -0
  109. {learningfoundry-0.52.0 → learningfoundry-0.55.0}/src/learningfoundry/sveltekit_template/src/lib/components/LessonList.svelte +0 -0
  110. {learningfoundry-0.52.0 → learningfoundry-0.55.0}/src/learningfoundry/sveltekit_template/src/lib/components/LessonView.svelte +0 -0
  111. {learningfoundry-0.52.0 → learningfoundry-0.55.0}/src/learningfoundry/sveltekit_template/src/lib/components/ModuleList.svelte +0 -0
  112. {learningfoundry-0.52.0 → learningfoundry-0.55.0}/src/learningfoundry/sveltekit_template/src/lib/components/Navigation.svelte +0 -0
  113. {learningfoundry-0.52.0 → learningfoundry-0.55.0}/src/learningfoundry/sveltekit_template/src/lib/components/PlaceholderBlock.svelte +0 -0
  114. {learningfoundry-0.52.0 → learningfoundry-0.55.0}/src/learningfoundry/sveltekit_template/src/lib/components/ProgressBar.svelte +0 -0
  115. {learningfoundry-0.52.0 → learningfoundry-0.55.0}/src/learningfoundry/sveltekit_template/src/lib/components/QuizBlock.svelte +0 -0
  116. {learningfoundry-0.52.0 → learningfoundry-0.55.0}/src/learningfoundry/sveltekit_template/src/lib/components/ResetCourseButton.svelte +0 -0
  117. {learningfoundry-0.52.0 → learningfoundry-0.55.0}/src/learningfoundry/sveltekit_template/src/lib/components/TextBlock.svelte +0 -0
  118. {learningfoundry-0.52.0 → learningfoundry-0.55.0}/src/learningfoundry/sveltekit_template/src/lib/components/TextBlock.test.ts +0 -0
  119. {learningfoundry-0.52.0 → learningfoundry-0.55.0}/src/learningfoundry/sveltekit_template/src/lib/components/VideoBlock.svelte +0 -0
  120. {learningfoundry-0.52.0 → learningfoundry-0.55.0}/src/learningfoundry/sveltekit_template/src/lib/components/VisualizationBlock.svelte +0 -0
  121. {learningfoundry-0.52.0 → learningfoundry-0.55.0}/src/learningfoundry/sveltekit_template/src/lib/components/lesson-view.helpers.ts +0 -0
  122. {learningfoundry-0.52.0 → learningfoundry-0.55.0}/src/learningfoundry/sveltekit_template/src/lib/components/module-list.helpers.ts +0 -0
  123. {learningfoundry-0.52.0 → learningfoundry-0.55.0}/src/learningfoundry/sveltekit_template/src/lib/components/module-list.test.ts +0 -0
  124. {learningfoundry-0.52.0 → learningfoundry-0.55.0}/src/learningfoundry/sveltekit_template/src/lib/components/mount.test.ts +0 -0
  125. {learningfoundry-0.52.0 → learningfoundry-0.55.0}/src/learningfoundry/sveltekit_template/src/lib/components/navigation.helpers.ts +0 -0
  126. {learningfoundry-0.52.0 → learningfoundry-0.55.0}/src/learningfoundry/sveltekit_template/src/lib/db/database.ts +0 -0
  127. {learningfoundry-0.52.0 → learningfoundry-0.55.0}/src/learningfoundry/sveltekit_template/src/lib/db/index.ts +0 -0
  128. {learningfoundry-0.52.0 → learningfoundry-0.55.0}/src/learningfoundry/sveltekit_template/src/lib/db/progress.test.ts +0 -0
  129. {learningfoundry-0.52.0 → learningfoundry-0.55.0}/src/learningfoundry/sveltekit_template/src/lib/db/progress.ts +0 -0
  130. {learningfoundry-0.52.0 → learningfoundry-0.55.0}/src/learningfoundry/sveltekit_template/src/lib/stores/curriculum.test.ts +0 -0
  131. {learningfoundry-0.52.0 → learningfoundry-0.55.0}/src/learningfoundry/sveltekit_template/src/lib/stores/curriculum.ts +0 -0
  132. {learningfoundry-0.52.0 → learningfoundry-0.55.0}/src/learningfoundry/sveltekit_template/src/lib/stores/progress.test.ts +0 -0
  133. {learningfoundry-0.52.0 → learningfoundry-0.55.0}/src/learningfoundry/sveltekit_template/src/lib/stores/progress.ts +0 -0
  134. {learningfoundry-0.52.0 → learningfoundry-0.55.0}/src/learningfoundry/sveltekit_template/src/lib/types/index.ts +0 -0
  135. {learningfoundry-0.52.0 → learningfoundry-0.55.0}/src/learningfoundry/sveltekit_template/src/lib/utils/locking.test.ts +0 -0
  136. {learningfoundry-0.52.0 → learningfoundry-0.55.0}/src/learningfoundry/sveltekit_template/src/lib/utils/locking.ts +0 -0
  137. {learningfoundry-0.52.0 → learningfoundry-0.55.0}/src/learningfoundry/sveltekit_template/src/lib/utils/markdown.test.ts +0 -0
  138. {learningfoundry-0.52.0 → learningfoundry-0.55.0}/src/learningfoundry/sveltekit_template/src/lib/utils/markdown.ts +0 -0
  139. {learningfoundry-0.52.0 → learningfoundry-0.55.0}/src/learningfoundry/sveltekit_template/src/lib/utils/progress.test.ts +0 -0
  140. {learningfoundry-0.52.0 → learningfoundry-0.55.0}/src/learningfoundry/sveltekit_template/src/lib/utils/progress.ts +0 -0
  141. {learningfoundry-0.52.0 → learningfoundry-0.55.0}/src/learningfoundry/sveltekit_template/src/lib/utils/viewport-completion.ts +0 -0
  142. {learningfoundry-0.52.0 → learningfoundry-0.55.0}/src/learningfoundry/sveltekit_template/src/routes/+layout.svelte +0 -0
  143. {learningfoundry-0.52.0 → learningfoundry-0.55.0}/src/learningfoundry/sveltekit_template/src/routes/+layout.ts +0 -0
  144. {learningfoundry-0.52.0 → learningfoundry-0.55.0}/src/learningfoundry/sveltekit_template/src/routes/+page.svelte +0 -0
  145. {learningfoundry-0.52.0 → learningfoundry-0.55.0}/src/learningfoundry/sveltekit_template/src/routes/[module]/[lesson]/+page.svelte +0 -0
  146. {learningfoundry-0.52.0 → learningfoundry-0.55.0}/src/learningfoundry/sveltekit_template/src/routes/layout.scroll.test.ts +0 -0
  147. {learningfoundry-0.52.0 → learningfoundry-0.55.0}/src/learningfoundry/sveltekit_template/src/routes/layout.scroll.ts +0 -0
  148. {learningfoundry-0.52.0 → learningfoundry-0.55.0}/src/learningfoundry/sveltekit_template/src/routes/layout.test.ts +0 -0
  149. {learningfoundry-0.52.0 → learningfoundry-0.55.0}/src/learningfoundry/sveltekit_template/static/.gitkeep +0 -0
  150. {learningfoundry-0.52.0 → learningfoundry-0.55.0}/src/learningfoundry/sveltekit_template/svelte.config.js +0 -0
  151. {learningfoundry-0.52.0 → learningfoundry-0.55.0}/src/learningfoundry/sveltekit_template/tsconfig.json +0 -0
@@ -7,6 +7,40 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
7
7
 
8
8
  ## [Unreleased]
9
9
 
10
+ ## [0.55.0] - 2026-05-01
11
+
12
+ ### Added
13
+
14
+ - **Real-DOM sidebar / dashboard / button test coverage** (Story I.u). Companion to v0.54.0 / I.t — closes the long tail of "the test passes but the rendered DOM doesn't match what the user sees" gaps on the navigation chrome that the existing helper-style tests can't reach. New [ModuleList.test.ts](src/learningfoundry/sveltekit_template/src/lib/components/ModuleList.test.ts) mounts the sidebar with a locked + unlocked module pair: asserts the locked row carries a `<svg class="lucide-lock">` icon and `aria-disabled="true"`, that clicking the locked header does not reveal a `<LessonList>`, that clicking the unlocked header does, and that an active module gets the `border-l-blue-500 bg-blue-50` highlight while inactive siblings do not. New [LessonList.test.ts](src/learningfoundry/sveltekit_template/src/lib/components/LessonList.test.ts) mounts five rows with mixed statuses and pins the rendered glyph for each (`○` / `…` / `✓` / `◇` / `…` for `not_started` / `in_progress` / `complete` / `optional` / `opened`), verifies `aria-disabled="true"` + `cursor-not-allowed` on locked rows with no `goto` on click, and confirms unlocked clicks call `goto('/${moduleId}/${lessonId}')`. [navigation.test.ts](src/learningfoundry/sveltekit_template/src/lib/components/navigation.test.ts) extended with three mount cases: `disabled=true` flips both the native `disabled` attribute and `opacity-50 cursor-not-allowed` classes; in-curriculum click runs `goto(path)` without touching `currentPosition.set`; Finish click (FR-P14 ordering) runs `currentPosition.set(null)` *before* `goto('/')` (verified via `mock.invocationCallOrder`). [ProgressDashboard.test.ts](src/learningfoundry/sveltekit_template/src/lib/components/ProgressDashboard.test.ts) extended with four mount cases: each module card's `<ProgressBar>` width matches the expected percent (parsed from inline `style.width`), the `{#if totalLessons > 0}` gate suppresses the curriculum summary bar when there are zero lessons, a complete module renders "✓ Complete" with no action button while incomplete siblings render "Start module →" / "Continue →". [ResetCourseButton.test.ts](src/learningfoundry/sveltekit_template/src/lib/components/ResetCourseButton.test.ts) rewritten from inline-handler-copy to mount-based — the inline copy stays as a documentation comment so the contract is readable without opening the .svelte file: disabled `<button>` blocks the synthetic click before `confirmFn` is even prompted; cancelled confirm runs no DB or navigation calls; accepted confirm runs `resetProgress` → `currentPosition.set(null)` → `invalidateProgress` → `goto('/')` in that order (FR-P14).
15
+
16
+ ### Changed
17
+
18
+ - **`vite.config.ts` `testTimeout` bumped from the implicit 5 s default to 15 s.** Component-mount tests pay a one-time vite-transform cost (~4 s) the very first time a file dynamic-imports a Svelte component whose graph pulls in lucide-svelte + marked + katex (`LessonView`, `Navigation`, `ResetCourseButton`). Under serial runs the previous 5 s default left a thin margin; under parallel test-file load the same import landed at 5.1–5.2 s and tipped a green run into a flake. The 15 s ceiling absorbs the cold-compile cost without masking real timeouts (every test in this codebase that *isn't* paying first-import cost completes in <100 ms).
19
+
20
+ ## [0.54.0] - 2026-05-01
21
+
22
+ ### Added
23
+
24
+ - **Real-DOM lesson-render-pipeline test coverage** (Story I.t). Backfills the component-mount cases the prior FR-P9..FR-P15 stories deferred while Svelte 5 + vitest mounting was unsupported (resolved in v0.52.0 / Story I.q). [TextBlock.observer.test.ts](src/learningfoundry/sveltekit_template/src/lib/components/TextBlock.observer.test.ts) gains two cases that capture the `IntersectionObserver` callback and drive `isIntersecting` directly — one verifies the 1 s in-viewport `ontextcomplete` fire (with re-entry latch), the other locks the early-leave cancel path. [VideoBlock.test.ts](src/learningfoundry/sveltekit_template/src/lib/components/VideoBlock.test.ts) rewritten from helper-only to mount-based: asserts the `<script src=".../iframe_api">` tag injection plus `[id^="yt-player-"]` placeholder render on cold start, exercises the URL-change cycle (prior `YT.Player.destroy()` runs, new player created with the new `videoId`, `fired` latch reset so a second `ENDED` event fires `onvideocomplete` again), and confirms the viewport-fallback `IntersectionObserver` arms after 5 s when `window.YT` never loads. [LessonView.test.ts](src/learningfoundry/sveltekit_template/src/lib/components/LessonView.test.ts) gains the FR-P15 transition matrix at the unit layer: engage transition (first `blockcomplete` → `markLessonInProgress` + `onlessonengage`), complete transition (every block completed → `markLessonComplete` + `invalidateProgress` + `onlessoncomplete`, with `engaged` latch holding `onlessonengage` to one fire), revisit suppression (`getLessonProgress` returns `complete` → `onlessonopen` only — no engage / complete events even when block observers fire), and the zero-block edge case (`onlessonopen` → `markLessonComplete` → `onlessoncomplete` in order with no engage in between).
25
+
26
+ ### Changed
27
+
28
+ - `LessonView.test.ts` curriculum-store mock replaced wholesale rather than spread-over: the prior `await importOriginal()` pattern still executed `loadCurriculum()` against the unreachable `/curriculum.json` because the actual derived stores closed over the real `curriculum` readable. The new mock returns hand-stubbed readables for every export the component graph touches, so test runs no longer log a noisy `[learningfoundry] Failed to load curriculum: TypeError: Failed to parse URL from /curriculum.json` and the suite is no longer at risk of timing out under the 5 s default when the fetch retry happens to coincide with module compile time.
29
+
30
+ ## [0.53.0] - 2026-05-01
31
+
32
+ ### Fixed
33
+
34
+ - **Dashboard "Start module →" wrongly displayed for modules with active-but-incomplete lessons.** `ProgressDashboard.svelte`'s `moduleStats()` derived per-module status from `done > 0` (count of `complete` lessons), so a module with an `opened` or `in_progress` lesson — but zero completed lessons — fell back to "Start module →" even though the sidebar correctly showed the lesson as `…`. Regression introduced in v0.45.0 (Story I.j) when the in-progress branch was narrowed from the rollup `mp.status` to a count check, made visible on every lesson click by v0.51.0 (Story I.p, `opened` status). Fix: restore the rollup-based check (`mp.status === 'in_progress'`); optional-lessons handling via `isModuleComplete` is unchanged. Logic extracted into a new `moduleStatus(mod, progress, curriculum?)` helper in `progress-dashboard.helpers.ts` with four anti-regression unit cases (`opened`, `in_progress`, `not_started`, `complete`).
35
+
36
+ ### Removed
37
+
38
+ - **Workspace-root `sveltekit_template/` duplicate.** The template was duplicated into `src/learningfoundry/sveltekit_template/` in v0.25.0 (PyPI wheel-shipping prep) and `_TEMPLATE_DIR` was repointed at the package copy, but the original at the repo root was never deleted. Nothing read it — verified across Python source, GitHub workflows, `.vscode/settings.json`, `pyproject.toml`, and `.gitignore` (the `*/sveltekit_template/*` and `**/sveltekit_template/static/sql-wasm.wasm` globs match the package copy after deletion). The two copies had already drifted on `curriculum.ts`, `+layout.svelte`, `app.css`, `markdown.ts`, and several test files. Deleting it eliminates the drift hazard and removes a confusing "mirror" step from every story.
39
+
40
+ ### Changed
41
+
42
+ - `src/learningfoundry/sveltekit_template/` is now the documented single source of truth. `docs/specs/project-essentials.md` "Architecture Quirks" entry updated; `docs/specs/stories.md` gains a top-of-document convention note instructing future stories not to add `sveltekit_template/` "mirror" tasks; one stale relative-path link in `docs/specs/phase-I-progress-ux-subplan.md` repointed at the package copy.
43
+
10
44
  ## [0.52.0] - 2026-05-01
11
45
 
12
46
  ### Added
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: learningfoundry
3
- Version: 0.52.0
3
+ Version: 0.55.0
4
4
  Summary: A curriculum engine that turns a YAML curriculum definition into a deployable SvelteKit learning application.
5
5
  Project-URL: Homepage, https://github.com/pointmatic/learningfoundry
6
6
  Project-URL: Repository, https://github.com/pointmatic/learningfoundry
@@ -4,7 +4,7 @@ build-backend = "hatchling.build"
4
4
 
5
5
  [project]
6
6
  name = "learningfoundry"
7
- version = "0.52.0"
7
+ version = "0.55.0"
8
8
  description = "A curriculum engine that turns a YAML curriculum definition into a deployable SvelteKit learning application."
9
9
  readme = "README.md"
10
10
  license = "Apache-2.0"
@@ -1,4 +1,4 @@
1
1
  # Copyright 2026 Pointmatic
2
2
  # SPDX-License-Identifier: Apache-2.0
3
3
 
4
- __version__ = "0.52.0"
4
+ __version__ = "0.55.0"
@@ -30,6 +30,9 @@ importers:
30
30
  specifier: ^5.0.0
31
31
  version: 5.55.4
32
32
  devDependencies:
33
+ '@playwright/test':
34
+ specifier: ^1.48.0
35
+ version: 1.59.1
33
36
  '@sveltejs/adapter-static':
34
37
  specifier: ^3.0.0
35
38
  version: 3.0.10(@sveltejs/kit@2.57.1(@sveltejs/vite-plugin-svelte@7.0.0(svelte@5.55.4)(vite@8.0.8(@types/node@25.6.0)(jiti@2.6.1)))(svelte@5.55.4)(typescript@5.9.3)(vite@8.0.8(@types/node@25.6.0)(jiti@2.6.1)))
@@ -42,6 +45,12 @@ importers:
42
45
  '@tailwindcss/vite':
43
46
  specifier: ^4.0.0
44
47
  version: 4.2.2(vite@8.0.8(@types/node@25.6.0)(jiti@2.6.1))
48
+ '@testing-library/jest-dom':
49
+ specifier: ^6.6.0
50
+ version: 6.9.1
51
+ '@testing-library/svelte':
52
+ specifier: ^5.2.0
53
+ version: 5.3.1(svelte@5.55.4)(vite@8.0.8(@types/node@25.6.0)(jiti@2.6.1))(vitest@3.2.4(@types/node@25.6.0)(jiti@2.6.1)(jsdom@25.0.1)(lightningcss@1.32.0))
45
54
  '@types/sql.js':
46
55
  specifier: ^1.4.11
47
56
  version: 1.4.11
@@ -72,9 +81,24 @@ importers:
72
81
 
73
82
  packages:
74
83
 
84
+ '@adobe/css-tools@4.4.4':
85
+ resolution: {integrity: sha512-Elp+iwUx5rN5+Y8xLt5/GRoG20WGoDCQ/1Fb+1LiGtvwbDavuSk0jhD/eZdckHAuzcDzccnkv+rEjyWfRx18gg==}
86
+
75
87
  '@asamuzakjp/css-color@3.2.0':
76
88
  resolution: {integrity: sha512-K1A6z8tS3XsmCMM86xoWdn7Fkdn9m6RSVtocUrJYIwZnFVkng/PvkEoWtOWmP+Scc6saYWHWZYbndEEXxl24jw==}
77
89
 
90
+ '@babel/code-frame@7.29.0':
91
+ resolution: {integrity: sha512-9NhCeYjq9+3uxgdtp20LSiJXJvN0FeCtNGpJxuMFZ1Kv3cWUNb6DOhJwUvcVCzKGR66cw4njwM6hrJLqgOwbcw==}
92
+ engines: {node: '>=6.9.0'}
93
+
94
+ '@babel/helper-validator-identifier@7.28.5':
95
+ resolution: {integrity: sha512-qSs4ifwzKJSV39ucNjsvc6WVHs6b7S03sOh2OcHF9UHfVPqWWALUsNUVzhSBiItjRZoLHx7nIarVjqKVusUZ1Q==}
96
+ engines: {node: '>=6.9.0'}
97
+
98
+ '@babel/runtime@7.29.2':
99
+ resolution: {integrity: sha512-JiDShH45zKHWyGe4ZNVRrCjBz8Nh9TMmZG1kh4QTK8hCBTWBi8Da+i7s1fJw7/lYpM4ccepSNfqzZ/QvABBi5g==}
100
+ engines: {node: '>=6.9.0'}
101
+
78
102
  '@csstools/color-helpers@5.1.0':
79
103
  resolution: {integrity: sha512-S11EXWJyy0Mz5SYvRmY8nJYTFFd1LCNV+7cXyAgQtOOuzb4EsgfqDufL+9esx72/eLhsRdGZwaldu/h+E4t4BA==}
80
104
  engines: {node: '>=18'}
@@ -293,6 +317,11 @@ packages:
293
317
  '@oxc-project/types@0.124.0':
294
318
  resolution: {integrity: sha512-VBFWMTBvHxS11Z5Lvlr3IWgrwhMTXV+Md+EQF0Xf60+wAdsGFTBx7X7K/hP4pi8N7dcm1RvcHwDxZ16Qx8keUg==}
295
319
 
320
+ '@playwright/test@1.59.1':
321
+ resolution: {integrity: sha512-PG6q63nQg5c9rIi4/Z5lR5IVF7yU5MqmKaPOe0HSc0O2cX1fPi96sUQu5j7eo4gKCkB2AnNGoWt7y4/Xx3Kcqg==}
322
+ engines: {node: '>=18'}
323
+ hasBin: true
324
+
296
325
  '@polka/url@1.0.0-next.29':
297
326
  resolution: {integrity: sha512-wwQAWhWSuHaag8c4q/KN/vCoeOJYshAIvMQwD4GpSb3OiZklFfvAgmj0VCBBImRpuF/aFgIRzllXlVX93Jevww==}
298
327
 
@@ -667,9 +696,39 @@ packages:
667
696
  peerDependencies:
668
697
  vite: ^5.2.0 || ^6 || ^7 || ^8
669
698
 
699
+ '@testing-library/dom@10.4.1':
700
+ resolution: {integrity: sha512-o4PXJQidqJl82ckFaXUeoAW+XysPLauYI43Abki5hABd853iMhitooc6znOnczgbTYmEP6U6/y1ZyKAIsvMKGg==}
701
+ engines: {node: '>=18'}
702
+
703
+ '@testing-library/jest-dom@6.9.1':
704
+ resolution: {integrity: sha512-zIcONa+hVtVSSep9UT3jZ5rizo2BsxgyDYU7WFD5eICBE7no3881HGeb/QkGfsJs6JTkY1aQhT7rIPC7e+0nnA==}
705
+ engines: {node: '>=14', npm: '>=6', yarn: '>=1'}
706
+
707
+ '@testing-library/svelte-core@1.0.0':
708
+ resolution: {integrity: sha512-VkUePoLV6oOYwSUvX6ShA8KLnJqZiYMIbP2JW2t0GLWLkJxKGvuH5qrrZBV/X7cXFnLGuFQEC7RheYiZOW68KQ==}
709
+ engines: {node: '>=16'}
710
+ peerDependencies:
711
+ svelte: ^3 || ^4 || ^5 || ^5.0.0-next.0
712
+
713
+ '@testing-library/svelte@5.3.1':
714
+ resolution: {integrity: sha512-8Ez7ZOqW5geRf9PF5rkuopODe5RGy3I9XR+kc7zHh26gBiktLaxTfKmhlGaSHYUOTQE7wFsLMN9xCJVCszw47w==}
715
+ engines: {node: '>= 10'}
716
+ peerDependencies:
717
+ svelte: ^3 || ^4 || ^5 || ^5.0.0-next.0
718
+ vite: '*'
719
+ vitest: '*'
720
+ peerDependenciesMeta:
721
+ vite:
722
+ optional: true
723
+ vitest:
724
+ optional: true
725
+
670
726
  '@tybys/wasm-util@0.10.1':
671
727
  resolution: {integrity: sha512-9tTaPJLSiejZKx+Bmog4uSubteqTvFrVrURwkmHixBo0G4seD0zUxp98E1DzUBJxLQ3NPwXrGKDiVjwx/DpPsg==}
672
728
 
729
+ '@types/aria-query@5.0.4':
730
+ resolution: {integrity: sha512-rfT93uj5s0PRL7EzccGMs3brplhcrghnDoV26NqKhCAS1hVo+WdNsPvE/yb6ilfr5hi2MEk6d5EWJTKdxg8jVw==}
731
+
673
732
  '@types/chai@5.2.3':
674
733
  resolution: {integrity: sha512-Mw558oeA9fFbv65/y4mHtXDs9bPnFMZAL/jxdPFUpOHHIXX91mcgEHbS5Lahr+pwZFR8A7GQleRWeI6cGFC2UA==}
675
734
 
@@ -732,6 +791,17 @@ packages:
732
791
  resolution: {integrity: sha512-MnA+YT8fwfJPgBx3m60MNqakm30XOkyIoH1y6huTQvC0PwZG7ki8NacLBcrPbNoo8vEZy7Jpuk7+jMO+CUovTQ==}
733
792
  engines: {node: '>= 14'}
734
793
 
794
+ ansi-regex@5.0.1:
795
+ resolution: {integrity: sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==}
796
+ engines: {node: '>=8'}
797
+
798
+ ansi-styles@5.2.0:
799
+ resolution: {integrity: sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==}
800
+ engines: {node: '>=10'}
801
+
802
+ aria-query@5.3.0:
803
+ resolution: {integrity: sha512-b0P0sZPKtyu8HkeRAfCq0IfURZK+SuwMjY1UXGBU27wpAiTwQAIlq56IbIO+ytk/JjS1fMR14ee5WBBfKi5J6A==}
804
+
735
805
  aria-query@5.3.1:
736
806
  resolution: {integrity: sha512-Z/ZeOgVl7bcSYZ/u/rh0fOpvEpq//LZmdbkXyc7syVzjPAhfOa9ebsdTSjEBDU4vs5nC98Kfduj1uFo0qyET3g==}
737
807
  engines: {node: '>= 0.4'}
@@ -783,6 +853,9 @@ packages:
783
853
  resolution: {integrity: sha512-U71cyTamuh1CRNCfpGY6to28lxvNwPG4Guz/EVjgf3Jmzv0vlDp1atT9eS5dDjMYHucpHbWns6Lwf3BKz6svdw==}
784
854
  engines: {node: '>= 0.6'}
785
855
 
856
+ css.escape@1.5.1:
857
+ resolution: {integrity: sha512-YUifsXXuknHlUsmlgyY0PKzgPOr7/FjCePfHNt0jxm83wHZi44VDMQ7/fGNkjY3/jV1MC+1CmZbaHzugyeRtpg==}
858
+
786
859
  cssesc@3.0.0:
787
860
  resolution: {integrity: sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg==}
788
861
  engines: {node: '>=4'}
@@ -820,6 +893,10 @@ packages:
820
893
  resolution: {integrity: sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==}
821
894
  engines: {node: '>=0.4.0'}
822
895
 
896
+ dequal@2.0.3:
897
+ resolution: {integrity: sha512-0je+qPKHEMohvfRTCEo3CrPG6cAzAYgmzKyxRiYSSDkS6eGJdyVJm7WaYA5ECaAD9wLB2T4EEeymA5aFVcYXCA==}
898
+ engines: {node: '>=6'}
899
+
823
900
  detect-libc@2.1.2:
824
901
  resolution: {integrity: sha512-Btj2BOOO83o3WyH59e8MgXsxEQVcarkUOpEYrubB0urwnN10yQ364rsiByU11nZlqWYZm05i/of7io4mzihBtQ==}
825
902
  engines: {node: '>=8'}
@@ -827,6 +904,12 @@ packages:
827
904
  devalue@5.7.1:
828
905
  resolution: {integrity: sha512-MUbZ586EgQqdRnC4yDrlod3BEdyvE4TapGYHMW2CiaW+KkkFmWEFqBUaLltEZCGi0iFXCEjRF0OjF0DV2QHjOA==}
829
906
 
907
+ dom-accessibility-api@0.5.16:
908
+ resolution: {integrity: sha512-X7BJ2yElsnOJ30pZF4uIIDfBEVgF4XEBxL9Bxhy6dnrm5hkzqmsWHGTiHqRiITNhMyFLyAiWndIJP7Z1NTteDg==}
909
+
910
+ dom-accessibility-api@0.6.3:
911
+ resolution: {integrity: sha512-7ZgogeTnjuHbo+ct10G9Ffp0mif17idi0IyWNVA/wcwcm7NPOD/WEHVP3n7n3MhXqxoIYm8d6MuZohYWIZ4T3w==}
912
+
830
913
  dunder-proto@1.0.1:
831
914
  resolution: {integrity: sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==}
832
915
  engines: {node: '>= 0.4'}
@@ -894,6 +977,11 @@ packages:
894
977
  resolution: {integrity: sha512-8RipRLol37bNs2bhoV67fiTEvdTrbMUYcFTiy3+wuuOnUog2QBHCZWXDRijWQfAkhBj2Uf5UnVaiWwA5vdd82w==}
895
978
  engines: {node: '>= 6'}
896
979
 
980
+ fsevents@2.3.2:
981
+ resolution: {integrity: sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==}
982
+ engines: {node: ^8.16.0 || ^10.6.0 || >=11.0.0}
983
+ os: [darwin]
984
+
897
985
  fsevents@2.3.3:
898
986
  resolution: {integrity: sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==}
899
987
  engines: {node: ^8.16.0 || ^10.6.0 || >=11.0.0}
@@ -945,6 +1033,10 @@ packages:
945
1033
  resolution: {integrity: sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==}
946
1034
  engines: {node: '>=0.10.0'}
947
1035
 
1036
+ indent-string@4.0.0:
1037
+ resolution: {integrity: sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg==}
1038
+ engines: {node: '>=8'}
1039
+
948
1040
  is-potential-custom-element-name@1.0.1:
949
1041
  resolution: {integrity: sha512-bCYeRA2rVibKZd+s2625gGnGF/t7DSqDs4dP7CrLA1m7jKWz6pps0LpYLJN8Q64HtmPKJ1hrN3nzPNKFEKOUiQ==}
950
1042
 
@@ -955,6 +1047,9 @@ packages:
955
1047
  resolution: {integrity: sha512-ekilCSN1jwRvIbgeg/57YFh8qQDNbwDb9xT/qu2DAHbFFZUicIl4ygVaAvzveMhMVr3LnpSKTNnwt8PoOfmKhQ==}
956
1048
  hasBin: true
957
1049
 
1050
+ js-tokens@4.0.0:
1051
+ resolution: {integrity: sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==}
1052
+
958
1053
  js-tokens@9.0.1:
959
1054
  resolution: {integrity: sha512-mxa9E9ITFOt0ban3j6L5MpjwegGz6lBQmM1IJkWeBZGcMxto50+eWdjC/52xDbS2vy0k7vIMK0Fe2wfL9OQSpQ==}
960
1055
 
@@ -1063,6 +1158,10 @@ packages:
1063
1158
  peerDependencies:
1064
1159
  svelte: ^3 || ^4 || ^5.0.0-next.42
1065
1160
 
1161
+ lz-string@1.5.0:
1162
+ resolution: {integrity: sha512-h5bgJWpxJNswbU7qCrV0tIKQCaS3blPDrqKWx+QxzuzL1zGUzij9XCWLrSLsJPu5t+eWA/ycetzYAO5IOMcWAQ==}
1163
+ hasBin: true
1164
+
1066
1165
  magic-string@0.30.21:
1067
1166
  resolution: {integrity: sha512-vd2F4YUyEXKGcLHoq+TEyCjxueSeHnFxyyjNp80yg0XV4vUhnDer/lvvlqM/arB5bXQN5K2/3oinyCRyx8T2CQ==}
1068
1167
 
@@ -1089,6 +1188,10 @@ packages:
1089
1188
  resolution: {integrity: sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==}
1090
1189
  engines: {node: '>= 0.6'}
1091
1190
 
1191
+ min-indent@1.0.1:
1192
+ resolution: {integrity: sha512-I9jwMn07Sy/IwOj3zVkVik2JTvgpaykDZEigL6Rx6N9LbMywwUSMtxET+7lVoDLLd3O3IXwJwvuuns8UB/HeAg==}
1193
+ engines: {node: '>=4'}
1194
+
1092
1195
  mri@1.2.0:
1093
1196
  resolution: {integrity: sha512-tzzskb3bG8LvYGFF/mDTpq3jpI6Q9wc3LEmBaghu+DdCssd1FakN7Bc0hVNmEyGq1bq3RgfkCb3cmQLpNPOroA==}
1094
1197
  engines: {node: '>=4'}
@@ -1128,6 +1231,16 @@ packages:
1128
1231
  resolution: {integrity: sha512-QP88BAKvMam/3NxH6vj2o21R6MjxZUAd6nlwAS/pnGvN9IVLocLHxGYIzFhg6fUQ+5th6P4dv4eW9jX3DSIj7A==}
1129
1232
  engines: {node: '>=12'}
1130
1233
 
1234
+ playwright-core@1.59.1:
1235
+ resolution: {integrity: sha512-HBV/RJg81z5BiiZ9yPzIiClYV/QMsDCKUyogwH9p3MCP6IYjUFu/MActgYAvK0oWyV9NlwM3GLBjADyWgydVyg==}
1236
+ engines: {node: '>=18'}
1237
+ hasBin: true
1238
+
1239
+ playwright@1.59.1:
1240
+ resolution: {integrity: sha512-C8oWjPR3F81yljW9o5OxcWzfh6avkVwDD2VYdwIGqTkl+OGFISgypqzfu7dOe4QNLL2aqcWBmI3PMtLIK233lw==}
1241
+ engines: {node: '>=18'}
1242
+ hasBin: true
1243
+
1131
1244
  postcss-selector-parser@6.0.10:
1132
1245
  resolution: {integrity: sha512-IQ7TZdoaqbT+LCpShg46jnZVlhWD2w6iQYAcYXfHARZ7X1t/UGhhceQDs5X0cGqKvYlHNOuv7Oa1xmb0oQuA3w==}
1133
1246
  engines: {node: '>=4'}
@@ -1147,14 +1260,25 @@ packages:
1147
1260
  engines: {node: '>=14'}
1148
1261
  hasBin: true
1149
1262
 
1263
+ pretty-format@27.5.1:
1264
+ resolution: {integrity: sha512-Qb1gy5OrP5+zDf2Bvnzdl3jsTf1qXVMazbvCoKhtKqVs4/YK4ozX4gKQJJVyNe+cajNPn0KoC0MC3FUmaHWEmQ==}
1265
+ engines: {node: ^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0}
1266
+
1150
1267
  punycode@2.3.1:
1151
1268
  resolution: {integrity: sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==}
1152
1269
  engines: {node: '>=6'}
1153
1270
 
1271
+ react-is@17.0.2:
1272
+ resolution: {integrity: sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w==}
1273
+
1154
1274
  readdirp@4.1.2:
1155
1275
  resolution: {integrity: sha512-GDhwkLfywWL2s6vEjyhri+eXmfH6j1L7JE27WhqLeYzoh/A3DBaYGEj2H/HFZCn/kMfim73FXxEJTw06WtxQwg==}
1156
1276
  engines: {node: '>= 14.18.0'}
1157
1277
 
1278
+ redent@3.0.0:
1279
+ resolution: {integrity: sha512-6tDA8g98We0zd0GvVeMT9arEOnTw9qM03L9cJXaCjrip1OO764RDBLBfrB4cwzNGDj5OA5ioymC9GkizgWJDUg==}
1280
+ engines: {node: '>=8'}
1281
+
1158
1282
  rolldown@1.0.0-rc.15:
1159
1283
  resolution: {integrity: sha512-Ff31guA5zT6WjnGp0SXw76X6hzGRk/OQq2hE+1lcDe+lJdHSgnSX6nK3erbONHyCbpSj9a9E+uX/OvytZoWp2g==}
1160
1284
  engines: {node: ^20.19.0 || >=22.12.0}
@@ -1205,6 +1329,10 @@ packages:
1205
1329
  std-env@3.10.0:
1206
1330
  resolution: {integrity: sha512-5GS12FdOZNliM5mAOxFRg7Ir0pWz8MdpYm6AY6VPkGpbA7ZzmbzNcBJQ0GPvvyWgcY7QAhCgf9Uy89I03faLkg==}
1207
1331
 
1332
+ strip-indent@3.0.0:
1333
+ resolution: {integrity: sha512-laJTa3Jb+VQpaC6DseHhF7dXVqHTfJPCRDaEbid/drOhgitgYku/letMUqOXFoWV0zIIUbjpdH2t+tYj4bQMRQ==}
1334
+ engines: {node: '>=8'}
1335
+
1208
1336
  strip-literal@3.1.0:
1209
1337
  resolution: {integrity: sha512-8r3mkIM/2+PpjHoOtiAW8Rg3jJLHaV7xPwG+YRGrv6FP0wwk/toTpATxWYOW0BKdWwl82VT2tFYi5DlROa0Mxg==}
1210
1338
 
@@ -1459,6 +1587,8 @@ packages:
1459
1587
 
1460
1588
  snapshots:
1461
1589
 
1590
+ '@adobe/css-tools@4.4.4': {}
1591
+
1462
1592
  '@asamuzakjp/css-color@3.2.0':
1463
1593
  dependencies:
1464
1594
  '@csstools/css-calc': 2.1.4(@csstools/css-parser-algorithms@3.0.5(@csstools/css-tokenizer@3.0.4))(@csstools/css-tokenizer@3.0.4)
@@ -1467,6 +1597,16 @@ snapshots:
1467
1597
  '@csstools/css-tokenizer': 3.0.4
1468
1598
  lru-cache: 10.4.3
1469
1599
 
1600
+ '@babel/code-frame@7.29.0':
1601
+ dependencies:
1602
+ '@babel/helper-validator-identifier': 7.28.5
1603
+ js-tokens: 4.0.0
1604
+ picocolors: 1.1.1
1605
+
1606
+ '@babel/helper-validator-identifier@7.28.5': {}
1607
+
1608
+ '@babel/runtime@7.29.2': {}
1609
+
1470
1610
  '@csstools/color-helpers@5.1.0': {}
1471
1611
 
1472
1612
  '@csstools/css-calc@2.1.4(@csstools/css-parser-algorithms@3.0.5(@csstools/css-tokenizer@3.0.4))(@csstools/css-tokenizer@3.0.4)':
@@ -1609,6 +1749,10 @@ snapshots:
1609
1749
 
1610
1750
  '@oxc-project/types@0.124.0': {}
1611
1751
 
1752
+ '@playwright/test@1.59.1':
1753
+ dependencies:
1754
+ playwright: 1.59.1
1755
+
1612
1756
  '@polka/url@1.0.0-next.29': {}
1613
1757
 
1614
1758
  '@rolldown/binding-android-arm64@1.0.0-rc.15':
@@ -1849,11 +1993,46 @@ snapshots:
1849
1993
  tailwindcss: 4.2.2
1850
1994
  vite: 8.0.8(@types/node@25.6.0)(jiti@2.6.1)
1851
1995
 
1996
+ '@testing-library/dom@10.4.1':
1997
+ dependencies:
1998
+ '@babel/code-frame': 7.29.0
1999
+ '@babel/runtime': 7.29.2
2000
+ '@types/aria-query': 5.0.4
2001
+ aria-query: 5.3.0
2002
+ dom-accessibility-api: 0.5.16
2003
+ lz-string: 1.5.0
2004
+ picocolors: 1.1.1
2005
+ pretty-format: 27.5.1
2006
+
2007
+ '@testing-library/jest-dom@6.9.1':
2008
+ dependencies:
2009
+ '@adobe/css-tools': 4.4.4
2010
+ aria-query: 5.3.1
2011
+ css.escape: 1.5.1
2012
+ dom-accessibility-api: 0.6.3
2013
+ picocolors: 1.1.1
2014
+ redent: 3.0.0
2015
+
2016
+ '@testing-library/svelte-core@1.0.0(svelte@5.55.4)':
2017
+ dependencies:
2018
+ svelte: 5.55.4
2019
+
2020
+ '@testing-library/svelte@5.3.1(svelte@5.55.4)(vite@8.0.8(@types/node@25.6.0)(jiti@2.6.1))(vitest@3.2.4(@types/node@25.6.0)(jiti@2.6.1)(jsdom@25.0.1)(lightningcss@1.32.0))':
2021
+ dependencies:
2022
+ '@testing-library/dom': 10.4.1
2023
+ '@testing-library/svelte-core': 1.0.0(svelte@5.55.4)
2024
+ svelte: 5.55.4
2025
+ optionalDependencies:
2026
+ vite: 8.0.8(@types/node@25.6.0)(jiti@2.6.1)
2027
+ vitest: 3.2.4(@types/node@25.6.0)(jiti@2.6.1)(jsdom@25.0.1)(lightningcss@1.32.0)
2028
+
1852
2029
  '@tybys/wasm-util@0.10.1':
1853
2030
  dependencies:
1854
2031
  tslib: 2.8.1
1855
2032
  optional: true
1856
2033
 
2034
+ '@types/aria-query@5.0.4': {}
2035
+
1857
2036
  '@types/chai@5.2.3':
1858
2037
  dependencies:
1859
2038
  '@types/deep-eql': 4.0.2
@@ -1924,6 +2103,14 @@ snapshots:
1924
2103
 
1925
2104
  agent-base@7.1.4: {}
1926
2105
 
2106
+ ansi-regex@5.0.1: {}
2107
+
2108
+ ansi-styles@5.2.0: {}
2109
+
2110
+ aria-query@5.3.0:
2111
+ dependencies:
2112
+ dequal: 2.0.3
2113
+
1927
2114
  aria-query@5.3.1: {}
1928
2115
 
1929
2116
  assertion-error@2.0.1: {}
@@ -1963,6 +2150,8 @@ snapshots:
1963
2150
 
1964
2151
  cookie@0.6.0: {}
1965
2152
 
2153
+ css.escape@1.5.1: {}
2154
+
1966
2155
  cssesc@3.0.0: {}
1967
2156
 
1968
2157
  cssstyle@4.6.0:
@@ -1987,10 +2176,16 @@ snapshots:
1987
2176
 
1988
2177
  delayed-stream@1.0.0: {}
1989
2178
 
2179
+ dequal@2.0.3: {}
2180
+
1990
2181
  detect-libc@2.1.2: {}
1991
2182
 
1992
2183
  devalue@5.7.1: {}
1993
2184
 
2185
+ dom-accessibility-api@0.5.16: {}
2186
+
2187
+ dom-accessibility-api@0.6.3: {}
2188
+
1994
2189
  dunder-proto@1.0.1:
1995
2190
  dependencies:
1996
2191
  call-bind-apply-helpers: 1.0.2
@@ -2074,6 +2269,9 @@ snapshots:
2074
2269
  hasown: 2.0.3
2075
2270
  mime-types: 2.1.35
2076
2271
 
2272
+ fsevents@2.3.2:
2273
+ optional: true
2274
+
2077
2275
  fsevents@2.3.3:
2078
2276
  optional: true
2079
2277
 
@@ -2133,6 +2331,8 @@ snapshots:
2133
2331
  dependencies:
2134
2332
  safer-buffer: 2.1.2
2135
2333
 
2334
+ indent-string@4.0.0: {}
2335
+
2136
2336
  is-potential-custom-element-name@1.0.1: {}
2137
2337
 
2138
2338
  is-reference@3.0.3:
@@ -2141,6 +2341,8 @@ snapshots:
2141
2341
 
2142
2342
  jiti@2.6.1: {}
2143
2343
 
2344
+ js-tokens@4.0.0: {}
2345
+
2144
2346
  js-tokens@9.0.1: {}
2145
2347
 
2146
2348
  jsdom@25.0.1:
@@ -2236,6 +2438,8 @@ snapshots:
2236
2438
  dependencies:
2237
2439
  svelte: 5.55.4
2238
2440
 
2441
+ lz-string@1.5.0: {}
2442
+
2239
2443
  magic-string@0.30.21:
2240
2444
  dependencies:
2241
2445
  '@jridgewell/sourcemap-codec': 1.5.5
@@ -2255,6 +2459,8 @@ snapshots:
2255
2459
  dependencies:
2256
2460
  mime-db: 1.52.0
2257
2461
 
2462
+ min-indent@1.0.1: {}
2463
+
2258
2464
  mri@1.2.0: {}
2259
2465
 
2260
2466
  mrmime@2.0.1: {}
@@ -2279,6 +2485,14 @@ snapshots:
2279
2485
 
2280
2486
  picomatch@4.0.4: {}
2281
2487
 
2488
+ playwright-core@1.59.1: {}
2489
+
2490
+ playwright@1.59.1:
2491
+ dependencies:
2492
+ playwright-core: 1.59.1
2493
+ optionalDependencies:
2494
+ fsevents: 2.3.2
2495
+
2282
2496
  postcss-selector-parser@6.0.10:
2283
2497
  dependencies:
2284
2498
  cssesc: 3.0.0
@@ -2297,10 +2511,23 @@ snapshots:
2297
2511
 
2298
2512
  prettier@3.8.3: {}
2299
2513
 
2514
+ pretty-format@27.5.1:
2515
+ dependencies:
2516
+ ansi-regex: 5.0.1
2517
+ ansi-styles: 5.2.0
2518
+ react-is: 17.0.2
2519
+
2300
2520
  punycode@2.3.1: {}
2301
2521
 
2522
+ react-is@17.0.2: {}
2523
+
2302
2524
  readdirp@4.1.2: {}
2303
2525
 
2526
+ redent@3.0.0:
2527
+ dependencies:
2528
+ indent-string: 4.0.0
2529
+ strip-indent: 3.0.0
2530
+
2304
2531
  rolldown@1.0.0-rc.15:
2305
2532
  dependencies:
2306
2533
  '@oxc-project/types': 0.124.0
@@ -2385,6 +2612,10 @@ snapshots:
2385
2612
 
2386
2613
  std-env@3.10.0: {}
2387
2614
 
2615
+ strip-indent@3.0.0:
2616
+ dependencies:
2617
+ min-indent: 1.0.1
2618
+
2388
2619
  strip-literal@3.1.0:
2389
2620
  dependencies:
2390
2621
  js-tokens: 9.0.1