@alphacifer/slidev-addon-theme 0.0.7 → 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 +106 -76
  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/{comparison-table/ComparisonTable.vue → comparisons/table-comparison/TableComparison.vue} +37 -27
  27. package/components/{comparison-table/ComparisonTableCell.vue → comparisons/table-comparison/TableComparisonCell.vue} +8 -8
  28. package/components/{comparison-table/ComparisonTableCol.vue → comparisons/table-comparison/TableComparisonCol.vue} +10 -10
  29. package/components/{comparison-table/ComparisonTableCols.vue → comparisons/table-comparison/TableComparisonCols.vue} +11 -11
  30. package/components/{comparison-table/ComparisonTableRow.vue → comparisons/table-comparison/TableComparisonRow.vue} +9 -9
  31. package/components/{comparison-table/ComparisonTableRows.vue → comparisons/table-comparison/TableComparisonRows.vue} +3 -3
  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/{comparisonTable → tableComparison}/context.ts +6 -6
  87. package/utils/useDiagramAutoScale.ts +1 -1
  88. package/components/arc-compare/ArcCompare.vue +0 -443
  89. package/components/arc-compare/ArcCompareCallout.vue +0 -386
  90. package/components/arc-compare/ArcCompareLeft.vue +0 -183
  91. package/components/arc-compare/ArcCompareRight.vue +0 -183
  92. package/components/arc-compare/ArcCompareTitle.vue +0 -47
  93. package/utils/arcCompare/context.ts +0 -36
  94. package/utils/arcCompare/index.ts +0 -3
  95. package/utils/quadHub/context.ts +0 -26
  96. package/utils/quadHub/index.ts +0 -3
  97. /package/components/{shifting-heading → core}/TransitionHeading.vue +0 -0
  98. /package/components/{thanks → core/thanks}/ThanksContent.vue +0 -0
  99. /package/components/{arrow-triad → facets/triad/arrow-triad}/ArrowTriadIcon.vue +0 -0
  100. /package/components/{hex-triad → facets/triad/hex-triad}/HexTriadCenterBadge.vue +0 -0
  101. /package/components/{hex-triad → facets/triad/hex-triad}/HexTriadContent.vue +0 -0
  102. /package/components/{hex-triad → facets/triad/hex-triad}/HexTriadLayer.vue +0 -0
  103. /package/components/{arc-arrow-process → process/arc-arrow-process}/ArcArrowProcessIcon.vue +0 -0
  104. /package/utils/{comparisonTable → tableComparison}/constants.ts +0 -0
  105. /package/utils/{comparisonTable → tableComparison}/index.ts +0 -0
