@meddleware/ui 0.1.11 → 0.1.13
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 +25 -4
- package/dist/base.css +1 -1
- package/dist/components/AppFooter.vue.d.ts +10 -0
- package/dist/index.d.ts +1 -0
- package/dist/safe-href.d.ts +8 -0
- package/dist/status.d.ts +4 -2
- package/dist/ui.js +151 -90
- package/package.json +4 -3
package/README.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# @meddleware/ui
|
|
2
2
|
|
|
3
|
-
Shared Vue 3 component library for the `@meddleware` UIs. Delivers a layout shell (header, sidebar, footer), colour-mode control, and UI primitives — all styled with [`@meddleware/design-tokens`](https://www.npmjs.com/package/@meddleware/design-tokens)
|
|
3
|
+
Shared Vue 3 component library for the `@meddleware` UIs. Delivers a layout shell (header, sidebar, footer), colour-mode control, and UI primitives — all styled with [`@meddleware/design-tokens`](https://www.npmjs.com/package/@meddleware/design-tokens): a warm-neutral canvas with functional primary/rainbow accents, sacred-geometry (φ/Fibonacci) type + spacing scales, and optional seasonal theming.
|
|
4
4
|
|
|
5
5
|
## Installation
|
|
6
6
|
|
|
@@ -14,18 +14,39 @@ yarn add @meddleware/ui @meddleware/design-tokens
|
|
|
14
14
|
|
|
15
15
|
## Setup
|
|
16
16
|
|
|
17
|
-
Import
|
|
17
|
+
Import the CSS once at your application entry point:
|
|
18
18
|
|
|
19
19
|
```ts
|
|
20
20
|
// src/main.ts (or equivalent)
|
|
21
|
-
import '@meddleware/design-tokens/tokens.css'
|
|
22
|
-
import '@meddleware/
|
|
21
|
+
import '@meddleware/design-tokens/tokens.css' // required — registers CSS custom properties
|
|
22
|
+
import '@meddleware/design-tokens/seasons.css' // optional — enables data-season theming
|
|
23
|
+
import '@meddleware/ui/base.css' // optional — element defaults + scale + utilities
|
|
23
24
|
import { createApp } from 'vue'
|
|
24
25
|
import App from './App.vue'
|
|
25
26
|
|
|
26
27
|
createApp(App).mount('#app')
|
|
27
28
|
```
|
|
28
29
|
|
|
30
|
+
## Styling, scales & utilities
|
|
31
|
+
|
|
32
|
+
Components consume the design-token **role** tokens (`--accent`, `--warning`, `--focus-ring`, …) and
|
|
33
|
+
the **sacred-geometry scales** (`--space-*`, `--font-size-*`, `--leading-*`, `--tracking-*`) — never
|
|
34
|
+
colour-named or magic-number values. Focus states use the dedicated `--focus-ring` (blue) so they are
|
|
35
|
+
always visible and never read as an error. Component **props and accessibility are unchanged** by the
|
|
36
|
+
theming system — only the styling tokens they resolve to.
|
|
37
|
+
|
|
38
|
+
`base.css` also ships opt-in utilities (respecting `prefers-reduced-motion`):
|
|
39
|
+
|
|
40
|
+
| Utility | Purpose |
|
|
41
|
+
| --- | --- |
|
|
42
|
+
| `.mw-noise` | Subtle CSS-native SVG-noise background layer (controlled imperfection over flat polish). |
|
|
43
|
+
| `.mw-mono` | Monospace font (`--mw-font-mono`). |
|
|
44
|
+
| `.mw-spinner` | Sigil-like ring loader that settles into a simple form. |
|
|
45
|
+
| `.mw-hand-drawn` | Empty positioned **placeholder hook** for bespoke hand-drawn SVG/canvas added later — drop an `<svg>`/`<canvas>` inside, or target `.mw-hand-drawn > svg` from your app. |
|
|
46
|
+
|
|
47
|
+
Seasonal theming is entirely in `@meddleware/design-tokens` (import `seasons.css` + set
|
|
48
|
+
`data-season`); the components pick it up automatically through the role tokens.
|
|
49
|
+
|
|
29
50
|
## Exports
|
|
30
51
|
|
|
31
52
|
### Layout shell
|
package/dist/base.css
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
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}.mw-tab-nav[data-v-88758ede]{border-bottom:2px solid var(--border);gap:.25rem;display:flex}.mw-tab-nav__tab[data-v-88758ede]{appearance:none;cursor:pointer;color:var(--muted);background:0 0;border:none;border-bottom:2px solid #0000;margin-bottom:-2px;padding:.5rem 1rem;font-size:.95rem;transition:color .1s,border-color .1s}.mw-tab-nav__tab[data-v-88758ede]:hover{color:var(--text)}.mw-tab-nav__tab--active[data-v-88758ede]{border-bottom-color:var(--accent);color:var(--text);font-weight:600}.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)}
|
|
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);font-size:var(--font-size-base);line-height:var(--leading-normal);letter-spacing:var(--tracking-normal);-webkit-font-smoothing:antialiased;text-rendering:optimizelegibility}: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);transition:color var(--transition-base);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(--focus-ring);outline-offset:2px}.mw-mono{font-family:var(--mw-font-mono)}.mw-noise{isolation:isolate;position:relative}.mw-noise:before{content:"";z-index:-1;background-image:var(--noise-overlay);opacity:var(--noise-opacity);pointer-events:none;background-repeat:repeat;position:absolute;inset:0}.mw-hand-drawn{display:inline-flex;position:relative}.mw-spinner{width:var(--space-sm);height:var(--space-sm);border:2px solid var(--border);border-top-color:var(--accent);animation:mw-spin var(--transition-slow) linear infinite;border-radius:50%;display:inline-block}@keyframes mw-spin{0%{transform:rotate(0)}to{transform:rotate(360deg)}}@media (prefers-reduced-motion:reduce){*,:before,:after{transition-duration:.001ms!important;animation-duration:.001ms!important}.mw-spinner{border-top-color:var(--accent);animation:none}}.mw-header[data-v-9b9826d5]{align-items:center;gap:var(--space-sm);height:var(--mw-header-height,56px);padding:0 var(--space-sm);background:var(--_bg);color:var(--_text);border-bottom:1px solid var(--_border);font-family:var(--mw-font-sans);display:flex}.mw-header--sticky[data-v-9b9826d5]{z-index:50;position:sticky;top:0}.mw-header__brand[data-v-9b9826d5]{align-items:center;gap:var(--space-2xs);letter-spacing:var(--tracking-wide);white-space:nowrap;font-weight:650;display:flex}.mw-header__center[data-v-9b9826d5]{flex:auto;min-width:0}.mw-header__actions[data-v-9b9826d5]{align-items:center;gap:var(--space-2xs);margin-left:auto;display:flex}.mw-sidebar[data-v-a2b8405c]{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-a2b8405c]{padding:var(--space-sm);border-bottom:1px solid var(--_border)}.mw-sidebar__nav[data-v-a2b8405c]{gap:var(--space-3xs);padding:var(--space-xs);flex-direction:column;flex:auto;display:flex;overflow-y:auto}.mw-sidebar__body[data-v-a2b8405c]{flex-shrink:0}.mw-sidebar__foot[data-v-a2b8405c]{padding:var(--space-xs) var(--space-sm);border-top:1px solid var(--_border);color:var(--_muted);font-size:var(--font-size-sm)}.mw-footer[data-v-979579a9]{align-items:center;gap:var(--space-sm);padding:var(--space-xs) var(--space-sm);background:var(--_bg);color:var(--_muted);border-top:1px solid var(--_border);font-family:var(--mw-font-sans);font-size:var(--font-size-sm);flex-wrap:wrap;display:flex}.mw-footer--transparent[data-v-979579a9]{border-top:1px solid var(--border)}.mw-footer__center[data-v-979579a9]{flex:auto;min-width:0}.mw-footer__end[data-v-979579a9]{align-items:center;gap:var(--space-sm);margin-left:auto;display:flex}.mw-footer__docs-link[data-v-979579a9]{color:inherit;text-underline-offset:2px;opacity:.7;text-decoration:underline}.mw-footer__docs-link[data-v-979579a9]:hover{opacity:1}.mw-mode[data-v-e2ea0d79]{border:1px solid var(--_border,var(--border));border-radius:var(--radius);background:color-mix(in srgb, var(--_text,var(--text)) 6%, transparent);gap:2px;padding:2px;display:inline-flex}.mw-mode__btn[data-v-e2ea0d79]{align-items:center;gap:var(--space-3xs);padding:var(--space-3xs) var(--space-2xs);border-radius:calc(var(--radius) - 3px);color:var(--_text,var(--text));font:inherit;font-size:var(--font-size-sm);cursor:pointer;opacity:.7;transition:opacity var(--transition-base), background var(--transition-base);background:0 0;border:0;display:inline-flex}.mw-mode__btn[data-v-e2ea0d79]:hover{opacity:1}.mw-mode__btn.is-active[data-v-e2ea0d79]{opacity:1;background:color-mix(in srgb, var(--_text,var(--text)) 14%, transparent)}.mw-mode__btn[data-v-e2ea0d79]:focus-visible{outline:2px solid var(--focus-ring);outline-offset:1px}@media (width<=640px){.mw-mode__label[data-v-e2ea0d79]{display:none}}.mw-btn[data-v-bc33cc23]{justify-content:center;align-items:center;gap:var(--space-2xs);padding:var(--space-2xs) var(--space-xs);border-radius:var(--radius);font:inherit;cursor:pointer;transition:filter var(--transition-base), background var(--transition-base);border:1px solid #0000;font-weight:550;display:inline-flex}.mw-btn[data-v-bc33cc23]:disabled{opacity:.55;cursor:not-allowed}.mw-btn[data-v-bc33cc23]:focus-visible{outline:2px solid var(--focus-ring);outline-offset:2px}.mw-btn--primary[data-v-bc33cc23]{background:var(--accent);color:var(--accent-contrast)}.mw-btn--primary[data-v-bc33cc23]:not(:disabled):hover{filter:brightness(1.08)}.mw-btn--secondary[data-v-bc33cc23]{background:var(--secondary);color:var(--secondary-contrast)}.mw-btn--secondary[data-v-bc33cc23]:not(:disabled):hover{filter:brightness(1.08)}.mw-btn--ghost[data-v-bc33cc23]{color:var(--text);border-color:var(--border);background:0 0}.mw-btn--ghost[data-v-bc33cc23]:not(:disabled):hover{background:var(--lift)}.mw-btn--danger[data-v-bc33cc23]{background:var(--danger);color:var(--accent-contrast)}.mw-btn--danger[data-v-bc33cc23]:not(:disabled):hover{filter:brightness(1.08)}.mw-card[data-v-883f87f5]{background:var(--surface);border:1px solid var(--border);border-radius:var(--radius);color:var(--text);overflow:hidden}.mw-card__header[data-v-883f87f5]{padding:var(--space-xs) var(--space-sm);border-bottom:1px solid var(--border)}.mw-card__title[data-v-883f87f5]{font-size:var(--font-size-base);margin:0;font-weight:600}.mw-card__body[data-v-883f87f5]{padding:var(--space-sm)}.mw-card__footer[data-v-883f87f5]{padding:var(--space-xs) var(--space-sm);border-top:1px solid var(--border);background:var(--lift)}.mw-select[data-v-7e206184]{position:relative}.mw-select select[data-v-7e206184]{appearance:none;width:100%;padding:var(--space-2xs) calc(var(--space-md) + var(--space-2xs)) var(--space-2xs) var(--space-xs);background:var(--surface);color:var(--text);border:1px solid var(--border);border-radius:var(--radius);font:inherit}.mw-select select[data-v-7e206184]:focus-visible{outline:2px solid var(--focus-ring);outline-offset:1px}.mw-select__chevron[data-v-7e206184]{right:var(--space-xs);pointer-events:none;stroke:var(--muted);stroke-width:1.5px;fill:none;position:absolute;top:50%;transform:translateY(-50%)}.mw-notice[data-v-ee7fffb1]{padding:var(--space-2xs) var(--space-xs);border:1px solid var(--border);border-radius:var(--radius);background:var(--lift);color:var(--text);font-size:var(--font-size-sm);border-left-width:3px;margin:0}.mw-notice--error[data-v-ee7fffb1]{border-left-color:var(--danger);color:var(--danger);background:color-mix(in srgb, var(--danger) 8%, transparent)}.mw-notice--ok[data-v-ee7fffb1]{border-left-color:var(--ok);color:var(--ok);background:color-mix(in srgb, var(--ok) 8%, transparent)}.sidebar-item[data-v-8da2d583]{align-items:center;gap:var(--space-2xs);width:100%;padding:var(--space-2xs) var(--space-xs);border-radius:var(--radius);color:inherit;font:inherit;text-align:left;cursor:pointer;opacity:.85;transition:background var(--transition-base), opacity var(--transition-base);background:0 0;border:0;display:flex}.sidebar-item[data-v-8da2d583]:hover:not(:disabled){background:color-mix(in srgb, currentColor 10%, transparent);opacity:1}.sidebar-item.is-active[data-v-8da2d583]{background:color-mix(in srgb, var(--accent) 26%, transparent);opacity:1}.sidebar-item[data-v-8da2d583]:disabled{cursor:default}.sidebar-item[data-v-8da2d583]:focus-visible{outline:2px solid var(--focus-ring);outline-offset:1px}.sidebar-item__icon[data-v-8da2d583]{text-align:center;width:1.1rem}.mw-tab-nav[data-v-97d31503]{gap:var(--space-3xs);border-bottom:2px solid var(--border);display:flex}.mw-tab-nav__tab[data-v-97d31503]{appearance:none;padding:var(--space-2xs) var(--space-sm);cursor:pointer;font-size:var(--font-size-base);color:var(--muted);transition:color var(--transition-base), border-color var(--transition-base);background:0 0;border:none;border-bottom:2px solid #0000;margin-bottom:-2px}.mw-tab-nav__tab[data-v-97d31503]:hover{color:var(--text)}.mw-tab-nav__tab--active[data-v-97d31503]{border-bottom-color:var(--accent);color:var(--text);font-weight:600}.ca-root[data-v-b43dabdd]{align-items:center;gap:.35em;display:inline-flex}.ca-value[data-v-b43dabdd]{font-family:var(--mw-font-mono,monospace);font-size:inherit}.ca-copy[data-v-b43dabdd]{color:var(--muted,#888);cursor:pointer;transition:color var(--transition-base);background:0 0;border:none;justify-content:center;align-items:center;padding:0;line-height:1;display:inline-flex}.ca-copy[data-v-b43dabdd]:hover{color:var(--text,#f0f0f0)}.ca-copy--copied[data-v-b43dabdd]{color:var(--accent,#6366f1)}.ca-icon[data-v-b43dabdd]{display:block}.el-root[data-v-073d1bbe]{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-073d1bbe]:hover{color:var(--text,#f0f0f0);text-decoration-style:solid}.status-widget[data-v-6436368e]{align-items:center;gap:var(--space-2xs);color:inherit;font-size:var(--font-size-sm);opacity:.85;transition:opacity var(--transition-base);text-decoration:none;display:inline-flex}.status-widget[data-v-6436368e]:hover{opacity:1}.status-widget__dot[data-v-6436368e]{width:var(--space-2xs);height:var(--space-2xs);border-radius:50%;flex-shrink:0}.status-widget--ok .status-widget__dot[data-v-6436368e]{background:var(--ok)}.status-widget--degraded .status-widget__dot[data-v-6436368e]{background:var(--warning)}.status-widget--error .status-widget__dot[data-v-6436368e]{background:var(--danger)}
|
|
2
2
|
/*$vite$:1*/
|
|
@@ -4,6 +4,16 @@ type __VLS_Props = {
|
|
|
4
4
|
variant?: PanelVariant;
|
|
5
5
|
/** Per-instance colour overrides; token values are used by default. */
|
|
6
6
|
colors?: PanelColors;
|
|
7
|
+
/**
|
|
8
|
+
* When set, renders a "Documentation" link pointing at this URL.
|
|
9
|
+
* Use `VITE_DOCS_URL` in the consuming app to make this configurable per deployment.
|
|
10
|
+
*/
|
|
11
|
+
docsUrl?: string;
|
|
12
|
+
/**
|
|
13
|
+
* When set, renders a "Developer docs" link pointing at this URL.
|
|
14
|
+
* Use `VITE_DEV_URL` in the consuming app to make this configurable per deployment.
|
|
15
|
+
*/
|
|
16
|
+
devUrl?: string;
|
|
7
17
|
};
|
|
8
18
|
declare var __VLS_1: {}, __VLS_3: {}, __VLS_5: {};
|
|
9
19
|
type __VLS_Slots = {} & {
|
package/dist/index.d.ts
CHANGED
|
@@ -19,4 +19,5 @@ export { useColorMode } from './composables/useColorMode.js';
|
|
|
19
19
|
export type { ColorMode } from './composables/useColorMode.js';
|
|
20
20
|
export type { PanelVariant, PanelColors } from './internal/panel.js';
|
|
21
21
|
export { isStatusLevel, parseSnapshot } from './status.js';
|
|
22
|
+
export { safeHref } from './safe-href.js';
|
|
22
23
|
export type { StatusLevel, StatusComponent, StatusGroup, StatusSnapshot } from './status.js';
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Validate a consumer-supplied URL before binding it to an `href` attribute.
|
|
3
|
+
*
|
|
4
|
+
* Allows `https:` (all hosts) and `http:` on `localhost`/`127.0.0.1` (dev only).
|
|
5
|
+
* Returns `undefined` for `javascript:`, `data:`, or any other disallowed scheme so Vue
|
|
6
|
+
* renders no `href` attribute rather than a potentially-executable link.
|
|
7
|
+
*/
|
|
8
|
+
export declare function safeHref(url: string | undefined | null): string | undefined;
|
package/dist/status.d.ts
CHANGED
|
@@ -21,7 +21,9 @@ export interface StatusSnapshot {
|
|
|
21
21
|
export declare function isStatusLevel(s: unknown): s is StatusLevel;
|
|
22
22
|
/**
|
|
23
23
|
* Parse and validate a raw API response as a `StatusSnapshot`.
|
|
24
|
-
* Returns `null` if the required fields are absent or have unexpected types
|
|
25
|
-
*
|
|
24
|
+
* Returns `null` if the required top-level fields are absent or have unexpected types.
|
|
25
|
+
* Per-group and per-component fields are sanitized: unknown status values are coerced to
|
|
26
|
+
* `'unknown'`; name fields are stripped of HTML-sensitive characters. Groups or components
|
|
27
|
+
* with empty/missing names are dropped.
|
|
26
28
|
*/
|
|
27
29
|
export declare function parseSnapshot(raw: unknown): StatusSnapshot | null;
|
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, createTextVNode as a, defineComponent as o, mergeProps as s, normalizeClass as c, normalizeStyle as l, onMounted as ee, onUnmounted as
|
|
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 ee, onUnmounted as te, openBlock as u, ref as d, renderList as f, renderSlot as p, toDisplayString as m, unref as h, useModel as g, vModelSelect as ne, watch as re, withDirectives as ie } from "vue";
|
|
2
2
|
//#region src/internal/panel.ts
|
|
3
|
-
function
|
|
3
|
+
function _(e, t) {
|
|
4
4
|
let n;
|
|
5
5
|
return n = e === "transparent" ? {
|
|
6
6
|
"--_bg": "transparent",
|
|
@@ -35,33 +35,33 @@ var ae = { class: "mw-header__brand" }, oe = { class: "mw-header__center" }, se
|
|
|
35
35
|
}
|
|
36
36
|
},
|
|
37
37
|
setup(e) {
|
|
38
|
-
let n = e, a = t(() =>
|
|
39
|
-
return (t, n) => (
|
|
38
|
+
let n = e, a = t(() => _(n.variant, n.colors));
|
|
39
|
+
return (t, n) => (u(), r("header", {
|
|
40
40
|
class: c(["mw-header", [`mw-header--${e.variant}`, { "mw-header--sticky": e.sticky }]]),
|
|
41
41
|
style: l(a.value)
|
|
42
42
|
}, [
|
|
43
|
-
i("div", ae, [
|
|
44
|
-
i("div", oe, [
|
|
45
|
-
i("div", se, [
|
|
43
|
+
i("div", ae, [p(t.$slots, "brand", {}, void 0, !0)]),
|
|
44
|
+
i("div", oe, [p(t.$slots, "default", {}, void 0, !0)]),
|
|
45
|
+
i("div", se, [p(t.$slots, "actions", {}, void 0, !0)])
|
|
46
46
|
], 6));
|
|
47
47
|
}
|
|
48
|
-
}),
|
|
48
|
+
}), v = (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
|
-
},
|
|
52
|
+
}, le = /*#__PURE__*/ v(ce, [["__scopeId", "data-v-9b9826d5"]]), ue = {
|
|
53
53
|
key: 0,
|
|
54
54
|
class: "mw-sidebar__head"
|
|
55
|
-
},
|
|
55
|
+
}, de = {
|
|
56
56
|
class: "mw-sidebar__nav",
|
|
57
57
|
"aria-label": "Primary"
|
|
58
|
-
},
|
|
58
|
+
}, y = {
|
|
59
59
|
key: 1,
|
|
60
60
|
class: "mw-sidebar__body"
|
|
61
|
-
},
|
|
61
|
+
}, b = {
|
|
62
62
|
key: 2,
|
|
63
63
|
class: "mw-sidebar__foot"
|
|
64
|
-
},
|
|
64
|
+
}, x = /*#__PURE__*/ v(/* @__PURE__ */ o({
|
|
65
65
|
__name: "AppSidebar",
|
|
66
66
|
props: {
|
|
67
67
|
variant: { default: "dark" },
|
|
@@ -70,45 +70,75 @@ var ae = { class: "mw-header__brand" }, oe = { class: "mw-header__center" }, se
|
|
|
70
70
|
},
|
|
71
71
|
setup(e) {
|
|
72
72
|
let a = e, o = t(() => {
|
|
73
|
-
let e =
|
|
73
|
+
let e = _(a.variant, a.colors);
|
|
74
74
|
return a.width && (e["--mw-sidebar-width"] = a.width), e;
|
|
75
75
|
});
|
|
76
|
-
return (t, a) => (
|
|
76
|
+
return (t, a) => (u(), r("aside", {
|
|
77
77
|
class: c(["mw-sidebar", `mw-sidebar--${e.variant}`]),
|
|
78
78
|
style: l(o.value)
|
|
79
79
|
}, [
|
|
80
|
-
t.$slots.head ? (
|
|
81
|
-
i("nav",
|
|
82
|
-
t.$slots.body ? (
|
|
83
|
-
t.$slots.foot ? (
|
|
80
|
+
t.$slots.head ? (u(), r("div", ue, [p(t.$slots, "head", {}, void 0, !0)])) : n("", !0),
|
|
81
|
+
i("nav", de, [p(t.$slots, "default", {}, void 0, !0)]),
|
|
82
|
+
t.$slots.body ? (u(), r("div", y, [p(t.$slots, "body", {}, void 0, !0)])) : n("", !0),
|
|
83
|
+
t.$slots.foot ? (u(), r("div", b, [p(t.$slots, "foot", {}, void 0, !0)])) : n("", !0)
|
|
84
84
|
], 6));
|
|
85
85
|
}
|
|
86
|
-
}), [["__scopeId", "data-v-
|
|
86
|
+
}), [["__scopeId", "data-v-a2b8405c"]]);
|
|
87
|
+
//#endregion
|
|
88
|
+
//#region src/safe-href.ts
|
|
89
|
+
function S(e) {
|
|
90
|
+
if (e) try {
|
|
91
|
+
let t = new URL(e);
|
|
92
|
+
if (t.protocol === "https:" || t.protocol === "http:" && (t.hostname === "localhost" || t.hostname === "127.0.0.1")) return e;
|
|
93
|
+
} catch {}
|
|
94
|
+
}
|
|
95
|
+
//#endregion
|
|
96
|
+
//#region src/components/AppFooter.vue?vue&type=script&setup=true&lang.ts
|
|
97
|
+
var C = { class: "mw-footer__start" }, w = { class: "mw-footer__center" }, T = { class: "mw-footer__end" }, E = ["href"], D = ["href"], O = /*#__PURE__*/ v(/* @__PURE__ */ o({
|
|
87
98
|
__name: "AppFooter",
|
|
88
99
|
props: {
|
|
89
100
|
variant: { default: "transparent" },
|
|
90
|
-
colors: {}
|
|
101
|
+
colors: {},
|
|
102
|
+
docsUrl: {},
|
|
103
|
+
devUrl: {}
|
|
91
104
|
},
|
|
92
105
|
setup(e) {
|
|
93
|
-
let
|
|
94
|
-
return (t,
|
|
106
|
+
let a = e, o = t(() => _(a.variant, a.colors));
|
|
107
|
+
return (t, a) => (u(), r("footer", {
|
|
95
108
|
class: c(["mw-footer", `mw-footer--${e.variant}`]),
|
|
96
|
-
style: l(
|
|
109
|
+
style: l(o.value)
|
|
97
110
|
}, [
|
|
98
|
-
i("div",
|
|
99
|
-
i("div",
|
|
100
|
-
i("div",
|
|
111
|
+
i("div", C, [p(t.$slots, "start", {}, void 0, !0)]),
|
|
112
|
+
i("div", w, [p(t.$slots, "default", {}, void 0, !0)]),
|
|
113
|
+
i("div", T, [
|
|
114
|
+
p(t.$slots, "end", {}, void 0, !0),
|
|
115
|
+
e.docsUrl ? (u(), r("a", {
|
|
116
|
+
key: 0,
|
|
117
|
+
href: h(S)(e.docsUrl),
|
|
118
|
+
target: "_blank",
|
|
119
|
+
rel: "noopener noreferrer",
|
|
120
|
+
class: "mw-footer__docs-link"
|
|
121
|
+
}, "Documentation", 8, E)) : n("", !0),
|
|
122
|
+
e.devUrl ? (u(), r("a", {
|
|
123
|
+
key: 1,
|
|
124
|
+
href: h(S)(e.devUrl),
|
|
125
|
+
target: "_blank",
|
|
126
|
+
rel: "noopener noreferrer",
|
|
127
|
+
"aria-label": "Developer documentation",
|
|
128
|
+
class: "mw-footer__docs-link"
|
|
129
|
+
}, "Developer docs", 8, D)) : n("", !0)
|
|
130
|
+
])
|
|
101
131
|
], 6));
|
|
102
132
|
}
|
|
103
|
-
}), [["__scopeId", "data-v-
|
|
133
|
+
}), [["__scopeId", "data-v-979579a9"]]), k = {
|
|
104
134
|
class: "mw-mode",
|
|
105
135
|
role: "group",
|
|
106
136
|
"aria-label": "Colour mode"
|
|
107
|
-
},
|
|
137
|
+
}, A = [
|
|
108
138
|
"aria-pressed",
|
|
109
139
|
"title",
|
|
110
140
|
"onClick"
|
|
111
|
-
],
|
|
141
|
+
], j = { "aria-hidden": "true" }, M = { class: "mw-mode__label" }, N = /*#__PURE__*/ v(/* @__PURE__ */ o({
|
|
112
142
|
__name: "ColorModeControl",
|
|
113
143
|
props: {
|
|
114
144
|
modelValue: {},
|
|
@@ -129,16 +159,16 @@ var ae = { class: "mw-header__brand" }, oe = { class: "mw-header__center" }, se
|
|
|
129
159
|
dark: "☾",
|
|
130
160
|
system: "🖵"
|
|
131
161
|
};
|
|
132
|
-
return (o, s) => (
|
|
162
|
+
return (o, s) => (u(), r("div", k, [(u(!0), r(e, null, f(t.modes, (e) => (u(), r("button", {
|
|
133
163
|
key: e,
|
|
134
164
|
type: "button",
|
|
135
165
|
class: c(["mw-mode__btn", { "is-active": t.modelValue === e }]),
|
|
136
166
|
"aria-pressed": t.modelValue === e,
|
|
137
167
|
title: n[e],
|
|
138
168
|
onClick: (t) => o.$emit("update:modelValue", e)
|
|
139
|
-
}, [i("span",
|
|
169
|
+
}, [i("span", j, m(a[e]), 1), i("span", M, m(n[e]), 1)], 10, A))), 128))]));
|
|
140
170
|
}
|
|
141
|
-
}), [["__scopeId", "data-v-
|
|
171
|
+
}), [["__scopeId", "data-v-e2ea0d79"]]), P = ["type", "disabled"], F = /*#__PURE__*/ v(/* @__PURE__ */ o({
|
|
142
172
|
__name: "UiButton",
|
|
143
173
|
props: {
|
|
144
174
|
variant: { default: "primary" },
|
|
@@ -149,29 +179,29 @@ var ae = { class: "mw-header__brand" }, oe = { class: "mw-header__center" }, se
|
|
|
149
179
|
}
|
|
150
180
|
},
|
|
151
181
|
setup(e) {
|
|
152
|
-
return (t, n) => (
|
|
182
|
+
return (t, n) => (u(), r("button", {
|
|
153
183
|
type: e.type,
|
|
154
184
|
disabled: e.disabled,
|
|
155
185
|
class: c(["mw-btn", `mw-btn--${e.variant}`])
|
|
156
|
-
}, [
|
|
186
|
+
}, [p(t.$slots, "default", {}, void 0, !0)], 10, P));
|
|
157
187
|
}
|
|
158
|
-
}), [["__scopeId", "data-v-
|
|
188
|
+
}), [["__scopeId", "data-v-bc33cc23"]]), I = { class: "mw-card" }, L = {
|
|
159
189
|
key: 0,
|
|
160
190
|
class: "mw-card__header"
|
|
161
|
-
},
|
|
191
|
+
}, R = { class: "mw-card__title" }, z = { class: "mw-card__body" }, B = {
|
|
162
192
|
key: 1,
|
|
163
193
|
class: "mw-card__footer"
|
|
164
|
-
},
|
|
194
|
+
}, V = /*#__PURE__*/ v(/* @__PURE__ */ o({
|
|
165
195
|
__name: "UiCard",
|
|
166
196
|
props: { title: {} },
|
|
167
197
|
setup(e) {
|
|
168
|
-
return (t, a) => (
|
|
169
|
-
e.title || t.$slots.header ? (
|
|
170
|
-
i("div",
|
|
171
|
-
t.$slots.footer ? (
|
|
198
|
+
return (t, a) => (u(), r("section", I, [
|
|
199
|
+
e.title || t.$slots.header ? (u(), r("header", L, [p(t.$slots, "header", {}, () => [i("h3", R, m(e.title), 1)], !0)])) : n("", !0),
|
|
200
|
+
i("div", z, [p(t.$slots, "default", {}, void 0, !0)]),
|
|
201
|
+
t.$slots.footer ? (u(), r("footer", B, [p(t.$slots, "footer", {}, void 0, !0)])) : n("", !0)
|
|
172
202
|
]));
|
|
173
203
|
}
|
|
174
|
-
}), [["__scopeId", "data-v-
|
|
204
|
+
}), [["__scopeId", "data-v-883f87f5"]]), H = { class: "mw-select" }, fe = /*#__PURE__*/ v(/* @__PURE__ */ o({
|
|
175
205
|
inheritAttrs: !1,
|
|
176
206
|
__name: "UiSelect",
|
|
177
207
|
props: {
|
|
@@ -180,8 +210,8 @@ var ae = { class: "mw-header__brand" }, oe = { class: "mw-header__center" }, se
|
|
|
180
210
|
},
|
|
181
211
|
emits: ["update:modelValue"],
|
|
182
212
|
setup(e) {
|
|
183
|
-
let t =
|
|
184
|
-
return (e, n) => (
|
|
213
|
+
let t = g(e, "modelValue");
|
|
214
|
+
return (e, n) => (u(), r("div", H, [ie(i("select", s(e.$attrs, { "onUpdate:modelValue": n[0] ||= (e) => t.value = e }), [p(e.$slots, "default", {}, void 0, !0)], 16), [[ne, t.value]]), n[1] ||= i("svg", {
|
|
185
215
|
class: "mw-select__chevron",
|
|
186
216
|
xmlns: "http://www.w3.org/2000/svg",
|
|
187
217
|
width: "12",
|
|
@@ -190,7 +220,7 @@ var ae = { class: "mw-header__brand" }, oe = { class: "mw-header__center" }, se
|
|
|
190
220
|
"aria-hidden": "true"
|
|
191
221
|
}, [i("path", { d: "M1 1l5 5 5-5" })], -1)]));
|
|
192
222
|
}
|
|
193
|
-
}), [["__scopeId", "data-v-
|
|
223
|
+
}), [["__scopeId", "data-v-7e206184"]]), pe = ["role"], me = /*#__PURE__*/ v(/* @__PURE__ */ o({
|
|
194
224
|
__name: "UiNotice",
|
|
195
225
|
props: { type: {} },
|
|
196
226
|
setup(e) {
|
|
@@ -198,16 +228,16 @@ var ae = { class: "mw-header__brand" }, oe = { class: "mw-header__center" }, se
|
|
|
198
228
|
if (n.type === "error") return "alert";
|
|
199
229
|
if (n.type === "ok") return "status";
|
|
200
230
|
});
|
|
201
|
-
return (t, n) => (
|
|
231
|
+
return (t, n) => (u(), r("p", {
|
|
202
232
|
class: c(["mw-notice", e.type && e.type !== "info" ? `mw-notice--${e.type}` : ""]),
|
|
203
233
|
role: i.value
|
|
204
|
-
}, [
|
|
234
|
+
}, [p(t.$slots, "default", {}, void 0, !0)], 10, pe));
|
|
205
235
|
}
|
|
206
|
-
}), [["__scopeId", "data-v-
|
|
236
|
+
}), [["__scopeId", "data-v-ee7fffb1"]]), he = ["disabled", "aria-current"], ge = {
|
|
207
237
|
key: 0,
|
|
208
238
|
class: "sidebar-item__icon",
|
|
209
239
|
"aria-hidden": "true"
|
|
210
|
-
},
|
|
240
|
+
}, _e = { class: "sidebar-item__label" }, ve = /*#__PURE__*/ v(/* @__PURE__ */ o({
|
|
211
241
|
__name: "SidebarItem",
|
|
212
242
|
props: {
|
|
213
243
|
label: {},
|
|
@@ -222,14 +252,14 @@ var ae = { class: "mw-header__brand" }, oe = { class: "mw-header__center" }, se
|
|
|
222
252
|
}
|
|
223
253
|
},
|
|
224
254
|
setup(e) {
|
|
225
|
-
return (t, a) => (
|
|
255
|
+
return (t, a) => (u(), r("button", {
|
|
226
256
|
type: "button",
|
|
227
257
|
class: c(["sidebar-item", { "is-active": e.active }]),
|
|
228
258
|
disabled: e.disabled,
|
|
229
259
|
"aria-current": e.active ? "page" : void 0
|
|
230
|
-
}, [e.icon ? (
|
|
260
|
+
}, [e.icon ? (u(), r("span", ge, m(e.icon), 1)) : n("", !0), i("span", _e, m(e.label), 1)], 10, he));
|
|
231
261
|
}
|
|
232
|
-
}), [["__scopeId", "data-v-
|
|
262
|
+
}), [["__scopeId", "data-v-8da2d583"]]), ye = ["aria-label"], be = ["aria-current", "onClick"], xe = /*#__PURE__*/ v(/* @__PURE__ */ o({
|
|
233
263
|
__name: "AppTabNav",
|
|
234
264
|
props: {
|
|
235
265
|
tabs: {},
|
|
@@ -239,18 +269,18 @@ var ae = { class: "mw-header__brand" }, oe = { class: "mw-header__center" }, se
|
|
|
239
269
|
emits: ["update:modelValue"],
|
|
240
270
|
setup(t, { emit: n }) {
|
|
241
271
|
let i = n;
|
|
242
|
-
return (n, a) => (
|
|
272
|
+
return (n, a) => (u(), r("nav", {
|
|
243
273
|
class: "mw-tab-nav",
|
|
244
274
|
"aria-label": t.ariaLabel
|
|
245
|
-
}, [(
|
|
275
|
+
}, [(u(!0), r(e, null, f(t.tabs, (e) => (u(), r("button", {
|
|
246
276
|
key: e.id,
|
|
247
277
|
type: "button",
|
|
248
278
|
class: c(["mw-tab-nav__tab", { "mw-tab-nav__tab--active": t.modelValue === e.id }]),
|
|
249
279
|
"aria-current": t.modelValue === e.id ? "page" : void 0,
|
|
250
280
|
onClick: (t) => i("update:modelValue", e.id)
|
|
251
|
-
},
|
|
281
|
+
}, m(e.label), 11, be))), 128))], 8, ye));
|
|
252
282
|
}
|
|
253
|
-
}), [["__scopeId", "data-v-
|
|
283
|
+
}), [["__scopeId", "data-v-97d31503"]]), Se = { class: "ca-root" }, Ce = ["title"], we = ["title", "aria-label"], Te = {
|
|
254
284
|
key: 0,
|
|
255
285
|
class: "ca-icon",
|
|
256
286
|
viewBox: "0 0 24 24",
|
|
@@ -262,7 +292,7 @@ var ae = { class: "mw-header__brand" }, oe = { class: "mw-header__center" }, se
|
|
|
262
292
|
"stroke-linecap": "round",
|
|
263
293
|
"stroke-linejoin": "round",
|
|
264
294
|
"aria-hidden": "true"
|
|
265
|
-
},
|
|
295
|
+
}, Ee = {
|
|
266
296
|
key: 1,
|
|
267
297
|
class: "ca-icon",
|
|
268
298
|
viewBox: "0 0 24 24",
|
|
@@ -274,7 +304,7 @@ var ae = { class: "mw-header__brand" }, oe = { class: "mw-header__center" }, se
|
|
|
274
304
|
"stroke-linecap": "round",
|
|
275
305
|
"stroke-linejoin": "round",
|
|
276
306
|
"aria-hidden": "true"
|
|
277
|
-
},
|
|
307
|
+
}, De = /*#__PURE__*/ v(/* @__PURE__ */ o({
|
|
278
308
|
__name: "CopyableAddress",
|
|
279
309
|
props: {
|
|
280
310
|
address: {},
|
|
@@ -286,7 +316,7 @@ var ae = { class: "mw-header__brand" }, oe = { class: "mw-header__center" }, se
|
|
|
286
316
|
label: { default: "Copy" }
|
|
287
317
|
},
|
|
288
318
|
setup(e) {
|
|
289
|
-
let n = e, o =
|
|
319
|
+
let n = e, o = d(!1), s = t(() => {
|
|
290
320
|
if (!n.truncate) return n.address;
|
|
291
321
|
let [e, t] = n.chars;
|
|
292
322
|
return `${n.address.slice(0, e)}…${n.address.slice(-t)}`;
|
|
@@ -296,25 +326,25 @@ var ae = { class: "mw-header__brand" }, oe = { class: "mw-header__center" }, se
|
|
|
296
326
|
o.value = !1;
|
|
297
327
|
}, 1500);
|
|
298
328
|
}
|
|
299
|
-
return (t, n) => (
|
|
329
|
+
return (t, n) => (u(), r("span", Se, [i("span", {
|
|
300
330
|
class: "ca-value",
|
|
301
331
|
title: e.address
|
|
302
|
-
}, [
|
|
332
|
+
}, [p(t.$slots, "default", {}, () => [a(m(s.value), 1)], !0)], 8, Ce), i("button", {
|
|
303
333
|
type: "button",
|
|
304
334
|
class: c(["ca-copy", { "ca-copy--copied": o.value }]),
|
|
305
335
|
title: o.value ? "Copied!" : e.label,
|
|
306
336
|
"aria-label": o.value ? "Copied" : e.label,
|
|
307
337
|
onClick: l
|
|
308
|
-
}, [o.value ? (
|
|
338
|
+
}, [o.value ? (u(), r("svg", Te, [...n[0] ||= [i("polyline", { points: "20 6 9 17 4 12" }, null, -1)]])) : (u(), r("svg", Ee, [...n[1] ||= [i("rect", {
|
|
309
339
|
x: "9",
|
|
310
340
|
y: "9",
|
|
311
341
|
width: "13",
|
|
312
342
|
height: "13",
|
|
313
343
|
rx: "2",
|
|
314
344
|
ry: "2"
|
|
315
|
-
}, 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,
|
|
345
|
+
}, 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, we)]));
|
|
316
346
|
}
|
|
317
|
-
}), [["__scopeId", "data-v-
|
|
347
|
+
}), [["__scopeId", "data-v-b43dabdd"]]), Oe = ["href", "title"], ke = /*#__PURE__*/ v(/* @__PURE__ */ o({
|
|
318
348
|
__name: "ExplorerLink",
|
|
319
349
|
props: {
|
|
320
350
|
href: {},
|
|
@@ -332,31 +362,62 @@ var ae = { class: "mw-header__brand" }, oe = { class: "mw-header__center" }, se
|
|
|
332
362
|
let [e, t] = n.chars;
|
|
333
363
|
return `${n.value.slice(0, e)}…${n.value.slice(-t)}`;
|
|
334
364
|
});
|
|
335
|
-
return (t, n) => (
|
|
365
|
+
return (t, n) => (u(), r("a", {
|
|
336
366
|
class: "el-root",
|
|
337
|
-
href: e.href,
|
|
367
|
+
href: h(S)(e.href),
|
|
338
368
|
target: "_blank",
|
|
339
369
|
rel: "noopener noreferrer",
|
|
340
370
|
title: e.value
|
|
341
|
-
}, [
|
|
371
|
+
}, [p(t.$slots, "default", {}, () => [a(m(i.value), 1)], !0)], 8, Oe));
|
|
342
372
|
}
|
|
343
|
-
}), [["__scopeId", "data-v-
|
|
373
|
+
}), [["__scopeId", "data-v-073d1bbe"]]), Ae = /* @__PURE__ */ new Set([
|
|
344
374
|
"operational",
|
|
345
375
|
"degraded",
|
|
346
376
|
"down",
|
|
347
377
|
"unknown"
|
|
348
378
|
]);
|
|
349
|
-
function
|
|
350
|
-
return typeof e == "string" &&
|
|
379
|
+
function U(e) {
|
|
380
|
+
return typeof e == "string" && Ae.has(e);
|
|
381
|
+
}
|
|
382
|
+
function W(e) {
|
|
383
|
+
return U(e) ? e : "unknown";
|
|
384
|
+
}
|
|
385
|
+
function G(e) {
|
|
386
|
+
return typeof e != "string" || e.trim() === "" ? "" : e.replace(/[<>&"]/g, "");
|
|
351
387
|
}
|
|
352
|
-
function
|
|
388
|
+
function je(e) {
|
|
389
|
+
if (typeof e != "object" || !e) return null;
|
|
390
|
+
let t = e, n = G(t.name);
|
|
391
|
+
return n ? {
|
|
392
|
+
name: n,
|
|
393
|
+
status: W(t.status)
|
|
394
|
+
} : null;
|
|
395
|
+
}
|
|
396
|
+
function Me(e) {
|
|
397
|
+
if (typeof e != "object" || !e) return null;
|
|
398
|
+
let t = e, n = G(t.name);
|
|
399
|
+
if (!n) return null;
|
|
400
|
+
let r = Array.isArray(t.components) ? t.components.map(je).filter((e) => e !== null) : [];
|
|
401
|
+
return {
|
|
402
|
+
name: n,
|
|
403
|
+
status: W(t.status),
|
|
404
|
+
components: r
|
|
405
|
+
};
|
|
406
|
+
}
|
|
407
|
+
function K(e) {
|
|
353
408
|
if (typeof e != "object" || !e) return null;
|
|
354
409
|
let t = e;
|
|
355
|
-
|
|
410
|
+
if (!U(t.overall) || typeof t.generated_at != "string" || !Array.isArray(t.groups)) return null;
|
|
411
|
+
let n = t.groups.map(Me).filter((e) => e !== null);
|
|
412
|
+
return {
|
|
413
|
+
generated_at: t.generated_at,
|
|
414
|
+
overall: t.overall,
|
|
415
|
+
groups: n
|
|
416
|
+
};
|
|
356
417
|
}
|
|
357
418
|
//#endregion
|
|
358
419
|
//#region src/components/StatusWidget.vue?vue&type=script&setup=true&lang.ts
|
|
359
|
-
var
|
|
420
|
+
var Ne = ["href", "title"], q = { class: "status-widget__label" }, Pe = /*#__PURE__*/ v(/* @__PURE__ */ o({
|
|
360
421
|
__name: "StatusWidget",
|
|
361
422
|
props: {
|
|
362
423
|
apiUrl: { default: "https://status.meddleware.co.uk/api/status" },
|
|
@@ -374,12 +435,12 @@ var we = ["href", "title"], Te = { class: "status-widget__label" }, Ee = /*#__PU
|
|
|
374
435
|
degraded: "Degraded",
|
|
375
436
|
down: "Major outage",
|
|
376
437
|
unknown: "Status unknown"
|
|
377
|
-
}, o =
|
|
378
|
-
async function
|
|
438
|
+
}, o = d("ok"), s = d("All systems operational"), l = null;
|
|
439
|
+
async function f() {
|
|
379
440
|
try {
|
|
380
441
|
let e = await fetch(t.apiUrl);
|
|
381
442
|
if (!e.ok) throw Error(`HTTP ${e.status}`);
|
|
382
|
-
let r =
|
|
443
|
+
let r = K(await e.json());
|
|
383
444
|
if (!r) throw Error("unexpected response shape");
|
|
384
445
|
o.value = n[r.overall], s.value = a[r.overall];
|
|
385
446
|
} catch {
|
|
@@ -387,41 +448,41 @@ var we = ["href", "title"], Te = { class: "status-widget__label" }, Ee = /*#__PU
|
|
|
387
448
|
}
|
|
388
449
|
}
|
|
389
450
|
return ee(() => {
|
|
390
|
-
|
|
391
|
-
}),
|
|
451
|
+
f(), l = setInterval(f, t.pollInterval);
|
|
452
|
+
}), te(() => {
|
|
392
453
|
l !== null && clearInterval(l);
|
|
393
|
-
}), (t, n) => (
|
|
394
|
-
href: e.href,
|
|
454
|
+
}), (t, n) => (u(), r("a", {
|
|
455
|
+
href: h(S)(e.href),
|
|
395
456
|
target: "_blank",
|
|
396
|
-
rel: "noopener",
|
|
457
|
+
rel: "noopener noreferrer",
|
|
397
458
|
class: c(["status-widget", `status-widget--${o.value}`]),
|
|
398
459
|
title: `Platform status: ${s.value}`
|
|
399
460
|
}, [n[0] ||= i("span", {
|
|
400
461
|
class: "status-widget__dot",
|
|
401
462
|
"aria-hidden": "true"
|
|
402
|
-
}, null, -1), i("span",
|
|
463
|
+
}, null, -1), i("span", q, m(s.value), 1)], 10, Ne));
|
|
403
464
|
}
|
|
404
|
-
}), [["__scopeId", "data-v-
|
|
465
|
+
}), [["__scopeId", "data-v-6436368e"]]), J = {
|
|
405
466
|
mainnet: "https://suivision.xyz",
|
|
406
467
|
testnet: "https://testnet.suivision.xyz",
|
|
407
468
|
devnet: "https://devnet.suivision.xyz"
|
|
408
469
|
};
|
|
409
|
-
function
|
|
470
|
+
function Fe(e, t, n = "testnet") {
|
|
410
471
|
return `${J[n] ?? J.testnet}/${e}/${t}`;
|
|
411
472
|
}
|
|
412
473
|
//#endregion
|
|
413
474
|
//#region src/composables/useColorMode.ts
|
|
414
|
-
var Y = "mw-color-mode", X =
|
|
415
|
-
function
|
|
475
|
+
var Y = "mw-color-mode", X = d("system"), Z = !1;
|
|
476
|
+
function Ie() {
|
|
416
477
|
return typeof window < "u" && typeof window.matchMedia == "function" && window.matchMedia("(prefers-color-scheme: dark)").matches;
|
|
417
478
|
}
|
|
418
479
|
function Q(e) {
|
|
419
|
-
return e === "dark" || e === "system" &&
|
|
480
|
+
return e === "dark" || e === "system" && Ie();
|
|
420
481
|
}
|
|
421
482
|
function $(e) {
|
|
422
483
|
typeof document > "u" || document.documentElement.setAttribute("data-theme", Q(e) ? "dark" : "light");
|
|
423
484
|
}
|
|
424
|
-
function
|
|
485
|
+
function Le(e = "system") {
|
|
425
486
|
if (!Z) {
|
|
426
487
|
Z = !0;
|
|
427
488
|
let t = null;
|
|
@@ -451,4 +512,4 @@ function ke(e = "system") {
|
|
|
451
512
|
};
|
|
452
513
|
}
|
|
453
514
|
//#endregion
|
|
454
|
-
export {
|
|
515
|
+
export { O as AppFooter, le as AppHeader, x as AppSidebar, xe as AppTabNav, N as ColorModeControl, De as CopyableAddress, ke as ExplorerLink, ve as SidebarItem, Pe as StatusWidget, F as UiButton, V as UiCard, me as UiNotice, fe as UiSelect, U as isStatusLevel, K as parseSnapshot, S as safeHref, Fe as suiExplorerUrl, Le as useColorMode };
|
package/package.json
CHANGED
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@meddleware/ui",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.13",
|
|
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
|
+
"homepage": "https://docs.meddleware.co.uk/",
|
|
5
6
|
"license": "0BSD",
|
|
6
7
|
"type": "module",
|
|
7
8
|
"sideEffects": [
|
|
@@ -30,13 +31,13 @@
|
|
|
30
31
|
"vue": "^3.5.0"
|
|
31
32
|
},
|
|
32
33
|
"dependencies": {
|
|
33
|
-
"@meddleware/design-tokens": "^0.1.
|
|
34
|
+
"@meddleware/design-tokens": "^0.1.3"
|
|
34
35
|
},
|
|
35
36
|
"devDependencies": {
|
|
36
37
|
"@vitejs/plugin-vue": "^6.0.8",
|
|
37
38
|
"typescript": "^6.0.0",
|
|
38
39
|
"vite": "^8.2.2",
|
|
39
|
-
"vitest": "~
|
|
40
|
+
"vitest": "~5.0.1",
|
|
40
41
|
"vue": "^3.5.42",
|
|
41
42
|
"vue-tsc": "~3.3.11"
|
|
42
43
|
},
|