@meddleware/ui 0.1.8 → 0.1.10

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -53,6 +53,24 @@ All three accept a `variant` prop:
53
53
  | `UiSelect` | Styled select input. |
54
54
  | `UiNotice` | Notice / alert banner. |
55
55
  | `SidebarItem` | Navigation button for use inside `AppSidebar`. Accepts `label`, `icon`, `active`, and `disabled` props. |
56
+ | `CopyableAddress` | Shows a value (address/blob id/tx digest) with a dedicated **copy icon** (the value text is not the copy trigger). Put a link in the default slot to make it both linkable and copyable. Props: `address`, `truncate`, `chars`, `label`. |
57
+ | `ExplorerLink` | External block-explorer link with a truncated label (or slot). Chain-agnostic — pass `href` (build it with `suiExplorerUrl`, or an app helper such as a Walruscan URL). Nest inside `CopyableAddress` for link + copy. |
58
+
59
+ Copy + link compose — nest `ExplorerLink` in `CopyableAddress` so the value links out while the
60
+ icon copies:
61
+
62
+ ```vue
63
+ <CopyableAddress :address="addr">
64
+ <ExplorerLink :href="suiExplorerUrl('account', addr, 'testnet')" :value="addr" />
65
+ </CopyableAddress>
66
+ ```
67
+
68
+ ### Explorer helper
69
+
70
+ | Export | Type | Description |
71
+ | --- | --- | --- |
72
+ | `suiExplorerUrl(kind, id, network?)` | Function | Builds a SuiVision URL. `kind`: `'account' \| 'object' \| 'txblock'`; `network` defaults to `'testnet'`. Single source of truth for Sui explorer links. |
73
+ | `SuiNetwork`, `SuiExplorerKind` | Types | `'mainnet' \| 'testnet' \| 'devnet'` and the link kinds. |
56
74
 
57
75
  ### Colour mode
58
76
 
