@docsector/docsector-reader 3.6.0 → 4.0.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.
Files changed (47) hide show
  1. package/README.md +10 -11
  2. package/bin/docsector.js +1 -283
  3. package/package.json +1 -1
  4. package/src/components/{DPageBlockquote.vue → DBlockBlockquote.vue} +4 -0
  5. package/src/components/{DBlockCard.vue → DBlockCards.vue} +1 -1
  6. package/src/components/{DPageEmbeddedUrl.vue → DBlockEmbeddedUrl.vue} +1 -1
  7. package/src/components/{DPageExpandable.vue → DBlockExpandable.vue} +4 -0
  8. package/src/components/{DPageFile.vue → DBlockFile.vue} +1 -1
  9. package/src/components/{DPageImage.vue → DBlockImage.vue} +1 -1
  10. package/src/components/{DMermaidDiagram.vue → DBlockMermaidDiagram.vue} +4 -0
  11. package/src/components/{DQuickLinks.vue → DBlockQuickLinks.vue} +4 -0
  12. package/src/components/{DPageSourceCode.vue → DBlockSourceCode.vue} +6 -1
  13. package/src/components/DBlockStepper.vue +210 -0
  14. package/src/components/DBlockTimeline.vue +319 -0
  15. package/src/components/DPageTokens.vue +46 -20
  16. package/src/components/page-section-tokens.js +273 -10
  17. package/src/i18n/languages/en-US.hjson +5 -0
  18. package/src/i18n/languages/pt-BR.hjson +5 -0
  19. package/src/pages/guide/i18n-and-markdown.overview.en-US.md +6 -6
  20. package/src/pages/guide/i18n-and-markdown.overview.pt-BR.md +6 -6
  21. package/src/pages/guide/theming.overview.en-US.md +1 -1
  22. package/src/pages/guide/theming.overview.pt-BR.md +1 -1
  23. package/src/pages/manual/content/blocks/embedded-urls.overview.en-US.md +3 -3
  24. package/src/pages/manual/content/blocks/embedded-urls.overview.pt-BR.md +3 -3
  25. package/src/pages/manual/content/blocks/embedded-urls.showcase.en-US.md +8 -8
  26. package/src/pages/manual/content/blocks/embedded-urls.showcase.pt-BR.md +8 -8
  27. package/src/pages/manual/content/blocks/expandable.overview.en-US.md +8 -8
  28. package/src/pages/manual/content/blocks/expandable.overview.pt-BR.md +8 -8
  29. package/src/pages/manual/content/blocks/expandable.showcase.en-US.md +6 -6
  30. package/src/pages/manual/content/blocks/expandable.showcase.pt-BR.md +6 -6
  31. package/src/pages/manual/content/blocks/files.overview.en-US.md +3 -3
  32. package/src/pages/manual/content/blocks/files.overview.pt-BR.md +3 -3
  33. package/src/pages/manual/content/blocks/files.showcase.en-US.md +5 -5
  34. package/src/pages/manual/content/blocks/files.showcase.pt-BR.md +5 -5
  35. package/src/pages/manual/content/blocks/quick-links.overview.en-US.md +4 -4
  36. package/src/pages/manual/content/blocks/quick-links.overview.pt-BR.md +4 -4
  37. package/src/pages/manual/content/blocks/quick-links.showcase.en-US.md +9 -9
  38. package/src/pages/manual/content/blocks/quick-links.showcase.pt-BR.md +9 -9
  39. package/src/pages/manual/content/blocks/stepper.overview.en-US.md +59 -0
  40. package/src/pages/manual/content/blocks/stepper.overview.pt-BR.md +59 -0
  41. package/src/pages/manual/content/blocks/stepper.showcase.en-US.md +115 -0
  42. package/src/pages/manual/content/blocks/stepper.showcase.pt-BR.md +115 -0
  43. package/src/pages/manual/content/blocks/timeline.overview.en-US.md +47 -0
  44. package/src/pages/manual/content/blocks/timeline.overview.pt-BR.md +47 -0
  45. package/src/pages/manual/content/blocks/timeline.showcase.en-US.md +170 -0
  46. package/src/pages/manual/content/blocks/timeline.showcase.pt-BR.md +170 -0
  47. package/src/pages/manual.index.js +56 -0
package/README.md CHANGED
@@ -64,17 +64,16 @@ Transform Markdown content into beautiful, navigable documentation sites — wit
64
64
  - 📅 **Last Updated Date** — Automatic per-page "last updated" date from git commit history, locale-formatted
