@meddleware/ui 0.1.34 → 0.1.36
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 +49 -13
- package/dist/_virtual/_plugin-vue_export-helper.js +8 -0
- package/dist/base.css +48 -2
- package/dist/components/AppFooter.css +1 -0
- package/dist/components/AppFooter.js +7 -0
- package/dist/components/AppFooter.vue_vue_type_script_setup_true_lang.js +42 -0
- package/dist/components/AppHeader.css +1 -0
- package/dist/components/AppHeader.js +7 -0
- package/dist/components/AppHeader.vue.d.ts +8 -0
- package/dist/components/AppHeader.vue_vue_type_script_setup_true_lang.js +68 -0
- package/dist/components/AppSidebar.css +1 -0
- package/dist/components/AppSidebar.js +7 -0
- package/dist/components/AppSidebar.vue.d.ts +3 -0
- package/dist/components/AppSidebar.vue_vue_type_script_setup_true_lang.js +37 -0
- package/dist/components/AppTabNav.css +1 -0
- package/dist/components/AppTabNav.js +7 -0
- package/dist/components/AppTabNav.vue.d.ts +3 -0
- package/dist/components/AppTabNav.vue_vue_type_script_setup_true_lang.js +70 -0
- package/dist/components/ColorModeControl.css +1 -0
- package/dist/components/ColorModeControl.js +7 -0
- package/dist/components/ColorModeControl.vue_vue_type_script_setup_true_lang.js +58 -0
- package/dist/components/CopyableAddress.css +1 -0
- package/dist/components/CopyableAddress.js +7 -0
- package/dist/components/CopyableAddress.vue_vue_type_script_setup_true_lang.js +28 -0
- package/dist/components/CopyrightLine.css +1 -0
- package/dist/components/CopyrightLine.js +7 -0
- package/dist/components/CopyrightLine.vue.d.ts +6 -0
- package/dist/components/CopyrightLine.vue_vue_type_script_setup_true_lang.js +80 -0
- package/dist/components/ExplorerLink.css +1 -0
- package/dist/components/ExplorerLink.js +7 -0
- package/dist/components/ExplorerLink.vue_vue_type_script_setup_true_lang.js +27 -0
- package/dist/components/SidebarGroup.css +1 -0
- package/dist/components/SidebarGroup.js +7 -0
- package/dist/components/SidebarGroup.vue_vue_type_script_setup_true_lang.js +14 -0
- package/dist/components/SidebarItem.css +1 -0
- package/dist/components/SidebarItem.js +7 -0
- package/dist/components/SidebarItem.vue.d.ts +3 -0
- package/dist/components/SidebarItem.vue_vue_type_script_setup_true_lang.js +43 -0
- package/dist/components/StatusWidget.css +1 -0
- package/dist/components/StatusWidget.js +7 -0
- package/dist/components/StatusWidget.vue_vue_type_script_setup_true_lang.js +33 -0
- package/dist/components/UiActivityFeed.css +1 -0
- package/dist/components/UiActivityFeed.js +7 -0
- package/dist/components/UiActivityFeed.vue_vue_type_script_setup_true_lang.js +13 -0
- package/dist/components/UiActivityItem.css +1 -0
- package/dist/components/UiActivityItem.js +7 -0
- package/dist/components/UiActivityItem.vue_vue_type_script_setup_true_lang.js +22 -0
- package/dist/components/UiAmount.css +1 -0
- package/dist/components/UiAmount.js +7 -0
- package/dist/components/UiAmount.vue.d.ts +12 -0
- package/dist/components/UiAmount.vue_vue_type_script_setup_true_lang.js +31 -0
- package/dist/components/UiAppShell.css +1 -0
- package/dist/components/UiAppShell.js +7 -0
- package/dist/components/UiAppShell.vue.d.ts +26 -0
- package/dist/components/UiAppShell.vue_vue_type_script_setup_true_lang.js +27 -0
- package/dist/components/UiBadge.css +1 -0
- package/dist/components/UiBadge.js +7 -0
- package/dist/components/UiBadge.vue.d.ts +10 -1
- package/dist/components/UiBadge.vue_vue_type_script_setup_true_lang.js +35 -0
- package/dist/components/UiButton.css +1 -0
- package/dist/components/UiButton.js +7 -0
- package/dist/components/UiButton.vue.d.ts +17 -7
- package/dist/components/UiButton.vue_vue_type_script_setup_true_lang.js +60 -0
- package/dist/components/UiCard.css +1 -0
- package/dist/components/UiCard.js +7 -0
- package/dist/components/UiCard.vue.d.ts +20 -6
- package/dist/components/UiCard.vue_vue_type_script_setup_true_lang.js +51 -0
- package/dist/components/UiCheckField.css +1 -0
- package/dist/components/UiCheckField.js +7 -0
- package/dist/components/UiCheckField.vue.d.ts +26 -0
- package/dist/components/UiCheckField.vue_vue_type_script_setup_true_lang.js +31 -0
- package/dist/components/UiCodeBlock.css +1 -0
- package/dist/components/UiCodeBlock.js +7 -0
- package/dist/components/UiCodeBlock.vue.d.ts +21 -0
- package/dist/components/UiCodeBlock.vue_vue_type_script_setup_true_lang.js +21 -0
- package/dist/components/UiCopyButton.css +1 -0
- package/dist/components/UiCopyButton.js +7 -0
- package/dist/components/UiCopyButton.vue.d.ts +11 -0
- package/dist/components/UiCopyButton.vue_vue_type_script_setup_true_lang.js +64 -0
- package/dist/components/UiDataTable.css +1 -0
- package/dist/components/UiDataTable.js +7 -0
- package/dist/components/UiDataTable.vue.d.ts +5 -0
- package/dist/components/UiDataTable.vue_vue_type_script_setup_true_lang.js +56 -0
- package/dist/components/UiDateTimeField.js +5 -0
- package/dist/components/UiDateTimeField.vue.d.ts +18 -0
- package/dist/components/UiDateTimeField.vue_vue_type_script_setup_true_lang.js +51 -0
- package/dist/components/UiDialog.css +1 -0
- package/dist/components/UiDialog.js +7 -0
- package/dist/components/UiDialog.vue.d.ts +8 -5
- package/dist/components/UiDialog.vue_vue_type_script_setup_true_lang.js +78 -0
- package/dist/components/UiEmptyState.css +1 -0
- package/dist/components/UiEmptyState.js +7 -0
- package/dist/components/UiEmptyState.vue.d.ts +15 -0
- package/dist/components/UiEmptyState.vue_vue_type_script_setup_true_lang.js +10 -0
- package/dist/components/UiFieldHint.css +1 -0
- package/dist/components/UiFieldHint.js +7 -0
- package/dist/components/UiFieldHint.vue_vue_type_script_setup_true_lang.js +24 -0
- package/dist/components/UiFileField.css +1 -0
- package/dist/components/UiFileField.js +7 -0
- package/dist/components/UiFileField.vue.d.ts +17 -0
- package/dist/components/UiFileField.vue_vue_type_script_setup_true_lang.js +55 -0
- package/dist/components/UiFormField.css +1 -0
- package/dist/components/UiFormField.js +7 -0
- package/dist/components/UiFormField.vue_vue_type_script_setup_true_lang.js +38 -0
- package/dist/components/UiInput.css +1 -0
- package/dist/components/UiInput.js +7 -0
- package/dist/components/UiInput.vue.d.ts +10 -0
- package/dist/components/UiInput.vue_vue_type_script_setup_true_lang.js +20 -0
- package/dist/components/UiLiveStatus.css +1 -0
- package/dist/components/UiLiveStatus.js +7 -0
- package/dist/components/UiLiveStatus.vue.d.ts +19 -0
- package/dist/components/UiLiveStatus.vue_vue_type_script_setup_true_lang.js +17 -0
- package/dist/components/UiMeter.css +1 -0
- package/dist/components/UiMeter.js +7 -0
- package/dist/components/UiMeter.vue.d.ts +11 -0
- package/dist/components/UiMeter.vue_vue_type_script_setup_true_lang.js +41 -0
- package/dist/components/UiNotice.css +1 -0
- package/dist/components/UiNotice.js +7 -0
- package/dist/components/UiNotice.vue.d.ts +16 -8
- package/dist/components/UiNotice.vue_vue_type_script_setup_true_lang.js +22 -0
- package/dist/components/UiPager.css +1 -0
- package/dist/components/UiPager.js +7 -0
- package/dist/components/UiPager.vue.d.ts +23 -0
- package/dist/components/UiPager.vue_vue_type_script_setup_true_lang.js +46 -0
- package/dist/components/UiPanel.css +1 -0
- package/dist/components/UiPanel.js +7 -0
- package/dist/components/UiPanel.vue_vue_type_script_setup_true_lang.js +21 -0
- package/dist/components/UiSegmentedControl.css +1 -0
- package/dist/components/UiSegmentedControl.js +7 -0
- package/dist/components/UiSegmentedControl.vue.d.ts +11 -1
- package/dist/components/UiSegmentedControl.vue_vue_type_script_setup_true_lang.js +57 -0
- package/dist/components/UiSelect.css +1 -0
- package/dist/components/UiSelect.js +7 -0
- package/dist/components/UiSelect.vue.d.ts +2 -1
- package/dist/components/UiSelect.vue_vue_type_script_setup_true_lang.js +19 -0
- package/dist/components/UiSelectField.js +5 -0
- package/dist/components/UiSelectField.vue.d.ts +29 -0
- package/dist/components/UiSelectField.vue_vue_type_script_setup_true_lang.js +58 -0
- package/dist/components/UiSkipLink.css +1 -0
- package/dist/components/UiSkipLink.js +7 -0
- package/dist/components/UiSkipLink.vue.d.ts +8 -0
- package/dist/components/UiSkipLink.vue_vue_type_script_setup_true_lang.js +14 -0
- package/dist/components/UiStatGrid.css +1 -0
- package/dist/components/UiStatGrid.js +7 -0
- package/dist/components/UiStatGrid.vue_vue_type_script_setup_true_lang.js +10 -0
- package/dist/components/UiStatRow.css +1 -0
- package/dist/components/UiStatRow.js +7 -0
- package/dist/components/UiStatRow.vue_vue_type_script_setup_true_lang.js +19 -0
- package/dist/components/UiStatusBar.css +1 -0
- package/dist/components/UiStatusBar.js +7 -0
- package/dist/components/UiStatusBar.vue_vue_type_script_setup_true_lang.js +45 -0
- package/dist/components/UiStatusDot.css +1 -0
- package/dist/components/UiStatusDot.js +7 -0
- package/dist/components/UiStatusDot.vue.d.ts +6 -2
- package/dist/components/UiStatusDot.vue_vue_type_script_setup_true_lang.js +26 -0
- package/dist/components/UiStepper.css +1 -0
- package/dist/components/UiStepper.js +7 -0
- package/dist/components/UiStepper.vue.d.ts +10 -2
- package/dist/components/UiStepper.vue_vue_type_script_setup_true_lang.js +55 -0
- package/dist/components/UiTabPanel.css +1 -0
- package/dist/components/UiTabPanel.js +7 -0
- package/dist/components/UiTabPanel.vue_vue_type_script_setup_true_lang.js +22 -0
- package/dist/components/UiTextField.js +5 -0
- package/dist/components/UiTextField.vue.d.ts +35 -0
- package/dist/components/UiTextField.vue_vue_type_script_setup_true_lang.js +59 -0
- package/dist/components/UiTextarea.css +1 -0
- package/dist/components/UiTextarea.js +7 -0
- package/dist/components/UiTextarea.vue.d.ts +10 -0
- package/dist/components/UiTextarea.vue_vue_type_script_setup_true_lang.js +19 -0
- package/dist/components/UiToolIntro.css +1 -0
- package/dist/components/UiToolIntro.js +7 -0
- package/dist/components/UiToolIntro.vue_vue_type_script_setup_true_lang.js +10 -0
- package/dist/components/UiToolbar.css +1 -0
- package/dist/components/UiToolbar.js +7 -0
- package/dist/components/UiToolbar.vue.d.ts +5 -2
- package/dist/components/UiToolbar.vue_vue_type_script_setup_true_lang.js +49 -0
- package/dist/components/UiToolbarButton.css +1 -0
- package/dist/components/UiToolbarButton.js +7 -0
- package/dist/components/UiToolbarButton.vue_vue_type_script_setup_true_lang.js +13 -0
- package/dist/composables/useColorMode.js +46 -0
- package/dist/composables/useNow.d.ts +6 -0
- package/dist/composables/useNow.js +12 -0
- package/dist/composables/usePager.d.ts +28 -0
- package/dist/composables/usePager.js +36 -0
- package/dist/composables/useSeason.js +8 -0
- package/dist/composables/useStatusSnapshot.d.ts +28 -0
- package/dist/composables/useStatusSnapshot.js +38 -0
- package/dist/index.d.ts +28 -8
- package/dist/index.js +58 -0
- package/dist/internal/panel.d.ts +8 -2
- package/dist/internal/panel.js +29 -0
- package/dist/reset.css +1 -0
- package/dist/runtime-config.js +73 -0
- package/dist/styles/reset.d.ts +1 -0
- package/dist/tabs.js +9 -0
- package/dist/theme-init.js +26 -0
- package/package.json +15 -11
- package/dist/explorer.d.ts +0 -13
- package/dist/safe-href.d.ts +0 -20
- package/dist/status.d.ts +0 -29
- package/dist/truncate.d.ts +0 -14
- package/dist/ui.js +0 -1086
|
@@ -0,0 +1 @@
|
|
|
1
|
+
@layer mw.reset;@layer mw.components{.ui-stepper[data-v-8a6485e2]{margin:0 0 var(--space-md);padding:0;list-style:none;display:flex}.ui-stepper--vertical[data-v-8a6485e2]{gap:var(--space-xs);flex-direction:column;margin:0}.ui-stepper__step[data-v-8a6485e2]{align-items:center;gap:var(--space-2xs);flex-direction:column;flex:1 1 0;min-width:0;display:flex;position:relative}.ui-stepper--vertical .ui-stepper__step[data-v-8a6485e2]{align-items:center;gap:var(--space-xs);flex-direction:row}.ui-stepper--horizontal .ui-stepper__step[data-v-8a6485e2]:not(:first-child):before{content:"";top:var(--space-xs);height:var(--space-4xs);background:var(--border);z-index:0;position:absolute;left:-50%;right:50%}.ui-stepper--horizontal .ui-stepper__step.is-done[data-v-8a6485e2]:before,.ui-stepper--horizontal .ui-stepper__step.is-active[data-v-8a6485e2]:before{background:var(--accent)}.ui-stepper__badge[data-v-8a6485e2]{z-index:var(--z-raised);width:var(--space-md);height:var(--space-md);font-size:var(--font-size-sm);font-weight:var(--font-weight-semibold);border:var(--space-4xs) solid var(--border);background:var(--surface);color:var(--muted);cursor:default;transition:background-color var(--transition-base), border-color var(--transition-base);border-radius:50%;flex-shrink:0;justify-content:center;align-items:center;padding:0;font-family:inherit;line-height:1;display:flex;position:relative}button.ui-stepper__badge[data-v-8a6485e2]{cursor:pointer}button.ui-stepper__badge[data-v-8a6485e2]:focus-visible{outline:2px solid var(--focus-ring);outline-offset:2px}.is-done .ui-stepper__badge[data-v-8a6485e2]{background:var(--accent);border-color:var(--accent);color:var(--accent-contrast)}.is-active .ui-stepper__badge[data-v-8a6485e2],.is-busy .ui-stepper__badge[data-v-8a6485e2]{background:color-mix(in srgb, var(--accent) 12%, var(--surface));border-color:var(--accent);color:var(--accent)}.is-error .ui-stepper__badge[data-v-8a6485e2]{background:color-mix(in srgb, var(--danger) 12%, var(--surface));border-color:var(--danger);color:var(--danger)}.ui-stepper__label[data-v-8a6485e2]{font-size:var(--font-size-sm);text-align:center;color:var(--muted);max-width:100%;line-height:var(--leading-tight)}.ui-stepper--horizontal .ui-stepper__label[data-v-8a6485e2]{white-space:nowrap;text-overflow:ellipsis;overflow:hidden}.ui-stepper--vertical .ui-stepper__label[data-v-8a6485e2]{text-align:start}.is-done .ui-stepper__label[data-v-8a6485e2],.is-active .ui-stepper__label[data-v-8a6485e2],.is-busy .ui-stepper__label[data-v-8a6485e2],.is-error .ui-stepper__label[data-v-8a6485e2]{color:var(--text)}.is-active .ui-stepper__label[data-v-8a6485e2],.is-busy .ui-stepper__label[data-v-8a6485e2]{font-weight:var(--font-weight-semibold)}}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import e from "../_virtual/_plugin-vue_export-helper.js";
|
|
2
|
+
import t from "./UiStepper.vue_vue_type_script_setup_true_lang.js";
|
|
3
|
+
import "./UiStepper.css";
|
|
4
|
+
//#region src/components/UiStepper.vue
|
|
5
|
+
var n = /*#__PURE__*/ e(t, [["__scopeId", "data-v-8a6485e2"]]);
|
|
6
|
+
//#endregion
|
|
7
|
+
export { n as default };
|
|
@@ -1,15 +1,23 @@
|
|
|
1
|
+
export type StepStatus = 'done' | 'busy' | 'error' | 'pending';
|
|
1
2
|
export interface StepperStep {
|
|
2
3
|
id: string;
|
|
3
4
|
label: string;
|
|
5
|
+
/** Explicit state, overriding the one derived from `modelValue`. */
|
|
6
|
+
status?: StepStatus;
|
|
4
7
|
}
|
|
5
8
|
type __VLS_Props = {
|
|
6
9
|
steps: StepperStep[];
|
|
7
|
-
|
|
10
|
+
/** Index of the current step in a wizard (ignored for steps that have a `status`). */
|
|
11
|
+
modelValue?: number;
|
|
12
|
+
orientation?: 'horizontal' | 'vertical';
|
|
8
13
|
};
|
|
9
14
|
declare const __VLS_export: import("vue").DefineComponent<__VLS_Props, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {
|
|
10
15
|
"update:modelValue": (index: number) => any;
|
|
11
16
|
}, string, import("vue").PublicProps, Readonly<__VLS_Props> & Readonly<{
|
|
12
17
|
"onUpdate:modelValue"?: ((index: number) => any) | undefined;
|
|
13
|
-
}>, {
|
|
18
|
+
}>, {
|
|
19
|
+
modelValue: number;
|
|
20
|
+
orientation: "horizontal" | "vertical";
|
|
21
|
+
}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
|
|
14
22
|
declare const _default: typeof __VLS_export;
|
|
15
23
|
export default _default;
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
import { Fragment as e, computed as t, createCommentVNode as n, createElementBlock as r, createElementVNode as i, createTextVNode as a, defineComponent as o, normalizeClass as s, openBlock as c, renderList as l, toDisplayString as u } from "vue";
|
|
2
|
+
//#region src/components/UiStepper.vue?vue&type=script&setup=true&lang.ts
|
|
3
|
+
var d = ["aria-current"], f = ["aria-label", "onClick"], p = {
|
|
4
|
+
key: 1,
|
|
5
|
+
class: "ui-stepper__badge",
|
|
6
|
+
"aria-hidden": "true"
|
|
7
|
+
}, m = {
|
|
8
|
+
key: 0,
|
|
9
|
+
class: "mw-spinner"
|
|
10
|
+
}, h = { class: "ui-stepper__label" }, g = {
|
|
11
|
+
key: 2,
|
|
12
|
+
class: "mw-visually-hidden"
|
|
13
|
+
}, _ = /*@__PURE__*/ o({
|
|
14
|
+
__name: "UiStepper",
|
|
15
|
+
props: {
|
|
16
|
+
steps: {},
|
|
17
|
+
modelValue: { default: 0 },
|
|
18
|
+
orientation: { default: "horizontal" }
|
|
19
|
+
},
|
|
20
|
+
emits: ["update:modelValue"],
|
|
21
|
+
setup(o, { emit: _ }) {
|
|
22
|
+
let v = o, y = _, b = t(() => v.steps.map((e, t) => e.status ?? (t < v.modelValue ? "done" : t === v.modelValue ? "active" : "upcoming"))), x = {
|
|
23
|
+
done: "done",
|
|
24
|
+
busy: "in progress",
|
|
25
|
+
error: "failed",
|
|
26
|
+
pending: "not started"
|
|
27
|
+
}, S = {
|
|
28
|
+
done: "✓",
|
|
29
|
+
error: "✗"
|
|
30
|
+
};
|
|
31
|
+
function C(e) {
|
|
32
|
+
!v.steps[e]?.status && e < v.modelValue && y("update:modelValue", e);
|
|
33
|
+
}
|
|
34
|
+
return (t, _) => (c(), r("ol", {
|
|
35
|
+
class: s(["ui-stepper", `ui-stepper--${o.orientation}`]),
|
|
36
|
+
role: "list"
|
|
37
|
+
}, [(c(!0), r(e, null, l(o.steps, (t, o) => (c(), r("li", {
|
|
38
|
+
key: t.id,
|
|
39
|
+
class: s(["ui-stepper__step", `is-${b.value[o]}`]),
|
|
40
|
+
"aria-current": b.value[o] === "active" ? "step" : void 0
|
|
41
|
+
}, [
|
|
42
|
+
!t.status && b.value[o] === "done" ? (c(), r("button", {
|
|
43
|
+
key: 0,
|
|
44
|
+
type: "button",
|
|
45
|
+
class: "ui-stepper__badge",
|
|
46
|
+
"aria-label": `Back to ${t.label}`,
|
|
47
|
+
onClick: (e) => C(o)
|
|
48
|
+
}, "✓", 8, f)) : (c(), r("span", p, [b.value[o] === "busy" ? (c(), r("span", m)) : (c(), r(e, { key: 1 }, [a(u(S[b.value[o]] ?? o + 1), 1)], 64))])),
|
|
49
|
+
i("span", h, u(t.label), 1),
|
|
50
|
+
t.status && x[b.value[o]] ? (c(), r("span", g, ", " + u(x[b.value[o]]), 1)) : n("", !0)
|
|
51
|
+
], 10, d))), 128))], 2));
|
|
52
|
+
}
|
|
53
|
+
});
|
|
54
|
+
//#endregion
|
|
55
|
+
export { _ as default };
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
@layer mw.reset;@layer mw.components{.mw-tab-panel[data-v-add194c8]:focus-visible{outline:2px solid var(--focus-ring);outline-offset:-2px}}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import e from "../_virtual/_plugin-vue_export-helper.js";
|
|
2
|
+
import t from "./UiTabPanel.vue_vue_type_script_setup_true_lang.js";
|
|
3
|
+
import "./UiTabPanel.css";
|
|
4
|
+
//#region src/components/UiTabPanel.vue
|
|
5
|
+
var n = /*#__PURE__*/ e(t, [["__scopeId", "data-v-add194c8"]]);
|
|
6
|
+
//#endregion
|
|
7
|
+
export { n as default };
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import { tabIds as e } from "../tabs.js";
|
|
2
|
+
import { computed as t, createElementBlock as n, defineComponent as r, openBlock as i, renderSlot as a } from "vue";
|
|
3
|
+
//#region src/components/UiTabPanel.vue?vue&type=script&setup=true&lang.ts
|
|
4
|
+
var o = ["id", "aria-labelledby"], s = /*@__PURE__*/ r({
|
|
5
|
+
__name: "UiTabPanel",
|
|
6
|
+
props: {
|
|
7
|
+
idPrefix: {},
|
|
8
|
+
tab: {}
|
|
9
|
+
},
|
|
10
|
+
setup(r) {
|
|
11
|
+
let s = r, c = t(() => e(s.idPrefix, s.tab));
|
|
12
|
+
return (e, t) => (i(), n("section", {
|
|
13
|
+
id: c.value.panel,
|
|
14
|
+
role: "tabpanel",
|
|
15
|
+
"aria-labelledby": c.value.tab,
|
|
16
|
+
tabindex: "0",
|
|
17
|
+
class: "mw-tab-panel"
|
|
18
|
+
}, [a(e.$slots, "default", {}, void 0, !0)], 8, o));
|
|
19
|
+
}
|
|
20
|
+
});
|
|
21
|
+
//#endregion
|
|
22
|
+
export { s as default };
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
type __VLS_Props = {
|
|
2
|
+
id: string;
|
|
3
|
+
label: string;
|
|
4
|
+
type?: 'text' | 'url' | 'number' | 'search' | 'email' | 'password';
|
|
5
|
+
/** Render a textarea of this many rows. */
|
|
6
|
+
rows?: number;
|
|
7
|
+
hint?: string;
|
|
8
|
+
error?: string | null;
|
|
9
|
+
};
|
|
10
|
+
type __VLS_ModelProps = {
|
|
11
|
+
modelValue?: string;
|
|
12
|
+
};
|
|
13
|
+
type __VLS_PublicProps = __VLS_Props & __VLS_ModelProps;
|
|
14
|
+
declare var __VLS_8: {};
|
|
15
|
+
type __VLS_Slots = {} & {
|
|
16
|
+
'label-suffix'?: (props: typeof __VLS_8) => any;
|
|
17
|
+
};
|
|
18
|
+
declare const __VLS_base: import("vue").DefineComponent<__VLS_PublicProps, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {
|
|
19
|
+
"update:modelValue": (value: string) => any;
|
|
20
|
+
}, string, import("vue").PublicProps, Readonly<__VLS_PublicProps> & Readonly<{
|
|
21
|
+
"onUpdate:modelValue"?: ((value: string) => any) | undefined;
|
|
22
|
+
}>, {
|
|
23
|
+
type: "number" | "text" | "search" | "email" | "password" | "url";
|
|
24
|
+
error: string | null;
|
|
25
|
+
hint: string;
|
|
26
|
+
rows: number;
|
|
27
|
+
}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
|
|
28
|
+
declare const __VLS_export: __VLS_WithSlots<typeof __VLS_base, __VLS_Slots>;
|
|
29
|
+
declare const _default: typeof __VLS_export;
|
|
30
|
+
export default _default;
|
|
31
|
+
type __VLS_WithSlots<T, S> = T & {
|
|
32
|
+
new (): {
|
|
33
|
+
$slots: S;
|
|
34
|
+
};
|
|
35
|
+
};
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
import e from "./UiFormField.js";
|
|
2
|
+
import t from "./UiInput.js";
|
|
3
|
+
import n from "./UiTextarea.js";
|
|
4
|
+
import { createBlock as r, createSlots as i, defineComponent as a, mergeModels as o, mergeProps as s, openBlock as c, renderSlot as l, useModel as u, withCtx as d } from "vue";
|
|
5
|
+
//#region src/components/UiTextField.vue?vue&type=script&setup=true&lang.ts
|
|
6
|
+
var f = /*@__PURE__*/ a({
|
|
7
|
+
inheritAttrs: !1,
|
|
8
|
+
__name: "UiTextField",
|
|
9
|
+
props: /*@__PURE__*/ o({
|
|
10
|
+
id: {},
|
|
11
|
+
label: {},
|
|
12
|
+
type: { default: "text" },
|
|
13
|
+
rows: { default: void 0 },
|
|
14
|
+
hint: { default: void 0 },
|
|
15
|
+
error: { default: null }
|
|
16
|
+
}, {
|
|
17
|
+
modelValue: { default: "" },
|
|
18
|
+
modelModifiers: {}
|
|
19
|
+
}),
|
|
20
|
+
emits: ["update:modelValue"],
|
|
21
|
+
setup(a) {
|
|
22
|
+
let o = u(a, "modelValue");
|
|
23
|
+
return (u, f) => (c(), r(e, {
|
|
24
|
+
id: a.id,
|
|
25
|
+
label: a.label,
|
|
26
|
+
hint: a.hint,
|
|
27
|
+
error: a.error
|
|
28
|
+
}, i({
|
|
29
|
+
default: d(({ attrs: e }) => [a.rows ? (c(), r(n, s({
|
|
30
|
+
key: 0,
|
|
31
|
+
modelValue: o.value,
|
|
32
|
+
"onUpdate:modelValue": f[0] ||= (e) => o.value = e
|
|
33
|
+
}, {
|
|
34
|
+
...e,
|
|
35
|
+
...u.$attrs
|
|
36
|
+
}, { rows: a.rows }), null, 16, ["modelValue", "rows"])) : (c(), r(t, s({
|
|
37
|
+
key: 1,
|
|
38
|
+
modelValue: o.value,
|
|
39
|
+
"onUpdate:modelValue": f[1] ||= (e) => o.value = e,
|
|
40
|
+
autocomplete: "off"
|
|
41
|
+
}, {
|
|
42
|
+
...e,
|
|
43
|
+
...u.$attrs
|
|
44
|
+
}, { type: a.type }), null, 16, ["modelValue", "type"]))]),
|
|
45
|
+
_: 2
|
|
46
|
+
}, [u.$slots["label-suffix"] ? {
|
|
47
|
+
name: "label-suffix",
|
|
48
|
+
fn: d(() => [l(u.$slots, "label-suffix")]),
|
|
49
|
+
key: "0"
|
|
50
|
+
} : void 0]), 1032, [
|
|
51
|
+
"id",
|
|
52
|
+
"label",
|
|
53
|
+
"hint",
|
|
54
|
+
"error"
|
|
55
|
+
]));
|
|
56
|
+
}
|
|
57
|
+
});
|
|
58
|
+
//#endregion
|
|
59
|
+
export { f as default };
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
@layer mw.reset;@layer mw.components{.mw-textarea[data-v-a5067b5e]{width:100%;padding:var(--space-2xs) var(--space-xs);background:var(--surface);color:var(--text);border:1px solid var(--border);border-radius:var(--radius);font:inherit;resize:vertical}.mw-textarea[data-v-a5067b5e]::placeholder{color:var(--muted)}.mw-textarea[data-v-a5067b5e]:focus-visible{outline:2px solid var(--focus-ring);outline-offset:1px}.mw-textarea[aria-invalid=true][data-v-a5067b5e]{border-color:var(--danger)}.mw-textarea[data-v-a5067b5e]:disabled{filter:grayscale(.6);cursor:not-allowed}}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import e from "../_virtual/_plugin-vue_export-helper.js";
|
|
2
|
+
import t from "./UiTextarea.vue_vue_type_script_setup_true_lang.js";
|
|
3
|
+
import "./UiTextarea.css";
|
|
4
|
+
//#region src/components/UiTextarea.vue
|
|
5
|
+
var n = /*#__PURE__*/ e(t, [["__scopeId", "data-v-a5067b5e"]]);
|
|
6
|
+
//#endregion
|
|
7
|
+
export { n as default };
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
type __VLS_ModelProps = {
|
|
2
|
+
modelValue?: string;
|
|
3
|
+
};
|
|
4
|
+
declare const __VLS_export: import("vue").DefineComponent<__VLS_ModelProps, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {
|
|
5
|
+
"update:modelValue": (value: string | undefined) => any;
|
|
6
|
+
}, string, import("vue").PublicProps, Readonly<__VLS_ModelProps> & Readonly<{
|
|
7
|
+
"onUpdate:modelValue"?: ((value: string | undefined) => any) | undefined;
|
|
8
|
+
}>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
|
|
9
|
+
declare const _default: typeof __VLS_export;
|
|
10
|
+
export default _default;
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { createElementBlock as e, defineComponent as t, openBlock as n, useModel as r, vModelText as i, withDirectives as a } from "vue";
|
|
2
|
+
//#region src/components/UiTextarea.vue?vue&type=script&setup=true&lang.ts
|
|
3
|
+
var o = /*@__PURE__*/ t({
|
|
4
|
+
__name: "UiTextarea",
|
|
5
|
+
props: {
|
|
6
|
+
modelValue: {},
|
|
7
|
+
modelModifiers: {}
|
|
8
|
+
},
|
|
9
|
+
emits: ["update:modelValue"],
|
|
10
|
+
setup(t) {
|
|
11
|
+
let o = r(t, "modelValue");
|
|
12
|
+
return (t, r) => a((n(), e("textarea", {
|
|
13
|
+
"onUpdate:modelValue": r[0] ||= (e) => o.value = e,
|
|
14
|
+
class: "mw-textarea"
|
|
15
|
+
}, null, 512)), [[i, o.value]]);
|
|
16
|
+
}
|
|
17
|
+
});
|
|
18
|
+
//#endregion
|
|
19
|
+
export { o as default };
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
@layer mw.reset;@layer mw.components{.mw-tool-intro[data-v-48ed04fc]{margin:var(--space-3xs) 0 var(--space-sm);color:var(--muted)}}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import e from "../_virtual/_plugin-vue_export-helper.js";
|
|
2
|
+
import t from "./UiToolIntro.vue_vue_type_script_setup_true_lang.js";
|
|
3
|
+
import "./UiToolIntro.css";
|
|
4
|
+
//#region src/components/UiToolIntro.vue
|
|
5
|
+
var n = /*#__PURE__*/ e(t, [["__scopeId", "data-v-48ed04fc"]]);
|
|
6
|
+
//#endregion
|
|
7
|
+
export { n as default };
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { createElementBlock as e, defineComponent as t, openBlock as n, renderSlot as r } from "vue";
|
|
2
|
+
//#region src/components/UiToolIntro.vue?vue&type=script&setup=true&lang.ts
|
|
3
|
+
var i = { class: "mw-tool-intro" }, a = /*@__PURE__*/ t({
|
|
4
|
+
__name: "UiToolIntro",
|
|
5
|
+
setup(t) {
|
|
6
|
+
return (t, a) => (n(), e("p", i, [r(t.$slots, "default", {}, void 0, !0)]));
|
|
7
|
+
}
|
|
8
|
+
});
|
|
9
|
+
//#endregion
|
|
10
|
+
export { a as default };
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
@layer mw.reset;@layer mw.components{.mw-toolbar[data-v-d09c20c7]{align-items:center;gap:var(--space-3xs);padding:var(--space-3xs) var(--space-2xs);border-bottom:1px solid var(--border);background:var(--surface);flex-shrink:0;margin:0;display:flex}}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import e from "../_virtual/_plugin-vue_export-helper.js";
|
|
2
|
+
import t from "./UiToolbar.vue_vue_type_script_setup_true_lang.js";
|
|
3
|
+
import "./UiToolbar.css";
|
|
4
|
+
//#region src/components/UiToolbar.vue
|
|
5
|
+
var n = /*#__PURE__*/ e(t, [["__scopeId", "data-v-d09c20c7"]]);
|
|
6
|
+
//#endregion
|
|
7
|
+
export { n as default };
|
|
@@ -4,12 +4,15 @@ export interface ToolbarAction {
|
|
|
4
4
|
disabled?: boolean;
|
|
5
5
|
}
|
|
6
6
|
type __VLS_Props = {
|
|
7
|
-
actions: ToolbarAction[];
|
|
7
|
+
actions: ToolbarAction[]; /** Names the toolbar for assistive technology. */
|
|
8
|
+
label?: string;
|
|
8
9
|
};
|
|
9
10
|
declare const __VLS_export: import("vue").DefineComponent<__VLS_Props, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {
|
|
10
11
|
action: (id: string) => any;
|
|
11
12
|
}, string, import("vue").PublicProps, Readonly<__VLS_Props> & Readonly<{
|
|
12
13
|
onAction?: ((id: string) => any) | undefined;
|
|
13
|
-
}>, {
|
|
14
|
+
}>, {
|
|
15
|
+
label: string;
|
|
16
|
+
}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
|
|
14
17
|
declare const _default: typeof __VLS_export;
|
|
15
18
|
export default _default;
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
import e from "./UiToolbarButton.js";
|
|
2
|
+
import { Fragment as t, createBlock as n, createElementBlock as r, createTextVNode as i, defineComponent as a, onBeforeUnmount as o, onMounted as s, onUpdated as c, openBlock as l, ref as u, renderList as d, toDisplayString as f, withCtx as p } from "vue";
|
|
3
|
+
//#region src/components/UiToolbar.vue?vue&type=script&setup=true&lang.ts
|
|
4
|
+
var m = ["aria-label"], h = /*@__PURE__*/ a({
|
|
5
|
+
__name: "UiToolbar",
|
|
6
|
+
props: {
|
|
7
|
+
actions: {},
|
|
8
|
+
label: { default: "Actions" }
|
|
9
|
+
},
|
|
10
|
+
emits: ["action"],
|
|
11
|
+
setup(a, { emit: h }) {
|
|
12
|
+
let g = h, _ = u(null), v = () => Array.from(_.value?.querySelectorAll("button:not(:disabled)") ?? []);
|
|
13
|
+
function y(e) {
|
|
14
|
+
let t = v(), n = t.indexOf(document.activeElement);
|
|
15
|
+
if (n < 0) return;
|
|
16
|
+
let r = t.length - 1, i = e.key === "ArrowRight" ? n === r ? 0 : n + 1 : e.key === "ArrowLeft" ? n === 0 ? r : n - 1 : e.key === "Home" ? 0 : e.key === "End" ? r : -1;
|
|
17
|
+
i < 0 || (e.preventDefault(), t.forEach((e, t) => e.tabIndex = t === i ? 0 : -1), t[i]?.focus());
|
|
18
|
+
}
|
|
19
|
+
function b() {
|
|
20
|
+
let e = v(), t = e.find((e) => e.tabIndex === 0) ?? e[0];
|
|
21
|
+
e.forEach((e) => e.tabIndex = e === t ? 0 : -1);
|
|
22
|
+
}
|
|
23
|
+
s(() => {
|
|
24
|
+
b(), _.value?.addEventListener("keydown", y), _.value?.addEventListener("focusin", x);
|
|
25
|
+
}), o(() => {
|
|
26
|
+
_.value?.removeEventListener("keydown", y), _.value?.removeEventListener("focusin", x);
|
|
27
|
+
}), c(b);
|
|
28
|
+
function x(e) {
|
|
29
|
+
let t = v(), n = e.target;
|
|
30
|
+
t.includes(n) && t.forEach((e) => e.tabIndex = e === n ? 0 : -1);
|
|
31
|
+
}
|
|
32
|
+
return (o, s) => (l(), r("div", {
|
|
33
|
+
ref_key: "bar",
|
|
34
|
+
ref: _,
|
|
35
|
+
class: "mw-toolbar",
|
|
36
|
+
role: "toolbar",
|
|
37
|
+
"aria-label": a.label
|
|
38
|
+
}, [(l(!0), r(t, null, d(a.actions, (t) => (l(), n(e, {
|
|
39
|
+
key: t.id,
|
|
40
|
+
disabled: t.disabled,
|
|
41
|
+
onClick: (e) => g("action", t.id)
|
|
42
|
+
}, {
|
|
43
|
+
default: p(() => [i(f(t.label), 1)]),
|
|
44
|
+
_: 2
|
|
45
|
+
}, 1032, ["disabled", "onClick"]))), 128))], 8, m));
|
|
46
|
+
}
|
|
47
|
+
});
|
|
48
|
+
//#endregion
|
|
49
|
+
export { h as default };
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
@layer mw.reset;@layer mw.components{.mw-toolbar-btn[data-v-c46bd947]{align-items:center;gap:var(--space-3xs);padding:var(--space-3xs) var(--space-2xs);min-height:var(--space-md);font-size:var(--font-size-sm);background:var(--lift);border:1px solid var(--border);border-radius:var(--radius-xs);color:var(--text);cursor:pointer;white-space:nowrap;transition:background var(--duration-fast), border-color var(--duration-fast);display:inline-flex}.mw-toolbar-btn[data-v-c46bd947]:hover:not(:disabled){background:var(--surface);border-color:var(--accent)}.mw-toolbar-btn[data-v-c46bd947]:disabled{filter:grayscale(.6);cursor:not-allowed}.mw-toolbar-btn[data-v-c46bd947]:focus-visible{outline:2px solid var(--focus-ring);outline-offset:1px}}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import e from "../_virtual/_plugin-vue_export-helper.js";
|
|
2
|
+
import t from "./UiToolbarButton.vue_vue_type_script_setup_true_lang.js";
|
|
3
|
+
import "./UiToolbarButton.css";
|
|
4
|
+
//#region src/components/UiToolbarButton.vue
|
|
5
|
+
var n = /*#__PURE__*/ e(t, [["__scopeId", "data-v-c46bd947"]]);
|
|
6
|
+
//#endregion
|
|
7
|
+
export { n as default };
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { createElementBlock as e, defineComponent as t, openBlock as n, renderSlot as r } from "vue";
|
|
2
|
+
//#region src/components/UiToolbarButton.vue?vue&type=script&setup=true&lang.ts
|
|
3
|
+
var i = {
|
|
4
|
+
type: "button",
|
|
5
|
+
class: "mw-toolbar-btn"
|
|
6
|
+
}, a = /*@__PURE__*/ t({
|
|
7
|
+
__name: "UiToolbarButton",
|
|
8
|
+
setup(t) {
|
|
9
|
+
return (t, a) => (n(), e("button", i, [r(t.$slots, "default", {}, void 0, !0)]));
|
|
10
|
+
}
|
|
11
|
+
});
|
|
12
|
+
//#endregion
|
|
13
|
+
export { a as default };
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import { effectScope as e, ref as t, watch as n } from "vue";
|
|
2
|
+
//#region src/composables/useColorMode.ts
|
|
3
|
+
var r = "mw-color-mode", i = t("system"), a = !1;
|
|
4
|
+
function o() {
|
|
5
|
+
return typeof window < "u" && typeof window.matchMedia == "function" && window.matchMedia("(prefers-color-scheme: dark)").matches;
|
|
6
|
+
}
|
|
7
|
+
function s(e) {
|
|
8
|
+
return e === "dark" || e === "system" && o();
|
|
9
|
+
}
|
|
10
|
+
function c(e) {
|
|
11
|
+
typeof document < "u" && document.documentElement.setAttribute("data-theme", s(e) ? "dark" : "light");
|
|
12
|
+
}
|
|
13
|
+
function l(t = "system") {
|
|
14
|
+
if (!a) {
|
|
15
|
+
a = !0;
|
|
16
|
+
let o = null;
|
|
17
|
+
try {
|
|
18
|
+
let e = typeof localStorage < "u" ? localStorage.getItem(r) : null;
|
|
19
|
+
(e === "light" || e === "dark" || e === "system") && (o = e);
|
|
20
|
+
} catch {}
|
|
21
|
+
i.value = o ?? t, c(i.value), typeof window < "u" && typeof window.matchMedia == "function" && window.matchMedia("(prefers-color-scheme: dark)").addEventListener("change", () => {
|
|
22
|
+
i.value === "system" && c("system");
|
|
23
|
+
}), e(!0).run(() => {
|
|
24
|
+
n(i, (e) => {
|
|
25
|
+
c(e);
|
|
26
|
+
try {
|
|
27
|
+
typeof localStorage < "u" && localStorage.setItem(r, e);
|
|
28
|
+
} catch {}
|
|
29
|
+
});
|
|
30
|
+
});
|
|
31
|
+
}
|
|
32
|
+
function o(e) {
|
|
33
|
+
i.value = e;
|
|
34
|
+
}
|
|
35
|
+
function l() {
|
|
36
|
+
o(i.value === "light" ? "dark" : i.value === "dark" ? "system" : "light");
|
|
37
|
+
}
|
|
38
|
+
return {
|
|
39
|
+
mode: i,
|
|
40
|
+
set: o,
|
|
41
|
+
cycle: l,
|
|
42
|
+
isDark: () => s(i.value)
|
|
43
|
+
};
|
|
44
|
+
}
|
|
45
|
+
//#endregion
|
|
46
|
+
export { l as useColorMode };
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import { type Ref } from 'vue';
|
|
2
|
+
/**
|
|
3
|
+
* The current time in milliseconds, refreshed every `intervalMs` (default 1 s) while the calling scope is alive. A relative-time label
|
|
4
|
+
* ("Refreshed 12s ago") reads it so it ticks on its own; the timer stops with the component.
|
|
5
|
+
*/
|
|
6
|
+
export declare function useNow(intervalMs?: number): Ref<number>;
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { getCurrentScope as e, onScopeDispose as t, ref as n } from "vue";
|
|
2
|
+
//#region src/composables/useNow.ts
|
|
3
|
+
function r(r = 1e3) {
|
|
4
|
+
let i = n(Date.now());
|
|
5
|
+
if (typeof window > "u") return i;
|
|
6
|
+
let a = setInterval(() => {
|
|
7
|
+
i.value = Date.now();
|
|
8
|
+
}, r);
|
|
9
|
+
return e() && t(() => clearInterval(a)), i;
|
|
10
|
+
}
|
|
11
|
+
//#endregion
|
|
12
|
+
export { r as useNow };
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import { type Ref } from 'vue';
|
|
2
|
+
/** A page of a keyset-paginated list: the items and an opaque cursor for the next page (absent or null on the last). */
|
|
3
|
+
export interface PageOf<T> {
|
|
4
|
+
items: T[];
|
|
5
|
+
next_cursor?: string | null;
|
|
6
|
+
}
|
|
7
|
+
export interface Pager<T> {
|
|
8
|
+
items: Ref<T[]>;
|
|
9
|
+
loading: Ref<boolean>;
|
|
10
|
+
error: Ref<string | null>;
|
|
11
|
+
/** Zero-based index of the page being shown. */
|
|
12
|
+
index: Ref<number>;
|
|
13
|
+
hasNext: Ref<boolean>;
|
|
14
|
+
/** Start again from the first page (after a filter changes). */
|
|
15
|
+
reset: () => Promise<void>;
|
|
16
|
+
/** Fetch the current page again. */
|
|
17
|
+
reload: () => Promise<void>;
|
|
18
|
+
next: () => Promise<void>;
|
|
19
|
+
prev: () => Promise<void>;
|
|
20
|
+
}
|
|
21
|
+
/**
|
|
22
|
+
* Keyset pagination for a list API that returns a page and an opaque cursor for the next one. It keeps the cursors already seen so
|
|
23
|
+
* Previous works, and drops answers that arrive out of order. Pair it with `UiPager`.
|
|
24
|
+
*
|
|
25
|
+
* @param load fetches the page at a cursor (`null` for the first page).
|
|
26
|
+
* @param describeError turns a failure into the sentence shown to people (default: the error's message).
|
|
27
|
+
*/
|
|
28
|
+
export declare function usePager<T>(load: (cursor: string | null) => Promise<PageOf<T>>, describeError?: (e: unknown) => string): Pager<T>;
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import { ref as e } from "vue";
|
|
2
|
+
import { errorMessage as t } from "@meddleware/web-utils";
|
|
3
|
+
//#region src/composables/usePager.ts
|
|
4
|
+
function n(n, r = t) {
|
|
5
|
+
let i = e([]), a = e(!1), o = e(null), s = e(0), c = e(!1), l = [null], u = 0;
|
|
6
|
+
async function d(e) {
|
|
7
|
+
let t = ++u;
|
|
8
|
+
a.value = !0;
|
|
9
|
+
try {
|
|
10
|
+
let r = await n(l[e] ?? null);
|
|
11
|
+
if (t !== u) return;
|
|
12
|
+
i.value = r.items;
|
|
13
|
+
let a = r.next_cursor ?? null;
|
|
14
|
+
c.value = a !== null, a && (l[e + 1] = a), s.value = e, o.value = null;
|
|
15
|
+
} catch (e) {
|
|
16
|
+
t === u && (o.value = r(e));
|
|
17
|
+
} finally {
|
|
18
|
+
t === u && (a.value = !1);
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
return {
|
|
22
|
+
items: i,
|
|
23
|
+
loading: a,
|
|
24
|
+
error: o,
|
|
25
|
+
index: s,
|
|
26
|
+
hasNext: c,
|
|
27
|
+
reset() {
|
|
28
|
+
return l = [null], d(0);
|
|
29
|
+
},
|
|
30
|
+
reload: () => d(s.value),
|
|
31
|
+
next: () => c.value ? d(s.value + 1) : Promise.resolve(),
|
|
32
|
+
prev: () => s.value > 0 ? d(s.value - 1) : Promise.resolve()
|
|
33
|
+
};
|
|
34
|
+
}
|
|
35
|
+
//#endregion
|
|
36
|
+
export { n as usePager };
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
//#region src/composables/useSeason.ts
|
|
2
|
+
function e() {
|
|
3
|
+
if (typeof document > "u") return;
|
|
4
|
+
let e = (/* @__PURE__ */ new Date()).getMonth(), t = e >= 2 && e <= 4 ? "spring" : e >= 5 && e <= 7 ? "summer" : e >= 8 && e <= 10 ? "autumn" : "winter";
|
|
5
|
+
document.documentElement.dataset.season = t;
|
|
6
|
+
}
|
|
7
|
+
//#endregion
|
|
8
|
+
export { e as useSeason };
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import { type Ref } from 'vue';
|
|
2
|
+
import { type StatusSnapshot } from '@meddleware/web-utils';
|
|
3
|
+
/** The shortest poll interval honoured, so a tiny `intervalMs` cannot hammer the status endpoint. */
|
|
4
|
+
export declare const MIN_STATUS_POLL_MS = 15000;
|
|
5
|
+
export interface UseStatusSnapshotOptions {
|
|
6
|
+
/** URL of the `GET /api/status` endpoint. */
|
|
7
|
+
url: string;
|
|
8
|
+
/** Poll interval in milliseconds (default 60 000; values below 15 000 are raised to it). */
|
|
9
|
+
intervalMs?: number;
|
|
10
|
+
/** Time allowed for one request, headers and body (default 10 000). */
|
|
11
|
+
timeoutMs?: number;
|
|
12
|
+
}
|
|
13
|
+
export interface StatusSnapshotState {
|
|
14
|
+
/** The latest valid snapshot, kept across a failed poll (null until the first success). */
|
|
15
|
+
snapshot: Ref<StatusSnapshot | null>;
|
|
16
|
+
/** The last poll's failure, or null when it succeeded. */
|
|
17
|
+
error: Ref<string | null>;
|
|
18
|
+
/** True until the first answer (or failure) arrives. */
|
|
19
|
+
loading: Ref<boolean>;
|
|
20
|
+
/** Poll now. */
|
|
21
|
+
refresh: () => Promise<void>;
|
|
22
|
+
}
|
|
23
|
+
/**
|
|
24
|
+
* Poll the platform status endpoint: once on mount, then every `intervalMs` while the tab is visible (a hidden tab catches up when it
|
|
25
|
+
* becomes visible again). Renders exactly what the API returns: a response that is not a valid snapshot is an error, never "healthy".
|
|
26
|
+
* An older, slower poll never overwrites a newer one. Must be called from a component's `setup`.
|
|
27
|
+
*/
|
|
28
|
+
export declare function useStatusSnapshot(options: UseStatusSnapshotOptions): StatusSnapshotState;
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import { onMounted as e, onScopeDispose as t, ref as n } from "vue";
|
|
2
|
+
import { createGeneration as r, errorMessage as i, fetchJson as a, parseSnapshot as o } from "@meddleware/web-utils";
|
|
3
|
+
//#region src/composables/useStatusSnapshot.ts
|
|
4
|
+
var s = 15e3;
|
|
5
|
+
function c(c) {
|
|
6
|
+
let l = n(null), u = n(null), d = n(!0), f = r();
|
|
7
|
+
async function p() {
|
|
8
|
+
let e = f.begin();
|
|
9
|
+
try {
|
|
10
|
+
let t = o(await a(c.url, { timeoutMs: c.timeoutMs ?? 1e4 }));
|
|
11
|
+
if (!t) throw Error("unexpected response shape");
|
|
12
|
+
if (!e()) return;
|
|
13
|
+
l.value = t, u.value = null;
|
|
14
|
+
} catch (t) {
|
|
15
|
+
if (!e()) return;
|
|
16
|
+
u.value = i(t);
|
|
17
|
+
} finally {
|
|
18
|
+
e() && (d.value = !1);
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
let m = () => {
|
|
22
|
+
document.hidden || p();
|
|
23
|
+
};
|
|
24
|
+
return e(() => {
|
|
25
|
+
p();
|
|
26
|
+
let e = setInterval(m, Math.max(c.intervalMs ?? 6e4, s));
|
|
27
|
+
document.addEventListener("visibilitychange", m), t(() => {
|
|
28
|
+
clearInterval(e), document.removeEventListener("visibilitychange", m);
|
|
29
|
+
});
|
|
30
|
+
}), {
|
|
31
|
+
snapshot: l,
|
|
32
|
+
error: u,
|
|
33
|
+
loading: d,
|
|
34
|
+
refresh: p
|
|
35
|
+
};
|
|
36
|
+
}
|
|
37
|
+
//#endregion
|
|
38
|
+
export { s as MIN_STATUS_POLL_MS, c as useStatusSnapshot };
|