@xenterprises/nuxt-x-marketing 1.4.8 → 1.4.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.
package/CHANGELOG.md
CHANGED
|
@@ -30,6 +30,18 @@ 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.4.10] - 2026-09-06
|
|
34
|
+
|
|
35
|
+
### Added
|
|
36
|
+
|
|
37
|
+
- `XMarkBreadcrumb` for Docs/Academy articles: default trail is Home > Docs|Academy > current page (last crumb unlinked). Pass `items` to override. Built on `UBreadcrumb`.
|
|
38
|
+
|
|
39
|
+
## [1.4.9] - 2026-09-06
|
|
40
|
+
|
|
41
|
+
### Fixed
|
|
42
|
+
|
|
43
|
+
- `XMarkPricingPlans` spells billing periods as **per month** / **per year** by default (not `/month` `/year`), and normalizes common slash forms when mapping plans.
|
|
44
|
+
|
|
33
45
|
## [1.4.8] - 2026-09-06
|
|
34
46
|
|
|
35
47
|
### Fixed
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<nav class="x-mark-breadcrumb" aria-label="Breadcrumb">
|
|
3
|
+
<UBreadcrumb :items="resolvedItems" />
|
|
4
|
+
</nav>
|
|
5
|
+
</template>
|
|
6
|
+
|
|
7
|
+
<script setup>
|
|
8
|
+
/**
|
|
9
|
+
* XMarkBreadcrumb — Docs/Academy article breadcrumbs (marketing page standard).
|
|
10
|
+
* Prefer section + current for the default Home > Docs|Academy > page trail.
|
|
11
|
+
* Pass items to fully override. Last item is the current page (no link).
|
|
12
|
+
*/
|
|
13
|
+
const props = defineProps({
|
|
14
|
+
/** Full trail [{ label, to? }]. When set, overrides section/current builders. */
|
|
15
|
+
items: {
|
|
16
|
+
type: Array,
|
|
17
|
+
default: null,
|
|
18
|
+
},
|
|
19
|
+
/** Section root: docs or academy (builds Home > Section > current). */
|
|
20
|
+
section: {
|
|
21
|
+
type: String,
|
|
22
|
+
default: "docs",
|
|
23
|
+
validator: (v) => ["docs", "academy"].includes(v),
|
|
24
|
+
},
|
|
25
|
+
/** Current page label (required for the default trail when items is null). */
|
|
26
|
+
current: {
|
|
27
|
+
type: String,
|
|
28
|
+
default: "",
|
|
29
|
+
},
|
|
30
|
+
/** Home crumb label */
|
|
31
|
+
homeLabel: {
|
|
32
|
+
type: String,
|
|
33
|
+
default: "Home",
|
|
34
|
+
},
|
|
35
|
+
/** Home crumb path */
|
|
36
|
+
homeTo: {
|
|
37
|
+
type: String,
|
|
38
|
+
default: "/",
|
|
39
|
+
},
|
|
40
|
+
/** Override section crumb label */
|
|
41
|
+
sectionLabel: {
|
|
42
|
+
type: String,
|
|
43
|
+
default: "",
|
|
44
|
+
},
|
|
45
|
+
/** Override section crumb path */
|
|
46
|
+
sectionTo: {
|
|
47
|
+
type: String,
|
|
48
|
+
default: "",
|
|
49
|
+
},
|
|
50
|
+
});
|
|
51
|
+
|
|
52
|
+
const sectionDefaults = {
|
|
53
|
+
docs: { label: "Docs", to: "/docs" },
|
|
54
|
+
academy: { label: "Academy", to: "/academy" },
|
|
55
|
+
};
|
|
56
|
+
|
|
57
|
+
const resolvedItems = computed(() => {
|
|
58
|
+
if (Array.isArray(props.items) && props.items.length) {
|
|
59
|
+
return props.items.map((item, index, arr) => {
|
|
60
|
+
const isLast = index === arr.length - 1;
|
|
61
|
+
return {
|
|
62
|
+
label: item.label,
|
|
63
|
+
...(isLast || !item.to ? {} : { to: item.to }),
|
|
64
|
+
};
|
|
65
|
+
});
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
const section = sectionDefaults[props.section] || sectionDefaults.docs;
|
|
69
|
+
const sectionLabel = props.sectionLabel || section.label;
|
|
70
|
+
const sectionTo = props.sectionTo || section.to;
|
|
71
|
+
const current = props.current || "Article";
|
|
72
|
+
|
|
73
|
+
return [
|
|
74
|
+
{ label: props.homeLabel, to: props.homeTo },
|
|
75
|
+
{ label: sectionLabel, to: sectionTo },
|
|
76
|
+
{ label: current },
|
|
77
|
+
];
|
|
78
|
+
});
|
|
79
|
+
</script>
|
|
@@ -82,7 +82,7 @@ const props = defineProps({
|
|
|
82
82
|
{
|
|
83
83
|
name: "Starter",
|
|
84
84
|
price: "$9",
|
|
85
|
-
period: "
|
|
85
|
+
period: "per month",
|
|
86
86
|
description: "Perfect for individuals and small projects.",
|
|
87
87
|
features: ["5 projects", "10GB storage", "Email support"],
|
|
88
88
|
button: { label: "Get Started" },
|
|
@@ -90,7 +90,7 @@ const props = defineProps({
|
|
|
90
90
|
{
|
|
91
91
|
name: "Pro",
|
|
92
92
|
price: "$29",
|
|
93
|
-
period: "
|
|
93
|
+
period: "per month",
|
|
94
94
|
description: "For growing teams that need more power.",
|
|
95
95
|
features: [
|
|
96
96
|
"Unlimited projects",
|
|
@@ -104,7 +104,7 @@ const props = defineProps({
|
|
|
104
104
|
{
|
|
105
105
|
name: "Enterprise",
|
|
106
106
|
price: "$99",
|
|
107
|
-
period: "
|
|
107
|
+
period: "per month",
|
|
108
108
|
description: "For large organizations with custom needs.",
|
|
109
109
|
features: [
|
|
110
110
|
"Unlimited everything",
|
|
@@ -171,6 +171,14 @@ const emit = defineEmits(["select"]);
|
|
|
171
171
|
|
|
172
172
|
const billingPeriod = ref("monthly");
|
|
173
173
|
|
|
174
|
+
function normalizePeriod(period) {
|
|
175
|
+
if (!period) return period;
|
|
176
|
+
const trimmed = String(period).trim().toLowerCase();
|
|
177
|
+
if (["/month", "/mo", "mo", "month"].includes(trimmed)) return "per month";
|
|
178
|
+
if (["/year", "/yr", "yr", "year"].includes(trimmed)) return "per year";
|
|
179
|
+
return period;
|
|
180
|
+
}
|
|
181
|
+
|
|
174
182
|
// Map XMark plan format to Nuxt UI format
|
|
175
183
|
const mappedPlans = computed(() => {
|
|
176
184
|
return props.plans.map((plan) => {
|
|
@@ -183,9 +191,13 @@ const mappedPlans = computed(() => {
|
|
|
183
191
|
billingPeriod.value === "yearly"
|
|
184
192
|
? plan.price.yearly
|
|
185
193
|
: plan.price.monthly;
|
|
186
|
-
billingCycle =
|
|
194
|
+
billingCycle =
|
|
195
|
+
billingPeriod.value === "yearly" ? "per year" : "per month";
|
|
187
196
|
} else if (props.hasBillingToggle && !plan.period) {
|
|
188
|
-
billingCycle =
|
|
197
|
+
billingCycle =
|
|
198
|
+
billingPeriod.value === "yearly" ? "per year" : "per month";
|
|
199
|
+
} else {
|
|
200
|
+
billingCycle = normalizePeriod(billingCycle);
|
|
189
201
|
}
|
|
190
202
|
|
|
191
203
|
// Determine if this plan should be highlighted
|