@sit-onyx/headless 1.0.0-beta.3 → 1.0.0-beta.4
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/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { computed, ref, unref, watchEffect, type MaybeRef, type Ref } from "vue";
|
|
2
2
|
import { createId } from "../..";
|
|
3
|
-
import { createBuilder, type
|
|
3
|
+
import { createBuilder, type VBindAttributes } from "../../utils/builder";
|
|
4
4
|
import { useTypeAhead } from "../helpers/useTypeAhead";
|
|
5
5
|
|
|
6
6
|
export type ListboxValue = string | number | boolean;
|
|
@@ -152,7 +152,7 @@ export const createListbox = createBuilder(
|
|
|
152
152
|
}
|
|
153
153
|
};
|
|
154
154
|
|
|
155
|
-
const listbox = computed<
|
|
155
|
+
const listbox = computed<VBindAttributes>(() =>
|
|
156
156
|
options.controlled
|
|
157
157
|
? {
|
|
158
158
|
role: "listbox",
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { computed,
|
|
2
|
-
import { createBuilder } from "../../utils/builder";
|
|
1
|
+
import { computed, type Ref } from "vue";
|
|
2
|
+
import { createBuilder, createElRef } from "../../utils/builder";
|
|
3
3
|
import { createId } from "../../utils/id";
|
|
4
4
|
import { debounce } from "../../utils/timer";
|
|
5
5
|
import { useGlobalEventListener } from "../helpers/useGlobalListener";
|
|
@@ -16,7 +16,7 @@ export const createMenuButton = createBuilder(
|
|
|
16
16
|
({ isExpanded, onToggle }: CreateMenuButtonOptions) => {
|
|
17
17
|
const rootId = createId("menu-button-root");
|
|
18
18
|
const menuId = createId("menu-button-list");
|
|
19
|
-
const menuRef =
|
|
19
|
+
const menuRef = createElRef<HTMLElement>();
|
|
20
20
|
const buttonId = createId("menu-button-button");
|
|
21
21
|
|
|
22
22
|
useGlobalEventListener({
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { computed, onBeforeMount, onBeforeUnmount, ref, unref, type MaybeRef } from "vue";
|
|
2
2
|
import { createId } from "../..";
|
|
3
|
-
import { createBuilder } from "../../utils/builder";
|
|
3
|
+
import { createBuilder, createElRef } from "../../utils/builder";
|
|
4
4
|
import { useOutsideClick } from "../helpers/useOutsideClick";
|
|
5
5
|
|
|
6
6
|
export type CreateTooltipOptions = {
|
|
@@ -22,7 +22,7 @@ export const TOOLTIP_TRIGGERS = ["hover", "click"] as const;
|
|
|
22
22
|
export type TooltipTrigger = (typeof TOOLTIP_TRIGGERS)[number];
|
|
23
23
|
|
|
24
24
|
export const createTooltip = createBuilder((options: CreateTooltipOptions) => {
|
|
25
|
-
const rootRef =
|
|
25
|
+
const rootRef = createElRef<HTMLElement>();
|
|
26
26
|
const tooltipId = createId("tooltip");
|
|
27
27
|
const _isVisible = ref(false);
|
|
28
28
|
let timeout: ReturnType<typeof setTimeout> | undefined;
|
package/src/index.ts
CHANGED
|
@@ -3,6 +3,7 @@ export * from "./composables/listbox/createListbox";
|
|
|
3
3
|
export * from "./composables/menuButton/createMenuButton";
|
|
4
4
|
export * from "./composables/navigationMenu/createMenu";
|
|
5
5
|
export * from "./composables/tooltip/createTooltip";
|
|
6
|
+
export * from "./utils/builder";
|
|
6
7
|
export { createId } from "./utils/id";
|
|
7
8
|
export { isPrintableCharacter, wasKeyPressed } from "./utils/keyboard";
|
|
8
9
|
export { debounce } from "./utils/timer";
|
package/src/utils/builder.ts
CHANGED
|
@@ -1,19 +1,37 @@
|
|
|
1
|
-
import
|
|
1
|
+
import {
|
|
2
|
+
computed,
|
|
3
|
+
shallowRef,
|
|
4
|
+
type ComponentPublicInstance,
|
|
5
|
+
type HTMLAttributes,
|
|
6
|
+
type MaybeRef,
|
|
7
|
+
type Ref,
|
|
8
|
+
type WritableComputedOptions,
|
|
9
|
+
type WritableComputedRef,
|
|
10
|
+
} from "vue";
|
|
2
11
|
import type { IfDefined } from "./types";
|
|
3
12
|
|
|
4
|
-
|
|
13
|
+
/**
|
|
14
|
+
* `v-bind`able attributes as they are provided by the headless composables.
|
|
15
|
+
* `ref` is restricted to be a `HeadlessElRef` which only can by created through `createElRef`.
|
|
16
|
+
*/
|
|
17
|
+
export type VBindAttributes<
|
|
18
|
+
A extends HTMLAttributes = HTMLAttributes,
|
|
19
|
+
E extends Element = Element,
|
|
20
|
+
> = A & {
|
|
21
|
+
ref?: VueTemplateRef<E>;
|
|
22
|
+
};
|
|
5
23
|
|
|
6
|
-
export type IteratedHeadlessElementFunc<
|
|
7
|
-
|
|
8
|
-
|
|
24
|
+
export type IteratedHeadlessElementFunc<
|
|
25
|
+
A extends HTMLAttributes,
|
|
26
|
+
T extends Record<string, unknown>,
|
|
27
|
+
> = (opts: T) => VBindAttributes<A>;
|
|
9
28
|
|
|
10
|
-
|
|
11
|
-
|
|
29
|
+
export type HeadlessElementAttributes<A extends HTMLAttributes> =
|
|
30
|
+
| VBindAttributes<A>
|
|
31
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
32
|
+
| IteratedHeadlessElementFunc<A, any>;
|
|
12
33
|
|
|
13
|
-
export type HeadlessElements = Record<
|
|
14
|
-
string,
|
|
15
|
-
HeadlessElementAttributes | ComputedRef<HeadlessElementAttributes>
|
|
16
|
-
>;
|
|
34
|
+
export type HeadlessElements = Record<string, MaybeRef<HeadlessElementAttributes<HTMLAttributes>>>;
|
|
17
35
|
|
|
18
36
|
export type HeadlessState = Record<string, Ref>;
|
|
19
37
|
|
|
@@ -28,6 +46,39 @@ export type HeadlessComposable<
|
|
|
28
46
|
|
|
29
47
|
/**
|
|
30
48
|
* We use this identity function to ensure the correct typings of the headless composables
|
|
49
|
+
* @example
|
|
50
|
+
* ```ts
|
|
51
|
+
* export const createTooltip = createBuilder(({ initialVisible }: CreateTooltipOptions) => {
|
|
52
|
+
* const tooltipId = createId("tooltip");
|
|
53
|
+
* const isVisible = ref(initialVisible);
|
|
54
|
+
*
|
|
55
|
+
* const hoverEvents = {
|
|
56
|
+
* onMouseover: () => (isVisible.value = true),
|
|
57
|
+
* onMouseout: () => (isVisible.value = false),
|
|
58
|
+
* onFocusin: () => (isVisible.value = true),
|
|
59
|
+
* onFocusout: () => (isVisible.value = false),
|
|
60
|
+
* };
|
|
61
|
+
*
|
|
62
|
+
* return {
|
|
63
|
+
* elements: {
|
|
64
|
+
* trigger: {
|
|
65
|
+
* "aria-describedby": tooltipId,
|
|
66
|
+
* ...hoverEvents,
|
|
67
|
+
* },
|
|
68
|
+
* tooltip: {
|
|
69
|
+
* role: "tooltip",
|
|
70
|
+
* id: tooltipId,
|
|
71
|
+
* tabindex: "-1",
|
|
72
|
+
* ...hoverEvents,
|
|
73
|
+
* },
|
|
74
|
+
* },
|
|
75
|
+
* state: {
|
|
76
|
+
* isVisible,
|
|
77
|
+
* },
|
|
78
|
+
* };
|
|
79
|
+
* });
|
|
80
|
+
*
|
|
81
|
+
* ```
|
|
31
82
|
*/
|
|
32
83
|
export const createBuilder = <
|
|
33
84
|
Args extends unknown[] = unknown[],
|
|
@@ -37,3 +88,47 @@ export const createBuilder = <
|
|
|
37
88
|
>(
|
|
38
89
|
builder: (...args: Args) => HeadlessComposable<Elements, State, Internals>,
|
|
39
90
|
) => builder;
|
|
91
|
+
|
|
92
|
+
type VueTemplateRefElement<E extends Element> = E | (ComponentPublicInstance & { $el: E }) | null;
|
|
93
|
+
type VueTemplateRef<E extends Element> = Ref<VueTemplateRefElement<E>>;
|
|
94
|
+
|
|
95
|
+
declare const HeadlessElRefSymbol: unique symbol;
|
|
96
|
+
type HeadlessElRef<E extends Element> = WritableComputedRef<E> & {
|
|
97
|
+
/**
|
|
98
|
+
* type differentiator
|
|
99
|
+
* ensures that only `createElRef` can be used for headless element ref bindings
|
|
100
|
+
*/
|
|
101
|
+
[HeadlessElRefSymbol]: true;
|
|
102
|
+
};
|
|
103
|
+
|
|
104
|
+
/**
|
|
105
|
+
* Creates a special writeable computed that references a DOM Element.
|
|
106
|
+
* Vue Component references will be unwrapped.
|
|
107
|
+
* @example
|
|
108
|
+
* ```ts
|
|
109
|
+
* createBuilder() => {
|
|
110
|
+
* const buttonRef = createElRef<HtmlButtonElement>();
|
|
111
|
+
* return {
|
|
112
|
+
* elements: {
|
|
113
|
+
* button: {
|
|
114
|
+
* ref: buttonRef,
|
|
115
|
+
* },
|
|
116
|
+
* }
|
|
117
|
+
* };
|
|
118
|
+
* });
|
|
119
|
+
* ```
|
|
120
|
+
*/
|
|
121
|
+
export function createElRef<E extends Element>(): HeadlessElRef<E>;
|
|
122
|
+
export function createElRef<
|
|
123
|
+
E extends Element,
|
|
124
|
+
V extends VueTemplateRefElement<E> = VueTemplateRefElement<E>,
|
|
125
|
+
>() {
|
|
126
|
+
const elementRef = shallowRef<E>();
|
|
127
|
+
|
|
128
|
+
return computed({
|
|
129
|
+
set: (element: V) => {
|
|
130
|
+
elementRef.value = element != null && "$el" in element ? element.$el : (element as E);
|
|
131
|
+
},
|
|
132
|
+
get: () => elementRef.value,
|
|
133
|
+
} as WritableComputedOptions<E>);
|
|
134
|
+
}
|