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.
Files changed (96) hide show
  1. package/CHANGELOG.md +38 -0
  2. package/README.md +65 -43
  3. package/dist/blessing-ui.css +60 -0
  4. package/dist/components/BlessCodeBlock.css +1 -0
  5. package/dist/components/BlessCodeBlock.js +6 -0
  6. package/dist/components/BlessCodeBlock.vue.d.ts +62 -0
  7. package/dist/components/BlessCodeBlock.vue_vue_type_script_setup_true_lang.js +134 -0
  8. package/dist/components/BlessCountUp.css +1 -0
  9. package/dist/components/BlessCountUp.js +6 -0
  10. package/dist/components/BlessCountUp.vue.d.ts +18 -0
  11. package/dist/components/BlessCountUp.vue_vue_type_script_setup_true_lang.js +49 -0
  12. package/dist/components/BlessCropper.css +1 -0
  13. package/dist/components/BlessCropper.js +6 -0
  14. package/dist/components/BlessCropper.vue.d.ts +54 -0
  15. package/dist/components/BlessCropper.vue_vue_type_script_setup_true_lang.js +212 -0
  16. package/dist/components/BlessDiff.css +1 -0
  17. package/dist/components/BlessDiff.js +6 -0
  18. package/dist/components/BlessDiff.vue.d.ts +22 -0
  19. package/dist/components/BlessDiff.vue_vue_type_script_setup_true_lang.js +148 -0
  20. package/dist/components/BlessGantt.css +1 -0
  21. package/dist/components/BlessGantt.js +6 -0
  22. package/dist/components/BlessGantt.vue.d.ts +69 -0
  23. package/dist/components/BlessGantt.vue_vue_type_script_setup_true_lang.js +270 -0
  24. package/dist/components/BlessGauge.css +1 -0
  25. package/dist/components/BlessGauge.js +6 -0
  26. package/dist/components/BlessGauge.vue.d.ts +36 -0
  27. package/dist/components/BlessGauge.vue_vue_type_script_setup_true_lang.js +100 -0
  28. package/dist/components/BlessHeatmapCalendar.css +1 -0
  29. package/dist/components/BlessHeatmapCalendar.js +6 -0
  30. package/dist/components/BlessHeatmapCalendar.vue.d.ts +38 -0
  31. package/dist/components/BlessHeatmapCalendar.vue_vue_type_script_setup_true_lang.js +146 -0
  32. package/dist/components/BlessHotspots.css +1 -0
  33. package/dist/components/BlessHotspots.js +6 -0
  34. package/dist/components/BlessHotspots.vue.d.ts +49 -0
  35. package/dist/components/BlessHotspots.vue_vue_type_script_setup_true_lang.js +127 -0
  36. package/dist/components/BlessKanban.css +1 -0
  37. package/dist/components/BlessKanban.js +6 -0
  38. package/dist/components/BlessKanban.vue.d.ts +55 -0
  39. package/dist/components/BlessKanban.vue_vue_type_script_setup_true_lang.js +165 -0
  40. package/dist/components/BlessLoupe.css +1 -0
  41. package/dist/components/BlessLoupe.js +6 -0
  42. package/dist/components/BlessLoupe.vue.d.ts +16 -0
  43. package/dist/components/BlessLoupe.vue_vue_type_script_setup_true_lang.js +93 -0
  44. package/dist/components/BlessMarquee.css +1 -0
  45. package/dist/components/BlessMarquee.js +6 -0
  46. package/dist/components/BlessMarquee.vue.d.ts +40 -0
  47. package/dist/components/BlessMarquee.vue_vue_type_script_setup_true_lang.js +64 -0
  48. package/dist/components/BlessMasonry.css +1 -0
  49. package/dist/components/BlessMasonry.js +6 -0
  50. package/dist/components/BlessMasonry.vue.d.ts +33 -0
  51. package/dist/components/BlessMasonry.vue_vue_type_script_setup_true_lang.js +79 -0
  52. package/dist/components/BlessMention.css +1 -0
  53. package/dist/components/BlessMention.js +6 -0
  54. package/dist/components/BlessMention.vue.d.ts +32 -0
  55. package/dist/components/BlessMention.vue_vue_type_script_setup_true_lang.js +116 -0
  56. package/dist/components/BlessRadialMenu.css +1 -0
  57. package/dist/components/BlessRadialMenu.js +6 -0
  58. package/dist/components/BlessRadialMenu.vue.d.ts +45 -0
  59. package/dist/components/BlessRadialMenu.vue_vue_type_script_setup_true_lang.js +146 -0
  60. package/dist/components/BlessShortcutRecorder.css +1 -0
  61. package/dist/components/BlessShortcutRecorder.js +6 -0
  62. package/dist/components/BlessShortcutRecorder.vue.d.ts +29 -0
  63. package/dist/components/BlessShortcutRecorder.vue_vue_type_script_setup_true_lang.js +116 -0
  64. package/dist/components/BlessSliderCaptcha.css +1 -0
  65. package/dist/components/BlessSliderCaptcha.js +6 -0
  66. package/dist/components/BlessSliderCaptcha.vue.d.ts +33 -0
  67. package/dist/components/BlessSliderCaptcha.vue_vue_type_script_setup_true_lang.js +141 -0
  68. package/dist/components/BlessSortable.css +1 -0
  69. package/dist/components/BlessSortable.js +6 -0
  70. package/dist/components/BlessSortable.vue.d.ts +33 -0
  71. package/dist/components/BlessSortable.vue_vue_type_script_setup_true_lang.js +87 -0
  72. package/dist/components/BlessSplitView.css +1 -0
  73. package/dist/components/BlessSplitView.js +6 -0
  74. package/dist/components/BlessSplitView.vue.d.ts +61 -0
  75. package/dist/components/BlessSplitView.vue_vue_type_script_setup_true_lang.js +92 -0
  76. package/dist/components/BlessSwipeDeck.css +1 -0
  77. package/dist/components/BlessSwipeDeck.js +6 -0
  78. package/dist/components/BlessSwipeDeck.vue.d.ts +46 -0
  79. package/dist/components/BlessSwipeDeck.vue_vue_type_script_setup_true_lang.js +199 -0
  80. package/dist/components/BlessTimer.css +1 -0
  81. package/dist/components/BlessTimer.js +6 -0
  82. package/dist/components/BlessTimer.vue.d.ts +56 -0
  83. package/dist/components/BlessTimer.vue_vue_type_script_setup_true_lang.js +130 -0
  84. package/dist/composables/cropBox.d.ts +22 -0
  85. package/dist/composables/cropBox.js +39 -0
  86. package/dist/composables/diffLines.d.ts +10 -0
  87. package/dist/composables/diffLines.js +55 -0
  88. package/dist/composables/radial.d.ts +15 -0
  89. package/dist/composables/radial.js +22 -0
  90. package/dist/composables/shortcut.d.ts +12 -0
  91. package/dist/composables/shortcut.js +35 -0
  92. package/dist/composables/useSortable.d.ts +18 -0
  93. package/dist/composables/useSortable.js +34 -0
  94. package/dist/index.d.ts +37 -0
  95. package/dist/index.js +78 -53
  96. 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,6 @@
1
+ import "./BlessMarquee.css";
2
+ import e from "./BlessMarquee.vue_vue_type_script_setup_true_lang.js";
3
+ //#region src/components/BlessMarquee.vue
4
+ var t = e;
5
+ //#endregion
6
+ export { t as default };
@@ -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,6 @@
1
+ import "./BlessMasonry.css";
2
+ import e from "./BlessMasonry.vue_vue_type_script_setup_true_lang.js";
3
+ //#region src/components/BlessMasonry.vue
4
+ var t = e;
5
+ //#endregion
6
+ export { t as default };
@@ -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,6 @@
1
+ import "./BlessMention.css";
2
+ import e from "./BlessMention.vue_vue_type_script_setup_true_lang.js";
3
+ //#region src/components/BlessMention.vue
4
+ var t = e;
5
+ //#endregion
6
+ export { t as default };
@@ -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,6 @@
1
+ import "./BlessRadialMenu.css";
2
+ import e from "./BlessRadialMenu.vue_vue_type_script_setup_true_lang.js";
3
+ //#region src/components/BlessRadialMenu.vue
4
+ var t = e;
5
+ //#endregion
6
+ export { t as default };
@@ -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
+ }) & {};