65
65
  - 📊 **Translation Progress** — Automatic translation percentage based on header coverage
66
66
  - 🌐 **Accurate Available Translations** — Locale availability counter now uses actual localized page source presence, avoiding false negatives when metadata is equal
67
- - 🧠 **Markdown Negotiation** — Responds with Markdown when clients send `Accept: text/markdown`, while keeping HTML as browser default
68
- - 🔐 **Web Bot Auth** — Can publish a signed HTTP message signatures directory and includes helpers to sign outbound bot requests
69
- - 🧭 **Content Signals** — Injects `Content-Signal` policy in `robots.txt` with deterministic, idempotent build output
70
67
  - 🏠 **Markdown Home at Root** — Homepage is rendered from `src/pages/Homepage.{lang}.md` directly at `/`
71
68
  - 🌍 **Remote README as Home** — Optional build-time remote README source for homepage with automatic local fallback
72
69
  - 🔗 **GitHub-Compatible Heading Anchors** — Markdown headings use GitHub-style slugs so standard README Table of Contents links work inside Docsector
73
70
  - 🧬 **Scaffolded Homepage Override Wiring** — New consumer projects automatically wire `virtual:docsector-homepage-override` into i18n message building
74
- - 📖 **Expandable Markdown Sections** — Use `<d-expandable title="...">...</d-expandable>` to collapse secondary content while keeping rich Markdown support inside the body
75
- - 📎 **File Attachment Blocks** — Use `<d-file src="/files/...">...</d-file>` in Markdown to render downloadable file cards with automatic local size detection and support for external URLs
76
- - 🌐 **Embedded URL Blocks** — Use `<d-embedded-url url="https://...">...</d-embedded-url>` to render curated embeds for YouTube, Vimeo, Spotify, and CodePen with a safe link-card fallback for unsupported URLs
77
- - 🧭 **Quick Links Custom Element** — Use `<d-quick-links>` and `<d-quick-link>` in Markdown to render rich home navigation cards
71
+ - 📖 **Expandable Markdown Sections** — Use `<d-block-expandable title="...">...</d-block-expandable>` to collapse secondary content while keeping rich Markdown support inside the body
72
+ - 1️⃣ **Stepper Guides** — Use `<d-block-stepper>` with nested `<d-block-step title="...">...</d-block-step>` items to render native Quasar vertical steppers with rich Markdown and optional per-step icon overrides
73
+ - 🕒 **Timeline Updates** — Use `<d-block-timeline>` with nested `<d-block-timeline-item date="...">...</d-block-timeline-item>` entries and optional `<d-block-timeline-tag>` labels to publish GitBook-inspired changelog items with direct-link anchors, tag icons/colors, and rich Markdown bodies
74
+ - 📎 **File Attachment Blocks** — Use `<d-block-file src="/files/...">...</d-block-file>` in Markdown to render downloadable file cards with automatic local size detection and support for external URLs
75
+ - 🌐 **Embedded URL Blocks** — Use `<d-block-embedded-url url="https://...">...</d-block-embedded-url>` to render curated embeds for YouTube, Vimeo, Spotify, and CodePen with a safe link-card fallback for unsupported URLs
76
+ - 🧭 **Quick Links Custom Element** — Use `<d-block-quick-links>` and `<d-block-quick-link>` in Markdown to render rich home navigation cards
78
77
  - 🗂️ **Cards Custom Element** — Use `<d-block-cards>` and `<d-block-card>` in Markdown to render linked content cards with optional cover images
79
78
  - 🗂️ **API Catalog Well-Known** — Auto-generates `/.well-known/api-catalog` as Linkset JSON for machine-readable API discovery
80
79
  - 🗃️ **Multi-Version History** — Archive older major versions under `src/pages/.old/<version>/` and expose them at prefixed routes (e.g. `/v0.x/guide/...`) while keeping the current docs at unprefixed routes
@@ -1026,9 +1025,9 @@ Regular blockquotes without `[!TYPE]` continue to work normally.
1026
1025
  ### File Attachment Blocks
1027
1026
 
1028
1027
  ```html
1029
- <d-file src="/files/manual/release-checklist.txt" title="Release checklist" size="1 KB">
1028
+ <d-block-file src="/files/manual/release-checklist.txt" title="Release checklist" size="1 KB">
1030
1029
  Download the example file bundled with the docs.
1031
- </d-file>
1030
+ </d-block-file>
1032
1031
  ```
