Skip to content

Commit

Permalink
provide signal to observe bounding box
Browse files Browse the repository at this point in the history
  • Loading branch information
danielwiehl committed Oct 21, 2024
1 parent 400de01 commit 8b41f4b
Show file tree
Hide file tree
Showing 11 changed files with 930 additions and 194 deletions.
2 changes: 1 addition & 1 deletion docs/site/scion-components.md
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ Provides Angular-based components and directives with a focus on SCION requireme
You can choose between different presentations: `ellipsis`, `ripple`, `roller`, `spinner`.

- [**Dimension**][link-tool-dimension]\
Provides a set of tools for observing the size of an element.
Provides a set of tools for observing the size and position of an element.

- [**SCION Design Tokens**][link-scion-design-tokens]\
SCION provides a set of design tokens to enable consistent design and theming of SCION components.
Expand Down
87 changes: 78 additions & 9 deletions docs/site/tools/dimension.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@

## [SCION Toolkit][menu-home] > [@scion/components][link-scion-components] > Dimension

The NPM sub-module `@scion/components/dimension` provides a set of tools for observing the size of an element.
The NPM sub-module `@scion/components/dimension` provides a set of tools for observing the size and position of an element.

Install the NPM module `@scion/components` as following:

Expand Down Expand Up @@ -50,7 +50,7 @@ The directive can be configured with `emitOutsideAngular` to control whether to
</details>

<details>
<summary><strong>Dimension Signal</strong></summary>
<summary><strong><a id="dimension"></a>Dimension Signal</strong></summary>

Signal to observe the size of an element.

Expand All @@ -63,13 +63,15 @@ import {dimension} from '@scion/components/dimension';
const element: HTMLElement = ...;
const size = dimension(element);

console.log('size', size());
console.log(size());
```

> The function must be called within an injection context or with an injector provided for automatic unsubscription.\
> The function must NOT be called within a reactive context to avoid repeated subscriptions.
***
> - The function must be called within an injection context or an injector provided. Destroying the injector will unsubscribe the signal.
> - The function must NOT be called within a reactive context to avoid repeated subscriptions.
***

**Example of observing the size of a component:**
**Example of observing the size of the component:**

```ts
import {Component, effect, ElementRef, inject} from '@angular/core';
Expand All @@ -82,14 +84,14 @@ class YourComponent {
private dimension = dimension(this.host);

constructor() {
effect(() => console.log('size', this.dimension()));
effect(() => console.log(this.dimension()));
}
}
```

**Example of observing the size of a view child:**

The element can be passed as a signal, useful for observing a view child as view children cannot be read in the constructor.
The element can be passed as a signal, enabling observation of view children in the component constructor.

```ts
import {Component, effect, ElementRef, viewChild} from '@angular/core';
Expand All @@ -101,13 +103,80 @@ class YourComponent {
private dimension = dimension(this.viewChild);

constructor() {
effect(() => console.log('size', this.dimension()));
effect(() => console.log(this.dimension()));
}
}
```

</details>

<details>
<summary><strong>BoundingClientRect Signal</strong></summary>

Signal to observe the bounding box of an element.

The [bounding box](https://developer.mozilla.org/en-US/docs/Web/API/Element/getBoundingClientRect) includes the element's position relative to the top-left of the viewport and its size.


```ts
import {boundingClientRect} from '@scion/components/dimension';

const element: HTMLElement = ...;
const boundingBox = boundingClientRect(element);

console.log(boundingBox());
```

***
> - The function must be called within an injection context or an injector provided. Destroying the injector will unsubscribe the signal.
> - The function must not be called within a reactive context to avoid repeated subscriptions.
> - The element and the document root (`<html>`) must be positioned `relative` or `absolute`. If not, a warning is logged, and positioning changed to `relative`.
***

*Note:*
There is no native browser API to observe the position of an element. The observable uses [`IntersectionObserver`](https://developer.mozilla.org/en-US/docs/Web/API/Intersection_Observer_API) and [`ResizeObserver`](https://developer.mozilla.org/en-US/docs/Web/API/ResizeObserver) to detect position changes. For tracking only size changes, use [`Dimension Signal`](#dimension) signal instead.


**Example of observing the bounding box of the component:**

```ts
import {Component, effect, ElementRef, inject} from '@angular/core';
import {boundingClientRect} from '@scion/components/dimension';

@Component({...})
class YourComponent {

private host = inject(ElementRef<HTMLElement>);
private boundingBox = boundingClientRect(this.host);

constructor() {
effect(() => console.log(this.boundingBox()));
}
}
```

**Example of observing the bounding box of a view child:**

The element can be passed as a signal, enabling observation of view children in the component constructor.

```ts
import {Component, effect, ElementRef, viewChild} from '@angular/core';
import {boundingClientRect} from '@scion/components/dimension';

@Component({...})
class YourComponent {
private viewChild = viewChild<ElementRef<HTMLElement>>('view_child');
private boundingBox = boundingClientRect(this.viewChild);

constructor() {
effect(() => console.log(this.boundingBox()));
}
}
```

</details>


[menu-home]: /README.md
[menu-projects-overview]: /docs/site/projects-overview.md
[menu-changelog]: /docs/site/changelog.md
Expand Down
6 changes: 2 additions & 4 deletions docs/site/tools/observable.md
Original file line number Diff line number Diff line change
Expand Up @@ -85,13 +85,11 @@ fromBoundingClientRect$(element).subscribe((clientRect: DOMRect) => {
```

***
The target element and the document root (`<html>`) must be positioned `relative` or `absolute`. If not, a warning is logged and positioning is changed to `relative`.
The element and the document root (`<html>`) must be positioned `relative` or `absolute`. If not, a warning is logged, and positioning changed to `relative`.
***

*Note:*
As of 2024, there is no native browser API to observe the position of an element. This implementation uses
[`IntersectionObserver`](https://developer.mozilla.org/en-US/docs/Web/API/Intersection_Observer_API) and [`ResizeObserver`](https://developer.mozilla.org/en-US/docs/Web/API/ResizeObserver) to detect position changes.
For tracking only size changes, use `fromResize$` instead.
There is no native browser API to observe the position of an element. The observable uses [`IntersectionObserver`](https://developer.mozilla.org/en-US/docs/Web/API/Intersection_Observer_API) and [`ResizeObserver`](https://developer.mozilla.org/en-US/docs/Web/API/ResizeObserver) to detect position changes. For tracking only size changes, use `fromResize$` instead.
</details>

[menu-home]: /README.md
Expand Down
2 changes: 1 addition & 1 deletion projects/scion/components/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ The SCION Components is a collection of Angular components and directives primar
Provides a viewport component with scrollbars that sit on top of the viewport client.

- [**Dimension**][link-tool-dimension]\
Provides a set of tools for observing the size of an element.
Provides a set of tools for observing the size and position of an element.

- [**Sashbox**][link-tool-sashbox]\
Provides a sashbox component for splitting content into multiple parts, which the user can resize by moving the splitter between the parts.
Expand Down
Loading

0 comments on commit 8b41f4b

Please sign in to comment.