@alphacifer/slidev-addon-theme 0.0.6 → 0.0.8

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 (105) hide show
  1. package/README.md +117 -51
  2. package/components/{chevron-card → card/chevron-card}/ChevronCard.vue +2 -2
  3. package/components/{chevron-card → card/chevron-card}/ChevronCardBadge.vue +1 -1
  4. package/components/{chevron-card → card/chevron-card}/ChevronCardContent.vue +1 -1
  5. package/components/{chevron-card → card/chevron-card}/ChevronCardHeading.vue +1 -1
  6. package/components/{horiz-card → card/horiz-card}/HorizCard.vue +2 -2
  7. package/components/{horiz-card → card/horiz-card}/HorizCardBadge.vue +2 -2
  8. package/components/{horiz-card → card/horiz-card}/HorizCardContent.vue +2 -2
  9. package/components/{horiz-card → card/horiz-card}/HorizCardHeading.vue +2 -2
  10. package/components/{horiz-card → card/horiz-card}/HorizCardIcon.vue +2 -2
  11. package/components/{vert-card → card/vert-card}/VertCard.vue +2 -2
  12. package/components/{vert-card → card/vert-card}/VertCardBadge.vue +5 -2
  13. package/components/{vert-card → card/vert-card}/VertCardContent.vue +2 -2
  14. package/components/{vert-card → card/vert-card}/VertCardHeading.vue +2 -2
  15. package/components/{vert-card → card/vert-card}/VertCardIcon.vue +2 -2
  16. package/components/{vert-card → card/vert-card}/VertCardTitle.vue +2 -2
  17. package/components/comparisons/arc-comparison/ArcComparison.vue +654 -0
  18. package/components/comparisons/arc-comparison/ArcComparisonBadge.vue +29 -0
  19. package/components/comparisons/arc-comparison/ArcComparisonContent.vue +29 -0
  20. package/components/comparisons/arc-comparison/ArcComparisonContents.vue +17 -0
  21. package/components/comparisons/arc-comparison/ArcComparisonHeading.vue +29 -0
  22. package/components/comparisons/arc-comparison/ArcComparisonLeft.vue +268 -0
  23. package/components/comparisons/arc-comparison/ArcComparisonOrbit.vue +47 -0
  24. package/components/comparisons/arc-comparison/ArcComparisonRight.vue +271 -0
  25. package/components/comparisons/arc-comparison/ArcComparisonTitle.vue +29 -0
  26. package/components/comparisons/table-comparison/TableComparison.vue +254 -0
  27. package/components/comparisons/table-comparison/TableComparisonCell.vue +88 -0
  28. package/components/comparisons/table-comparison/TableComparisonCol.vue +97 -0
  29. package/components/comparisons/table-comparison/TableComparisonCols.vue +74 -0
  30. package/components/comparisons/table-comparison/TableComparisonRow.vue +92 -0
  31. package/components/comparisons/table-comparison/TableComparisonRows.vue +21 -0
  32. package/components/core/ReflectedTitle.vue +2 -1
  33. package/components/core/arc-orbit/ArcOrbit.vue +468 -0
  34. package/components/{arc-compare/ArcCompareBadge.vue → core/arc-orbit/ArcOrbitBadge.vue} +11 -8
  35. package/components/core/arc-orbit/ArcOrbitCallout.vue +400 -0
  36. package/components/{arc-compare/ArcCompareContent.vue → core/arc-orbit/ArcOrbitContent.vue} +8 -8
  37. package/components/{arc-compare/ArcCompareContents.vue → core/arc-orbit/ArcOrbitContents.vue} +3 -3
  38. package/components/{arc-compare/ArcCompareHeading.vue → core/arc-orbit/ArcOrbitHeading.vue} +11 -8
  39. package/components/core/arc-orbit/ArcOrbitTitle.vue +50 -0
  40. package/components/{thanks → core/thanks}/ThanksOutlineSquare.vue +1 -1
  41. package/components/{thanks → core/thanks}/ThanksSquare.vue +1 -1
  42. package/components/{quad-hub/QuadHub.vue → facets/tetrad/rect-orbit-tetrad/RectOrbitTetrad.vue} +71 -69
  43. package/components/{quad-hub/QuadHubCallout.vue → facets/tetrad/rect-orbit-tetrad/RectOrbitTetradCallout.vue} +45 -43
  44. package/components/{quad-hub/QuadHubCenter.vue → facets/tetrad/rect-orbit-tetrad/RectOrbitTetradCenter.vue} +4 -4
  45. package/components/{quad-hub/QuadHubContent.vue → facets/tetrad/rect-orbit-tetrad/RectOrbitTetradContent.vue} +6 -6
  46. package/components/{quad-hub/QuadHubHeading.vue → facets/tetrad/rect-orbit-tetrad/RectOrbitTetradHeading.vue} +6 -6
  47. package/components/{quad-hub/QuadHubIcon.vue → facets/tetrad/rect-orbit-tetrad/RectOrbitTetradIcon.vue} +6 -6
  48. package/components/{arrow-triad → facets/triad/arrow-triad}/ArrowTriad.vue +3 -3
  49. package/components/{arrow-triad → facets/triad/arrow-triad}/ArrowTriadCallout.vue +1 -1
  50. package/components/{arrow-triad → facets/triad/arrow-triad}/ArrowTriadContent.vue +1 -1
  51. package/components/{arrow-triad → facets/triad/arrow-triad}/ArrowTriadHeading.vue +1 -1
  52. package/components/facets/triad/gear-triad/GearTriad.vue +591 -0
  53. package/components/facets/triad/gear-triad/GearTriadCallout.vue +285 -0
  54. package/components/facets/triad/gear-triad/GearTriadCenter.vue +41 -0
  55. package/components/facets/triad/gear-triad/GearTriadContent.vue +58 -0
  56. package/components/facets/triad/gear-triad/GearTriadContents.vue +111 -0
  57. package/components/facets/triad/gear-triad/GearTriadDescription.vue +38 -0
  58. package/components/facets/triad/gear-triad/GearTriadHeading.vue +38 -0
  59. package/components/facets/triad/gear-triad/GearTriadIcon.vue +157 -0
  60. package/components/{hex-triad → facets/triad/hex-triad}/HexTriad.vue +2 -2
  61. package/components/{hex-triad → facets/triad/hex-triad}/HexTriadBadge.vue +1 -1
  62. package/components/{hex-triad → facets/triad/hex-triad}/HexTriadCallout.vue +1 -1
  63. package/components/{hex-triad → facets/triad/hex-triad}/HexTriadHeading.vue +1 -1
  64. package/components/{arc-arrow-process → process/arc-arrow-process}/ArcArrowProcess.vue +2 -2
  65. package/components/{arc-arrow-process → process/arc-arrow-process}/ArcArrowProcessArrow.vue +1 -1
  66. package/components/{arc-arrow-process → process/arc-arrow-process}/ArcArrowProcessCallout.vue +1 -1
  67. package/components/{arc-arrow-process → process/arc-arrow-process}/ArcArrowProcessContent.vue +1 -1
  68. package/components/{arc-arrow-process → process/arc-arrow-process}/ArcArrowProcessHeading.vue +1 -1
  69. package/package.json +1 -1
  70. package/utils/arcComparison/context.ts +40 -0
  71. package/utils/arcComparison/createArcComparisonGeometry.ts +175 -0
  72. package/utils/arcComparison/index.ts +3 -0
  73. package/utils/{arcCompare/resolveArcCompareItems.ts → arcComparison/resolveArcComparisonItems.ts} +24 -45
  74. package/utils/arcOrbit/context.ts +38 -0
  75. package/utils/{arcCompare/createArcCompareGeometry.ts → arcOrbit/createArcOrbitGeometry.ts} +77 -108
  76. package/utils/arcOrbit/index.ts +3 -0
  77. package/utils/arcOrbit/resolveArcOrbitItems.ts +92 -0
  78. package/utils/gearTriad/context.ts +51 -0
  79. package/utils/gearTriad/createGearTriadGeometry.ts +210 -0
  80. package/utils/gearTriad/index.ts +3 -0
  81. package/utils/gearTriad/resolveGearTriadItems.ts +159 -0
  82. package/utils/rectOrbitTetrad/context.ts +31 -0
  83. package/utils/{quadHub/createQuadHubGeometry.ts → rectOrbitTetrad/createRectOrbitTetradGeometry.ts} +33 -28
  84. package/utils/rectOrbitTetrad/index.ts +3 -0
  85. package/utils/{quadHub/resolveQuadHubItems.ts → rectOrbitTetrad/resolveRectOrbitTetradItems.ts} +25 -25
  86. package/utils/tableComparison/constants.ts +72 -0
  87. package/utils/tableComparison/context.ts +24 -0
  88. package/utils/tableComparison/index.ts +2 -0
  89. package/utils/useDiagramAutoScale.ts +1 -1
  90. package/components/arc-compare/ArcCompare.vue +0 -443
  91. package/components/arc-compare/ArcCompareCallout.vue +0 -386
  92. package/components/arc-compare/ArcCompareLeft.vue +0 -183
  93. package/components/arc-compare/ArcCompareRight.vue +0 -183
  94. package/components/arc-compare/ArcCompareTitle.vue +0 -47
  95. package/utils/arcCompare/context.ts +0 -36
  96. package/utils/arcCompare/index.ts +0 -3
  97. package/utils/quadHub/context.ts +0 -26
  98. package/utils/quadHub/index.ts +0 -3
  99. /package/components/{shifting-heading → core}/TransitionHeading.vue +0 -0
  100. /package/components/{thanks → core/thanks}/ThanksContent.vue +0 -0
  101. /package/components/{arrow-triad → facets/triad/arrow-triad}/ArrowTriadIcon.vue +0 -0
  102. /package/components/{hex-triad → facets/triad/hex-triad}/HexTriadCenterBadge.vue +0 -0
  103. /package/components/{hex-triad → facets/triad/hex-triad}/HexTriadContent.vue +0 -0
  104. /package/components/{hex-triad → facets/triad/hex-triad}/HexTriadLayer.vue +0 -0
  105. /package/components/{arc-arrow-process → process/arc-arrow-process}/ArcArrowProcessIcon.vue +0 -0
