origam 2.37.2 → 2.37.3

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/CHANGELOG.md CHANGED
@@ -18,6 +18,17 @@ This project follows [Semantic Versioning](https://semver.org).
18
18
 
19
19
  ## [Unreleased]
20
20
 
21
+ ## [2.37.3] - 2026-10-19
22
+
23
+ ### Fixed — `v-intersect` lié avec le tuple `withDirectives` : handler jamais appelé (#1205)
24
+
25
+ `OrigamLazy`, `OrigamTextField`, `OrigamTextareaField` et `OrigamPasswordField` passaient à `v-intersect` le tuple `[{ handler, options }, null, ['once']]` comme valeur. La directive lit `.handler` / `.options` sur la valeur : sur un tableau, elle obtient `undefined`. Aucune intersection n'appelait donc le handler, `once` n'était jamais lu et les `options` n'atteignaient pas l'`IntersectionObserver`.
26
+
27
+ - **`OrigamLazy`** : le contenu ne s'affichait jamais à l'intersection, et les `options` du consommateur (ex. `rootMargin`) étaient ignorées. C'est corrigé ; mesuré dans Chromium.
28
+ - **Champs texte, textarea et mot de passe** : l'appel JS de `focus()` sur intersection (autofocus) n'avait jamais lieu. Dans Chromium, l'attribut natif `autofocus` masquait le défaut. Safari et Firefox n'ont pas été mesurés.
29
+ - Liaison désormais en `v-intersect.once="{ handler, options }"`.
30
+ - La directive émet un `console.warn` en mode dev (une fois par balise) quand on lui lie un tableau.
31
+
21
32
  ## [2.37.2] - 2026-10-19
22
33
 
23
34
  ### Fixed — `OrigamImg` sous SSR : écart d'hydratation `aspect-ratio`, et image montée côté client jamais chargée (#1192)
@@ -2,7 +2,7 @@
2
2
  <component
3
3
  :is="tag"
4
4
  :id="id"
5
- v-intersect="intersect"
5
+ v-intersect.once="intersect"
6
6
  :aria-busy="!isActive || undefined"
7
7
  :class="lazyClasses"
8
8
  :style="lazyStyles"
@@ -52,11 +52,7 @@ const { filterProps } = useProps(props);
52
52
  const { dimensionStyles } = useDimension(props);
53
53
  const isActive = useVModel(props, "modelValue");
54
54
  const intersect = computed(() => {
55
- return [
56
- { handler: handleIntersect, options: props.options },
57
- null,
58
- isActive.value ? [] : ["once"]
59
- ];
55
+ return { handler: handleIntersect, options: props.options };
60
56
  });
61
57
  const handleIntersect = (isIntersecting) => {
62
58
  if (isActive.value) return;
@@ -124,7 +124,7 @@
124
124
  />
125
125
  <input
126
126
  ref="inputRef"
127
- v-intersect="intersect"
127
+ v-intersect.once="intersect"
128
128
  :autofocus="autofocus"
129
129
  :disabled="isDisabled"
130
130
  :name="name"
@@ -501,7 +501,7 @@ const handleIntersect = (isIntersecting, entries) => {
501
501
  entries[0].target?.focus?.();
502
502
  };
503
503
  const intersect = computed(() => {
504
- return [{ handler: handleIntersect }, null, ["once"]];
504
+ return { handler: handleIntersect };
505
505
  });
506
506
  const origamInputRef = ref();
507
507
  const origamFieldRef = ref();
@@ -83,7 +83,7 @@
83
83
  />
84
84
  <input
85
85
  ref="inputRef"
86
- v-intersect="intersect"
86
+ v-intersect.once="intersect"
87
87
  :autofocus="autofocus"
88
88
  :disabled="isDisabled"
89
89
  :name="name"
@@ -372,9 +372,7 @@ const max = computed(() => {
372
372
  return props.counter;
373
373
  });
374
374
  const intersect = computed(() => {
375
- return [{
376
- handler: handleIntersect
377
- }, null, ["once"]];
375
+ return { handler: handleIntersect };
378
376
  });
379
377
  const handleIntersect = (isIntersecting, entries) => {
380
378
  if (!props.autofocus || !isIntersecting) return;
@@ -131,7 +131,7 @@
131
131
  <textarea
132
132
  v-else
133
133
  ref="textareaRef"
134
- v-intersect="intersect"
134
+ v-intersect.once="intersect"
135
135
  :autofocus="autofocus"
136
136
  :disabled="isDisabled"
137
137
  :name="name"
@@ -499,9 +499,7 @@ const {
499
499
  onClickAppend: handleClickAppend
500
500
  } = useAdjacent(props, toRef(props, "prependIcon"), toRef(props, "appendIcon"));
501
501
  const intersect = computed(() => {
502
- return [{
503
- handler: handleIntersect
504
- }, null, ["once"]];
502
+ return { handler: handleIntersect };
505
503
  });
506
504
  const handleIntersect = (isIntersecting, entries) => {
507
505
  if (!props.autofocus || !isIntersecting) return;
@@ -9,6 +9,7 @@ var _intersect = require("../../utils/Commons/intersect.util.cjs");
9
9
  const Intersect = exports.Intersect = {
10
10
  mounted(el, binding) {
11
11
  if (!_commons.SUPPORTS_INTERSECTION) return;
12
+ (0, _intersect.warnIntersectTupleBinding)(el, binding.value);
12
13
  const read = () => {
13
14
  const b = el._observe?.[binding.instance.$.uid]?.binding ?? binding;
14
15
  const v = b.value;
@@ -1,8 +1,9 @@
1
1
  import { SUPPORTS_INTERSECTION } from "../../consts/Commons/commons.const.js";
2
- import { unmountIntersect } from "../../utils/Commons/intersect.util.js";
2
+ import { unmountIntersect, warnIntersectTupleBinding } from "../../utils/Commons/intersect.util.js";
3
3
  export const Intersect = {
4
4
  mounted(el, binding) {
5
5
  if (!SUPPORTS_INTERSECTION) return;
6
+ warnIntersectTupleBinding(el, binding.value);
6
7
  const read = () => {
7
8
  const b = el._observe?.[binding.instance.$.uid]?.binding ?? binding;
8
9
  const v = b.value;
@@ -4,9 +4,20 @@ Object.defineProperty(exports, "__esModule", {
4
4
  value: true
5
5
  });
6
6
  exports.unmountIntersect = unmountIntersect;
7
+ exports.warnIntersectTupleBinding = warnIntersectTupleBinding;
7
8
  function unmountIntersect(el, binding) {
8
9
  const observe = el._observe?.[binding.instance.$.uid];
9
10
  if (!observe) return;
10
11
  observe.observer.unobserve(el);
11
12
  delete el._observe[binding.instance.$.uid];
13
+ }
14
+ const _warnedIntersectTupleTags = /* @__PURE__ */new Set();
15
+ function warnIntersectTupleBinding(el, value) {
16
+ if (!Array.isArray(value)) return;
17
+ if (typeof console === "undefined") return;
18
+ if (!process.env?.DEV) return;
19
+ const tag = el.tagName.toLowerCase();
20
+ if (_warnedIntersectTupleTags.has(tag)) return;
21
+ _warnedIntersectTupleTags.add(tag);
22
+ console.warn(`[origam] v-intersect on <${tag}> is bound to an array (the withDirectives tuple): the handler will never be called. Bind { handler, options } and use the modifier, e.g. v-intersect.once="{ handler, options }".`);
12
23
  }
@@ -6,3 +6,15 @@ import type { IIntersectDirectiveBinding, IIntersectHtmlElement } from '../../in
6
6
  * @param binding …
7
7
  */
8
8
  export declare function unmountIntersect(el: IIntersectHtmlElement, binding: IIntersectDirectiveBinding): void;
9
+ /*********************************************************
10
+ * warnIntersectTupleBinding
11
+ *
12
+ * @description
13
+ * Dev-only warning (#1205, once per element tag) when `v-intersect` is bound
14
+ * to an ARRAY. The `withDirectives` tuple `[{ handler, options }, null,
15
+ * ['once']]` is not a valid binding VALUE: the directive reads `.handler` /
16
+ * `.options` off it, gets `undefined`, never calls the handler and never
17
+ * reads the `once`. The correct form is `v-intersect.once="{ handler,
18
+ * options }"`. Gated on `import.meta.env.DEV`, like `warnUnsupportedProp`.
19
+ ********************************************************/
20
+ export declare function warnIntersectTupleBinding(el: HTMLElement, value: unknown): void;
@@ -4,3 +4,15 @@ export function unmountIntersect(el, binding) {
4
4
  observe.observer.unobserve(el);
5
5
  delete el._observe[binding.instance.$.uid];
6
6
  }
7
+ const _warnedIntersectTupleTags = /* @__PURE__ */ new Set();
8
+ export function warnIntersectTupleBinding(el, value) {
9
+ if (!Array.isArray(value)) return;
10
+ if (typeof console === "undefined") return;
11
+ if (!import.meta.env?.DEV) return;
12
+ const tag = el.tagName.toLowerCase();
13
+ if (_warnedIntersectTupleTags.has(tag)) return;
14
+ _warnedIntersectTupleTags.add(tag);
15
+ console.warn(
16
+ `[origam] v-intersect on <${tag}> is bound to an array (the withDirectives tuple): the handler will never be called. Bind { handler, options } and use the modifier, e.g. v-intersect.once="{ handler, options }".`
17
+ );
18
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "origam",
3
- "version": "2.37.2",
3
+ "version": "2.37.3",
4
4
  "type": "module",
5
5
  "description": "origam — a Vue 3 design system with multi-theme design tokens, CSS-first components and TypeScript types.",
6
6
  "keywords": [