@leavepulse/ui 0.43.1 → 0.43.3
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-s_kKuCRf.css → LpCommandPalette-DH7sPcKP.css} +21 -21
- package/dist/assets/{LpImageEditor-D-s8tNGO.css → LpImageEditor-Ct7Y3aNu.css} +6 -6
- package/dist/component-names.d.ts +1 -0
- package/dist/components/LayoutCanvas.vue.d.ts +28 -0
- package/dist/components/LayoutNode.vue.d.ts +40 -0
- package/dist/components/LpActionBar.vue.d.ts +84 -0
- package/dist/components/LpAddressInput.vue.d.ts +70 -0
- package/dist/components/LpAlert.vue.d.ts +44 -0
- package/dist/components/LpAppShell.vue.d.ts +123 -0
- package/dist/components/LpAutocomplete.vue.d.ts +50 -0
- package/dist/components/LpAvatar.vue.d.ts +34 -0
- package/dist/components/LpBadge.vue.d.ts +20 -0
- package/dist/components/LpBreadcrumbs.vue.d.ts +32 -0
- package/dist/components/LpButton.vue.d.ts +113 -0
- package/dist/components/LpCalendar.vue.d.ts +29 -0
- package/dist/components/LpCard.vue.d.ts +60 -0
- package/dist/components/LpChart.vue.d.ts +130 -0
- package/dist/components/LpCheckbox.vue.d.ts +32 -0
- package/dist/components/LpCodeBlock.vue.d.ts +58 -0
- package/dist/components/LpColorPicker.vue.d.ts +124 -0
- package/dist/components/LpCommandPalette.vue.d.ts +206 -0
- package/dist/components/LpCommandPalette.vue.js +2 -2
- package/dist/components/LpConfirmDialog.vue.d.ts +59 -0
- package/dist/components/LpContextMenu.vue.d.ts +44 -0
- package/dist/components/LpDatePicker.vue.d.ts +33 -0
- package/dist/components/LpDisclosure.vue.d.ts +47 -0
- package/dist/components/LpDivider.vue.d.ts +17 -0
- package/dist/components/LpDrawer.vue.d.ts +170 -0
- package/dist/components/LpDropdownMenu.vue.d.ts +23 -0
- package/dist/components/LpDropzone.vue.d.ts +90 -0
- package/dist/components/LpEmptyState.vue.d.ts +28 -0
- package/dist/components/LpFileTree.vue.d.ts +126 -0
- package/dist/components/LpFileTreeNode.vue.d.ts +62 -0
- package/dist/components/LpFormField.vue.d.ts +24 -0
- package/dist/components/LpIcon.vue.d.ts +9 -0
- package/dist/components/LpImageEditor.vue.d.ts +106 -0
- package/dist/components/LpImageEditor.vue.js +2 -2
- package/dist/components/LpInfraNode.vue.d.ts +65 -0
- package/dist/components/LpInput.vue.d.ts +80 -0
- package/dist/components/LpLaneNode.vue.d.ts +24 -0
- package/dist/components/LpLightbox.vue.d.ts +62 -0
- package/dist/components/LpLink.vue.d.ts +93 -0
- package/dist/components/LpLogViewer.vue.d.ts +153 -0
- package/dist/components/LpMapPicker.vue.d.ts +59 -0
- package/dist/components/LpMediaGallery.vue.d.ts +80 -0
- package/dist/components/LpModal.vue.d.ts +66 -0
- package/dist/components/LpModalNav.vue.d.ts +66 -0
- package/dist/components/LpNotificationBell.vue.d.ts +85 -0
- package/dist/components/LpNumberField.vue.d.ts +21 -0
- package/dist/components/LpNumberFlow.vue.d.ts +35 -0
- package/dist/components/LpOtpInput.vue.d.ts +39 -0
- package/dist/components/LpPagination.vue.d.ts +35 -0
- package/dist/components/LpPasswordInput.vue.d.ts +36 -0
- package/dist/components/LpPhoneInput.vue.d.ts +49 -0
- package/dist/components/LpPie.vue.d.ts +196 -0
- package/dist/components/LpPopover.vue.d.ts +34 -0
- package/dist/components/LpProgress.vue.d.ts +66 -0
- package/dist/components/LpRadio.vue.d.ts +18 -0
- package/dist/components/LpRadioGroup.vue.d.ts +26 -0
- package/dist/components/LpRollingText.vue.d.ts +33 -0
- package/dist/components/LpScrollArea.vue.d.ts +28 -0
- package/dist/components/LpSection.vue.d.ts +120 -0
- package/dist/components/LpSegmented.vue.d.ts +30 -0
- package/dist/components/LpSelect.vue.d.ts +47 -0
- package/dist/components/LpServiceNode.vue.d.ts +14 -0
- package/dist/components/LpShift.vue.d.ts +36 -0
- package/dist/components/LpShortcutsDialog.vue.d.ts +24 -0
- package/dist/components/LpSidebar.vue.d.ts +146 -0
- package/dist/components/LpSidebarNav.vue.d.ts +54 -0
- package/dist/components/LpSkeleton.vue.d.ts +16 -0
- package/dist/components/LpSlider.vue.d.ts +30 -0
- package/dist/components/LpSparkline.vue.d.ts +48 -0
- package/dist/components/LpStat.vue.d.ts +69 -0
- package/dist/components/LpStepper.vue.d.ts +36 -0
- package/dist/components/LpSwitch.vue.d.ts +42 -0
- package/dist/components/LpTable.vue.d.ts +124 -0
- package/dist/components/LpTableOfContents.vue.d.ts +19 -0
- package/dist/components/LpTabs.vue.d.ts +47 -0
- package/dist/components/LpTextarea.vue.d.ts +22 -0
- package/dist/components/LpThemeSwitcher.vue.d.ts +47 -0
- package/dist/components/LpTilt.vue.d.ts +31 -0
- package/dist/components/LpTimeField.vue.d.ts +24 -0
- package/dist/components/LpToaster.vue.d.ts +3 -0
- package/dist/components/LpTooltip.vue.d.ts +58 -0
- package/dist/components/LpTopologyCanvas.vue.d.ts +205 -0
- package/dist/components/LpUptimeBar.vue.d.ts +46 -0
- package/dist/components/LpWaypointEdge.vue.d.ts +33 -0
- package/dist/components/actionBar.d.ts +19 -0
- package/dist/components/address.d.ts +107 -0
- package/dist/components/chart.d.ts +180 -0
- package/dist/components/codeHighlight.d.ts +8 -0
- package/dist/components/color.d.ts +65 -0
- package/dist/components/commandSearch.d.ts +14 -0
- package/dist/components/countries-data.d.ts +2 -0
- package/dist/components/countries.d.ts +20 -0
- package/dist/components/dropdown.d.ts +29 -0
- package/dist/components/fileTree.d.ts +79 -0
- package/dist/components/lightbox.d.ts +24 -0
- package/dist/components/modalDepth.d.ts +11 -0
- package/dist/components/sidebar.d.ts +42 -0
- package/dist/composables/easing.d.ts +46 -0
- package/dist/composables/useAsyncTask.d.ts +18 -0
- package/dist/composables/useClipboard.d.ts +46 -0
- package/dist/composables/useFormDraft.d.ts +67 -0
- package/dist/composables/useGlass.d.ts +9 -0
- package/dist/composables/useHotkeys.d.ts +101 -0
- package/dist/composables/useInputFilter.d.ts +14 -0
- package/dist/composables/useMergedClass.d.ts +42 -0
- package/dist/composables/usePillTransition.d.ts +21 -0
- package/dist/composables/useReveal.d.ts +26 -0
- package/dist/composables/useRovingFocus.d.ts +49 -0
- package/dist/composables/useSettled.d.ts +26 -0
- package/dist/composables/useShift.d.ts +35 -0
- package/dist/composables/useTilt.d.ts +23 -0
- package/dist/composables/useToast.d.ts +41 -0
- package/dist/composables/useZoomPan.d.ts +58 -0
- package/dist/icons.d.ts +1 -0
- package/dist/index.d.ts +162 -0
- package/dist/layout/registry.d.ts +26 -0
- package/dist/layout/tree.d.ts +75 -0
- package/dist/layout/useLayout.d.ts +39 -0
- package/dist/theme/backdrop.d.ts +9 -0
- package/dist/theme/config.d.ts +16 -0
- package/dist/theme/define.d.ts +12 -0
- package/dist/theme/presets.d.ts +20 -0
- package/dist/theme/tokens.d.ts +75 -0
- package/dist/theme/useTheme.d.ts +46 -0
- package/package.json +2 -2
- package/src/components/LpCommandPalette.vue +4 -4
- package/src/components/LpImageEditor.vue +2 -2
- package/src/components/commandSearch.ts +1 -1
- package/src/composables/useHotkeys.ts +1 -1
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import type { ContextMenuItemDef } from "./LpContextMenu.vue";
|
|
2
|
+
export interface SidebarItem {
|
|
3
|
+
id: string;
|
|
4
|
+
label: string;
|
|
5
|
+
icon?: string;
|
|
6
|
+
/** Render as a link instead of a button. */
|
|
7
|
+
href?: string;
|
|
8
|
+
/** Count chip on the right (number or short string). */
|
|
9
|
+
badge?: number | string;
|
|
10
|
+
disabled?: boolean;
|
|
11
|
+
/** Right-click menu for this item (e.g. "Open in new tab", "Pin"). */
|
|
12
|
+
menu?: ContextMenuItemDef[];
|
|
13
|
+
/**
|
|
14
|
+
* Extra terms the sidebar's filter should match, beyond the label. For the
|
|
15
|
+
* item people look for under a name it does not carry — "Billing" found by
|
|
16
|
+
* "invoice", a page found by the feature it used to be called.
|
|
17
|
+
*/
|
|
18
|
+
keywords?: string[];
|
|
19
|
+
}
|
|
20
|
+
export interface SidebarSection {
|
|
21
|
+
/** Optional heading above the group. */
|
|
22
|
+
title?: string;
|
|
23
|
+
items: SidebarItem[];
|
|
24
|
+
/**
|
|
25
|
+
* The heading folds the group away when clicked. Needs a `title` — there is
|
|
26
|
+
* nothing to click otherwise.
|
|
27
|
+
*
|
|
28
|
+
* A long nav is read by scanning headings, not items: past a certain length
|
|
29
|
+
* every item is equally far from the eye, and folding the groups that are
|
|
30
|
+
* not today's work restores that. Which groups start folded is the app's
|
|
31
|
+
* call (see `collapsedIds`), not this component's.
|
|
32
|
+
*/
|
|
33
|
+
collapsible?: boolean;
|
|
34
|
+
/**
|
|
35
|
+
* Stable key for remembering this group's folded state. Defaults to `title`;
|
|
36
|
+
* set it when the title is translated, so the memory survives a language
|
|
37
|
+
* change.
|
|
38
|
+
*/
|
|
39
|
+
key?: string;
|
|
40
|
+
/** Icon for the heading — shown when the group is collapsible. */
|
|
41
|
+
icon?: string;
|
|
42
|
+
}
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Does the OS ask for less motion?
|
|
3
|
+
*
|
|
4
|
+
* Written out in eight places before this, in two different shapes — some
|
|
5
|
+
* guarded against SSR, some not, which is a crash in a Nuxt app rather than a
|
|
6
|
+
* style difference. Anything that animates asks here.
|
|
7
|
+
*
|
|
8
|
+
* A plain function, not a reactive composable: it is read at the moment an
|
|
9
|
+
* animation starts, and a component that also needs to RE-RENDER when the
|
|
10
|
+
* setting changes mid-session should use motion-v's `useReducedMotion`.
|
|
11
|
+
*/
|
|
12
|
+
export declare const prefersReducedMotion: () => boolean;
|
|
13
|
+
/**
|
|
14
|
+
* A motion token's value, for an API that cannot take a `var()`.
|
|
15
|
+
*
|
|
16
|
+
* The Web Animations API and SVG's SMIL both want a literal easing string, so
|
|
17
|
+
* three call sites had `cubic-bezier(0.2, 0, 0, 1)` typed out — the value of
|
|
18
|
+
* `--ease-emphasized`, copied. A theme that retuned the token moved everything
|
|
19
|
+
* except those, and nothing said they were meant to match.
|
|
20
|
+
*
|
|
21
|
+
* Reading the custom property keeps them themeable. The fallback covers SSR and
|
|
22
|
+
* the frame before tokens are applied.
|
|
23
|
+
*/
|
|
24
|
+
export declare const easingToken: (name: "ease-emphasized" | "ease-travel" | "ease-settle", fallback?: string) => string;
|
|
25
|
+
/**
|
|
26
|
+
* Comes to rest — `--ease-settle`'s shape without the overshoot.
|
|
27
|
+
*
|
|
28
|
+
* Gently decelerating: the value keeps moving visibly for most of the travel
|
|
29
|
+
* instead of arriving early and then creeping. Use it wherever a figure counts
|
|
30
|
+
* up to something, so the digits keep turning across the whole duration.
|
|
31
|
+
*/
|
|
32
|
+
export declare const easeOut: (t: number) => number;
|
|
33
|
+
/**
|
|
34
|
+
* Travels a distance the eye follows — the JS form of `--ease-travel`.
|
|
35
|
+
*
|
|
36
|
+
* Nearly linear, and deliberately so: an ease-out spends about half its
|
|
37
|
+
* duration covering the last tenth of the path, so a stroke or sweep animated
|
|
38
|
+
* with one flashes past and then visibly creeps. Use this wherever the journey
|
|
39
|
+
* is the content — a line drawing itself, a wipe crossing a plot, a circle
|
|
40
|
+
* sweeping open.
|
|
41
|
+
*
|
|
42
|
+
* The ease is applied only near the ends, and the finish is NOT flattened onto
|
|
43
|
+
* the target: the motion is still moving when it lands, which is what keeps
|
|
44
|
+
* the tail short.
|
|
45
|
+
*/
|
|
46
|
+
export declare const easeTravel: (t: number) => number;
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* One debounced, abortable request at a time — the shape every "fetch on input"
|
|
3
|
+
* control in the kit needs: the command palette's `search`, the table's `load`.
|
|
4
|
+
*
|
|
5
|
+
* Two races are lost silently without it: a stale response overwriting a
|
|
6
|
+
* fresher one, and a response landing after the control moved on. The token
|
|
7
|
+
* guards both — the abort signal only asks the consumer to stop, it cannot
|
|
8
|
+
* promise they did.
|
|
9
|
+
*/
|
|
10
|
+
export declare function useAsyncTask<T>(): {
|
|
11
|
+
pending: import("vue").Ref<boolean, boolean>;
|
|
12
|
+
run: (task: (signal: AbortSignal) => T | Promise<T>, options: {
|
|
13
|
+
delay?: number;
|
|
14
|
+
apply: (value: T) => void;
|
|
15
|
+
fail?: (error: unknown) => void;
|
|
16
|
+
}) => void;
|
|
17
|
+
cancel: () => void;
|
|
18
|
+
};
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
export interface CopyOptions {
|
|
2
|
+
/**
|
|
3
|
+
* Toast to raise on success. `false` (the default) stays silent, for callers
|
|
4
|
+
* whose button already shows the tick and would otherwise say it twice.
|
|
5
|
+
*/
|
|
6
|
+
toast?: string | false;
|
|
7
|
+
/**
|
|
8
|
+
* Toast to raise when the copy fails. Defaults to silence for the same
|
|
9
|
+
* reason the kit's other best-effort paths are silent: a copy that didn't
|
|
10
|
+
* happen is usually obvious, and a scary red box over a blocked clipboard
|
|
11
|
+
* helps nobody. Pass a string where losing the copy actually costs something.
|
|
12
|
+
*/
|
|
13
|
+
errorToast?: string | false;
|
|
14
|
+
}
|
|
15
|
+
export interface UseClipboard {
|
|
16
|
+
/**
|
|
17
|
+
* True for a moment after a successful copy. Bind it to swap a copy icon for
|
|
18
|
+
* a tick:
|
|
19
|
+
*
|
|
20
|
+
* ```vue
|
|
21
|
+
* <LpIcon :name="copied ? 'lucide:check' : 'lucide:copy'" />
|
|
22
|
+
* ```
|
|
23
|
+
*/
|
|
24
|
+
copied: import("vue").Ref<boolean>;
|
|
25
|
+
/**
|
|
26
|
+
* Writes `text` to the clipboard. Resolves true on success, false when the
|
|
27
|
+
* clipboard was unavailable or refused — it never rejects, so `await copy(x)`
|
|
28
|
+
* is safe to call bare from an event handler.
|
|
29
|
+
*/
|
|
30
|
+
copy: (text: string, options?: CopyOptions) => Promise<boolean>;
|
|
31
|
+
}
|
|
32
|
+
/**
|
|
33
|
+
* Clipboard writes with optional toast feedback.
|
|
34
|
+
*
|
|
35
|
+
* ```ts
|
|
36
|
+
* const { copy, copied } = useClipboard()
|
|
37
|
+
* copy(hex) // silent; bind `copied` to a tick
|
|
38
|
+
* copy(hex, { toast: "Copied #3b82f6" }) // says so
|
|
39
|
+
* ```
|
|
40
|
+
*
|
|
41
|
+
* Defaults are per-call rather than per-instance: one component often copies
|
|
42
|
+
* several things for different reasons — a menu item that should announce
|
|
43
|
+
* itself, a button that shows its own tick — and hoisting the choice to the
|
|
44
|
+
* composable would force those to agree.
|
|
45
|
+
*/
|
|
46
|
+
export declare function useClipboard(): UseClipboard;
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
import { type MaybeRefOrGetter, type Ref } from "vue";
|
|
2
|
+
export interface UseFormDraftOptions<T> {
|
|
3
|
+
/**
|
|
4
|
+
* Where this draft lives. Include whatever identifies the subject — a draft
|
|
5
|
+
* for device A must not surface while editing device B.
|
|
6
|
+
*/
|
|
7
|
+
key: MaybeRefOrGetter<string>;
|
|
8
|
+
/** The form's current value. Watched deeply; every change rewrites the draft. */
|
|
9
|
+
value: MaybeRefOrGetter<T>;
|
|
10
|
+
/**
|
|
11
|
+
* Whether there is anything worth keeping. Return false while the form still
|
|
12
|
+
* matches what was loaded, so an untouched form leaves nothing behind and no
|
|
13
|
+
* later visit is offered its own starting state back as a "draft".
|
|
14
|
+
*/
|
|
15
|
+
dirty?: MaybeRefOrGetter<boolean>;
|
|
16
|
+
/**
|
|
17
|
+
* How long a draft stays offerable, in milliseconds. Older ones are dropped
|
|
18
|
+
* on read: a fortnight-old draft of a record that has been edited twice since
|
|
19
|
+
* is not a rescue, it is a way to overwrite current facts with stale ones.
|
|
20
|
+
* Defaults to a week. `0` keeps them indefinitely.
|
|
21
|
+
*/
|
|
22
|
+
maxAgeMs?: number;
|
|
23
|
+
/** Skip the write without tearing the composable out of the component. */
|
|
24
|
+
disabled?: MaybeRefOrGetter<boolean>;
|
|
25
|
+
}
|
|
26
|
+
export interface UseFormDraft<T> {
|
|
27
|
+
/** A draft was found for this key, and has not been restored or discarded. */
|
|
28
|
+
hasDraft: Ref<boolean>;
|
|
29
|
+
/** When that draft was written, ISO-8601, or `null` when there is none. */
|
|
30
|
+
savedAt: Ref<string | null>;
|
|
31
|
+
/**
|
|
32
|
+
* The stored value, or `null`. Reading does not apply it — the caller decides
|
|
33
|
+
* what to do with each field, because only it knows the form's shape.
|
|
34
|
+
*/
|
|
35
|
+
read: () => T | null;
|
|
36
|
+
/** Forget the draft. Call after applying it, and after a successful save. */
|
|
37
|
+
discard: () => void;
|
|
38
|
+
/** Write now, ignoring `dirty`. For "save and come back to this later". */
|
|
39
|
+
save: () => void;
|
|
40
|
+
}
|
|
41
|
+
/**
|
|
42
|
+
* Keeps an unsaved form in browser storage, so losing the page does not lose
|
|
43
|
+
* what was typed into it.
|
|
44
|
+
*
|
|
45
|
+
* ```ts
|
|
46
|
+
* const draft = useFormDraft({
|
|
47
|
+
* key: () => `lp.draft.device-power:${deviceId.value}`,
|
|
48
|
+
* value: () => interfaces.value,
|
|
49
|
+
* dirty: () => hasUnsavedChanges.value,
|
|
50
|
+
* })
|
|
51
|
+
* ```
|
|
52
|
+
* ```vue
|
|
53
|
+
* <LpAlert v-if="draft.hasDraft.value" variant="info">
|
|
54
|
+
* {{ t("draft.found", { when: draft.savedAt.value }) }}
|
|
55
|
+
* <LpButton @click="applyDraft">Restore</LpButton>
|
|
56
|
+
* <LpButton variant="ghost" @click="draft.discard()">Discard</LpButton>
|
|
57
|
+
* </LpAlert>
|
|
58
|
+
* ```
|
|
59
|
+
*
|
|
60
|
+
* `hasDraft` answers for the key as it is now, so a form that switches subject
|
|
61
|
+
* re-reads rather than carrying the previous subject's answer.
|
|
62
|
+
*
|
|
63
|
+
* Call `discard()` once the record is saved. A draft that outlives the save it
|
|
64
|
+
* describes is offered back on the next visit as though it were newer than the
|
|
65
|
+
* record, which is how a form helpfully undoes somebody's work.
|
|
66
|
+
*/
|
|
67
|
+
export declare function useFormDraft<T>(options: UseFormDraftOptions<T>): UseFormDraft<T>;
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { type ComputedRef, type MaybeRefOrGetter } from "vue";
|
|
2
|
+
/** Make `glass` the default for every overlay below the calling component. */
|
|
3
|
+
export declare function provideGlass(enabled?: MaybeRefOrGetter<boolean>): void;
|
|
4
|
+
/**
|
|
5
|
+
* The glass flag an overlay renders with: its own prop when set, otherwise the
|
|
6
|
+
* nearest `provideGlass`, otherwise off. The prop must default to `undefined`,
|
|
7
|
+
* not `false`, or an unset prop could not be told apart from an explicit off.
|
|
8
|
+
*/
|
|
9
|
+
export declare function useGlass(own: () => boolean | undefined): ComputedRef<boolean>;
|
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
import { type MaybeRefOrGetter } from "vue";
|
|
2
|
+
export interface HotkeyBinding {
|
|
3
|
+
/** Layout-produced key, compared case-insensitively ("l", "f2", "escape"). */
|
|
4
|
+
key: string;
|
|
5
|
+
/**
|
|
6
|
+
* Physical key position ("KeyL", "F2", "Digit1"). Matches on its own, which
|
|
7
|
+
* is what makes non-Latin layouts work.
|
|
8
|
+
*/
|
|
9
|
+
code?: string;
|
|
10
|
+
/** Ctrl on Windows/Linux, ⌘ on macOS — the two are treated as one. */
|
|
11
|
+
ctrl?: boolean;
|
|
12
|
+
shift?: boolean;
|
|
13
|
+
alt?: boolean;
|
|
14
|
+
/**
|
|
15
|
+
* Runs even while a text field has focus. Only for shortcuts that mean
|
|
16
|
+
* something there — Escape, and the palette the user reaches from anywhere.
|
|
17
|
+
*/
|
|
18
|
+
allowInInput?: boolean;
|
|
19
|
+
/**
|
|
20
|
+
* How the key reference lists this binding while it is mounted. Bindings
|
|
21
|
+
* without it still work, they just stay out of `activeShortcuts`.
|
|
22
|
+
*/
|
|
23
|
+
help?: HotkeyHelp;
|
|
24
|
+
/**
|
|
25
|
+
* Returning `false` declines the key: the event keeps its default and the
|
|
26
|
+
* search moves on. This is what lets a binding defer to a layer that owns the
|
|
27
|
+
* key better than it does — Escape belongs to whichever overlay is on top,
|
|
28
|
+
* and swallowing it here would close all of them. The event is passed for
|
|
29
|
+
* the checks only it can answer: where the focus is, whether an inner
|
|
30
|
+
* control already took the key.
|
|
31
|
+
*/
|
|
32
|
+
handler: (event: KeyboardEvent) => void | boolean;
|
|
33
|
+
}
|
|
34
|
+
export interface HotkeyHelp {
|
|
35
|
+
/** Section of the reference the entry goes under. */
|
|
36
|
+
group: string;
|
|
37
|
+
label: string;
|
|
38
|
+
/**
|
|
39
|
+
* Written the way it reads, "+"-separated. Defaults to one built from the
|
|
40
|
+
* binding; set it where the binding is not the whole story, such as the
|
|
41
|
+
* second key of a chord ("G+D") or a key that needs Shift to type ("?").
|
|
42
|
+
*/
|
|
43
|
+
combo?: string;
|
|
44
|
+
}
|
|
45
|
+
export interface ShortcutEntry {
|
|
46
|
+
/** Rendered one <kbd> per "+"-separated key, so write it the way it reads. */
|
|
47
|
+
combo: string;
|
|
48
|
+
label: string;
|
|
49
|
+
}
|
|
50
|
+
export interface ShortcutGroup {
|
|
51
|
+
title: string;
|
|
52
|
+
entries: ShortcutEntry[];
|
|
53
|
+
}
|
|
54
|
+
/**
|
|
55
|
+
* Whether this machine prints ⌘ where the rest print Ctrl. Read once: the
|
|
56
|
+
* keyboard does not change under a running window, and the check is only ever
|
|
57
|
+
* used to pick a label.
|
|
58
|
+
*/
|
|
59
|
+
export declare const isAppleKeyboard: boolean;
|
|
60
|
+
/**
|
|
61
|
+
* The symbol to print for a modifier on this platform. Bindings treat Ctrl and
|
|
62
|
+
* Meta as one modifier, so only the label may differ — never the binding.
|
|
63
|
+
*/
|
|
64
|
+
export declare function appleModifierLabel(key: string): string;
|
|
65
|
+
/**
|
|
66
|
+
* Bind a list of hotkeys for as long as the calling component is mounted.
|
|
67
|
+
*
|
|
68
|
+
* The list is read on every keystroke rather than captured once, so bindings
|
|
69
|
+
* may come and go with the state that owns them — a getter is the point, not a
|
|
70
|
+
* formality.
|
|
71
|
+
*/
|
|
72
|
+
export interface UseHotkeysOptions {
|
|
73
|
+
enabled?: MaybeRefOrGetter<boolean>;
|
|
74
|
+
priority?: MaybeRefOrGetter<number>;
|
|
75
|
+
/**
|
|
76
|
+
* Only act while the focus is inside this element.
|
|
77
|
+
*
|
|
78
|
+
* The default is the whole window, which is right for a command palette and
|
|
79
|
+
* wrong for a control: two of the same component on one page would both
|
|
80
|
+
* answer the same key, and a control beside a form would answer keys aimed
|
|
81
|
+
* at the form. Scoping it here rather than in each component because every
|
|
82
|
+
* one of them was about to write the same `document.activeElement` check and
|
|
83
|
+
* decline by hand.
|
|
84
|
+
*
|
|
85
|
+
* Undefined or null means the window, so the palette case stays the default.
|
|
86
|
+
*/
|
|
87
|
+
scope?: MaybeRefOrGetter<HTMLElement | null | undefined>;
|
|
88
|
+
}
|
|
89
|
+
export declare function useHotkeys(bindings: MaybeRefOrGetter<HotkeyBinding[]>, options?: UseHotkeysOptions): void;
|
|
90
|
+
/**
|
|
91
|
+
* The shortcuts that work right now, grouped for `LpShortcutsDialog`: every
|
|
92
|
+
* binding with `help` from every mounted `useHotkeys`. A screen that binds its
|
|
93
|
+
* own keys adds its section while it is open, so the reference never lists a
|
|
94
|
+
* key that does nothing here or misses one that does.
|
|
95
|
+
*/
|
|
96
|
+
export declare const activeShortcuts: import("vue").ComputedRef<ShortcutGroup[]>;
|
|
97
|
+
/**
|
|
98
|
+
* Groups merged by title, entries kept once per combo: what a reference shows
|
|
99
|
+
* when it lists both its own entries and the live ones.
|
|
100
|
+
*/
|
|
101
|
+
export declare function mergeShortcutGroups(...lists: ShortcutGroup[][]): ShortcutGroup[];
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { type MaybeRefOrGetter } from "vue";
|
|
2
|
+
export interface UseInputFilterOptions {
|
|
3
|
+
/** One-char RegExp of allowed characters. Disallowed input is blocked. */
|
|
4
|
+
restrict?: MaybeRefOrGetter<RegExp | undefined>;
|
|
5
|
+
/** RegExp/string the full value must match to be valid. Validation only. */
|
|
6
|
+
pattern?: MaybeRefOrGetter<RegExp | string | undefined>;
|
|
7
|
+
}
|
|
8
|
+
export declare function useInputFilter(options?: UseInputFilterOptions): {
|
|
9
|
+
isInvalid: (value: string | undefined) => boolean;
|
|
10
|
+
onBeforeInput: (event: InputEvent) => void;
|
|
11
|
+
onPaste: (event: ClipboardEvent) => void;
|
|
12
|
+
patternRe: import("vue").ComputedRef<RegExp | undefined>;
|
|
13
|
+
restrict: import("vue").ComputedRef<RegExp | undefined>;
|
|
14
|
+
};
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import { type ComputedRef, type MaybeRefOrGetter } from "vue";
|
|
2
|
+
/**
|
|
3
|
+
* Merges the component's own classes with the `class` attribute the consumer
|
|
4
|
+
* passed, resolving Tailwind conflicts in the consumer's favour.
|
|
5
|
+
*
|
|
6
|
+
* ```ts
|
|
7
|
+
* const rootClass = useMergedClass(() => shell({ size: props.size }))
|
|
8
|
+
* ```
|
|
9
|
+
* ```vue
|
|
10
|
+
* <div :class="rootClass">
|
|
11
|
+
* ```
|
|
12
|
+
*
|
|
13
|
+
* Pair it with `inheritAttrs: false` (and bind the rest of `$attrs` yourself)
|
|
14
|
+
* so the raw `class` does not land on the element a second time, unmerged.
|
|
15
|
+
*/
|
|
16
|
+
export declare function useMergedClass(own: MaybeRefOrGetter<string | undefined>): ComputedRef<string>;
|
|
17
|
+
/**
|
|
18
|
+
* `useMergedClass` plus the rest of `$attrs`, for the common `inheritAttrs:
|
|
19
|
+
* false` shape: bind `class` and `attrs` and the consumer's `class` lands once,
|
|
20
|
+
* merged, while ids, handlers and aria-* still reach the element.
|
|
21
|
+
*
|
|
22
|
+
* ```ts
|
|
23
|
+
* const { class: rootClass, attrs: rest } = useMergedAttrs(() => card({ padded }))
|
|
24
|
+
* ```
|
|
25
|
+
* ```vue
|
|
26
|
+
* <div :class="rootClass" v-bind="rest">
|
|
27
|
+
* ```
|
|
28
|
+
*
|
|
29
|
+
* Binding the raw `$attrs` alongside a merged class is the bug this avoids:
|
|
30
|
+
* Vue appends that second `class` to the merged one, and stylesheet order —
|
|
31
|
+
* not the caller — decides which wins.
|
|
32
|
+
*/
|
|
33
|
+
export declare function useMergedAttrs(own: MaybeRefOrGetter<string | undefined>): {
|
|
34
|
+
class: ComputedRef<string>;
|
|
35
|
+
attrs: ComputedRef<Record<string, unknown>>;
|
|
36
|
+
};
|
|
37
|
+
/**
|
|
38
|
+
* The same merge as a plain function, for the places that already have both
|
|
39
|
+
* strings in hand and do not need the attrs lookup — a render helper, or a
|
|
40
|
+
* component merging a class onto a child rather than its own root.
|
|
41
|
+
*/
|
|
42
|
+
export declare function mergeClass(...classes: (string | undefined | null | false)[]): string;
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { type ComputedRef } from "vue";
|
|
2
|
+
export type PillTransition = {
|
|
3
|
+
duration: number;
|
|
4
|
+
} | {
|
|
5
|
+
type: "spring";
|
|
6
|
+
stiffness: number;
|
|
7
|
+
damping: number;
|
|
8
|
+
};
|
|
9
|
+
export type PillFeel = "pill" | "float";
|
|
10
|
+
export declare function usePillTransition(feel?: PillFeel): ComputedRef<PillTransition>;
|
|
11
|
+
export interface SpringState {
|
|
12
|
+
/** Current position; seed it with the start value. */
|
|
13
|
+
value: number;
|
|
14
|
+
/** Current velocity; seed with 0. */
|
|
15
|
+
velocity: number;
|
|
16
|
+
}
|
|
17
|
+
export declare function springStep(state: SpringState, target: number, feel?: PillFeel,
|
|
18
|
+
/** Frame time in seconds; clamped so a backgrounded tab can't explode it. */
|
|
19
|
+
dt?: number): SpringState;
|
|
20
|
+
/** True once a spring is close enough to its target to stop animating. */
|
|
21
|
+
export declare const springSettled: (state: SpringState, target: number) => boolean;
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import { type MaybeRefOrGetter, type Ref } from "vue";
|
|
2
|
+
export interface UseRevealOptions {
|
|
3
|
+
/**
|
|
4
|
+
* Skip the wait and reveal at once. For a caller that has switched its
|
|
5
|
+
* entrance off — there is nothing to gate, and holding content back for an
|
|
6
|
+
* observer that no longer guards anything only delays the first paint.
|
|
7
|
+
*/
|
|
8
|
+
immediate?: MaybeRefOrGetter<boolean | undefined>;
|
|
9
|
+
/**
|
|
10
|
+
* Fraction of the element that must be on screen. A sliver of a tall chart
|
|
11
|
+
* scrolling into view is not yet an arrival; a quarter of it is.
|
|
12
|
+
*/
|
|
13
|
+
threshold?: number;
|
|
14
|
+
/**
|
|
15
|
+
* Grow the viewport for the test, so an element just past the fold starts
|
|
16
|
+
* drawing as it is scrolled toward rather than after it lands.
|
|
17
|
+
*/
|
|
18
|
+
rootMargin?: string;
|
|
19
|
+
}
|
|
20
|
+
export interface UseReveal {
|
|
21
|
+
/** Attach to the element whose appearance starts the animation. */
|
|
22
|
+
el: Ref<Element | null>;
|
|
23
|
+
/** False until that element has been seen; true forever after. */
|
|
24
|
+
revealed: Ref<boolean>;
|
|
25
|
+
}
|
|
26
|
+
export declare function useReveal(options?: UseRevealOptions): UseReveal;
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
import { type MaybeRefOrGetter } from "vue";
|
|
2
|
+
export interface RovingItem {
|
|
3
|
+
/** Stable identity of the row. */
|
|
4
|
+
id: string;
|
|
5
|
+
/**
|
|
6
|
+
* What typeahead matches against. Omit to opt this row out of typeahead —
|
|
7
|
+
* a separator, say.
|
|
8
|
+
*/
|
|
9
|
+
label?: string;
|
|
10
|
+
disabled?: boolean;
|
|
11
|
+
}
|
|
12
|
+
export interface UseRovingFocusOptions {
|
|
13
|
+
/**
|
|
14
|
+
* Which axis the arrows follow. `vertical` (default) uses ↑↓, `horizontal`
|
|
15
|
+
* uses ←→, `both` accepts either — for a grid whose wrapping the caller
|
|
16
|
+
* cannot describe here.
|
|
17
|
+
*/
|
|
18
|
+
orientation?: "vertical" | "horizontal" | "both";
|
|
19
|
+
/** Wrap around at the ends instead of stopping. Default true. */
|
|
20
|
+
loop?: boolean;
|
|
21
|
+
/** Jump to an item by typing its first letters. Default true. */
|
|
22
|
+
typeahead?: boolean;
|
|
23
|
+
/** Called when the user activates the current item (Enter or Space). */
|
|
24
|
+
onActivate?: (id: string) => void;
|
|
25
|
+
/**
|
|
26
|
+
* Called when focus should leave the list without activating anything —
|
|
27
|
+
* Escape. Lets a dialog close, or a filter field take focus back.
|
|
28
|
+
*/
|
|
29
|
+
onEscape?: () => void;
|
|
30
|
+
}
|
|
31
|
+
export declare function useRovingFocus(items: MaybeRefOrGetter<RovingItem[]>, options?: UseRovingFocusOptions): {
|
|
32
|
+
activeId: import("vue").Ref<string | undefined, string | undefined>;
|
|
33
|
+
focus: (id: string | undefined) => void;
|
|
34
|
+
move: (delta: number) => void;
|
|
35
|
+
first: () => void;
|
|
36
|
+
last: () => void;
|
|
37
|
+
onKeydown: (event: KeyboardEvent) => void;
|
|
38
|
+
setContainer: (el: HTMLElement | null) => void;
|
|
39
|
+
containerProps: import("vue").ComputedRef<{
|
|
40
|
+
ref: (el: unknown) => void;
|
|
41
|
+
onKeydown: (event: KeyboardEvent) => void;
|
|
42
|
+
}>;
|
|
43
|
+
itemProps: (id: string) => {
|
|
44
|
+
tabindex: number;
|
|
45
|
+
"data-active": string | undefined;
|
|
46
|
+
"data-roving-id": string;
|
|
47
|
+
onFocus: () => void;
|
|
48
|
+
};
|
|
49
|
+
};
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import { type MaybeRefOrGetter } from "vue";
|
|
2
|
+
export interface UseSettledOptions {
|
|
3
|
+
/** Override the wait. Defaults to the kit's overlay animation duration. */
|
|
4
|
+
delay?: MaybeRefOrGetter<number>;
|
|
5
|
+
}
|
|
6
|
+
/**
|
|
7
|
+
* Returns a ref that flips true once `open` has been truthy for the length of
|
|
8
|
+
* the overlay's opening animation. Gate expensive content on it:
|
|
9
|
+
*
|
|
10
|
+
* ```ts
|
|
11
|
+
* const settled = useSettled(() => isOpen.value)
|
|
12
|
+
* ```
|
|
13
|
+
* ```vue
|
|
14
|
+
* <RowList v-if="settled" :rows="rows" />
|
|
15
|
+
* <RowSkeletons v-else />
|
|
16
|
+
* ```
|
|
17
|
+
*
|
|
18
|
+
* Anything truthy counts as open, so an id can be passed instead of a boolean.
|
|
19
|
+
* That is the useful form when the same panel is reused for different subjects:
|
|
20
|
+
* the wait restarts when the id changes, because the panel is mounting a whole
|
|
21
|
+
* new body without ever having closed.
|
|
22
|
+
*
|
|
23
|
+
* With reduced motion there is no animation to protect, so it resolves on the
|
|
24
|
+
* next tick rather than making the user wait for a delay that buys nothing.
|
|
25
|
+
*/
|
|
26
|
+
export declare function useSettled(open: MaybeRefOrGetter<unknown>, options?: UseSettledOptions): import("vue").Ref<boolean, boolean>;
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import { type MaybeRefOrGetter, type Ref } from "vue";
|
|
2
|
+
export type ShiftAxis = "height" | "width" | "both";
|
|
3
|
+
export interface UseShiftOptions {
|
|
4
|
+
/** Which dimension is content-derived. Default `"height"`. */
|
|
5
|
+
axis?: MaybeRefOrGetter<ShiftAxis | undefined>;
|
|
6
|
+
/** Tween length. Defaults to the kit's `--duration-fast` (160ms). */
|
|
7
|
+
duration?: MaybeRefOrGetter<number | undefined>;
|
|
8
|
+
/**
|
|
9
|
+
* Gate: while falsy the element is left entirely alone — no observers, no
|
|
10
|
+
* pinning. Use it for a box that only exists while something is open, so a
|
|
11
|
+
* remounted element starts measuring from scratch rather than easing in from
|
|
12
|
+
* a size it held in a previous life. Default: always active.
|
|
13
|
+
*/
|
|
14
|
+
enabled?: MaybeRefOrGetter<unknown>;
|
|
15
|
+
}
|
|
16
|
+
export interface UseShift {
|
|
17
|
+
/** Attach to the element whose content-derived size should ease. */
|
|
18
|
+
el: Ref<HTMLElement | null>;
|
|
19
|
+
/**
|
|
20
|
+
* True while a tween owns the size. Bind the transition utilities off this,
|
|
21
|
+
* so the element is only transition-enabled once it has a size to ease FROM
|
|
22
|
+
* (otherwise the very first pin animates in from zero).
|
|
23
|
+
*/
|
|
24
|
+
tweening: Ref<boolean>;
|
|
25
|
+
/**
|
|
26
|
+
* True while the element is still catching up to its new size. During the
|
|
27
|
+
* tween the box is briefly smaller than the content it already holds, so any
|
|
28
|
+
* scroll region inside it would raise a bar for an overflow that resolves
|
|
29
|
+
* itself as the tween lands — hide the bar (not the scrolling) on this.
|
|
30
|
+
*/
|
|
31
|
+
resizing: Ref<boolean>;
|
|
32
|
+
/** Re-measure and ease to the current natural size. Rarely needed by hand. */
|
|
33
|
+
retune: () => void;
|
|
34
|
+
}
|
|
35
|
+
export declare function useShift(options?: UseShiftOptions): UseShift;
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { type ComputedRef, type CSSProperties, type Ref } from "vue";
|
|
2
|
+
export interface UseTiltOptions {
|
|
3
|
+
/** Max rotation toward the pointer, in degrees (per axis). Default 10. */
|
|
4
|
+
max?: number;
|
|
5
|
+
/** Upward lift on hover, in px. Default 8. */
|
|
6
|
+
lift?: number;
|
|
7
|
+
/** Scale on hover. Default 1.03. */
|
|
8
|
+
scale?: number;
|
|
9
|
+
/** Glare highlight following the pointer. Default false. */
|
|
10
|
+
glare?: boolean;
|
|
11
|
+
}
|
|
12
|
+
export interface UseTilt {
|
|
13
|
+
/** Bind to the tilting element's style. */
|
|
14
|
+
style: ComputedRef<CSSProperties>;
|
|
15
|
+
/** Radial-gradient background for an optional glare overlay (0 when idle). */
|
|
16
|
+
glareStyle: ComputedRef<CSSProperties>;
|
|
17
|
+
onPointerMove: (e: PointerEvent) => void;
|
|
18
|
+
onPointerEnter: () => void;
|
|
19
|
+
onPointerLeave: () => void;
|
|
20
|
+
/** True while the pointer is over the element (drives lift/scale). */
|
|
21
|
+
active: Ref<boolean>;
|
|
22
|
+
}
|
|
23
|
+
export declare function useTilt(options?: UseTiltOptions): UseTilt;
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
export type ToastVariant = "info" | "success" | "warning" | "error";
|
|
2
|
+
export interface ToastAction {
|
|
3
|
+
label: string;
|
|
4
|
+
/** Optional leading icon (any name LpIcon accepts, e.g. "lucide:copy"). */
|
|
5
|
+
icon?: string;
|
|
6
|
+
onClick: () => void | Promise<void>;
|
|
7
|
+
}
|
|
8
|
+
export interface ToastItem {
|
|
9
|
+
id: number;
|
|
10
|
+
title?: string;
|
|
11
|
+
message: string;
|
|
12
|
+
variant: ToastVariant;
|
|
13
|
+
duration: number;
|
|
14
|
+
/** Epoch ms when this toast auto-dismisses, or null if it never does. */
|
|
15
|
+
dismissAt: number | null;
|
|
16
|
+
actions?: ToastAction[];
|
|
17
|
+
/** Whole-toast click handler (UAProject-style clickable toast). */
|
|
18
|
+
onClick?: () => void | Promise<void>;
|
|
19
|
+
}
|
|
20
|
+
export interface ToastOptions {
|
|
21
|
+
title?: string;
|
|
22
|
+
duration?: number;
|
|
23
|
+
actions?: ToastAction[];
|
|
24
|
+
onClick?: () => void | Promise<void>;
|
|
25
|
+
}
|
|
26
|
+
declare function push(variant: ToastVariant, message: string, options?: ToastOptions): number;
|
|
27
|
+
declare function dismiss(id: number): void;
|
|
28
|
+
declare function clear(): void;
|
|
29
|
+
export declare function useToast(): {
|
|
30
|
+
queue: ToastItem[];
|
|
31
|
+
toast: (message: string, o?: ToastOptions) => number;
|
|
32
|
+
info: (message: string, o?: ToastOptions) => number;
|
|
33
|
+
success: (message: string, o?: ToastOptions) => number;
|
|
34
|
+
warning: (message: string, o?: ToastOptions) => number;
|
|
35
|
+
error: (message: string, o?: ToastOptions) => number;
|
|
36
|
+
/** Low-level push for bridges (e.g. @leavepulse/ui-sdk apiError). */
|
|
37
|
+
push: typeof push;
|
|
38
|
+
dismiss: typeof dismiss;
|
|
39
|
+
clear: typeof clear;
|
|
40
|
+
};
|
|
41
|
+
export {};
|