origam 2.37.0 → 2.37.1

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.1] - 2026-10-19
22
+
23
+ ### Fixed — `OrigamImg` / `OrigamResponsive` : prop `tag`, `<img>` visible en SSR, fondu en rendu client seul (#1182)
24
+
25
+ Un `<origam-img>` placé dans un `<p>` (contenu prose) produisait un `<div>` invalide dans un paragraphe, que le parseur HTML expulse : DOM serveur et client divergeaient. Et l'`<img>` était servie en `display:none` jusqu'au `load` côté client, donc invisible tant que le JS n'avait pas tourné.
26
+
27
+ - **Nouvelle prop `tag`** (défaut `'div'`) sur `OrigamResponsive` et `OrigamImg` (transmise au Responsive et aux conteneurs placeholder / error / gradient). `tag="span"` garde un DOM valide dans un `<p>`.
28
+ - **`<img>` visible dans le HTML serveur** : elle n'est plus masquée avant le `load`.
29
+ - **Fondu conservé uniquement au montage client** (navigation SPA, `v-if` après hydratation). Une image hydratée depuis le HTML serveur s'affiche sans fondu et sans clignotement.
30
+ - ⚠️ Changement de rendu assumé : en rendu serveur puis hydratation, l'image n'apparaît plus en fondu.
31
+
21
32
  ## [2.37.0] - 2026-10-19
22
33
 
23
34
  ### Added — module Nuxt : options `locale` transmises à `createOrigam` (#1181)
@@ -76,6 +76,7 @@ const props = defineProps({
76
76
  id: { type: String, required: false },
77
77
  class: { type: [String, Array, Object], required: false },
78
78
  style: { type: [String, Array, Object, Boolean, null], required: false, skipCheck: true },
79
+ tag: { type: String, required: false },
79
80
  padding: { type: [Boolean, Number, String], required: false },
80
81
  paddingTop: { type: [Boolean, Number, String], required: false },
81
82
  paddingLeft: { type: [Boolean, Number, String], required: false },
@@ -10,11 +10,11 @@
10
10
  >
11
11
  <template #additional>
12
12
  <origam-transition
13
+ :appear="fadesIn"
13
14
  :transition="transition"
14
- appear
15
15
  >
16
16
  <img
17
- v-show="isLoaded"
17
+ v-show="isPictureShown"
18
18
  ref="image"
19
19
  :alt="alt"
20
20
  :class="imgPictureClasses"
@@ -46,25 +46,28 @@
46
46
  :transition="transition"
47
47
  appear
48
48
  >
49
- <div
49
+ <component
50
+ :is="tag"
50
51
  v-if="(isLoading || (isError && !slots.error)) && slots.placeholder"
51
52
  class="origam-img__placeholder"
52
53
  >
53
54
  <slot name="placeholder"/>
54
- </div>
55
+ </component>
55
56
  </origam-transition>
56
57
  <origam-transition
57
58
  :transition="transition"
58
59
  appear
59
60
  >
60
- <div
61
+ <component
62
+ :is="tag"
61
63
  v-if="isError && slots.error"
62
64
  class="origam-img__error"
63
65
  >
64
66
  <slot name="error"/>
65
- </div>
67
+ </component>
66
68
  </origam-transition>
67
- <div
69
+ <component
70
+ :is="tag"
68
71
  v-if="gradient"
69
72
  :style="imgGradientStyles"
70
73
  class="origam-img__gradient"
@@ -133,6 +136,7 @@ const props = defineProps({
133
136
  id: { type: String, required: false },
134
137
  class: { type: [String, Array, Object], required: false },
135
138
  style: { type: [String, Array, Object, Boolean, null], required: false, skipCheck: true },
139
+ tag: { type: String, required: false, default: "div" },
136
140
  padding: { type: [Boolean, Number, String], required: false },
137
141
  paddingTop: { type: [Boolean, Number, String], required: false },
138
142
  paddingLeft: { type: [Boolean, Number, String], required: false },
@@ -219,7 +223,7 @@ const normalisedSrc = computed(() => {
219
223
  const aspectRatio = computed(() => {
220
224
  return normalisedSrc.value.aspectRatio || naturalWidth.value / naturalHeight.value || 0;
221
225
  });
222
- const responsiveProps = computed(() => pick(props, ["aspectRatio", "contentClass", "height", "maxHeight", "maxWidth", "minHeight", "minWidth", "width", "class", "style"]));
226
+ const responsiveProps = computed(() => pick(props, ["tag", "aspectRatio", "contentClass", "height", "maxHeight", "maxWidth", "minHeight", "minWidth", "width", "class", "style"]));
223
227
  watch(() => props.src, () => {
224
228
  init(state.value !== IMG_STATE.IDLE);
225
229
  });
@@ -337,6 +341,10 @@ const isLoading = computed(() => {
337
341
  const isError = computed(() => {
338
342
  return state.value === IMG_STATE.ERROR;
339
343
  });
344
+ const fadesIn = IN_BROWSER && !vm.vnode.el;
345
+ const isPictureShown = computed(() => {
346
+ return fadesIn ? isLoaded.value : !isError.value;
347
+ });
340
348
  const hasContent = computed(() => {
341
349
  return slots.default;
342
350
  });
@@ -1,17 +1,19 @@
1
1
  <template>
2
- <div
2
+ <component
3
+ :is="tag"
3
4
  :id="id"
4
5
  :class="responsiveClasses"
5
6
  :style="responsiveStyles"
6
7
  >
7
8
  <slot name="additional"/>
8
- <div
9
+ <component
10
+ :is="tag"
9
11
  v-if="slots.default"
10
12
  :class="responsiveContentClasses"
11
13
  >
12
14
  <slot name="default"/>
13
- </div>
14
- </div>
15
+ </component>
16
+ </component>
15
17
  </template>
16
18
 
17
19
  <script lang="ts" setup>
@@ -36,6 +38,7 @@ const props = defineProps({
36
38
  id: { type: String, required: false },
37
39
  class: { type: [String, Array, Object], required: false },
38
40
  style: { type: [String, Array, Object, Boolean, null], required: false, skipCheck: true },
41
+ tag: { type: String, required: false, default: "div" },
39
42
  padding: { type: [Boolean, Number, String], required: false },
40
43
  paddingTop: { type: [Boolean, Number, String], required: false },
41
44
  paddingLeft: { type: [Boolean, Number, String], required: false },
@@ -1,10 +1,10 @@
1
1
  import type { IBorderProps } from '../Commons/border.interface';
2
- import type { ICommonsComponentProps } from '../Commons/commons.interface';
2
+ import type { ICommonsComponentProps, ITagProps } from '../Commons/commons.interface';
3
3
  import type { IDimensionProps } from '../Commons/dimension.interface';
4
4
  import type { IMarginProps } from '../Commons/margin.interface';
5
5
  import type { IPaddingProps } from '../Commons/padding.interface';
6
6
  import type { IRoundedProps } from '../Commons/rounded.interface';
7
- export interface IResponsiveProps extends IDimensionProps, ICommonsComponentProps, IPaddingProps, IMarginProps, IBorderProps, IRoundedProps {
7
+ export interface IResponsiveProps extends IDimensionProps, ICommonsComponentProps, ITagProps, IPaddingProps, IMarginProps, IBorderProps, IRoundedProps {
8
8
  aspectRatio?: string | number;
9
9
  contentClass?: string;
10
10
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "origam",
3
- "version": "2.37.0",
3
+ "version": "2.37.1",
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": [