elements-kit 0.27.8 → 0.27.10

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.
@@ -144,6 +144,23 @@ type Inset = PhysicalInset | "inset-block-start" | "inset-block-end" | "inset-in
144
144
  * box's reactive geometry, so calling it inside an `effect` tracks the anchor.
145
145
  */
146
146
  declare function anchor_length(box: Box & Partial<IDirection>, inset: Inset, side: BlockSide | InlineSide | number): number;
147
+ /** Keywords naming the block axis. */
148
+ type BlockKeyword = "top" | "bottom" | "span-top" | "span-bottom" | "block-start" | "block-end" | "span-block-start" | "span-block-end" | "y-start" | "y-end" | "span-y-start" | "span-y-end";
149
+ /** Keywords naming the inline axis. */
150
+ type InlineKeyword = "left" | "right" | "span-left" | "span-right" | "inline-start" | "inline-end" | "span-inline-start" | "span-inline-end" | "x-start" | "x-end" | "span-x-start" | "span-x-end";
151
+ /** Keywords naming no axis — each takes whichever one is still free. */
152
+ type AmbiguousKeyword = "center" | "span-all" | "start" | "end" | "span-start" | "span-end" | "self-start" | "self-end" | "span-self-start" | "span-self-end";
153
+ type AreaKeyword = BlockKeyword | InlineKeyword | AmbiguousKeyword;
154
+ /** Two keywords, in either order — `position-area` is unordered. */
155
+ type Unordered<A extends string, B extends string> = `${A} ${B}` | `${B} ${A}`;
156
+ /**
157
+ * A valid `position-area` value: one keyword, or two naming different axes.
158
+ * Two of the same explicit axis (`top bottom`, `left right`) is not a value —
159
+ * {@link resolveArea} resolves anything invalid to the `block-end` fallback,
160
+ * so catching it here is the difference between a compile error and a menu
161
+ * that quietly opens on the wrong side.
162
+ */
163
+ type PositionAreaValue = AreaKeyword | Unordered<BlockKeyword, InlineKeyword> | Unordered<BlockKeyword, AmbiguousKeyword> | Unordered<InlineKeyword, AmbiguousKeyword> | `${AmbiguousKeyword} ${AmbiguousKeyword}`;
147
164
  /**
148
165
  * The reactive `position-area` property: the region of the viewport an
149
166
  * overlay anchored to `anchor` may occupy, with the region's default
@@ -167,7 +184,7 @@ declare function anchor_length(box: Box & Partial<IDirection>, inset: Inset, sid
167
184
  declare class PositionArea implements Region, ReadonlyBox {
168
185
  #private;
169
186
  readonly anchor: ReadonlyBox;
170
- constructor(anchor: ReadonlyBox, area: string);
187
+ constructor(anchor: ReadonlyBox, area: PositionAreaValue);
171
188
  get x(): number;
172
189
  get y(): number;
173
190
  get w(): number;
@@ -266,4 +283,4 @@ declare class Motion implements IMotion {
266
283
  abort(initial?: number): void;
267
284
  }
268
285
  //#endregion
269
- export { type Align, type Axis, type BlockSide, type Boundary, ElementBox, gestures_d_exports as Gestures, type IDirection, type IMotion, type InlineSide, type Inset, Motion, MutableRegion, OverlayBox, type PhysicalInset, type Pin, type Placement, PositionArea, type ReadonlyBox, type Region, WINDOW_BOX, WindowBox, anchor_length };
286
+ export { type Align, type Axis, type BlockSide, type Boundary, ElementBox, gestures_d_exports as Gestures, type IDirection, type IMotion, type InlineSide, type Inset, Motion, MutableRegion, OverlayBox, type PhysicalInset, type Pin, type Placement, PositionArea, type PositionAreaValue, type ReadonlyBox, type Region, WINDOW_BOX, WindowBox, anchor_length };
@@ -181,7 +181,8 @@ const A = (region, self = false) => ({
181
181
  physical: false,
182
182
  self
183
183
  });
184
- /** The full `position-area` keyword grammar → axis + physical region. */
184
+ /** The full `position-area` keyword grammar → axis + physical region. The
185
+ * key type forces this table and {@link PositionAreaValue} to stay in step. */
185
186
  const KEYWORDS = {
186
187
  top: B("start", true),
187
188
  bottom: B("end", true),
@@ -2,19 +2,14 @@ import { r as MaybeReactive, t as Computed } from "../index-BSAqa0-0.mjs";
2
2
 
3
3
  //#region src/utilities/element-rect.d.ts
4
4
  /**
5
- * Observes the full bounding rect of `target` and returns it as ONE reactive
6
- * `DOMRect`, so every field a reader sees was measured at the same instant.
7
- * Change sources: a `ResizeObserver` for size, plus capture-phase `scroll` and
8
- * window `resize` for position a `ResizeObserver` stays silent when an
9
- * element merely moves.
5
+ * `target`'s bounding rect as one reactive `DOMRect`, every field from the
6
+ * same instant. Refreshed by a `ResizeObserver` (size) and capture-phase
7
+ * `scroll` / window `resize` (position), never on read. Size is the observer's
8
+ * border box, not the rect's: a transform scales the rect and never fires the
9
+ * observer.
10
10
  *
11
- * `target` may be a getter, in which case the observer follows it: the previous
12
- * element is unobserved before the new one is observed. The returned computed
13
- * keeps its identity across a swap, so consumers never rebind.
14
- *
15
- * The value is CACHED, not measured per read: it refreshes when one of the
16
- * sources above fires, not at the moment you read it. Dispose explicitly, or
17
- * let the enclosing scope do it.
11
+ * A reactive `target` is followed, keeping the computed's identity. Dispose
12
+ * explicitly, or let the enclosing scope do it.
18
13
  */
19
14
  declare function createElementRect(target: MaybeReactive<Element>): Computed<DOMRect> & Disposable;
20
15
  //#endregion
@@ -3,30 +3,38 @@ import { resolve } from "../signals/index.mjs";
3
3
  import { createResizeObserver } from "./resize-observer.mjs";
4
4
  //#region src/utilities/element-rect.ts
5
5
  /**
6
- * Observes the full bounding rect of `target` and returns it as ONE reactive
7
- * `DOMRect`, so every field a reader sees was measured at the same instant.
8
- * Change sources: a `ResizeObserver` for size, plus capture-phase `scroll` and
9
- * window `resize` for position a `ResizeObserver` stays silent when an
10
- * element merely moves.
6
+ * `target`'s bounding rect as one reactive `DOMRect`, every field from the
7
+ * same instant. Refreshed by a `ResizeObserver` (size) and capture-phase
8
+ * `scroll` / window `resize` (position), never on read. Size is the observer's
9
+ * border box, not the rect's: a transform scales the rect and never fires the
10
+ * observer.
11
11
  *
12
- * `target` may be a getter, in which case the observer follows it: the previous
13
- * element is unobserved before the new one is observed. The returned computed
14
- * keeps its identity across a swap, so consumers never rebind.
15
- *
16
- * The value is CACHED, not measured per read: it refreshes when one of the
17
- * sources above fires, not at the moment you read it. Dispose explicitly, or
18
- * let the enclosing scope do it.
12
+ * A reactive `target` is followed, keeping the computed's identity. Dispose
13
+ * explicitly, or let the enclosing scope do it.
19
14
  */
20
15
  function createElementRect(target) {
21
- const cache = signal(resolve(target).getBoundingClientRect());
16
+ let size;
17
+ const read = (el) => {
18
+ const r = el.getBoundingClientRect();
19
+ return size ? new DOMRect(r.x, r.y, size.width, size.height) : r;
20
+ };
21
+ const cache = signal(read(resolve(target)));
22
22
  const updateRect = (el) => {
23
- cache(el.getBoundingClientRect());
23
+ cache(read(el));
24
24
  };
25
25
  const stop = effectScope(() => {
26
26
  effect(() => {
27
27
  const el = resolve(target);
28
+ size = void 0;
28
29
  createResizeObserver(el, (entries) => {
29
- for (const entry of entries) updateRect(entry.target);
30
+ for (const entry of entries) {
31
+ const box = entry.borderBoxSize?.[0];
32
+ if (box) size = {
33
+ width: box.inlineSize,
34
+ height: box.blockSize
35
+ };
36
+ updateRect(entry.target);
37
+ }
30
38
  });
31
39
  const remeasure = () => updateRect(el);
32
40
  window.addEventListener("scroll", remeasure, {
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "elements-kit",
3
3
  "type": "module",
4
- "version": "0.27.8",
4
+ "version": "0.27.10",
5
5
  "description": "A lightweight reactive UI library that transforms native HTMLElements into reactive components with signals. Ideal for framework-agnostic applications and web components.",
6
6
  "keywords": [
7
7
  "webcomponents",