@stackonward/cli 1.3.3 → 1.4.0
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/dist/index.js +33 -34
- package/dist/index.js.map +1 -1
- package/dist/resources/components/nuxt/site-source/app/app.vue +4 -2
- package/dist/resources/components/nuxt/site-source/app/assets/css/site-shell.css +50 -50
- package/dist/resources/components/nuxt/site-source/app/components/{site/ApplicationHeader.vue → app/Header.vue} +3 -3
- package/dist/resources/components/nuxt/site-source/app/components/{site/ApplicationShell.vue → app/Shell.vue} +2 -2
- package/dist/resources/components/nuxt/site-source/app/components/{site/ApplicationSidebar.vue → app/Sidebar.vue} +2 -2
- package/dist/resources/components/nuxt/site-source/app/components/{ui/CheckoutStatus.vue → checkout/Status.vue} +8 -3
- package/dist/resources/components/nuxt/site-source/app/components/{ui/CheckoutSummary.vue → checkout/Summary.vue} +11 -11
- package/dist/resources/components/nuxt/site-source/app/components/{site/CookieConsent.vue → consent/Banner.vue} +3 -3
- package/dist/resources/components/nuxt/site-source/app/components/{site/ContentArticlePage.vue → content/Article.vue} +3 -3
- package/dist/resources/components/nuxt/site-source/app/components/{site/ContentListPage.vue → content/List.vue} +2 -2
- package/dist/resources/components/nuxt/site-source/app/components/{ui/GoogleSignInButton.vue → google/SignInButton.vue} +3 -3
- package/dist/resources/components/nuxt/site-source/app/components/{site/LocaleSwitcher.vue → locale/Menu.vue} +2 -2
- package/dist/resources/components/nuxt/site-source/app/components/site/{MarketingFooter.vue → Footer.vue} +8 -8
- package/dist/resources/components/nuxt/site-source/app/components/site/{MarketingHeader.vue → Header.vue} +27 -27
- package/dist/resources/components/nuxt/site-source/app/components/site/Shell.vue +29 -0
- package/dist/resources/components/nuxt/site-source/app/components/{site/ThemeSwitcher.vue → theme/Menu.vue} +2 -2
- package/dist/resources/components/nuxt/site-source/app/components/ui/{BaseButton.vue → Button.vue} +1 -8
- package/dist/resources/components/nuxt/site-source/app/components/ui/InfiniteScroll.vue +2 -2
- package/dist/resources/components/nuxt/site-source/app/components/{ui/YoutubeEmbed.vue → youtube/Embed.vue} +10 -2
- package/dist/resources/components/nuxt/site-source/app/composables/useConsent.ts +8 -10
- package/dist/resources/components/nuxt/site-source/app/composables/useNavigation.ts +9 -14
- package/dist/resources/components/nuxt/site-source/app/composables/useSeo.ts +3 -1
- package/dist/resources/components/nuxt/site-source/app/composables/useSiteShell.ts +19 -22
- package/dist/resources/components/nuxt/site-source/app/consent/types.ts +59 -0
- package/dist/resources/components/nuxt/site-source/app/content/types.ts +17 -0
- package/dist/resources/components/nuxt/site-source/app/layouts/app.vue +2 -2
- package/dist/resources/components/nuxt/site-source/app/layouts/default.vue +2 -2
- package/dist/resources/components/nuxt/site-source/app/navigation/types.ts +68 -0
- package/dist/resources/components/nuxt/site-source/app/plugins/consent.ts +2 -2
- package/dist/resources/components/nuxt/site-source/app/site/config.ts +35 -0
- package/dist/resources/components/registry.json +63 -51
- package/dist/resources/registry.json +6 -6
- package/dist/resources/templates/nuxt/README.md +3 -3
- package/dist/resources/templates/nuxt/app/app.config.ts +1 -1
- package/dist/resources/templates/nuxt/app/i18n/locales/en.json +1 -1
- package/dist/resources/templates/nuxt/app/pages/app/index.vue +1 -1
- package/dist/resources/templates/nuxt/app/pages/authors/[slug].vue +2 -2
- package/dist/resources/templates/nuxt/app/pages/blog/[slug].vue +4 -3
- package/dist/resources/templates/nuxt/app/pages/blog/category/[category].vue +2 -2
- package/dist/resources/templates/nuxt/app/pages/blog/index.vue +2 -2
- package/dist/resources/templates/nuxt/app/pages/legal/cookies.vue +3 -3
- package/dist/resources/templates/nuxt/app/pages/legal/privacy.vue +2 -2
- package/dist/resources/templates/nuxt/app/pages/legal/terms.vue +2 -2
- package/dist/resources/templates/nuxt/app/pages/ui/index.vue +45 -45
- package/dist/resources/templates/nuxt/nuxt.config.ts +4 -10
- package/dist/resources/templates/nuxt/package.json +2 -2
- package/dist/resources/templates/nuxt/test/e2e/rendering.test.ts +1 -0
- package/dist/resources/templates/nuxt/test/unit/consent.test.ts +4 -7
- package/package.json +3 -3
- package/dist/resources/components/nuxt/site-source/app/components/site/MarketingShell.vue +0 -33
- package/dist/resources/components/nuxt/site-source/app/types/site-shell.ts +0 -172
- /package/dist/resources/components/nuxt/site-source/app/components/{site/ConsentSettingsButton.vue → consent/Settings.vue} +0 -0
- /package/dist/resources/components/nuxt/site-source/app/components/{site/StaticPage.vue → content/Document.vue} +0 -0
- /package/dist/resources/components/nuxt/site-source/app/components/{site/ToastViewport.vue → feedback/Toast.vue} +0 -0
- /package/dist/resources/components/nuxt/site-source/app/components/site/{SiteBrand.vue → Brand.vue} +0 -0
- /package/dist/resources/components/nuxt/site-source/app/components/ui/{BaseGradientBorder.vue → GradientBorder.vue} +0 -0
- /package/dist/resources/components/nuxt/site-source/app/components/ui/{BaseModal.vue → Modal.vue} +0 -0
- /package/dist/resources/components/nuxt/site-source/app/components/ui/{BasePopover.vue → Popover.vue} +0 -0
- /package/dist/resources/components/nuxt/site-source/app/components/ui/{BaseText.vue → Text.vue} +0 -0
|
@@ -144,7 +144,7 @@
|
|
|
144
144
|
},
|
|
145
145
|
"nuxt-site-source": {
|
|
146
146
|
"name": "Nuxt Site Source",
|
|
147
|
-
"description": "Editable Nuxt product-site source:
|
|
147
|
+
"description": "Editable Nuxt product-site source: site shell, app shell, content shell, UI primitives, composables, plugins, theme tokens, and CSS.",
|
|
148
148
|
"installContext": "template",
|
|
149
149
|
"files": [
|
|
150
150
|
{
|
|
@@ -164,108 +164,108 @@
|
|
|
164
164
|
"target": "app/assets/icons/common/.gitkeep"
|
|
165
165
|
},
|
|
166
166
|
{
|
|
167
|
-
"path": "site-source/app/components/
|
|
168
|
-
"target": "app/components/
|
|
167
|
+
"path": "site-source/app/components/app/Header.vue",
|
|
168
|
+
"target": "app/components/app/Header.vue"
|
|
169
169
|
},
|
|
170
170
|
{
|
|
171
|
-
"path": "site-source/app/components/
|
|
172
|
-
"target": "app/components/
|
|
171
|
+
"path": "site-source/app/components/app/Shell.vue",
|
|
172
|
+
"target": "app/components/app/Shell.vue"
|
|
173
173
|
},
|
|
174
174
|
{
|
|
175
|
-
"path": "site-source/app/components/
|
|
176
|
-
"target": "app/components/
|
|
175
|
+
"path": "site-source/app/components/app/Sidebar.vue",
|
|
176
|
+
"target": "app/components/app/Sidebar.vue"
|
|
177
177
|
},
|
|
178
178
|
{
|
|
179
179
|
"path": "site-source/app/components/site/BackToTop.vue",
|
|
180
180
|
"target": "app/components/site/BackToTop.vue"
|
|
181
181
|
},
|
|
182
182
|
{
|
|
183
|
-
"path": "site-source/app/components/
|
|
184
|
-
"target": "app/components/
|
|
183
|
+
"path": "site-source/app/components/content/Article.vue",
|
|
184
|
+
"target": "app/components/content/Article.vue"
|
|
185
185
|
},
|
|
186
186
|
{
|
|
187
|
-
"path": "site-source/app/components/
|
|
188
|
-
"target": "app/components/
|
|
187
|
+
"path": "site-source/app/components/content/List.vue",
|
|
188
|
+
"target": "app/components/content/List.vue"
|
|
189
189
|
},
|
|
190
190
|
{
|
|
191
|
-
"path": "site-source/app/components/
|
|
192
|
-
"target": "app/components/
|
|
191
|
+
"path": "site-source/app/components/consent/Settings.vue",
|
|
192
|
+
"target": "app/components/consent/Settings.vue"
|
|
193
193
|
},
|
|
194
194
|
{
|
|
195
|
-
"path": "site-source/app/components/
|
|
196
|
-
"target": "app/components/
|
|
195
|
+
"path": "site-source/app/components/consent/Banner.vue",
|
|
196
|
+
"target": "app/components/consent/Banner.vue"
|
|
197
197
|
},
|
|
198
198
|
{
|
|
199
|
-
"path": "site-source/app/components/
|
|
200
|
-
"target": "app/components/
|
|
199
|
+
"path": "site-source/app/components/locale/Menu.vue",
|
|
200
|
+
"target": "app/components/locale/Menu.vue"
|
|
201
201
|
},
|
|
202
202
|
{
|
|
203
|
-
"path": "site-source/app/components/site/
|
|
204
|
-
"target": "app/components/site/
|
|
203
|
+
"path": "site-source/app/components/site/Footer.vue",
|
|
204
|
+
"target": "app/components/site/Footer.vue"
|
|
205
205
|
},
|
|
206
206
|
{
|
|
207
|
-
"path": "site-source/app/components/site/
|
|
208
|
-
"target": "app/components/site/
|
|
207
|
+
"path": "site-source/app/components/site/Header.vue",
|
|
208
|
+
"target": "app/components/site/Header.vue"
|
|
209
209
|
},
|
|
210
210
|
{
|
|
211
|
-
"path": "site-source/app/components/site/
|
|
212
|
-
"target": "app/components/site/
|
|
211
|
+
"path": "site-source/app/components/site/Shell.vue",
|
|
212
|
+
"target": "app/components/site/Shell.vue"
|
|
213
213
|
},
|
|
214
214
|
{
|
|
215
|
-
"path": "site-source/app/components/site/
|
|
216
|
-
"target": "app/components/site/
|
|
215
|
+
"path": "site-source/app/components/site/Brand.vue",
|
|
216
|
+
"target": "app/components/site/Brand.vue"
|
|
217
217
|
},
|
|
218
218
|
{
|
|
219
|
-
"path": "site-source/app/components/
|
|
220
|
-
"target": "app/components/
|
|
219
|
+
"path": "site-source/app/components/content/Document.vue",
|
|
220
|
+
"target": "app/components/content/Document.vue"
|
|
221
221
|
},
|
|
222
222
|
{
|
|
223
|
-
"path": "site-source/app/components/
|
|
224
|
-
"target": "app/components/
|
|
223
|
+
"path": "site-source/app/components/feedback/Toast.vue",
|
|
224
|
+
"target": "app/components/feedback/Toast.vue"
|
|
225
225
|
},
|
|
226
226
|
{
|
|
227
|
-
"path": "site-source/app/components/
|
|
228
|
-
"target": "app/components/
|
|
227
|
+
"path": "site-source/app/components/theme/Menu.vue",
|
|
228
|
+
"target": "app/components/theme/Menu.vue"
|
|
229
229
|
},
|
|
230
230
|
{
|
|
231
|
-
"path": "site-source/app/components/ui/
|
|
232
|
-
"target": "app/components/ui/
|
|
231
|
+
"path": "site-source/app/components/ui/Button.vue",
|
|
232
|
+
"target": "app/components/ui/Button.vue"
|
|
233
233
|
},
|
|
234
234
|
{
|
|
235
|
-
"path": "site-source/app/components/ui/
|
|
236
|
-
"target": "app/components/ui/
|
|
235
|
+
"path": "site-source/app/components/ui/GradientBorder.vue",
|
|
236
|
+
"target": "app/components/ui/GradientBorder.vue"
|
|
237
237
|
},
|
|
238
238
|
{
|
|
239
|
-
"path": "site-source/app/components/ui/
|
|
240
|
-
"target": "app/components/ui/
|
|
239
|
+
"path": "site-source/app/components/ui/Modal.vue",
|
|
240
|
+
"target": "app/components/ui/Modal.vue"
|
|
241
241
|
},
|
|
242
242
|
{
|
|
243
|
-
"path": "site-source/app/components/ui/
|
|
244
|
-
"target": "app/components/ui/
|
|
243
|
+
"path": "site-source/app/components/ui/Popover.vue",
|
|
244
|
+
"target": "app/components/ui/Popover.vue"
|
|
245
245
|
},
|
|
246
246
|
{
|
|
247
|
-
"path": "site-source/app/components/ui/
|
|
248
|
-
"target": "app/components/ui/
|
|
247
|
+
"path": "site-source/app/components/ui/Text.vue",
|
|
248
|
+
"target": "app/components/ui/Text.vue"
|
|
249
249
|
},
|
|
250
250
|
{
|
|
251
|
-
"path": "site-source/app/components/
|
|
252
|
-
"target": "app/components/
|
|
251
|
+
"path": "site-source/app/components/checkout/Status.vue",
|
|
252
|
+
"target": "app/components/checkout/Status.vue"
|
|
253
253
|
},
|
|
254
254
|
{
|
|
255
|
-
"path": "site-source/app/components/
|
|
256
|
-
"target": "app/components/
|
|
255
|
+
"path": "site-source/app/components/checkout/Summary.vue",
|
|
256
|
+
"target": "app/components/checkout/Summary.vue"
|
|
257
257
|
},
|
|
258
258
|
{
|
|
259
|
-
"path": "site-source/app/components/
|
|
260
|
-
"target": "app/components/
|
|
259
|
+
"path": "site-source/app/components/google/SignInButton.vue",
|
|
260
|
+
"target": "app/components/google/SignInButton.vue"
|
|
261
261
|
},
|
|
262
262
|
{
|
|
263
263
|
"path": "site-source/app/components/ui/InfiniteScroll.vue",
|
|
264
264
|
"target": "app/components/ui/InfiniteScroll.vue"
|
|
265
265
|
},
|
|
266
266
|
{
|
|
267
|
-
"path": "site-source/app/components/
|
|
268
|
-
"target": "app/components/
|
|
267
|
+
"path": "site-source/app/components/youtube/Embed.vue",
|
|
268
|
+
"target": "app/components/youtube/Embed.vue"
|
|
269
269
|
},
|
|
270
270
|
{
|
|
271
271
|
"path": "site-source/app/composables/useCheckout.ts",
|
|
@@ -364,8 +364,20 @@
|
|
|
364
364
|
"target": "app/theme/tooltip.ts"
|
|
365
365
|
},
|
|
366
366
|
{
|
|
367
|
-
"path": "site-source/app/types
|
|
368
|
-
"target": "app/types
|
|
367
|
+
"path": "site-source/app/consent/types.ts",
|
|
368
|
+
"target": "app/consent/types.ts"
|
|
369
|
+
},
|
|
370
|
+
{
|
|
371
|
+
"path": "site-source/app/content/types.ts",
|
|
372
|
+
"target": "app/content/types.ts"
|
|
373
|
+
},
|
|
374
|
+
{
|
|
375
|
+
"path": "site-source/app/navigation/types.ts",
|
|
376
|
+
"target": "app/navigation/types.ts"
|
|
377
|
+
},
|
|
378
|
+
{
|
|
379
|
+
"path": "site-source/app/site/config.ts",
|
|
380
|
+
"target": "app/site/config.ts"
|
|
369
381
|
}
|
|
370
382
|
],
|
|
371
383
|
"dependencies": [],
|
|
@@ -9,19 +9,19 @@
|
|
|
9
9
|
"name": "@stackonward/analytics-core",
|
|
10
10
|
"description": "Provider-neutral analytics pipeline and browser autocapture",
|
|
11
11
|
"type": "npm",
|
|
12
|
-
"version": "^0.
|
|
12
|
+
"version": "^0.3.0"
|
|
13
13
|
},
|
|
14
14
|
"@stackonward/analytics-nuxt": {
|
|
15
15
|
"name": "@stackonward/analytics-nuxt",
|
|
16
16
|
"description": "Provider-neutral Nuxt analytics lifecycle",
|
|
17
17
|
"type": "npm",
|
|
18
|
-
"version": "^0.
|
|
18
|
+
"version": "^0.2.0"
|
|
19
19
|
},
|
|
20
20
|
"@stackonward/cli": {
|
|
21
21
|
"name": "@stackonward/cli",
|
|
22
22
|
"description": "StackOnward project and resource CLI",
|
|
23
23
|
"type": "npm",
|
|
24
|
-
"version": "^1.
|
|
24
|
+
"version": "^1.4.0"
|
|
25
25
|
},
|
|
26
26
|
"@stackonward/cms-client": {
|
|
27
27
|
"name": "@stackonward/cms-client",
|
|
@@ -69,13 +69,13 @@
|
|
|
69
69
|
"name": "@stackonward/google-tag-manager-nuxt",
|
|
70
70
|
"description": "Consent-aware Google Tag Manager analytics integration for Nuxt",
|
|
71
71
|
"type": "npm",
|
|
72
|
-
"version": "^0.
|
|
72
|
+
"version": "^0.3.0"
|
|
73
73
|
},
|
|
74
74
|
"@stackonward/google-tag-manager": {
|
|
75
75
|
"name": "@stackonward/google-tag-manager",
|
|
76
76
|
"description": "Google Tag Manager transport and declarative container generator",
|
|
77
77
|
"type": "npm",
|
|
78
|
-
"version": "^0.
|
|
78
|
+
"version": "^0.2.0"
|
|
79
79
|
},
|
|
80
80
|
"@stackonward/identity-browser": {
|
|
81
81
|
"name": "@stackonward/identity-browser",
|
|
@@ -111,7 +111,7 @@
|
|
|
111
111
|
"name": "@stackonward/nuxt-site-shell",
|
|
112
112
|
"description": "Brand-free Nuxt product-site shell",
|
|
113
113
|
"type": "layer",
|
|
114
|
-
"version": "^0.
|
|
114
|
+
"version": "^0.3.0"
|
|
115
115
|
},
|
|
116
116
|
"@stackonward/onex-cms-client": {
|
|
117
117
|
"name": "@stackonward/onex-cms-client",
|
|
@@ -3,8 +3,8 @@
|
|
|
3
3
|
This template extends `@stackonward/nuxt-site-shell` for Nuxt module wiring and installs editable source from the component registry, so a new project starts with:
|
|
4
4
|
|
|
5
5
|
- Nuxt UI and Tailwind theme wiring.
|
|
6
|
-
- Local source files for
|
|
7
|
-
-
|
|
6
|
+
- Local source files for site, app and content shells under `app/layouts` and owner-scoped component directories.
|
|
7
|
+
- Owner-scoped components such as `UiButton`, `UiModal`, `UiText`, `UiPopover`, `GoogleSignInButton`, `YoutubeEmbed`, `UiInfiniteScroll`, `CheckoutSummary` and `CheckoutStatus`.
|
|
8
8
|
- Editable composables and plugins for Google Identity, consent presentation, privacy-enhanced YouTube embeds and provider-free checkout redirects.
|
|
9
9
|
- Versioned global analytics through `@stackonward/google-tag-manager-nuxt`, including consent gating, SPA page views, element/link autocapture, manual events and product-configurable capture rules.
|
|
10
10
|
- Local Nuxt UI theme overrides under `app/theme` and CSS tokens under `app/assets/css`.
|
|
@@ -16,7 +16,7 @@ Product-specific copy, assets, auth, analytics, CMS providers and business workf
|
|
|
16
16
|
|
|
17
17
|
Set `NUXT_PUBLIC_GTM_ID` to a published GTM container such as `GTM-ABC123`. The integration remains disabled when the ID is empty. The included consent UI restores the product-owned local decision and starts analytics only after acceptance.
|
|
18
18
|
|
|
19
|
-
Global capture defaults and product overrides live under `
|
|
19
|
+
Global capture defaults and product overrides live under `gtm.analytics` in `nuxt.config.ts`. Products can configure selectors, internal domains, tracked link types, module naming/rules, event names, device breakpoints and privacy-sensitive field capture. Business event names remain typed in product source.
|
|
20
20
|
|
|
21
21
|
Create a product-owned `analytics.google.json` with the GA4 measurement ID and any product event parameters, then generate the GTM import artifact without granting account credentials to the application:
|
|
22
22
|
|
|
@@ -7,7 +7,7 @@
|
|
|
7
7
|
"home": "Home",
|
|
8
8
|
"backToTop": "Back to top",
|
|
9
9
|
"skipToContent": "Skip to content",
|
|
10
|
-
"
|
|
10
|
+
"openSite": "View site",
|
|
11
11
|
"description": "A premium product media workspace for generating product images, campaign sets, and short-form ad videos."
|
|
12
12
|
},
|
|
13
13
|
"actions": {
|
|
@@ -26,7 +26,7 @@ useSeo({
|
|
|
26
26
|
<p>Production board</p>
|
|
27
27
|
<h1>Creative output queue</h1>
|
|
28
28
|
</div>
|
|
29
|
-
<
|
|
29
|
+
<UiButton label="New campaign" leading-icon="i-lucide-plus" />
|
|
30
30
|
</header>
|
|
31
31
|
|
|
32
32
|
<div class="workspace-page__grid">
|
|
@@ -27,11 +27,11 @@ useSeo({
|
|
|
27
27
|
</script>
|
|
28
28
|
|
|
29
29
|
<template>
|
|
30
|
-
<
|
|
30
|
+
<ContentList
|
|
31
31
|
:title="author"
|
|
32
32
|
description="Use this route shape for author profiles and authored content from the selected provider."
|
|
33
33
|
:items="posts"
|
|
34
34
|
>
|
|
35
35
|
<template #eyebrow>Author</template>
|
|
36
|
-
</
|
|
36
|
+
</ContentList>
|
|
37
37
|
</template>
|
|
@@ -36,10 +36,11 @@ useSeo({
|
|
|
36
36
|
</script>
|
|
37
37
|
|
|
38
38
|
<template>
|
|
39
|
-
<
|
|
39
|
+
<ContentArticle :article="article" :related="related">
|
|
40
40
|
<p>
|
|
41
41
|
A paid creative product needs content that sells outcomes before it explains implementation.
|
|
42
|
-
Use this article shape for launch guides, comparison pages, creator education, and SEO
|
|
42
|
+
Use this article shape for launch guides, comparison pages, creator education, and SEO
|
|
43
|
+
content.
|
|
43
44
|
</p>
|
|
44
45
|
<h2>Production Boundary</h2>
|
|
45
46
|
<p>
|
|
@@ -51,5 +52,5 @@ useSeo({
|
|
|
51
52
|
Use the SEO composable for page title, description, canonical path, robots rules, and social
|
|
52
53
|
image values so each campaign page can target a specific commercial search intent.
|
|
53
54
|
</p>
|
|
54
|
-
</
|
|
55
|
+
</ContentArticle>
|
|
55
56
|
</template>
|
|
@@ -28,11 +28,11 @@ useSeo({
|
|
|
28
28
|
</script>
|
|
29
29
|
|
|
30
30
|
<template>
|
|
31
|
-
<
|
|
31
|
+
<ContentList
|
|
32
32
|
:title="`${categoryLabel} resources`"
|
|
33
33
|
description="Use this route shape for product education, launch notes, and SEO category pages."
|
|
34
34
|
:items="posts"
|
|
35
35
|
>
|
|
36
36
|
<template #eyebrow>Category</template>
|
|
37
|
-
</
|
|
37
|
+
</ContentList>
|
|
38
38
|
</template>
|
|
@@ -36,11 +36,11 @@ useSeo({
|
|
|
36
36
|
</script>
|
|
37
37
|
|
|
38
38
|
<template>
|
|
39
|
-
<
|
|
39
|
+
<ContentList
|
|
40
40
|
title="Content hub"
|
|
41
41
|
description="Playbooks, production notes, and design-system guidance for a paid creative product."
|
|
42
42
|
:items="posts"
|
|
43
43
|
>
|
|
44
44
|
<template #eyebrow>Resources</template>
|
|
45
|
-
</
|
|
45
|
+
</ContentList>
|
|
46
46
|
</template>
|
|
@@ -10,7 +10,7 @@ useSeo({
|
|
|
10
10
|
</script>
|
|
11
11
|
|
|
12
12
|
<template>
|
|
13
|
-
<
|
|
13
|
+
<ContentDocument
|
|
14
14
|
:title="t('legal.cookies.title')"
|
|
15
15
|
:description="t('legal.cookies.description')"
|
|
16
16
|
:updated-at="t('legal.cookies.updated')"
|
|
@@ -52,7 +52,7 @@ useSeo({
|
|
|
52
52
|
<section>
|
|
53
53
|
<h2>{{ t("legal.cookies.choicesTitle") }}</h2>
|
|
54
54
|
<p>{{ t("legal.cookies.choices") }}</p>
|
|
55
|
-
<
|
|
55
|
+
<ConsentSettings />
|
|
56
56
|
</section>
|
|
57
57
|
|
|
58
58
|
<section>
|
|
@@ -64,5 +64,5 @@ useSeo({
|
|
|
64
64
|
<h2>{{ t("legal.cookies.contactTitle") }}</h2>
|
|
65
65
|
<p>{{ t("legal.cookies.contact") }}</p>
|
|
66
66
|
</section>
|
|
67
|
-
</
|
|
67
|
+
</ContentDocument>
|
|
68
68
|
</template>
|
|
@@ -7,7 +7,7 @@ useSeo({
|
|
|
7
7
|
</script>
|
|
8
8
|
|
|
9
9
|
<template>
|
|
10
|
-
<
|
|
10
|
+
<ContentDocument title="Privacy" description="Replace this sample with approved privacy text.">
|
|
11
11
|
<p>
|
|
12
12
|
This generated page provides structure only. Consumer projects must supply reviewed privacy
|
|
13
13
|
disclosures for their data collection, processors, and retention policy.
|
|
@@ -17,5 +17,5 @@ useSeo({
|
|
|
17
17
|
Add concrete categories of data, processing purposes, retention periods, user rights, contact
|
|
18
18
|
channels, and regional disclosures.
|
|
19
19
|
</p>
|
|
20
|
-
</
|
|
20
|
+
</ContentDocument>
|
|
21
21
|
</template>
|
|
@@ -7,7 +7,7 @@ useSeo({
|
|
|
7
7
|
</script>
|
|
8
8
|
|
|
9
9
|
<template>
|
|
10
|
-
<
|
|
10
|
+
<ContentDocument title="Terms" description="Replace this sample with approved legal text.">
|
|
11
11
|
<p>
|
|
12
12
|
This generated page provides structure only. Consumer projects must supply reviewed terms that
|
|
13
13
|
match their product, jurisdiction, and operating model.
|
|
@@ -17,5 +17,5 @@ useSeo({
|
|
|
17
17
|
Add the binding contract for account use, acceptable use, billing if applicable, termination,
|
|
18
18
|
and support channels.
|
|
19
19
|
</p>
|
|
20
|
-
</
|
|
20
|
+
</ContentDocument>
|
|
21
21
|
</template>
|
|
@@ -72,31 +72,31 @@ useSeo({
|
|
|
72
72
|
<div class="system-lab__header">
|
|
73
73
|
<p class="system-lab__eyebrow">Design system</p>
|
|
74
74
|
<h1>Reusable components tuned for premium paid conversion.</h1>
|
|
75
|
-
<
|
|
75
|
+
<UiText as="p" tone="muted" size="lg">
|
|
76
76
|
Buttons, inputs, identity, analytics, video, infinite lists, checkout, and text constraints
|
|
77
77
|
share the same mobile-first visual language.
|
|
78
|
-
</
|
|
78
|
+
</UiText>
|
|
79
79
|
</div>
|
|
80
80
|
|
|
81
81
|
<div class="system-lab__grid">
|
|
82
|
-
<
|
|
82
|
+
<UiGradientBorder radius="10px" class="system-lab__panel system-lab__panel--featured">
|
|
83
83
|
<div class="system-lab__panel-inner">
|
|
84
84
|
<div>
|
|
85
|
-
<
|
|
86
|
-
<
|
|
85
|
+
<UiText as="h2" size="xl" weight="bold">Actions</UiText>
|
|
86
|
+
<UiText as="p" tone="muted">
|
|
87
87
|
Primary actions are reserved for creation, checkout, and committed conversion steps.
|
|
88
|
-
</
|
|
88
|
+
</UiText>
|
|
89
89
|
</div>
|
|
90
90
|
<div class="system-lab__actions">
|
|
91
|
-
<
|
|
92
|
-
<
|
|
93
|
-
<
|
|
91
|
+
<UiButton label="Generate set" leading-icon="i-lucide-wand-sparkles" />
|
|
92
|
+
<UiButton label="Compare outputs" color="neutral" variant="outline" />
|
|
93
|
+
<UiButton label="Review brief" variant="soft" trailing-icon="i-lucide-arrow-right" />
|
|
94
94
|
</div>
|
|
95
95
|
</div>
|
|
96
|
-
</
|
|
96
|
+
</UiGradientBorder>
|
|
97
97
|
|
|
98
98
|
<section class="system-lab__panel">
|
|
99
|
-
<
|
|
99
|
+
<UiText as="h2" size="xl" weight="bold">Inputs</UiText>
|
|
100
100
|
<div class="system-lab__form">
|
|
101
101
|
<UInput icon="i-lucide-search" placeholder="Search campaign assets" />
|
|
102
102
|
<USelect v-model="selectedPlan" :items="planOptions" />
|
|
@@ -105,38 +105,38 @@ useSeo({
|
|
|
105
105
|
</section>
|
|
106
106
|
|
|
107
107
|
<section class="system-lab__panel">
|
|
108
|
-
<
|
|
109
|
-
<
|
|
108
|
+
<UiText as="h2" size="xl" weight="bold">Modal shell</UiText>
|
|
109
|
+
<UiText as="p" tone="muted">
|
|
110
110
|
The modal frame owns title, body, footer, close behavior, and scroll boundaries.
|
|
111
|
-
</
|
|
112
|
-
<
|
|
111
|
+
</UiText>
|
|
112
|
+
<UiButton
|
|
113
113
|
label="Open modal"
|
|
114
114
|
color="secondary"
|
|
115
115
|
variant="solid"
|
|
116
116
|
leading-icon="i-lucide-panel-top-open"
|
|
117
117
|
@click="modalOpen = true"
|
|
118
118
|
/>
|
|
119
|
-
<
|
|
119
|
+
<UiModal
|
|
120
120
|
v-model="modalOpen"
|
|
121
121
|
title="Approve campaign set"
|
|
122
122
|
description="Use slots for business-specific body and footer content."
|
|
123
123
|
>
|
|
124
124
|
<template #content>
|
|
125
|
-
<
|
|
125
|
+
<UiText as="p" tone="muted">
|
|
126
126
|
Campaign output is ready for review. The consuming product owns approval rules and
|
|
127
127
|
provider fulfillment.
|
|
128
|
-
</
|
|
128
|
+
</UiText>
|
|
129
129
|
</template>
|
|
130
130
|
<template #footer="{ close }">
|
|
131
|
-
<
|
|
132
|
-
<
|
|
131
|
+
<UiButton label="Close" color="neutral" variant="outline" @click="close" />
|
|
132
|
+
<UiButton label="Approve" @click="close" />
|
|
133
133
|
</template>
|
|
134
|
-
</
|
|
134
|
+
</UiModal>
|
|
135
135
|
</section>
|
|
136
136
|
|
|
137
137
|
<section class="system-lab__panel">
|
|
138
|
-
<
|
|
139
|
-
<
|
|
138
|
+
<UiText as="h2" size="xl" weight="bold">Popover actions</UiText>
|
|
139
|
+
<UiPopover
|
|
140
140
|
title="Quick actions"
|
|
141
141
|
description="Popover content and action rows share one base style."
|
|
142
142
|
:actions="[
|
|
@@ -145,24 +145,24 @@ useSeo({
|
|
|
145
145
|
]"
|
|
146
146
|
>
|
|
147
147
|
<template #reference>
|
|
148
|
-
<
|
|
148
|
+
<UiButton
|
|
149
149
|
label="Open actions"
|
|
150
150
|
variant="outline"
|
|
151
151
|
trailing-icon="i-lucide-chevron-down"
|
|
152
152
|
/>
|
|
153
153
|
</template>
|
|
154
|
-
</
|
|
154
|
+
</UiPopover>
|
|
155
155
|
</section>
|
|
156
156
|
|
|
157
157
|
<section class="system-lab__panel">
|
|
158
|
-
<
|
|
159
|
-
<
|
|
158
|
+
<UiText as="h2" size="xl" weight="bold">Identity and analytics</UiText>
|
|
159
|
+
<UiText as="p" tone="muted">
|
|
160
160
|
Google Identity and GA/GTM are config-driven, consent-aware, and replaceable at the
|
|
161
161
|
application boundary.
|
|
162
|
-
</
|
|
162
|
+
</UiText>
|
|
163
163
|
<div class="system-lab__actions system-lab__actions--stacked">
|
|
164
164
|
<GoogleSignInButton />
|
|
165
|
-
<
|
|
165
|
+
<UiButton
|
|
166
166
|
label="Track preview event"
|
|
167
167
|
color="neutral"
|
|
168
168
|
variant="outline"
|
|
@@ -173,13 +173,13 @@ useSeo({
|
|
|
173
173
|
</section>
|
|
174
174
|
|
|
175
175
|
<section class="system-lab__panel">
|
|
176
|
-
<
|
|
176
|
+
<UiText as="h2" size="xl" weight="bold">Video embed</UiText>
|
|
177
177
|
<YoutubeEmbed source="dQw4w9WgXcQ" title="Reusable YouTube embed" />
|
|
178
178
|
</section>
|
|
179
179
|
|
|
180
180
|
<section class="system-lab__panel">
|
|
181
|
-
<
|
|
182
|
-
<
|
|
181
|
+
<UiText as="h2" size="xl" weight="bold">Infinite list</UiText>
|
|
182
|
+
<UiInfiniteScroll
|
|
183
183
|
:loading="infiniteLoading"
|
|
184
184
|
:has-more="hasMoreInfiniteItems"
|
|
185
185
|
root-margin="180px 0px"
|
|
@@ -187,20 +187,20 @@ useSeo({
|
|
|
187
187
|
>
|
|
188
188
|
<ul class="system-lab__list">
|
|
189
189
|
<li v-for="item in visibleInfiniteItems" :key="item.id" class="system-lab__list-item">
|
|
190
|
-
<
|
|
191
|
-
<
|
|
190
|
+
<UiText weight="semibold">{{ item.title }}</UiText>
|
|
191
|
+
<UiText as="p" tone="muted" size="sm">{{ item.summary }}</UiText>
|
|
192
192
|
</li>
|
|
193
193
|
</ul>
|
|
194
|
-
</
|
|
194
|
+
</UiInfiniteScroll>
|
|
195
195
|
</section>
|
|
196
196
|
|
|
197
197
|
<section class="system-lab__panel">
|
|
198
|
-
<
|
|
198
|
+
<UiText as="h2" size="xl" weight="bold">Checkout status</UiText>
|
|
199
199
|
<CheckoutStatus status="pending" show-idle />
|
|
200
200
|
</section>
|
|
201
201
|
|
|
202
202
|
<section class="system-lab__panel system-lab__panel--wide">
|
|
203
|
-
<
|
|
203
|
+
<UiText as="h2" size="xl" weight="bold">Checkout summary</UiText>
|
|
204
204
|
<div class="system-lab__checkout-grid">
|
|
205
205
|
<CheckoutSummary
|
|
206
206
|
attempt-id="campaign-checkout"
|
|
@@ -209,27 +209,27 @@ useSeo({
|
|
|
209
209
|
@checkout="checkoutUrlPreview = $event"
|
|
210
210
|
/>
|
|
211
211
|
<div class="system-lab__preview">
|
|
212
|
-
<
|
|
213
|
-
<
|
|
212
|
+
<UiText as="h3" size="lg" weight="bold">Generated checkout URL</UiText>
|
|
213
|
+
<UiText as="p" tone="muted" size="sm">
|
|
214
214
|
Product apps own session creation and provider fulfillment; this layer owns the
|
|
215
215
|
reusable URL and summary frame.
|
|
216
|
-
</
|
|
216
|
+
</UiText>
|
|
217
217
|
<code>{{ checkoutUrlPreview || "Click the checkout action to generate a URL." }}</code>
|
|
218
218
|
</div>
|
|
219
219
|
</div>
|
|
220
220
|
</section>
|
|
221
221
|
|
|
222
222
|
<section class="system-lab__panel system-lab__panel--wide">
|
|
223
|
-
<
|
|
223
|
+
<UiText as="h2" size="xl" weight="bold">Text constraints</UiText>
|
|
224
224
|
<div class="system-lab__text-row">
|
|
225
|
-
<
|
|
225
|
+
<UiText truncate>
|
|
226
226
|
Long generated asset labels stay inside their container without resizing navigation or
|
|
227
227
|
checkout rows.
|
|
228
|
-
</
|
|
229
|
-
<
|
|
228
|
+
</UiText>
|
|
229
|
+
<UiText :line-clamp="2" tone="muted">
|
|
230
230
|
Multi-line campaign summaries can be clamped by the reusable text component so compact
|
|
231
231
|
cards, popovers, and tables remain stable.
|
|
232
|
-
</
|
|
232
|
+
</UiText>
|
|
233
233
|
</div>
|
|
234
234
|
</section>
|
|
235
235
|
</div>
|