@@ -0,0 +1,654 @@
1
+ <script setup lang="ts">
2
+ import {
3
+ type ComputedRef,
4
+ computed,
5
+ Fragment,
6
+ inject,
7
+ provide,
8
+ type Ref,
9
+ ref,
10
+ useSlots,
11
+ type VNode,
12
+ watch,
13
+ } from 'vue';
14
+
15
+ import {
16
+ ARC_COMPARISON_ROOT_KEY,
17
+ createArcComparisonGeometry,
18
+ } from '../../../utils/arcComparison';
19
+ import { useDiagramAutoScale } from '../../../utils/useDiagramAutoScale';
20
+ import { useMergedUnoAttrs } from '../../../utils/useMergedUnoAttrs';
21
+ import ArcComparisonLeft from './ArcComparisonLeft.vue';
22
+ import ArcComparisonRight from './ArcComparisonRight.vue';
23
+
24
+ defineOptions({
25
+ name: 'ArcComparison',
26
+ inheritAttrs: false,
27
+ });
28
+
29
+ export type TArcComparisonAs = 'layout';
30
+
31
+ export interface IArcComparisonProps {
32
+ readonly as?: TArcComparisonAs | null;
33
+ readonly moved?: boolean;
34
+ readonly edgeOffset?: number;
35
+ readonly vsText?: string;
36
+ readonly vsSize?: number;
37
+ readonly count?: number;
38
+ readonly hubRadius?: number;
39
+ readonly arcRadius?: number;
40
+ readonly arcOffset?: number;
41
+ readonly animation?: boolean;
42
+ readonly height?: number | string;
43
+ readonly startDelay?: number;
44
+ readonly active?: boolean;
45
+ readonly scale?: number;
46
+ readonly autoScale?: boolean;
47
+ readonly maxScale?: number;
48
+ readonly hidePagy?: boolean;
49
+ }
50
+
51
+ const props = withDefaults(defineProps<IArcComparisonProps>(), {
52
+ as: undefined,
53
+ moved: undefined,
54
+ edgeOffset: 30,
55
+ vsText: 'Vs',
56
+ vsSize: 14,
57
+ count: undefined,
58
+ hubRadius: undefined,
59
+ arcRadius: undefined,
60
+ arcOffset: undefined,
61
+ animation: true,
62
+ height: undefined,
63
+ startDelay: undefined,
64
+ active: undefined,
65
+ scale: undefined,
66
+ autoScale: true,
67
+ maxScale: undefined,
68
+ hidePagy: undefined,
69
+ });
70
+
71
+ const emit = defineEmits<{
72
+ (e: 'click', event: MouseEvent): void;
73
+ (e: 'update:moved', value: boolean): void;
74
+ }>();
75
+
76
+ const slots = useSlots();
77
+ const rootRef = ref<HTMLElement | null>(null);
78
+
79
+ const shiftingIntro = inject<
80
+ | {
81
+ active: ComputedRef<boolean>;
82
+ clicks?: Ref<number> | ComputedRef<number>;
83
+ isShifting?: ComputedRef<boolean>;
84
+ }
85
+ | undefined
86
+ >('SLIDEV_LAYOUT_SHIFTING_INTRO', undefined);
87
+
88
+ const isAnimated = computed(() => {
89
+ if (!props.animation) {
90
+ return false;
91
+ }
92
+
93
+ if (props.active !== undefined) {
94
+ return props.active;
95
+ }
96
+
97
+ if (shiftingIntro) {
98
+ return shiftingIntro.active.value;
99
+ }
100
+
101
+ return true;
102
+ });
103
+
104
+ const resolvedStartDelay = computed(() => {
105
+ if (props.startDelay !== undefined) {
106
+ return props.startDelay;
107
+ }
108
+
109
+ if (shiftingIntro) {
110
+ return shiftingIntro.isShifting?.value ? 500 : 0;
111
+ }
112
+
113
+ return 0;
114
+ });
115
+
116
+ function isSignificantNode(node: VNode): boolean {
117
+ if (typeof node.type === 'symbol') {
118
+ if (typeof node.children === 'string' && !node.children.trim()) {
119
+ return false;
120
+ }
121
+ }
122
+
123
+ if (typeof node.children === 'string' && !node.children.trim()) {
124
+ return false;
125
+ }
126
+
127
+ return true;
128
+ }
129
+
130
+ function flattenVNodes(nodes: VNode[]): VNode[] {
131
+ const result: VNode[] = [];
132
+
133
+ for (const node of nodes) {
134
+ if (node.type === Fragment && Array.isArray(node.children)) {
135
+ result.push(...flattenVNodes(node.children as VNode[]));
136
+ } else if (isSignificantNode(node)) {
137
+ result.push(node);
138
+ }
139
+ }
140
+
141
+ return result;
142
+ }
143
+
144
+ const defaultNodes = computed(() => {
145
+ if (!slots.default) {
146
+ return [];
147
+ }
148
+
149
+ return flattenVNodes(slots.default());
150
+ });
151
+
152
+ const resolvedCount = computed(() => {
153
+ if (props.count === 4 || (props.count as unknown) === '4') {
154
+ return 4;
155
+ }
156
+
157
+ for (const node of defaultNodes.value) {
158
+ if (node.props?.count === 4 || (node.props?.count as unknown) === '4') {
159
+ return 4;
160
+ }
161
+ }
162
+
163
+ return 3;
164
+ });
165
+
166
+ const geo = computed(() => {
167
+ return createArcComparisonGeometry({
168
+ viewBoxWidth: 1000,
169
+ viewBoxHeight: 480,
170
+ hubRadius: props.hubRadius,
171
+ arcRadius: props.arcRadius,
172
+ arcOffset: props.arcOffset,
173
+ pointsCount: resolvedCount.value,
174
+ isLayout: true,
175
+ });
176
+ });
177
+
178
+ let clipInstanceCounter = 0;
179
+ const clipId = `alpha-arc-canvas-clip-${++clipInstanceCounter}`;
180
+
181
+ const internalMoved = ref(false);
182
+
183
+ const isMoved = computed(() => {
184
+ if (props.moved !== undefined) {
185
+ return props.moved;
186
+ }
187
+
188
+ if (shiftingIntro?.clicks && shiftingIntro.clicks.value > 0) {
189
+ return true;
190
+ }
191
+
192
+ return internalMoved.value;
193
+ });
194
+
195
+ watch(
196
+ () => props.as,
197
+ (newAs) => {
198
+ if (newAs === 'layout') {
199
+ internalMoved.value = false;
200
+ }
201
+ },
202
+ );
203
+
204
+ function handleClick(event: MouseEvent): void {
205
+ if (props.as === 'layout') {
206
+ internalMoved.value = !internalMoved.value;
207
+ emit('update:moved', internalMoved.value);
208
+ }
209
+
210
+ emit('click', event);
211
+ }
212
+
213
+ const resolvedEdgeOffset = computed(() => props.edgeOffset ?? 30);
214
+
215
+ const leftTranslateX = computed(() => {
216
+ const delta = 500 - resolvedEdgeOffset.value;
217
+ return `-${delta}px`;
218
+ });
219
+
220
+ const rightTranslateX = computed(() => {
221
+ const delta = 500 - resolvedEdgeOffset.value;
222
+ return `${delta}px`;
223
+ });
224
+
225
+ const leftHubMoverStyle = computed(() => {
226
+ if (props.as === 'layout' && !isMoved.value) {
227
+ return { transform: 'translateX(0px)' };
228
+ }
229
+ return { transform: `translateX(${leftTranslateX.value})` };
230
+ });
231
+
232
+ const rightHubMoverStyle = computed(() => {
233
+ if (props.as === 'layout' && !isMoved.value) {
234
+ return { transform: 'translateX(0px)' };
235
+ }
236
+ return { transform: `translateX(${rightTranslateX.value})` };
237
+ });
238
+
239
+ const dividerScaleY = computed(() => {
240
+ if (props.as !== 'layout' || isMoved.value) {
241
+ return 1;
242
+ }
243
+
244
+ const fullLineLength = geo.value.dividerLine.y2 - geo.value.dividerLine.y1;
245
+ const circleDiameter = 2 * geo.value.left.hubRadius;
246
+
247
+ return fullLineLength > 0 ? circleDiameter / fullLineLength : 1;
248
+ });
249
+
250
+ const dividerStyle = computed(() => {
251
+ if (props.as !== 'layout') {
252
+ return undefined;
253
+ }
254
+
255
+ return {
256
+ transform: `scaleY(${dividerScaleY.value})`,
257
+ transformOrigin: `${geo.value.dividerLine.x}px ${geo.value.centerY}px`,
258
+ };
259
+ });
260
+
261
+ provide(ARC_COMPARISON_ROOT_KEY, {
262
+ animation: isAnimated,
263
+ startDelay: resolvedStartDelay,
264
+ pointsCount: resolvedCount,
265
+ geo,
266
+ as: computed(() => props.as),
267
+ isMoved,
268
+ edgeOffset: resolvedEdgeOffset,
269
+ });
270
+
271
+ const { resolvedScale, containerHeight } = useDiagramAutoScale({
272
+ rootRef,
273
+ baseWidth: 1000,
274
+ baseHeight: 480,
275
+ scale: () => props.scale,
276
+ autoScale: () => props.autoScale,
277
+ maxScale: () => props.maxScale,
278
+ height: () => props.height,
279
+ });
280
+
281
+ const stageTransform = computed(() => {
282
+ if (resolvedScale.value !== 1) {
283
+ return `scale(${resolvedScale.value})`;
284
+ }
285
+
286
+ return undefined;
287
+ });
288
+
289
+ const resolvedHeightStyle = computed(() => {
290
+ if (props.height !== undefined) {
291
+ return typeof props.height === 'number'
292
+ ? `${props.height}px`
293
+ : props.height;
294
+ }
295
+
296
+ if (containerHeight.value > 0) {
297
+ return `${containerHeight.value}px`;
298
+ }
299
+
300
+ return undefined;
301
+ });
302
+
303
+ const { className, forwardedAttrs } = useMergedUnoAttrs(
304
+ 'alpha-arc-comparison w-full flex-1 flex flex-col items-center justify-center select-none font-sans relative min-h-0',
305
+ );
306
+ </script>
307
+
308
+ <template>
309
+ <div
310
+ ref="rootRef"
311
+ v-bind="forwardedAttrs()"
312
+ :class="[
313
+ className(),
314
+ { 'hide-pagy': props.hidePagy },
315
+ props.as ? `alpha-arc-comparison--as-${props.as}` : undefined,
316
+ { 'alpha-arc-comparison--moved': isMoved },
317
+ ]"
318
+ :data-as="props.as ?? undefined"
319
+ :data-moved="isMoved ? '' : undefined"
320
+ :data-hide-pagy="props.hidePagy ? '' : undefined"
321
+ :style="{
322
+ height: resolvedHeightStyle,
323
+ cursor: props.as === 'layout' ? 'pointer' : undefined,
324
+ fontFamily:
325
+ 'ui-sans-serif, system-ui, -apple-system, BlinkMacSystemFont, \'Segoe UI\', Roboto, sans-serif',
326
+ '--arc-comparison-start-delay': `${resolvedStartDelay}ms`,
327
+ '--arc-orbit-start-delay': `${resolvedStartDelay}ms`,
328
+ }"
329
+ @click="handleClick"
330
+ >
331
+ <!-- Relative stage container -->
332
+ <div
333
+ class="alpha-arc-comparison__stage relative w-[1000px] h-[480px] flex items-center justify-center overflow-visible flex-shrink-0"
334
+ :style="{
335
+ transform: stageTransform,
336
+ transformOrigin: 'center center',
337
+ }"
338
+ >
339
+ <!-- Base SVG Layer -->
340
+ <svg
341
+ class="alpha-arc-comparison__svg absolute inset-0 w-full h-full pointer-events-none overflow-visible"
342
+ viewBox="0 0 1000 480"
343
+ xmlns="http://www.w3.org/2000/svg"
344
+ >
345
+ <defs>
346
+ <clipPath :id="clipId">
347
+ <rect x="0" y="0" width="1000" height="480" />
348
+ </clipPath>
349
+ </defs>
350
+ <!-- Semicircular Hubs Group with Canvas Clip -->
351
+ <g :clip-path="`url(#${clipId})`">
352
+ <!-- Other Semicircular Hub Backgrounds (rendered underneath current hubs) -->
353
+ <g
354
+ v-if="geo.left.otherHubPath"
355
+ class="alpha-arc-comparison__hub-mover alpha-arc-comparison__hub-mover--left"
356
+ :class="{ 'alpha-arc-comparison__hub-mover--moved': isMoved || props.as !== 'layout' }"
357
+ :style="leftHubMoverStyle"
358
+ >
359
+ <g
360
+ class="alpha-arc-comparison__hub alpha-arc-comparison__hub--other alpha-arc-comparison__hub--other-left alpha-arc-comparison__hub--left"
361
+ :class="{ 'alpha-arc-comparison--animated': isAnimated }"
362
+ >
363
+ <path
364
+ :d="geo.left.otherHubPath"
365
+ fill="#f1f3f6"
366
+ class="transition-colors duration-300 dark:fill-slate-800/80"
367
+ />
368
+ </g>
369
+ </g>
370
+ <g
371
+ v-if="geo.right.otherHubPath"
372
+ class="alpha-arc-comparison__hub-mover alpha-arc-comparison__hub-mover--right"
373
+ :class="{ 'alpha-arc-comparison__hub-mover--moved': isMoved || props.as !== 'layout' }"
374
+ :style="rightHubMoverStyle"
375
+ >
376
+ <g
377
+ class="alpha-arc-comparison__hub alpha-arc-comparison__hub--other alpha-arc-comparison__hub--other-right alpha-arc-comparison__hub--right"
378
+ :class="{ 'alpha-arc-comparison--animated': isAnimated }"
379
+ >
380
+ <path
381
+ :d="geo.right.otherHubPath"
382
+ fill="#f1f3f6"
383
+ class="transition-colors duration-300 dark:fill-slate-800/80"
384
+ />
385
+ </g>
386
+ </g>
387
+ <!-- Left Semicircular Hub Background -->
388
+ <g
389
+ class="alpha-arc-comparison__hub-mover alpha-arc-comparison__hub-mover--left"
390
+ :class="{ 'alpha-arc-comparison__hub-mover--moved': isMoved || props.as !== 'layout' }"
391
+ :style="leftHubMoverStyle"
392
+ >
393
+ <g
394
+ class="alpha-arc-comparison__hub alpha-arc-comparison__hub--left"
395
+ :class="{ 'alpha-arc-comparison--animated': isAnimated }"
396
+ >
397
+ <path
398
+ :d="geo.left.hubPath"
399
+ fill="#f1f3f6"
400
+ class="transition-colors duration-300 dark:fill-slate-800/80"
401
+ />
402
+ </g>
403
+ </g>
404
+ <!-- Right Semicircular Hub Background -->
405
+ <g
406
+ class="alpha-arc-comparison__hub-mover alpha-arc-comparison__hub-mover--right"
407
+ :class="{ 'alpha-arc-comparison__hub-mover--moved': isMoved || props.as !== 'layout' }"
408
+ :style="rightHubMoverStyle"
409
+ >
410
+ <g
411
+ class="alpha-arc-comparison__hub alpha-arc-comparison__hub--right"
412
+ :class="{ 'alpha-arc-comparison--animated': isAnimated }"
413
+ >
414
+ <path
415
+ :d="geo.right.hubPath"
416
+ fill="#f1f3f6"
417
+ class="transition-colors duration-300 dark:fill-slate-800/80"
418
+ />
419
+ </g>
420
+ </g>
421
+ </g>
422
+ <!-- Left Arc Guide Line and End Dots -->
423
+ <g
424
+ v-if="props.as !== 'layout' || isMoved"
425
+ class="alpha-arc-comparison__arc alpha-arc-comparison__arc--left transition-opacity duration-500 ease-out"
426
+ :class="{
427
+ 'alpha-arc-comparison--animated': isAnimated,
428
+ 'opacity-0': props.as === 'layout' && !isMoved,
429
+ 'opacity-100': props.as !== 'layout' || isMoved,
430
+ }"
431
+ :style="{
432
+ transitionDelay:
433
+ props.as === 'layout' && isMoved ? '300ms' : '0ms',
434
+ }"
435
+ >
436
+ <path
437
+ :d="geo.left.arcPath"
438
+ fill="none"
439
+ stroke="#cbd5e1"
440
+ stroke-width="1.5"
441
+ class="transition-colors duration-300 dark:stroke-slate-700"
442
+ />
443
+ <circle
444
+ :cx="geo.left.topDot.x"
445
+ :cy="geo.left.topDot.y"
446
+ :r="geo.left.dotRadius"
447
+ fill="#94a3b8"
448
+ class="dark:fill-slate-600"
449
+ />
450
+ <circle
451
+ :cx="geo.left.bottomDot.x"
452
+ :cy="geo.left.bottomDot.y"
453
+ :r="geo.left.dotRadius"
454
+ fill="#94a3b8"
455
+ class="dark:fill-slate-600"
456
+ />
457
+ </g>
458
+ <!-- Right Arc Guide Line and End Dots -->
459
+ <g
460
+ v-if="props.as !== 'layout' || isMoved"
461
+ class="alpha-arc-comparison__arc alpha-arc-comparison__arc--right transition-opacity duration-500 ease-out"
462
+ :class="{
463
+ 'alpha-arc-comparison--animated': isAnimated,
464
+ 'opacity-0': props.as === 'layout' && !isMoved,
465
+ 'opacity-100': props.as !== 'layout' || isMoved,
466
+ }"
467
+ :style="{
468
+ transitionDelay:
469
+ props.as === 'layout' && isMoved ? '300ms' : '0ms',
470
+ }"
471
+ >
472
+ <path
473
+ :d="geo.right.arcPath"
474
+ fill="none"
475
+ stroke="#cbd5e1"
476
+ stroke-width="1.5"
477
+ class="transition-colors duration-300 dark:stroke-slate-700"
478
+ />
479
+ <circle
480
+ :cx="geo.right.topDot.x"
481
+ :cy="geo.right.topDot.y"
482
+ :r="geo.right.dotRadius"
483
+ fill="#94a3b8"
484
+ class="dark:fill-slate-600"
485
+ />
486
+ <circle
487
+ :cx="geo.right.bottomDot.x"
488
+ :cy="geo.right.bottomDot.y"
489
+ :r="geo.right.dotRadius"
490
+ fill="#94a3b8"
491
+ class="dark:fill-slate-600"
492
+ />
493
+ </g>
494
+ <!-- Center Divider Line -->
495
+ <line
496
+ class="alpha-arc-comparison__divider transition-colors duration-300 dark:stroke-slate-700"
497
+ :class="{
498
+ 'alpha-arc-comparison--animated': isAnimated,
499
+ 'alpha-arc-comparison__divider--layout': props.as === 'layout',
500
+ }"
501
+ :style="dividerStyle"
502
+ :x1="geo.dividerLine.x"
503
+ :y1="geo.dividerLine.y1"
504
+ :x2="geo.dividerLine.x"
505
+ :y2="geo.dividerLine.y2"
506
+ stroke="#cbd5e1"
507
+ stroke-width="1.5"
508
+ />
509
+ <!-- Center "Vs" Circle Badge -->
510
+ <g
511
+ class="alpha-arc-comparison__vs"
512
+ :class="{ 'alpha-arc-comparison--animated': isAnimated }"
513
+ >
514
+ <circle
515
+ :cx="geo.vsCenter.x"
516
+ :cy="geo.vsCenter.y"
517
+ :r="geo.vsRadius"
518
+ fill="#ffffff"
519
+ stroke="#cbd5e1"
520
+ stroke-width="2"
521
+ class="transition-colors duration-300 dark:fill-slate-100 dark:stroke-slate-300"
522
+ style="filter: drop-shadow(0 2px 6px rgba(0, 0, 0, 0.22));"
523
+ />
524
+ <text
525
+ :x="geo.vsCenter.x"
526
+ :y="geo.vsCenter.y"
527
+ text-anchor="middle"
528
+ dominant-baseline="central"
529
+ font-weight="700"
530
+ :font-size="props.vsSize"
531
+ fill="#0f172a"
532
+ letter-spacing="-0.01em"
533
+ class="dark:fill-slate-900 select-none pointer-events-none"
534
+ style="font-family: ui-sans-serif, system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;"
535
+ >
536
+ {{ props.vsText }}
537
+ </text>
538
+ </g>
539
+ </svg>
540
+ <!-- Compound Content Layer -->
541
+ <template v-if="defaultNodes.length > 0">
542
+ <component :is="node" v-for="(node, i) in defaultNodes" :key="i" />
543
+ </template>
544
+ <template v-else>
545
+ <ArcComparisonLeft :count="resolvedCount" />
546
+ <ArcComparisonRight :count="resolvedCount" />
547
+ </template>
548
+ </div>
549
+ </div>
550
+ </template>
551
+
552
+ <style scoped>
553
+ /* Animated Transitions */
554
+ .alpha-arc-comparison--animated.alpha-arc-comparison__divider:not(.alpha-arc-comparison__divider--layout) {
555
+ animation: arc-divider-in 500ms cubic-bezier(0.16, 1, 0.3, 1) calc(var(--arc-comparison-start-delay, 0ms) + 50ms) both;
556
+ transform-origin: 500px 240px;
557
+ transform-box: view-box;
558
+ }
559
+
560
+ .alpha-arc-comparison--animated.alpha-arc-comparison__divider--layout {
561
+ animation: arc-line-fade 500ms cubic-bezier(0.16, 1, 0.3, 1) calc(var(--arc-comparison-start-delay, 0ms) + 50ms) both;
562
+ }
563
+
564
+ .alpha-arc-comparison__divider--layout {
565
+ transform-box: view-box;
566
+ transition: transform 700ms cubic-bezier(0.16, 1, 0.3, 1);
567
+ }
568
+
569
+ .alpha-arc-comparison--animated.alpha-arc-comparison__hub--left {
570
+ animation: arc-hub-left-in 550ms cubic-bezier(0.16, 1, 0.3, 1) calc(var(--arc-comparison-start-delay, 0ms) + 30ms) both;
571
+ }
572
+
573
+ .alpha-arc-comparison--animated.alpha-arc-comparison__hub--right {
574
+ animation: arc-hub-right-in 550ms cubic-bezier(0.16, 1, 0.3, 1) calc(var(--arc-comparison-start-delay, 0ms) + 30ms) both;
575
+ }
576
+
577
+ .alpha-arc-comparison--animated.alpha-arc-comparison__arc--left,
578
+ .alpha-arc-comparison--animated.alpha-arc-comparison__arc--right {
579
+ animation: arc-line-fade 500ms cubic-bezier(0.16, 1, 0.3, 1) calc(var(--arc-comparison-start-delay, 0ms) + 100ms) both;
580
+ }
581
+
582
+ .alpha-arc-comparison--animated.alpha-arc-comparison__vs {
583
+ animation: arc-vs-bounce 550ms cubic-bezier(0.34, 1.56, 0.64, 1) calc(var(--arc-comparison-start-delay, 0ms) + 220ms) both;
584
+ transform-origin: 500px 240px;
585
+ transform-box: view-box;
586
+ }
587
+
588
+ @keyframes arc-divider-in {
589
+ 0% {
590
+ opacity: 0;
591
+ transform: scaleY(0);
592
+ transform-origin: center;
593
+ }
594
+ 100% {
595
+ opacity: 1;
596
+ transform: scaleY(1);
597
+ }
598
+ }
599
+
600
+ @keyframes arc-hub-left-in {
601
+ 0% {
602
+ opacity: 0;
603
+ transform: translateX(-40px);
604
+ }
605
+ 100% {
606
+ opacity: 1;
607
+ transform: translateX(0);
608
+ }
609
+ }
610
+
611
+ @keyframes arc-hub-right-in {
612
+ 0% {
613
+ opacity: 0;
614
+ transform: translateX(40px);
615
+ }
616
+ 100% {
617
+ opacity: 1;
618
+ transform: translateX(0);
619
+ }
620
+ }
621
+
622
+ @keyframes arc-line-fade {
623
+ 0% {
624
+ opacity: 0;
625
+ }
626
+ 100% {
627
+ opacity: 1;
628
+ }
629
+ }
630
+
631
+ @keyframes arc-vs-bounce {
632
+ 0% {
633
+ opacity: 0;
634
+ transform: scale(0.4);
635
+ }
636
+ 100% {
637
+ opacity: 1;
638
+ transform: scale(1);
639
+ }
640
+ }
641
+
642
+ /* Hub mover transitions for layout mode on click */
643
+ .alpha-arc-comparison__hub-mover {
644
+ transition: transform 700ms cubic-bezier(0.16, 1, 0.3, 1);
645
+ }
646
+
647
+ .alpha-arc-comparison__hub-mover--left.alpha-arc-comparison__hub-mover--moved {
648
+ transform: translateX(-470px);
649
+ }
650
+
651
+ .alpha-arc-comparison__hub-mover--right.alpha-arc-comparison__hub-mover--moved {
652
+ transform: translateX(470px);
653
+ }
654
+ </style>
@@ -0,0 +1,29 @@
1
+ <script setup lang="ts">
2
+ import ArcOrbitBadge, {
3
+ type IArcOrbitBadgeProps,
4
+ } from '../../core/arc-orbit/ArcOrbitBadge.vue';
5
+
6
+ defineOptions({
7
+ inheritAttrs: false,
8
+ name: 'ArcComparisonBadge',
9
+ });
10
+
11
+ export interface IArcComparisonBadgeProps extends IArcOrbitBadgeProps {}
12
+
13
+ const props = defineProps<IArcComparisonBadgeProps>();
14
+ </script>
15
+
16
+ <template>
17
+ <ArcOrbitBadge
18
+ v-if="$slots.default"
19
+ v-bind="{ ...props, ...$attrs }"
20
+ class="alpha-arc-comparison-badge"
21
+ >
22
+ <slot />
23
+ </ArcOrbitBadge>
24
+ <ArcOrbitBadge
25
+ v-else
26
+ v-bind="{ ...props, ...$attrs }"
27
+ class="alpha-arc-comparison-badge"
28
+ />
29
+ </template>
@@ -0,0 +1,29 @@
1
+ <script setup lang="ts">
2
+ import ArcOrbitContent, {
3
+ type IArcOrbitContentProps,
4
+ } from '../../core/arc-orbit/ArcOrbitContent.vue';
5
+
6
+ defineOptions({
7
+ inheritAttrs: false,
8
+ name: 'ArcComparisonContent',
9
+ });
10
+
11
+ export interface IArcComparisonContentProps extends IArcOrbitContentProps {}
12
+
13
+ const props = defineProps<IArcComparisonContentProps>();
14
+ </script>
15
+
16
+ <template>
17
+ <ArcOrbitContent
18
+ v-if="$slots.default"
19
+ v-bind="{ ...props, ...$attrs }"
20
+ class="alpha-arc-comparison-content"
21
+ >
22
+ <slot />
23
+ </ArcOrbitContent>
24
+ <ArcOrbitContent
25
+ v-else
26
+ v-bind="{ ...props, ...$attrs }"
27
+ class="alpha-arc-comparison-content"
28
+ />
29
+ </template>