managarten/packages/help/src/components/ChangelogSection.svelte
Till JS 9bf73fffa3 fix(help): correct broken imports + tighten SupportedLanguage typing
Two unrelated bugs in the @mana/help package surface that together
accounted for ~40 type errors:

Broken component imports
  Ten components inside packages/help/src/components/ were importing
  from `'../types.js'` and `'./content'` — neither path resolves.
  The actual files are at `../ui-types` (where FAQSectionProps,
  FeaturesOverviewProps etc. live) and `../content` (where FAQItem,
  FeatureItem, FAQCategory live). Fix the imports to point at the
  real files. ESM resolution doesn't need `.js` suffixes when
  TypeScript is feeding tsc, and the existing index.ts already
  re-exports under the correct paths.

  Net: -19 type errors across:
    ChangelogEntry, ChangelogSection, ContactSection, FAQItem,
    FAQSection, FeatureCard, FeaturesOverview, GettingStartedGuide,
    HelpSearch, KeyboardShortcuts

content/help/index.ts SupportedLanguage cast
  `getManaHelpContent()` was passing `currentLocale` (typed `string`)
  into FAQ rows that expect a `SupportedLanguage` enum — 9 errors
  from each FAQ row. Add a small `asSupportedLanguage()` guard that
  validates the locale string against the union and falls back to
  'de' for unknown values. Single source of truth lives next to
  the function that needed it.

  Net: -9 type errors.

Combined with the spiral-db dist rebuild (local-only, gitignored)
and the previous Observable migration commit, the total error count
drops from 418 → 115.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-09 18:13:18 +02:00

45 lines
1.1 KiB
Svelte

<script lang="ts">
import type { ChangelogSectionProps } from '../ui-types';
import ChangelogEntry from './ChangelogEntry.svelte';
let { items, translations, maxItems = 10 }: ChangelogSectionProps = $props();
let showAll = $state(false);
const sortedItems = $derived(() => {
return [...items].sort(
(a, b) => new Date(b.releaseDate).getTime() - new Date(a.releaseDate).getTime()
);
});
const displayedItems = $derived(() => {
if (showAll) return sortedItems();
return sortedItems().slice(0, maxItems);
});
const hasMore = $derived(items.length > maxItems && !showAll);
</script>
{#if items.length === 0}
<p class="py-8 text-center text-gray-500 dark:text-gray-400">
{translations.changelog.noItems}
</p>
{:else}
<div>
{#each displayedItems() as item (item.id)}
<ChangelogEntry {item} {translations} />
{/each}
{#if hasMore}
<div class="pt-4 text-center">
<button
type="button"
class="text-primary-600 dark:text-primary-400 text-sm font-medium hover:underline"
onclick={() => (showAll = true)}
>
{translations.changelog.showAll} ({items.length - maxItems})
</button>
</div>
{/if}
</div>
{/if}