@svadmin/ui 0.79.0 → 0.81.0

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.
@@ -0,0 +1,75 @@
1
+ <script lang="ts">
2
+ import type { Snippet } from 'svelte';
3
+ import { definedOptions } from '@svadmin/core/options';
4
+ import ContentPageShell from './content/ContentPageShell.svelte';
5
+
6
+ interface Props {
7
+ title: string;
8
+ description?: string;
9
+ eyebrow?: string;
10
+ actions?: Snippet;
11
+ footer?: Snippet;
12
+ children: Snippet;
13
+ width?: 'narrow' | 'default' | 'wide';
14
+ density?: 'compact' | 'comfortable';
15
+ class?: string;
16
+ }
17
+
18
+ let {
19
+ title,
20
+ description,
21
+ eyebrow,
22
+ actions,
23
+ footer,
24
+ children,
25
+ width = 'default',
26
+ density = 'comfortable',
27
+ class: className = '',
28
+ }: Props = $props();
29
+ </script>
30
+
31
+ <ContentPageShell
32
+ {title}
33
+ {...definedOptions({ description, eyebrow, actions })}
34
+ {width}
35
+ {density}
36
+ class={className}
37
+ >
38
+ <div class="configuration-page__content">
39
+ {@render children()}
40
+ </div>
41
+ {#if footer}
42
+ <footer class="configuration-page__footer">
43
+ {@render footer()}
44
+ </footer>
45
+ {/if}
46
+ </ContentPageShell>
47
+
48
+ <style>
49
+ .configuration-page__content {
50
+ display: grid;
51
+ gap: 24px;
52
+ }
53
+
54
+ .configuration-page__footer {
55
+ display: flex;
56
+ flex-wrap: wrap;
57
+ align-items: center;
58
+ justify-content: flex-end;
59
+ gap: 8px;
60
+ margin-top: 24px;
61
+ padding: 12px 0;
62
+ border-top: 1px solid var(--border);
63
+ background: var(--background);
64
+ }
65
+
66
+ @media (max-width: 640px) {
67
+ .configuration-page__footer {
68
+ justify-content: stretch;
69
+ }
70
+
71
+ .configuration-page__footer :global(button) {
72
+ flex: 1;
73
+ }
74
+ }
75
+ </style>
@@ -0,0 +1,15 @@
1
+ import type { Snippet } from 'svelte';
2
+ interface Props {
3
+ title: string;
4
+ description?: string;
5
+ eyebrow?: string;
6
+ actions?: Snippet;
7
+ footer?: Snippet;
8
+ children: Snippet;
9
+ width?: 'narrow' | 'default' | 'wide';
10
+ density?: 'compact' | 'comfortable';
11
+ class?: string;
12
+ }
13
+ declare const ConfigurationPage: import("svelte").Component<Props, {}, "">;
14
+ type ConfigurationPage = ReturnType<typeof ConfigurationPage>;
15
+ export default ConfigurationPage;
@@ -1,8 +1,9 @@
1
1
  <script lang="ts">
2
2
  import { onMount } from 'svelte';
3
3
  import { connectPanelChannel, type PanelChannel } from 'devframe/in-page-channel';
4
+ import { DEVTOOLS_CHANNEL } from '@vibeunion/devtools-devframe';
4
5
  import {
5
- SVADMIN_DEVFRAME_CHANNEL,
6
+ type DevtoolsCacheMutation,
6
7
  type DevtoolsQuerySelector,
7
8
  type SvadminDevframeProtocol,
8
9
  type SvadminDevtoolsSnapshot,
@@ -22,11 +23,14 @@
22
23
  ...(selectedOperation ? { operation: selectedOperation } : {}),
23
24
  });
24
25
 