package/dist/base.css CHANGED
@@ -1,2 +1,2 @@
1
- .mw-header[data-v-ad7cd1c5]{height:var(--mw-header-height,56px);background:var(--_bg);color:var(--_text);border-bottom:1px solid var(--_border);font-family:var(--mw-font-sans);align-items:center;gap:1rem;padding:0 1rem;display:flex}.mw-header--sticky[data-v-ad7cd1c5]{z-index:50;position:sticky;top:0}.mw-header__brand[data-v-ad7cd1c5]{letter-spacing:.01em;white-space:nowrap;align-items:center;gap:.5rem;font-weight:650;display:flex}.mw-header__center[data-v-ad7cd1c5]{flex:auto;min-width:0}.mw-header__actions[data-v-ad7cd1c5]{align-items:center;gap:.5rem;margin-left:auto;display:flex}.mw-sidebar[data-v-0e0c098e]{width:var(--mw-sidebar-width,240px);background:var(--_bg);color:var(--_text);border-right:1px solid var(--_border);font-family:var(--mw-font-sans);flex-direction:column;display:flex}.mw-sidebar__head[data-v-0e0c098e]{border-bottom:1px solid var(--_border);padding:1rem}.mw-sidebar__nav[data-v-0e0c098e]{flex-direction:column;flex:auto;gap:.25rem;padding:.75rem;display:flex;overflow-y:auto}.mw-sidebar__body[data-v-0e0c098e]{flex-shrink:0}.mw-sidebar__foot[data-v-0e0c098e]{border-top:1px solid var(--_border);color:var(--_muted);padding:.75rem 1rem;font-size:.85rem}.mw-footer[data-v-c646b8e1]{background:var(--_bg);color:var(--_muted);border-top:1px solid var(--_border);font-family:var(--mw-font-sans);flex-wrap:wrap;align-items:center;gap:1rem;padding:.75rem 1rem;font-size:.85rem;display:flex}.mw-footer--transparent[data-v-c646b8e1]{border-top:1px solid var(--border)}.mw-footer__center[data-v-c646b8e1]{flex:auto;min-width:0}.mw-footer__end[data-v-c646b8e1]{margin-left:auto}.mw-mode[data-v-e4a6bf1d]{border:1px solid var(--_border,var(--border));border-radius:var(--mw-radius,10px);background:color-mix(in srgb, var(--_text,var(--text)) 6%, transparent);gap:2px;padding:2px;display:inline-flex}.mw-mode__btn[data-v-e4a6bf1d]{border-radius:calc(var(--mw-radius,10px) - 3px);color:var(--_text,var(--text));font:inherit;cursor:pointer;opacity:.7;background:0 0;border:0;align-items:center;gap:.35rem;padding:.25rem .5rem;font-size:.8rem;display:inline-flex}.mw-mode__btn[data-v-e4a6bf1d]:hover{opacity:1}.mw-mode__btn.is-active[data-v-e4a6bf1d]{opacity:1;background:color-mix(in srgb, var(--_text,var(--text)) 14%, transparent)}.mw-mode__btn[data-v-e4a6bf1d]:focus-visible{outline:2px solid var(--accent);outline-offset:1px}@media (width<=640px){.mw-mode__label[data-v-e4a6bf1d]{display:none}}.mw-btn[data-v-299de2c3]{border-radius:var(--mw-radius,10px);font:inherit;cursor:pointer;border:1px solid #0000;justify-content:center;align-items:center;gap:.4rem;padding:.5rem .9rem;font-weight:550;transition:filter .12s,background .12s;display:inline-flex}.mw-btn[data-v-299de2c3]:disabled{opacity:.55;cursor:not-allowed}.mw-btn[data-v-299de2c3]:focus-visible{outline:2px solid var(--accent);outline-offset:2px}.mw-btn--primary[data-v-299de2c3]{background:var(--accent);color:var(--accent-contrast)}.mw-btn--primary[data-v-299de2c3]:not(:disabled):hover{filter:brightness(1.08)}.mw-btn--secondary[data-v-299de2c3]{background:var(--secondary);color:var(--secondary-contrast)}.mw-btn--secondary[data-v-299de2c3]:not(:disabled):hover{filter:brightness(1.08)}.mw-btn--ghost[data-v-299de2c3]{color:var(--text);border-color:var(--border);background:0 0}.mw-btn--ghost[data-v-299de2c3]:not(:disabled):hover{background:var(--lift)}.mw-btn--danger[data-v-299de2c3]{background:var(--danger);color:var(--mw-neutral-000)}.mw-btn--danger[data-v-299de2c3]:not(:disabled):hover{filter:brightness(1.08)}.mw-card[data-v-fd2fd7ab]{background:var(--surface);border:1px solid var(--border);border-radius:var(--mw-radius,10px);color:var(--text);overflow:hidden}.mw-card__header[data-v-fd2fd7ab]{border-bottom:1px solid var(--border);padding:.85rem 1rem}.mw-card__title[data-v-fd2fd7ab]{margin:0;font-size:1rem;font-weight:600}.mw-card__body[data-v-fd2fd7ab]{padding:1rem}.mw-card__footer[data-v-fd2fd7ab]{border-top:1px solid var(--border);background:var(--lift);padding:.75rem 1rem}.mw-select[data-v-b9468387]{position:relative}.mw-select select[data-v-b9468387]{appearance:none;background:var(--surface);width:100%;color:var(--text);border:1px solid var(--border);border-radius:var(--mw-radius,10px);font:inherit;padding:.5rem 2.5rem .5rem .7rem}.mw-select select[data-v-b9468387]:focus-visible{outline:2px solid var(--accent);outline-offset:1px}.mw-select__chevron[data-v-b9468387]{pointer-events:none;stroke:var(--muted);stroke-width:1.5px;fill:none;position:absolute;top:50%;right:.75rem;transform:translateY(-50%)}.mw-notice[data-v-6f53d0be]{border:1px solid var(--border);border-radius:var(--mw-radius,10px);background:var(--lift);color:var(--text);border-left-width:3px;margin:0;padding:.6rem .8rem;font-size:.9rem}.mw-notice--error[data-v-6f53d0be]{border-left-color:var(--danger);color:var(--danger);background:color-mix(in srgb, var(--danger) 8%, transparent)}.mw-notice--ok[data-v-6f53d0be]{border-left-color:var(--ok);color:var(--ok);background:color-mix(in srgb, var(--ok) 8%, transparent)}.sidebar-item[data-v-e15afdf7]{border-radius:var(--mw-radius,10px);width:100%;color:inherit;font:inherit;text-align:left;cursor:pointer;opacity:.85;background:0 0;border:0;align-items:center;gap:.6rem;padding:.55rem .7rem;display:flex}.sidebar-item[data-v-e15afdf7]:hover:not(:disabled){background:color-mix(in srgb, currentColor 10%, transparent);opacity:1}.sidebar-item.is-active[data-v-e15afdf7]{background:color-mix(in srgb, var(--accent) 26%, transparent);opacity:1}.sidebar-item[data-v-e15afdf7]:disabled{cursor:default}.sidebar-item[data-v-e15afdf7]:focus-visible{outline:2px solid var(--accent);outline-offset:1px}.sidebar-item__icon[data-v-e15afdf7]{text-align:center;width:1.1rem}.ca-root[data-v-e2d23de9]{font-family:monospace;font-size:inherit;color:var(--muted,#888);cursor:pointer;text-underline-offset:2px;background:0 0;border:none;padding:0;-webkit-text-decoration:underline dotted;text-decoration:underline dotted;transition:color .15s;display:inline-block}.ca-root[data-v-e2d23de9]:hover{color:var(--text,#f0f0f0)}.ca-root--copied[data-v-e2d23de9]{color:var(--accent,#6366f1);text-decoration:none}.status-widget[data-v-20197983]{color:inherit;opacity:.85;align-items:center;gap:.4rem;font-size:.8rem;text-decoration:none;display:inline-flex}.status-widget[data-v-20197983]:hover{opacity:1}.status-widget__dot[data-v-20197983]{border-radius:50%;flex-shrink:0;width:.55rem;height:.55rem}.status-widget--ok .status-widget__dot[data-v-20197983]{background:var(--mw-ok-500)}.status-widget--degraded .status-widget__dot[data-v-20197983]{background:var(--mw-gold-500)}.status-widget--error .status-widget__dot[data-v-20197983]{background:var(--mw-danger-500)}
1
+ *,:before,:after{box-sizing:border-box}html,body{margin:0;padding:0}body{background:var(--bg);min-height:100vh;color:var(--text);font-family:var(--mw-font-sans);-webkit-font-smoothing:antialiased;text-rendering:optimizelegibility;font-size:16px;line-height:1.55}:where(ul,ol):where([role=list],[role=listitem]){margin:0;padding:0;list-style:none}:where(img,svg,video,canvas){max-width:100%;display:block}:where(fieldset){border:0;margin:0;padding:0}a{color:var(--accent);text-decoration:none}a:hover{text-decoration:underline}:where(button,input,select,textarea){font-family:inherit}:where(a,button,input,select,textarea):focus-visible{outline:2px solid var(--accent);outline-offset:2px}.mw-mono{font-family:var(--mw-font-mono)}@media (prefers-reduced-motion:reduce){*,:before,:after{transition-duration:.001ms!important;animation-duration:.001ms!important}}.mw-header[data-v-ad7cd1c5]{height:var(--mw-header-height,56px);background:var(--_bg);color:var(--_text);border-bottom:1px solid var(--_border);font-family:var(--mw-font-sans);align-items:center;gap:1rem;padding:0 1rem;display:flex}.mw-header--sticky[data-v-ad7cd1c5]{z-index:50;position:sticky;top:0}.mw-header__brand[data-v-ad7cd1c5]{letter-spacing:.01em;white-space:nowrap;align-items:center;gap:.5rem;font-weight:650;display:flex}.mw-header__center[data-v-ad7cd1c5]{flex:auto;min-width:0}.mw-header__actions[data-v-ad7cd1c5]{align-items:center;gap:.5rem;margin-left:auto;display:flex}.mw-sidebar[data-v-23c3c7f3]{height:100%;width:var(--mw-sidebar-width,240px);background:var(--_bg);color:var(--_text);border-right:1px solid var(--_border);font-family:var(--mw-font-sans);flex-direction:column;display:flex}.mw-sidebar__head[data-v-23c3c7f3]{border-bottom:1px solid var(--_border);padding:1rem}.mw-sidebar__nav[data-v-23c3c7f3]{flex-direction:column;flex:auto;gap:.25rem;padding:.75rem;display:flex;overflow-y:auto}.mw-sidebar__body[data-v-23c3c7f3]{flex-shrink:0}.mw-sidebar__foot[data-v-23c3c7f3]{border-top:1px solid var(--_border);color:var(--_muted);padding:.75rem 1rem;font-size:.85rem}.mw-footer[data-v-c646b8e1]{background:var(--_bg);color:var(--_muted);border-top:1px solid var(--_border);font-family:var(--mw-font-sans);flex-wrap:wrap;align-items:center;gap:1rem;padding:.75rem 1rem;font-size:.85rem;display:flex}.mw-footer--transparent[data-v-c646b8e1]{border-top:1px solid var(--border)}.mw-footer__center[data-v-c646b8e1]{flex:auto;min-width:0}.mw-footer__end[data-v-c646b8e1]{margin-left:auto}.mw-mode[data-v-186f8312]{border:1px solid var(--_border,var(--border));border-radius:var(--mw-radius,10px);background:color-mix(in srgb, var(--_text,var(--text)) 6%, transparent);gap:2px;padding:2px;display:inline-flex}.mw-mode__btn[data-v-186f8312]{border-radius:calc(var(--mw-radius,10px) - 3px);color:var(--_text,var(--text));font:inherit;cursor:pointer;opacity:.7;background:0 0;border:0;align-items:center;gap:.35rem;padding:.25rem .5rem;font-size:.8rem;display:inline-flex}.mw-mode__btn[data-v-186f8312]:hover{opacity:1}.mw-mode__btn.is-active[data-v-186f8312]{opacity:1;background:color-mix(in srgb, var(--_text,var(--text)) 14%, transparent)}.mw-mode__btn[data-v-186f8312]:focus-visible{outline:2px solid var(--accent);outline-offset:1px}@media (width<=640px){.mw-mode__label[data-v-186f8312]{display:none}}.mw-btn[data-v-299de2c3]{border-radius:var(--mw-radius,10px);font:inherit;cursor:pointer;border:1px solid #0000;justify-content:center;align-items:center;gap:.4rem;padding:.5rem .9rem;font-weight:550;transition:filter .12s,background .12s;display:inline-flex}.mw-btn[data-v-299de2c3]:disabled{opacity:.55;cursor:not-allowed}.mw-btn[data-v-299de2c3]:focus-visible{outline:2px solid var(--accent);outline-offset:2px}.mw-btn--primary[data-v-299de2c3]{background:var(--accent);color:var(--accent-contrast)}.mw-btn--primary[data-v-299de2c3]:not(:disabled):hover{filter:brightness(1.08)}.mw-btn--secondary[data-v-299de2c3]{background:var(--secondary);color:var(--secondary-contrast)}.mw-btn--secondary[data-v-299de2c3]:not(:disabled):hover{filter:brightness(1.08)}.mw-btn--ghost[data-v-299de2c3]{color:var(--text);border-color:var(--border);background:0 0}.mw-btn--ghost[data-v-299de2c3]:not(:disabled):hover{background:var(--lift)}.mw-btn--danger[data-v-299de2c3]{background:var(--danger);color:var(--mw-neutral-000)}.mw-btn--danger[data-v-299de2c3]:not(:disabled):hover{filter:brightness(1.08)}.mw-card[data-v-fd2fd7ab]{background:var(--surface);border:1px solid var(--border);border-radius:var(--mw-radius,10px);color:var(--text);overflow:hidden}.mw-card__header[data-v-fd2fd7ab]{border-bottom:1px solid var(--border);padding:.85rem 1rem}.mw-card__title[data-v-fd2fd7ab]{margin:0;font-size:1rem;font-weight:600}.mw-card__body[data-v-fd2fd7ab]{padding:1rem}.mw-card__footer[data-v-fd2fd7ab]{border-top:1px solid var(--border);background:var(--lift);padding:.75rem 1rem}.mw-select[data-v-b9468387]{position:relative}.mw-select select[data-v-b9468387]{appearance:none;background:var(--surface);width:100%;color:var(--text);border:1px solid var(--border);border-radius:var(--mw-radius,10px);font:inherit;padding:.5rem 2.5rem .5rem .7rem}.mw-select select[data-v-b9468387]:focus-visible{outline:2px solid var(--accent);outline-offset:1px}.mw-select__chevron[data-v-b9468387]{pointer-events:none;stroke:var(--muted);stroke-width:1.5px;fill:none;position:absolute;top:50%;right:.75rem;transform:translateY(-50%)}.mw-notice[data-v-6f53d0be]{border:1px solid var(--border);border-radius:var(--mw-radius,10px);background:var(--lift);color:var(--text);border-left-width:3px;margin:0;padding:.6rem .8rem;font-size:.9rem}.mw-notice--error[data-v-6f53d0be]{border-left-color:var(--danger);color:var(--danger);background:color-mix(in srgb, var(--danger) 8%, transparent)}.mw-notice--ok[data-v-6f53d0be]{border-left-color:var(--ok);color:var(--ok);background:color-mix(in srgb, var(--ok) 8%, transparent)}.sidebar-item[data-v-e15afdf7]{border-radius:var(--mw-radius,10px);width:100%;color:inherit;font:inherit;text-align:left;cursor:pointer;opacity:.85;background:0 0;border:0;align-items:center;gap:.6rem;padding:.55rem .7rem;display:flex}.sidebar-item[data-v-e15afdf7]:hover:not(:disabled){background:color-mix(in srgb, currentColor 10%, transparent);opacity:1}.sidebar-item.is-active[data-v-e15afdf7]{background:color-mix(in srgb, var(--accent) 26%, transparent);opacity:1}.sidebar-item[data-v-e15afdf7]:disabled{cursor:default}.sidebar-item[data-v-e15afdf7]:focus-visible{outline:2px solid var(--accent);outline-offset:1px}.sidebar-item__icon[data-v-e15afdf7]{text-align:center;width:1.1rem}.ca-root[data-v-08c3420b]{align-items:center;gap:.35em;display:inline-flex}.ca-value[data-v-08c3420b]{font-family:monospace;font-size:inherit}.ca-copy[data-v-08c3420b]{color:var(--muted,#888);cursor:pointer;background:0 0;border:none;justify-content:center;align-items:center;padding:0;line-height:1;transition:color .15s;display:inline-flex}.ca-copy[data-v-08c3420b]:hover{color:var(--text,#f0f0f0)}.ca-copy--copied[data-v-08c3420b]{color:var(--accent,#6366f1)}.ca-icon[data-v-08c3420b]{display:block}.el-root[data-v-7a44607e]{font-family:monospace;font-size:inherit;color:var(--accent,#6366f1);text-underline-offset:2px;-webkit-text-decoration:underline dotted;text-decoration:underline dotted;transition:color .15s}.el-root[data-v-7a44607e]:hover{color:var(--text,#f0f0f0);text-decoration-style:solid}.status-widget[data-v-20197983]{color:inherit;opacity:.85;align-items:center;gap:.4rem;font-size:.8rem;text-decoration:none;display:inline-flex}.status-widget[data-v-20197983]:hover{opacity:1}.status-widget__dot[data-v-20197983]{border-radius:50%;flex-shrink:0;width:.55rem;height:.55rem}.status-widget--ok .status-widget__dot[data-v-20197983]{background:var(--mw-ok-500)}.status-widget--degraded .status-widget__dot[data-v-20197983]{background:var(--mw-gold-500)}.status-widget--error .status-widget__dot[data-v-20197983]{background:var(--mw-danger-500)}
2
2
  /*$vite$:1*/
@@ -1,13 +1,27 @@
1
1
  type __VLS_Props = {
2
+ /** The full value to copy (and to truncate for the default label). */
2
3
  address: string;
3
- /** Show prefix…suffix truncation (default true). Full address shown in title attribute always. */
4
+ /** Prefix…suffix truncation for the default label (default true). Ignored when a slot is given. */
4
5
  truncate?: boolean;
5
- /** [prefixChars, suffixChars] — only used when truncate is true. */
6
+ /** [prefixChars, suffixChars] — only used for the default label when truncate is true. */
6
7
  chars?: [number, number];
8
+ /** Accessible label / tooltip for the copy button (default "Copy"). */
9
+ label?: string;
7
10
  };
8
- declare const __VLS_export: import("vue").DefineComponent<__VLS_Props, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").PublicProps, Readonly<__VLS_Props> & Readonly<{}>, {
11
+ declare var __VLS_1: {};
12
+ type __VLS_Slots = {} & {
13
+ default?: (props: typeof __VLS_1) => any;
14
+ };
15
+ declare const __VLS_base: import("vue").DefineComponent<__VLS_Props, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").PublicProps, Readonly<__VLS_Props> & Readonly<{}>, {
16
+ label: string;
9
17
  truncate: boolean;
10
18
  chars: [number, number];
11
19
  }, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
20
+ declare const __VLS_export: __VLS_WithSlots<typeof __VLS_base, __VLS_Slots>;
12
21
  declare const _default: typeof __VLS_export;
13
22
  export default _default;
23
+ type __VLS_WithSlots<T, S> = T & {
24
+ new (): {
25
+ $slots: S;
26
+ };
27
+ };
@@ -0,0 +1,26 @@
1
+ type __VLS_Props = {
2
+ /** Destination URL (opens in a new tab). */
3
+ href: string;
4
+ /** Value used for the truncated label + title; omit when providing slot content. */
5
+ value?: string;
6
+ /** Prefix…suffix truncation of `value` (default true). */
7
+ truncate?: boolean;
8
+ /** [prefixChars, suffixChars] — only used when truncate is true. */
9
+ chars?: [number, number];
10
+ };
11
+ declare var __VLS_1: {};
12
+ type __VLS_Slots = {} & {
13
+ default?: (props: typeof __VLS_1) => any;
14
+ };
15
+ declare const __VLS_base: import("vue").DefineComponent<__VLS_Props, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").PublicProps, Readonly<__VLS_Props> & Readonly<{}>, {
16
+ truncate: boolean;
17
+ chars: [number, number];
18
+ }, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
19
+ declare const __VLS_export: __VLS_WithSlots<typeof __VLS_base, __VLS_Slots>;
20
+ declare const _default: typeof __VLS_export;
21
+ export default _default;
22
+ type __VLS_WithSlots<T, S> = T & {
23
+ new (): {
24
+ $slots: S;
25
+ };
26
+ };
@@ -7,8 +7,8 @@ type __VLS_Props = {
7
7
  pollInterval?: number;
8
8
  };
