@lilydesignsystem/vue-motion-picker 0.2.0 → 0.3.1
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/LICENSE.md +64 -0
- package/README.md +82 -0
- package/dist/MotionPicker.vue.d.ts +14 -2
- package/dist/index.js +82 -69
- package/index.md +11 -11
- package/package.json +19 -5
package/LICENSE.md
ADDED
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
<!-- Synced from the canonical repository by bin/sync-special-files.
|
|
2
|
+
Do not edit here; edit the root copy and re-run the script.
|
|
3
|
+
Canonical: https://github.com/LilyDesignSystem/lily-design-system/blob/main/LICENSE.md -->
|
|
4
|
+
|
|
5
|
+
# License
|
|
6
|
+
|
|
7
|
+
Lily Design System™ is free open source software.
|
|
8
|
+
|
|
9
|
+
License is any of these, at your option, or contact us for custom license options.
|
|
10
|
+
|
|
11
|
+
- [MIT](https://opensource.org/license/mit) ([SPDX: MIT](https://spdx.org/licenses/MIT.html))
|
|
12
|
+
|
|
13
|
+
- [Apache License 2.0](https://www.apache.org/licenses/LICENSE-2.0) ([SPDX: Apache-2.0](https://spdx.org/licenses/Apache-2.0.html))
|
|
14
|
+
|
|
15
|
+
- [GNU General Public License v2.0](https://www.gnu.org/licenses/old-licenses/gpl-2.0-standalone.html) ([SPDX: GPL-2.0-only](https://spdx.org/licenses/GPL-2.0-only.html))
|
|
16
|
+
|
|
17
|
+
- [GNU General Public License v3.0](https://www.gnu.org/licenses/gpl-3.0-standalone.html) ([SPDX: GPL-3.0-only](https://spdx.org/licenses/GPL-3.0-only.html))
|
|
18
|
+
|
|
19
|
+
- [BSD 3-Clause License](https://opensource.org/license/bsd-3-clause) ([SPDX: BSD-3-Clause](https://spdx.org/licenses/BSD-3-Clause.html))
|
|
20
|
+
|
|
21
|
+
## SPDX
|
|
22
|
+
|
|
23
|
+
The machine-readable expression for the choice above is:
|
|
24
|
+
|
|
25
|
+
```
|
|
26
|
+
SPDX-License-Identifier: MIT OR Apache-2.0 OR GPL-2.0-only OR GPL-3.0-only OR BSD-3-Clause
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
Every package manifest in this repository should carry that expression, or a
|
|
30
|
+
single identifier from the list where the packaging format does not accept a
|
|
31
|
+
disjunction. You do not need permission to pick one: choose whichever member of
|
|
32
|
+
the list suits your project and comply with that one.
|
|
33
|
+
|
|
34
|
+
This applies to the whole repository — the component catalog, the headless
|
|
35
|
+
libraries, the example applications, the helper packages, the `themes/`
|
|
36
|
+
stylesheets, the `bin/` tooling, and the documentation.
|
|
37
|
+
|
|
38
|
+
## Scope note
|
|
39
|
+
|
|
40
|
+
This file supersedes an earlier `CC BY-NC-SA` notice. That notice was a content
|
|
41
|
+
license with a non-commercial clause, it was not an open-source license, and it
|
|
42
|
+
contradicted both the specification and the published packages. It should not be
|
|
43
|
+
relied on. If you obtained Lily under it and that raises a question for you,
|
|
44
|
+
contact <joel@joelparkerhenderson.com>.
|
|
45
|
+
|
|
46
|
+
## Trademarks
|
|
47
|
+
|
|
48
|
+
Lily™ and Lily Design System™ are trademarks. The trademarks are distinct from
|
|
49
|
+
the software license: a trademark claim (™) asserts use of the marks and is
|
|
50
|
+
independent of the licenses above. A license to the software is not a license to
|
|
51
|
+
the marks.
|
|
52
|
+
|
|
53
|
+
You may say your project uses Lily, is built with Lily, or is compatible with
|
|
54
|
+
Lily. Please do not use the marks as the name of your fork or product, or in a
|
|
55
|
+
way that suggests affiliation or endorsement. For any use beyond that, contact
|
|
56
|
+
<joel@joelparkerhenderson.com>.
|
|
57
|
+
|
|
58
|
+
## Third-party references
|
|
59
|
+
|
|
60
|
+
Lily's example applications and `themes/` stylesheets take visual reference from
|
|
61
|
+
public-sector design systems including NHS UK, GOV.UK, and USWDS. Lily is not
|
|
62
|
+
affiliated with, endorsed by, or connected to any of those organisations. Their
|
|
63
|
+
names and marks belong to them, and this license grants nothing in respect of
|
|
64
|
+
them.
|
package/README.md
ADDED
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
# MotionPicker (Vue helper)
|
|
2
|
+
|
|
3
|
+
A reusable Vue 3 headless **motion (reduced-motion) picker** — an icon
|
|
4
|
+
button that opens a WAI-ARIA APG listbox of motion-preference slugs.
|
|
5
|
+
On every change it sets `data-motion="{slug}"` on a target element
|
|
6
|
+
(default `document.documentElement`), optionally persisting the choice
|
|
7
|
+
to `localStorage`. Ships no CSS — the consumer decides what
|
|
8
|
+
`data-motion="reduce"` actually suppresses, e.g.:
|
|
9
|
+
|
|
10
|
+
```css
|
|
11
|
+
:root[data-motion="reduce"] * {
|
|
12
|
+
animation-duration: 0.001ms !important;
|
|
13
|
+
animation-iteration-count: 1 !important;
|
|
14
|
+
transition-duration: 0.001ms !important;
|
|
15
|
+
scroll-behavior: auto !important;
|
|
16
|
+
}
|
|
17
|
+
```
|
|
18
|
+
|
|
19
|
+
Unlike its `theme-picker` and `text-size-picker` siblings, MotionPicker's
|
|
20
|
+
initial value defers to the platform's own
|
|
21
|
+
`(prefers-reduced-motion: reduce)` media query before falling back to
|
|
22
|
+
an arbitrary default.
|
|
23
|
+
|
|
24
|
+
## Usage
|
|
25
|
+
|
|
26
|
+
```vue
|
|
27
|
+
<script setup lang="ts">
|
|
28
|
+
import { ref } from "vue";
|
|
29
|
+
import MotionPicker from "@lilydesignsystem/vue-motion-picker";
|
|
30
|
+
|
|
31
|
+
const motion = ref("");
|
|
32
|
+
</script>
|
|
33
|
+
|
|
34
|
+
<template>
|
|
35
|
+
<MotionPicker
|
|
36
|
+
label="Motion"
|
|
37
|
+
:motions="['no-preference', 'reduce']"
|
|
38
|
+
v-model:value="motion"
|
|
39
|
+
storageKey="lily-motion"
|
|
40
|
+
/>
|
|
41
|
+
</template>
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
## Props
|
|
45
|
+
|
|
46
|
+
| Prop | Type | Required | Description |
|
|
47
|
+
| -------------- | ----------------------- | -------- | -------------------------------------------------------- |
|
|
48
|
+
| `label` | `string` | yes | Accessible name (`aria-label`) for the button + listbox. |
|
|
49
|
+
| `motions` | `string[]` | yes | Available motion slugs. |
|
|
50
|
+
| `value` | `string` | no | Selected slug. Two-way bindable via `v-model:value`. |
|
|
51
|
+
| `defaultValue` | `string` | no | Initial slug when nothing else is supplied. |
|
|
52
|
+
| `storageKey` | `string` | no | If set, persist the slug to `localStorage`. |
|
|
53
|
+
| `name` | `string` | no | `name` of the hidden input (default `"motion"`). |
|
|
54
|
+
| `target` | `HTMLElement \| null` | no | Element to receive `data-motion`. Default `<html>`. |
|
|
55
|
+
| `motionLabels` | `Record<string,string>` | no | Pretty labels per slug. |
|
|
56
|
+
| `class` | `string` | no | Extra CSS class on the root. |
|
|
57
|
+
|
|
58
|
+
Emits `change` (the applied slug) and `update:value` (for
|
|
59
|
+
`v-model:value`).
|
|
60
|
+
|
|
61
|
+
## Behaviour
|
|
62
|
+
|
|
63
|
+
Initial value resolves from `value` > storage > `defaultValue` > the
|
|
64
|
+
platform's `(prefers-reduced-motion: reduce)` preference (mapped to
|
|
65
|
+
`"reduce"` / `"no-preference"` if either is in `motions`) > `motions[0]`.
|
|
66
|
+
All DOM writes happen inside `onMounted`/`watch`, so the component is
|
|
67
|
+
SSR-safe.
|
|
68
|
+
|
|
69
|
+
## Accessibility
|
|
70
|
+
|
|
71
|
+
- WCAG 2.2 AAA target; directly supports 2.3.3 (Animation from
|
|
72
|
+
Interactions).
|
|
73
|
+
- APG listbox keyboard contract: arrows (clamped), `Home` / `End`,
|
|
74
|
+
`PageUp` / `PageDown` (by ten), typeahead with same-character
|
|
75
|
+
cycling, `Escape` discards, and `Tab` closes via the button so the
|
|
76
|
+
default Tab proceeds from the picker's position.
|
|
77
|
+
- `aria-label` carries the consumer-supplied accessible name.
|
|
78
|
+
- Default labels title-case the slug.
|
|
79
|
+
|
|
80
|
+
---
|
|
81
|
+
|
|
82
|
+
Lily™ and Lily Design System™ are trademarks.
|
|
@@ -37,6 +37,8 @@ export type Props = {
|
|
|
37
37
|
target?: HTMLElement | null;
|
|
38
38
|
/** Optional pretty labels per slug. */
|
|
39
39
|
motionLabels?: Record<string, string>;
|
|
40
|
+
/** Disables the button; an open popup closes. The popup's open state is `v-model:open`. */
|
|
41
|
+
disabled?: boolean;
|
|
40
42
|
/** Extra CSS class on the root element. */
|
|
41
43
|
class?: string;
|
|
42
44
|
};
|
|
@@ -57,10 +59,19 @@ export declare function prefersReducedMotion(): boolean;
|
|
|
57
59
|
export declare function nextMotionPickerId(): string;
|
|
58
60
|
declare const _default: typeof __VLS_export;
|
|
59
61
|
export default _default;
|
|
60
|
-
declare const __VLS_export: __VLS_WithSlots<import("vue").DefineComponent<Props
|
|
62
|
+
declare const __VLS_export: __VLS_WithSlots<import("vue").DefineComponent<Props & {
|
|
63
|
+
/** Is the popup open? Bindable: `v-model:open` (the picker keeps its own state when none is bound). */
|
|
64
|
+
open?: boolean;
|
|
65
|
+
}, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {
|
|
66
|
+
"update:open": (value: boolean) => any;
|
|
67
|
+
} & {
|
|
61
68
|
"update:value": (value: string) => any;
|
|
62
69
|
change: (value: string) => any;
|
|
63
|
-
}, string, import("vue").PublicProps, Readonly<Props
|
|
70
|
+
}, string, import("vue").PublicProps, Readonly<Props & {
|
|
71
|
+
/** Is the popup open? Bindable: `v-model:open` (the picker keeps its own state when none is bound). */
|
|
72
|
+
open?: boolean;
|
|
73
|
+
}> & Readonly<{
|
|
74
|
+
"onUpdate:open"?: ((value: boolean) => any) | undefined;
|
|
64
75
|
"onUpdate:value"?: ((value: string) => any) | undefined;
|
|
65
76
|
onChange?: ((value: string) => any) | undefined;
|
|
66
77
|
}>, {
|
|
@@ -70,6 +81,7 @@ declare const __VLS_export: __VLS_WithSlots<import("vue").DefineComponent<Props,
|
|
|
70
81
|
name: string;
|
|
71
82
|
target: HTMLElement | null;
|
|
72
83
|
motionLabels: Record<string, string>;
|
|
84
|
+
disabled: boolean;
|
|
73
85
|
class: string;
|
|
74
86
|
}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>, {
|
|
75
87
|
default?: (props: {
|
package/dist/index.js
CHANGED
|
@@ -1,16 +1,16 @@
|
|
|
1
|
-
import { Fragment as e, computed as t, createElementBlock as n, createElementVNode as r, createVNode as i, defineComponent as a, guardReactiveProps as o,
|
|
2
|
-
import { IconButton as
|
|
3
|
-
|
|
4
|
-
var
|
|
1
|
+
import { Fragment as e, computed as t, createElementBlock as n, createElementVNode as r, createVNode as i, defineComponent as a, guardReactiveProps as o, mergeModels as s, nextTick as c, normalizeClass as l, normalizeProps as ee, onBeforeUnmount as u, onMounted as te, openBlock as d, ref as f, renderList as p, renderSlot as ne, toDisplayString as m, unref as h, useModel as g, watch as _, withCtx as v } from "vue";
|
|
2
|
+
import { IconButton as re, Listbox as y } from "@lilydesignsystem/vue-headless";
|
|
3
|
+
// MotionPicker.vue?vue&type=script&setup=true&lang.ts
|
|
4
|
+
var b = ["name", "value"], x = ["hidden"], ie = [
|
|
5
5
|
"id",
|
|
6
6
|
"aria-selected",
|
|
7
7
|
"data-active",
|
|
8
8
|
"onClick"
|
|
9
9
|
];
|
|
10
|
-
function
|
|
10
|
+
function S(e) {
|
|
11
11
|
return e.split("-").map((e) => e.charAt(0).toUpperCase() + e.slice(1)).join(" ");
|
|
12
12
|
}
|
|
13
|
-
function
|
|
13
|
+
function C() {
|
|
14
14
|
if (typeof window > "u" || typeof window.matchMedia != "function") return !1;
|
|
15
15
|
try {
|
|
16
16
|
return window.matchMedia("(prefers-reduced-motion: reduce)").matches;
|
|
@@ -18,15 +18,14 @@ function S() {
|
|
|
18
18
|
return !1;
|
|
19
19
|
}
|
|
20
20
|
}
|
|
21
|
-
var
|
|
22
|
-
function
|
|
23
|
-
return
|
|
21
|
+
var w = 0;
|
|
22
|
+
function T() {
|
|
23
|
+
return w += 1, `motion-picker-${w}`;
|
|
24
24
|
}
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
var T = /* @__PURE__ */ a({
|
|
25
|
+
// MotionPicker.vue
|
|
26
|
+
var E = /* @__PURE__ */ a({
|
|
28
27
|
__name: "MotionPicker",
|
|
29
|
-
props: {
|
|
28
|
+
props: /*@__PURE__*/ s({
|
|
30
29
|
label: {},
|
|
31
30
|
motions: {},
|
|
32
31
|
value: { default: "" },
|
|
@@ -35,15 +34,29 @@ var T = /* @__PURE__ */ a({
|
|
|
35
34
|
name: { default: "motion" },
|
|
36
35
|
target: { default: void 0 },
|
|
37
36
|
motionLabels: { default: () => ({}) },
|
|
37
|
+
disabled: {
|
|
38
|
+
type: Boolean,
|
|
39
|
+
default: !1
|
|
40
|
+
},
|
|
38
41
|
class: { default: "" }
|
|
39
|
-
},
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
42
|
+
}, {
|
|
43
|
+
open: {
|
|
44
|
+
type: Boolean,
|
|
45
|
+
default: !1
|
|
46
|
+
},
|
|
47
|
+
openModifiers: {}
|
|
48
|
+
}),
|
|
49
|
+
emits: /*@__PURE__*/ s(["update:value", "change"], ["update:open"]),
|
|
50
|
+
setup(a, { emit: s }) {
|
|
51
|
+
let w = a, E = s, D = T(), O = `${D}-list`, k = (e) => `${D}-option-${e}`, A = g(a, "open");
|
|
52
|
+
_(() => w.disabled, (e) => {
|
|
53
|
+
e && (A.value = !1);
|
|
54
|
+
}, { immediate: !0 });
|
|
55
|
+
let j = `${D}-tooltip`, M = f(!1), N = f(!1), P = f(!1), F = f(!1), I = t(() => !A.value && !F.value && (M.value || N.value || P.value));
|
|
56
|
+
function ae() {
|
|
44
57
|
M.value = !0, F.value = !1;
|
|
45
58
|
}
|
|
46
|
-
function
|
|
59
|
+
function oe() {
|
|
47
60
|
M.value = !1;
|
|
48
61
|
}
|
|
49
62
|
function L(e) {
|
|
@@ -66,61 +79,61 @@ var T = /* @__PURE__ */ a({
|
|
|
66
79
|
function H(e) {
|
|
67
80
|
typeof document < "u" && e !== V && (V = e, e ? document.addEventListener("keydown", B) : document.removeEventListener("keydown", B));
|
|
68
81
|
}
|
|
69
|
-
|
|
70
|
-
let U =
|
|
82
|
+
_(I, (e) => H(e), { flush: "sync" }), u(() => H(!1));
|
|
83
|
+
let U = f(-1), W = f(null), G = f(null), K = f(null);
|
|
71
84
|
function q(e) {
|
|
72
|
-
let t =
|
|
73
|
-
return e in t ? t[e] :
|
|
85
|
+
let t = w.motionLabels ?? {};
|
|
86
|
+
return e in t ? t[e] : S(e);
|
|
74
87
|
}
|
|
75
88
|
function J(e) {
|
|
76
89
|
if (typeof document < "u" && e) {
|
|
77
|
-
if ((
|
|
78
|
-
localStorage.setItem(
|
|
90
|
+
if ((w.target ?? document.documentElement).setAttribute("data-motion", e), w.storageKey) try {
|
|
91
|
+
localStorage.setItem(w.storageKey, e);
|
|
79
92
|
} catch {}
|
|
80
93
|
E("change", e);
|
|
81
94
|
}
|
|
82
95
|
}
|
|
83
|
-
let Y =
|
|
84
|
-
function
|
|
96
|
+
let Y = f(w.value ?? "");
|
|
97
|
+
function se(e) {
|
|
85
98
|
Y.value = e, E("update:value", e);
|
|
86
99
|
}
|
|
87
|
-
|
|
100
|
+
_(() => w.value, (e) => {
|
|
88
101
|
e !== void 0 && e !== Y.value && (Y.value = e);
|
|
89
|
-
}),
|
|
102
|
+
}), _(Y, (e, t) => {
|
|
90
103
|
e && e !== t && J(e);
|
|
91
104
|
});
|
|
92
105
|
async function X(e) {
|
|
93
|
-
let t =
|
|
94
|
-
U.value =
|
|
106
|
+
let t = w.motions.indexOf(Y.value);
|
|
107
|
+
U.value = w.motions.length === 0 ? -1 : e ?? (t >= 0 ? t : 0), A.value = !0, await c(), G.value?.el?.focus({ preventScroll: !0 });
|
|
95
108
|
}
|
|
96
109
|
async function Z(e = !0) {
|
|
97
|
-
A.value && (A.value = !1, U.value = -1, e && (await
|
|
110
|
+
A.value && (A.value = !1, U.value = -1, e && (await c(), W.value?.el?.focus({ preventScroll: !0 })));
|
|
98
111
|
}
|
|
99
112
|
function Q(e) {
|
|
100
|
-
let t =
|
|
101
|
-
t &&
|
|
113
|
+
let t = w.motions[e];
|
|
114
|
+
t && se(t), Z();
|
|
102
115
|
}
|
|
103
|
-
function
|
|
116
|
+
function ce() {
|
|
104
117
|
U.value < 0 || !G.value?.el || document.getElementById(k(U.value))?.scrollIntoView?.({ block: "nearest" });
|
|
105
118
|
}
|
|
106
|
-
|
|
107
|
-
function
|
|
119
|
+
_(U, () => ce());
|
|
120
|
+
function le() {
|
|
108
121
|
W.value?.el?.focus?.({ preventScroll: !0 }), Z(!1);
|
|
109
122
|
}
|
|
110
|
-
function
|
|
123
|
+
function ue() {
|
|
111
124
|
M.value = !1, A.value ? Z() : X();
|
|
112
125
|
}
|
|
113
|
-
function
|
|
126
|
+
function de(e) {
|
|
114
127
|
switch (z(e), e.key) {
|
|
115
128
|
case "ArrowDown":
|
|
116
129
|
case "Enter":
|
|
117
130
|
case " ":
|
|
118
131
|
e.preventDefault(), X();
|
|
119
132
|
break;
|
|
120
|
-
case "ArrowUp": e.preventDefault(), X(
|
|
133
|
+
case "ArrowUp": e.preventDefault(), X(w.motions.length - 1);
|
|
121
134
|
}
|
|
122
135
|
}
|
|
123
|
-
function
|
|
136
|
+
function fe(e) {
|
|
124
137
|
let t = e.relatedTarget;
|
|
125
138
|
t && K.value?.contains(t) || Z(!1);
|
|
126
139
|
}
|
|
@@ -132,32 +145,29 @@ var T = /* @__PURE__ */ a({
|
|
|
132
145
|
return te(() => {
|
|
133
146
|
document.addEventListener("click", $);
|
|
134
147
|
let e = Y.value;
|
|
135
|
-
if (!e &&
|
|
136
|
-
e = localStorage.getItem(
|
|
148
|
+
if (!e && w.storageKey) try {
|
|
149
|
+
e = localStorage.getItem(w.storageKey) ?? "";
|
|
137
150
|
} catch {}
|
|
138
151
|
if (!e) {
|
|
139
|
-
let t =
|
|
140
|
-
e =
|
|
141
|
-
}
|
|
142
|
-
if (e && e !== Y.value) {
|
|
143
|
-
Y.value = e, E("update:value", e);
|
|
144
|
-
return;
|
|
152
|
+
let t = C() ? "reduce" : "no-preference";
|
|
153
|
+
e = w.defaultValue ?? (w.motions.includes(t) ? t : void 0) ?? w.motions[0] ?? "";
|
|
145
154
|
}
|
|
146
|
-
e && J(e);
|
|
147
|
-
}),
|
|
155
|
+
e && e !== Y.value ? (Y.value = e, E("update:value", e)) : e && J(e);
|
|
156
|
+
}), u(() => {
|
|
148
157
|
document.removeEventListener("click", $);
|
|
149
|
-
}), (t, s) => (
|
|
158
|
+
}), (t, s) => (d(), n("div", {
|
|
150
159
|
ref_key: "rootEl",
|
|
151
160
|
ref: K,
|
|
152
|
-
class:
|
|
153
|
-
onFocusout:
|
|
161
|
+
class: l(`motion-picker ${w.class}`.trim()),
|
|
162
|
+
onFocusout: fe
|
|
154
163
|
}, [
|
|
155
164
|
r("input", {
|
|
156
165
|
type: "hidden",
|
|
157
166
|
name: a.name,
|
|
158
167
|
value: Y.value
|
|
159
|
-
}, null, 8,
|
|
160
|
-
i(
|
|
168
|
+
}, null, 8, b),
|
|
169
|
+
i(h(re), {
|
|
170
|
+
disabled: a.disabled,
|
|
161
171
|
ref_key: "buttonEl",
|
|
162
172
|
ref: W,
|
|
163
173
|
baseClass: "motion-picker-button",
|
|
@@ -165,14 +175,14 @@ var T = /* @__PURE__ */ a({
|
|
|
165
175
|
"aria-haspopup": "listbox",
|
|
166
176
|
"aria-expanded": A.value ? "true" : "false",
|
|
167
177
|
"aria-controls": O,
|
|
168
|
-
onClick:
|
|
169
|
-
onKeydown:
|
|
170
|
-
onMouseenter:
|
|
171
|
-
onMouseleave:
|
|
178
|
+
onClick: ue,
|
|
179
|
+
onKeydown: de,
|
|
180
|
+
onMouseenter: ae,
|
|
181
|
+
onMouseleave: oe,
|
|
172
182
|
onFocus: L,
|
|
173
183
|
onBlur: R
|
|
174
184
|
}, {
|
|
175
|
-
default:
|
|
185
|
+
default: v(() => [ne(t.$slots, "default", ee(o({
|
|
176
186
|
value: Y.value,
|
|
177
187
|
open: A.value,
|
|
178
188
|
labelFor: q
|
|
@@ -189,7 +199,11 @@ var T = /* @__PURE__ */ a({
|
|
|
189
199
|
"stroke-linejoin": "round"
|
|
190
200
|
}, [r("path", { d: "M5 3v10M11 3v10" })], -1)])]),
|
|
191
201
|
_: 3
|
|
192
|
-
}, 8, [
|
|
202
|
+
}, 8, [
|
|
203
|
+
"disabled",
|
|
204
|
+
"label",
|
|
205
|
+
"aria-expanded"
|
|
206
|
+
]),
|
|
193
207
|
r("div", {
|
|
194
208
|
class: "motion-picker-tooltip",
|
|
195
209
|
role: "tooltip",
|
|
@@ -197,8 +211,8 @@ var T = /* @__PURE__ */ a({
|
|
|
197
211
|
hidden: !I.value || void 0,
|
|
198
212
|
onMouseenter: s[0] ||= (e) => N.value = !0,
|
|
199
213
|
onMouseleave: s[1] ||= (e) => N.value = !1
|
|
200
|
-
},
|
|
201
|
-
i(
|
|
214
|
+
}, m(a.label), 41, x),
|
|
215
|
+
i(h(y), {
|
|
202
216
|
ref_key: "listEl",
|
|
203
217
|
ref: G,
|
|
204
218
|
as: "ul",
|
|
@@ -214,9 +228,9 @@ var T = /* @__PURE__ */ a({
|
|
|
214
228
|
hidden: !A.value || void 0,
|
|
215
229
|
onActivate: Q,
|
|
216
230
|
onEscape: s[3] ||= () => Z(),
|
|
217
|
-
onTabOut:
|
|
231
|
+
onTabOut: le
|
|
218
232
|
}, {
|
|
219
|
-
default:
|
|
233
|
+
default: v(() => [(d(!0), n(e, null, p(a.motions, (e, t) => (d(), n("li", {
|
|
220
234
|
key: e,
|
|
221
235
|
class: "motion-picker-option",
|
|
222
236
|
id: k(t),
|
|
@@ -224,7 +238,7 @@ var T = /* @__PURE__ */ a({
|
|
|
224
238
|
"aria-selected": e === Y.value ? "true" : "false",
|
|
225
239
|
"data-active": t === U.value ? "" : void 0,
|
|
226
240
|
onClick: (e) => Q(t)
|
|
227
|
-
},
|
|
241
|
+
}, m(q(e)), 9, ie))), 128))]),
|
|
228
242
|
_: 1
|
|
229
243
|
}, 8, [
|
|
230
244
|
"label",
|
|
@@ -234,5 +248,4 @@ var T = /* @__PURE__ */ a({
|
|
|
234
248
|
], 34));
|
|
235
249
|
}
|
|
236
250
|
});
|
|
237
|
-
|
|
238
|
-
export { T as MotionPicker, T as default, x as motionName, w as nextMotionPickerId, S as prefersReducedMotion };
|
|
251
|
+
export { E as MotionPicker, E as default, S as motionName, T as nextMotionPickerId, C as prefersReducedMotion };
|
package/index.md
CHANGED
|
@@ -43,17 +43,17 @@ const motion = ref("");
|
|
|
43
43
|
|
|
44
44
|
## Props
|
|
45
45
|
|
|
46
|
-
| Prop | Type
|
|
47
|
-
| -------------- |
|
|
48
|
-
| `label` | `string`
|
|
49
|
-
| `motions` | `string[]`
|
|
50
|
-
| `value` | `string`
|
|
51
|
-
| `defaultValue` | `string`
|
|
52
|
-
| `storageKey` | `string`
|
|
53
|
-
| `name` | `string`
|
|
54
|
-
| `target` | `HTMLElement \| null`
|
|
55
|
-
| `motionLabels` | `Record<string,string>`
|
|
56
|
-
| `class` | `string`
|
|
46
|
+
| Prop | Type | Required | Description |
|
|
47
|
+
| -------------- | ----------------------- | -------- | -------------------------------------------------------- |
|
|
48
|
+
| `label` | `string` | yes | Accessible name (`aria-label`) for the button + listbox. |
|
|
49
|
+
| `motions` | `string[]` | yes | Available motion slugs. |
|
|
50
|
+
| `value` | `string` | no | Selected slug. Two-way bindable via `v-model:value`. |
|
|
51
|
+
| `defaultValue` | `string` | no | Initial slug when nothing else is supplied. |
|
|
52
|
+
| `storageKey` | `string` | no | If set, persist the slug to `localStorage`. |
|
|
53
|
+
| `name` | `string` | no | `name` of the hidden input (default `"motion"`). |
|
|
54
|
+
| `target` | `HTMLElement \| null` | no | Element to receive `data-motion`. Default `<html>`. |
|
|
55
|
+
| `motionLabels` | `Record<string,string>` | no | Pretty labels per slug. |
|
|
56
|
+
| `class` | `string` | no | Extra CSS class on the root. |
|
|
57
57
|
|
|
58
58
|
Emits `change` (the applied slug) and `update:value` (for
|
|
59
59
|
`v-model:value`).
|
package/package.json
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@lilydesignsystem/vue-motion-picker",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.3.1",
|
|
4
4
|
"engines": {
|
|
5
|
-
"node": "
|
|
5
|
+
"node": ">=26"
|
|
6
6
|
},
|
|
7
7
|
"description": "Lily Design System - Vue 3 motion (reduced-motion) picker",
|
|
8
8
|
"type": "module",
|
|
@@ -21,14 +21,28 @@
|
|
|
21
21
|
"README.md"
|
|
22
22
|
],
|
|
23
23
|
"scripts": {
|
|
24
|
-
"
|
|
24
|
+
"build": "node build.mjs",
|
|
25
|
+
"test": "vitest run",
|
|
26
|
+
"check": "vue-tsc --noEmit -p tsconfig.lib.json",
|
|
27
|
+
"test:watch": "vitest",
|
|
28
|
+
"prepublishOnly": "npm run build"
|
|
25
29
|
},
|
|
26
30
|
"dependencies": {
|
|
27
|
-
"@lilydesignsystem/vue-headless": "^0.
|
|
31
|
+
"@lilydesignsystem/vue-headless": "^0.7.0"
|
|
28
32
|
},
|
|
29
33
|
"peerDependencies": {
|
|
30
34
|
"vue": "^3.0.0"
|
|
31
35
|
},
|
|
36
|
+
"devDependencies": {
|
|
37
|
+
"@vitejs/plugin-vue": "^6.0.10",
|
|
38
|
+
"@vue/test-utils": "^2.5.1",
|
|
39
|
+
"jsdom": "^30.1.3",
|
|
40
|
+
"typescript": "^5.9.3",
|
|
41
|
+
"vite": "^8.3.5",
|
|
42
|
+
"vitest": "^5.0.5",
|
|
43
|
+
"vue": "^3.5.44",
|
|
44
|
+
"vue-tsc": "^3.3.14"
|
|
45
|
+
},
|
|
32
46
|
"keywords": [
|
|
33
47
|
"lily",
|
|
34
48
|
"design",
|
|
@@ -42,7 +56,7 @@
|
|
|
42
56
|
"license": "MIT OR Apache-2.0 OR GPL-2.0-only OR GPL-3.0-only OR BSD-3-Clause",
|
|
43
57
|
"repository": {
|
|
44
58
|
"type": "git",
|
|
45
|
-
"url": "git+https://github.com/LilyDesignSystem/lily-design-system
|
|
59
|
+
"url": "git+https://github.com/LilyDesignSystem/lily-design-system.git",
|
|
46
60
|
"directory": "lily-design-system-vue-motion-picker"
|
|
47
61
|
},
|
|
48
62
|
"homepage": "https://lilydesignsystem.com/",
|