@@ -1,15 +1,17 @@
1
- export interface IArcComparePoint {
1
+ export type TArcOrbitPosition = 'left' | 'right';
2
+
3
+ export interface IArcOrbitPoint {
2
4
  readonly x: number;
3
5
  readonly y: number;
4
6
  }
5
7
 
6
- export interface IArcCompareNodeGeo {
8
+ export interface IArcOrbitNodeGeo {
7
9
  readonly index: number;
8
- readonly center: IArcComparePoint;
10
+ readonly center: IArcOrbitPoint;
9
11
  readonly radius: number;
10
12
  }
11
13
 
12
- export interface IArcCompareCalloutBox {
14
+ export interface IArcOrbitCalloutBox {
13
15
  readonly index: number;
14
16
  readonly x: number;
15
17
  readonly y: number;
@@ -20,72 +22,58 @@ export interface IArcCompareCalloutBox {
20
22
  readonly textWidth?: number;
21
23
  }
22
24
 
23
- export interface IArcCompareSideGeometry {
24
- readonly hubPath: string;
25
- readonly hubCenter: IArcComparePoint;
25
+ export interface IArcOrbitGeometry {
26
+ readonly viewBoxWidth: number;
27
+ readonly viewBoxHeight: number;
28
+ readonly position: TArcOrbitPosition;
29
+ readonly hubCenter: IArcOrbitPoint;
26
30
  readonly hubRadius: number;
31
+ readonly hubPath: string;
27
32
  readonly arcPath: string;
28
- readonly topDot: IArcComparePoint;
29
- readonly bottomDot: IArcComparePoint;
33
+ readonly topDot: IArcOrbitPoint;
34
+ readonly bottomDot: IArcOrbitPoint;
30
35
  readonly dotRadius: number;
31
- readonly nodes: readonly IArcCompareNodeGeo[];
32
- readonly callouts: readonly IArcCompareCalloutBox[];
33
- }
34
-
35
- export interface IArcCompareGeometry {
36
- readonly viewBoxWidth: number;
37
- readonly viewBoxHeight: number;
38
- readonly centerX: number;
39
- readonly centerY: number;
40
- readonly vsCenter: IArcComparePoint;
41
- readonly vsRadius: number;
36
+ readonly nodes: readonly IArcOrbitNodeGeo[];
37
+ readonly callouts: readonly IArcOrbitCalloutBox[];
42
38
  readonly pointsCount: number;
43
- readonly dividerLine: {
44
- readonly x: number;
45
- readonly y1: number;
46
- readonly y2: number;
47
- };
48
- readonly left: IArcCompareSideGeometry;
49
- readonly right: IArcCompareSideGeometry;
50
39
  }
51
40
 
52
- export interface ICreateArcCompareGeometryOptions {
41
+ export interface ICreateArcOrbitGeometryOptions {
53
42
  readonly viewBoxWidth?: number;
54
43
  readonly viewBoxHeight?: number;
44
+ readonly position?: TArcOrbitPosition;
55
45
  readonly hubRadius?: number;
46
+ readonly edgeOffset?: number;
56
47
  readonly arcRadius?: number;
57
48
  readonly arcOffset?: number;
58
49
  readonly nodeRadius?: number;
59
50
  readonly nodeAngleDeg?: number;
60
51
  readonly arcExtentDeg?: number;
61
- readonly vsRadius?: number;
62
52
  readonly pointsCount?: number;
63
53
  }
64
54
 
65
- export function createArcCompareGeometry(
66
- options: ICreateArcCompareGeometryOptions = {},
67
- ): IArcCompareGeometry {
68
- const viewBoxWidth = options.viewBoxWidth ?? 1000;
55
+ export function createArcOrbitGeometry(
56
+ options: ICreateArcOrbitGeometryOptions = {},
57
+ ): IArcOrbitGeometry {
58
+ const viewBoxWidth = options.viewBoxWidth ?? 500;
69
59
  const viewBoxHeight = options.viewBoxHeight ?? 480;
60
+ const position: TArcOrbitPosition = options.position ?? 'left';
70
61
  const hubRadius = options.hubRadius ?? 135;
62
+ const edgeOffset = options.edgeOffset !== undefined ? options.edgeOffset : 30;
71
63
  const arcRadius = options.arcRadius ?? 235;
72
64
  const arcOffset = options.arcOffset ?? 25;
73
65
  const nodeRadius = options.nodeRadius ?? 26;
74
- const vsRadius = options.vsRadius ?? 26;
75
66
  const dotRadius = 3.5;
76
67
  const pointsCount = options.pointsCount === 4 ? 4 : 3;
77
68
 
78
69
  const defaultArcExtent = pointsCount === 4 ? 66 : 58;
79
70
  const arcExtentDeg = options.arcExtentDeg ?? defaultArcExtent;
71
+ const extentRad = (arcExtentDeg * Math.PI) / 180;
80
72
 
81
- const centerX = viewBoxWidth / 2;
82
73
  const centerY = viewBoxHeight / 2;
83
- const leftArcCenterX = -arcOffset;
84
-
85
- // Angular math for left side:
86
- const extentRad = (arcExtentDeg * Math.PI) / 180;
87
74
 
88
- // Left arc start (top) and end (bottom)
75
+ // Base left calculations (origin at x = 0)
76
+ const leftArcCenterX = -arcOffset;
89
77
  const leftStartCos = Math.cos(extentRad);
90
78
  const leftStartSin = Math.sin(extentRad);
91
79
  const leftTopX = Number(
@@ -95,25 +83,18 @@ export function createArcCompareGeometry(
95
83
  const leftBottomX = leftTopX;
96
84
  const leftBottomY = Number((centerY + arcRadius * leftStartSin).toFixed(2));
97
85
 
98
- // Left arc path
99
- const leftArcPath = `M ${leftTopX} ${leftTopY} A ${arcRadius} ${arcRadius} 0 0 1 ${leftBottomX} ${leftBottomY}`;
100
-
101
- // Left hub path (semicircle centered at 0, centerY)
102
- const leftHubPath = `M 0 ${centerY - hubRadius} A ${hubRadius} ${hubRadius} 0 0 1 0 ${centerY + hubRadius} Z`;
103
-
104
86
  // Determine node angles for 3 or 4 points
105
87
  const nodeAnglesDeg: readonly number[] =
106
88
  pointsCount === 4
107
89
  ? [50, 16.5, -16.5, -50]
108
90
  : [options.nodeAngleDeg ?? 38, 0, -(options.nodeAngleDeg ?? 38)];
109
91
 
110
- // Left nodes and callouts
111
- const leftCalloutGap = 26;
112
- const leftNodes: IArcCompareNodeGeo[] = [];
113
- const leftCallouts: IArcCompareCalloutBox[] = [];
114
92
  const defaultTextGap = 28;
115
93
  const textWidth = pointsCount === 4 ? 215 : 205;
116
94
 
95
+ const leftNodes: IArcOrbitNodeGeo[] = [];
96
+ const leftCallouts: IArcOrbitCalloutBox[] = [];
97
+
117
98
  for (let i = 0; i < pointsCount; i++) {
118
99
  const angleDeg = nodeAnglesDeg[i] ?? 0;
119
100
  const angleRad = (angleDeg * Math.PI) / 180;
@@ -133,14 +114,12 @@ export function createArcCompareGeometry(
133
114
 
134
115
  const badgeOffset = Math.round(nodeX - nodeRadius);
135
116
  const top = Math.round(nodeY - nodeRadius);
136
- // Only adjust position for 01 (index 0) so its text does not overlay the arc curve.
137
- // 02, 03, and 04 keep their standard natural gap.
138
117
  const textGap = i === 0 ? (pointsCount === 4 ? 46 : 36) : defaultTextGap;
139
118
  const width = Math.round(nodeRadius * 2 + textGap + textWidth);
140
119
 
141
120
  leftCallouts.push({
142
121
  index: i,
143
- x: nodeX + leftCalloutGap,
122
+ x: nodeX + 26,
144
123
  y: nodeY - 32,
145
124
  width,
146
125
  badgeOffset,
@@ -150,17 +129,46 @@ export function createArcCompareGeometry(
150
129
  });
151
130
  }
152
131
 
153
- // Right side (symmetrical reflection across centerX)
132
+ if (position === 'left') {
133
+ const leftArcPath = `M ${leftTopX} ${leftTopY} A ${arcRadius} ${arcRadius} 0 0 1 ${leftBottomX} ${leftBottomY}`;
134
+ const leftHubCenterX = edgeOffset;
135
+ const leftHubPath =
136
+ edgeOffset > 0
137
+ ? `M ${leftHubCenterX} ${centerY - hubRadius} A ${hubRadius} ${hubRadius} 0 0 1 ${leftHubCenterX} ${centerY + hubRadius} A ${hubRadius} ${hubRadius} 0 0 1 ${leftHubCenterX} ${centerY - hubRadius} Z`
138
+ : `M 0 ${centerY - hubRadius} A ${hubRadius} ${hubRadius} 0 0 1 0 ${centerY + hubRadius} Z`;
139
+
140
+ return {
141
+ viewBoxWidth,
142
+ viewBoxHeight,
143
+ position: 'left',
144
+ hubCenter: { x: leftHubCenterX, y: centerY },
145
+ hubRadius,
146
+ hubPath: leftHubPath,
147
+ arcPath: leftArcPath,
148
+ topDot: { x: leftTopX, y: leftTopY },
149
+ bottomDot: { x: leftBottomX, y: leftBottomY },
150
+ dotRadius,
151
+ nodes: leftNodes,
152
+ callouts: leftCallouts,
153
+ pointsCount,
154
+ };
155
+ }
156
+
157
+ // Right position: mirrored across viewBoxWidth
154
158
  const rightTopX = Number((viewBoxWidth - leftTopX).toFixed(2));
155
159
  const rightTopY = leftTopY;
156
160
  const rightBottomX = rightTopX;
157
161
  const rightBottomY = leftBottomY;
158
162
 
159
163
  const rightArcPath = `M ${rightTopX} ${rightTopY} A ${arcRadius} ${arcRadius} 0 0 0 ${rightBottomX} ${rightBottomY}`;
160
- const rightHubPath = `M ${viewBoxWidth} ${centerY - hubRadius} A ${hubRadius} ${hubRadius} 0 0 0 ${viewBoxWidth} ${centerY + hubRadius} Z`;
164
+ const rightHubCenterX = viewBoxWidth - edgeOffset;
165
+ const rightHubPath =
166
+ edgeOffset > 0
167
+ ? `M ${rightHubCenterX} ${centerY - hubRadius} A ${hubRadius} ${hubRadius} 0 0 1 ${rightHubCenterX} ${centerY + hubRadius} A ${hubRadius} ${hubRadius} 0 0 1 ${rightHubCenterX} ${centerY - hubRadius} Z`
168
+ : `M ${viewBoxWidth} ${centerY - hubRadius} A ${hubRadius} ${hubRadius} 0 0 0 ${viewBoxWidth} ${centerY + hubRadius} Z`;
161
169
 
162
- const rightNodes: IArcCompareNodeGeo[] = [];
163
- const rightCallouts: IArcCompareCalloutBox[] = [];
170
+ const rightNodes: IArcOrbitNodeGeo[] = [];
171
+ const rightCallouts: IArcOrbitCalloutBox[] = [];
164
172
 
165
173
  for (let i = 0; i < pointsCount; i++) {
166
174
  const leftNode = leftNodes[i];
@@ -184,7 +192,7 @@ export function createArcCompareGeometry(
184
192
 
185
193
  rightCallouts.push({
186
194
  index: i,
187
- x: centerX + 20,
195
+ x: rightNodeX - leftCallout.width,
188
196
  y: rightNodeY - 32,
189
197
  width: leftCallout.width,
190
198
  badgeOffset: leftCallout.badgeOffset,
@@ -197,58 +205,19 @@ export function createArcCompareGeometry(
197
205
  return {
198
206
  viewBoxWidth,
199
207
  viewBoxHeight,
200
- centerX,
201
- centerY,
202
- vsCenter: {
203
- x: centerX,
208
+ position: 'right',
209
+ hubCenter: {
210
+ x: rightHubCenterX,
204
211
  y: centerY,
205
212
  },
206
- vsRadius,
213
+ hubRadius,
214
+ hubPath: rightHubPath,
215
+ arcPath: rightArcPath,
216
+ topDot: { x: rightTopX, y: rightTopY },
217
+ bottomDot: { x: rightBottomX, y: rightBottomY },
218
+ dotRadius,
219
+ nodes: rightNodes,
220
+ callouts: rightCallouts,
207
221
  pointsCount,
208
- dividerLine: {
209
- x: centerX,
210
- y1: 20,
211
- y2: viewBoxHeight - 20,
212
- },
213
- left: {
214
- hubPath: leftHubPath,
215
- hubCenter: {
216
- x: 55,
217
- y: centerY,
218
- },
219
- hubRadius,
220
- arcPath: leftArcPath,
221
- topDot: {
222
- x: leftTopX,
223
- y: leftTopY,
224
- },
225
- bottomDot: {
226
- x: leftBottomX,
227
- y: leftBottomY,
228
- },
229
- dotRadius,
230
- nodes: leftNodes,
231
- callouts: leftCallouts,
232
- },
233
- right: {
234
- hubPath: rightHubPath,
235
- hubCenter: {
236
- x: viewBoxWidth - 55,
237
- y: centerY,
238
- },
239
- hubRadius,
240
- arcPath: rightArcPath,
241
- topDot: {
242
- x: rightTopX,
243
- y: rightTopY,
244
- },
245
- bottomDot: {
246
- x: rightBottomX,
247
- y: rightBottomY,
248
- },
249
- dotRadius,
250
- nodes: rightNodes,
251
- callouts: rightCallouts,
252
- },
253
222
  };
254
223
  }
@@ -0,0 +1,3 @@
1
+ export * from './context';
2
+ export * from './createArcOrbitGeometry';
3
+ export * from './resolveArcOrbitItems';
@@ -0,0 +1,92 @@
1
+ export interface IArcOrbitItem {
2
+ readonly id?: string | number;
3
+ readonly title?: string;
4
+ readonly description?: string;
5
+ readonly color?: string;
6
+ readonly textColor?: string;
7
+ }
8
+
9
+ export interface IResolvedArcOrbitItem {
10
+ readonly id: string | number;
11
+ readonly title: string;
12
+ readonly description: string;
13
+ readonly color: string;
14
+ readonly textColor?: string;
15
+ }
16
+
17
+ export const DEFAULT_ARC_ORBIT_COLOR = '#ea580c';
18
+
19
+ export const DEFAULT_LOREM_TEXT =
20
+ 'Lorem ipsum dolor sit amet, constitutor adipiscing elit. Nam vulputate augue vel ligula.';
21
+
22
+ export const DEFAULT_ARC_ORBIT_ITEMS: readonly [
23
+ IResolvedArcOrbitItem,
24
+ IResolvedArcOrbitItem,
25
+ IResolvedArcOrbitItem,
26
+ IResolvedArcOrbitItem,
27
+ ] = [
28
+ {
29
+ id: '01',
30
+ title: 'Add Text Here',
31
+ description: DEFAULT_LOREM_TEXT,
32
+ color: DEFAULT_ARC_ORBIT_COLOR,
33
+ },
34
+ {
35
+ id: '02',
36
+ title: 'Add Text Here',
37
+ description: DEFAULT_LOREM_TEXT,
38
+ color: DEFAULT_ARC_ORBIT_COLOR,
39
+ },
40
+ {
41
+ id: '03',
42
+ title: 'Add Text Here',
43
+ description: DEFAULT_LOREM_TEXT,
44
+ color: DEFAULT_ARC_ORBIT_COLOR,
45
+ },
46
+ {
47
+ id: '04',
48
+ title: 'Add Text Here',
49
+ description: DEFAULT_LOREM_TEXT,
50
+ color: DEFAULT_ARC_ORBIT_COLOR,
51
+ },
52
+ ];
53
+
54
+ export interface IResolveArcOrbitItemsOptions {
55
+ readonly items?: readonly IArcOrbitItem[];
56
+ readonly defaultColor?: string;
57
+ readonly count?: number;
58
+ }
59
+
60
+ export function resolveArcOrbitItems(
61
+ options: IResolveArcOrbitItemsOptions = {},
62
+ ): readonly IResolvedArcOrbitItem[] {
63
+ const { items, defaultColor = DEFAULT_ARC_ORBIT_COLOR, count = 3 } = options;
64
+
65
+ const result: IResolvedArcOrbitItem[] = [];
66
+
67
+ for (let i = 0; i < count; i++) {
68
+ const custom = items?.[i];
69
+ const defaultItem = DEFAULT_ARC_ORBIT_ITEMS[i];
70
+
71
+ const id =
72
+ custom?.id !== undefined
73
+ ? custom.id
74
+ : (defaultItem?.id ?? String(i + 1).padStart(2, '0'));
75
+
76
+ const title = custom?.title ?? defaultItem?.title ?? 'Add Text Here';
77
+ const description =
78
+ custom?.description ?? defaultItem?.description ?? DEFAULT_LOREM_TEXT;
79
+ const color = custom?.color ?? defaultColor;
80
+ const textColor = custom?.textColor ?? defaultItem?.textColor;
81
+
82
+ result.push({
83
+ id,
84
+ title,
85
+ description,
86
+ color,
87
+ textColor,
88
+ });
89
+ }
90
+
91
+ return result;
92
+ }
@@ -0,0 +1,51 @@
1
+ import type { ComputedRef, InjectionKey } from 'vue';
2
+
3
+ import type {
4
+ IGearTriadItem,
5
+ IResolvedGearTriadItem,
6
+ } from './resolveGearTriadItems';
7
+
8
+ export interface IGearTriadRegistration {
9
+ readonly index: number;
10
+ readonly item: ComputedRef<IResolvedGearTriadItem>;
11
+ }
12
+
13
+ export interface IGearTriadRootContext {
14
+ readonly animation: ComputedRef<boolean>;
15
+ readonly isShifted: ComputedRef<boolean>;
16
+ readonly currentStep: ComputedRef<number>;
17
+ readonly activeOptionIndex: ComputedRef<number>;
18
+ readonly hasContents: ComputedRef<boolean>;
19
+ readonly registerCallout: (
20
+ override?: ComputedRef<IGearTriadItem> | (() => IGearTriadItem),
21
+ ) => IGearTriadRegistration;
22
+ readonly registerContents: () => void;
23
+ readonly items: ComputedRef<
24
+ readonly [
25
+ IResolvedGearTriadItem,
26
+ IResolvedGearTriadItem,
27
+ IResolvedGearTriadItem,
28
+ ]
29
+ >;
30
+ }
31
+
32
+ export interface IGearTriadCalloutContext {
33
+ readonly item: ComputedRef<IResolvedGearTriadItem>;
34
+ readonly index: number;
35
+ }
36
+
37
+ export interface IGearTriadContentsContext {
38
+ readonly activeItem: ComputedRef<IResolvedGearTriadItem>;
39
+ readonly activeOptionIndex: ComputedRef<number>;
40
+ readonly registerContent: (option?: number) => { index: number };
41
+ }
42
+
43
+ export const GEAR_TRIAD_ROOT_KEY: InjectionKey<IGearTriadRootContext> = Symbol(
44
+ 'GEAR_TRIAD_ROOT_KEY',
45
+ );
46
+
47
+ export const GEAR_TRIAD_CALLOUT_KEY: InjectionKey<IGearTriadCalloutContext> =
48
+ Symbol('GEAR_TRIAD_CALLOUT_KEY');
49
+
50
+ export const GEAR_TRIAD_CONTENTS_KEY: InjectionKey<IGearTriadContentsContext> =
51
+ Symbol('GEAR_TRIAD_CONTENTS_KEY');
@@ -0,0 +1,210 @@
1
+ export interface IGearTriadPoint {
2
+ readonly x: number;
3
+ readonly y: number;
4
+ }
5
+
6
+ export interface IGearTriadPetalGeometry {
7
+ readonly facePath: string;
8
+ readonly valleyPath: string;
9
+ readonly leftFoldPath: string;
10
+ readonly rightFoldPath: string;
11
+ readonly iconPosition: IGearTriadPoint;
12
+ }
13
+
14
+ export interface IGearTriadSectorGeometry extends IGearTriadPetalGeometry {}
15
+
16
+ export interface IGearTriadGeometry {
17
+ readonly viewBoxWidth: number;
18
+ readonly viewBoxHeight: number;
19
+ readonly centerX: number;
20
+ readonly centerY: number;
21
+ readonly hubRadius: number;
22
+ readonly baseGearPath: string;
23
+ readonly valleyPath: string;
24
+ /**
25
+ * One canonical petal geometry (facing South, 270 deg).
26
+ * Reused for all 3 sectors via 0 deg (Pink), 120 deg (Cyan), and 240 deg (Orange).
27
+ */
28
+ readonly petal: IGearTriadPetalGeometry;
29
+ readonly cyanSector: IGearTriadSectorGeometry;
30
+ readonly orangeSector: IGearTriadSectorGeometry;
31
+ readonly pinkSector: IGearTriadSectorGeometry;
32
+ }
33
+
34
+ /**
35
+ * Polar to Cartesian conversion in SVG screen space:
36
+ * - 0 deg = East (3 o'clock)
37
+ * - 90 deg = North (12 o'clock, straight UP)
38
+ * - 180 deg = West (9 o'clock)
39
+ * - 270 deg = South (6 o'clock, straight DOWN)
40
+ */
41
+ function polarToCartesian(
42
+ cx: number,
43
+ cy: number,
44
+ radius: number,
45
+ angleInDegrees: number,
46
+ ): IGearTriadPoint {
47
+ const radians = (angleInDegrees * Math.PI) / 180;
48
+
49
+ return {
50
+ x: Number((cx + radius * Math.cos(radians)).toFixed(2)),
51
+ y: Number((cy - radius * Math.sin(radians)).toFixed(2)),
52
+ };
53
+ }
54
+
55
+ function rotatePoint(
56
+ p: IGearTriadPoint,
57
+ cx: number,
58
+ cy: number,
59
+ degrees: number,
60
+ ): IGearTriadPoint {
61
+ const rad = (degrees * Math.PI) / 180;
62
+ const dx = p.x - cx;
63
+ const dy = p.y - cy;
64
+
65
+ return {
66
+ x: Number((dx * Math.cos(rad) - dy * Math.sin(rad) + cx).toFixed(2)),
67
+ y: Number((dx * Math.sin(rad) + dy * Math.cos(rad) + cy).toFixed(2)),
68
+ };
69
+ }
70
+
71
+ export function createGearTriadGeometry(): IGearTriadGeometry {
72
+ const viewBoxWidth = 540;
73
+ const viewBoxHeight = 480;
74
+ const centerX = 270;
75
+ const centerY = 220;
76
+ const rOut = 180;
77
+ const rNotch = 128;
78
+ const hubRadius = 54;
79
+
80
+ // Base 6-tooth gear with rounded valleys (6 teeth at 0, 60, 120, 180, 240, 300 deg)
81
+ const toothCenters = [0, 60, 120, 180, 240, 300];
82
+ let baseGearPath = '';
83
+ for (let i = 0; i < toothCenters.length; i++) {
84
+ const th = toothCenters[i] ?? 0;
85
+ const p1 = polarToCartesian(centerX, centerY, rOut, th - 10);
86
+ const p2 = polarToCartesian(centerX, centerY, rOut, th + 10);
87
+ const p3 = polarToCartesian(centerX, centerY, rNotch, th + 20);
88
+ const p4 = polarToCartesian(centerX, centerY, rNotch, th + 40);
89
+ if (i === 0) {
90
+ baseGearPath += `M ${p1.x} ${p1.y}`;
91
+ } else {
92
+ baseGearPath += ` L ${p1.x} ${p1.y}`;
93
+ }
94
+ baseGearPath += ` L ${p2.x} ${p2.y} L ${p3.x} ${p3.y} A ${rNotch} ${rNotch} 0 0 0 ${p4.x} ${p4.y}`;
95
+ }
96
+ baseGearPath += ' Z';
97
+
98
+ // ONE CANONICAL PETAL SHAPE (pointing South / 270 deg):
99
+ // Reused across all 3 sectors via 0 deg (Pink), 120 deg (Cyan), and 240 deg (Orange)
100
+ const p0 = polarToCartesian(centerX, centerY, hubRadius, 230);
101
+ const p1 = polarToCartesian(centerX, centerY, rOut, 230);
102
+ const p2 = polarToCartesian(centerX, centerY, rOut, 250);
103
+ const p3a = polarToCartesian(centerX, centerY, rNotch, 260);
104
+ const p3b = polarToCartesian(centerX, centerY, rNotch, 280);
105
+ const p4 = polarToCartesian(centerX, centerY, rOut, 290);
106
+ const p5 = polarToCartesian(centerX, centerY, rOut, 310);
107
+ const p6 = polarToCartesian(centerX, centerY, hubRadius, 310);
108
+
109
+ const petalFacePath = [
110
+ `M ${p0.x} ${p0.y}`,
111
+ `L ${p1.x} ${p1.y}`,
112
+ `L ${p2.x} ${p2.y}`,
113
+ `L ${p3a.x} ${p3a.y}`,
114
+ `A ${rNotch} ${rNotch} 0 0 0 ${p3b.x} ${p3b.y}`,
115
+ `L ${p4.x} ${p4.y}`,
116
+ `L ${p5.x} ${p5.y}`,
117
+ `L ${p6.x} ${p6.y}`,
118
+ `A ${hubRadius} ${hubRadius} 0 0 1 ${p0.x} ${p0.y}`,
119
+ 'Z',
120
+ ].join(' ');
121
+
122
+ // The unified canonical shape between the colored petals (centered at 210 deg):
123
+ // Reused across all 3 inter-sector positions via 0 deg, 120 deg, and 240 deg rotations.
124
+ const pvFlankPink = polarToCartesian(centerX, centerY, rOut, 230);
125
+ const pvNotchPink = polarToCartesian(centerX, centerY, rNotch, 220);
126
+ const pvNotchCyan = polarToCartesian(centerX, centerY, rNotch, 200);
127
+ const pvFlankCyan = polarToCartesian(centerX, centerY, rOut, 190);
128
+ const pvHubCyan = polarToCartesian(centerX, centerY, hubRadius, 190);
129
+ const pvHubPink = polarToCartesian(centerX, centerY, hubRadius, 230);
130
+
131
+ const valleyPath = [
132
+ `M ${pvFlankPink.x} ${pvFlankPink.y}`,
133
+ `L ${pvNotchPink.x} ${pvNotchPink.y}`,
134
+ `A ${rNotch} ${rNotch} 0 0 1 ${pvNotchCyan.x} ${pvNotchCyan.y}`,
135
+ `L ${pvFlankCyan.x} ${pvFlankCyan.y}`,
136
+ `L ${pvHubCyan.x} ${pvHubCyan.y}`,
137
+ `A ${hubRadius} ${hubRadius} 0 0 0 ${pvHubPink.x} ${pvHubPink.y}`,
138
+ 'Z',
139
+ ].join(' ');
140
+
141
+ // Legacy fold paths maintained for backwards compatibility
142
+ const pValley220 = polarToCartesian(centerX, centerY, rNotch, 220);
143
+ const pValley210 = polarToCartesian(centerX, centerY, rNotch, 210);
144
+ const pHub210 = polarToCartesian(centerX, centerY, hubRadius, 210);
145
+
146
+ const leftFoldPath = [
147
+ `M ${p1.x} ${p1.y}`,
148
+ `L ${pValley220.x} ${pValley220.y}`,
149
+ `A ${rNotch} ${rNotch} 0 0 0 ${pValley210.x} ${pValley210.y}`,
150
+ `L ${pHub210.x} ${pHub210.y}`,
151
+ `A ${hubRadius} ${hubRadius} 0 0 1 ${p0.x} ${p0.y}`,
152
+ 'Z',
153
+ ].join(' ');
154
+
155
+ const pValley320 = polarToCartesian(centerX, centerY, rNotch, 320);
156
+ const pValley330 = polarToCartesian(centerX, centerY, rNotch, 330);
157
+ const pHub330 = polarToCartesian(centerX, centerY, hubRadius, 330);
158
+
159
+ const rightFoldPath = [
160
+ `M ${p5.x} ${p5.y}`,
161
+ `L ${pValley320.x} ${pValley320.y}`,
162
+ `A ${rNotch} ${rNotch} 0 0 1 ${pValley330.x} ${pValley330.y}`,
163
+ `L ${pHub330.x} ${pHub330.y}`,
164
+ `A ${hubRadius} ${hubRadius} 0 0 0 ${p6.x} ${p6.y}`,
165
+ 'Z',
166
+ ].join(' ');
167
+
168
+ const canonicalIconPos = polarToCartesian(centerX, centerY, 105, 270);
169
+
170
+ const canonicalPetal: IGearTriadPetalGeometry = {
171
+ facePath: petalFacePath,
172
+ valleyPath,
173
+ leftFoldPath,
174
+ rightFoldPath,
175
+ iconPosition: canonicalIconPos,
176
+ };
177
+
178
+ // The 3 sectors reuse the canonical petal rotated by 120 deg intervals:
179
+ // - Pink (Option 3, Bottom): rotation 0 deg
180
+ // - Cyan (Option 1, Top-Left): rotation 120 deg
181
+ // - Orange (Option 2, Top-Right): rotation 240 deg
182
+ const pinkSector: IGearTriadSectorGeometry = {
183
+ ...canonicalPetal,
184
+ iconPosition: canonicalIconPos,
185
+ };
186
+
187
+ const cyanSector: IGearTriadSectorGeometry = {
188
+ ...canonicalPetal,
189
+ iconPosition: rotatePoint(canonicalIconPos, centerX, centerY, 120),
190
+ };
191
+
192
+ const orangeSector: IGearTriadSectorGeometry = {
193
+ ...canonicalPetal,
194
+ iconPosition: rotatePoint(canonicalIconPos, centerX, centerY, 240),
195
+ };
196
+
197
+ return {
198
+ viewBoxWidth,
199
+ viewBoxHeight,
200
+ centerX,
201
+ centerY,
202
+ hubRadius,
203
+ baseGearPath,
204
+ valleyPath,
205
+ petal: canonicalPetal,
206
+ cyanSector,
207
+ orangeSector,
208
+ pinkSector,
209
+ };
210
+ }
@@ -0,0 +1,3 @@
1
+ export * from './context';
2
+ export * from './createGearTriadGeometry';
3
+ export * from './resolveGearTriadItems';