9
9
  declare const __VLS_export: import("vue").DefineComponent<__VLS_Props, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").PublicProps, Readonly<__VLS_Props> & Readonly<{}>, {
10
- apiUrl: string;
11
10
  href: string;
11
+ apiUrl: string;
12
12
  pollInterval: number;
13
13
  }, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
14
14
  declare const _default: typeof __VLS_export;
@@ -0,0 +1,13 @@
1
+ /** Sui networks SuiVision serves. */
2
+ export type SuiNetwork = 'mainnet' | 'testnet' | 'devnet';
3
+ /** The kind of Sui entity to link, mapped to SuiVision's URL path segment. */
4
+ export type SuiExplorerKind = 'account' | 'object' | 'txblock';
5
+ /**
6
+ * Build a SuiVision explorer URL for a Sui entity.
7
+ *
8
+ * @param kind - `account` (address), `object`, or `txblock` (transaction digest).
9
+ * @param id - The address / object id / transaction digest.
10
+ * @param network - Target network (default `testnet`).
11
+ * @returns The full SuiVision URL, e.g. `https://testnet.suivision.xyz/account/0x…`.
12
+ */
13
+ export declare function suiExplorerUrl(kind: SuiExplorerKind, id: string, network?: SuiNetwork): string;
package/dist/index.d.ts CHANGED
@@ -1,3 +1,4 @@
1
+ import './styles/base.css';
1
2
  export { default as AppHeader } from './components/AppHeader.vue';
