@xenterprises/nuxt-x-marketing 1.15.2 → 1.15.4

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
@@ -30,6 +30,32 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
30
30
  section and its sample product data were dropped with them. Every other section of the
31
31
  demo page is unchanged.
32
32
 
33
+ ## [1.15.4] - 2026-10-21
34
+
35
+ ### Fixed
36
+
37
+ - **`XMarkHero` subtitle centring with `align="center"`.** The subtitle's `max-w-2xl` box sat at
38
+ the left of the `max-w-3xl` text column, so a centred subtitle was 48px left of centre at
39
+ 1024px and up (24px at 768px). The subtitle now gets `mx-auto` when `align="center"` (prop or
40
+ `#subtitle` slot), so its box and text are centred on the column. Title and CTA were already
41
+ centred and are unchanged. `align="left"` (default) and `align="right"`: body HTML identical to
42
+ 1.15.3 and 0 px difference at 1440x900, 1024x768, 768x1024, 390x844 and 375x667. Centred heroes
43
+ below about 720px wide are also 0 px (the box already fills the column).
44
+
45
+ ## [1.15.3] - 2026-10-20
46
+
47
+ ### Added (opt-in)
48
+
49
+ - **`XMarkHero` `constrainToScrim`** (boolean, kebab `constrain-to-scrim`). With
50
+ `overlay="scrim-left"` and `align="left"`, at md and up the text column is capped so it stays
51
+ inside the 90% scrim zone: max width = effective scrim width (`scrimWidth`, or 55% when unset)
52
+ minus the container's left offset and a 2rem inner gap, never wider than the default
53
+ `max-w-3xl` and never narrower than 14rem. A `%` scrimWidth resolves against the hero width
54
+ (the section becomes an inline-size container at md+ only). Below md nothing changes,
55
+ including `scrimMobile="bottom"`. Lets a 50 to 55% scrim pass 4.5:1 at 768 to 1024px without
56
+ burying the photo. Unset: body HTML identical to 1.15.2 and 0 px difference at 1440, 1024,
57
+ 768 and 390.
58
+
33
59
  ## [1.15.2] - 2026-10-19
34
60
 
35
61
  ### Fixed
@@ -5,7 +5,7 @@
5
5
  heightClass,
6
6
  alignmentClasses,
7
7
  verticalAlignClasses,
8
- { 'pt-20': includeNavPadding },
8
+ { 'pt-20': includeNavPadding, 'x-hero-cts': constrain },
9
9
  ]"
10
10
  >
11
11
  <!-- Background -->
@@ -81,7 +81,11 @@
81
81
 
82
82
  <!-- Content -->
83
83
  <div class="relative z-10 w-full max-w-7xl mx-auto px-4 sm:px-6 lg:px-8">
84
- <div class="max-w-3xl pb-6 md:pb-8" :class="contentAlignmentClasses">
84
+ <div
85
+ class="max-w-3xl pb-6 md:pb-8"
86
+ :class="[contentAlignmentClasses, { 'x-hero-cts-col': constrain }]"
87
+ v-bind="constrain ? { style: constrainStyle } : {}"
88
+ >
85
89
  <!-- Eyebrow -->
86
90
  <p v-if="eyebrow" class="xText-eyebrow text-white/70 mb-4">
87
91
  {{ eyebrow }}
@@ -98,6 +102,7 @@
98
102
  <p
99
103
  v-if="subtitle || $slots.subtitle"
100
104
  class="mt-6 text-xl text-white/80 max-w-2xl"
105
+ :class="{ 'mx-auto': align === 'center' }"
101
106
  >
102
107
  <slot name="subtitle">{{ subtitle }}</slot>
103
108
  </p>
@@ -260,6 +265,18 @@ const props = defineProps({
260
265
  default: "",
261
266
  validator: (v) => ["", "bottom"].includes(v),
262
267
  },
268
+ /**
269
+ * scrim-left only, opt-in (1.15.3). At md and up, caps the text column so its right
270
+ * edge stays inside the 90% scrim zone: max width = effective scrim width (scrimWidth,
271
+ * or 55% when unset) minus the container's left offset and a 2rem inner gap, never
272
+ * wider than the default max-w-3xl and never narrower than 14rem. Left-aligned
273
+ * content only (center/right alignment is unaffected). Below md nothing changes,
274
+ * including scrimMobile="bottom". Unset (default): output identical to 1.15.2.
275
+ */
276
+ constrainToScrim: {
277
+ type: Boolean,
278
+ default: false,
279
+ },
263
280
  /** Add top padding for non-transparent nav */
264
281
  includeNavPadding: {
265
282
  type: Boolean,
@@ -293,6 +310,19 @@ const mobileBottom = computed(
293
310
 
294
311
  const softScrim = computed(() => props.overlay === "scrim-left" && !!props.scrimWidth);
295
312
 
313
+ // constrainToScrim (1.15.3): only meaningful for left-aligned content over scrim-left.
314
+ const constrain = computed(
315
+ () => props.constrainToScrim && props.overlay === "scrim-left" && props.align === "left",
316
+ );
317
+
318
+ // Effective scrim width in units that resolve against the hero section (a size container
319
+ // at md+ when constrained): N% of the section becomes Ncqw; other lengths pass through.
320
+ const constrainStyle = computed(() => {
321
+ if (!constrain.value) return undefined;
322
+ const w = props.scrimWidth || "55%";
323
+ return { "--x-cts-w": w.endsWith("%") ? `${parseFloat(w)}cqw` : w };
324
+ });
325
+
296
326
  const heightClass = computed(() => {
297
327
  const heights = {
298
328
  full: "min-h-[calc(100svh-var(--ui-header-height))]",
@@ -370,6 +400,29 @@ const contentAlignmentClasses = computed(() => {
370
400
  );
371
401
  }
372
402
  }
403
+ /* constrainToScrim (1.15.3), md+ only: the section is an inline-size container so the
404
+ * text column can be capped against the section width. Column left edge = container
405
+ * offset (max(0, (100cqw - 80rem) / 2)) + container padding (md 1.5rem, lg 2rem). */
406
+ @media (min-width: 768px) {
407
+ .x-hero-cts {
408
+ container-type: inline-size;
409
+ }
410
+ .x-hero-cts-col {
411
+ --x-cts-pad: 1.5rem;
412
+ max-width: min(
413
+ 48rem,
414
+ max(
415
+ 14rem,
416
+ calc(var(--x-cts-w, 55cqw) - max(0px, (100cqw - 80rem) / 2) - var(--x-cts-pad) - 2rem)
417
+ )
418
+ );
419
+ }
420
+ }
421
+ @media (min-width: 1024px) {
422
+ .x-hero-cts-col {
423
+ --x-cts-pad: 2rem;
424
+ }
425
+ }
373
426
  /* md+: 90% up to --x-scrim-w, then a long eased fade to clear. */
374
427
  @media (min-width: 768px) {
375
428
  .x-hero-scrim-w {
package/package.json CHANGED
@@ -2,7 +2,7 @@
2
2
  "name": "@xenterprises/nuxt-x-marketing",
3
3
  "license": "SEE LICENSE IN LICENSE",
4
4
  "type": "module",
5
- "version": "1.15.2",
5
+ "version": "1.15.4",
6
6
  "main": "./nuxt.config.ts",
7
7
  "scripts": {
8
8
  "dev": "nuxi dev .playground",