@cwygoda/service-catalog-ui 0.17.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.
Files changed (68) hide show
  1. package/dist/__mocks__/app-environment.d.ts +4 -0
  2. package/dist/__mocks__/app-environment.js +4 -0
  3. package/dist/__mocks__/app-state.d.ts +12 -0
  4. package/dist/__mocks__/app-state.js +10 -0
  5. package/dist/adapters/index.d.ts +1 -0
  6. package/dist/adapters/index.js +1 -0
  7. package/dist/adapters/static-json.adapter.d.ts +2 -0
  8. package/dist/adapters/static-json.adapter.js +34 -0
  9. package/dist/components/BpmnDiagram.svelte +496 -0
  10. package/dist/components/BpmnDiagram.svelte.d.ts +18 -0
  11. package/dist/components/Breadcrumbs.svelte +32 -0
  12. package/dist/components/Breadcrumbs.svelte.d.ts +11 -0
  13. package/dist/components/DataStoreCard.svelte +26 -0
  14. package/dist/components/DataStoreCard.svelte.d.ts +7 -0
  15. package/dist/components/DataStoreShield.svelte +67 -0
  16. package/dist/components/DataStoreShield.svelte.d.ts +9 -0
  17. package/dist/components/DomainCard.svelte +34 -0
  18. package/dist/components/DomainCard.svelte.d.ts +9 -0
  19. package/dist/components/DomainCard.test.d.ts +1 -0
  20. package/dist/components/DomainCard.test.js +45 -0
  21. package/dist/components/Header.svelte +144 -0
  22. package/dist/components/Header.svelte.d.ts +3 -0
  23. package/dist/components/NavModeToggle.svelte +43 -0
  24. package/dist/components/NavModeToggle.svelte.d.ts +18 -0
  25. package/dist/components/NavTree.svelte +245 -0
  26. package/dist/components/NavTree.svelte.d.ts +10 -0
  27. package/dist/components/SearchModal.svelte +288 -0
  28. package/dist/components/SearchModal.svelte.d.ts +3 -0
  29. package/dist/components/ServiceCard.svelte +36 -0
  30. package/dist/components/ServiceCard.svelte.d.ts +7 -0
  31. package/dist/components/ServiceCard.test.d.ts +1 -0
  32. package/dist/components/ServiceCard.test.js +43 -0
  33. package/dist/components/ServiceGraph.svelte +437 -0
  34. package/dist/components/ServiceGraph.svelte.d.ts +10 -0
  35. package/dist/components/ServiceTypeShield.svelte +32 -0
  36. package/dist/components/ServiceTypeShield.svelte.d.ts +8 -0
  37. package/dist/components/Shield.svelte +118 -0
  38. package/dist/components/Shield.svelte.d.ts +7 -0
  39. package/dist/components/ThemeToggle.svelte +44 -0
  40. package/dist/components/ThemeToggle.svelte.d.ts +18 -0
  41. package/dist/components/ThemeToggle.test.d.ts +1 -0
  42. package/dist/components/ThemeToggle.test.js +52 -0
  43. package/dist/components/UseCaseCard.svelte +61 -0
  44. package/dist/components/UseCaseCard.svelte.d.ts +7 -0
  45. package/dist/components/UseCaseCard.test.d.ts +1 -0
  46. package/dist/components/UseCaseCard.test.js +87 -0
  47. package/dist/components/index.d.ts +15 -0
  48. package/dist/components/index.js +15 -0
  49. package/dist/index.d.ts +5 -0
  50. package/dist/index.js +5 -0
  51. package/dist/ports/catalog.port.d.ts +5 -0
  52. package/dist/ports/catalog.port.js +1 -0
  53. package/dist/ports/index.d.ts +1 -0
  54. package/dist/ports/index.js +1 -0
  55. package/dist/source.css +1 -0
  56. package/dist/stores/index.d.ts +4 -0
  57. package/dist/stores/index.js +3 -0
  58. package/dist/stores/nav-mode.svelte.d.ts +7 -0
  59. package/dist/stores/nav-mode.svelte.js +32 -0
  60. package/dist/stores/search.svelte.d.ts +9 -0
  61. package/dist/stores/search.svelte.js +14 -0
  62. package/dist/stores/theme.svelte.d.ts +8 -0
  63. package/dist/stores/theme.svelte.js +61 -0
  64. package/dist/utils/fetch-catalog.d.ts +6 -0
  65. package/dist/utils/fetch-catalog.js +26 -0
  66. package/dist/utils/index.d.ts +1 -0
  67. package/dist/utils/index.js +1 -0
  68. package/package.json +63 -0
