srcdev-nuxt-components 9.4.9 → 9.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.
Files changed (112) hide show
  1. package/.claude/commands/migrate-component.md +20 -6
  2. package/.claude/component-ledger/audit.json +1 -1
  3. package/.claude/component-ledger/build.mjs +26 -0
  4. package/.claude/component-ledger/output.html +8 -3
  5. package/.claude/component-ledger/template.html +7 -2
  6. package/.claude/skills/component-dynamic-slots.md +1 -1
  7. package/.claude/skills/components/alert-mask-core.md +84 -0
  8. package/.claude/skills/components/canvas-switcher.md +1 -1
  9. package/.claude/skills/components/carousel-flip.md +112 -168
  10. package/.claude/skills/components/container-glow.md +123 -0
  11. package/.claude/skills/components/dashboard-quad-grid.md +98 -0
  12. package/.claude/skills/components/dashboard-stats-grid.md +103 -0
  13. package/.claude/skills/components/display-theme-switch.md +60 -0
  14. package/.claude/skills/components/glowing-border.md +66 -0
  15. package/.claude/skills/components/input-range-core.md +142 -0
  16. package/.claude/skills/components/section-parallax.md +32 -10
  17. package/.claude/skills/components/ui-block-decorated.md +56 -0
  18. package/.claude/skills/components/wipe-away-vertical.md +98 -0
  19. package/.claude/skills/icon-sets.md +1 -1
  20. package/.claude/skills/index.md +10 -1
  21. package/.vscode/css-custom-data.json +38 -0
  22. package/.vscode/settings.json +3 -0
  23. package/.vscode/srcdev-component-alert-mask-core.code-snippets +31 -0
  24. package/.vscode/srcdev-component-carousel-flip.code-snippets +41 -0
  25. package/.vscode/srcdev-component-container-glow.code-snippets +33 -0
  26. package/.vscode/srcdev-component-dashboard-quad-grid.code-snippets +36 -0
  27. package/.vscode/srcdev-component-dashboard-stats-grid.code-snippets +35 -0
  28. package/.vscode/srcdev-component-display-theme-switch.code-snippets +27 -0
  29. package/.vscode/srcdev-component-glowing-border.code-snippets +23 -0
  30. package/.vscode/srcdev-component-input-range.code-snippets +85 -0
  31. package/.vscode/srcdev-component-section-parallax.code-snippets +27 -0
  32. package/.vscode/srcdev-component-ui-block-decorated.code-snippets +24 -0
  33. package/.vscode/srcdev-component-wipe-away-vertical.code-snippets +25 -0
  34. package/README.md +18 -37
  35. package/app/components/{alert-mask → 01.atoms/alert-mask}/AlertMaskCore.vue +16 -17
  36. package/app/components/01.atoms/alert-mask/CONSUMER-STYLING.md +46 -0
  37. package/app/components/01.atoms/alert-mask/stories/AlertMaskCore.stories.ts +79 -0
  38. package/app/components/{alert-mask → 01.atoms/alert-mask}/tests/AlertMaskCore.spec.ts +10 -10
  39. package/app/components/01.atoms/animations/container-glow/CONSUMER-STYLING.md +86 -0
  40. package/app/components/01.atoms/animations/container-glow/ContainerGlow.vue +299 -0
  41. package/app/components/01.atoms/animations/container-glow/stories/ContainerGlow.stories.ts +175 -0
  42. package/app/components/01.atoms/animations/container-glow/tests/ContainerGlow.spec.ts +131 -0
  43. package/app/components/01.atoms/animations/container-glow/tests/__snapshots__/ContainerGlow.spec.ts.snap +14 -0
  44. package/app/components/01.atoms/animations/glowing-border/CONSUMER-STYLING.md +61 -0
  45. package/app/components/01.atoms/animations/glowing-border/GlowingBorder.vue +132 -0
  46. package/app/components/01.atoms/animations/glowing-border/stories/GlowingBorder.stories.ts +165 -0
  47. package/app/components/01.atoms/animations/glowing-border/tests/GlowingBorder.spec.ts +94 -0
  48. package/app/components/01.atoms/animations/glowing-border/tests/__snapshots__/GlowingBorder.spec.ts.snap +3 -0
  49. package/app/components/01.atoms/animations/section-parallax/CONSUMER-STYLING.md +44 -0
  50. package/app/components/{parallax → 01.atoms/animations/section-parallax}/SectionParallax.vue +11 -10
  51. package/app/components/01.atoms/animations/section-parallax/stories/SectionParallax.stories.ts +98 -0
  52. package/app/components/01.atoms/animations/section-parallax/tests/SectionParallax.spec.ts +102 -0
  53. package/app/components/01.atoms/animations/section-parallax/tests/__snapshots__/SectionParallax.spec.ts.snap +9 -0
  54. package/app/components/01.atoms/animations/view-timeline/CONSUMER-STYLING.md +70 -0
  55. package/app/components/01.atoms/animations/view-timeline/WipeAwayVertical.vue +181 -0
  56. package/app/components/01.atoms/animations/view-timeline/stories/WipeAwayVertical.stories.ts +269 -0
  57. package/app/components/01.atoms/animations/view-timeline/tests/WipeAwayVertical.spec.ts +127 -0
  58. package/app/components/01.atoms/canvas-switcher/CONSUMER-STYLING.md +1 -1
  59. package/app/components/01.atoms/canvas-switcher/stories/CanvasSwitcher.stories.ts +1 -1
  60. package/app/components/01.atoms/content-wrappers/layout-grid/dashboard-quad-grid/CONSUMER-STYLING.md +42 -0
  61. package/app/components/{layout-grids/LayoutGridA.vue → 01.atoms/content-wrappers/layout-grid/dashboard-quad-grid/DashboardQuadGrid.vue} +23 -13
  62. package/app/components/{layout-grids/stories/LayoutGridA.stories.ts → 01.atoms/content-wrappers/layout-grid/dashboard-quad-grid/stories/DashboardQuadGrid.stories.ts} +151 -23
  63. package/app/components/{layout-grids/tests/LayoutGridA.spec.ts → 01.atoms/content-wrappers/layout-grid/dashboard-quad-grid/tests/DashboardQuadGrid.spec.ts} +25 -25
  64. package/app/components/01.atoms/content-wrappers/layout-grid/dashboard-stats-grid/CONSUMER-STYLING.md +41 -0
  65. package/app/components/01.atoms/content-wrappers/layout-grid/dashboard-stats-grid/DashboardStatsGrid.vue +133 -0
  66. package/app/components/{layout-grids/stories/LayoutGridB.stories.ts → 01.atoms/content-wrappers/layout-grid/dashboard-stats-grid/stories/DashboardStatsGrid.stories.ts} +24 -24
  67. package/app/components/{layout-grids/tests/LayoutGridB.spec.ts → 01.atoms/content-wrappers/layout-grid/dashboard-stats-grid/tests/DashboardStatsGrid.spec.ts} +23 -23
  68. package/app/components/01.atoms/ui-block-decorated/CONSUMER-STYLING.md +39 -0
  69. package/app/components/01.atoms/ui-block-decorated/UiBlockDecorated.vue +141 -0
  70. package/app/components/01.atoms/ui-block-decorated/stories/UiBlockDecorated.stories.ts +148 -0
  71. package/app/components/01.atoms/ui-block-decorated/tests/UiBlockDecorated.spec.ts +80 -0
  72. package/app/components/01.atoms/ui-block-decorated/tests/__snapshots__/UiBlockDecorated.spec.ts.snap +3 -0
  73. package/app/components/02.molecules/alert-masked-content/tests/AlertMaskedContent.spec.ts +6 -6
  74. package/app/components/02.molecules/display-theme-switch/CONSUMER-STYLING.md +34 -0
  75. package/app/components/02.molecules/display-theme-switch/DisplayThemeSwitch.vue +102 -0
  76. package/app/components/02.molecules/display-theme-switch/stories/DisplayThemeSwitch.stories.ts +115 -0
  77. package/app/components/02.molecules/display-theme-switch/tests/DisplayThemeSwitch.spec.ts +86 -0
  78. package/app/components/03.organisms/image-galleries/carousel-flip/CONSUMER-STYLING.md +46 -0
  79. package/app/components/{carousels → 03.organisms/image-galleries/carousel-flip}/CarouselFlip.vue +63 -42
  80. package/app/components/{carousels → 03.organisms/image-galleries/carousel-flip}/stories/CarouselFlip.stories.ts +96 -11
  81. package/app/components/{carousels → 03.organisms/image-galleries/carousel-flip}/tests/CarouselFlip.spec.ts +80 -0
  82. package/app/components/05.forms/form-field/FormField.vue +1 -1
  83. package/app/components/05.forms/form-wrapper/FormWrapper.vue +1 -1
  84. package/app/components/05.forms/input-range/CONSUMER-STYLING.md +45 -0
  85. package/app/components/05.forms/input-range/InputRangeCore.vue +79 -143
  86. package/app/components/05.forms/input-range/stories/InputRangeCore.stories.ts +126 -0
  87. package/app/components/05.forms/input-range/tests/InputRangeCore.spec.ts +124 -0
  88. package/app/components/05.forms/input-range/variants/InputRangeDefault.vue +9 -32
  89. package/app/components/05.forms/input-range/variants/stories/InputRangeDefault.stories.ts +108 -0
  90. package/app/components/05.forms/input-range/variants/tests/InputRangeDefault.spec.ts +140 -0
  91. package/app/components/05.forms/patterns/stories/MigratedFieldsForm.stories.ts +135 -0
  92. package/app/components/05.forms/triple-toggle-switch/CONSUMER-STYLING.md +16 -2
  93. package/app/components/05.forms/triple-toggle-switch/TripleToggleSwitchCore.vue +6 -4
  94. package/app/types/components/container-glow.d.ts +8 -0
  95. package/app/types/components/index.ts +1 -1
  96. package/package.json +3 -2
  97. package/app/components/05.forms/input-range-fancy/InputRangeFancyCore.vue +0 -426
  98. package/app/components/05.forms/input-range-fancy/InputRangeFancyWithLabel.vue +0 -94
  99. package/app/components/carousels/CarouselBasic.vue +0 -317
  100. package/app/components/carousels/CarouselInfinite.vue +0 -358
  101. package/app/components/container-glow/ContainerGlowCore.vue +0 -296
  102. package/app/components/container-glow/stories/ContainerGlowCore.stories.ts +0 -337
  103. package/app/components/display-theme-switch/DisplayThemeSwitch.vue +0 -189
  104. package/app/components/display-theme-switch/stories/DisplayThemeSwitch.stories.ts +0 -154
  105. package/app/components/glowing-border/GlowingBorder.vue +0 -142
  106. package/app/components/glowing-border/stories/GlowingBorder.stories.ts +0 -141
  107. package/app/components/layout-grids/LayoutGridB.vue +0 -134
  108. package/app/components/test-storybook/TestStorybook.vue +0 -49
  109. package/app/components/test-storybook/stories/TestStorybook.stories.ts +0 -28
  110. package/app/components/ui-block-decorated/UiBlockDecorated.vue +0 -167
  111. package/app/components/view-timeline/WipeAwayVertical.vue +0 -180
  112. package/app/types/components/carousel-basic.d.ts +0 -19
