@leavepulse/ui 0.55.0 → 0.56.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/chunks/{LpActionBar-CnfFVIwC.js → LpActionBar-C3hkVsFz.js} +1 -1
- package/dist/chunks/{LpAddressInput-iOJhmRzy.js → LpAddressInput-NUHmplCd.js} +1 -1
- package/dist/chunks/{LpAppShell-DcSXik4a.js → LpAppShell-BEGjSqFl.js} +1 -1
- package/dist/chunks/{LpButton-CKSwC6Mu.js → LpButton-BdfZFNqi.js} +31 -7
- package/dist/chunks/{LpConfirmDialog-Ca-CTlxT.js → LpConfirmDialog-CrbUZgJE.js} +1 -1
- package/dist/chunks/{LpConfirmHost-BAaSaT2b.js → LpConfirmHost-BgMIV8r9.js} +1 -1
- package/dist/chunks/{LpModalNav-aWwc_5CD.js → LpModalNav-DXBilXr0.js} +1 -1
- package/dist/chunks/{LpNotificationBell-wZ3meeim.js → LpNotificationBell-DEL-RoHS.js} +1 -1
- package/dist/components/LpActionBar.vue.js +1 -1
- package/dist/components/LpAddressInput.vue.js +1 -1
- package/dist/components/LpAppShell.vue.js +1 -1
- package/dist/components/LpButton.vue.d.ts +10 -0
- package/dist/components/LpButton.vue.js +1 -1
- package/dist/components/LpConfirmDialog.vue.js +1 -1
- package/dist/components/LpConfirmHost.vue.js +1 -1
- package/dist/components/LpImageEditor.vue.js +1 -1
- package/dist/components/LpModalNav.vue.js +1 -1
- package/dist/components/LpNotificationBell.vue.js +1 -1
- package/dist/components/LpTable.vue.js +1 -1
- package/dist/index.js +8 -8
- package/package.json +1 -1
- package/src/components/LpButton.vue +28 -1
|
@@ -2,7 +2,7 @@ import { defineComponent, useSlots, computed, ref, watch, onBeforeUnmount, openB
|
|
|
2
2
|
import { useLabels } from "../composables/useLpConfig.js";
|
|
3
3
|
import { useBarStack } from "../components/actionBar.js";
|
|
4
4
|
import { CLOSE_ICON } from "../components/dropdown.js";
|
|
5
|
-
import { _ as _sfc_main$2 } from "./LpButton-
|
|
5
|
+
import { _ as _sfc_main$2 } from "./LpButton-BdfZFNqi.js";
|
|
6
6
|
import { _ as _sfc_main$1 } from "./LpIcon-DYtaid0K.js";
|
|
7
7
|
const _hoisted_1 = ["aria-label"];
|
|
8
8
|
const _hoisted_2 = {
|
|
@@ -3,7 +3,7 @@ import { useAsyncTask } from "../composables/useAsyncTask.js";
|
|
|
3
3
|
import { OSM_TILES, createNominatimProvider, emptyAddress, formatAddress } from "../components/address.js";
|
|
4
4
|
import { flagEmoji, loadCountries } from "../components/countries.js";
|
|
5
5
|
import { _ as _sfc_main$2 } from "./LpAutocomplete-C8IgSMsi.js";
|
|
6
|
-
import { _ as _sfc_main$3 } from "./LpButton-
|
|
6
|
+
import { _ as _sfc_main$3 } from "./LpButton-BdfZFNqi.js";
|
|
7
7
|
import { _ as _sfc_main$1 } from "./LpFormField-CtVYj6tO.js";
|
|
8
8
|
import { _ as _sfc_main$4 } from "./LpIcon-DYtaid0K.js";
|
|
9
9
|
import { _ as _sfc_main$5 } from "./LpInput-D-YGQbEv.js";
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { defineComponent, computed, ref, useId, watch, openBlock, createElementBlock, mergeProps, unref, createElementVNode, withModifiers, toDisplayString, createVNode, createSlots, withCtx, renderSlot, normalizeProps, guardReactiveProps, normalizeClass, createBlock } from "vue";
|
|
2
2
|
import { useLabels } from "../composables/useLpConfig.js";
|
|
3
|
-
import { _ as _sfc_main$2 } from "./LpButton-
|
|
3
|
+
import { _ as _sfc_main$2 } from "./LpButton-BdfZFNqi.js";
|
|
4
4
|
import { _ as _sfc_main$3 } from "./LpIcon-DYtaid0K.js";
|
|
5
5
|
import { _ as _sfc_main$5 } from "./LpScrollArea-Hz3-JWUG.js";
|
|
6
6
|
import { _ as _sfc_main$4 } from "./LpShift-DXNsauQZ.js";
|
|
@@ -1,7 +1,8 @@
|
|
|
1
|
-
import { defineComponent, computed, openBlock, createBlock, resolveDynamicComponent, mergeProps, unref, withCtx, renderSlot } from "vue";
|
|
1
|
+
import { defineComponent, computed, openBlock, createBlock, resolveDynamicComponent, mergeProps, unref, withCtx, renderSlot, createElementBlock, normalizeClass, createVNode, createCommentVNode } from "vue";
|
|
2
2
|
import { tv } from "tailwind-variants";
|
|
3
3
|
import { useLinkComponent } from "../composables/useLpConfig.js";
|
|
4
4
|
import { useMergedAttrs } from "../composables/useMergedClass.js";
|
|
5
|
+
import { _ as _sfc_main$1 } from "./LpIcon-DYtaid0K.js";
|
|
5
6
|
import { resolveLink } from "../components/link.js";
|
|
6
7
|
const __default__ = { inheritAttrs: false };
|
|
7
8
|
const _sfc_main = /* @__PURE__ */ defineComponent({
|
|
@@ -17,7 +18,8 @@ const _sfc_main = /* @__PURE__ */ defineComponent({
|
|
|
17
18
|
to: {},
|
|
18
19
|
href: {},
|
|
19
20
|
type: { default: "button" },
|
|
20
|
-
disabled: { type: Boolean }
|
|
21
|
+
disabled: { type: Boolean },
|
|
22
|
+
loading: { type: Boolean }
|
|
21
23
|
},
|
|
22
24
|
setup(__props) {
|
|
23
25
|
const button = tv({
|
|
@@ -54,7 +56,9 @@ const _sfc_main = /* @__PURE__ */ defineComponent({
|
|
|
54
56
|
// icon-only square button — equal sides, no horizontal padding
|
|
55
57
|
square: { true: "aspect-square p-0" },
|
|
56
58
|
// soft elevation glow keyed to the variant's colour
|
|
57
|
-
glow: { true: "" }
|
|
59
|
+
glow: { true: "" },
|
|
60
|
+
// busy: the label fades out in place (no width jump) and a spinner sits on top
|
|
61
|
+
loading: { true: "relative cursor-progress !text-transparent hover:!text-transparent" }
|
|
58
62
|
},
|
|
59
63
|
compoundVariants: [
|
|
60
64
|
{ square: true, size: "xs", class: "size-8" },
|
|
@@ -91,10 +95,18 @@ const _sfc_main = /* @__PURE__ */ defineComponent({
|
|
|
91
95
|
});
|
|
92
96
|
const isNativeButton = computed(() => resolved.value.is === "button");
|
|
93
97
|
function blockDisabled(event) {
|
|
94
|
-
if (!props.disabled || isNativeButton.value) return;
|
|
98
|
+
if (!props.loading && (!props.disabled || isNativeButton.value)) return;
|
|
95
99
|
event.preventDefault();
|
|
96
100
|
event.stopImmediatePropagation();
|
|
97
101
|
}
|
|
102
|
+
const SPINNER_TONE = {
|
|
103
|
+
solid: "text-ink-inverse",
|
|
104
|
+
action: "text-ink-inverse",
|
|
105
|
+
danger: "text-ink-inverse",
|
|
106
|
+
light: "text-[#0b1210]",
|
|
107
|
+
muted: "text-muted"
|
|
108
|
+
};
|
|
109
|
+
const spinnerTone = computed(() => SPINNER_TONE[props.variant ?? "solid"] ?? "text-ink");
|
|
98
110
|
const linkProps = computed(() => {
|
|
99
111
|
if (isNativeButton.value) return {};
|
|
100
112
|
if (!props.disabled) return resolved.value.props;
|
|
@@ -106,7 +118,8 @@ const _sfc_main = /* @__PURE__ */ defineComponent({
|
|
|
106
118
|
size: props.size,
|
|
107
119
|
block: props.block,
|
|
108
120
|
square: props.square,
|
|
109
|
-
glow: props.glow
|
|
121
|
+
glow: props.glow,
|
|
122
|
+
loading: props.loading
|
|
110
123
|
})
|
|
111
124
|
);
|
|
112
125
|
return (_ctx, _cache) => {
|
|
@@ -115,14 +128,25 @@ const _sfc_main = /* @__PURE__ */ defineComponent({
|
|
|
115
128
|
disabled: isNativeButton.value ? __props.disabled : void 0,
|
|
116
129
|
"aria-disabled": !isNativeButton.value && __props.disabled ? "true" : void 0,
|
|
117
130
|
tabindex: !isNativeButton.value && __props.disabled ? -1 : void 0,
|
|
131
|
+
"aria-busy": __props.loading ? "true" : void 0,
|
|
118
132
|
class: unref(classes),
|
|
119
133
|
onClickCapture: blockDisabled
|
|
120
134
|
}), {
|
|
121
135
|
default: withCtx(() => [
|
|
122
|
-
renderSlot(_ctx.$slots, "default")
|
|
136
|
+
renderSlot(_ctx.$slots, "default"),
|
|
137
|
+
__props.loading ? (openBlock(), createElementBlock("span", {
|
|
138
|
+
key: 0,
|
|
139
|
+
class: normalizeClass(["pointer-events-none absolute inset-0 flex items-center justify-center animate-[fade-in_var(--duration-fast)_var(--ease-emphasized)] motion-reduce:animate-none", spinnerTone.value]),
|
|
140
|
+
"aria-hidden": "true"
|
|
141
|
+
}, [
|
|
142
|
+
createVNode(_sfc_main$1, {
|
|
143
|
+
name: "lucide:loader-circle",
|
|
144
|
+
class: "size-[1.15em] animate-spin motion-reduce:animate-none"
|
|
145
|
+
})
|
|
146
|
+
], 2)) : createCommentVNode("", true)
|
|
123
147
|
]),
|
|
124
148
|
_: 3
|
|
125
|
-
}, 16, ["type", "disabled", "aria-disabled", "tabindex", "class"]);
|
|
149
|
+
}, 16, ["type", "disabled", "aria-disabled", "tabindex", "aria-busy", "class"]);
|
|
126
150
|
};
|
|
127
151
|
}
|
|
128
152
|
});
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { defineComponent, computed, ref, watch, openBlock, createBlock, createSlots, withCtx, renderSlot, createElementBlock, toDisplayString, createCommentVNode, createVNode, createTextVNode, unref, createElementVNode, normalizeClass, nextTick } from "vue";
|
|
2
2
|
import { useLabels } from "../composables/useLpConfig.js";
|
|
3
|
-
import { _ as _sfc_main$2 } from "./LpButton-
|
|
3
|
+
import { _ as _sfc_main$2 } from "./LpButton-BdfZFNqi.js";
|
|
4
4
|
import { _ as _sfc_main$3 } from "./LpIcon-DYtaid0K.js";
|
|
5
5
|
import { _ as _sfc_main$1 } from "./LpModal-JNa3B_Lr.js";
|
|
6
6
|
const _hoisted_1 = { class: "inline-flex items-center gap-2.5" };
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { defineComponent, computed, ref, watch, openBlock, createBlock, createCommentVNode } from "vue";
|
|
2
2
|
import { confirmQueue, settleConfirm } from "../components/confirm.js";
|
|
3
|
-
import { _ as _sfc_main$1 } from "./LpConfirmDialog-
|
|
3
|
+
import { _ as _sfc_main$1 } from "./LpConfirmDialog-CrbUZgJE.js";
|
|
4
4
|
const _sfc_main = /* @__PURE__ */ defineComponent({
|
|
5
5
|
__name: "LpConfirmHost",
|
|
6
6
|
props: {
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { defineComponent, computed, ref, openBlock, createBlock, createSlots, withCtx, renderSlot, createElementVNode, normalizeClass, createVNode, createCommentVNode, createTextVNode, toDisplayString } from "vue";
|
|
2
2
|
import { useGlass } from "../composables/useGlass.js";
|
|
3
3
|
import { useLabels } from "../composables/useLpConfig.js";
|
|
4
|
-
import { _ as _sfc_main$2 } from "./LpButton-
|
|
4
|
+
import { _ as _sfc_main$2 } from "./LpButton-BdfZFNqi.js";
|
|
5
5
|
import { _ as _sfc_main$3 } from "./LpIcon-DYtaid0K.js";
|
|
6
6
|
import { _ as _sfc_main$1 } from "./LpModal-JNa3B_Lr.js";
|
|
7
7
|
import { _ as _sfc_main$4 } from "./LpSidebar-C2oolgwy.js";
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { defineComponent, computed, useModel, getCurrentInstance, ref, onMounted, onBeforeUnmount, openBlock, createBlock, withCtx, createElementVNode, toDisplayString, createElementBlock, createCommentVNode, createVNode, Fragment, renderList, resolveDynamicComponent, normalizeClass, Transition, mergeModels } from "vue";
|
|
2
2
|
import { useLabels } from "../composables/useLpConfig.js";
|
|
3
3
|
import { _ as _sfc_main$8 } from "./LpBadge-Fe0D1bYx.js";
|
|
4
|
-
import { _ as _sfc_main$7 } from "./LpButton-
|
|
4
|
+
import { _ as _sfc_main$7 } from "./LpButton-BdfZFNqi.js";
|
|
5
5
|
import { _ as _sfc_main$5 } from "./LpContextMenu-EF_90u3g.js";
|
|
6
6
|
import { _ as _sfc_main$3 } from "./LpEmptyState-BJbZXC8D.js";
|
|
7
7
|
import { _ as _sfc_main$6 } from "./LpIcon-DYtaid0K.js";
|
|
@@ -20,6 +20,11 @@ declare const __VLS_export: __VLS_WithSlots<import("vue").DefineComponent<{
|
|
|
20
20
|
href?: string;
|
|
21
21
|
type?: "button" | "submit" | "reset";
|
|
22
22
|
disabled?: boolean;
|
|
23
|
+
/**
|
|
24
|
+
* Busy state: blocks clicks like `disabled` without dimming, fades the label out
|
|
25
|
+
* in place and shows a spinner over it, so the width never jumps. Sets `aria-busy`.
|
|
26
|
+
*/
|
|
27
|
+
loading?: boolean;
|
|
23
28
|
}, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").PublicProps, Readonly<{
|
|
24
29
|
variant?: "ghost" | "action" | "muted" | "outline" | "danger" | "solid" | "light" | "soft" | undefined;
|
|
25
30
|
size?: "md" | "sm" | "lg" | "xs" | undefined;
|
|
@@ -38,6 +43,11 @@ declare const __VLS_export: __VLS_WithSlots<import("vue").DefineComponent<{
|
|
|
38
43
|
href?: string;
|
|
39
44
|
type?: "button" | "submit" | "reset";
|
|
40
45
|
disabled?: boolean;
|
|
46
|
+
/**
|
|
47
|
+
* Busy state: blocks clicks like `disabled` without dimming, fades the label out
|
|
48
|
+
* in place and shows a spinner over it, so the width never jumps. Sets `aria-busy`.
|
|
49
|
+
*/
|
|
50
|
+
loading?: boolean;
|
|
41
51
|
}> & Readonly<{}>, {
|
|
42
52
|
type: "button" | "submit" | "reset";
|
|
43
53
|
}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>, {
|
|
@@ -4,7 +4,7 @@ import { isSideways, coverScale, cropGeometry } from "./imageCrop.js";
|
|
|
4
4
|
import { useHotkeys } from "../composables/useHotkeys.js";
|
|
5
5
|
import { useReveal } from "../composables/useReveal.js";
|
|
6
6
|
import { useZoomPan } from "../composables/useZoomPan.js";
|
|
7
|
-
import { _ as _sfc_main$1 } from "../chunks/LpButton-
|
|
7
|
+
import { _ as _sfc_main$1 } from "../chunks/LpButton-BdfZFNqi.js";
|
|
8
8
|
import "reka-ui";
|
|
9
9
|
import { _ as _sfc_main$2 } from "../chunks/LpIcon-DYtaid0K.js";
|
|
10
10
|
import { useMergedAttrs } from "../composables/useMergedClass.js";
|
|
@@ -14,7 +14,7 @@ import { usePaintSelect } from "../composables/usePaintSelect.js";
|
|
|
14
14
|
import { useRovingFocus } from "../composables/useRovingFocus.js";
|
|
15
15
|
import { useLabels } from "../composables/useLpConfig.js";
|
|
16
16
|
import { compareValues } from "./tableSort.js";
|
|
17
|
-
import { _ as _sfc_main$1 } from "../chunks/LpButton-
|
|
17
|
+
import { _ as _sfc_main$1 } from "../chunks/LpButton-BdfZFNqi.js";
|
|
18
18
|
import { toCsv, downloadFile, fileStem } from "./exportData.js";
|
|
19
19
|
import { summarizeShown, parseTableState, serializeTableState, countValues } from "./tableFilter.js";
|
|
20
20
|
import { _ as _export_sfc } from "../chunks/_plugin-vue_export-helper-1tPrXgE0.js";
|
package/dist/index.js
CHANGED
|
@@ -1,15 +1,15 @@
|
|
|
1
1
|
import { _ } from "./chunks/LayoutCanvas-BkaGXTjx.js";
|
|
2
|
-
import { _ as _2 } from "./chunks/LpAddressInput-
|
|
2
|
+
import { _ as _2 } from "./chunks/LpAddressInput-NUHmplCd.js";
|
|
3
3
|
import { _ as _3 } from "./chunks/LpMapPicker-Cc84LaM3.js";
|
|
4
4
|
import { OSM_TILES, createNominatimProvider, emptyAddress, formatAddress, project, tileUrl, unproject } from "./components/address.js";
|
|
5
|
-
import { _ as _4 } from "./chunks/LpActionBar-
|
|
5
|
+
import { _ as _4 } from "./chunks/LpActionBar-C3hkVsFz.js";
|
|
6
6
|
import { _ as _5 } from "./chunks/LpAlert-B6ilrM7T.js";
|
|
7
|
-
import { _ as _6 } from "./chunks/LpAppShell-
|
|
7
|
+
import { _ as _6 } from "./chunks/LpAppShell-BEGjSqFl.js";
|
|
8
8
|
import { _ as _7 } from "./chunks/LpAutocomplete-C8IgSMsi.js";
|
|
9
9
|
import { _ as _8 } from "./chunks/LpAvatar-LTvy0OkE.js";
|
|
10
10
|
import { _ as _9 } from "./chunks/LpBadge-Fe0D1bYx.js";
|
|
11
11
|
import { _ as _10 } from "./chunks/LpBreadcrumbs-D4TsoFju.js";
|
|
12
|
-
import { _ as _11 } from "./chunks/LpButton-
|
|
12
|
+
import { _ as _11 } from "./chunks/LpButton-BdfZFNqi.js";
|
|
13
13
|
import { _ as _12 } from "./chunks/LpCalendar-DrA2McTU.js";
|
|
14
14
|
import { _ as _13 } from "./chunks/LpCard-DbjO5yaF.js";
|
|
15
15
|
import { default as default2 } from "./components/LpChart.vue.js";
|
|
@@ -30,8 +30,8 @@ import { default as default6 } from "./components/LpPaletteStats.vue.js";
|
|
|
30
30
|
import { default as default7 } from "./components/LpPaletteSwatches.vue.js";
|
|
31
31
|
import { default as default8 } from "./components/LpKeys.vue.js";
|
|
32
32
|
import { comboKeys, comboSteps } from "./components/keys.js";
|
|
33
|
-
import { _ as _18 } from "./chunks/LpConfirmDialog-
|
|
34
|
-
import { _ as _19 } from "./chunks/LpConfirmHost-
|
|
33
|
+
import { _ as _18 } from "./chunks/LpConfirmDialog-CrbUZgJE.js";
|
|
34
|
+
import { _ as _19 } from "./chunks/LpConfirmHost-BgMIV8r9.js";
|
|
35
35
|
import { confirm, useConfirm } from "./components/confirm.js";
|
|
36
36
|
import { _ as _20 } from "./chunks/LpContextMenu-EF_90u3g.js";
|
|
37
37
|
import { _ as _21 } from "./chunks/LpDatePicker-BrdFtSTy.js";
|
|
@@ -60,8 +60,8 @@ import { _ as _37 } from "./chunks/LpLogViewer-BfgtXVKm.js";
|
|
|
60
60
|
import { countLevels, matchPositions, matchesTerm, ringWindow, stepMatch } from "./components/logSearch.js";
|
|
61
61
|
import { _ as _38 } from "./chunks/LpMediaGallery-BnlkN_1f.js";
|
|
62
62
|
import { _ as _39 } from "./chunks/LpModal-JNa3B_Lr.js";
|
|
63
|
-
import { _ as _40 } from "./chunks/LpModalNav-
|
|
64
|
-
import { _ as _41 } from "./chunks/LpNotificationBell-
|
|
63
|
+
import { _ as _40 } from "./chunks/LpModalNav-DXBilXr0.js";
|
|
64
|
+
import { _ as _41 } from "./chunks/LpNotificationBell-DEL-RoHS.js";
|
|
65
65
|
import { _ as _42 } from "./chunks/LpNumberField-B77O-z28.js";
|
|
66
66
|
import { _ as _43 } from "./chunks/LpTimeField-Cqe7fXnh.js";
|
|
67
67
|
import { _ as _44 } from "./chunks/LpNumberFlow-z4WPZcZu.js";
|
package/package.json
CHANGED
|
@@ -9,6 +9,7 @@ import { tv, type VariantProps } from "tailwind-variants"
|
|
|
9
9
|
import { computed, type Component } from "vue"
|
|
10
10
|
import { useLinkComponent } from "../composables/useLpConfig"
|
|
11
11
|
import { useMergedAttrs } from "../composables/useMergedClass"
|
|
12
|
+
import LpIcon from "./LpIcon.vue"
|
|
12
13
|
import { resolveLink, type LinkTarget } from "./link"
|
|
13
14
|
|
|
14
15
|
const button = tv({
|
|
@@ -47,6 +48,8 @@ const button = tv({
|
|
|
47
48
|
square: { true: "aspect-square p-0" },
|
|
48
49
|
// soft elevation glow keyed to the variant's colour
|
|
49
50
|
glow: { true: "" },
|
|
51
|
+
// busy: the label fades out in place (no width jump) and a spinner sits on top
|
|
52
|
+
loading: { true: "relative cursor-progress !text-transparent hover:!text-transparent" },
|
|
50
53
|
},
|
|
51
54
|
compoundVariants: [
|
|
52
55
|
{ square: true, size: "xs", class: "size-8" },
|
|
@@ -96,6 +99,11 @@ const props = withDefaults(
|
|
|
96
99
|
href?: string
|
|
97
100
|
type?: "button" | "submit" | "reset"
|
|
98
101
|
disabled?: boolean
|
|
102
|
+
/**
|
|
103
|
+
* Busy state: blocks clicks like `disabled` without dimming, fades the label out
|
|
104
|
+
* in place and shows a spinner over it, so the width never jumps. Sets `aria-busy`.
|
|
105
|
+
*/
|
|
106
|
+
loading?: boolean
|
|
99
107
|
}>(),
|
|
100
108
|
{ type: "button" },
|
|
101
109
|
)
|
|
@@ -119,11 +127,20 @@ const isNativeButton = computed(() => resolved.value.is === "button")
|
|
|
119
127
|
* own handler, which skips navigation once the event is default-prevented.
|
|
120
128
|
*/
|
|
121
129
|
function blockDisabled(event: MouseEvent) {
|
|
122
|
-
if (!props.disabled || isNativeButton.value) return
|
|
130
|
+
if (!props.loading && (!props.disabled || isNativeButton.value)) return
|
|
123
131
|
event.preventDefault()
|
|
124
132
|
event.stopImmediatePropagation()
|
|
125
133
|
}
|
|
126
134
|
|
|
135
|
+
const SPINNER_TONE: Record<string, string> = {
|
|
136
|
+
solid: "text-ink-inverse",
|
|
137
|
+
action: "text-ink-inverse",
|
|
138
|
+
danger: "text-ink-inverse",
|
|
139
|
+
light: "text-[#0b1210]",
|
|
140
|
+
muted: "text-muted",
|
|
141
|
+
}
|
|
142
|
+
const spinnerTone = computed(() => SPINNER_TONE[props.variant ?? "solid"] ?? "text-ink")
|
|
143
|
+
|
|
127
144
|
const linkProps = computed(() => {
|
|
128
145
|
if (isNativeButton.value) return {}
|
|
129
146
|
if (!props.disabled) return resolved.value.props
|
|
@@ -137,6 +154,7 @@ const { class: classes, attrs: rest } = useMergedAttrs(() =>
|
|
|
137
154
|
block: props.block,
|
|
138
155
|
square: props.square,
|
|
139
156
|
glow: props.glow,
|
|
157
|
+
loading: props.loading,
|
|
140
158
|
}),
|
|
141
159
|
)
|
|
142
160
|
</script>
|
|
@@ -149,9 +167,18 @@ const { class: classes, attrs: rest } = useMergedAttrs(() =>
|
|
|
149
167
|
:disabled="isNativeButton ? disabled : undefined"
|
|
150
168
|
:aria-disabled="!isNativeButton && disabled ? 'true' : undefined"
|
|
151
169
|
:tabindex="!isNativeButton && disabled ? -1 : undefined"
|
|
170
|
+
:aria-busy="loading ? 'true' : undefined"
|
|
152
171
|
:class="classes"
|
|
153
172
|
@click.capture="blockDisabled"
|
|
154
173
|
>
|
|
155
174
|
<slot />
|
|
175
|
+
<span
|
|
176
|
+
v-if="loading"
|
|
177
|
+
class="pointer-events-none absolute inset-0 flex items-center justify-center animate-[fade-in_var(--duration-fast)_var(--ease-emphasized)] motion-reduce:animate-none"
|
|
178
|
+
:class="spinnerTone"
|
|
179
|
+
aria-hidden="true"
|
|
180
|
+
>
|
|
181
|
+
<LpIcon name="lucide:loader-circle" class="size-[1.15em] animate-spin motion-reduce:animate-none" />
|
|
182
|
+
</span>
|
|
156
183
|
</component>
|
|
157
184
|
</template>
|