2
3
  export { default as AppSidebar } from './components/AppSidebar.vue';
3
4
  export { default as AppFooter } from './components/AppFooter.vue';
@@ -8,7 +9,10 @@ export { default as UiSelect } from './components/UiSelect.vue';
8
9
  export { default as UiNotice } from './components/UiNotice.vue';
9
10
  export { default as SidebarItem } from './components/SidebarItem.vue';
10
11
  export { default as CopyableAddress } from './components/CopyableAddress.vue';
12
+ export { default as ExplorerLink } from './components/ExplorerLink.vue';
11
13
  export { default as StatusWidget } from './components/StatusWidget.vue';
14
+ export { suiExplorerUrl } from './explorer.js';
15
+ export type { SuiNetwork, SuiExplorerKind } from './explorer.js';
12
16
  export { useColorMode } from './composables/useColorMode.js';
13
17
  export type { ColorMode } from './composables/useColorMode.js';
14
18
  export type { PanelVariant, PanelColors } from './internal/panel.js';
package/dist/ui.js CHANGED
@@ -1,6 +1,6 @@
1
- import { Fragment as e, computed as t, createCommentVNode as n, createElementBlock as r, createElementVNode as i, defineComponent as a, mergeProps as o, normalizeClass as s, normalizeStyle as c, onMounted as l, onUnmounted as u, openBlock as d, ref as f, renderList as p, renderSlot as m, toDisplayString as h, useModel as ee, vModelSelect as te, watch as ne, withDirectives as g } from "vue";
1
+ import { Fragment as e, computed as t, createCommentVNode as n, createElementBlock as r, createElementVNode as i, createTextVNode as a, defineComponent as o, mergeProps as s, normalizeClass as c, normalizeStyle as l, onMounted as u, onUnmounted as ee, openBlock as d, ref as f, renderList as p, renderSlot as m, toDisplayString as h, useModel as te, vModelSelect as ne, watch as re, withDirectives as ie } from "vue";
2
2
  //#region src/internal/panel.ts