@@ -1,134 +0,0 @@
1
- <template>
2
- <div class="layout-grid-b" :class="[elementClasses]">
3
- <section class="top-row">
4
- <div class="top-row-slot-1">
5
- <div class="top-row-slot-1-inner">
6
- <div v-for="key in topRowSlot1ItemCount" :key="key" class="panel">
7
- <slot :name="`top-row-slot1-${key}-content`"></slot>
8
- </div>
9
- </div>
10
- </div>
11
-
12
- <div class="top-row-slot-2">
13
- <div class="panel">
14
- <slot name="top-row-slot-2"></slot>
15
- </div>
16
- </div>
17
- <div class="top-row-slot-3">
18
- <div class="panel">
19
- <slot name="top-row-slot-3"></slot>
20
- </div>
21
- </div>
22
- </section>
23
-
24
- <section class="bottom-row">
25
- <div v-for="key in bottomRowItemCount" :key="key" class="panel">
26
- <slot :name="`bottom-row-${key}-content`"></slot>
27
- </div>
28
- </section>
29
- </div>
30
- </template>
31
-
32
- <script setup lang="ts">
33
- const props = defineProps({
34
- topRowSlot1ItemCount: {
35
- type: Number as PropType<number>,
36
- default: 6,
37
- },
38
- bottomRowItemCount: {
39
- type: Number as PropType<number>,
40
- default: 4,
41
- },
42
- styleClassPassthrough: {
43
- type: [String, Array] as PropType<string | string[]>,
44
- default: () => [],
45
- },
46
- });
47
-
48
- const { elementClasses, resetElementClasses } = useStyleClassPassthrough(props.styleClassPassthrough);
49
-
50
- watch(
51
- () => props.styleClassPassthrough,
52
- () => {
53
- resetElementClasses(props.styleClassPassthrough);
54
- }
55
- );
56
- </script>
57
-
58
- <style lang="css">
59
- @layer components {
60
- .layout-grid-b {
61
- --_border-color: light-dark(hsl(0, 29%, 3%), hsl(0, 0%, 92%));
62
- --_color: light-dark(hsl(0, 29%, 3%), hsl(0, 0%, 92%));
63
- --_gap: 12px;
64
-
65
- .panel {
66
- border: 1px solid var(--_border-color);
67
- border-radius: 12px;
68
- padding: 12px;
69
- height: auto;
70
- }
71
-
72
- container-type: inline-size;
73
- display: grid;
74
- grid-template-columns: 1fr;
75
- gap: var(--_gap);
76
- width: 100%;
77
- margin-inline: auto;
78
-
79
- .top-row {
80
- display: grid;
81
- gap: var(--_gap);
82
- width: 100%;
83
-
84
- grid-template-columns: 1fr;
85
- grid-template-areas:
86
- "slot1"
87
- "slot2"
88
- "slot3";
89
-
90
- @container (min-width: 1024px) {
91
- grid-template-columns: 1fr minmax(460px, 33%);
92
- grid-template-areas:
93
- "slot1 slot2"
94
- "slot3 slot2";
95
- }
96
- }
97
-
98
- .top-row-slot-1 {
99
- grid-area: slot1;
100
- container-type: inline-size;
101
-
102
- .top-row-slot-1-inner {
103
- display: grid;
104
- grid-template-columns: repeat(2, 1fr);
105
-
106
- gap: var(--_gap);
107
-
108
- @container (min-width: 680px) {
109
- grid-template-columns: repeat(3, 1fr);
110
- }
111
-
112
- .panel {
113
- display: grid;
114
- }
115
- }
116
- }
117
-
118
- .top-row-slot-2 {
119
- grid-area: slot2;
120
- display: grid;
121
- }
122
- .top-row-slot-3 {
123
- grid-area: slot3;
124
- display: grid;
125
- }
126
-
127
- .bottom-row {
128
- display: grid;
129
- grid-template-columns: repeat(2, 1fr);
130
- gap: var(--_gap);
131
- }
132
- }
133
- }
134
- </style>
@@ -1,49 +0,0 @@
1
- <template>
2
- <div class="test-storybook" :class="[elementClasses]" :data-testid="props.dataTestid">
3
- <PageRow tag="div" variant="full" :style-class-passthrough="['mbe-20']">
4
- <h1>Test Storybook Component</h1>
5
- <slot v-if="slots.titleSlot" name="titleSlot"></slot>
6
- <div class="test-storybook__content">
7
- <p>
8
- <code>&lt;Icon name="mdi:star"&gt;</code>
9
- NuxtIcon test
10
- </p>
11
- <Icon name="mdi:star" style="width: 48px; height: 48px; color: orange" />
12
- </div>
13
- </PageRow>
14
- </div>
15
- </template>
16
-
17
- <script setup lang="ts">
18
- const props = defineProps({
19
- dataTestid: {
20
- type: String,
21
- default: "test-storybook",
22
- },
23
- styleClassPassthrough: {
24
- type: Array as PropType<string[]>,
25
- default: () => [],
26
- },
27
- });
28
- const slots = useSlots();
29
- const { elementClasses } = useStyleClassPassthrough(props.styleClassPassthrough);
30
- </script>
31
-
32
- <style lang="css">
33
- @layer components {
34
- .test-storybook {
35
- border: 1px solid #ccc;
36
- padding: 16px;
37
- margin: 16px;
38
- text-align: center;
39
- .test-storybook__content {
40
- display: grid;
41
- grid-template-columns: auto 1fr;
42
- gap: 24px;
43
- border: 1px solid #ccc;
44
- padding: 16px;
45
- margin-top: 12px;
46
- }
47
- }
48
- }
49
- </style>
@@ -1,28 +0,0 @@
1
- import type { Meta, StoryFn } from "@nuxtjs/storybook"
2
- import StoryBookComponent from "../TestStorybook.vue"
3
-
4
- export default {
5
- title: "Components/TestStorybook/TestStorybook",
6
- component: StoryBookComponent,
7
- args: {
8
- styleClassPassthrough: ["test-storybook"],
9
- },
10
- } as Meta<typeof StoryBookComponent>
11
-
12
- const Template: StoryFn<typeof StoryBookComponent> = (args) => ({
13
- components: { StoryBookComponent },
14
- setup() {
15
- return { args }
16
- },
17
- template: `
18
- <StoryBookComponent v-bind="args">
19
- <template v-if="args.titleSlot" v-slot:titleSlot>{{ args.titleSlot }}</template>
20
- </StoryBookComponent>
21
- `,
22
- })
23
-
24
- export const TitleOnlyDismissable = Template.bind({})
25
- TitleOnlyDismissable.args = {
26
- styleClassPassthrough: ["test-storybook--title-only-dismissable"],
27
- titleSlot: "Title Slot Content",
28
- }
@@ -1,167 +0,0 @@
1
- <template>
2
- <component
3
- :is="tag"
4
- class="ui-block-decorated"
5
- :class="[
6
- { ['border-' + borderStrength]: borderStrength > 0 },
7
- { ['shadow-' + shadowStrength]: shadowStrength > 0 },
8
- { ['inner-shadow-' + innerShadowStrength]: innerShadowStrength > 0 },
9
- elementClasses,
10
- ]"
11
- >
12
- <slot name="default"></slot>
13
- </component>
14
- </template>
15
-
16
- <script setup lang="ts">
17
- const props = defineProps({
18
- tag: {
19
- type: String,
20
- default: "div",
21
- validator(value: string) {
22
- return [
23
- "div",
24
- "p",
25
- "span",
26
- "section",
27
- "article",
28
- "aside",
29
- "header",
30
- "footer",
31
- "main",
32
- "nav",
33
- "ul",
34
- "ol",
35
- ].includes(value)
36
- },
37
- },
38
- borderStrength: {
39
- type: Number,
40
- default: 0,
41
- validator(value: number) {
42
- return value >= 0 && value <= 6
43
- },
44
- },
45
- shadowStrength: {
46
- type: Number,
47
- default: 0,
48
- validator(value: number) {
49
- return value >= 0 && value <= 6
50
- },
51
- },
52
- innerShadowStrength: {
53
- type: Number,
54
- default: 0,
55
- validator(value: number) {
56
- return value >= 0 && value <= 4
57
- },
58
- },
59
- styleClassPassthrough: {
60
- type: [String, Array] as PropType<string | string[]>,
61
- default: () => [],
62
- },
63
- })
64
-
65
- const { elementClasses, resetElementClasses } = useStyleClassPassthrough(props.styleClassPassthrough)
66
-
67
- watch(
68
- () => props.styleClassPassthrough,
69
- () => {
70
- resetElementClasses(props.styleClassPassthrough)
71
- }
72
- )
73
- </script>
74
-
75
- <style lang="css">
76
- @layer components {
77
- .ui-block-decorated {
78
- /* Component styles */
79
- }
80
-
81
- /*
82
- * Border utility classes
83
- */
84
- .border-1 {
85
- border: var(--border-1);
86
- }
87
- .border-2 {
88
- border: var(--border-2);
89
- }
90
- .border-3 {
91
- border: var(--border-3);
92
- }
93
- .border-4 {
94
- border: var(--border-4);
95
- }
96
- .border-5 {
97
- border: var(--border-5);
98
- }
99
- .border-6 {
100
- border: var(--border-6);
101
- }
102
- /*
103
- * Shadow utility classes
104
- */
105
- .shadow-1 {
106
- box-shadow: var(--shadow-1);
107
- }
108
-
109
- .shadow-2 {
110
- box-shadow: var(--shadow-2);
111
- }
112
- .shadow-3 {
113
- box-shadow: var(--shadow-3);
114
- }
115
- .shadow-4 {
116
- box-shadow: var(--shadow-4);
117
- }
118
- .shadow-5 {
119
- box-shadow: var(--shadow-5);
120
- }
121
- .shadow-6 {
122
- box-shadow: var(--shadow-6);
123
- }
124
-
125
- /*
126
- * Inner shadow utility classes
127
- * Could use substring match [class*="inner-shadow"] but not as performant
128
- */
129
-
130
- .inner-shadow-1,
131
- .inner-shadow-2,
132
- .inner-shadow-3,
133
- .inner-shadow-4 {
134
- position: relative;
135
- isolation: isolate;
136
- }
137
-
138
- .inner-shadow-1::before,
139
- .inner-shadow-2::before,
140
- .inner-shadow-3::before,
141
- .inner-shadow-4::before {
142
- content: "";
143
- display: block;
144
- position: absolute;
145
- inset: 0;
146
- pointer-events: none;
147
- border-radius: inherit;
148
- z-index: 2;
149
- }
150
-
151
- .inner-shadow-1::before {
152
- box-shadow: var(--inner-shadow-1), var(--inner-shadow-highlight);
153
- }
154
-
155
- .inner-shadow-2::before {
156
- box-shadow: var(--inner-shadow-2), var(--inner-shadow-highlight);
157
- }
158
-
159
- .inner-shadow-3::before {
160
- box-shadow: var(--inner-shadow-3), var(--inner-shadow-highlight);
161
- }
162
-
163
- .inner-shadow-4::before {
164
- box-shadow: var(--inner-shadow-4), var(--inner-shadow-highlight);
165
- }
166
- }
167
- </style>
@@ -1,180 +0,0 @@
1
- <template>
2
- <component
3
- :is="tag"
4
- class="wipe-away-vertical"
5
- :class="[elementClasses]"
6
- :style="{ 'timeline-scope': timelineScope }"
7
- ref="scrollContainerRef"
8
- >
9
- <div ref="stickyItemsContainerRef" class="sticky-items-container">
10
- <div
11
- class="sticky-item"
12
- v-for="(item, key) in itemCount"
13
- :key="key"
14
- :style="{
15
- 'animation-timeline': key === itemCount - 1 ? 'none' : `--section-${timelineId}-${key}`,
16
- 'z-index': itemCount - key,
17
- }"
18
- ref="stickyItemsRef"
19
- >
20
- <slot :name="`stickyItem-${key}`"></slot>
21
- </div>
22
- </div>
23
-
24
- <section
25
- v-for="(item, key) in itemCount"
26
- :key="key"
27
- class="scrolling-section"
28
- :style="{
29
- 'view-timeline-name': `--section-${timelineId}-${key}`,
30
- }"
31
- ref="scrollingItemsRef"
32
- >
33
- <slot :name="`scrollingItem-${key}`"></slot>
34
- </section>
35
- </component>
36
- </template>
37
-
38
- <script setup lang="ts">
39
- const props = defineProps({
40
- tag: {
41
- type: String as PropType<"div" | "section" | "main" | "article" | "aside">,
42
- default: "div",
43
- validator: (val: string) => ["div", "section", "main", "article", "aside"].includes(val),
44
- },
45
- itemCount: {
46
- type: Number as PropType<number>,
47
- default: 0,
48
- },
49
- styleClassPassthrough: {
50
- type: [String, Array] as PropType<string | string[]>,
51
- default: () => [],
52
- },
53
- })
54
-
55
- const { elementClasses, resetElementClasses } = useStyleClassPassthrough(props.styleClassPassthrough)
56
-
57
- const timelineId = useId()
58
- const stickyItemsContainerRef = useTemplateRef<HTMLElement | null>("stickyItemsContainerRef")
59
- const stickyItemsRef = useTemplateRef<HTMLElement[] | null>("stickyItemsRef")
60
- const scrollContainerRef = useTemplateRef<HTMLElement | null>("scrollContainerRef")
61
- const scrollingItemsRef = useTemplateRef<HTMLElement[] | null>("scrollingItemsRef")
62
- const timelineInset = ref("35% 35%")
63
- const topPercent = ref("0")
64
- const bottomPercent = ref("0")
65
-
66
- const timelineScope = computed(() =>
67
- Array.from({ length: props.itemCount }, (_, i) => `--section-${timelineId}-${i}`).join(", ")
68
- )
69
-
70
- const calculateInset = () => {
71
- if (!stickyItemsContainerRef.value) return
72
-
73
- const rect = stickyItemsContainerRef.value.getBoundingClientRect()
74
- const innerHeight = window.innerHeight
75
-
76
- topPercent.value = ((rect.top / innerHeight) * 100).toFixed(2)
77
- bottomPercent.value = (((innerHeight - rect.bottom) / innerHeight) * 100).toFixed(2)
78
-
79
- timelineInset.value = `${topPercent.value}% ${bottomPercent.value}%`
80
-
81
- if (!scrollContainerRef.value) return
82
- scrollContainerRef.value.style.setProperty("--calculated-inset", timelineInset.value)
83
- }
84
-
85
- let requestAnimationFrameId: number | null = null
86
- const onScrollDebounce = () => {
87
- if (requestAnimationFrameId !== null) return
88
- requestAnimationFrameId = requestAnimationFrame(() => {
89
- calculateInset()
90
- requestAnimationFrameId = null
91
- })
92
- }
93
-
94
- watch(
95
- () => props.styleClassPassthrough,
96
- () => {
97
- resetElementClasses(props.styleClassPassthrough)
98
- }
99
- )
100
-
101
- const fallbackScrollHandler = () => {
102
- const sections = scrollingItemsRef.value || []
103
- const layers = stickyItemsRef.value || []
104
-
105
- const mid = window.innerHeight / 2
106
-
107
- sections.forEach((section, i) => {
108
- const rect = section.getBoundingClientRect()
109
- const active = rect.top <= mid && rect.bottom >= mid
110
- if (layers[i]) layers[i].style.opacity = active ? "1" : "0"
111
- })
112
- }
113
-
114
- const supportsScrollTimeline = import.meta.client ? CSS.supports("animation-timeline: view()") : false
115
-
116
- onMounted(() => {
117
- calculateInset()
118
- if (supportsScrollTimeline) {
119
- window.addEventListener("scroll", onScrollDebounce)
120
- } else {
121
- window.addEventListener("scroll", fallbackScrollHandler)
122
- }
123
- })
124
-
125
- onUnmounted(() => {
126
- if (supportsScrollTimeline) {
127
- window.removeEventListener("scroll", onScrollDebounce)
128
- } else {
129
- window.removeEventListener("scroll", fallbackScrollHandler)
130
- }
131
- })
132
- </script>
133
-
134
- <style lang="css">
135
- @layer components {
136
- .wipe-away-vertical {
137
- .sticky-items-container {
138
- position: sticky;
139
- top: 50%;
140
- left: 100%;
141
- transform: translateY(-50%);
142
-
143
- .sticky-item {
144
- position: absolute;
145
- inset: 0;
146
- border-radius: 0.5rem;
147
- width: 100%;
148
- }
149
- }
150
-
151
- .scrolling-section {
152
- view-timeline-axis: block;
153
- view-timeline-inset: var(--calculated-inset);
154
- }
155
- }
156
-
157
- @supports (animation-timeline: view()) {
158
- @keyframes wipe-out {
159
- 0% {
160
- clip-path: inset(0 0 0% 0);
161
- }
162
- 100% {
163
- clip-path: inset(0 0 100% 0);
164
- }
165
- }
166
-
167
- .sticky-item {
168
- animation: wipe-out 1s linear both;
169
- animation-range: entry 0% entry 100%;
170
- }
171
- }
172
-
173
- @supports not (animation-timeline: view()) {
174
- .sticky-item {
175
- opacity: 0;
176
- transition: opacity 0.4s ease-in-out;
177
- }
178
- }
179
- }
180
- </style>
@@ -1,19 +0,0 @@
1
- export interface CarouselBasicItem {
2
- id: number | string
3
- url: string
4
- alt: string
5
- }
6
-
7
- export interface CarouselModifiedItem {
8
- id: number | string
9
- url: string
10
- alt: string
11
- order: number
12
- }
13
-
14
- export interface ICarouselBasic {
15
- items: CarouselBasicItem[] | CarouselModifiedItem[]
16
- total: number
17
- skip: number
18
- limit: number
19
- }