1033
1032
 
1034
1033
  Notes:
@@ -1041,9 +1040,9 @@ Notes:
1041
1040
  ### Embedded URL Blocks
1042
1041
 
1043
1042
  ```html
1044
- <d-embedded-url url="https://www.youtube.com/watch?v=M7lc1UVf-VE" title="YouTube player demo">
1043
+ <d-block-embedded-url url="https://www.youtube.com/watch?v=M7lc1UVf-VE" title="YouTube player demo">
1045
1044
  Optional caption rendered as inline Markdown.
1046
- </d-embedded-url>
1045
+ </d-block-embedded-url>
1047
1046
  ```
1048
1047
 
1049
1048
  Notes:
package/bin/docsector.js CHANGED
@@ -23,7 +23,7 @@ const packageRoot = resolve(__dirname, '..')
23
23
  const args = process.argv.slice(2)
24
24
  const command = args[0]
25
25
 
26
- const VERSION = '3.6.0'
26
+ const VERSION = '4.0.0'
27
27
 
28
28
  const HELP = `
29
29
  Docsector Reader v${VERSION}
@@ -488,288 +488,6 @@ Docsector Reader is a markdown-first documentation engine.
488
488
  - Repository: [docsector/docsector-reader](https://github.com/docsector/docsector-reader)
489
489
  `
490
490
 