25
- async function run(action: (selector?: DevtoolsQuerySelector) => Promise<void> | void): Promise<void> {
26
+ async function run(action: DevtoolsCacheMutation, selector?: DevtoolsQuerySelector): Promise<void> {
26
27
  if (!channel || !snapshot) return;
27
28
  busy = true;
28
29
  try {
29
- await action(Object.keys(selector).length > 0 ? selector : undefined);
30
+ await channel.call('cacheAction', {
31
+ action,
32
+ ...(selector && Object.keys(selector).length > 0 ? { selector } : {}),
33
+ });
30
34
  snapshot = await channel.call('getSnapshot');
31
35
  } finally {
32
36
  busy = false;
@@ -35,7 +39,7 @@
35
39
 
36
40
  onMount(() => {
37
41
  const nextChannel = connectPanelChannel<SvadminDevframeProtocol>({
38
- name: SVADMIN_DEVFRAME_CHANNEL,
42
+ name: DEVTOOLS_CHANNEL,
39
43
  functions: {},
40
44
  });
41
45
  channel = nextChannel;
@@ -109,13 +113,13 @@
109
113
  </ul>
110
114
  {/if}
111
115
  <div>
112
- <button type="button" disabled={busy} onclick={() => run((selector) => channel?.call('cacheInvalidate', selector))}>Invalidate</button>
113
- <button type="button" disabled={busy} onclick={() => run((selector) => channel?.call('cacheRefetch', selector))}>Refetch</button>
114
- <button type="button" disabled={busy} onclick={() => run((selector) => channel?.call('cacheCancel', selector))}>Cancel</button>
115
- <button type="button" disabled={busy} onclick={() => run((selector) => channel?.call('cacheReset', selector))}>Reset</button>
116
- <button type="button" disabled={busy} onclick={() => run((selector) => channel?.call('cacheRemove', selector))}>Remove</button>
117
- <button type="button" disabled={busy} onclick={() => run(() => channel?.call('cacheClear'))}>Clear cache</button>
118
- <button type="button" disabled={busy} onclick={() => run(() => channel?.call('clearMutations'))}>Clear mutations</button>
116
+ <button type="button" disabled={busy} onclick={() => run('invalidate', selector)}>Invalidate</button>
117
+ <button type="button" disabled={busy} onclick={() => run('refetch', selector)}>Refetch</button>
118
+ <button type="button" disabled={busy} onclick={() => run('cancel', selector)}>Cancel</button>
119
+ <button type="button" disabled={busy} onclick={() => run('reset', selector)}>Reset</button>
120
+ <button type="button" disabled={busy} onclick={() => run('remove', selector)}>Remove</button>
121
+ <button type="button" disabled={busy} onclick={() => run('clear')}>Clear cache</button>
122
+ <button type="button" disabled={busy} onclick={() => run('clearMutations')}>Clear mutations</button>
119
123
  </div>
120
124
  {:else}
121
125
  <p>Waiting for an svadmin page.</p>
@@ -1,5 +1,4 @@
1
1
  <script lang="ts">
2
- import { scale } from 'svelte/transition';
3
2
  import { PackageOpen } from '@lucide/svelte';
4
3
  import { useTranslation } from '@svadmin/core';
5
4
 
@@ -17,19 +16,29 @@
17
16
  </script>
18
17
 
19
18
  <div
20
- class="svadmin-u-60fbb7713999 svadmin-u-8dddea0773ed svadmin-u-3960ffc248d9 svadmin-u-86843cf1e227 svadmin-u-5f22e64f2282 svadmin-u-24104d87db9a svadmin-u-7e3e9a76c966 svadmin-u-1100bef66e60 svadmin-u-ca6bf63030aa svadmin-u-cef5b893cf23"
21
- in:scale={{ start: 0.95, duration: 200, opacity: 0 }}
19
+ class="empty-state"
22
20
  role="status"
23
21
  aria-live="polite"
24
22
  >
25
- <div class="svadmin-u-0a769880db93 svadmin-u-ed831a4dff32 svadmin-u-ac204c108886 svadmin-u-2ef11f1cb219 svadmin-u-60fbb7713999 svadmin-u-3960ffc248d9 svadmin-u-86843cf1e227 svadmin-u-da019856f2cc">
26
- <PackageOpen class="svadmin-u-426b8b75185b svadmin-u-d854e5698b57 svadmin-u-bfa603190748" />
23
+ <span class="empty-state__icon" aria-hidden="true">
24
+ <PackageOpen size={16} />
25
+ </span>
26
+ <div class="empty-state__body">
27
+ <h3>{title}</h3>
28
+ {#if description}<p>{description}</p>{/if}
29
+ {#if children}
30
+ <div class="empty-state__action">
31
+ {@render children()}
32
+ </div>
33
+ {/if}
27
34
  </div>
28
- <h3 class="svadmin-u-42536e69e639 svadmin-u-e83a7042bc91 svadmin-u-1d7f28b046ad">{title}</h3>
29
- <p class="svadmin-u-fc7473ca09eb svadmin-u-bfa603190748 svadmin-u-50d0d216a2f8 svadmin-u-2472e9b81a97">{description}</p>
30
- {#if children}
31
- <div class="svadmin-u-31f2553311b6">
32
- {@render children()}
33
- </div>
34
- {/if}
35
35
  </div>
36
+
37
+ <style>
38
+ .empty-state { display: flex; align-items: flex-start; gap: 12px; padding: 16px; text-align: left; color: var(--foreground); }
39
+ .empty-state__icon { display: flex; align-items: center; justify-content: center; flex: 0 0 32px; height: 32px; border-radius: 6px; background: var(--muted); color: var(--muted-foreground); }
40
+ .empty-state__body { min-width: 0; flex: 1; overflow-wrap: anywhere; }
41
+ h3 { margin: 0; font-size: 14px; line-height: 20px; font-weight: 600; letter-spacing: 0; }
42
+ p { margin: 4px 0 0; font-size: 14px; line-height: 20px; color: var(--muted-foreground); }
43
+ .empty-state__action { margin-top: 12px; }
44
+ </style>
@@ -0,0 +1,114 @@
1
+ <script lang="ts">
2
+ import type { Snippet } from 'svelte';
3
+ import { definedOptions } from '@svadmin/core/options';
4
+ import ContentPageShell from './content/ContentPageShell.svelte';
5
+ import WorkspaceLayout from './content/WorkspaceLayout.svelte';
6
+
7
+ export type PagePatternKind = 'list' | 'form' | 'detail' | 'workspace' | 'dashboard';
8
+
9
+ interface Props {
10
+ kind: PagePatternKind;
11
+ title: string;
12
+ description?: string;
13
+ eyebrow?: string;
14
+ actions?: Snippet;
15
+ toolbar?: Snippet;
16
+ metrics?: Snippet;
17
+ secondary?: Snippet;
18
+ children: Snippet;
19
+ footer?: Snippet;
20
+ width?: 'narrow' | 'default' | 'wide';
21
+ density?: 'compact' | 'comfortable';
22
+ pageId?: string;
23
+ class?: string;
24
+ }
25
+
26
+ let {
27
+ kind,
28
+ title,
29
+ description,
30
+ eyebrow,
31
+ actions,
32
+ toolbar,
33
+ metrics,
34
+ secondary,
35
+ children,
36
+ footer,
37
+ width,
38
+ density,
39
+ pageId,
40
+ class: className = '',
41
+ }: Props = $props();
42
+
43
+ const resolvedPageId = $derived(pageId ?? `pattern-${kind}`);
44
+ const resolvedWidth = $derived(width ?? (kind === 'form' ? 'narrow' : kind === 'detail' ? 'default' : 'wide'));
45
+ const resolvedDensity = $derived(density ?? (kind === 'list' || kind === 'workspace' ? 'compact' : 'comfortable'));
46
+ </script>
47
+
48
+ <ContentPageShell
49
+ {title}
50
+ {...definedOptions({ description, eyebrow, actions })}
51
+ density={resolvedDensity}
52
+ width={resolvedWidth}
53
+ pageId={resolvedPageId}
54
+ class={className}
55
+ >
56
+ {#if metrics}
57
+ <div class="page-pattern__metrics" data-page-pattern-metrics>
58
+ {@render metrics()}
59
+ </div>
60
+ {/if}
61
+
62
+ {#if toolbar}
63
+ <div class="page-pattern__toolbar" data-page-pattern-toolbar>
64
+ {@render toolbar()}
65
+ </div>
66
+ {/if}
67
+
68
+ {#if secondary}
69
+ <WorkspaceLayout primary={children} {...definedOptions({ secondary })} />
70
+ {:else}
71
+ <div class="page-pattern__content" data-page-pattern-content={kind} data-density={resolvedDensity}>
72
+ {@render children()}
73
+ </div>
74
+ {/if}
75
+
76
+ {#if footer}
77
+ <footer class="page-pattern__footer" data-page-pattern-footer>
78
+ {@render footer()}
79
+ </footer>
80
+ {/if}
81
+ </ContentPageShell>
82
+
83
+ <style>
84
+ .page-pattern__metrics {
85
+ display: grid;
86
+ grid-template-columns: repeat(auto-fit, minmax(min(100%, 14rem), 1fr));
87
+ gap: 16px;
88
+ }
89
+
90
+ .page-pattern__toolbar,
91
+ .page-pattern__content {
92
+ min-width: 0;
93
+ }
94
+
95
+ .page-pattern__content {
96
+ display: grid;
97
+ gap: 24px;
98
+ }
99
+
100
+ .page-pattern__content[data-density='compact'] {
101
+ gap: 16px;
102
+ }
103
+
104
+ .page-pattern__footer {
105
+ display: flex;
106
+ flex-wrap: wrap;
107
+ align-items: center;
108
+ justify-content: flex-end;
109
+ gap: 8px;
110
+ margin-top: 24px;
111
+ padding-top: 12px;
112
+ border-top: 1px solid var(--border);
113
+ }
114
+ </style>
@@ -0,0 +1,21 @@
1
+ import type { Snippet } from 'svelte';
2
+ export type PagePatternKind = 'list' | 'form' | 'detail' | 'workspace' | 'dashboard';
3
+ interface Props {
4
+ kind: PagePatternKind;
5
+ title: string;
6
+ description?: string;
7
+ eyebrow?: string;
8
+ actions?: Snippet;
9
+ toolbar?: Snippet;
10
+ metrics?: Snippet;
11
+ secondary?: Snippet;
12
+ children: Snippet;
13
+ footer?: Snippet;
14
+ width?: 'narrow' | 'default' | 'wide';
15
+ density?: 'compact' | 'comfortable';
16
+ pageId?: string;
17
+ class?: string;
18
+ }
19
+ declare const PagePattern: import("svelte").Component<Props, {}, "">;
20
+ type PagePattern = ReturnType<typeof PagePattern>;
21
+ export default PagePattern;
@@ -53,8 +53,23 @@
53
53
  {#if action}<div class="svadmin-u-eccd13ef4f2f">{@render action()}</div>{/if}
54
54
  </Alert.Root>
55
55
  {:else}
56
- <div class={'svadmin-u-60fbb7713999 svadmin-u-8dddea0773ed svadmin-u-3960ffc248d9 svadmin-u-86843cf1e227 svadmin-u-5f22e64f2282 svadmin-u-ca6bcd4b6f3f svadmin-u-a29b7a649c77 svadmin-u-18049387f0af svadmin-u-cd0ad9a56558 svadmin-u-f92d02360b8f svadmin-u-a1f611f027dd svadmin-u-ca6bf63030aa ' + className} role="status" aria-live="polite">
57
- <Inbox class="svadmin-u-d8f5213f0fe0 svadmin-u-bfa603190748" aria-hidden="true" /><h3 class="svadmin-u-eccd13ef4f2f svadmin-u-fc7473ca09eb svadmin-u-e83a7042bc91 svadmin-u-d4108abe6359">{resolvedTitle}</h3><p class="svadmin-u-b6b02c0ebef6 svadmin-u-2472e9b81a97 svadmin-u-fc7473ca09eb svadmin-u-bfa603190748">{resolvedDescription}</p>
58
- {#if action}<div class="svadmin-u-0ab8667228fd">{@render action()}</div>{/if}
56
+ <div class={'empty-state ' + className} role="status" aria-live="polite">
57
+ <span class="empty-state__icon" aria-hidden="true">
58
+ <Inbox size={16} />
59
+ </span>
60
+ <div class="empty-state__body">
61
+ <h3>{resolvedTitle}</h3>
62
+ {#if resolvedDescription}<p>{resolvedDescription}</p>{/if}
63
+ {#if action}<div class="empty-state__action">{@render action()}</div>{/if}
64
+ </div>
59
65
  </div>
60
66
  {/if}
67
+
68
+ <style>
69
+ .empty-state { display: flex; align-items: flex-start; gap: 12px; padding: 16px; text-align: left; color: var(--foreground); }
70
+ .empty-state__icon { display: flex; align-items: center; justify-content: center; flex: 0 0 32px; height: 32px; border-radius: 6px; background: var(--muted); color: var(--muted-foreground); }
71
+ .empty-state__body { min-width: 0; flex: 1; overflow-wrap: anywhere; }
72
+ .empty-state h3 { margin: 0; font-size: 14px; line-height: 20px; font-weight: 600; letter-spacing: 0; }
73
+ .empty-state p { margin: 4px 0 0; font-size: 14px; line-height: 20px; color: var(--muted-foreground); }
74
+ .empty-state__action { margin-top: 12px; }
75
+ </style>
@@ -1,22 +1,7 @@
1
- import type { DevtoolsQueryDiagnostic, SvadminDevtoolsSnapshot } from '@svadmin/devtools-contract';
2
- export declare const SVADMIN_DEVFRAME_CHANNEL = "svadmin:devtools";
1
+ import { type DevtoolsPageBridge } from '@vibeunion/devtools-devframe';
2
+ import type { DevtoolsCacheActionRequest, DevtoolsCacheActionResult, DevtoolsQueryDiagnostic, SvadminDevtoolsSnapshot } from '@svadmin/devtools-contract';
3
3
  export type { DevtoolsCacheDiagnostics, DevtoolsProviderDiagnostic, DevtoolsQueryDiagnostic, SvadminDevtoolsSnapshot, } from '@svadmin/devtools-contract';
4
- export type SvadminDevtoolsBridge = {
5
- getSnapshot: () => SvadminDevtoolsSnapshot | null;
6
- subscribe: (listener: (snapshot: SvadminDevtoolsSnapshot) => void) => () => void;
7
- cache: {
8
- cancel: (selector?: DevtoolsQuerySelector) => Promise<void>;
9
- invalidate: (selector?: DevtoolsQuerySelector) => Promise<void>;
10
- refetch: (selector?: DevtoolsQuerySelector) => Promise<void>;
11
- remove: (selector?: DevtoolsQuerySelector) => void;
12
- reset: (selector?: DevtoolsQuerySelector) => Promise<void>;
13
- clear: () => void;
14
- clearMutations: () => void;
15
- };
16
- devframe: {
17
- channelName: typeof SVADMIN_DEVFRAME_CHANNEL;
18
- };
19
- };
4
+ export type { DevtoolsCacheActionRequest, DevtoolsCacheActionResult, DevtoolsCacheMutation, } from '@svadmin/devtools-contract';
20
5
  export type DevtoolsQuerySelector = Partial<Pick<DevtoolsQueryDiagnostic, 'provider' | 'resource' | 'operation'>>;
21
6
  type QueryClientLike = {
22
7
  getQueryCache: () => {
@@ -43,19 +28,19 @@ type QueryClientLike = {
43
28
  }) => Promise<void>;
44
29
  getMutationCache: () => {
45
30
  clear: () => void;
31
+ getAll?: () => readonly unknown[];
46
32
  };
47
33
  };
34
+ /**
35
+ * Page-script protocol as seen by a panel. It mirrors the shared DevTools wire
36
+ * (`getSnapshot` + `cacheAction`); the shared bridge installs the same shape on
37
+ * `window.__VIBEUNION_DEVTOOLS__`.
38
+ */
48
39
  export type SvadminDevframeProtocol = {
49
40
  functions: {
50
41
  pageScript: {
51
42
  getSnapshot: () => SvadminDevtoolsSnapshot | null;
52
- cacheCancel: (selector?: DevtoolsQuerySelector) => Promise<void>;
53
- cacheInvalidate: (selector?: DevtoolsQuerySelector) => Promise<void>;
54
- cacheRefetch: (selector?: DevtoolsQuerySelector) => Promise<void>;
55
- cacheRemove: (selector?: DevtoolsQuerySelector) => void;
56
- cacheReset: (selector?: DevtoolsQuerySelector) => Promise<void>;
57
- cacheClear: () => void;
58
- clearMutations: () => void;
43
+ cacheAction: (request: DevtoolsCacheActionRequest) => Promise<DevtoolsCacheActionResult>;
59
44
  };
60
45
  };
61
46
  };
@@ -72,9 +57,10 @@ export declare function createSvadminDevtoolsCacheActions(): {
72
57
  clear: () => void;
73
58
  clearMutations: () => void | undefined;
74
59
  };
75
- export declare function installSvadminDevtoolsBridge(): void;
76
- declare global {
77
- interface Window {
78
- __SVADMIN_DEVTOOLS__?: SvadminDevtoolsBridge;
79
- }
80
- }
60
+ /**
61
+ * Executes a shared-protocol cache action against the attached query client and
62
+ * reports how many entries matched. Only the operations svadmin implements are
63
+ * accepted; mutation-variant operations the panel never advertises throw.
64
+ */
65
+ export declare function runSvadminDevtoolsCacheAction(request: DevtoolsCacheActionRequest): Promise<DevtoolsCacheActionResult>;
66
+ export declare function installSvadminDevtoolsBridge(): DevtoolsPageBridge | null;
@@ -1,11 +1,9 @@
1
1
  import { parseQueryKey } from '@svadmin/core';
2
- import { createPageScriptChannel } from 'devframe/in-page-channel';
2
+ import { installDevtoolsPageBridge, } from '@vibeunion/devtools-devframe';
3
3
  import { DEV } from 'esm-env';
4
- export const SVADMIN_DEVFRAME_CHANNEL = 'svadmin:devtools';
5
4
  const listeners = new Set();
6
5
  let snapshot = null;
7
6
  let queryClient = null;
8
- let devframeChannel = null;
9
7
  export function publishSvadminDevtoolsSnapshot(next) {
10
8
  snapshot = next;
11
9
  for (const listener of listeners)
@@ -58,35 +56,53 @@ export function createSvadminDevtoolsCacheActions() {
58
56
  clearMutations: () => queryClient?.getMutationCache().clear(),
59
57
  };
60
58
  }
61
- export function installSvadminDevtoolsBridge() {
62
- if (typeof window === 'undefined' || !DEV)
63
- return;
64
- if (!devframeChannel) {
65
- const cache = createSvadminDevtoolsCacheActions();
66
- devframeChannel = createPageScriptChannel({
67
- name: SVADMIN_DEVFRAME_CHANNEL,
68
- functions: {
69
- getSnapshot: { type: 'query', handler: getSvadminDevtoolsSnapshot },
70
- cacheCancel: { type: 'action', handler: cache.cancel },
71
- cacheInvalidate: { type: 'action', handler: cache.invalidate },
72
- cacheRefetch: { type: 'action', handler: cache.refetch },
73
- cacheRemove: { type: 'action', handler: cache.remove },
74
- cacheReset: { type: 'action', handler: cache.reset },
75
- cacheClear: { type: 'action', handler: cache.clear },
76
- clearMutations: { type: 'action', handler: cache.clearMutations },
77
- },
78
- });
59
+ /**
60
+ * Executes a shared-protocol cache action against the attached query client and
61
+ * reports how many entries matched. Only the operations svadmin implements are
62
+ * accepted; mutation-variant operations the panel never advertises throw.
63
+ */
64
+ export async function runSvadminDevtoolsCacheAction(request) {
65
+ const { action, selector } = request;
66
+ const actions = createSvadminDevtoolsCacheActions();
67
+ let matched;
68
+ switch (action) {
69
+ case 'cancel':
70
+ matched = matchingQueryKeys(selector).length;
71
+ await actions.cancel(selector);
72
+ break;
73
+ case 'invalidate':
74
+ matched = matchingQueryKeys(selector).length;
75
+ await actions.invalidate(selector);
76
+ break;
77
+ case 'refetch':
78
+ matched = matchingQueryKeys(selector).length;
79
+ await actions.refetch(selector);
80
+ break;
81
+ case 'remove':
82
+ matched = matchingQueryKeys(selector).length;
83
+ actions.remove(selector);
84
+ break;
85
+ case 'reset':
86
+ matched = matchingQueryKeys(selector).length;
87
+ await actions.reset(selector);
88
+ break;
89
+ case 'clear':
90
+ matched = matchingQueryKeys().length;
91
+ actions.clear();
92
+ break;
93
+ case 'clearMutations':
94
+ matched = queryClient?.getMutationCache().getAll?.().length ?? 0;
95
+ actions.clearMutations();
96
+ break;
97
+ default:
98
+ throw new Error(`Unsupported svadmin cache action: ${String(action)}`);
79
99
  }
80
- const bridge = {
100
+ return { action, matched, changed: matched };
101
+ }
102
+ export function installSvadminDevtoolsBridge() {
103
+ return installDevtoolsPageBridge({
104
+ development: DEV,
81
105
  getSnapshot: getSvadminDevtoolsSnapshot,
82
- subscribe: subscribeSvadminDevtools,
83
- cache: createSvadminDevtoolsCacheActions(),
84
- devframe: { channelName: SVADMIN_DEVFRAME_CHANNEL },
85
- };
86
- Object.defineProperty(window, '__SVADMIN_DEVTOOLS__', {
87
- configurable: true,
88
- enumerable: false,
89
- value: bridge,
90
- writable: false,
106
+ cacheAction: runSvadminDevtoolsCacheAction,
91
107
  });
92
108
  }
package/dist/index.d.ts CHANGED
@@ -36,6 +36,8 @@ export { default as StatsCard } from './components/StatsCard.svelte';
36
36
  export { default as MetricStrip } from './components/MetricStrip.svelte';
37
37
  export type { MetricStripItem, MetricTone } from './components/MetricStrip.svelte';
38
38
  export { default as PageHeader } from './components/PageHeader.svelte';
39
+ export { default as PagePattern } from './components/PagePattern.svelte';
40
+ export type { PagePatternKind } from './components/PagePattern.svelte';
39
41
  export { default as ResourceOperationsPage } from './components/ResourceOperationsPage.svelte';
40
42
  export { default as RecordDetailDrawer } from './components/RecordDetailDrawer.svelte';
41
43
  export { default as ResourceAccessGuard } from './components/ResourceAccessGuard.svelte';
@@ -48,8 +50,9 @@ export { default as Can } from './components/CanAccess.svelte';
48
50
  export { default as UndoableNotification } from './components/UndoableNotification.svelte';
49
51
  export { default as DevTools } from './components/DevTools.svelte';
50
52
  export { default as DevframePanel } from './components/DevframePanel.svelte';
51
- export { attachSvadminDevtoolsQueryClient, createSvadminDevtoolsCacheActions, getSvadminDevtoolsSnapshot, installSvadminDevtoolsBridge, publishSvadminDevtoolsSnapshot, subscribeSvadminDevtools, SVADMIN_DEVFRAME_CHANNEL, } from './devtools-bridge.js';
52
- export type { DevtoolsCacheDiagnostics, DevtoolsProviderDiagnostic, DevtoolsQueryDiagnostic, SvadminDevtoolsBridge, SvadminDevtoolsSnapshot, DevtoolsQuerySelector, SvadminDevframeProtocol, } from './devtools-bridge.js';
53
+ export { attachSvadminDevtoolsQueryClient, createSvadminDevtoolsCacheActions, getSvadminDevtoolsSnapshot, installSvadminDevtoolsBridge, publishSvadminDevtoolsSnapshot, runSvadminDevtoolsCacheAction, subscribeSvadminDevtools, } from './devtools-bridge.js';
54
+ export type { DevtoolsCacheDiagnostics, DevtoolsProviderDiagnostic, DevtoolsQueryDiagnostic, SvadminDevtoolsSnapshot, DevtoolsQuerySelector, SvadminDevframeProtocol, } from './devtools-bridge.js';
55
+ export type { DevtoolsPageBridge } from '@vibeunion/devtools-devframe';
53
56
  export { default as Authenticated } from './components/Authenticated.svelte';
54
57
  export { default as UpdatePasswordPage } from './components/UpdatePasswordPage.svelte';
55
58
  export { default as ProfilePage } from './components/ProfilePage.svelte';
@@ -275,6 +278,7 @@ export { default as ContentPageShell } from './components/content/ContentPageShe
275
278
  export { default as DashboardPage } from './components/content/DashboardPage.svelte';
276
279
  export { default as PageSection } from './components/content/PageSection.svelte';
277
280
  export { default as ContentPageHeader } from './components/content/ContentPageHeader.svelte';
281
+ export { default as ConfigurationPage } from './components/ConfigurationPage.svelte';
278
282
  export { default as SectionHeader } from './components/content/SectionHeader.svelte';
279
283
  export { default as PageToolbar } from './components/content/PageToolbar.svelte';
280
284
  export { default as WorkspaceLayout } from './components/content/WorkspaceLayout.svelte';
package/dist/index.js CHANGED
@@ -30,6 +30,7 @@ export { default as EmptyState } from './components/EmptyState.svelte';
30
30
  export { default as StatsCard } from './components/StatsCard.svelte';
31
31
  export { default as MetricStrip } from './components/MetricStrip.svelte';
32
32
  export { default as PageHeader } from './components/PageHeader.svelte';
33
+ export { default as PagePattern } from './components/PagePattern.svelte';
33
34
  export { default as ResourceOperationsPage } from './components/ResourceOperationsPage.svelte';
34
35
  export { default as RecordDetailDrawer } from './components/RecordDetailDrawer.svelte';
35
36
  export { default as ResourceAccessGuard } from './components/ResourceAccessGuard.svelte';
@@ -42,7 +43,7 @@ export { default as Can } from './components/CanAccess.svelte';
42
43
  export { default as UndoableNotification } from './components/UndoableNotification.svelte';
43
44
  export { default as DevTools } from './components/DevTools.svelte';
44
45
  export { default as DevframePanel } from './components/DevframePanel.svelte';
45
- export { attachSvadminDevtoolsQueryClient, createSvadminDevtoolsCacheActions, getSvadminDevtoolsSnapshot, installSvadminDevtoolsBridge, publishSvadminDevtoolsSnapshot, subscribeSvadminDevtools, SVADMIN_DEVFRAME_CHANNEL, } from './devtools-bridge.js';
46
+ export { attachSvadminDevtoolsQueryClient, createSvadminDevtoolsCacheActions, getSvadminDevtoolsSnapshot, installSvadminDevtoolsBridge, publishSvadminDevtoolsSnapshot, runSvadminDevtoolsCacheAction, subscribeSvadminDevtools, } from './devtools-bridge.js';
46
47
  export { default as Authenticated } from './components/Authenticated.svelte';
47
48
  export { default as UpdatePasswordPage } from './components/UpdatePasswordPage.svelte';
48
49
  export { default as ProfilePage } from './components/ProfilePage.svelte';
@@ -245,6 +246,7 @@ export { default as ContentPageShell } from './components/content/ContentPageShe
245
246
  export { default as DashboardPage } from './components/content/DashboardPage.svelte';
246
247
  export { default as PageSection } from './components/content/PageSection.svelte';
247
248
  export { default as ContentPageHeader } from './components/content/ContentPageHeader.svelte';
249
+ export { default as ConfigurationPage } from './components/ConfigurationPage.svelte';
248
250
  export { default as SectionHeader } from './components/content/SectionHeader.svelte';
249
251
  export { default as PageToolbar } from './components/content/PageToolbar.svelte';
250
252
  export { default as WorkspaceLayout } from './components/content/WorkspaceLayout.svelte';
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@svadmin/ui",
3
- "version": "0.79.0",
3
+ "version": "0.81.0",
4
4
  "description": "Pre-built admin UI components — AdminApp, AutoTable, AutoForm, Sidebar, Layout",
5
5
  "type": "module",
6
6
  "sideEffects": [
@@ -139,7 +139,8 @@
139
139
  }
140
140
  },
141
141
  "dependencies": {
142
- "@svadmin/devtools-contract": "^0.2.0",
142
+ "@svadmin/devtools-contract": "^0.3.0",
143
+ "@vibeunion/devtools-devframe": "^0.1.0",
143
144
  "@sinclair/typebox": "^0.34.52",
144
145
  "@floating-ui/dom": "^1.8.0",
145
146
  "esm-env": "^1.2.2",