@@ -0,0 +1,52 @@
1
+ /// <reference types="@testing-library/jest-dom" />
2
+ import { render, screen, cleanup } from '@testing-library/svelte';
3
+ import { userEvent } from '@testing-library/user-event';
4
+ import { afterEach, beforeEach, describe, expect, it } from 'vitest';
5
+ import ThemeToggle from './ThemeToggle.svelte';
6
+ describe('ThemeToggle', () => {
7
+ beforeEach(() => {
8
+ // Clear localStorage and reset document
9
+ localStorage.clear();
10
+ document.documentElement.classList.remove('dark');
11
+ });
12
+ afterEach(() => {
13
+ cleanup();
14
+ });
15
+ it('renders toggle button', () => {
16
+ render(ThemeToggle);
17
+ expect(screen.getByRole('button', { name: 'Toggle theme' })).toBeInTheDocument();
18
+ });
19
+ it('toggles theme on click', async () => {
20
+ const user = userEvent.setup();
21
+ render(ThemeToggle);
22
+ const button = screen.getByRole('button', { name: 'Toggle theme' });
23
+ const initialDark = document.documentElement.classList.contains('dark');
24
+ await user.click(button);
25
+ // Theme should be toggled from initial state
26
+ const afterClick = document.documentElement.classList.contains('dark');
27
+ expect(afterClick).not.toBe(initialDark);
28
+ });
29
+ it('toggles theme back on second click', async () => {
30
+ const user = userEvent.setup();
31
+ render(ThemeToggle);
32
+ const button = screen.getByRole('button', { name: 'Toggle theme' });
33
+ // Get state after first click
34
+ await user.click(button);
35
+ const afterFirstClick = document.documentElement.classList.contains('dark');
36
+ // Click again
37
+ await user.click(button);
38
+ const afterSecondClick = document.documentElement.classList.contains('dark');
39
+ // Should be opposite of after first click
40
+ expect(afterSecondClick).not.toBe(afterFirstClick);
41
+ });
42
+ it('persists theme to localStorage', async () => {
43
+ const user = userEvent.setup();
44
+ render(ThemeToggle);
45
+ const button = screen.getByRole('button', { name: 'Toggle theme' });
46
+ await user.click(button);
47
+ // Should have persisted something to localStorage
48
+ const stored = localStorage.getItem('theme');
49
+ expect(stored).toBeTruthy();
50
+ expect(['light', 'dark']).toContain(stored);
51
+ });
52
+ });
@@ -0,0 +1,61 @@
1
+ <script lang="ts">
2
+ import type { UseCase } from '@cwygoda/service-catalog-core/domain';
3
+ import Shield from './Shield.svelte';
4
+
5
+ let { useCase }: { useCase: UseCase } = $props();
6
+
7
+ function truncate(text: string, maxLength: number): string {
8
+ if (text.length <= maxLength) return text;
9
+ return text.slice(0, maxLength).trimEnd() + '...';
10
+ }
11
+ </script>
12
+
13
+ <a
14
+ href="/use-cases/{useCase.id}"
15
+ aria-label="View {useCase.name} use case"
16
+ class="block rounded-lg border border-gray-200 bg-white p-6 shadow-sm transition-shadow hover:shadow-md active:shadow-sm dark:border-gray-700 dark:bg-gray-800"
17
+ >
18
+ <div class="mb-3 flex items-start gap-4">
19
+ <Shield label={useCase.name} size={44} />
20
+ <div class="min-w-0 flex-1">
21
+ <h3 class="truncate text-lg font-semibold text-gray-900 dark:text-white">
22
+ {useCase.name}
23
+ </h3>
24
+ <p class="mt-1 text-sm text-gray-600 dark:text-gray-400">
25
+ {truncate(useCase.description, 120)}
26
+ </p>
27
+ </div>
28
+ </div>
29
+
30
+ <div class="flex items-center gap-4 text-xs text-gray-500 dark:text-gray-400">
31
+ <span class="flex items-center gap-1">
32
+ <svg class="h-4 w-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
33
+ <path
34
+ stroke-linecap="round"
35
+ stroke-linejoin="round"
36
+ stroke-width="2"
37
+ d="M17 20h5v-2a3 3 0 00-5.356-1.857M17 20H7m10 0v-2c0-.656-.126-1.283-.356-1.857M7 20H2v-2a3 3 0 015.356-1.857M7 20v-2c0-.656.126-1.283.356-1.857m0 0a5.002 5.002 0 019.288 0M15 7a3 3 0 11-6 0 3 3 0 016 0zm6 3a2 2 0 11-4 0 2 2 0 014 0zM7 10a2 2 0 11-4 0 2 2 0 014 0z"
38
+ />
39
+ </svg>
40
+ {useCase.participants.length} participant{useCase.participants.length !== 1 ? 's' : ''}
41
+ </span>
42
+ <span class="flex items-center gap-1">
43
+ <svg class="h-4 w-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
44
+ <path
45
+ stroke-linecap="round"
46
+ stroke-linejoin="round"
47
+ stroke-width="2"
48
+ d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-3 7h3m-3 4h3m-6-4h.01M9 16h.01"
49
+ />
50
+ </svg>
51
+ {useCase.steps.length} step{useCase.steps.length !== 1 ? 's' : ''}
52
+ </span>
53
+ {#if useCase.bpmn}
54
+ <span
55
+ class="rounded-full bg-primary-100 px-2 py-0.5 text-xs font-medium text-primary-800 dark:bg-primary-900 dark:text-primary-200"
56
+ >
57
+ BPMN
58
+ </span>
59
+ {/if}
60
+ </div>
61
+ </a>
@@ -0,0 +1,7 @@
1
+ import type { UseCase } from '@cwygoda/service-catalog-core/domain';
2
+ type $$ComponentProps = {
3
+ useCase: UseCase;
4
+ };
5
+ declare const UseCaseCard: import("svelte").Component<$$ComponentProps, {}, "">;
6
+ type UseCaseCard = ReturnType<typeof UseCaseCard>;
7
+ export default UseCaseCard;
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,87 @@
1
+ /// <reference types="@testing-library/jest-dom" />
2
+ import { render, screen } from '@testing-library/svelte';
3
+ import { describe, expect, it } from 'vitest';
4
+ import UseCaseCard from './UseCaseCard.svelte';
5
+ describe('UseCaseCard', () => {
6
+ const baseUseCase = {
7
+ id: 'test-use-case',
8
+ name: 'Test Use Case',
9
+ description: 'A test use case description',
10
+ participants: [],
11
+ steps: [],
12
+ };
13
+ it('renders use case name', () => {
14
+ render(UseCaseCard, { props: { useCase: baseUseCase } });
15
+ expect(screen.getByText('Test Use Case')).toBeInTheDocument();
16
+ });
17
+ it('renders use case description', () => {
18
+ render(UseCaseCard, { props: { useCase: baseUseCase } });
19
+ expect(screen.getByText('A test use case description')).toBeInTheDocument();
20
+ });
21
+ it('links to use case detail page', () => {
22
+ render(UseCaseCard, { props: { useCase: baseUseCase } });
23
+ const link = screen.getByRole('link');
24
+ expect(link).toHaveAttribute('href', '/use-cases/test-use-case');
25
+ });
26
+ it('truncates long descriptions with ellipsis', () => {
27
+ const longDesc = 'A'.repeat(150);
28
+ const useCaseWithLongDesc = {
29
+ ...baseUseCase,
30
+ description: longDesc,
31
+ };
32
+ render(UseCaseCard, { props: { useCase: useCaseWithLongDesc } });
33
+ // Should truncate to 120 chars + "..."
34
+ expect(screen.getByText(/^A{100,120}\.\.\.$/)).toBeInTheDocument();
35
+ });
36
+ it('shows BPMN badge when bpmn is defined', () => {
37
+ const useCaseWithBpmn = {
38
+ ...baseUseCase,
39
+ bpmn: './diagram.bpmn',
40
+ };
41
+ render(UseCaseCard, { props: { useCase: useCaseWithBpmn } });
42
+ expect(screen.getByText('BPMN')).toBeInTheDocument();
43
+ });
44
+ it('does not show BPMN badge when no bpmn', () => {
45
+ render(UseCaseCard, { props: { useCase: baseUseCase } });
46
+ expect(screen.queryByText('BPMN')).not.toBeInTheDocument();
47
+ });
48
+ it('shows participant count', () => {
49
+ const useCaseWithParticipants = {
50
+ ...baseUseCase,
51
+ participants: [
52
+ { service: 'svc-1', role: 'Role 1' },
53
+ { service: 'svc-2', role: 'Role 2' },
54
+ ],
55
+ };
56
+ render(UseCaseCard, { props: { useCase: useCaseWithParticipants } });
57
+ expect(screen.getByText('2 participants')).toBeInTheDocument();
58
+ });
59
+ it('shows singular participant when count is 1', () => {
60
+ const useCaseWithOneParticipant = {
61
+ ...baseUseCase,
62
+ participants: [{ service: 'svc-1', role: 'Role 1' }],
63
+ };
64
+ render(UseCaseCard, { props: { useCase: useCaseWithOneParticipant } });
65
+ expect(screen.getByText('1 participant')).toBeInTheDocument();
66
+ });
67
+ it('shows step count', () => {
68
+ const useCaseWithSteps = {
69
+ ...baseUseCase,
70
+ steps: [
71
+ { sequence: 1, action: 'Step 1' },
72
+ { sequence: 2, action: 'Step 2' },
73
+ { sequence: 3, action: 'Step 3' },
74
+ ],
75
+ };
76
+ render(UseCaseCard, { props: { useCase: useCaseWithSteps } });
77
+ expect(screen.getByText('3 steps')).toBeInTheDocument();
78
+ });
79
+ it('shows singular step when count is 1', () => {
80
+ const useCaseWithOneStep = {
81
+ ...baseUseCase,
82
+ steps: [{ sequence: 1, action: 'Step 1' }],
83
+ };
84
+ render(UseCaseCard, { props: { useCase: useCaseWithOneStep } });
85
+ expect(screen.getByText('1 step')).toBeInTheDocument();
86
+ });
87
+ });
@@ -0,0 +1,15 @@
1
+ export { default as BpmnDiagram } from './BpmnDiagram.svelte';
2
+ export { default as Breadcrumbs } from './Breadcrumbs.svelte';
3
+ export { default as DataStoreCard } from './DataStoreCard.svelte';
4
+ export { default as DataStoreShield } from './DataStoreShield.svelte';
5
+ export { default as DomainCard } from './DomainCard.svelte';
6
+ export { default as Header } from './Header.svelte';
7
+ export { default as NavModeToggle } from './NavModeToggle.svelte';
8
+ export { default as NavTree } from './NavTree.svelte';
9
+ export { default as SearchModal } from './SearchModal.svelte';
10
+ export { default as ServiceCard } from './ServiceCard.svelte';
11
+ export { default as ServiceTypeShield } from './ServiceTypeShield.svelte';
12
+ export { default as Shield } from './Shield.svelte';
13
+ export { default as ServiceGraph } from './ServiceGraph.svelte';
14
+ export { default as ThemeToggle } from './ThemeToggle.svelte';
15
+ export { default as UseCaseCard } from './UseCaseCard.svelte';
@@ -0,0 +1,15 @@
1
+ export { default as BpmnDiagram } from './BpmnDiagram.svelte';
2
+ export { default as Breadcrumbs } from './Breadcrumbs.svelte';
3
+ export { default as DataStoreCard } from './DataStoreCard.svelte';
4
+ export { default as DataStoreShield } from './DataStoreShield.svelte';
5
+ export { default as DomainCard } from './DomainCard.svelte';
6
+ export { default as Header } from './Header.svelte';
7
+ export { default as NavModeToggle } from './NavModeToggle.svelte';
8
+ export { default as NavTree } from './NavTree.svelte';
9
+ export { default as SearchModal } from './SearchModal.svelte';
10
+ export { default as ServiceCard } from './ServiceCard.svelte';
11
+ export { default as ServiceTypeShield } from './ServiceTypeShield.svelte';
12
+ export { default as Shield } from './Shield.svelte';
13
+ export { default as ServiceGraph } from './ServiceGraph.svelte';
14
+ export { default as ThemeToggle } from './ThemeToggle.svelte';
15
+ export { default as UseCaseCard } from './UseCaseCard.svelte';
@@ -0,0 +1,5 @@
1
+ export * from './components/index.js';
2
+ export * from './stores/index.js';
3
+ export * from './adapters/index.js';
4
+ export * from './ports/index.js';
5
+ export * from './utils/index.js';
package/dist/index.js ADDED
@@ -0,0 +1,5 @@
1
+ export * from './components/index.js';
2
+ export * from './stores/index.js';
3
+ export * from './adapters/index.js';
4
+ export * from './ports/index.js';
5
+ export * from './utils/index.js';
@@ -0,0 +1,5 @@
1
+ import type { Catalog, Service } from '@cwygoda/service-catalog-core/domain';
2
+ export interface CatalogPort {
3
+ getCatalog(): Promise<Catalog>;
4
+ getService(id: string): Promise<Service | undefined>;
5
+ }
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1 @@
1
+ export type { CatalogPort } from './catalog.port.js';
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1 @@
1
+ @source "./";
@@ -0,0 +1,4 @@
1
+ export { theme } from './theme.svelte.js';
2
+ export type { Theme } from './theme.svelte.js';
3
+ export { navModeStore } from './nav-mode.svelte.js';
4
+ export { searchStore } from './search.svelte.js';
@@ -0,0 +1,3 @@
1
+ export { theme } from './theme.svelte.js';
2
+ export { navModeStore } from './nav-mode.svelte.js';
3
+ export { searchStore } from './search.svelte.js';
@@ -0,0 +1,7 @@
1
+ type NavMode = 'flat' | 'tree';
2
+ export declare const navModeStore: {
3
+ readonly mode: NavMode;
4
+ toggle(): void;
5
+ setMode(newMode: NavMode): void;
6
+ };
7
+ export {};
@@ -0,0 +1,32 @@
1
+ import { browser } from '$app/environment';
2
+ const STORAGE_KEY = 'nav-mode';
3
+ function getInitialMode() {
4
+ if (browser) {
5
+ const stored = localStorage.getItem(STORAGE_KEY);
6
+ if (stored === 'tree' || stored === 'flat') {
7
+ return stored;
8
+ }
9
+ }
10
+ return 'flat';
11
+ }
12
+ function createNavModeStore() {
13
+ let mode = $state(getInitialMode());
14
+ return {
15
+ get mode() {
16
+ return mode;
17
+ },
18
+ toggle() {
19
+ mode = mode === 'flat' ? 'tree' : 'flat';
20
+ if (browser) {
21
+ localStorage.setItem(STORAGE_KEY, mode);
22
+ }
23
+ },
24
+ setMode(newMode) {
25
+ mode = newMode;
26
+ if (browser) {
27
+ localStorage.setItem(STORAGE_KEY, mode);
28
+ }
29
+ },
30
+ };
31
+ }
32
+ export const navModeStore = createNavModeStore();
@@ -0,0 +1,9 @@
1
+ /** Reactive store for search modal open state */
2
+ declare class SearchStore {
3
+ open: boolean;
4
+ toggle(): void;
5
+ show(): void;
6
+ hide(): void;
7
+ }
8
+ export declare const searchStore: SearchStore;
9
+ export {};
@@ -0,0 +1,14 @@
1
+ /** Reactive store for search modal open state */
2
+ class SearchStore {
3
+ open = $state(false);
4
+ toggle() {
5
+ this.open = !this.open;
6
+ }
7
+ show() {
8
+ this.open = true;
9
+ }
10
+ hide() {
11
+ this.open = false;
12
+ }
13
+ }
14
+ export const searchStore = new SearchStore();
@@ -0,0 +1,8 @@
1
+ export type Theme = 'light' | 'dark' | 'system';
2
+ export declare const theme: {
3
+ readonly current: Theme;
4
+ readonly resolved: "light" | "dark";
5
+ init(): void;
6
+ set(newTheme: Theme): void;
7
+ toggle(): void;
8
+ };
@@ -0,0 +1,61 @@
1
+ const STORAGE_KEY = 'theme';
2
+ function getStoredTheme() {
3
+ if (typeof localStorage === 'undefined')
4
+ return 'system';
5
+ const stored = localStorage.getItem(STORAGE_KEY);
6
+ if (stored === 'light' || stored === 'dark' || stored === 'system') {
7
+ return stored;
8
+ }
9
+ return 'system';
10
+ }
11
+ function getSystemTheme() {
12
+ if (typeof window === 'undefined')
13
+ return 'light';
14
+ return window.matchMedia('(prefers-color-scheme: dark)').matches ? 'dark' : 'light';
15
+ }
16
+ function applyTheme(theme) {
17
+ if (typeof document === 'undefined')
18
+ return;
19
+ const resolved = theme === 'system' ? getSystemTheme() : theme;
20
+ const root = document.documentElement;
21
+ if (resolved === 'dark') {
22
+ root.classList.add('dark');
23
+ }
24
+ else {
25
+ root.classList.remove('dark');
26
+ }
27
+ }
28
+ // Simple reactive state using $state rune at module level
29
+ let currentTheme = $state('system');
30
+ export const theme = {
31
+ get current() {
32
+ return currentTheme;
33
+ },
34
+ get resolved() {
35
+ return currentTheme === 'system' ? getSystemTheme() : currentTheme;
36
+ },
37
+ init() {
38
+ if (typeof window === 'undefined')
39
+ return;
40
+ // Load stored theme
41
+ currentTheme = getStoredTheme();
42
+ // Listen for system theme changes
43
+ const mediaQuery = window.matchMedia('(prefers-color-scheme: dark)');
44
+ mediaQuery.addEventListener('change', () => {
45
+ if (currentTheme === 'system') {
46
+ applyTheme('system');
47
+ }
48
+ });
49
+ },
50
+ set(newTheme) {
51
+ currentTheme = newTheme;
52
+ if (typeof localStorage !== 'undefined') {
53
+ localStorage.setItem(STORAGE_KEY, newTheme);
54
+ }
55
+ applyTheme(newTheme);
56
+ },
57
+ toggle() {
58
+ const next = this.resolved === 'dark' ? 'light' : 'dark';
59
+ this.set(next);
60
+ },
61
+ };
@@ -0,0 +1,6 @@
1
+ import type { Catalog } from '@cwygoda/service-catalog-core/domain';
2
+ /**
3
+ * Fetches and validates catalog.json with proper error handling.
4
+ * Use in SvelteKit load functions.
5
+ */
6
+ export declare function fetchCatalog(fetch: typeof globalThis.fetch, path?: string): Promise<Catalog>;
@@ -0,0 +1,26 @@
1
+ import { error } from '@sveltejs/kit';
2
+ import { Value } from '@sinclair/typebox/value';
3
+ import { CatalogSchema } from '@cwygoda/service-catalog-core/schemas';
4
+ /**
5
+ * Fetches and validates catalog.json with proper error handling.
6
+ * Use in SvelteKit load functions.
7
+ */
8
+ export async function fetchCatalog(fetch, path = '/catalog.json') {
9
+ const response = await fetch(path);
10
+ if (!response.ok) {
11
+ error(response.status, `Failed to load catalog: ${response.statusText}`);
12
+ }
13
+ let data;
14
+ try {
15
+ data = await response.json();
16
+ }
17
+ catch {
18
+ error(500, 'Invalid JSON in catalog');
19
+ }
20
+ if (!Value.Check(CatalogSchema, data)) {
21
+ const errors = [...Value.Errors(CatalogSchema, data)];
22
+ const message = errors.map((e) => `${e.path}: ${e.message}`).join('; ');
23
+ error(500, `Invalid catalog data: ${message}`);
24
+ }
25
+ return data;
26
+ }
@@ -0,0 +1 @@
1
+ export { fetchCatalog } from './fetch-catalog.js';
@@ -0,0 +1 @@
1
+ export { fetchCatalog } from './fetch-catalog.js';
package/package.json ADDED
@@ -0,0 +1,63 @@
1
+ {
2
+ "name": "@cwygoda/service-catalog-ui",
3
+ "version": "0.17.1",
4
+ "type": "module",
5
+ "svelte": "./dist/index.js",
6
+ "exports": {
7
+ ".": {
8
+ "types": "./dist/index.d.ts",
9
+ "style": "./dist/source.css",
10
+ "svelte": "./dist/index.js"
11
+ },
12
+ "./components": {
13
+ "types": "./dist/components/index.d.ts",
14
+ "style": "./dist/source.css",
15
+ "svelte": "./dist/components/index.js"
16
+ },
17
+ "./stores": {
18
+ "types": "./dist/stores/index.d.ts",
19
+ "style": "./dist/source.css",
20
+ "svelte": "./dist/stores/index.js"
21
+ }
22
+ },
23
+ "files": [
24
+ "dist"
25
+ ],
26
+ "dependencies": {
27
+ "@sinclair/typebox": "^0.34.48",
28
+ "@cwygoda/service-catalog-core": "0.17.1"
29
+ },
30
+ "peerDependencies": {
31
+ "@sveltejs/kit": "^2.0.0",
32
+ "bpmn-js": "^18.0.0",
33
+ "d3-drag": "^3.0.0",
34
+ "d3-force": "^3.0.0",
35
+ "d3-selection": "^3.0.0",
36
+ "d3-zoom": "^3.0.0",
37
+ "svelte": "^5.0.0"
38
+ },
39
+ "devDependencies": {
40
+ "@sveltejs/kit": "^2.53.4",
41
+ "@sveltejs/package": "^2.5.7",
42
+ "@sveltejs/vite-plugin-svelte": "^6.2.4",
43
+ "@testing-library/jest-dom": "^6.9.1",
44
+ "@testing-library/svelte": "^5.3.1",
45
+ "@testing-library/user-event": "^14.6.1",
46
+ "@types/d3-drag": "^3.0.7",
47
+ "@types/d3-force": "^3.0.10",
48
+ "@types/d3-selection": "^3.0.11",
49
+ "@types/d3-zoom": "^3.0.8",
50
+ "jsdom": "^28.1.0",
51
+ "svelte": "^5.53.6",
52
+ "svelte-check": "^4.4.4",
53
+ "typescript": "^5.9.3",
54
+ "vite": "^7.3.1",
55
+ "vitest": "^4.0.18"
56
+ },
57
+ "scripts": {
58
+ "build": "svelte-kit sync && svelte-package",
59
+ "test": "vitest run",
60
+ "test:watch": "vitest",
61
+ "typecheck": "svelte-kit sync && svelte-check"
62
+ }
63
+ }