491
- const TEMPLATE_BOOT_PAGE = `\
492
- <template>
493
- <q-page-container>
494
- <q-page class="boot-page">
495
- <!-- Hero Section -->
496
- <div class="hero-section">
497
- <div class="hero-content">
498
- <div class="hero-icon-container">
499
- <q-icon name="auto_stories" size="64px" color="white" />
500
- </div>
501
- <h1 class="hero-title">{{ projectName }}</h1>
502
- <p class="hero-subtitle">{{ $t('_.home.texts[0]') }}{{ projectName }}</p>
503
- <p class="hero-description">{{ $t('_.home.texts[2]') }}</p>
504
- <div class="hero-actions">
505
- <q-btn
506
- unelevated
507
- color="white"
508
- text-color="primary"
509
- label="Get Started"
510
- icon="rocket_launch"
511
- to="/guide/getting-started/overview"
512
- class="hero-btn"
513
- size="lg"
514
- no-caps
515
- />
516
- <q-btn
517
- v-if="projectUrl !== '#'"
518
- outline
519
- color="white"
520
- label="GitHub"
521
- icon="fab fa-github"
522
- @click="openURL(projectUrl)"
523
- class="hero-btn"
524
- size="lg"
525
- no-caps
526
- />
527
- </div>
528
- </div>
529
- </div>
530
-
531
- <!-- Features Section -->
532
- <div class="features-section">
533
- <div class="features-grid">
534
- <div class="feature-card">
535
- <q-icon name="edit_note" size="40px" color="primary" />
536
- <h3>Markdown Powered</h3>
537
- <p>Write your documentation in Markdown. Pages are automatically converted into beautiful, navigable content.</p>
538
- </div>
539
- <div class="feature-card">
540
- <q-icon name="translate" size="40px" color="primary" />
541
- <h3>Multi-language</h3>
542
- <p>Built-in i18n support. Add translations by creating locale files — no extra configuration needed.</p>
543
- </div>
544
- <div class="feature-card">
545
- <q-icon name="palette" size="40px" color="primary" />
546
- <h3>Beautiful UI</h3>
547
- <p>Powered by Quasar Framework. Responsive, accessible, and production-ready out of the box.</p>
548
- </div>
549
- <div class="feature-card">
550
- <q-icon name="bolt" size="40px" color="primary" />
551
- <h3>Lightning Fast</h3>
552
- <p>Vite-powered dev server with hot-reload. See your changes instantly as you write.</p>
553
- </div>
554
- <div class="feature-card">
555
- <q-icon name="search" size="40px" color="primary" />
556
- <h3>Full-text Search</h3>
557
- <p>Instant client-side search across all your documentation pages and translations.</p>
558
- </div>
559
- <div class="feature-card">
560
- <q-icon name="settings" size="40px" color="primary" />
561
- <h3>Easy Configuration</h3>
562
- <p>One config file for branding, links, languages, and GitHub integration.</p>
563
- </div>
564
- </div>
565
- </div>
566
-
567
- <!-- Quick Start Section -->
568
- <div class="quickstart-section">
569
- <h2 class="section-title">Quick Links</h2>
570
- <div class="quickstart-grid">
571
- <q-card flat bordered class="quickstart-card" clickable @click="$router.push('/guide/getting-started/overview')">
572
- <q-card-section horizontal>
573
- <q-card-section class="flex flex-center" style="width: 60px;">
574
- <q-icon name="flag" size="28px" color="primary" />
575
- </q-card-section>
576
- <q-card-section>
577
- <div class="text-subtitle1 text-weight-bold">Getting Started</div>
578
- <div class="text-caption text-grey-7">Installation, setup, and your first page</div>
579
- </q-card-section>
580
- <q-space />
581
- <q-card-section class="flex flex-center">
582
- <q-icon name="chevron_right" color="grey-5" />
583
- </q-card-section>
584
- </q-card-section>
585
- </q-card>
586
- </div>
587
- </div>
588
-
589
- <!-- Footer -->
590
- <div class="boot-footer">
591
- <p>{{ $t('_.home.texts[1]') }}
592
- <a :href="projectUrl" target="_blank" class="footer-link">Docsector Reader</a>
593
- </p>
594
- </div>
595
- </q-page>
596
- </q-page-container>
597
- </template>
598
-
599
- <script setup>
600
- import { openURL } from 'quasar'
601
- import docsectorConfig from 'docsector.config.js'
602
-
603
- defineOptions({ name: 'BootPage' })
604
-
605
- const projectName = docsectorConfig.branding?.name || 'My Documentation'
606
- const projectUrl = docsectorConfig.links?.github || '#'
607
- </script>
608
-
609
- <style lang="sass" scoped>
610
- .boot-page
611
- padding: 0 !important
612
-
613
- // Hero
614
- .hero-section
615
- background: linear-gradient(135deg, #655529 0%, #8b7340 50%, #a08850 100%)
616
- color: white
617
- padding: 80px 24px 60px
618
- text-align: center
619
- position: relative
620
- overflow: hidden
621
-
622
- &::before
623
- content: ''
624
- position: absolute
625
- top: -50%
626
- left: -50%
627
- width: 200%
628
- height: 200%
629
- background: radial-gradient(circle, rgba(255,255,255,0.05) 0%, transparent 60%)
630
- animation: pulse 8s ease-in-out infinite
631
-
632
- @keyframes pulse
633
- 0%, 100%
634
- transform: scale(1)
635
- 50%
636
- transform: scale(1.1)
637
-
638
- .hero-content
639
- position: relative
640
- z-index: 1
641
- max-width: 700px
642
- margin: 0 auto
643
-
644
- .hero-icon-container
645
- margin-bottom: 24px
646
- .q-icon
647
- opacity: 0.9
648
-
649
- .hero-title
650
- font-size: 2.8rem
651
- font-weight: 700
652
- margin: 0 0 12px
653
- line-height: 1.2
654
- letter-spacing: -0.02em
655
-
656
- .hero-subtitle
657
- font-size: 1.2rem
658
- opacity: 0.9
659
- margin: 0 0 8px
660
- font-weight: 400
661
-
662
- .hero-description
663
- font-size: 1rem
664
- opacity: 0.7
665
- margin: 0 0 32px
666
-
667
- .hero-actions
668
- display: flex
669
- gap: 16px
670
- justify-content: center
671
- flex-wrap: wrap
672
-
673
- .hero-btn
674
- border-radius: 8px
675
- padding: 8px 28px
676
- font-weight: 600
677
-
678
- // Features
679
- .features-section
680
- padding: 60px 24px
681
- max-width: 1100px
682
- margin: 0 auto
683
-
684
- .features-grid
685
- display: grid
686
- grid-template-columns: repeat(auto-fit, minmax(280px, 1fr))
687
- gap: 24px
688
-
689
- .feature-card
690
- padding: 28px 24px
691
- border-radius: 12px
692
- border: 1px solid #e8e8e8
693
- transition: transform 0.2s, box-shadow 0.2s
694
- text-align: center
695
-
696
- &:hover
697
- transform: translateY(-4px)
698
- box-shadow: 0 8px 25px rgba(0,0,0,0.08)
699
-
700
- h3
701
- font-size: 1.1rem
702
- font-weight: 600
703
- margin: 16px 0 8px
704
- color: #333
705
-
706
- p
707
- font-size: 0.9rem
708
- color: #666
709
- line-height: 1.5
710
- margin: 0
711
-
712
- // Quick Start
713
- .quickstart-section
714
- padding: 40px 24px 60px
715
- max-width: 700px
716
- margin: 0 auto
717
-
718
- .section-title
719
- font-size: 1.6rem
720
- font-weight: 700
721
- text-align: center
722
- margin: 0 0 24px
723
- color: #333
724
-
725
- .quickstart-grid
726
- display: flex
727
- flex-direction: column
728
- gap: 12px
729
-
730
- .quickstart-card
731
- border-radius: 10px
732
- transition: box-shadow 0.2s
733
- cursor: pointer
734
-
735
- &:hover
736
- box-shadow: 0 4px 15px rgba(0,0,0,0.1)
737
-
738
- // Footer
739
- .boot-footer
740
- text-align: center
741
- padding: 24px
742
- border-top: 1px solid #e8e8e8
743
- color: #999
744
- font-size: 0.85rem
745
-
746
- .footer-link
747
- color: #655529
748
- text-decoration: none
749
- font-weight: 500
750
-
751
- &:hover
752
- text-decoration: underline
753
-
754
- // Dark mode
755
- body.body--dark
756
- .feature-card
757
- border-color: #333
758
- h3
759
- color: #e0e0e0
760
- p
761
- color: #aaa
762
-
763
- .section-title
764
- color: #e0e0e0
765
-
766
- .boot-footer
767
- border-color: #333
768
- .footer-link
769
- color: #c4a856
770
- </style>
771
- `
772
-
773
491
  const TEMPLATE_404_PAGE = `\
774
492
  <template>
775
493
  <q-page-container>
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@docsector/docsector-reader",
3
- "version": "3.6.0",
3
+ "version": "4.0.0",
4
4
  "description": "A documentation rendering engine built with Vue 3, Quasar v2 and Vite. Transform Markdown into beautiful, navigable documentation sites.",
5
5
  "productName": "Docsector Reader",
6
6
  "author": "Rodrigo de Araujo Vieira",
@@ -2,6 +2,10 @@
2
2
  // defineProps is a compiler macro in <script setup>, no import needed
3
3
  import { computed } from 'vue'
4
4
 
5
+ defineOptions({
6
+ name: 'DBlockBlockquote'
7
+ })
8
+
5
9
  const props = defineProps({
6
10
  message: {
7
11
  type: String,
@@ -2,7 +2,7 @@
2
2
  const BASE_URL = import.meta.env.BASE_URL || '/'
3
3
 
4
4
  defineOptions({
5
- name: 'DBlockCard'
5
+ name: 'DBlockCards'
6
6
  })
7
7
 
8
8
  const props = defineProps({
@@ -5,7 +5,7 @@ import { useI18n } from 'vue-i18n'
5
5
  import { resolveEmbeddedUrl } from '../composables/useEmbeddedUrl'
6
6
 
7
7
  defineOptions({
8
- name: 'DPageEmbeddedUrl'
8
+ name: 'DBlockEmbeddedUrl'
9
9
  })
10
10
 
11
11
  const props = defineProps({
@@ -1,4 +1,8 @@
1
1
  <script setup>
2
+ defineOptions({
3
+ name: 'DBlockExpandable'
4
+ })
5
+
2
6
  defineProps({
3
7
  title: {
4
8
  type: String,
@@ -8,7 +8,7 @@ import { resolveFileIconUrl } from '../composables/useFileIcon'
8
8
  const BASE_URL = import.meta.env.BASE_URL || '/'
9
9
 
10
10
  defineOptions({
11
- name: 'DPageFile'
11
+ name: 'DBlockFile'
12
12
  })
13
13
 
14
14
  const props = defineProps({
@@ -2,7 +2,7 @@
2
2
  import { computed } from 'vue'
3
3
 
4
4
  defineOptions({
5
- name: 'DPageImage'
5
+ name: 'DBlockImage'
6
6
  })
7
7
 
8
8
  const props = defineProps({
@@ -2,6 +2,10 @@
2
2
  import { ref, onMounted, watch } from 'vue'
3
3
  import { useQuasar } from 'quasar'
4
4
 
5
+ defineOptions({
6
+ name: 'DBlockMermaidDiagram'
7
+ })
8
+
5
9
  const props = defineProps({
6
10
  content: {
7
11
  type: String,
@@ -1,4 +1,8 @@
1
1
  <script setup>
2
+ defineOptions({
3
+ name: 'DBlockQuickLinks'
4
+ })
5
+
2
6
  const props = defineProps({
3
7
  items: {
4
8
  type: Array,
@@ -11,6 +11,10 @@ import 'prismjs/components/prism-php'
11
11
  import 'prismjs/components/prism-bash'
12
12
  import { looksLikeFileName, resolveFileIconUrl } from '../composables/useFileIcon'
13
13
 
14
+ defineOptions({
15
+ name: 'DBlockSourceCode'
16
+ })
17
+
14
18
  const props = defineProps({
15
19
  index: {
16
20
  type: Number,
@@ -504,11 +508,12 @@ function printToLetter(number) {
504
508
  padding: 0
505
509
 
506
510
  .lines
507
- padding: 11px 5px 8px 5px
511
+ padding: 10px 5px 10px 5px
508
512
  text-align: right
509
513
  float: left
510
514
  -webkit-user-select: none
511
515
  user-select: none
516
+ line-height: 19px
512
517
 
513
518
  a
514
519
  display: block
@@ -0,0 +1,210 @@
1
+ <script setup>
2
+ import { computed, ref, watch } from 'vue'
3
+ import { useI18n } from 'vue-i18n'
4
+
5
+ defineOptions({
6
+ name: 'DBlockStepper'
7
+ })
8
+
9
+ const props = defineProps({
10
+ steps: {
11
+ type: Array,
12
+ default: () => []
13
+ }
14
+ })
15
+
16
+ const { t } = useI18n()
17
+ const currentStep = ref(1)
18
+ const isFinished = ref(false)
19
+ const stepCount = computed(() => props.steps.length)
20
+
21
+ watch(stepCount, (count) => {
22
+ if (count < 1) {
23
+ currentStep.value = 1
24
+ isFinished.value = false
25
+ return
26
+ }
27
+
28
+ if (currentStep.value > count) {
29
+ currentStep.value = count
30
+ }
31
+ }, { immediate: true })
32
+
33
+ const isLastStep = (index) => index === props.steps.length - 1
34
+ const hasDefaultIcon = (step) => typeof step?.icon === 'string' && step.icon !== '' && step.icon !== 'none'
35
+ const stepPrefix = (step, index) => hasDefaultIcon(step) ? void 0 : String(index + 1)
36
+ const isStepDone = (index) => isFinished.value || currentStep.value > index + 1
37
+
38
+ const goToStep = (stepNumber) => {
39
+ if (stepNumber < 1 || stepNumber > props.steps.length) {
40
+ return
41
+ }
42
+
43
+ isFinished.value = false
44
+ currentStep.value = stepNumber
45
+ }
46
+
47
+ const finishStepper = () => {
48
+ isFinished.value = true
49
+ currentStep.value = null
50
+ }
51
+ </script>
52
+
53
+ <template>
54
+ <div v-if="steps.length" class="d-stepper">
55
+ <q-stepper
56
+ v-model="currentStep"
57
+ vertical
58
+ animated
59
+ flat
60
+ bordered
61
+ header-nav
62
+ color="primary"
63
+ active-color="primary"
64
+ done-color="positive"
65
+ inactive-color="grey-6"
66
+ class="d-stepper__shell"
67
+ >
68
+ <q-step
69
+ v-for="(step, index) in steps"
70
+ :key="`${step.title}-${index}`"
71
+ :name="index + 1"
72
+ :title="step.title"
73
+ :prefix="stepPrefix(step, index)"
74
+ :icon="step.icon || void 0"
75
+ :active-icon="step.activeIcon || step.icon || void 0"
76
+ :done-icon="step.doneIcon || step.icon || void 0"
77
+ :error-icon="step.errorIcon || step.icon || void 0"
78
+ :done="isStepDone(index)"
79
+ header-class="d-stepper__step-header"
80
+ class="d-stepper__step"
81
+ >
82
+ <div class="d-stepper__body">
83
+ <slot :step="step" :index="index" />
84
+ </div>
85
+
86
+ <q-stepper-navigation class="d-stepper__navigation">
87
+ <q-btn
88
+ v-if="!isLastStep(index)"
89
+ color="primary"
90
+ no-caps
91
+ unelevated
92
+ :label="t('page.stepper.continue')"
93
+ @click="goToStep(index + 2)"
94
+ />
95
+
96
+ <q-btn
97
+ v-else
98
+ color="positive"
99
+ no-caps
100
+ unelevated
101
+ :label="t('page.stepper.finish')"
102
+ @click="finishStepper"
103
+ />
104
+
105
+ <q-btn
106
+ v-if="index > 0"
107
+ unelevated
108
+ no-caps
109
+ class="d-stepper__back d-stepper__secondary-action"
110
+ :label="t('page.stepper.back')"
111
+ @click="goToStep(index)"
112
+ />
113
+ </q-stepper-navigation>
114
+ </q-step>
115
+ </q-stepper>
116
+ </div>
117
+ </template>
118
+
119
+ <style lang="sass">
120
+ body.body--light
121
+ --d-stepper-shell-bg: #fffdfa
122
+ --d-stepper-shell-border: rgba(123, 94, 45, 0.16)
123
+ --d-stepper-shell-shadow: rgba(94, 73, 37, 0.08)
124
+ --d-stepper-header-bg: rgba(255, 242, 212, 0.32)
125
+ --d-stepper-divider: rgba(123, 94, 45, 0.14)
126
+ --d-stepper-text-muted: #5f6772
127
+ --d-stepper-secondary-bg: rgba(123, 94, 45, 0.12)
128
+ --d-stepper-secondary-bg-hover: rgba(123, 94, 45, 0.18)
129
+ --d-stepper-secondary-text: #705420
130
+
131
+ body.body--dark
132
+ --d-stepper-shell-bg: rgba(255, 248, 235, 0.04)
133
+ --d-stepper-shell-border: rgba(255, 235, 194, 0.12)
134
+ --d-stepper-shell-shadow: rgba(0, 0, 0, 0.28)
135
+ --d-stepper-header-bg: rgba(255, 240, 210, 0.04)
136
+ --d-stepper-divider: rgba(255, 235, 194, 0.08)
137
+ --d-stepper-text-muted: rgba(255, 255, 255, 0.72)
138
+ --d-stepper-secondary-bg: rgba(255, 235, 194, 0.1)
139
+ --d-stepper-secondary-bg-hover: rgba(255, 235, 194, 0.16)
140
+ --d-stepper-secondary-text: #f4ddb0
141
+
142
+ .d-stepper
143
+ margin: 1.5rem 0
144
+
145
+ .d-stepper__shell
146
+ border-radius: 20px
147
+ overflow: hidden
148
+ background: var(--d-stepper-shell-bg)
149
+ border-color: var(--d-stepper-shell-border)
150
+ box-shadow: 0 16px 36px var(--d-stepper-shell-shadow)
151
+
152
+ .d-stepper__shell.q-stepper--vertical
153
+ .q-stepper__header
154
+ background: var(--d-stepper-header-bg)
155
+
156
+ .q-stepper__tab
157
+ min-height: 72px
158
+
159
+ .q-stepper__step-inner
160
+ border-top: 1px solid var(--d-stepper-divider)
161
+
162
+ .q-stepper__title
163
+ font-size: 1rem
164
+ font-weight: 700
165
+ line-height: 1.45
166
+
167
+ .q-stepper__caption
168
+ color: var(--d-stepper-text-muted)
169
+
170
+ .d-stepper__step-header
171
+ font-weight: 700
172
+
173
+ .d-stepper__body
174
+ min-width: 0
175
+ padding-top: 0.85rem
176
+
177
+ > :first-child
178
+ margin-top: 0
179
+
180
+ > :last-child
181
+ margin-bottom: 0
182
+
183
+ .d-stepper__navigation
184
+ display: flex
185
+ flex-wrap: wrap
186
+ gap: 0.75rem
187
+ margin-top: 1rem
188
+
189
+ .d-stepper__back
190
+ margin-left: 0 !important
191
+
192
+ .d-stepper__secondary-action
193
+ background: var(--d-stepper-secondary-bg) !important
194
+ color: var(--d-stepper-secondary-text) !important
195
+
196
+ &:hover,
197
+ &:focus-visible
198
+ background: var(--d-stepper-secondary-bg-hover) !important
199
+
200
+ @media (max-width: 599px)
201
+ .d-stepper__shell.q-stepper--vertical
202
+ .q-stepper__tab
203
+ min-height: 64px
204
+
205
+ .q-stepper__title
206
+ font-size: 0.97rem
207
+
208
+ .d-stepper__navigation
209
+ gap: 0.55rem
210
+ </style>