3
- function _(e, t) {
3
+ function g(e, t) {
4
4
  let n;
5
5
  return n = e === "transparent" ? {
6
6
  "--_bg": "transparent",
@@ -24,7 +24,7 @@ function _(e, t) {
24
24
  }
25
25
  //#endregion
26
26
  //#region src/components/AppHeader.vue?vue&type=script&setup=true&lang.ts
27
- var re = { class: "mw-header__brand" }, ie = { class: "mw-header__center" }, ae = { class: "mw-header__actions" }, oe = /*@__PURE__*/ a({
27
+ var ae = { class: "mw-header__brand" }, oe = { class: "mw-header__center" }, se = { class: "mw-header__actions" }, ce = /*@__PURE__*/ o({
28
28
  __name: "AppHeader",
29
29
  props: {
30
30
  variant: { default: "dark" },
@@ -35,33 +35,33 @@ var re = { class: "mw-header__brand" }, ie = { class: "mw-header__center" }, ae
35
35
  }
36
36
  },
37
37
  setup(e) {
38
- let n = e, a = t(() => _(n.variant, n.colors));
38
+ let n = e, a = t(() => g(n.variant, n.colors));
39
39
  return (t, n) => (d(), r("header", {
40
- class: s(["mw-header", [`mw-header--${e.variant}`, { "mw-header--sticky": e.sticky }]]),
41
- style: c(a.value)
40
+ class: c(["mw-header", [`mw-header--${e.variant}`, { "mw-header--sticky": e.sticky }]]),
41
+ style: l(a.value)
42
42
  }, [
43
- i("div", re, [m(t.$slots, "brand", {}, void 0, !0)]),
44
- i("div", ie, [m(t.$slots, "default", {}, void 0, !0)]),
45
- i("div", ae, [m(t.$slots, "actions", {}, void 0, !0)])
43
+ i("div", ae, [m(t.$slots, "brand", {}, void 0, !0)]),
44
+ i("div", oe, [m(t.$slots, "default", {}, void 0, !0)]),
45
+ i("div", se, [m(t.$slots, "actions", {}, void 0, !0)])
46
46
  ], 6));
47
47
  }
48
- }), v = (e, t) => {
48
+ }), _ = (e, t) => {
49
49
  let n = e.__vccOpts || e;
50
50
  for (let [e, r] of t) n[e] = r;
51
51
  return n;
52
- }, y = /*#__PURE__*/ v(oe, [["__scopeId", "data-v-ad7cd1c5"]]), b = {
52
+ }, v = /*#__PURE__*/ _(ce, [["__scopeId", "data-v-ad7cd1c5"]]), y = {
53
53
  key: 0,
54
54
  class: "mw-sidebar__head"
55
- }, x = {
55
+ }, b = {
56
56
  class: "mw-sidebar__nav",
57
57
  "aria-label": "Primary"
58
- }, S = {
58
+ }, x = {
59
59
  key: 1,
60
60
  class: "mw-sidebar__body"
61
- }, C = {
61
+ }, S = {
62
62
  key: 2,
63
63
  class: "mw-sidebar__foot"
64
- }, w = /*#__PURE__*/ v(/* @__PURE__ */ a({
64
+ }, C = /*#__PURE__*/ _(/* @__PURE__ */ o({
65
65
  __name: "AppSidebar",
66
66
  props: {
67
67
  variant: { default: "dark" },
@@ -70,45 +70,45 @@ var re = { class: "mw-header__brand" }, ie = { class: "mw-header__center" }, ae
70
70
  },
71
71
  setup(e) {
72
72
  let a = e, o = t(() => {
73
- let e = _(a.variant, a.colors);
73
+ let e = g(a.variant, a.colors);
74
74
  return a.width && (e["--mw-sidebar-width"] = a.width), e;
75
75
  });
76
76
  return (t, a) => (d(), r("aside", {
77
- class: s(["mw-sidebar", `mw-sidebar--${e.variant}`]),
78
- style: c(o.value)
77
+ class: c(["mw-sidebar", `mw-sidebar--${e.variant}`]),
78
+ style: l(o.value)
79
79
  }, [
80
- t.$slots.head ? (d(), r("div", b, [m(t.$slots, "head", {}, void 0, !0)])) : n("", !0),
81
- i("nav", x, [m(t.$slots, "default", {}, void 0, !0)]),
82
- t.$slots.body ? (d(), r("div", S, [m(t.$slots, "body", {}, void 0, !0)])) : n("", !0),
83
- t.$slots.foot ? (d(), r("div", C, [m(t.$slots, "foot", {}, void 0, !0)])) : n("", !0)
80
+ t.$slots.head ? (d(), r("div", y, [m(t.$slots, "head", {}, void 0, !0)])) : n("", !0),
81
+ i("nav", b, [m(t.$slots, "default", {}, void 0, !0)]),
82
+ t.$slots.body ? (d(), r("div", x, [m(t.$slots, "body", {}, void 0, !0)])) : n("", !0),
83
+ t.$slots.foot ? (d(), r("div", S, [m(t.$slots, "foot", {}, void 0, !0)])) : n("", !0)
84
84
  ], 6));
85
85
  }
86
- }), [["__scopeId", "data-v-0e0c098e"]]), T = { class: "mw-footer__start" }, E = { class: "mw-footer__center" }, D = { class: "mw-footer__end" }, O = /*#__PURE__*/ v(/* @__PURE__ */ a({
86
+ }), [["__scopeId", "data-v-23c3c7f3"]]), w = { class: "mw-footer__start" }, T = { class: "mw-footer__center" }, E = { class: "mw-footer__end" }, D = /*#__PURE__*/ _(/* @__PURE__ */ o({
87
87
  __name: "AppFooter",
88
88
  props: {
89
89
  variant: { default: "transparent" },
90
90
  colors: {}
91
91
  },
92
92
  setup(e) {
93
- let n = e, a = t(() => _(n.variant, n.colors));
93
+ let n = e, a = t(() => g(n.variant, n.colors));
94
94
  return (t, n) => (d(), r("footer", {
95
- class: s(["mw-footer", `mw-footer--${e.variant}`]),
96
- style: c(a.value)
95
+ class: c(["mw-footer", `mw-footer--${e.variant}`]),
96
+ style: l(a.value)
97
97
  }, [
98
- i("div", T, [m(t.$slots, "start", {}, void 0, !0)]),
99
- i("div", E, [m(t.$slots, "default", {}, void 0, !0)]),
100
- i("div", D, [m(t.$slots, "end", {}, void 0, !0)])
98
+ i("div", w, [m(t.$slots, "start", {}, void 0, !0)]),
99
+ i("div", T, [m(t.$slots, "default", {}, void 0, !0)]),
100
+ i("div", E, [m(t.$slots, "end", {}, void 0, !0)])
101
101
  ], 6));
102
102
  }
103
- }), [["__scopeId", "data-v-c646b8e1"]]), k = {
103
+ }), [["__scopeId", "data-v-c646b8e1"]]), O = {
104
104
  class: "mw-mode",
105
105
  role: "group",
106
106
  "aria-label": "Colour mode"
107
- }, A = [
107
+ }, k = [
108
108
  "aria-pressed",
109
109
  "title",
110
110
  "onClick"
111
- ], j = { "aria-hidden": "true" }, M = { class: "mw-mode__label" }, N = /*#__PURE__*/ v(/* @__PURE__ */ a({
111
+ ], A = { "aria-hidden": "true" }, j = { class: "mw-mode__label" }, M = /*#__PURE__*/ _(/* @__PURE__ */ o({
112
112
  __name: "ColorModeControl",
113
113
  props: {
114
114
  modelValue: {},
@@ -127,18 +127,18 @@ var re = { class: "mw-header__brand" }, ie = { class: "mw-header__center" }, ae
127
127
  }, a = {
128
128
  light: "☀",
129
129
  dark: "☾",
130
- system: "◐"
130
+ system: "🖵"
131
131
  };
132
- return (o, c) => (d(), r("div", k, [(d(!0), r(e, null, p(t.modes, (e) => (d(), r("button", {
132
+ return (o, s) => (d(), r("div", O, [(d(!0), r(e, null, p(t.modes, (e) => (d(), r("button", {
133
133
  key: e,
134
134
  type: "button",
135
- class: s(["mw-mode__btn", { "is-active": t.modelValue === e }]),
135
+ class: c(["mw-mode__btn", { "is-active": t.modelValue === e }]),
136
136
  "aria-pressed": t.modelValue === e,
137
137
  title: n[e],
138
138
  onClick: (t) => o.$emit("update:modelValue", e)
139
- }, [i("span", j, h(a[e]), 1), i("span", M, h(n[e]), 1)], 10, A))), 128))]));
139
+ }, [i("span", A, h(a[e]), 1), i("span", j, h(n[e]), 1)], 10, k))), 128))]));
140
140
  }
141
- }), [["__scopeId", "data-v-e4a6bf1d"]]), P = ["type", "disabled"], F = /*#__PURE__*/ v(/* @__PURE__ */ a({
141
+ }), [["__scopeId", "data-v-186f8312"]]), N = ["type", "disabled"], P = /*#__PURE__*/ _(/* @__PURE__ */ o({
142
142
  __name: "UiButton",
143
143
  props: {
144
144
  variant: { default: "primary" },
@@ -152,26 +152,26 @@ var re = { class: "mw-header__brand" }, ie = { class: "mw-header__center" }, ae
152
152
  return (t, n) => (d(), r("button", {
153
153
  type: e.type,
154
154
  disabled: e.disabled,
155
- class: s(["mw-btn", `mw-btn--${e.variant}`])
156
- }, [m(t.$slots, "default", {}, void 0, !0)], 10, P));
155
+ class: c(["mw-btn", `mw-btn--${e.variant}`])
156
+ }, [m(t.$slots, "default", {}, void 0, !0)], 10, N));
157
157
  }
158
- }), [["__scopeId", "data-v-299de2c3"]]), I = { class: "mw-card" }, L = {
158
+ }), [["__scopeId", "data-v-299de2c3"]]), F = { class: "mw-card" }, I = {
159
159
  key: 0,
160
160
  class: "mw-card__header"
161
- }, R = { class: "mw-card__title" }, z = { class: "mw-card__body" }, B = {
161
+ }, L = { class: "mw-card__title" }, R = { class: "mw-card__body" }, z = {
162
162
  key: 1,
163
163
  class: "mw-card__footer"
164
- }, se = /*#__PURE__*/ v(/* @__PURE__ */ a({
164
+ }, B = /*#__PURE__*/ _(/* @__PURE__ */ o({
165
165
  __name: "UiCard",
166
166
  props: { title: {} },
167
167
  setup(e) {
168
- return (t, a) => (d(), r("section", I, [
169
- e.title || t.$slots.header ? (d(), r("header", L, [m(t.$slots, "header", {}, () => [i("h3", R, h(e.title), 1)], !0)])) : n("", !0),
170
- i("div", z, [m(t.$slots, "default", {}, void 0, !0)]),
171
- t.$slots.footer ? (d(), r("footer", B, [m(t.$slots, "footer", {}, void 0, !0)])) : n("", !0)
168
+ return (t, a) => (d(), r("section", F, [
169
+ e.title || t.$slots.header ? (d(), r("header", I, [m(t.$slots, "header", {}, () => [i("h3", L, h(e.title), 1)], !0)])) : n("", !0),
170
+ i("div", R, [m(t.$slots, "default", {}, void 0, !0)]),
171
+ t.$slots.footer ? (d(), r("footer", z, [m(t.$slots, "footer", {}, void 0, !0)])) : n("", !0)
172
172
  ]));
173
173
  }
174
- }), [["__scopeId", "data-v-fd2fd7ab"]]), V = { class: "mw-select" }, H = /*#__PURE__*/ v(/* @__PURE__ */ a({
174
+ }), [["__scopeId", "data-v-fd2fd7ab"]]), le = { class: "mw-select" }, V = /*#__PURE__*/ _(/* @__PURE__ */ o({
175
175
  inheritAttrs: !1,
176
176
  __name: "UiSelect",
177
177
  props: {
@@ -180,8 +180,8 @@ var re = { class: "mw-header__brand" }, ie = { class: "mw-header__center" }, ae
180
180
  },
181
181
  emits: ["update:modelValue"],
182
182
  setup(e) {
183
- let t = ee(e, "modelValue");
184
- return (e, n) => (d(), r("div", V, [g(i("select", o(e.$attrs, { "onUpdate:modelValue": n[0] ||= (e) => t.value = e }), [m(e.$slots, "default", {}, void 0, !0)], 16), [[te, t.value]]), n[1] ||= i("svg", {
183
+ let t = te(e, "modelValue");
184
+ return (e, n) => (d(), r("div", le, [ie(i("select", s(e.$attrs, { "onUpdate:modelValue": n[0] ||= (e) => t.value = e }), [m(e.$slots, "default", {}, void 0, !0)], 16), [[ne, t.value]]), n[1] ||= i("svg", {
185
185
  class: "mw-select__chevron",
186
186
  xmlns: "http://www.w3.org/2000/svg",
187
187
  width: "12",
@@ -190,7 +190,7 @@ var re = { class: "mw-header__brand" }, ie = { class: "mw-header__center" }, ae
190
190
  "aria-hidden": "true"
191
191
  }, [i("path", { d: "M1 1l5 5 5-5" })], -1)]));
192
192
  }
193
- }), [["__scopeId", "data-v-b9468387"]]), U = ["role"], W = /*#__PURE__*/ v(/* @__PURE__ */ a({
193
+ }), [["__scopeId", "data-v-b9468387"]]), H = ["role"], U = /*#__PURE__*/ _(/* @__PURE__ */ o({
194
194
  __name: "UiNotice",
195
195
  props: { type: {} },
196
196
  setup(e) {
@@ -199,15 +199,15 @@ var re = { class: "mw-header__brand" }, ie = { class: "mw-header__center" }, ae
199
199
  if (n.type === "ok") return "status";
200
200
  });
201
201
  return (t, n) => (d(), r("p", {
202
- class: s(["mw-notice", e.type && e.type !== "info" ? `mw-notice--${e.type}` : ""]),
202
+ class: c(["mw-notice", e.type && e.type !== "info" ? `mw-notice--${e.type}` : ""]),
203
203
  role: i.value
204
- }, [m(t.$slots, "default", {}, void 0, !0)], 10, U));
204
+ }, [m(t.$slots, "default", {}, void 0, !0)], 10, H));
205
205
  }
206
- }), [["__scopeId", "data-v-6f53d0be"]]), G = ["disabled", "aria-current"], K = {
206
+ }), [["__scopeId", "data-v-6f53d0be"]]), W = ["disabled", "aria-current"], ue = {
207
207
  key: 0,
208
208
  class: "sidebar-item__icon",
209
209
  "aria-hidden": "true"
210
- }, ce = { class: "sidebar-item__label" }, le = /*#__PURE__*/ v(/* @__PURE__ */ a({
210
+ }, de = { class: "sidebar-item__label" }, fe = /*#__PURE__*/ _(/* @__PURE__ */ o({
211
211
  __name: "SidebarItem",
212
212
  props: {
213
213
  label: {},
@@ -224,12 +224,36 @@ var re = { class: "mw-header__brand" }, ie = { class: "mw-header__center" }, ae
224
224
  setup(e) {
225
225
  return (t, a) => (d(), r("button", {
226
226
  type: "button",
227
- class: s(["sidebar-item", { "is-active": e.active }]),
227
+ class: c(["sidebar-item", { "is-active": e.active }]),
228
228
  disabled: e.disabled,
229
229
  "aria-current": e.active ? "page" : void 0
230
- }, [e.icon ? (d(), r("span", K, h(e.icon), 1)) : n("", !0), i("span", ce, h(e.label), 1)], 10, G));
230
+ }, [e.icon ? (d(), r("span", ue, h(e.icon), 1)) : n("", !0), i("span", de, h(e.label), 1)], 10, W));
231
231
  }
232
- }), [["__scopeId", "data-v-e15afdf7"]]), ue = ["title"], de = /*#__PURE__*/ v(/* @__PURE__ */ a({
232
+ }), [["__scopeId", "data-v-e15afdf7"]]), pe = { class: "ca-root" }, me = ["title"], he = ["title", "aria-label"], ge = {
233
+ key: 0,
234
+ class: "ca-icon",
235
+ viewBox: "0 0 24 24",
236
+ width: "1em",
237
+ height: "1em",
238
+ fill: "none",
239
+ stroke: "currentColor",
240
+ "stroke-width": "2",
241
+ "stroke-linecap": "round",
242
+ "stroke-linejoin": "round",
243
+ "aria-hidden": "true"
244
+ }, _e = {
245
+ key: 1,
246
+ class: "ca-icon",
247
+ viewBox: "0 0 24 24",
248
+ width: "1em",
249
+ height: "1em",
250
+ fill: "none",
251
+ stroke: "currentColor",
252
+ "stroke-width": "2",
253
+ "stroke-linecap": "round",
254
+ "stroke-linejoin": "round",
255
+ "aria-hidden": "true"
256
+ }, ve = /*#__PURE__*/ _(/* @__PURE__ */ o({
233
257
  __name: "CopyableAddress",
234
258
  props: {
235
259
  address: {},
@@ -237,44 +261,81 @@ var re = { class: "mw-header__brand" }, ie = { class: "mw-header__center" }, ae
237
261
  type: Boolean,
238
262
  default: !0
239
263
  },
240
- chars: { default: () => [6, 4] }
264
+ chars: { default: () => [6, 4] },
265
+ label: { default: "Copy" }
241
266
  },
242
267
  setup(e) {
243
- let n = e, i = f(!1), a = t(() => {
244
- if (i.value) return "Copied!";
268
+ let n = e, o = f(!1), s = t(() => {
245
269
  if (!n.truncate) return n.address;
246
270
  let [e, t] = n.chars;
247
271
  return `${n.address.slice(0, e)}…${n.address.slice(-t)}`;
248
272
  });
249
- async function o() {
250
- await navigator.clipboard.writeText(n.address), i.value = !0, setTimeout(() => {
251
- i.value = !1;
273
+ async function l() {
274
+ await navigator.clipboard.writeText(n.address), o.value = !0, setTimeout(() => {
275
+ o.value = !1;
252
276
  }, 1500);
253
277
  }
254
- return (t, n) => (d(), r("button", {
278
+ return (t, n) => (d(), r("span", pe, [i("span", {
279
+ class: "ca-value",
280
+ title: e.address
281
+ }, [m(t.$slots, "default", {}, () => [a(h(s.value), 1)], !0)], 8, me), i("button", {
255
282
  type: "button",
256
- class: s(["ca-root", { "ca-root--copied": i.value }]),
257
- title: e.address,
258
- onClick: o
259
- }, h(a.value), 11, ue));
283
+ class: c(["ca-copy", { "ca-copy--copied": o.value }]),
284
+ title: o.value ? "Copied!" : e.label,
285
+ "aria-label": o.value ? "Copied" : e.label,
286
+ onClick: l
287
+ }, [o.value ? (d(), r("svg", ge, [...n[0] ||= [i("polyline", { points: "20 6 9 17 4 12" }, null, -1)]])) : (d(), r("svg", _e, [...n[1] ||= [i("rect", {
288
+ x: "9",
289
+ y: "9",
290
+ width: "13",
291
+ height: "13",
292
+ rx: "2",
293
+ ry: "2"
294
+ }, null, -1), i("path", { d: "M5 15H4a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h9a2 2 0 0 1 2 2v1" }, null, -1)]]))], 10, he)]));
295
+ }
296
+ }), [["__scopeId", "data-v-08c3420b"]]), ye = ["href", "title"], be = /*#__PURE__*/ _(/* @__PURE__ */ o({
297
+ __name: "ExplorerLink",
298
+ props: {
299
+ href: {},
300
+ value: {},
301
+ truncate: {
302
+ type: Boolean,
303
+ default: !0
304
+ },
305
+ chars: { default: () => [6, 4] }
306
+ },
307
+ setup(e) {
308
+ let n = e, i = t(() => {
309
+ if (!n.value) return "";
310
+ if (!n.truncate) return n.value;
311
+ let [e, t] = n.chars;
312
+ return `${n.value.slice(0, e)}…${n.value.slice(-t)}`;
313
+ });
314
+ return (t, n) => (d(), r("a", {
315
+ class: "el-root",
316
+ href: e.href,
317
+ target: "_blank",
318
+ rel: "noopener noreferrer",
319
+ title: e.value
320
+ }, [m(t.$slots, "default", {}, () => [a(h(i.value), 1)], !0)], 8, ye));
260
321
  }
261
- }), [["__scopeId", "data-v-e2d23de9"]]), fe = /* @__PURE__ */ new Set([
322
+ }), [["__scopeId", "data-v-7a44607e"]]), xe = /* @__PURE__ */ new Set([
262
323
  "operational",
263
324
  "degraded",
264
325
  "down",
265
326
  "unknown"
266
327
  ]);
267
- function q(e) {
268
- return typeof e == "string" && fe.has(e);
328
+ function G(e) {
329
+ return typeof e == "string" && xe.has(e);
269
330
  }
270
- function J(e) {
331
+ function K(e) {
271
332
  if (typeof e != "object" || !e) return null;
272
333
  let t = e;
273
- return !q(t.overall) || typeof t.generated_at != "string" || !Array.isArray(t.groups) ? null : e;
334
+ return !G(t.overall) || typeof t.generated_at != "string" || !Array.isArray(t.groups) ? null : e;
274
335
  }
275
336
  //#endregion
276
337
  //#region src/components/StatusWidget.vue?vue&type=script&setup=true&lang.ts
277
- var pe = ["href", "title"], me = { class: "status-widget__label" }, he = /*#__PURE__*/ v(/* @__PURE__ */ a({
338
+ var Se = ["href", "title"], Ce = { class: "status-widget__label" }, we = /*#__PURE__*/ _(/* @__PURE__ */ o({
278
339
  __name: "StatusWidget",
279
340
  props: {
280
341
  apiUrl: { default: "https://status.meddleware.co.uk/api/status" },
@@ -292,71 +353,81 @@ var pe = ["href", "title"], me = { class: "status-widget__label" }, he = /*#__PU
292
353
  degraded: "Degraded",
293
354
  down: "Major outage",
294
355
  unknown: "Status unknown"
295
- }, o = f("ok"), c = f("All systems operational"), p = null;
296
- async function m() {
356
+ }, o = f("ok"), s = f("All systems operational"), l = null;
357
+ async function p() {
297
358
  try {
298
359
  let e = await fetch(t.apiUrl);
299
360
  if (!e.ok) throw Error(`HTTP ${e.status}`);
300
- let r = J(await e.json());
361
+ let r = K(await e.json());
301
362
  if (!r) throw Error("unexpected response shape");
302
- o.value = n[r.overall], c.value = a[r.overall];
363
+ o.value = n[r.overall], s.value = a[r.overall];
303
364
  } catch {
304
- o.value = "error", c.value = "Status unavailable";
365
+ o.value = "error", s.value = "Status unavailable";
305
366
  }
306
367
  }
307
- return l(() => {
308
- m(), p = setInterval(m, t.pollInterval);
309
- }), u(() => {
310
- p !== null && clearInterval(p);
368
+ return u(() => {
369
+ p(), l = setInterval(p, t.pollInterval);
370
+ }), ee(() => {
371
+ l !== null && clearInterval(l);
311
372
  }), (t, n) => (d(), r("a", {
312
373
  href: e.href,
313
374
  target: "_blank",
314
375
  rel: "noopener",
315
- class: s(["status-widget", `status-widget--${o.value}`]),
316
- title: `Platform status: ${c.value}`
376
+ class: c(["status-widget", `status-widget--${o.value}`]),
377
+ title: `Platform status: ${s.value}`
317
378
  }, [n[0] ||= i("span", {
318
379
  class: "status-widget__dot",
319
380
  "aria-hidden": "true"
320
- }, null, -1), i("span", me, h(c.value), 1)], 10, pe));
381
+ }, null, -1), i("span", Ce, h(s.value), 1)], 10, Se));
321
382
  }
322
- }), [["__scopeId", "data-v-20197983"]]), Y = "mw-color-mode", X = f("system"), Z = !1;
323
- function ge() {
383
+ }), [["__scopeId", "data-v-20197983"]]), q = {
384
+ mainnet: "https://suivision.xyz",
385
+ testnet: "https://testnet.suivision.xyz",
386
+ devnet: "https://devnet.suivision.xyz"
387
+ };
388
+ function Te(e, t, n = "testnet") {
389
+ return `${q[n] ?? q.testnet}/${e}/${t}`;
390
+ }
391
+ //#endregion
392
+ //#region src/composables/useColorMode.ts
393
+ var J = "mw-color-mode", Y = f("system"), X = !1;
394
+ function Z() {
324
395
  return typeof window < "u" && typeof window.matchMedia == "function" && window.matchMedia("(prefers-color-scheme: dark)").matches;
325
396
  }
326
397
  function Q(e) {
327
- return e === "dark" || e === "system" && ge();
398
+ return e === "dark" || e === "system" && Z();
328
399
  }
329
400
  function $(e) {
330
401
  typeof document > "u" || document.documentElement.setAttribute("data-theme", Q(e) ? "dark" : "light");
331
402
  }
332
- function _e(e = "system") {
333
- if (!Z) {
334
- Z = !0;
403
+ function Ee(e = "system") {
404
+ if (!X) {
405
+ X = !0;
335
406
  let t = null;
336
407
  try {
337
- t = typeof localStorage < "u" ? localStorage.getItem(Y) : null;
408
+ t = typeof localStorage < "u" ? localStorage.getItem(J) : null;
338
409
  } catch {}
339
- X.value = t ?? e, $(X.value), typeof window < "u" && typeof window.matchMedia == "function" && window.matchMedia("(prefers-color-scheme: dark)").addEventListener("change", () => {
340
- X.value === "system" && $("system");
341
- }), ne(X, (e) => {
410
+ Y.value = t ?? e, $(Y.value), typeof window < "u" && typeof window.matchMedia == "function" && window.matchMedia("(prefers-color-scheme: dark)").addEventListener("change", () => {
411
+ Y.value === "system" && $("system");
412
+ }), re(Y, (e) => {
342
413
  $(e);
343
414
  try {
344
- typeof localStorage < "u" && localStorage.setItem(Y, e);
415
+ typeof localStorage < "u" && localStorage.setItem(J, e);
345
416
  } catch {}
346
417
  });
347
418
  }
348
419
  function t(e) {
349
- X.value = e;
420
+ Y.value = e;
350
421
  }
351
422
  function n() {
352
- t(X.value === "light" ? "dark" : X.value === "dark" ? "system" : "light");
423
+ t(Y.value === "light" ? "dark" : Y.value === "dark" ? "system" : "light");
353
424
  }
354
425
  return {
355
- mode: X,
426
+ mode: Y,
356
427
  set: t,
357
428
  cycle: n,
358
- isDark: () => Q(X.value)
429
+ isDark: () => Q(Y.value)
359
430
  };
360
431
  }
361
432
  //#endregion
362
- export { O as AppFooter, y as AppHeader, w as AppSidebar, N as ColorModeControl, de as CopyableAddress, le as SidebarItem, he as StatusWidget, F as UiButton, se as UiCard, W as UiNotice, H as UiSelect, q as isStatusLevel, J as parseSnapshot, _e as useColorMode };
433
+ export { D as AppFooter, v as AppHeader, C as AppSidebar, M as ColorModeControl, ve as CopyableAddress, be as ExplorerLink, fe as SidebarItem, we as StatusWidget, P as UiButton, B as UiCard, U as UiNotice, V as UiSelect, G as isStatusLevel, K as parseSnapshot, Te as suiExplorerUrl, Ee as useColorMode };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@meddleware/ui",
3
- "version": "0.1.8",
3
+ "version": "0.1.10",
4
4
  "description": "Shared Vue 3 component library for @meddleware UIs \u2014 layout shell (header/sidebar/footer), colour-mode control, and primitives. Built on @meddleware/design-tokens.",
5
5
  "license": "0BSD",
6
6
  "type": "module",
@@ -23,7 +23,8 @@
23
23
  ],
24
24
  "scripts": {
25
25
  "build": "rm -rf dist && vue-tsc -p tsconfig.build.json && vite build",
26
- "type-check": "vue-tsc --noEmit"
26
+ "type-check": "vue-tsc --noEmit",
27
+ "test": "vitest run"
27
28
  },
28
29
  "peerDependencies": {
29
30
  "vue": "^3.5.0"
@@ -35,6 +36,7 @@
35
36
  "@vitejs/plugin-vue": "^6.0.8",
36
37
  "typescript": "^6.0.0",
37
38
  "vite": "^8.2.2",
39
+ "vitest": "~4.1.11",
38
40
  "vue": "^3.5.42",
39
41
  "vue-tsc": "~3.3.11"
40
42
  },