blessing-ui 0.1.0 → 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +38 -0
- package/README.md +65 -43
- package/dist/blessing-ui.css +60 -0
- package/dist/components/BlessCodeBlock.css +1 -0
- package/dist/components/BlessCodeBlock.js +6 -0
- package/dist/components/BlessCodeBlock.vue.d.ts +62 -0
- package/dist/components/BlessCodeBlock.vue_vue_type_script_setup_true_lang.js +134 -0
- package/dist/components/BlessCountUp.css +1 -0
- package/dist/components/BlessCountUp.js +6 -0
- package/dist/components/BlessCountUp.vue.d.ts +18 -0
- package/dist/components/BlessCountUp.vue_vue_type_script_setup_true_lang.js +49 -0
- package/dist/components/BlessCropper.css +1 -0
- package/dist/components/BlessCropper.js +6 -0
- package/dist/components/BlessCropper.vue.d.ts +54 -0
- package/dist/components/BlessCropper.vue_vue_type_script_setup_true_lang.js +212 -0
- package/dist/components/BlessDiff.css +1 -0
- package/dist/components/BlessDiff.js +6 -0
- package/dist/components/BlessDiff.vue.d.ts +22 -0
- package/dist/components/BlessDiff.vue_vue_type_script_setup_true_lang.js +148 -0
- package/dist/components/BlessGantt.css +1 -0
- package/dist/components/BlessGantt.js +6 -0
- package/dist/components/BlessGantt.vue.d.ts +69 -0
- package/dist/components/BlessGantt.vue_vue_type_script_setup_true_lang.js +270 -0
- package/dist/components/BlessGauge.css +1 -0
- package/dist/components/BlessGauge.js +6 -0
- package/dist/components/BlessGauge.vue.d.ts +36 -0
- package/dist/components/BlessGauge.vue_vue_type_script_setup_true_lang.js +100 -0
- package/dist/components/BlessHeatmapCalendar.css +1 -0
- package/dist/components/BlessHeatmapCalendar.js +6 -0
- package/dist/components/BlessHeatmapCalendar.vue.d.ts +38 -0
- package/dist/components/BlessHeatmapCalendar.vue_vue_type_script_setup_true_lang.js +146 -0
- package/dist/components/BlessHotspots.css +1 -0
- package/dist/components/BlessHotspots.js +6 -0
- package/dist/components/BlessHotspots.vue.d.ts +49 -0
- package/dist/components/BlessHotspots.vue_vue_type_script_setup_true_lang.js +127 -0
- package/dist/components/BlessKanban.css +1 -0
- package/dist/components/BlessKanban.js +6 -0
- package/dist/components/BlessKanban.vue.d.ts +55 -0
- package/dist/components/BlessKanban.vue_vue_type_script_setup_true_lang.js +165 -0
- package/dist/components/BlessLoupe.css +1 -0
- package/dist/components/BlessLoupe.js +6 -0
- package/dist/components/BlessLoupe.vue.d.ts +16 -0
- package/dist/components/BlessLoupe.vue_vue_type_script_setup_true_lang.js +93 -0
- package/dist/components/BlessMarquee.css +1 -0
- package/dist/components/BlessMarquee.js +6 -0
- package/dist/components/BlessMarquee.vue.d.ts +40 -0
- package/dist/components/BlessMarquee.vue_vue_type_script_setup_true_lang.js +64 -0
- package/dist/components/BlessMasonry.css +1 -0
- package/dist/components/BlessMasonry.js +6 -0
- package/dist/components/BlessMasonry.vue.d.ts +33 -0
- package/dist/components/BlessMasonry.vue_vue_type_script_setup_true_lang.js +79 -0
- package/dist/components/BlessMention.css +1 -0
- package/dist/components/BlessMention.js +6 -0
- package/dist/components/BlessMention.vue.d.ts +32 -0
- package/dist/components/BlessMention.vue_vue_type_script_setup_true_lang.js +116 -0
- package/dist/components/BlessRadialMenu.css +1 -0
- package/dist/components/BlessRadialMenu.js +6 -0
- package/dist/components/BlessRadialMenu.vue.d.ts +45 -0
- package/dist/components/BlessRadialMenu.vue_vue_type_script_setup_true_lang.js +146 -0
- package/dist/components/BlessShortcutRecorder.css +1 -0
- package/dist/components/BlessShortcutRecorder.js +6 -0
- package/dist/components/BlessShortcutRecorder.vue.d.ts +29 -0
- package/dist/components/BlessShortcutRecorder.vue_vue_type_script_setup_true_lang.js +116 -0
- package/dist/components/BlessSliderCaptcha.css +1 -0
- package/dist/components/BlessSliderCaptcha.js +6 -0
- package/dist/components/BlessSliderCaptcha.vue.d.ts +33 -0
- package/dist/components/BlessSliderCaptcha.vue_vue_type_script_setup_true_lang.js +141 -0
- package/dist/components/BlessSortable.css +1 -0
- package/dist/components/BlessSortable.js +6 -0
- package/dist/components/BlessSortable.vue.d.ts +33 -0
- package/dist/components/BlessSortable.vue_vue_type_script_setup_true_lang.js +87 -0
- package/dist/components/BlessSplitView.css +1 -0
- package/dist/components/BlessSplitView.js +6 -0
- package/dist/components/BlessSplitView.vue.d.ts +61 -0
- package/dist/components/BlessSplitView.vue_vue_type_script_setup_true_lang.js +92 -0
- package/dist/components/BlessSwipeDeck.css +1 -0
- package/dist/components/BlessSwipeDeck.js +6 -0
- package/dist/components/BlessSwipeDeck.vue.d.ts +46 -0
- package/dist/components/BlessSwipeDeck.vue_vue_type_script_setup_true_lang.js +199 -0
- package/dist/components/BlessTimer.css +1 -0
- package/dist/components/BlessTimer.js +6 -0
- package/dist/components/BlessTimer.vue.d.ts +56 -0
- package/dist/components/BlessTimer.vue_vue_type_script_setup_true_lang.js +130 -0
- package/dist/composables/cropBox.d.ts +22 -0
- package/dist/composables/cropBox.js +39 -0
- package/dist/composables/diffLines.d.ts +10 -0
- package/dist/composables/diffLines.js +55 -0
- package/dist/composables/radial.d.ts +15 -0
- package/dist/composables/radial.js +22 -0
- package/dist/composables/shortcut.d.ts +12 -0
- package/dist/composables/shortcut.js +35 -0
- package/dist/composables/useSortable.d.ts +18 -0
- package/dist/composables/useSortable.js +34 -0
- package/dist/index.d.ts +37 -0
- package/dist/index.js +78 -53
- package/package.json +20 -18
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
import { computed as e, createCommentVNode as t, createElementBlock as n, createElementVNode as r, defineComponent as i, normalizeStyle as a, openBlock as o, ref as s } from "vue";
|
|
2
|
+
//#region src/components/BlessLoupe.vue?vue&type=script&setup=true&lang.ts
|
|
3
|
+
var c = ["src", "alt"], l = /*@__PURE__*/ i({
|
|
4
|
+
name: "BlessLoupe",
|
|
5
|
+
__name: "BlessLoupe",
|
|
6
|
+
props: {
|
|
7
|
+
src: {},
|
|
8
|
+
alt: {},
|
|
9
|
+
zoomSrc: {},
|
|
10
|
+
zoom: { default: 2.5 },
|
|
11
|
+
size: { default: 140 }
|
|
12
|
+
},
|
|
13
|
+
setup(i) {
|
|
14
|
+
let l = i, u = s(), d = s(null), f = s({
|
|
15
|
+
w: 1,
|
|
16
|
+
h: 1
|
|
17
|
+
}), p = s(!1), m = s({
|
|
18
|
+
x: .5,
|
|
19
|
+
y: .5
|
|
20
|
+
});
|
|
21
|
+
function h(e, t) {
|
|
22
|
+
let n = u.value.getBoundingClientRect();
|
|
23
|
+
f.value = {
|
|
24
|
+
w: n.width,
|
|
25
|
+
h: n.height
|
|
26
|
+
}, d.value = {
|
|
27
|
+
x: Math.min(n.width, Math.max(0, e - n.left)),
|
|
28
|
+
y: Math.min(n.height, Math.max(0, t - n.top))
|
|
29
|
+
};
|
|
30
|
+
}
|
|
31
|
+
function g(e) {
|
|
32
|
+
p.value = e.pointerType === "touch" || e.pointerType === "pen", h(e.clientX, e.clientY);
|
|
33
|
+
}
|
|
34
|
+
let _ = () => d.value = null;
|
|
35
|
+
function v() {
|
|
36
|
+
let e = u.value.getBoundingClientRect();
|
|
37
|
+
h(e.left + m.value.x * e.width, e.top + m.value.y * e.height);
|
|
38
|
+
}
|
|
39
|
+
function y(e) {
|
|
40
|
+
let t = e.shiftKey ? .2 : .05, n = {
|
|
41
|
+
ArrowLeft: [-t, 0],
|
|
42
|
+
ArrowRight: [t, 0],
|
|
43
|
+
ArrowUp: [0, -t],
|
|
44
|
+
ArrowDown: [0, t]
|
|
45
|
+
};
|
|
46
|
+
if (e.key === "Escape") return _();
|
|
47
|
+
n[e.key] && (e.preventDefault(), p.value = !1, m.value = {
|
|
48
|
+
x: Math.min(1, Math.max(0, m.value.x + n[e.key][0])),
|
|
49
|
+
y: Math.min(1, Math.max(0, m.value.y + n[e.key][1]))
|
|
50
|
+
}, v());
|
|
51
|
+
}
|
|
52
|
+
let b = e(() => {
|
|
53
|
+
let e = d.value;
|
|
54
|
+
if (!e) return;
|
|
55
|
+
let { zoom: t, size: n } = l, r = p.value ? n / 2 + 28 : 0;
|
|
56
|
+
return {
|
|
57
|
+
width: `${n}px`,
|
|
58
|
+
height: `${n}px`,
|
|
59
|
+
left: `${e.x - n / 2}px`,
|
|
60
|
+
top: `${e.y - n / 2 - r}px`,
|
|
61
|
+
backgroundImage: `url(${l.zoomSrc ?? l.src})`,
|
|
62
|
+
backgroundSize: `${f.value.w * t}px ${f.value.h * t}px`,
|
|
63
|
+
backgroundPosition: `${n / 2 - e.x * t}px ${n / 2 - e.y * t}px`
|
|
64
|
+
};
|
|
65
|
+
});
|
|
66
|
+
return (e, s) => (o(), n("div", {
|
|
67
|
+
ref_key: "root",
|
|
68
|
+
ref: u,
|
|
69
|
+
class: "bless-loupe",
|
|
70
|
+
tabindex: "0",
|
|
71
|
+
onPointerenter: g,
|
|
72
|
+
onPointermove: g,
|
|
73
|
+
onPointerleave: _,
|
|
74
|
+
onPointercancel: _,
|
|
75
|
+
onPointerup: s[0] ||= (e) => p.value && _(),
|
|
76
|
+
onFocus: v,
|
|
77
|
+
onBlur: _,
|
|
78
|
+
onKeydown: y
|
|
79
|
+
}, [r("img", {
|
|
80
|
+
src: i.src,
|
|
81
|
+
alt: i.alt,
|
|
82
|
+
class: "bless-loupe__img",
|
|
83
|
+
draggable: "false"
|
|
84
|
+
}, null, 8, c), b.value ? (o(), n("span", {
|
|
85
|
+
key: 0,
|
|
86
|
+
class: "bless-loupe__lens",
|
|
87
|
+
style: a(b.value),
|
|
88
|
+
"aria-hidden": "true"
|
|
89
|
+
}, null, 4)) : t("", !0)], 544));
|
|
90
|
+
}
|
|
91
|
+
});
|
|
92
|
+
//#endregion
|
|
93
|
+
export { l as default };
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
.bless-marquee{align-items:center;gap:var(--bless-space-2);--bless-marquee-dir:1;min-width:0;max-width:100%;font-family:var(--bless-font-sans);color:var(--bless-color-text);display:flex;position:relative}[dir=rtl] .bless-marquee{--bless-marquee-dir:-1}.bless-marquee__viewport{flex:1;min-width:0;overflow:hidden}.bless-marquee__track{width:max-content;animation:bless-marquee var(--bless-marquee-time) linear infinite;display:flex}.bless-marquee--reverse .bless-marquee__track{animation-direction:reverse}.bless-marquee__run{align-items:center;gap:var(--bless-space-6);flex:none;padding-inline-end:var(--bless-space-6);display:flex}.bless-marquee--paused .bless-marquee__track,.bless-marquee--hover:hover .bless-marquee__track,.bless-marquee--hover:focus-within .bless-marquee__track{animation-play-state:paused}.bless-marquee--still .bless-marquee__track{flex-wrap:wrap;width:auto;animation:none}.bless-marquee--still .bless-marquee__run:last-child{display:none}.bless-marquee__btn{padding:var(--bless-space-1) var(--bless-space-2);border:var(--bless-border-width) solid var(--bless-color-border);background:var(--bless-color-bg);color:inherit;font:inherit;font-size:var(--bless-text-xs);cursor:pointer;flex:none}.bless-marquee__btn:focus-visible{outline:2px solid var(--bless-color-accent);outline-offset:2px}@keyframes bless-marquee{to{transform:translateX(calc(var(--bless-marquee-dir) * -50%))}}@media (prefers-reduced-motion:reduce){.bless-marquee__track{animation:none}}
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
type __VLS_Props = {
|
|
2
|
+
/** px per second */
|
|
3
|
+
speed?: number;
|
|
4
|
+
/** run the other way (toward the start of the line) */
|
|
5
|
+
reverse?: boolean;
|
|
6
|
+
/** stop while the pointer is over it or focus is inside */
|
|
7
|
+
pauseOnHover?: boolean;
|
|
8
|
+
/** show the Pause button (needed when it moves for more than five seconds, WCAG 2.2.2) */
|
|
9
|
+
controls?: boolean;
|
|
10
|
+
label?: string;
|
|
11
|
+
};
|
|
12
|
+
type __VLS_ModelProps = {
|
|
13
|
+
/** true while paused by the button */
|
|
14
|
+
"paused"?: boolean;
|
|
15
|
+
};
|
|
16
|
+
type __VLS_PublicProps = __VLS_Props & __VLS_ModelProps;
|
|
17
|
+
declare var __VLS_1: {}, __VLS_3: {};
|
|
18
|
+
type __VLS_Slots = {} & {
|
|
19
|
+
default?: (props: typeof __VLS_1) => any;
|
|
20
|
+
} & {
|
|
21
|
+
default?: (props: typeof __VLS_3) => any;
|
|
22
|
+
};
|
|
23
|
+
declare const __VLS_base: import('vue').DefineComponent<__VLS_PublicProps, {}, {}, {}, {}, import('vue').ComponentOptionsMixin, import('vue').ComponentOptionsMixin, {
|
|
24
|
+
"update:paused": (value: boolean) => any;
|
|
25
|
+
}, string, import('vue').PublicProps, Readonly<__VLS_PublicProps> & Readonly<{
|
|
26
|
+
"onUpdate:paused"?: ((value: boolean) => any) | undefined;
|
|
27
|
+
}>, {
|
|
28
|
+
label: string;
|
|
29
|
+
controls: boolean;
|
|
30
|
+
speed: number;
|
|
31
|
+
pauseOnHover: boolean;
|
|
32
|
+
}, {}, {}, {}, string, import('vue').ComponentProvideOptions, false, {}, any>;
|
|
33
|
+
declare const __VLS_export: __VLS_WithSlots<typeof __VLS_base, __VLS_Slots>;
|
|
34
|
+
declare const _default: typeof __VLS_export;
|
|
35
|
+
export default _default;
|
|
36
|
+
type __VLS_WithSlots<T, S> = T & {
|
|
37
|
+
new (): {
|
|
38
|
+
$slots: S;
|
|
39
|
+
};
|
|
40
|
+
};
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
import { reducedMotion as e } from "../composables/useMedia.js";
|
|
2
|
+
import { createCommentVNode as t, createElementBlock as n, createElementVNode as r, defineComponent as i, mergeModels as a, normalizeClass as o, normalizeStyle as s, onBeforeUnmount as c, onMounted as l, openBlock as u, ref as d, renderSlot as f, toDisplayString as p, useModel as m } from "vue";
|
|
3
|
+
//#region src/components/BlessMarquee.vue?vue&type=script&setup=true&lang.ts
|
|
4
|
+
var h = ["aria-label"], g = { class: "bless-marquee__viewport" }, _ = { class: "bless-marquee__track" }, v = {
|
|
5
|
+
class: "bless-marquee__run",
|
|
6
|
+
"aria-hidden": "true",
|
|
7
|
+
inert: ""
|
|
8
|
+
}, y = ["aria-pressed"], b = /*@__PURE__*/ i({
|
|
9
|
+
name: "BlessMarquee",
|
|
10
|
+
__name: "BlessMarquee",
|
|
11
|
+
props: /*@__PURE__*/ a({
|
|
12
|
+
speed: { default: 40 },
|
|
13
|
+
reverse: { type: Boolean },
|
|
14
|
+
pauseOnHover: {
|
|
15
|
+
type: Boolean,
|
|
16
|
+
default: !0
|
|
17
|
+
},
|
|
18
|
+
controls: {
|
|
19
|
+
type: Boolean,
|
|
20
|
+
default: !0
|
|
21
|
+
},
|
|
22
|
+
label: { default: "Scrolling items" }
|
|
23
|
+
}, {
|
|
24
|
+
paused: {
|
|
25
|
+
type: Boolean,
|
|
26
|
+
default: !1
|
|
27
|
+
},
|
|
28
|
+
pausedModifiers: {}
|
|
29
|
+
}),
|
|
30
|
+
emits: ["update:paused"],
|
|
31
|
+
setup(i) {
|
|
32
|
+
let a = i, b = m(i, "paused"), x = d(), S = d(!1), C = d(20), w;
|
|
33
|
+
function T() {
|
|
34
|
+
let e = x.value?.scrollWidth ?? 0;
|
|
35
|
+
C.value = e && a.speed > 0 ? e / a.speed : 20;
|
|
36
|
+
}
|
|
37
|
+
return l(() => {
|
|
38
|
+
S.value = e(), T(), typeof ResizeObserver < "u" && x.value && (w = new ResizeObserver(T), w.observe(x.value));
|
|
39
|
+
}), c(() => w?.disconnect()), (e, a) => (u(), n("div", {
|
|
40
|
+
class: o(["bless-marquee", {
|
|
41
|
+
"bless-marquee--paused": b.value,
|
|
42
|
+
"bless-marquee--hover": i.pauseOnHover,
|
|
43
|
+
"bless-marquee--still": S.value,
|
|
44
|
+
"bless-marquee--reverse": i.reverse
|
|
45
|
+
}]),
|
|
46
|
+
role: "group",
|
|
47
|
+
"aria-roledescription": "marquee",
|
|
48
|
+
"aria-label": i.label,
|
|
49
|
+
style: s({ "--bless-marquee-time": `${C.value}s` })
|
|
50
|
+
}, [r("div", g, [r("div", _, [r("div", {
|
|
51
|
+
ref_key: "run",
|
|
52
|
+
ref: x,
|
|
53
|
+
class: "bless-marquee__run"
|
|
54
|
+
}, [f(e.$slots, "default")], 512), r("div", v, [f(e.$slots, "default")])])]), i.controls && !S.value ? (u(), n("button", {
|
|
55
|
+
key: 0,
|
|
56
|
+
type: "button",
|
|
57
|
+
class: "bless-marquee__btn",
|
|
58
|
+
"aria-pressed": b.value,
|
|
59
|
+
onClick: a[0] ||= (e) => b.value = !b.value
|
|
60
|
+
}, p(b.value ? "Play" : "Pause"), 9, y)) : t("", !0)], 14, h));
|
|
61
|
+
}
|
|
62
|
+
});
|
|
63
|
+
//#endregion
|
|
64
|
+
export { b as default };
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
.bless-masonry{gap:var(--bless-masonry-gap,16px);min-width:0;display:grid;position:relative}.bless-masonry--ready{display:block}.bless-masonry--ready>.bless-masonry__cell{position:absolute;inset-block-start:0;inset-inline-start:0}.bless-masonry--animate>.bless-masonry__cell{transition:transform var(--bless-duration-slow) var(--bless-ease-out)}[dir=rtl] .bless-masonry--ready>.bless-masonry__cell{inset-inline:auto 0}@media (prefers-reduced-motion:reduce){.bless-masonry--animate>.bless-masonry__cell{transition:none}}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
declare const __VLS_export: <T>(__VLS_props: NonNullable<Awaited<typeof __VLS_setup>>["props"], __VLS_ctx?: __VLS_PrettifyLocal<Pick<NonNullable<Awaited<typeof __VLS_setup>>, "attrs" | "emit" | "slots">>, __VLS_exposed?: NonNullable<Awaited<typeof __VLS_setup>>["expose"], __VLS_setup?: Promise<{
|
|
2
|
+
props: import('vue').PublicProps & __VLS_PrettifyLocal<{
|
|
3
|
+
items: T[];
|
|
4
|
+
rowKey?: (item: T, index: number) => string | number;
|
|
5
|
+
/** a fixed number of columns; leave out to fit as many as `minWidth` allows */
|
|
6
|
+
columns?: number;
|
|
7
|
+
/** narrowest a column may get, in px, when `columns` is not set */
|
|
8
|
+
minWidth?: number;
|
|
9
|
+
/** space between cards, in px */
|
|
10
|
+
gap?: number;
|
|
11
|
+
label?: string;
|
|
12
|
+
}> & (typeof globalThis extends {
|
|
13
|
+
__VLS_PROPS_FALLBACK: infer P;
|
|
14
|
+
} ? P : {});
|
|
15
|
+
expose: (exposed: {}) => void;
|
|
16
|
+
attrs: any;
|
|
17
|
+
slots: {
|
|
18
|
+
default?: (props: {
|
|
19
|
+
item: T;
|
|
20
|
+
index: number;
|
|
21
|
+
}) => any;
|
|
22
|
+
};
|
|
23
|
+
emit: {};
|
|
24
|
+
}>) => import('vue').VNode & {
|
|
25
|
+
__ctx?: NonNullable<Awaited<typeof __VLS_setup>>;
|
|
26
|
+
};
|
|
27
|
+
declare const _default: typeof __VLS_export;
|
|
28
|
+
export default _default;
|
|
29
|
+
type __VLS_PrettifyLocal<T> = (T extends any ? {
|
|
30
|
+
[K in keyof T]: T[K];
|
|
31
|
+
} : {
|
|
32
|
+
[K in keyof T as K]: T[K];
|
|
33
|
+
}) & {};
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
import { Fragment as e, createElementBlock as t, createTextVNode as n, defineComponent as r, nextTick as i, normalizeClass as a, normalizeStyle as o, onBeforeUnmount as s, onMounted as c, openBlock as l, ref as u, renderList as d, renderSlot as f, toDisplayString as p, watch as m } from "vue";
|
|
2
|
+
//#region src/components/BlessMasonry.vue?vue&type=script&setup=true&lang.ts
|
|
3
|
+
var h = ["aria-label"], g = /*@__PURE__*/ r({
|
|
4
|
+
name: "BlessMasonry",
|
|
5
|
+
__name: "BlessMasonry",
|
|
6
|
+
props: {
|
|
7
|
+
items: {},
|
|
8
|
+
rowKey: {},
|
|
9
|
+
columns: {},
|
|
10
|
+
minWidth: { default: 240 },
|
|
11
|
+
gap: { default: 16 },
|
|
12
|
+
label: {}
|
|
13
|
+
},
|
|
14
|
+
setup(r) {
|
|
15
|
+
let g = r, _ = u(), v = u([]), y = u(!1), b = u(0), x = u([]), S = u(0), C = u(!1), w = u(!1), T = (e, t) => {
|
|
16
|
+
e && (v.value[t] = e);
|
|
17
|
+
};
|
|
18
|
+
function E() {
|
|
19
|
+
let e = _.value;
|
|
20
|
+
if (!e) return;
|
|
21
|
+
let t = e.clientWidth, n = g.columns ?? Math.max(1, Math.floor((t + g.gap) / (g.minWidth + g.gap)));
|
|
22
|
+
b.value = (t - g.gap * (n - 1)) / n, i(D);
|
|
23
|
+
}
|
|
24
|
+
function D() {
|
|
25
|
+
let e = _.value;
|
|
26
|
+
if (!e || !b.value) return;
|
|
27
|
+
C.value = getComputedStyle(e).direction === "rtl";
|
|
28
|
+
let t = e.clientWidth, n = Math.max(1, Math.round((t + g.gap) / (b.value + g.gap))), r = Array(n).fill(0);
|
|
29
|
+
x.value = g.items.map((e, t) => {
|
|
30
|
+
let n = r.indexOf(Math.min(...r)), i = {
|
|
31
|
+
left: n * (b.value + g.gap),
|
|
32
|
+
top: r[n]
|
|
33
|
+
};
|
|
34
|
+
return r[n] = i.top + (v.value[t]?.offsetHeight ?? 0) + g.gap, i;
|
|
35
|
+
}), S.value = Math.max(0, Math.max(...r) - g.gap), y.value = !0, requestAnimationFrame(() => w.value = !0);
|
|
36
|
+
}
|
|
37
|
+
let O, k = /* @__PURE__ */ new Set();
|
|
38
|
+
function A() {
|
|
39
|
+
if (O) for (let e of v.value) e && !k.has(e) && (O.observe(e), k.add(e));
|
|
40
|
+
}
|
|
41
|
+
return c(() => {
|
|
42
|
+
typeof ResizeObserver < "u" && (O = new ResizeObserver((e) => {
|
|
43
|
+
e.some((e) => e.target === _.value) ? E() : D();
|
|
44
|
+
}), _.value && O.observe(_.value)), E(), i(A);
|
|
45
|
+
}), s(() => O?.disconnect()), m(() => [
|
|
46
|
+
g.items,
|
|
47
|
+
g.columns,
|
|
48
|
+
g.minWidth,
|
|
49
|
+
g.gap
|
|
50
|
+
], () => i(() => {
|
|
51
|
+
v.value.length = g.items.length, k = new Set([...k].filter((e) => e.isConnected)), A(), E();
|
|
52
|
+
})), (i, s) => (l(), t("div", {
|
|
53
|
+
ref_key: "root",
|
|
54
|
+
ref: _,
|
|
55
|
+
class: a(["bless-masonry", {
|
|
56
|
+
"bless-masonry--ready": y.value,
|
|
57
|
+
"bless-masonry--animate": w.value
|
|
58
|
+
}]),
|
|
59
|
+
role: "list",
|
|
60
|
+
"aria-label": r.label,
|
|
61
|
+
style: o(y.value ? { height: `${S.value}px` } : { "--bless-masonry-gap": `${r.gap}px` })
|
|
62
|
+
}, [(l(!0), t(e, null, d(r.items, (e, a) => (l(), t("div", {
|
|
63
|
+
key: r.rowKey ? r.rowKey(e, a) : a,
|
|
64
|
+
ref_for: !0,
|
|
65
|
+
ref: (e) => T(e, a),
|
|
66
|
+
class: "bless-masonry__cell",
|
|
67
|
+
role: "listitem",
|
|
68
|
+
style: o(b.value ? {
|
|
69
|
+
width: `${b.value}px`,
|
|
70
|
+
...y.value && { transform: `translate(${(C.value ? -1 : 1) * (x.value[a]?.left ?? 0)}px, ${x.value[a]?.top ?? 0}px)` }
|
|
71
|
+
} : void 0)
|
|
72
|
+
}, [f(i.$slots, "default", {
|
|
73
|
+
item: e,
|
|
74
|
+
index: a
|
|
75
|
+
}, () => [n(p(e), 1)])], 4))), 128))], 14, h));
|
|
76
|
+
}
|
|
77
|
+
});
|
|
78
|
+
//#endregion
|
|
79
|
+
export { g as default };
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
.bless-mention{position:relative}.bless-mention__panel{inset:unset;border:var(--bless-border-width) solid var(--bless-color-border);background:var(--bless-color-bg);color:var(--bless-color-text);box-shadow:var(--bless-shadow-plate);margin:0;padding:0;position:fixed}.bless-mention__list{max-height:240px;padding:var(--bless-space-1) 0;scrollbar-width:thin;overflow-y:auto}.bless-mention__option{align-items:baseline;gap:var(--bless-space-2);padding:var(--bless-space-2) var(--bless-space-3);font-family:var(--bless-font-sans);font-size:var(--bless-text-sm);cursor:pointer;display:flex}.bless-mention__option small{color:var(--bless-color-text-muted);font-size:var(--bless-text-xs)}.bless-mention__option--active{background:var(--bless-color-surface)}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
export interface BlessMentionOption {
|
|
2
|
+
/** inserted after the trigger: `@mika` */
|
|
3
|
+
value: string;
|
|
4
|
+
label: string;
|
|
5
|
+
/** muted second line, e.g. a role or an email */
|
|
6
|
+
hint?: string;
|
|
7
|
+
}
|
|
8
|
+
type __VLS_Props = {
|
|
9
|
+
/** one list for every trigger, or `{ "@": [...], "#": [...] }` to give each its own */
|
|
10
|
+
options: BlessMentionOption[] | Record<string, BlessMentionOption[]>;
|
|
11
|
+
/** characters that open the list when they start a word; ignored when `options` is a record */
|
|
12
|
+
triggers?: string[];
|
|
13
|
+
limit?: number;
|
|
14
|
+
label?: string;
|
|
15
|
+
};
|
|
16
|
+
type __VLS_ModelProps = {
|
|
17
|
+
modelValue?: string;
|
|
18
|
+
};
|
|
19
|
+
type __VLS_PublicProps = __VLS_Props & __VLS_ModelProps;
|
|
20
|
+
declare const __VLS_export: import('vue').DefineComponent<__VLS_PublicProps, {}, {}, {}, {}, import('vue').ComponentOptionsMixin, import('vue').ComponentOptionsMixin, {
|
|
21
|
+
select: (option: BlessMentionOption, trigger: string) => any;
|
|
22
|
+
"update:modelValue": (value: string) => any;
|
|
23
|
+
}, string, import('vue').PublicProps, Readonly<__VLS_PublicProps> & Readonly<{
|
|
24
|
+
onSelect?: ((option: BlessMentionOption, trigger: string) => any) | undefined;
|
|
25
|
+
"onUpdate:modelValue"?: ((value: string) => any) | undefined;
|
|
26
|
+
}>, {
|
|
27
|
+
label: string;
|
|
28
|
+
triggers: string[];
|
|
29
|
+
limit: number;
|
|
30
|
+
}, {}, {}, {}, string, import('vue').ComponentProvideOptions, false, {}, any>;
|
|
31
|
+
declare const _default: typeof __VLS_export;
|
|
32
|
+
export default _default;
|
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
import e from "./BlessTextarea.js";
|
|
2
|
+
import { useFloating as t } from "../composables/useFloating.js";
|
|
3
|
+
import { Fragment as n, computed as r, createCommentVNode as i, createElementBlock as a, createElementVNode as o, createVNode as s, defineComponent as c, mergeModels as l, mergeProps as u, nextTick as d, normalizeClass as f, normalizeStyle as p, openBlock as m, ref as h, renderList as g, toDisplayString as _, unref as v, useId as y, useModel as b, watch as x, withKeys as S, withModifiers as C } from "vue";
|
|
4
|
+
//#region src/components/BlessMention.vue?vue&type=script&setup=true&lang.ts
|
|
5
|
+
var w = ["id", "aria-label"], T = [
|
|
6
|
+
"id",
|
|
7
|
+
"aria-selected",
|
|
8
|
+
"onMousedown",
|
|
9
|
+
"onMousemove"
|
|
10
|
+
], E = { key: 0 }, D = /*@__PURE__*/ c({
|
|
11
|
+
name: "BlessMention",
|
|
12
|
+
inheritAttrs: !1,
|
|
13
|
+
__name: "BlessMention",
|
|
14
|
+
props: /*@__PURE__*/ l({
|
|
15
|
+
options: {},
|
|
16
|
+
triggers: { default: () => ["@"] },
|
|
17
|
+
limit: { default: 8 },
|
|
18
|
+
label: { default: "Suggestions" }
|
|
19
|
+
}, {
|
|
20
|
+
modelValue: { default: "" },
|
|
21
|
+
modelModifiers: {}
|
|
22
|
+
}),
|
|
23
|
+
emits: /*@__PURE__*/ l(["select"], ["update:modelValue"]),
|
|
24
|
+
setup(c, { emit: l }) {
|
|
25
|
+
let D = c, O = b(c, "modelValue"), k = l, A = y(), j = h(), M = h(), N = h(!1), P = h(0), F = h({
|
|
26
|
+
trigger: "",
|
|
27
|
+
query: "",
|
|
28
|
+
start: 0
|
|
29
|
+
}), { x: I, y: L } = t(j, M, N, {
|
|
30
|
+
placement: "bottom-start",
|
|
31
|
+
offset: 4
|
|
32
|
+
}), R = r(() => Array.isArray(D.options) ? D.triggers : Object.keys(D.options)), z = r(() => {
|
|
33
|
+
let e = Array.isArray(D.options) ? D.options : D.options[F.value.trigger] ?? [], t = F.value.query.toLowerCase();
|
|
34
|
+
return e.filter((e) => !t || e.label.toLowerCase().includes(t) || e.value.toLowerCase().includes(t)).slice(0, D.limit);
|
|
35
|
+
}), B = () => j.value?.querySelector("textarea") ?? null;
|
|
36
|
+
function V() {
|
|
37
|
+
let e = B();
|
|
38
|
+
if (!e || e.selectionStart !== e.selectionEnd) return H();
|
|
39
|
+
let t = e.selectionStart, n = e.value.slice(0, t), r = /(^|\s)(\S)([^\s]*)$/.exec(n);
|
|
40
|
+
if (!r || !R.value.includes(r[2])) return H();
|
|
41
|
+
let i = {
|
|
42
|
+
trigger: r[2],
|
|
43
|
+
query: r[3],
|
|
44
|
+
start: t - r[2].length - r[3].length
|
|
45
|
+
};
|
|
46
|
+
(i.trigger !== F.value.trigger || i.query !== F.value.query) && (P.value = 0), F.value = i, N.value = z.value.length > 0;
|
|
47
|
+
}
|
|
48
|
+
let H = () => N.value = !1;
|
|
49
|
+
function U(e) {
|
|
50
|
+
let t = B();
|
|
51
|
+
if (!t) return;
|
|
52
|
+
let { trigger: n, start: r } = F.value, i = `${n}${e.value} `, a = t.selectionStart;
|
|
53
|
+
O.value = t.value.slice(0, r) + i + t.value.slice(a), k("select", e, n), H(), d(() => {
|
|
54
|
+
t.focus(), t.setSelectionRange(r + i.length, r + i.length);
|
|
55
|
+
});
|
|
56
|
+
}
|
|
57
|
+
function W(e) {
|
|
58
|
+
if (!N.value || e.isComposing) return;
|
|
59
|
+
let t = z.value.length;
|
|
60
|
+
e.key === "ArrowDown" || e.key === "ArrowUp" ? (e.preventDefault(), P.value = (P.value + (e.key === "ArrowDown" ? 1 : t - 1)) % t) : e.key === "Enter" || e.key === "Tab" ? (e.preventDefault(), U(z.value[P.value])) : e.key === "Escape" && (e.preventDefault(), e.stopPropagation(), H());
|
|
61
|
+
}
|
|
62
|
+
let G = () => d(V);
|
|
63
|
+
return x(N, (e) => d(() => {
|
|
64
|
+
let t = M.value;
|
|
65
|
+
t && typeof t.showPopover == "function" && (e && !t.matches(":popover-open") ? t.showPopover() : !e && t.matches(":popover-open") && t.hidePopover());
|
|
66
|
+
})), (t, r) => (m(), a("div", {
|
|
67
|
+
ref_key: "root",
|
|
68
|
+
ref: j,
|
|
69
|
+
class: "bless-mention",
|
|
70
|
+
onInput: G,
|
|
71
|
+
onKeydown: W,
|
|
72
|
+
onKeyup: [S(G, ["left"]), S(G, ["right"])],
|
|
73
|
+
onClick: G,
|
|
74
|
+
onFocusout: H
|
|
75
|
+
}, [s(e, u(t.$attrs, {
|
|
76
|
+
modelValue: O.value,
|
|
77
|
+
"onUpdate:modelValue": r[0] ||= (e) => O.value = e,
|
|
78
|
+
role: "combobox",
|
|
79
|
+
"aria-autocomplete": "list",
|
|
80
|
+
"aria-haspopup": "listbox",
|
|
81
|
+
"aria-expanded": N.value,
|
|
82
|
+
"aria-controls": `${v(A)}-list`,
|
|
83
|
+
"aria-activedescendant": N.value ? `${v(A)}-opt-${P.value}` : void 0
|
|
84
|
+
}), null, 16, [
|
|
85
|
+
"modelValue",
|
|
86
|
+
"aria-expanded",
|
|
87
|
+
"aria-controls",
|
|
88
|
+
"aria-activedescendant"
|
|
89
|
+
]), o("div", {
|
|
90
|
+
ref_key: "panel",
|
|
91
|
+
ref: M,
|
|
92
|
+
popover: "manual",
|
|
93
|
+
class: "bless-mention__panel",
|
|
94
|
+
style: p({
|
|
95
|
+
left: `${v(I)}px`,
|
|
96
|
+
top: `${v(L)}px`,
|
|
97
|
+
minWidth: j.value ? `${Math.min(j.value.offsetWidth, 280)}px` : void 0
|
|
98
|
+
})
|
|
99
|
+
}, [o("div", {
|
|
100
|
+
id: `${v(A)}-list`,
|
|
101
|
+
role: "listbox",
|
|
102
|
+
"aria-label": c.label,
|
|
103
|
+
class: "bless-mention__list"
|
|
104
|
+
}, [(m(!0), a(n, null, g(N.value ? z.value : [], (e, t) => (m(), a("div", {
|
|
105
|
+
id: `${v(A)}-opt-${t}`,
|
|
106
|
+
key: e.value,
|
|
107
|
+
role: "option",
|
|
108
|
+
class: f(["bless-mention__option", { "bless-mention__option--active": t === P.value }]),
|
|
109
|
+
"aria-selected": t === P.value,
|
|
110
|
+
onMousedown: C((t) => U(e), ["prevent"]),
|
|
111
|
+
onMousemove: (e) => P.value = t
|
|
112
|
+
}, [o("span", null, _(e.label), 1), e.hint ? (m(), a("small", E, _(e.hint), 1)) : i("", !0)], 42, T))), 128))], 8, w)], 4)], 544));
|
|
113
|
+
}
|
|
114
|
+
});
|
|
115
|
+
//#endregion
|
|
116
|
+
export { D as default };
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
.bless-radial__area{-webkit-touch-callout:none}.bless-radial{inset:unset;font-family:var(--bless-font-sans);color:var(--bless-color-text);touch-action:none;-webkit-user-select:none;user-select:none;background:0 0;border:0;margin:0;padding:0;position:fixed;overflow:visible}.bless-radial::backdrop{background:0 0}.bless-radial__core{max-width:64px;padding:var(--bless-space-1);text-align:center;font-size:var(--bless-text-xs);pointer-events:none;line-height:1.2;position:absolute;inset:50% auto auto 50%;translate:-50% -50%}.bless-radial__item{border:var(--bless-border-width) solid var(--bless-color-text);background:var(--bless-color-bg);width:44px;height:44px;color:inherit;font:inherit;font-size:var(--bless-text-md);box-shadow:var(--bless-shadow-plate);cursor:pointer;place-items:center;padding:0;display:grid;position:absolute;translate:-50% -50%}.bless-radial__item--on{background:var(--bless-color-accent);border-color:var(--bless-color-accent);color:var(--bless-color-on-accent)}.bless-radial__item[aria-disabled=true]{opacity:.4;cursor:not-allowed}.bless-radial__item:focus-visible{outline:2px solid var(--bless-color-accent);outline-offset:2px}@media (prefers-reduced-motion:no-preference){.bless-radial:popover-open .bless-radial__item{animation:bless-radial-in var(--bless-duration-base) var(--bless-ease-out)}}@keyframes bless-radial-in{0%{opacity:0;scale:.6}}
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
export interface BlessRadialItem {
|
|
2
|
+
id: string | number;
|
|
3
|
+
label: string;
|
|
4
|
+
/** a character or emoji for the button; `#item` replaces it */
|
|
5
|
+
icon?: string;
|
|
6
|
+
disabled?: boolean;
|
|
7
|
+
}
|
|
8
|
+
declare const _default: typeof __VLS_export;
|
|
9
|
+
export default _default;
|
|
10
|
+
declare const __VLS_export: <T extends BlessRadialItem = BlessRadialItem>(__VLS_props: NonNullable<Awaited<typeof __VLS_setup>>["props"], __VLS_ctx?: __VLS_PrettifyLocal<Pick<NonNullable<Awaited<typeof __VLS_setup>>, "attrs" | "emit" | "slots">>, __VLS_exposed?: NonNullable<Awaited<typeof __VLS_setup>>["expose"], __VLS_setup?: Promise<{
|
|
11
|
+
props: import('vue').PublicProps & __VLS_PrettifyLocal<({
|
|
12
|
+
items: T[];
|
|
13
|
+
/** distance from the centre to the buttons, in px */
|
|
14
|
+
radius?: number;
|
|
15
|
+
/** how long a touch has to stay down to open it, in ms */
|
|
16
|
+
holdMs?: number;
|
|
17
|
+
disabled?: boolean;
|
|
18
|
+
label?: string;
|
|
19
|
+
} & {
|
|
20
|
+
open?: boolean;
|
|
21
|
+
}) & {
|
|
22
|
+
onSelect?: ((item: T) => any) | undefined;
|
|
23
|
+
"onUpdate:open"?: ((value: boolean) => any) | undefined;
|
|
24
|
+
}> & (typeof globalThis extends {
|
|
25
|
+
__VLS_PROPS_FALLBACK: infer P;
|
|
26
|
+
} ? P : {});
|
|
27
|
+
expose: (exposed: {}) => void;
|
|
28
|
+
attrs: any;
|
|
29
|
+
slots: {
|
|
30
|
+
default?: (props: {}) => any;
|
|
31
|
+
} & {
|
|
32
|
+
item?: (props: {
|
|
33
|
+
item: T;
|
|
34
|
+
index: number;
|
|
35
|
+
}) => any;
|
|
36
|
+
};
|
|
37
|
+
emit: ((evt: "select", item: T) => void) & ((event: "update:open", value: boolean) => void);
|
|
38
|
+
}>) => import('vue').VNode & {
|
|
39
|
+
__ctx?: NonNullable<Awaited<typeof __VLS_setup>>;
|
|
40
|
+
};
|
|
41
|
+
type __VLS_PrettifyLocal<T> = (T extends any ? {
|
|
42
|
+
[K in keyof T]: T[K];
|
|
43
|
+
} : {
|
|
44
|
+
[K in keyof T as K]: T[K];
|
|
45
|
+
}) & {};
|