Skip to content

Commit aec635a

Browse files
committed
refactor!: update integration usage to pass target as first param
1 parent 938351b commit aec635a

15 files changed

Lines changed: 110 additions & 108 deletions

File tree

README.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -79,7 +79,7 @@ import { useRef } from 'react';
7979
export function App() {
8080
const targetEl = useRef<HTMLElement>(null);
8181

82-
useAdhesive({ target: targetEl, position: 'top' });
82+
useAdhesive(targetEl, { position: 'top' });
8383

8484
return (
8585
<div>
@@ -124,7 +124,7 @@ import { useTemplateRef } from 'vue';
124124
125125
const targetEl = useTemplateRef('target');
126126
127-
useAdhesive({ target: targetEl }, { position: 'top' });
127+
useAdhesive(targetEl, { position: 'top' });
128128
</script>
129129
130130
<template>

packages/react/README.md

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -72,8 +72,9 @@ export function App() {
7272
const [position, setPosition] = useState<AdhesivePosition>('top');
7373

7474
useAdhesive(
75-
{ target: targetEl, bounding: boundingEl },
75+
targetEl,
7676
{
77+
boundingEl,
7778
position,
7879
offset: 20,
7980
enabled,
@@ -133,13 +134,14 @@ For more control over the sticky behavior.
133134

134135
**Parameters:**
135136

136-
- `elements`: Object with `target` (required) and `bounding` (optional) refs
137+
- `target`: React ref object for the element that should become sticky
137138
- `options`: Configuration options (optional)
138139

139140
**UseAdhesiveOptions:**
140141

141142
| Option | Type | Default | Description |
142143
|--------|------|---------|-------------|
144+
| `boundingEl` | `React.RefObject` \| `string` | `undefined` | The element that defines the sticky boundaries |
143145
| `position` | `'top' \| 'bottom'` | `'top'` | Where the element should stick |
144146
| `offset` | `number` | `0` | Offset in pixels from the position |
145147
| `zIndex` | `number` | `1` | Z-index for the fixed element |

packages/react/src/components/AdhesiveContainer.tsx

Lines changed: 4 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,5 @@
11
import { useMemo, useRef, type ComponentProps } from "react";
2-
import {
3-
useAdhesive,
4-
type UseAdhesiveElements,
5-
type UseAdhesiveOptions,
6-
} from "../hooks/useAdhesive.js";
2+
import { useAdhesive, type UseAdhesiveOptions } from "../hooks/useAdhesive.js";
73

84
export type AdhesiveContainerProps = Partial<UseAdhesiveOptions> &
95
ComponentProps<"div">;
@@ -32,12 +28,7 @@ export function AdhesiveContainer({
3228
children,
3329
...rest
3430
}: AdhesiveContainerProps) {
35-
const targetEl = useRef<HTMLDivElement>(null);
36-
37-
const elements = useMemo<UseAdhesiveElements>(
38-
() => ({ target: targetEl }),
39-
[],
40-
);
31+
const targetRef = useRef<HTMLDivElement>(null);
4132

4233
const options = useMemo<UseAdhesiveOptions>(
4334
() => ({
@@ -64,10 +55,10 @@ export function AdhesiveContainer({
6455
],
6556
);
6657

67-
useAdhesive(elements, options);
58+
useAdhesive(targetRef, options);
6859

6960
return (
70-
<div ref={targetEl} {...rest}>
61+
<div ref={targetRef} {...rest}>
7162
{children}
7263
</div>
7364
);

packages/react/src/hooks/useAdhesive.ts

Lines changed: 18 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,15 @@
11
import { Adhesive, type AdhesiveOptions } from "@adhesivejs/core";
2-
import { useEffect, useRef, type RefObject } from "react";
2+
import { useEffect, useRef } from "react";
3+
import {
4+
unrefElement,
5+
type MaybeElementOrSelectorRef,
6+
} from "../utils/unrefElement.js";
37

4-
/**
5-
* Template ref objects for React elements used by the Adhesive hook.
6-
*/
7-
export interface UseAdhesiveElements {
8-
/** React ref to the element that should become sticky */
9-
target: RefObject<HTMLDivElement | null | undefined>;
10-
/** Optional React ref to the element that defines sticky boundaries */
11-
bounding?: RefObject<HTMLDivElement | null | undefined> | null;
12-
}
13-
14-
/**
15-
* Configuration options for the `useAdhesive` hook.
16-
* Excludes `targetEl` and `boundingEl` since they're provided via template refs.
17-
*/
18-
export type UseAdhesiveOptions = Partial<Omit<AdhesiveOptions, "targetEl">>;
8+
export type UseAdhesiveOptions = Partial<
9+
Omit<AdhesiveOptions, "targetEl" | "boundingEl">
10+
> & {
11+
boundingEl?: AdhesiveOptions["boundingEl"] | MaybeElementOrSelectorRef;
12+
};
1913

2014
/**
2115
* React hook for adding sticky positioning behavior to DOM elements.
@@ -24,8 +18,8 @@ export type UseAdhesiveOptions = Partial<Omit<AdhesiveOptions, "targetEl">>;
2418
* handling initialization, updates, and cleanup. It integrates seamlessly
2519
* with React's ref system and component lifecycle.
2620
*
27-
* @param elements - Object containing React refs for target and optional bounding elements
28-
* @param options - Configuration options for sticky behavior (excluding element references)
21+
* @param target - React ref for the element that should become sticky
22+
* @param options - Configuration options for sticky behavior
2923
*
3024
* @example
3125
* ```tsx
@@ -37,8 +31,8 @@ export type UseAdhesiveOptions = Partial<Omit<AdhesiveOptions, "targetEl">>;
3731
* const boundingEl = useRef<HTMLDivElement>(null);
3832
*
3933
* useAdhesive(
40-
* { target: targetEl, bounding: boundingEl },
41-
* { position: 'top' }
34+
* targetEl,
35+
* { boundingEl, position: 'top' }
4236
* );
4337
*
4438
* return (
@@ -50,12 +44,12 @@ export type UseAdhesiveOptions = Partial<Omit<AdhesiveOptions, "targetEl">>;
5044
* ```
5145
*/
5246
export function useAdhesive(
53-
elements: UseAdhesiveElements,
47+
target: MaybeElementOrSelectorRef,
5448
options?: UseAdhesiveOptions,
5549
) {
5650
function getValidatedOptions() {
57-
const targetEl = elements.target.current;
58-
const boundingEl = elements.bounding?.current ?? options?.boundingEl;
51+
const targetEl = unrefElement(target);
52+
const boundingEl = unrefElement(options?.boundingEl);
5953

6054
if (!targetEl) {
6155
throw new Error("@adhesivejs/react: sticky element is not defined");
@@ -73,7 +67,7 @@ export function useAdhesive(
7367
adhesive.current?.cleanup();
7468
adhesive.current = null;
7569
};
76-
}, [elements.target]);
70+
}, [target]);
7771

7872
useEffect(() => {
7973
if (!adhesive.current) return;

packages/react/src/index.ts

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -8,11 +8,7 @@ export {
88
type AdhesiveStatus,
99
} from "@adhesivejs/core";
1010

11-
export {
12-
useAdhesive,
13-
type UseAdhesiveElements,
14-
type UseAdhesiveOptions,
15-
} from "./hooks/useAdhesive.js";
11+
export { useAdhesive, type UseAdhesiveOptions } from "./hooks/useAdhesive.js";
1612

1713
export {
1814
AdhesiveContainer,
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
import type { RefObject } from "react";
2+
3+
type MaybeElementRefObject = RefObject<HTMLElement | HTMLDivElement | null>;
4+
5+
export type MaybeElementOrSelectorRef =
6+
| MaybeElementRefObject
7+
| HTMLElement
8+
| string
9+
| null
10+
| undefined;
11+
12+
type UnRefElementReturn = HTMLElement | string | null | undefined;
13+
14+
export function unrefElement(
15+
elOrSelectorRef: MaybeElementOrSelectorRef,
16+
): UnRefElementReturn {
17+
// Handle React ref objects by accessing their .current property
18+
// For non-ref values, return them as-is
19+
if (
20+
elOrSelectorRef &&
21+
typeof elOrSelectorRef === "object" &&
22+
"current" in elOrSelectorRef
23+
) {
24+
return elOrSelectorRef.current;
25+
}
26+
return elOrSelectorRef as UnRefElementReturn;
27+
}

packages/vue/README.md

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -77,8 +77,9 @@ const enabled = ref(true);
7777
const position = ref<AdhesivePosition>('top');
7878
7979
useAdhesive(
80-
{ target: targetEl, bounding: boundingEl },
80+
targetEl,
8181
() => ({
82+
boundingEl: boundingEl.value,
8283
position: position.value,
8384
offset: 20,
8485
enabled: enabled.value,
@@ -128,7 +129,7 @@ A simple wrapper component that automatically applies sticky positioning to its
128129
<AdhesiveContainer
129130
position="bottom"
130131
:offset="30"
131-
className="custom-class"
132+
class="custom-class"
132133
>
133134
Content to make sticky
134135
</AdhesiveContainer>
@@ -140,13 +141,14 @@ For more control over the sticky behavior with full Vue reactivity support.
140141

141142
**Parameters:**
142143

143-
- `elements`: Object with `target` (required) and `bounding` (optional) template refs
144+
- `target`: Vue template ref for the element that should become sticky
144145
- `options`: Reactive configuration options (optional, can be a ref or getter function)
145146

146147
**UseAdhesiveOptions:**
147148

148149
| Option | Type | Default | Description |
149150
|--------|------|---------|-------------|
151+
| `boundingEl` | `TemplateRef` \| `string` | `undefined` | The element that defines the sticky boundaries |
150152
| `position` | `'top' \| 'bottom'` | `'top'` | Where the element should stick |
151153
| `offset` | `number` | `0` | Offset in pixels from the position |
152154
| `zIndex` | `number` | `1` | Z-index for the fixed element |

packages/vue/src/components/AdhesiveContainer.vue

Lines changed: 2 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@
22
import { computed, useTemplateRef } from "vue";
33
import {
44
useAdhesive,
5-
type UseAdhesiveElements,
65
type UseAdhesiveOptions,
76
} from "../composables/useAdhesive";
87
@@ -47,11 +46,7 @@ const {
4746
releasedClass,
4847
} = defineProps<AdhesiveContainerProps>();
4948
50-
const targetEl = useTemplateRef("target");
51-
52-
const elements = {
53-
target: targetEl,
54-
} satisfies UseAdhesiveElements;
49+
const targetRef = useTemplateRef("target");
5550
5651
const options = computed<UseAdhesiveOptions>(() => ({
5752
boundingEl,
@@ -65,7 +60,7 @@ const options = computed<UseAdhesiveOptions>(() => ({
6560
releasedClassName: releasedClass,
6661
}));
6762
68-
useAdhesive(elements, options);
63+
useAdhesive(targetRef, options);
6964
</script>
7065

7166
<template>

packages/vue/src/composables/useAdhesive.ts

Lines changed: 15 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -8,24 +8,14 @@ import {
88
} from "vue";
99
import {
1010
unrefElement,
11-
type MaybeComputedElementRef,
11+
type MaybeElementOrSelectorRef,
1212
} from "../utils/unrefElement.js";
1313

14-
/**
15-
* Template ref objects for Vue elements used by the Adhesive composable.
16-
*/
17-
export interface UseAdhesiveElements {
18-
/** Vue template ref or element that should become sticky */
19-
target: MaybeComputedElementRef;
20-
/** Optional Vue template ref or element that defines sticky boundaries */
21-
bounding?: MaybeComputedElementRef;
22-
}
23-
24-
/**
25-
* Configuration options for the `useAdhesive` composable.
26-
* Excludes `targetEl` and `boundingEl` since they're provided via template refs.
27-
*/
28-
export type UseAdhesiveOptions = Partial<Omit<AdhesiveOptions, "targetEl">>;
14+
export type UseAdhesiveOptions = Partial<
15+
Omit<AdhesiveOptions, "targetEl" | "boundingEl">
16+
> & {
17+
boundingEl?: AdhesiveOptions["boundingEl"] | MaybeElementOrSelectorRef;
18+
};
2919

3020
/**
3121
* Vue composable for adding sticky positioning behavior to DOM elements.
@@ -34,8 +24,8 @@ export type UseAdhesiveOptions = Partial<Omit<AdhesiveOptions, "targetEl">>;
3424
* handling initialization, updates, and cleanup. It integrates seamlessly
3525
* with Vue's reactivity system and component lifecycle.
3626
*
37-
* @param elements - Object containing Vue refs for target and optional bounding elements
38-
* @param options - Reactive configuration options for sticky behavior (excluding element references)
27+
* @param target - Vue template ref for the element that should become sticky
28+
* @param options - Reactive configuration options for sticky behavior
3929
*
4030
* @example
4131
* ```vue
@@ -47,8 +37,8 @@ export type UseAdhesiveOptions = Partial<Omit<AdhesiveOptions, "targetEl">>;
4737
* const boundingEl = useTemplateRef('bounding');
4838
*
4939
* useAdhesive(
50-
* { target: targetEl, bounding: boundingEl },
51-
* { position: 'top' }
40+
* targetEl,
41+
* () => ({ boundingEl: boundingEl.value, position: 'top' })
5242
* );
5343
* </script>
5444
*
@@ -70,24 +60,23 @@ export type UseAdhesiveOptions = Partial<Omit<AdhesiveOptions, "targetEl">>;
7060
* const offset = ref(10);
7161
*
7262
* // Reactive options
73-
* useAdhesive({ target: targetEl }, () => ({
74-
* position: 'top'
63+
* useAdhesive(targetEl, () => ({
64+
* position: 'top',
7565
* enabled: enabled.value,
7666
* offset: offset.value,
7767
* }));
7868
* </script>
7969
* ```
8070
*/
8171
export function useAdhesive(
82-
elements: UseAdhesiveElements,
72+
target: MaybeElementOrSelectorRef,
8373
options?: MaybeRefOrGetter<UseAdhesiveOptions>,
8474
) {
8575
function getValidatedOptions() {
8676
const optionsValue = toValue(options);
8777

88-
const targetEl = unrefElement(elements.target);
89-
const boundingEl =
90-
unrefElement(elements.bounding) ?? optionsValue?.boundingEl;
78+
const targetEl = unrefElement(target);
79+
const boundingEl = unrefElement(optionsValue?.boundingEl);
9180

9281
if (!targetEl) {
9382
throw new Error("@adhesivejs/vue: sticky element is not defined");

packages/vue/src/index.ts

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,6 @@ export {
1010

1111
export {
1212
useAdhesive,
13-
type UseAdhesiveElements,
1413
type UseAdhesiveOptions,
1514
} from "./composables/useAdhesive.js";
1615

0 commit comments

Comments
 (0)