@leavepulse/ui 0.15.5 → 0.16.2
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/{LpConfirmDialog-C-iOXJIM.js → LpConfirmDialog-DnReh5pF.js} +1 -1
- package/dist/chunks/{LpLightbox-BYIA9qne.js → LpLightbox-CWdIsthW.js} +17 -12
- package/dist/chunks/{LpModal-DeZlvK1B.js → LpModal-CezA8eJ3.js} +9 -6
- package/dist/chunks/{LpSelect-DznhPEWX.js → LpSelect-D5mU4cZO.js} +5 -1
- package/dist/components/LpConfirmDialog.vue.js +1 -1
- package/dist/components/LpLightbox.vue.js +1 -1
- package/dist/components/LpModal.vue.js +1 -1
- package/dist/components/LpSelect.vue.js +1 -1
- package/dist/index.js +4 -4
- package/package.json +1 -1
- package/src/components/LpLightbox.vue +24 -6
- package/src/components/LpModal.vue +15 -0
- package/src/components/LpSelect.vue +0 -0
- package/src/index.ts +169 -169
- package/src/tokens/tokens.css +18 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { defineComponent, openBlock, createBlock, withCtx, renderSlot, createVNode, createTextVNode, toDisplayString } from "vue";
|
|
2
2
|
import { _ as _sfc_main$2 } from "./LpButton-5VXXCjwF.js";
|
|
3
|
-
import { _ as _sfc_main$1 } from "./LpModal-
|
|
3
|
+
import { _ as _sfc_main$1 } from "./LpModal-CezA8eJ3.js";
|
|
4
4
|
const _sfc_main = /* @__PURE__ */ defineComponent({
|
|
5
5
|
__name: "LpConfirmDialog",
|
|
6
6
|
props: {
|
|
@@ -3,7 +3,7 @@ import { DialogRoot, DialogPortal, DialogOverlay, DialogContent, DialogTitle, Di
|
|
|
3
3
|
import { useZoomPan } from "../composables/useZoomPan.js";
|
|
4
4
|
import { fileNameOf } from "../components/lightbox.js";
|
|
5
5
|
import { _ as _sfc_main$1 } from "./LpIcon-CCnX5_2j.js";
|
|
6
|
-
const _hoisted_1 = { class: "flex shrink-0 items-center gap-1 p-3 text-sm text-white/70" };
|
|
6
|
+
const _hoisted_1 = { class: "flex shrink-0 items-center gap-1 p-3 text-sm text-white/70 [--chrome-from:-8px] animate-[lightbox-chrome-in_var(--duration-medium)_var(--ease-emphasized)_60ms_both] motion-reduce:animate-none" };
|
|
7
7
|
const _hoisted_2 = {
|
|
8
8
|
key: 0,
|
|
9
9
|
class: "px-2 tabular-nums"
|
|
@@ -20,7 +20,7 @@ const _hoisted_6 = {
|
|
|
20
20
|
};
|
|
21
21
|
const _hoisted_7 = ["src", "alt"];
|
|
22
22
|
const _hoisted_8 = ["disabled"];
|
|
23
|
-
const _hoisted_9 = { class: "shrink-0 p-3 pt-2" };
|
|
23
|
+
const _hoisted_9 = { class: "shrink-0 p-3 pt-2 animate-[lightbox-chrome-in_var(--duration-medium)_var(--ease-emphasized)_60ms_both] motion-reduce:animate-none" };
|
|
24
24
|
const _hoisted_10 = {
|
|
25
25
|
key: 0,
|
|
26
26
|
class: "mb-2 text-center"
|
|
@@ -55,9 +55,9 @@ const _sfc_main = /* @__PURE__ */ defineComponent({
|
|
|
55
55
|
const props = __props;
|
|
56
56
|
const emit = __emit;
|
|
57
57
|
const zoom = useZoomPan({ max: props.maxZoom });
|
|
58
|
-
computed(() => zoom.scale.value);
|
|
59
|
-
computed(() => zoom.zoomed.value);
|
|
60
|
-
computed(() => zoom.panning.value);
|
|
58
|
+
const scale = computed(() => zoom.scale.value);
|
|
59
|
+
const isZoomed = computed(() => zoom.zoomed.value);
|
|
60
|
+
const isPanning = computed(() => zoom.panning.value);
|
|
61
61
|
const current = computed(() => Math.min(Math.max(props.index, 0), Math.max(props.items.length - 1, 0)));
|
|
62
62
|
const item = computed(() => props.items[current.value]);
|
|
63
63
|
const total = computed(() => props.items.length);
|
|
@@ -68,10 +68,12 @@ const _sfc_main = /* @__PURE__ */ defineComponent({
|
|
|
68
68
|
const viewport = ref(null);
|
|
69
69
|
const stripEl = ref(null);
|
|
70
70
|
watch(viewport, (el) => zoom.setViewport(el));
|
|
71
|
+
const direction = ref(1);
|
|
71
72
|
function go(next) {
|
|
72
73
|
if (!total.value) return;
|
|
73
74
|
const wrapped = props.loop ? (next + total.value) % total.value : Math.min(Math.max(next, 0), total.value - 1);
|
|
74
75
|
if (wrapped === current.value) return;
|
|
76
|
+
direction.value = next > current.value ? 1 : -1;
|
|
75
77
|
emit("update:index", wrapped);
|
|
76
78
|
emit("change", wrapped, props.items[wrapped]);
|
|
77
79
|
}
|
|
@@ -196,7 +198,9 @@ const _sfc_main = /* @__PURE__ */ defineComponent({
|
|
|
196
198
|
}
|
|
197
199
|
const imageStyle = computed(() => ({
|
|
198
200
|
...zoom.style.value,
|
|
199
|
-
rotate: `${rotation.value}deg
|
|
201
|
+
rotate: `${rotation.value}deg`,
|
|
202
|
+
// Consumed by the lightbox-frame-in keyframe; negative when paging backwards.
|
|
203
|
+
"--frame-from": `${direction.value * 24}px`
|
|
200
204
|
}));
|
|
201
205
|
return (_ctx, _cache) => {
|
|
202
206
|
return openBlock(), createBlock(unref(DialogRoot), {
|
|
@@ -208,7 +212,7 @@ const _sfc_main = /* @__PURE__ */ defineComponent({
|
|
|
208
212
|
default: withCtx(() => [
|
|
209
213
|
createVNode(unref(DialogOverlay), { class: "fixed inset-0 z-(--z-overlay) bg-black/85 backdrop-blur-sm data-[state=open]:animate-[fade-in_var(--duration-medium)_var(--ease-emphasized)] data-[state=closed]:animate-[fade-out_120ms_ease]" }),
|
|
210
214
|
createVNode(unref(DialogContent), {
|
|
211
|
-
class: "fixed inset-0 z-(--z-modal) flex flex-col outline-none data-[state=open]:animate-[
|
|
215
|
+
class: "fixed inset-0 z-(--z-modal) flex flex-col outline-none data-[state=open]:animate-[lightbox-in_var(--duration-medium)_var(--ease-emphasized)] data-[state=closed]:animate-[lightbox-out_140ms_cubic-bezier(0.4,0,1,1)] motion-reduce:animate-none",
|
|
212
216
|
onKeydown
|
|
213
217
|
}, {
|
|
214
218
|
default: withCtx(() => [
|
|
@@ -226,7 +230,7 @@ const _sfc_main = /* @__PURE__ */ defineComponent({
|
|
|
226
230
|
}),
|
|
227
231
|
createElementVNode("div", _hoisted_1, [
|
|
228
232
|
total.value > 1 ? (openBlock(), createElementBlock("span", _hoisted_2, toDisplayString(current.value + 1) + " / " + toDisplayString(total.value), 1)) : createCommentVNode("", true),
|
|
229
|
-
|
|
233
|
+
isZoomed.value ? (openBlock(), createElementBlock("span", _hoisted_3, toDisplayString(Math.round(scale.value * 100)) + "% ", 1)) : createCommentVNode("", true),
|
|
230
234
|
createElementVNode("div", _hoisted_4, [
|
|
231
235
|
renderSlot(_ctx.$slots, "actions", {
|
|
232
236
|
item: item.value,
|
|
@@ -306,7 +310,7 @@ const _sfc_main = /* @__PURE__ */ defineComponent({
|
|
|
306
310
|
createElementVNode("div", {
|
|
307
311
|
ref_key: "viewport",
|
|
308
312
|
ref: viewport,
|
|
309
|
-
class: normalizeClass(["relative flex min-h-0 flex-1 items-center justify-center overflow-hidden",
|
|
313
|
+
class: normalizeClass(["relative flex min-h-0 flex-1 items-center justify-center overflow-hidden", isPanning.value ? "cursor-grabbing" : isZoomed.value ? "cursor-grab" : ""]),
|
|
310
314
|
onWheel: _cache[6] || (_cache[6] = //@ts-ignore
|
|
311
315
|
(...args) => unref(zoom).onWheel && unref(zoom).onWheel(...args)),
|
|
312
316
|
onPointerdown: onPointerDown,
|
|
@@ -341,7 +345,7 @@ const _sfc_main = /* @__PURE__ */ defineComponent({
|
|
|
341
345
|
"data-lightbox-image": "",
|
|
342
346
|
src: item.value.src,
|
|
343
347
|
alt: item.value.title ?? "",
|
|
344
|
-
class: "max-h-full max-w-full select-none object-contain transition-transform duration-[var(--duration-medium)] ease-[var(--ease-emphasized)] motion-reduce:transition-none",
|
|
348
|
+
class: "max-h-full max-w-full select-none object-contain transition-transform duration-[var(--duration-medium)] ease-[var(--ease-emphasized)] animate-[lightbox-frame-in_var(--duration-medium)_var(--ease-emphasized)] motion-reduce:animate-none motion-reduce:transition-none",
|
|
345
349
|
style: normalizeStyle(imageStyle.value),
|
|
346
350
|
draggable: "false",
|
|
347
351
|
onLoad: _cache[3] || (_cache[3] = ($event) => loading.value = false),
|
|
@@ -388,7 +392,8 @@ const _sfc_main = /* @__PURE__ */ defineComponent({
|
|
|
388
392
|
key: entry.src + i,
|
|
389
393
|
"data-index": i,
|
|
390
394
|
type: "button",
|
|
391
|
-
|
|
395
|
+
style: normalizeStyle({ "--thumb-delay": `${Math.min(i * 30, 240)}ms` }),
|
|
396
|
+
class: normalizeClass(["size-14 shrink-0 overflow-hidden rounded-control outline-none ring-2 transition-[opacity,box-shadow,scale] duration-[var(--duration-fast)] hover:scale-105 focus-visible:ring-ring animate-[lightbox-chrome-in_var(--duration-medium)_var(--ease-emphasized)_both] [animation-delay:var(--thumb-delay)] motion-reduce:animate-none", i === current.value ? "opacity-100 ring-brand" : "opacity-45 ring-transparent hover:opacity-80"]),
|
|
392
397
|
"aria-label": entry.title ?? `Image ${i + 1}`,
|
|
393
398
|
onClick: ($event) => go(i)
|
|
394
399
|
}, [
|
|
@@ -398,7 +403,7 @@ const _sfc_main = /* @__PURE__ */ defineComponent({
|
|
|
398
403
|
class: "size-full object-cover",
|
|
399
404
|
draggable: "false"
|
|
400
405
|
}, null, 8, _hoisted_14)
|
|
401
|
-
],
|
|
406
|
+
], 14, _hoisted_13);
|
|
402
407
|
}), 128))
|
|
403
408
|
], 512)) : createCommentVNode("", true)
|
|
404
409
|
])
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { defineComponent, computed, useSlots, openBlock, createBlock, unref, withCtx, createVNode, createElementVNode,
|
|
1
|
+
import { defineComponent, computed, useSlots, openBlock, createBlock, unref, withCtx, createVNode, createElementVNode, mergeProps, createElementBlock, renderSlot, createTextVNode, toDisplayString, createCommentVNode, normalizeClass } from "vue";
|
|
2
2
|
import { DialogRoot, DialogPortal, DialogOverlay, DialogContent, DialogTitle, DialogDescription, DialogClose } from "reka-ui";
|
|
3
3
|
import { CLOSE_ICON } from "../components/dropdown.js";
|
|
4
4
|
import { _ as _sfc_main$1 } from "./LpIcon-CCnX5_2j.js";
|
|
@@ -26,6 +26,9 @@ const _sfc_main = /* @__PURE__ */ defineComponent({
|
|
|
26
26
|
emits: ["update:open"],
|
|
27
27
|
setup(__props) {
|
|
28
28
|
const props = __props;
|
|
29
|
+
const describedByAttrs = computed(
|
|
30
|
+
() => props.description ? {} : { "aria-describedby": void 0 }
|
|
31
|
+
);
|
|
29
32
|
const widthClass = computed(() => {
|
|
30
33
|
if (props.width) return "";
|
|
31
34
|
return {
|
|
@@ -56,10 +59,10 @@ const _sfc_main = /* @__PURE__ */ defineComponent({
|
|
|
56
59
|
default: withCtx(() => [
|
|
57
60
|
createVNode(unref(DialogOverlay), { class: "fixed inset-0 z-(--z-overlay) bg-black/50 backdrop-blur-sm data-[state=open]:animate-[fade-in_var(--duration-medium)_var(--ease-emphasized)] data-[state=closed]:animate-[fade-out_120ms_ease]" }),
|
|
58
61
|
createElementVNode("div", _hoisted_1, [
|
|
59
|
-
createVNode(unref(DialogContent), {
|
|
60
|
-
class:
|
|
61
|
-
style:
|
|
62
|
-
}, {
|
|
62
|
+
createVNode(unref(DialogContent), mergeProps({
|
|
63
|
+
class: ["pointer-events-auto flex max-h-[min(90vh,calc(100dvh-2rem))] min-h-0 flex-col rounded-card border border-line bg-surface-raised shadow-panel outline-none data-[state=open]:animate-[rise-in_var(--duration-medium)_var(--ease-emphasized)] data-[state=closed]:animate-[rise-out_120ms_cubic-bezier(0.4,0,1,1)]", widthClass.value],
|
|
64
|
+
style: __props.width ? { width: __props.width } : void 0
|
|
65
|
+
}, describedByAttrs.value), {
|
|
63
66
|
default: withCtx(() => [
|
|
64
67
|
__props.title || _ctx.$slots.title ? (openBlock(), createElementBlock("header", _hoisted_2, [
|
|
65
68
|
createElementVNode("div", _hoisted_3, [
|
|
@@ -115,7 +118,7 @@ const _sfc_main = /* @__PURE__ */ defineComponent({
|
|
|
115
118
|
])) : createCommentVNode("", true)
|
|
116
119
|
]),
|
|
117
120
|
_: 3
|
|
118
|
-
},
|
|
121
|
+
}, 16, ["class", "style"])
|
|
119
122
|
])
|
|
120
123
|
]),
|
|
121
124
|
_: 3
|
|
@@ -60,6 +60,9 @@ const _sfc_main = /* @__PURE__ */ defineComponent({
|
|
|
60
60
|
else localQuery.value = v;
|
|
61
61
|
}
|
|
62
62
|
});
|
|
63
|
+
function onOpenChange(_open) {
|
|
64
|
+
query.value = "";
|
|
65
|
+
}
|
|
63
66
|
function encode(v) {
|
|
64
67
|
return v === "" ? EMPTY_SENTINEL : v;
|
|
65
68
|
}
|
|
@@ -108,7 +111,8 @@ const _sfc_main = /* @__PURE__ */ defineComponent({
|
|
|
108
111
|
disabled: __props.disabled,
|
|
109
112
|
"ignore-filter": true,
|
|
110
113
|
class: "relative",
|
|
111
|
-
"onUpdate:modelValue": onUpdate
|
|
114
|
+
"onUpdate:modelValue": onUpdate,
|
|
115
|
+
"onUpdate:open": onOpenChange
|
|
112
116
|
}, {
|
|
113
117
|
default: withCtx(() => [
|
|
114
118
|
createVNode(unref(ComboboxAnchor), {
|
package/dist/index.js
CHANGED
|
@@ -11,7 +11,7 @@ import { _ as _10 } from "./chunks/LpCard-BmrTvWOe.js";
|
|
|
11
11
|
import { _ as _11 } from "./chunks/LpCheckbox-BO0zuuPh.js";
|
|
12
12
|
import { _ as _12 } from "./chunks/LpCodeBlock-CSiOSPs8.js";
|
|
13
13
|
import { default as default2 } from "./components/LpCommandPalette.vue.js";
|
|
14
|
-
import { _ as _13 } from "./chunks/LpConfirmDialog-
|
|
14
|
+
import { _ as _13 } from "./chunks/LpConfirmDialog-DnReh5pF.js";
|
|
15
15
|
import { _ as _14 } from "./chunks/LpContextMenu-D0mzXqA7.js";
|
|
16
16
|
import { _ as _15 } from "./chunks/LpDatePicker-dY2q4dr4.js";
|
|
17
17
|
import { _ as _16 } from "./chunks/LpDisclosure-DP6yfgfM.js";
|
|
@@ -25,11 +25,11 @@ import { _ as _22 } from "./chunks/LpFormField-Bn-ZwC6z.js";
|
|
|
25
25
|
import { _ as _23 } from "./chunks/LpIcon-CCnX5_2j.js";
|
|
26
26
|
import { _ as _24 } from "./chunks/LpInfraNode-C_PHcthC.js";
|
|
27
27
|
import { _ as _25 } from "./chunks/LpInput-BauZRyzm.js";
|
|
28
|
-
import { _ as _26 } from "./chunks/LpLightbox-
|
|
28
|
+
import { _ as _26 } from "./chunks/LpLightbox-CWdIsthW.js";
|
|
29
29
|
import { fileNameOf } from "./components/lightbox.js";
|
|
30
30
|
import { _ as _27 } from "./chunks/LpLink-DHwOEp4e.js";
|
|
31
31
|
import { _ as _28 } from "./chunks/LpLogViewer-BvzRZPjs.js";
|
|
32
|
-
import { _ as _29 } from "./chunks/LpModal-
|
|
32
|
+
import { _ as _29 } from "./chunks/LpModal-CezA8eJ3.js";
|
|
33
33
|
import { _ as _30 } from "./chunks/LpNotificationBell-BtfRoL2i.js";
|
|
34
34
|
import { _ as _31 } from "./chunks/LpNumberField-C5ar-OwE.js";
|
|
35
35
|
import { _ as _32 } from "./chunks/LpOtpInput-DqaT0Z75.js";
|
|
@@ -43,7 +43,7 @@ import { _ as _38 } from "./chunks/LpRadio-CL-pI0_O.js";
|
|
|
43
43
|
import { _ as _39 } from "./chunks/LpRadioGroup-B4yDTmi6.js";
|
|
44
44
|
import { _ as _40 } from "./chunks/LpScrollArea-De9DLpa1.js";
|
|
45
45
|
import { _ as _41 } from "./chunks/LpSegmented-BmpanyAo.js";
|
|
46
|
-
import { _ as _42 } from "./chunks/LpSelect-
|
|
46
|
+
import { _ as _42 } from "./chunks/LpSelect-D5mU4cZO.js";
|
|
47
47
|
import { _ as _43 } from "./chunks/LpServiceNode-Dc-Ut5RS.js";
|
|
48
48
|
import { _ as _44 } from "./chunks/LpSidebar-B11IDRQi.js";
|
|
49
49
|
import { _ as _45 } from "./chunks/LpSkeleton-eSFIo4kD.js";
|
package/package.json
CHANGED
|
@@ -94,12 +94,19 @@ const stripEl = ref<HTMLElement | null>(null)
|
|
|
94
94
|
|
|
95
95
|
watch(viewport, (el) => zoom.setViewport(el))
|
|
96
96
|
|
|
97
|
+
// Which way the last navigation went, so the incoming frame slides in from the
|
|
98
|
+
// side it travelled from instead of always drifting the same direction.
|
|
99
|
+
const direction = ref<1 | -1>(1)
|
|
100
|
+
|
|
97
101
|
function go(next: number) {
|
|
98
102
|
if (!total.value) return
|
|
99
103
|
const wrapped = props.loop
|
|
100
104
|
? (next + total.value) % total.value
|
|
101
105
|
: Math.min(Math.max(next, 0), total.value - 1)
|
|
102
106
|
if (wrapped === current.value) return
|
|
107
|
+
// Compare against the raw target, not the wrapped one: stepping past the last
|
|
108
|
+
// image is still "forward" even though the index jumps back to 0.
|
|
109
|
+
direction.value = next > current.value ? 1 : -1
|
|
103
110
|
emit("update:index", wrapped)
|
|
104
111
|
emit("change", wrapped, props.items[wrapped])
|
|
105
112
|
}
|
|
@@ -250,6 +257,8 @@ async function reencodeToPng(bitmap: ImageBitmap): Promise<Blob> {
|
|
|
250
257
|
const imageStyle = computed(() => ({
|
|
251
258
|
...zoom.style.value,
|
|
252
259
|
rotate: `${rotation.value}deg`,
|
|
260
|
+
// Consumed by the lightbox-frame-in keyframe; negative when paging backwards.
|
|
261
|
+
"--frame-from": `${direction.value * 24}px`,
|
|
253
262
|
}))
|
|
254
263
|
|
|
255
264
|
const BTN =
|
|
@@ -265,7 +274,7 @@ const ARROW =
|
|
|
265
274
|
class="fixed inset-0 z-(--z-overlay) bg-black/85 backdrop-blur-sm data-[state=open]:animate-[fade-in_var(--duration-medium)_var(--ease-emphasized)] data-[state=closed]:animate-[fade-out_120ms_ease]"
|
|
266
275
|
/>
|
|
267
276
|
<DialogContent
|
|
268
|
-
class="fixed inset-0 z-(--z-modal) flex flex-col outline-none data-[state=open]:animate-[
|
|
277
|
+
class="fixed inset-0 z-(--z-modal) flex flex-col outline-none data-[state=open]:animate-[lightbox-in_var(--duration-medium)_var(--ease-emphasized)] data-[state=closed]:animate-[lightbox-out_140ms_cubic-bezier(0.4,0,1,1)] motion-reduce:animate-none"
|
|
269
278
|
@keydown="onKeydown"
|
|
270
279
|
>
|
|
271
280
|
<!-- reka wants both for a labelled dialog; the caption is the title. -->
|
|
@@ -274,8 +283,11 @@ const ARROW =
|
|
|
274
283
|
{{ item?.description ?? `Image ${current + 1} of ${total}` }}
|
|
275
284
|
</DialogDescription>
|
|
276
285
|
|
|
277
|
-
<!-- Toolbar
|
|
278
|
-
|
|
286
|
+
<!-- Toolbar. Chrome drifts in from its own edge, slightly behind the
|
|
287
|
+
image, so the picture is what arrives first. -->
|
|
288
|
+
<div
|
|
289
|
+
class="flex shrink-0 items-center gap-1 p-3 text-sm text-white/70 [--chrome-from:-8px] animate-[lightbox-chrome-in_var(--duration-medium)_var(--ease-emphasized)_60ms_both] motion-reduce:animate-none"
|
|
290
|
+
>
|
|
279
291
|
<span v-if="total > 1" class="px-2 tabular-nums">{{ current + 1 }} / {{ total }}</span>
|
|
280
292
|
<span v-if="isZoomed" class="px-2 tabular-nums">
|
|
281
293
|
{{ Math.round(scale * 100) }}%
|
|
@@ -347,13 +359,16 @@ const ARROW =
|
|
|
347
359
|
<LpIcon name="lucide:image-off" :size="40" />
|
|
348
360
|
<p class="text-sm">This image couldn't be loaded.</p>
|
|
349
361
|
</div>
|
|
362
|
+
<!-- Keyed on src so paging remounts the img and replays the slide;
|
|
363
|
+
without the key Vue patches it in place and the change is a hard
|
|
364
|
+
cut with no sense of direction. -->
|
|
350
365
|
<img
|
|
351
366
|
v-else-if="item"
|
|
352
367
|
:key="item.src"
|
|
353
368
|
data-lightbox-image
|
|
354
369
|
:src="item.src"
|
|
355
370
|
:alt="item.title ?? ''"
|
|
356
|
-
class="max-h-full max-w-full select-none object-contain transition-transform duration-[var(--duration-medium)] ease-[var(--ease-emphasized)] motion-reduce:transition-none"
|
|
371
|
+
class="max-h-full max-w-full select-none object-contain transition-transform duration-[var(--duration-medium)] ease-[var(--ease-emphasized)] animate-[lightbox-frame-in_var(--duration-medium)_var(--ease-emphasized)] motion-reduce:animate-none motion-reduce:transition-none"
|
|
357
372
|
:style="imageStyle"
|
|
358
373
|
draggable="false"
|
|
359
374
|
@load="loading = false"
|
|
@@ -379,7 +394,9 @@ const ARROW =
|
|
|
379
394
|
</div>
|
|
380
395
|
|
|
381
396
|
<!-- Caption + filmstrip -->
|
|
382
|
-
<div
|
|
397
|
+
<div
|
|
398
|
+
class="shrink-0 p-3 pt-2 animate-[lightbox-chrome-in_var(--duration-medium)_var(--ease-emphasized)_60ms_both] motion-reduce:animate-none"
|
|
399
|
+
>
|
|
383
400
|
<slot name="caption" :item="item!" :index="current" :total="total">
|
|
384
401
|
<div v-if="item?.title || item?.description" class="mb-2 text-center">
|
|
385
402
|
<p v-if="item.title" class="truncate text-sm font-medium text-white">
|
|
@@ -401,7 +418,8 @@ const ARROW =
|
|
|
401
418
|
:key="entry.src + i"
|
|
402
419
|
:data-index="i"
|
|
403
420
|
type="button"
|
|
404
|
-
|
|
421
|
+
:style="{ '--thumb-delay': `${Math.min(i * 30, 240)}ms` }"
|
|
422
|
+
class="size-14 shrink-0 overflow-hidden rounded-control outline-none ring-2 transition-[opacity,box-shadow,scale] duration-[var(--duration-fast)] hover:scale-105 focus-visible:ring-ring animate-[lightbox-chrome-in_var(--duration-medium)_var(--ease-emphasized)_both] [animation-delay:var(--thumb-delay)] motion-reduce:animate-none"
|
|
405
423
|
:class="i === current ? 'opacity-100 ring-brand' : 'opacity-45 ring-transparent hover:opacity-80'"
|
|
406
424
|
:aria-label="entry.title ?? `Image ${i + 1}`"
|
|
407
425
|
@click="go(i)"
|
|
@@ -37,6 +37,13 @@ const props = withDefaults(
|
|
|
37
37
|
|
|
38
38
|
defineEmits<{ (e: "update:open", value: boolean): void }>()
|
|
39
39
|
|
|
40
|
+
// Spread rather than a plain `:aria-describedby` binding: with a description
|
|
41
|
+
// the key must be absent entirely so reka-ui's own generated id survives, and
|
|
42
|
+
// only the description-less case overrides it away.
|
|
43
|
+
const describedByAttrs = computed(() =>
|
|
44
|
+
props.description ? {} : { "aria-describedby": undefined },
|
|
45
|
+
)
|
|
46
|
+
|
|
40
47
|
const widthClass = computed(() => {
|
|
41
48
|
if (props.width) return ""
|
|
42
49
|
return {
|
|
@@ -85,10 +92,18 @@ const bodyPad = computed(() =>
|
|
|
85
92
|
box it is free to overflow, so a tall body stopped handing its
|
|
86
93
|
overflow to the scroll area below and simply ran off-screen. -->
|
|
87
94
|
<div class="fixed inset-0 z-(--z-modal) flex items-center justify-center pointer-events-none">
|
|
95
|
+
<!-- Without a description reka-ui warns on every open, and the opt-out it
|
|
96
|
+
checks for is an ABSENT `aria-describedby` — despite the message
|
|
97
|
+
naming the string "undefined" (a leftover from Radix, where
|
|
98
|
+
`aria-describedby={undefined}` is how you drop the attribute).
|
|
99
|
+
Dropping it here is what silences the warning; a caller that does
|
|
100
|
+
pass a description keeps the generated id and the link to
|
|
101
|
+
DialogDescription. -->
|
|
88
102
|
<DialogContent
|
|
89
103
|
class="pointer-events-auto flex max-h-[min(90vh,calc(100dvh-2rem))] min-h-0 flex-col rounded-card border border-line bg-surface-raised shadow-panel outline-none data-[state=open]:animate-[rise-in_var(--duration-medium)_var(--ease-emphasized)] data-[state=closed]:animate-[rise-out_120ms_cubic-bezier(0.4,0,1,1)]"
|
|
90
104
|
:class="widthClass"
|
|
91
105
|
:style="width ? { width } : undefined"
|
|
106
|
+
v-bind="describedByAttrs"
|
|
92
107
|
>
|
|
93
108
|
<header v-if="title || $slots.title" class="flex shrink-0 items-start justify-between gap-4 p-5 pb-3">
|
|
94
109
|
<div class="flex flex-col gap-1">
|
|
Binary file
|
package/src/index.ts
CHANGED
|
@@ -1,169 +1,169 @@
|
|
|
1
|
-
export { default as LayoutCanvas } from "./components/LayoutCanvas.vue"
|
|
2
|
-
export { default as LpAlert } from "./components/LpAlert.vue"
|
|
3
|
-
export { default as LpAppShell } from "./components/LpAppShell.vue"
|
|
4
|
-
export { default as LpAutocomplete } from "./components/LpAutocomplete.vue"
|
|
5
|
-
export type { AutocompleteOption } from "./components/LpAutocomplete.vue"
|
|
6
|
-
export { default as LpAvatar } from "./components/LpAvatar.vue"
|
|
7
|
-
export { default as LpBadge } from "./components/LpBadge.vue"
|
|
8
|
-
export { default as LpBreadcrumbs } from "./components/LpBreadcrumbs.vue"
|
|
9
|
-
export type { Crumb } from "./components/LpBreadcrumbs.vue"
|
|
10
|
-
export { default as LpButton } from "./components/LpButton.vue"
|
|
11
|
-
export { default as LpCalendar } from "./components/LpCalendar.vue"
|
|
12
|
-
export { default as LpCard } from "./components/LpCard.vue"
|
|
13
|
-
export { default as LpCheckbox } from "./components/LpCheckbox.vue"
|
|
14
|
-
export { default as LpCodeBlock } from "./components/LpCodeBlock.vue"
|
|
15
|
-
export type { CodeLang } from "./components/codeHighlight"
|
|
16
|
-
export { default as LpCommandPalette } from "./components/LpCommandPalette.vue"
|
|
17
|
-
export type { Command } from "./components/LpCommandPalette.vue"
|
|
18
|
-
export { default as LpConfirmDialog } from "./components/LpConfirmDialog.vue"
|
|
19
|
-
export { default as LpContextMenu } from "./components/LpContextMenu.vue"
|
|
20
|
-
export type { ContextMenuItemDef } from "./components/LpContextMenu.vue"
|
|
21
|
-
export { default as LpDatePicker } from "./components/LpDatePicker.vue"
|
|
22
|
-
export { default as LpDisclosure } from "./components/LpDisclosure.vue"
|
|
23
|
-
export { default as LpDivider } from "./components/LpDivider.vue"
|
|
24
|
-
export { default as LpDrawer } from "./components/LpDrawer.vue"
|
|
25
|
-
export { default as LpDropdownMenu } from "./components/LpDropdownMenu.vue"
|
|
26
|
-
export type { MenuItem } from "./components/LpDropdownMenu.vue"
|
|
27
|
-
export { default as LpEmptyState } from "./components/LpEmptyState.vue"
|
|
28
|
-
export { default as LpFileTree } from "./components/LpFileTree.vue"
|
|
29
|
-
export type { FileTreeSummary } from "./components/LpFileTree.vue"
|
|
30
|
-
export type { CheckState, FileNode, NodeStats } from "./components/fileTree"
|
|
31
|
-
export {
|
|
32
|
-
ancestorIds,
|
|
33
|
-
checkedCount,
|
|
34
|
-
checkStateOf,
|
|
35
|
-
computeStats,
|
|
36
|
-
fileIcon,
|
|
37
|
-
formatModified,
|
|
38
|
-
formatSize,
|
|
39
|
-
sortNodes,
|
|
40
|
-
subtreeIds,
|
|
41
|
-
subtreeSize,
|
|
42
|
-
} from "./components/fileTree"
|
|
43
|
-
export { default as LpFormField } from "./components/LpFormField.vue"
|
|
44
|
-
export { default as LpIcon } from "./components/LpIcon.vue"
|
|
45
|
-
export { default as LpInfraNode } from "./components/LpInfraNode.vue"
|
|
46
|
-
export type { InfraNodeData } from "./components/LpInfraNode.vue"
|
|
47
|
-
export { default as LpInput } from "./components/LpInput.vue"
|
|
48
|
-
export { default as LpLightbox } from "./components/LpLightbox.vue"
|
|
49
|
-
export type { LightboxItem } from "./components/lightbox"
|
|
50
|
-
export { fileNameOf } from "./components/lightbox"
|
|
51
|
-
export { default as LpLink } from "./components/LpLink.vue"
|
|
52
|
-
export { default as LpLogViewer } from "./components/LpLogViewer.vue"
|
|
53
|
-
export type { LogLevel, LogLine } from "./components/LpLogViewer.vue"
|
|
54
|
-
export { default as LpModal } from "./components/LpModal.vue"
|
|
55
|
-
export { default as LpNotificationBell } from "./components/LpNotificationBell.vue"
|
|
56
|
-
export type { NotificationItem } from "./components/LpNotificationBell.vue"
|
|
57
|
-
export { default as LpNumberField } from "./components/LpNumberField.vue"
|
|
58
|
-
export { default as LpOtpInput } from "./components/LpOtpInput.vue"
|
|
59
|
-
export { default as LpPagination } from "./components/LpPagination.vue"
|
|
60
|
-
export { default as LpPasswordInput } from "./components/LpPasswordInput.vue"
|
|
61
|
-
export { default as LpPhoneInput } from "./components/LpPhoneInput.vue"
|
|
62
|
-
export type { PhoneDetail } from "./components/LpPhoneInput.vue"
|
|
63
|
-
export { flagEmoji, loadCountries, matchCountryByValue } from "./components/countries"
|
|
64
|
-
export type { Country } from "./components/countries"
|
|
65
|
-
export { default as LpPopover } from "./components/LpPopover.vue"
|
|
66
|
-
export { default as LpProgress } from "./components/LpProgress.vue"
|
|
67
|
-
export { default as LpRadio } from "./components/LpRadio.vue"
|
|
68
|
-
export { default as LpRadioGroup } from "./components/LpRadioGroup.vue"
|
|
69
|
-
export type { RadioOption } from "./components/LpRadioGroup.vue"
|
|
70
|
-
export { default as LpScrollArea } from "./components/LpScrollArea.vue"
|
|
71
|
-
export { default as LpSegmented } from "./components/LpSegmented.vue"
|
|
72
|
-
export type { SegmentedOption } from "./components/LpSegmented.vue"
|
|
73
|
-
export { default as LpSelect } from "./components/LpSelect.vue"
|
|
74
|
-
export type { SelectOption, SelectValue } from "./components/LpSelect.vue"
|
|
75
|
-
export { default as LpServiceNode } from "./components/LpServiceNode.vue"
|
|
76
|
-
export type { ServiceNodeData } from "./components/LpServiceNode.vue"
|
|
77
|
-
export { default as LpSidebar } from "./components/LpSidebar.vue"
|
|
78
|
-
export type { SidebarItem, SidebarSection } from "./components/LpSidebar.vue"
|
|
79
|
-
export { default as LpSkeleton } from "./components/LpSkeleton.vue"
|
|
80
|
-
export { default as LpSlider } from "./components/LpSlider.vue"
|
|
81
|
-
export { default as LpStat } from "./components/LpStat.vue"
|
|
82
|
-
export { default as LpStepper } from "./components/LpStepper.vue"
|
|
83
|
-
export type { Step } from "./components/LpStepper.vue"
|
|
84
|
-
export { default as LpSwitch } from "./components/LpSwitch.vue"
|
|
85
|
-
export { default as LpTable } from "./components/LpTable.vue"
|
|
86
|
-
export type { SortState, TableColumn } from "./components/LpTable.vue"
|
|
87
|
-
export { default as LpTableOfContents } from "./components/LpTableOfContents.vue"
|
|
88
|
-
export type { TocLink } from "./components/LpTableOfContents.vue"
|
|
89
|
-
export { default as LpTabs } from "./components/LpTabs.vue"
|
|
90
|
-
export type { TabItem } from "./components/LpTabs.vue"
|
|
91
|
-
export { default as LpTextarea } from "./components/LpTextarea.vue"
|
|
92
|
-
export { default as LpThemeSwitcher } from "./components/LpThemeSwitcher.vue"
|
|
93
|
-
export { default as LpTilt } from "./components/LpTilt.vue"
|
|
94
|
-
export { default as LpToaster } from "./components/LpToaster.vue"
|
|
95
|
-
export { default as LpTooltip } from "./components/LpTooltip.vue"
|
|
96
|
-
export { default as LpTopologyCanvas } from "./components/LpTopologyCanvas.vue"
|
|
97
|
-
export type {
|
|
98
|
-
CanvasViewport,
|
|
99
|
-
EdgeCategory,
|
|
100
|
-
EdgeObserved,
|
|
101
|
-
TopologyEdge,
|
|
102
|
-
TopologyLane,
|
|
103
|
-
TopologyNode,
|
|
104
|
-
} from "./components/LpTopologyCanvas.vue"
|
|
105
|
-
export { default as LpUptimeBar } from "./components/LpUptimeBar.vue"
|
|
106
|
-
export type { UptimeSegment, UptimeStatus } from "./components/LpUptimeBar.vue"
|
|
107
|
-
|
|
108
|
-
export {
|
|
109
|
-
addLeaf,
|
|
110
|
-
addTab,
|
|
111
|
-
countBlocks,
|
|
112
|
-
countLeaves,
|
|
113
|
-
deserializeLayout,
|
|
114
|
-
makeLayout,
|
|
115
|
-
moveLeaf,
|
|
116
|
-
removeBlock,
|
|
117
|
-
removeLeaf,
|
|
118
|
-
reorderTab,
|
|
119
|
-
resizeAt,
|
|
120
|
-
setActiveTab,
|
|
121
|
-
serializeLayout,
|
|
122
|
-
} from "./layout/tree"
|
|
123
|
-
export type { Dir, LayoutNode, Leaf, Side, Split } from "./layout/tree"
|
|
124
|
-
export { blockTitle, defineBlocks } from "./layout/registry"
|
|
125
|
-
export type { BlockDef, BlockRegistry } from "./layout/registry"
|
|
126
|
-
export { useLayout } from "./layout/useLayout"
|
|
127
|
-
export type { UseLayout, UseLayoutOptions } from "./layout/useLayout"
|
|
128
|
-
|
|
129
|
-
// theme engine — themes are JSON (TokenSet), applied at runtime
|
|
130
|
-
export {
|
|
131
|
-
applyTheme,
|
|
132
|
-
applyThemeWithTransition,
|
|
133
|
-
bootstrapTheme,
|
|
134
|
-
parseTheme,
|
|
135
|
-
serializeTheme,
|
|
136
|
-
themeToCssRule,
|
|
137
|
-
themeToCssVars,
|
|
138
|
-
useTheme,
|
|
139
|
-
} from "./theme/useTheme"
|
|
140
|
-
export type { RevealOrigin } from "./theme/useTheme"
|
|
141
|
-
export { DEFAULT_SURFACE } from "./theme/tokens"
|
|
142
|
-
export { defineTheme } from "./theme/define"
|
|
143
|
-
export type { ThemeOverrides } from "./theme/define"
|
|
144
|
-
export type {
|
|
145
|
-
ColorTokens,
|
|
146
|
-
DensityTokens,
|
|
147
|
-
FontTokens,
|
|
148
|
-
ShapeTokens,
|
|
149
|
-
SurfaceTokens,
|
|
150
|
-
TokenSet,
|
|
151
|
-
} from "./theme/tokens"
|
|
152
|
-
export { amber, dark, leavepulse, light, lime, nord, presets, rose, violet } from "./theme/presets"
|
|
153
|
-
export type { PresetName } from "./theme/presets"
|
|
154
|
-
export { parseConfig, serializeConfig, UI_CONFIG_VERSION } from "./theme/config"
|
|
155
|
-
export type { UiConfig } from "./theme/config"
|
|
156
|
-
|
|
157
|
-
export { useInputFilter } from "./composables/useInputFilter"
|
|
158
|
-
export type { UseInputFilterOptions } from "./composables/useInputFilter"
|
|
159
|
-
export { useTilt } from "./composables/useTilt"
|
|
160
|
-
export type { UseTilt, UseTiltOptions } from "./composables/useTilt"
|
|
161
|
-
export { useZoomPan } from "./composables/useZoomPan"
|
|
162
|
-
export type { UseZoomPan, UseZoomPanOptions } from "./composables/useZoomPan"
|
|
163
|
-
export { useToast } from "./composables/useToast"
|
|
164
|
-
export type {
|
|
165
|
-
ToastAction,
|
|
166
|
-
ToastItem,
|
|
167
|
-
ToastOptions,
|
|
168
|
-
ToastVariant,
|
|
169
|
-
} from "./composables/useToast"
|
|
1
|
+
export { default as LayoutCanvas } from "./components/LayoutCanvas.vue"
|
|
2
|
+
export { default as LpAlert } from "./components/LpAlert.vue"
|
|
3
|
+
export { default as LpAppShell } from "./components/LpAppShell.vue"
|
|
4
|
+
export { default as LpAutocomplete } from "./components/LpAutocomplete.vue"
|
|
5
|
+
export type { AutocompleteOption } from "./components/LpAutocomplete.vue"
|
|
6
|
+
export { default as LpAvatar } from "./components/LpAvatar.vue"
|
|
7
|
+
export { default as LpBadge } from "./components/LpBadge.vue"
|
|
8
|
+
export { default as LpBreadcrumbs } from "./components/LpBreadcrumbs.vue"
|
|
9
|
+
export type { Crumb } from "./components/LpBreadcrumbs.vue"
|
|
10
|
+
export { default as LpButton } from "./components/LpButton.vue"
|
|
11
|
+
export { default as LpCalendar } from "./components/LpCalendar.vue"
|
|
12
|
+
export { default as LpCard } from "./components/LpCard.vue"
|
|
13
|
+
export { default as LpCheckbox } from "./components/LpCheckbox.vue"
|
|
14
|
+
export { default as LpCodeBlock } from "./components/LpCodeBlock.vue"
|
|
15
|
+
export type { CodeLang } from "./components/codeHighlight"
|
|
16
|
+
export { default as LpCommandPalette } from "./components/LpCommandPalette.vue"
|
|
17
|
+
export type { Command } from "./components/LpCommandPalette.vue"
|
|
18
|
+
export { default as LpConfirmDialog } from "./components/LpConfirmDialog.vue"
|
|
19
|
+
export { default as LpContextMenu } from "./components/LpContextMenu.vue"
|
|
20
|
+
export type { ContextMenuItemDef } from "./components/LpContextMenu.vue"
|
|
21
|
+
export { default as LpDatePicker } from "./components/LpDatePicker.vue"
|
|
22
|
+
export { default as LpDisclosure } from "./components/LpDisclosure.vue"
|
|
23
|
+
export { default as LpDivider } from "./components/LpDivider.vue"
|
|
24
|
+
export { default as LpDrawer } from "./components/LpDrawer.vue"
|
|
25
|
+
export { default as LpDropdownMenu } from "./components/LpDropdownMenu.vue"
|
|
26
|
+
export type { MenuItem } from "./components/LpDropdownMenu.vue"
|
|
27
|
+
export { default as LpEmptyState } from "./components/LpEmptyState.vue"
|
|
28
|
+
export { default as LpFileTree } from "./components/LpFileTree.vue"
|
|
29
|
+
export type { FileTreeSummary } from "./components/LpFileTree.vue"
|
|
30
|
+
export type { CheckState, FileNode, NodeStats } from "./components/fileTree"
|
|
31
|
+
export {
|
|
32
|
+
ancestorIds,
|
|
33
|
+
checkedCount,
|
|
34
|
+
checkStateOf,
|
|
35
|
+
computeStats,
|
|
36
|
+
fileIcon,
|
|
37
|
+
formatModified,
|
|
38
|
+
formatSize,
|
|
39
|
+
sortNodes,
|
|
40
|
+
subtreeIds,
|
|
41
|
+
subtreeSize,
|
|
42
|
+
} from "./components/fileTree"
|
|
43
|
+
export { default as LpFormField } from "./components/LpFormField.vue"
|
|
44
|
+
export { default as LpIcon } from "./components/LpIcon.vue"
|
|
45
|
+
export { default as LpInfraNode } from "./components/LpInfraNode.vue"
|
|
46
|
+
export type { InfraNodeData } from "./components/LpInfraNode.vue"
|
|
47
|
+
export { default as LpInput } from "./components/LpInput.vue"
|
|
48
|
+
export { default as LpLightbox } from "./components/LpLightbox.vue"
|
|
49
|
+
export type { LightboxItem } from "./components/lightbox"
|
|
50
|
+
export { fileNameOf } from "./components/lightbox"
|
|
51
|
+
export { default as LpLink } from "./components/LpLink.vue"
|
|
52
|
+
export { default as LpLogViewer } from "./components/LpLogViewer.vue"
|
|
53
|
+
export type { LogLevel, LogLine } from "./components/LpLogViewer.vue"
|
|
54
|
+
export { default as LpModal } from "./components/LpModal.vue"
|
|
55
|
+
export { default as LpNotificationBell } from "./components/LpNotificationBell.vue"
|
|
56
|
+
export type { NotificationItem } from "./components/LpNotificationBell.vue"
|
|
57
|
+
export { default as LpNumberField } from "./components/LpNumberField.vue"
|
|
58
|
+
export { default as LpOtpInput } from "./components/LpOtpInput.vue"
|
|
59
|
+
export { default as LpPagination } from "./components/LpPagination.vue"
|
|
60
|
+
export { default as LpPasswordInput } from "./components/LpPasswordInput.vue"
|
|
61
|
+
export { default as LpPhoneInput } from "./components/LpPhoneInput.vue"
|
|
62
|
+
export type { PhoneDetail } from "./components/LpPhoneInput.vue"
|
|
63
|
+
export { flagEmoji, loadCountries, matchCountryByValue } from "./components/countries"
|
|
64
|
+
export type { Country } from "./components/countries"
|
|
65
|
+
export { default as LpPopover } from "./components/LpPopover.vue"
|
|
66
|
+
export { default as LpProgress } from "./components/LpProgress.vue"
|
|
67
|
+
export { default as LpRadio } from "./components/LpRadio.vue"
|
|
68
|
+
export { default as LpRadioGroup } from "./components/LpRadioGroup.vue"
|
|
69
|
+
export type { RadioOption } from "./components/LpRadioGroup.vue"
|
|
70
|
+
export { default as LpScrollArea } from "./components/LpScrollArea.vue"
|
|
71
|
+
export { default as LpSegmented } from "./components/LpSegmented.vue"
|
|
72
|
+
export type { SegmentedOption } from "./components/LpSegmented.vue"
|
|
73
|
+
export { default as LpSelect } from "./components/LpSelect.vue"
|
|
74
|
+
export type { SelectOption, SelectValue } from "./components/LpSelect.vue"
|
|
75
|
+
export { default as LpServiceNode } from "./components/LpServiceNode.vue"
|
|
76
|
+
export type { ServiceNodeData } from "./components/LpServiceNode.vue"
|
|
77
|
+
export { default as LpSidebar } from "./components/LpSidebar.vue"
|
|
78
|
+
export type { SidebarItem, SidebarSection } from "./components/LpSidebar.vue"
|
|
79
|
+
export { default as LpSkeleton } from "./components/LpSkeleton.vue"
|
|
80
|
+
export { default as LpSlider } from "./components/LpSlider.vue"
|
|
81
|
+
export { default as LpStat } from "./components/LpStat.vue"
|
|
82
|
+
export { default as LpStepper } from "./components/LpStepper.vue"
|
|
83
|
+
export type { Step } from "./components/LpStepper.vue"
|
|
84
|
+
export { default as LpSwitch } from "./components/LpSwitch.vue"
|
|
85
|
+
export { default as LpTable } from "./components/LpTable.vue"
|
|
86
|
+
export type { SortState, TableColumn } from "./components/LpTable.vue"
|
|
87
|
+
export { default as LpTableOfContents } from "./components/LpTableOfContents.vue"
|
|
88
|
+
export type { TocLink } from "./components/LpTableOfContents.vue"
|
|
89
|
+
export { default as LpTabs } from "./components/LpTabs.vue"
|
|
90
|
+
export type { TabItem } from "./components/LpTabs.vue"
|
|
91
|
+
export { default as LpTextarea } from "./components/LpTextarea.vue"
|
|
92
|
+
export { default as LpThemeSwitcher } from "./components/LpThemeSwitcher.vue"
|
|
93
|
+
export { default as LpTilt } from "./components/LpTilt.vue"
|
|
94
|
+
export { default as LpToaster } from "./components/LpToaster.vue"
|
|
95
|
+
export { default as LpTooltip } from "./components/LpTooltip.vue"
|
|
96
|
+
export { default as LpTopologyCanvas } from "./components/LpTopologyCanvas.vue"
|
|
97
|
+
export type {
|
|
98
|
+
CanvasViewport,
|
|
99
|
+
EdgeCategory,
|
|
100
|
+
EdgeObserved,
|
|
101
|
+
TopologyEdge,
|
|
102
|
+
TopologyLane,
|
|
103
|
+
TopologyNode,
|
|
104
|
+
} from "./components/LpTopologyCanvas.vue"
|
|
105
|
+
export { default as LpUptimeBar } from "./components/LpUptimeBar.vue"
|
|
106
|
+
export type { UptimeSegment, UptimeStatus } from "./components/LpUptimeBar.vue"
|
|
107
|
+
|
|
108
|
+
export {
|
|
109
|
+
addLeaf,
|
|
110
|
+
addTab,
|
|
111
|
+
countBlocks,
|
|
112
|
+
countLeaves,
|
|
113
|
+
deserializeLayout,
|
|
114
|
+
makeLayout,
|
|
115
|
+
moveLeaf,
|
|
116
|
+
removeBlock,
|
|
117
|
+
removeLeaf,
|
|
118
|
+
reorderTab,
|
|
119
|
+
resizeAt,
|
|
120
|
+
setActiveTab,
|
|
121
|
+
serializeLayout,
|
|
122
|
+
} from "./layout/tree"
|
|
123
|
+
export type { Dir, LayoutNode, Leaf, Side, Split } from "./layout/tree"
|
|
124
|
+
export { blockTitle, defineBlocks } from "./layout/registry"
|
|
125
|
+
export type { BlockDef, BlockRegistry } from "./layout/registry"
|
|
126
|
+
export { useLayout } from "./layout/useLayout"
|
|
127
|
+
export type { UseLayout, UseLayoutOptions } from "./layout/useLayout"
|
|
128
|
+
|
|
129
|
+
// theme engine — themes are JSON (TokenSet), applied at runtime
|
|
130
|
+
export {
|
|
131
|
+
applyTheme,
|
|
132
|
+
applyThemeWithTransition,
|
|
133
|
+
bootstrapTheme,
|
|
134
|
+
parseTheme,
|
|
135
|
+
serializeTheme,
|
|
136
|
+
themeToCssRule,
|
|
137
|
+
themeToCssVars,
|
|
138
|
+
useTheme,
|
|
139
|
+
} from "./theme/useTheme"
|
|
140
|
+
export type { RevealOrigin } from "./theme/useTheme"
|
|
141
|
+
export { DEFAULT_SURFACE } from "./theme/tokens"
|
|
142
|
+
export { defineTheme } from "./theme/define"
|
|
143
|
+
export type { ThemeOverrides } from "./theme/define"
|
|
144
|
+
export type {
|
|
145
|
+
ColorTokens,
|
|
146
|
+
DensityTokens,
|
|
147
|
+
FontTokens,
|
|
148
|
+
ShapeTokens,
|
|
149
|
+
SurfaceTokens,
|
|
150
|
+
TokenSet,
|
|
151
|
+
} from "./theme/tokens"
|
|
152
|
+
export { amber, dark, leavepulse, light, lime, nord, presets, rose, violet } from "./theme/presets"
|
|
153
|
+
export type { PresetName } from "./theme/presets"
|
|
154
|
+
export { parseConfig, serializeConfig, UI_CONFIG_VERSION } from "./theme/config"
|
|
155
|
+
export type { UiConfig } from "./theme/config"
|
|
156
|
+
|
|
157
|
+
export { useInputFilter } from "./composables/useInputFilter"
|
|
158
|
+
export type { UseInputFilterOptions } from "./composables/useInputFilter"
|
|
159
|
+
export { useTilt } from "./composables/useTilt"
|
|
160
|
+
export type { UseTilt, UseTiltOptions } from "./composables/useTilt"
|
|
161
|
+
export { useZoomPan } from "./composables/useZoomPan"
|
|
162
|
+
export type { UseZoomPan, UseZoomPanOptions } from "./composables/useZoomPan"
|
|
163
|
+
export { useToast } from "./composables/useToast"
|
|
164
|
+
export type {
|
|
165
|
+
ToastAction,
|
|
166
|
+
ToastItem,
|
|
167
|
+
ToastOptions,
|
|
168
|
+
ToastVariant,
|
|
169
|
+
} from "./composables/useToast"
|
package/src/tokens/tokens.css
CHANGED
|
@@ -347,6 +347,24 @@
|
|
|
347
347
|
}
|
|
348
348
|
}
|
|
349
349
|
|
|
350
|
+
/*
|
|
351
|
+
* Map. Tiles arrive over the network in whatever order they finish, so each one
|
|
352
|
+
* fades in on load — popping in at full opacity makes a pan look like tearing.
|
|
353
|
+
* The pin drops onto the point instead of appearing, which reads as placement
|
|
354
|
+
* rather than a redraw.
|
|
355
|
+
*/
|
|
356
|
+
@keyframes map-tile-in {
|
|
357
|
+
from {
|
|
358
|
+
opacity: 0;
|
|
359
|
+
}
|
|
360
|
+
}
|
|
361
|
+
@keyframes map-pin-in {
|
|
362
|
+
from {
|
|
363
|
+
opacity: 0;
|
|
364
|
+
transform: translateY(-10px) scale(0.8);
|
|
365
|
+
}
|
|
366
|
+
}
|
|
367
|
+
|
|
350
368
|
/*
|
|
351
369
|
* Skin painter. A raised panel opts in with .lp-skin-panel and gets the active
|
|
352
370
|
* skin (flat → glass) purely from the surface tokens: border width, an overlay
|