@leavepulse/ui 0.71.1 → 0.71.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/assets/{LpCommandPalette-DgPZX0us.css → LpCommandPalette-Rtbg669l.css} +19 -19
- package/dist/assets/{LpNumberFlow-rZkwQwlU.css → LpNumberFlow-Chp9pEDe.css} +8 -0
- package/dist/assets/LpTabs-DT0XPTc2.css +18 -0
- package/dist/chunks/{LpAddressInput-CD0bzrt-.js → LpAddressInput-Bu6ws3Fp.js} +1 -1
- package/dist/chunks/{LpAppShell-1RmBp6xQ.js → LpAppShell-C5YW5pI7.js} +1 -1
- package/dist/chunks/{LpCodeDisplay-BK2FHbtM.js → LpCodeDisplay-C9pIMF2R.js} +1 -1
- package/dist/chunks/{LpCommandScope-ubtWDMa0.js → LpCommandScope-BlKcgBnK.js} +1 -1
- package/dist/chunks/{LpCountdown-DTdMF8DL.js → LpCountdown-CXrEK0ev.js} +1 -1
- package/dist/chunks/{LpGauge-BdjPGnqw.js → LpGauge-DFdt33x8.js} +1 -1
- package/dist/chunks/{LpModalNav-BH4ANQGJ.js → LpModalNav-Cuna8c_3.js} +1 -1
- package/dist/chunks/{LpNumberFlow-5khYxsfX.js → LpNumberFlow-Dwb9MV1A.js} +6 -5
- package/dist/chunks/{LpPaletteTheme-CqWNRwHE.js → LpPaletteTheme-DkikZ362.js} +5 -3
- package/dist/chunks/{LpPie-DdFSTbGE.js → LpPie-C1uIUFxu.js} +1 -1
- package/dist/chunks/{LpProgress-BX33EKkN.js → LpProgress-WNaH4emv.js} +1 -1
- package/dist/chunks/{LpQuota-DqNv1yjs.js → LpQuota-Cz9PvklM.js} +1 -1
- package/dist/chunks/{LpSelect-DYX2-u5A.js → LpSelect-D3pRJfRY.js} +4 -4
- package/dist/chunks/{LpSidebar-D44peKq2.js → LpSidebar-Bk7b-K4l.js} +1 -1
- package/dist/chunks/{LpSidebarNav--VwkXO_a.js → LpSidebarNav-BR2AW3KT.js} +6 -1
- package/dist/chunks/{LpStat-DIsQfbeD.js → LpStat-Dzn6WFzi.js} +4 -4
- package/dist/chunks/{LpThemeStudio-B2nPaG-h.js → LpThemeStudio-IupHqP0x.js} +2 -2
- package/dist/chunks/{LpThemeSwitcher-C0A5sg_E.js → LpThemeSwitcher-DarPHuX8.js} +4 -3
- package/dist/chunks/{LpTopologyCanvas-B0wEvAoq.js → LpTopologyCanvas-Cq-MiJwo.js} +42 -12
- package/dist/chunks/{LpUptimeBar-DRadGq4Y.js → LpUptimeBar-BbhVTPnL.js} +1 -1
- package/dist/chunks/{palette-BiY7yQZL.js → palette-Cvxl_1tM.js} +1 -1
- package/dist/components/LpAddressInput.vue.js +1 -1
- package/dist/components/LpAppShell.vue.js +1 -1
- package/dist/components/LpChart.vue.js +22 -4
- package/dist/components/LpCodeDisplay.vue.js +1 -1
- package/dist/components/LpCommandPalette.vue.js +43 -22
- package/dist/components/LpCommandScope.vue.js +1 -1
- package/dist/components/LpCountdown.vue.js +1 -1
- package/dist/components/LpGauge.vue.js +1 -1
- package/dist/components/LpModalNav.vue.js +1 -1
- package/dist/components/LpNumberFlow.vue.js +1 -1
- package/dist/components/LpPaletteStats.vue.js +1 -1
- package/dist/components/LpPaletteTheme.vue.d.ts +2 -0
- package/dist/components/LpPaletteTheme.vue.js +1 -1
- package/dist/components/LpPie.vue.js +1 -1
- package/dist/components/LpProgress.vue.js +1 -1
- package/dist/components/LpQuota.vue.js +1 -1
- package/dist/components/LpSelect.vue.js +1 -1
- package/dist/components/LpSidebar.vue.js +1 -1
- package/dist/components/LpSidebarNav.vue.js +1 -1
- package/dist/components/LpStat.vue.js +1 -1
- package/dist/components/LpTabs.vue.d.ts +8 -0
- package/dist/components/LpTabs.vue.js +7 -5
- package/dist/components/LpThemeStudio.vue.js +1 -1
- package/dist/components/LpThemeSwitcher.vue.js +1 -1
- package/dist/components/LpTopologyCanvas.vue.d.ts +3 -1
- package/dist/components/LpTopologyCanvas.vue.js +1 -1
- package/dist/components/LpUptimeBar.vue.js +1 -1
- package/dist/components/chart.d.ts +14 -0
- package/dist/components/chart.js +13 -0
- package/dist/components/format.d.ts +10 -3
- package/dist/components/format.js +14 -2
- package/dist/composables/usePaletteCommands.js +1 -0
- package/dist/composables/useReveal.js +1 -22
- package/dist/index.d.ts +1 -1
- package/dist/index.js +21 -20
- package/dist/theme/palette.d.ts +3 -0
- package/package.json +1 -1
- package/src/components/LpChart.vue +23 -3
- package/src/components/LpCommandPalette.vue +23 -5
- package/src/components/LpNumberFlow.vue +19 -7
- package/src/components/LpPaletteTheme.vue +3 -3
- package/src/components/LpSelect.vue +5 -4
- package/src/components/LpSidebarNav.vue +8 -1
- package/src/components/LpStat.vue +5 -3
- package/src/components/LpTabs.vue +10 -2
- package/src/components/LpThemeStudio.vue +1 -1
- package/src/components/LpThemeSwitcher.vue +4 -1
- package/src/components/LpTopologyCanvas.vue +35 -4
- package/src/components/chart.ts +26 -0
- package/src/components/format.ts +31 -5
- package/src/composables/usePaletteCommands.ts +3 -0
- package/src/composables/useReveal.ts +7 -30
- package/src/index.ts +1 -1
- package/src/theme/palette.ts +4 -2
- package/dist/assets/LpTabs-CO3EcsNV.css +0 -18
package/src/components/format.ts
CHANGED
|
@@ -78,14 +78,39 @@ const COMPACT_UNITS: readonly (readonly [number, string])[] = [
|
|
|
78
78
|
[1e12, "T"],
|
|
79
79
|
]
|
|
80
80
|
|
|
81
|
+
/*
|
|
82
|
+
* The unit word and the gap before it as the locale writes them: "тыс." with a
|
|
83
|
+
* no-break space in Russian, "K" glued on in English. Taken from Intl's compact
|
|
84
|
+
* notation rather than a table, so any locale reads its own.
|
|
85
|
+
*/
|
|
86
|
+
const compactSuffixes = new Map<string, string>()
|
|
87
|
+
|
|
88
|
+
function compactSuffix(locale: string, step: number): string {
|
|
89
|
+
const key = `${locale}|${step}`
|
|
90
|
+
let found = compactSuffixes.get(key)
|
|
91
|
+
if (found === undefined) {
|
|
92
|
+
const parts = numberFormat(locale, { notation: "compact", compactDisplay: "short" }).formatToParts(COMPACT_UNITS[step][0])
|
|
93
|
+
const at = parts.findIndex((p) => p.type === "compact")
|
|
94
|
+
found = at < 0 ? COMPACT_UNITS[step][1] : (parts[at - 1]?.type === "literal" ? parts[at - 1].value : "") + parts[at].value
|
|
95
|
+
compactSuffixes.set(key, found)
|
|
96
|
+
}
|
|
97
|
+
return found
|
|
98
|
+
}
|
|
99
|
+
|
|
81
100
|
export interface CompactNumberOptions {
|
|
82
101
|
/**
|
|
83
102
|
* Writes the decimal separator the locale's way ("1,2k" in Russian). The
|
|
84
103
|
* k/M/B/T suffixes stay: Intl's own compact notation changes the shape of
|
|
85
|
-
* the figure per locale ("1,2 тыс."), which a tick label
|
|
86
|
-
*
|
|
104
|
+
* the figure per locale ("1,2 тыс."), which a tick label cannot absorb.
|
|
105
|
+
* Unset keeps a plain "." whatever the browser says.
|
|
87
106
|
*/
|
|
88
107
|
locale?: string
|
|
108
|
+
/**
|
|
109
|
+
* With a locale, write the unit as that locale does: "11,9 тыс." in Russian.
|
|
110
|
+
* For a figure read on its own (a stat tile, a counter), where "11,9k" looks
|
|
111
|
+
* foreign; not for axis ticks, where the longer word crowds the axis.
|
|
112
|
+
*/
|
|
113
|
+
words?: boolean
|
|
89
114
|
/** Places for a figure below a thousand (12.25). Default 2. */
|
|
90
115
|
plainDecimals?: number
|
|
91
116
|
/** Places once a unit is in play (1.2k). Default 1. */
|
|
@@ -98,7 +123,8 @@ export interface CompactNumberOptions {
|
|
|
98
123
|
}
|
|
99
124
|
|
|
100
125
|
/**
|
|
101
|
-
* A figure shortened with k/M/B/T: 1 200 → "1.2k", 3 400 000 → "3.4M"
|
|
126
|
+
* A figure shortened with k/M/B/T: 1 200 → "1.2k", 3 400 000 → "3.4M"; with
|
|
127
|
+
* `words` and a locale in that locale's own words, "1,2 тыс." in Russian.
|
|
102
128
|
*
|
|
103
129
|
* The unit is picked by what will PRINT, not by the raw size: 999 950 at one
|
|
104
130
|
* place rounds to "1000k", which reads as the next unit up, so it becomes
|
|
@@ -106,7 +132,7 @@ export interface CompactNumberOptions {
|
|
|
106
132
|
*/
|
|
107
133
|
export function compactNumber(value: number, options: CompactNumberOptions = {}): string {
|
|
108
134
|
if (!Number.isFinite(value)) return String(value)
|
|
109
|
-
const { locale, plainDecimals = 2, decimals = 1, fixed = false } = options
|
|
135
|
+
const { locale, plainDecimals = 2, decimals = 1, fixed = false, words = false } = options
|
|
110
136
|
const abs = Math.abs(value)
|
|
111
137
|
let i = COMPACT_UNITS.length - 1
|
|
112
138
|
while (i > 0 && abs < COMPACT_UNITS[i][0]) i--
|
|
@@ -132,7 +158,7 @@ export function compactNumber(value: number, options: CompactNumberOptions = {})
|
|
|
132
158
|
maximumFractionDigits: places,
|
|
133
159
|
useGrouping: false,
|
|
134
160
|
}).format(scaled)
|
|
135
|
-
return `${number}${COMPACT_UNITS[i][1]}`
|
|
161
|
+
return `${number}${words && locale !== undefined && i > 0 ? compactSuffix(locale, i) : COMPACT_UNITS[i][1]}`
|
|
136
162
|
}
|
|
137
163
|
|
|
138
164
|
/**
|
|
@@ -31,6 +31,9 @@ function numbered(entries: readonly PaletteRegistration[]): Command[] {
|
|
|
31
31
|
for (const entry of entries) {
|
|
32
32
|
for (const command of entry.commands()) {
|
|
33
33
|
if (!entry.automatic) {
|
|
34
|
+
// Two mounts of one component (a header switcher and its phone twin)
|
|
35
|
+
// register the same command: it is one command, listed once.
|
|
36
|
+
if (manual.has(command.id)) continue
|
|
34
37
|
manual.add(command.id)
|
|
35
38
|
out.push(command)
|
|
36
39
|
continue
|
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
import { onBeforeUnmount, ref, toValue, watch, type MaybeRefOrGetter, type Ref } from "vue"
|
|
2
2
|
import { prefersReducedMotion } from "./easing"
|
|
3
|
-
import { atScrollEnd } from "./scroll"
|
|
4
3
|
|
|
5
4
|
/*
|
|
6
5
|
* "Has this element actually been SEEN yet?"
|
|
@@ -60,7 +59,13 @@ export interface UseReveal {
|
|
|
60
59
|
}
|
|
61
60
|
|
|
62
61
|
export function useReveal(options: UseRevealOptions = {}): UseReveal {
|
|
63
|
-
|
|
62
|
+
/*
|
|
63
|
+
* No margin by default. Shrinking the viewport from below meant whatever sat
|
|
64
|
+
* in the bottom strip of the screen showed its starting state (a 0, an empty
|
|
65
|
+
* bar) while plainly on screen, which reads as "no data" rather than as an
|
|
66
|
+
* entrance yet to come; a quarter of the element in view is arrival enough.
|
|
67
|
+
*/
|
|
68
|
+
const { threshold = 0.25, rootMargin = "0px" } = options
|
|
64
69
|
|
|
65
70
|
const el = ref<Element | null>(null)
|
|
66
71
|
// SSR has no viewport to intersect with, and no animation runs there either;
|
|
@@ -68,16 +73,10 @@ export function useReveal(options: UseRevealOptions = {}): UseReveal {
|
|
|
68
73
|
const revealed = ref(typeof window === "undefined")
|
|
69
74
|
|
|
70
75
|
let observer: IntersectionObserver | null = null
|
|
71
|
-
let edge: IntersectionObserver | null = null
|
|
72
|
-
let onScroll: (() => void) | null = null
|
|
73
76
|
|
|
74
77
|
function stop() {
|
|
75
78
|
observer?.disconnect()
|
|
76
79
|
observer = null
|
|
77
|
-
edge?.disconnect()
|
|
78
|
-
edge = null
|
|
79
|
-
if (onScroll) window.removeEventListener("scroll", onScroll, true)
|
|
80
|
-
onScroll = null
|
|
81
80
|
}
|
|
82
81
|
|
|
83
82
|
function reveal() {
|
|
@@ -110,28 +109,6 @@ export function useReveal(options: UseRevealOptions = {}): UseReveal {
|
|
|
110
109
|
{ threshold, rootMargin },
|
|
111
110
|
)
|
|
112
111
|
observer.observe(node)
|
|
113
|
-
|
|
114
|
-
/*
|
|
115
|
-
* The margin shrinks the viewport from below, so the last element of a
|
|
116
|
-
* page sits in that strip for good: there is no more scroll to lift it
|
|
117
|
-
* out, and its count-up never started (a figure at the bottom of a
|
|
118
|
-
* dashboard stayed at 0). On screen with nowhere left to scroll is an
|
|
119
|
-
* arrival too.
|
|
120
|
-
*/
|
|
121
|
-
let onScreen = false
|
|
122
|
-
const check = () => {
|
|
123
|
-
if (onScreen && atScrollEnd(node)) reveal()
|
|
124
|
-
}
|
|
125
|
-
edge = new IntersectionObserver(
|
|
126
|
-
(entries) => {
|
|
127
|
-
onScreen = entries.some((entry) => entry.isIntersecting)
|
|
128
|
-
check()
|
|
129
|
-
},
|
|
130
|
-
{ threshold },
|
|
131
|
-
)
|
|
132
|
-
edge.observe(node)
|
|
133
|
-
onScroll = check
|
|
134
|
-
window.addEventListener("scroll", onScroll, { capture: true, passive: true })
|
|
135
112
|
},
|
|
136
113
|
{ immediate: true, flush: "post" },
|
|
137
114
|
)
|
package/src/index.ts
CHANGED
|
@@ -308,7 +308,7 @@ export type { RevealOrigin } from "./theme/useTheme"
|
|
|
308
308
|
export { detectBackdropFilter, GLASS_BACKDROP_ATTR, isBrokenBackdropEngine, NO_BACKDROP_ATTR, setGlassBackdrop } from "./theme/backdrop"
|
|
309
309
|
export { DEFAULT_SURFACE } from "./theme/tokens"
|
|
310
310
|
export { defineTheme, withBrand } from "./theme/define"
|
|
311
|
-
export { STUDIO_BRANDS, STUDIO_CORNERS, STUDIO_MOTION, STUDIO_SIZES, useThemeStudio } from "./theme/studio"
|
|
311
|
+
export { STUDIO_BRANDS, STUDIO_CORNERS, STUDIO_MOTION, STUDIO_SIZES, STUDIO_SYSTEM, useThemeStudio } from "./theme/studio"
|
|
312
312
|
export type { StudioState, ThemeStudio, ThemeStudioOptions } from "./theme/studio"
|
|
313
313
|
export type { ThemeOverrides } from "./theme/define"
|
|
314
314
|
export type {
|
package/src/theme/palette.ts
CHANGED
|
@@ -1,19 +1,21 @@
|
|
|
1
1
|
import { defineAsyncComponent, defineComponent, h, toValue, type MaybeRefOrGetter } from "vue"
|
|
2
2
|
import { usePaletteCommands, usePaletteScope, type PaletteScope } from "../composables/usePaletteCommands"
|
|
3
3
|
import type { PreviewableThemeStudio, ThemeStudio } from "./studio"
|
|
4
|
+
import type { ThemeStudioPart } from "../components/LpThemeStudio.vue"
|
|
4
5
|
import { useLabels } from "../composables/useLpConfig"
|
|
5
6
|
|
|
6
7
|
const Editor = defineAsyncComponent(() => import("../components/LpPaletteTheme.vue"))
|
|
7
8
|
|
|
8
9
|
/** Registers the studio itself; no second list of theme options in the app. */
|
|
9
|
-
|
|
10
|
+
/** `hide` leaves out the same studio rows the app hides in its own studio. */
|
|
11
|
+
export function usePaletteTheme(studio: MaybeRefOrGetter<ThemeStudio | undefined>, options: { id?: string; label?: string; scope?: PaletteScope; hide?: ThemeStudioPart[] } = {}) {
|
|
10
12
|
const scope = options.scope ?? usePaletteScope()
|
|
11
13
|
const text = useLabels("paletteTheme", { title: "Theme" })
|
|
12
14
|
const currentStudio = () => {
|
|
13
15
|
const current = toValue(studio)
|
|
14
16
|
return current && "preview" in current && typeof current.preview === "function" ? current as PreviewableThemeStudio : undefined
|
|
15
17
|
}
|
|
16
|
-
const preview = defineComponent({ setup: () => () => currentStudio() ? h(Editor, { studio: currentStudio()
|
|
18
|
+
const preview = defineComponent({ setup: () => () => currentStudio() ? h(Editor, { studio: currentStudio()!, hide: options.hide }) : null })
|
|
17
19
|
usePaletteCommands(() => {
|
|
18
20
|
const current = currentStudio()
|
|
19
21
|
if (!current) return []
|
|
@@ -1,18 +0,0 @@
|
|
|
1
|
-
|
|
2
|
-
.lp-tab-badge-enter-active[data-v-2c920d5a],
|
|
3
|
-
.lp-tab-badge-leave-active[data-v-2c920d5a] {
|
|
4
|
-
transition:
|
|
5
|
-
opacity var(--duration-fast) var(--ease-emphasized),
|
|
6
|
-
transform var(--duration-fast) var(--ease-emphasized);
|
|
7
|
-
}
|
|
8
|
-
.lp-tab-badge-enter-from[data-v-2c920d5a],
|
|
9
|
-
.lp-tab-badge-leave-to[data-v-2c920d5a] {
|
|
10
|
-
opacity: 0;
|
|
11
|
-
transform: scale(0.6);
|
|
12
|
-
}
|
|
13
|
-
@media (prefers-reduced-motion: reduce) {
|
|
14
|
-
.lp-tab-badge-enter-active[data-v-2c920d5a],
|
|
15
|
-
.lp-tab-badge-leave-active[data-v-2c920d5a] {
|
|
16
|
-
transition: none;
|
|
17
|
-
}
|
|
18
|
-
}
|