@alphacifer/slidev-addon-theme 0.0.5 → 0.0.7
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +163 -2
- package/components/arc-arrow-process/ArcArrowProcess.vue +361 -0
- package/components/arc-arrow-process/ArcArrowProcessArrow.vue +143 -0
- package/components/arc-arrow-process/ArcArrowProcessCallout.vue +361 -0
- package/components/arc-arrow-process/ArcArrowProcessContent.vue +38 -0
- package/components/arc-arrow-process/ArcArrowProcessHeading.vue +43 -0
- package/components/arc-arrow-process/ArcArrowProcessIcon.vue +154 -0
- package/components/arc-compare/ArcCompare.vue +443 -0
- package/components/arc-compare/ArcCompareBadge.vue +63 -0
- package/components/arc-compare/ArcCompareCallout.vue +386 -0
- package/components/arc-compare/ArcCompareContent.vue +52 -0
- package/components/arc-compare/ArcCompareContents.vue +18 -0
- package/components/arc-compare/ArcCompareHeading.vue +52 -0
- package/components/arc-compare/ArcCompareLeft.vue +183 -0
- package/components/arc-compare/ArcCompareRight.vue +183 -0
- package/components/arc-compare/ArcCompareTitle.vue +47 -0
- package/components/arrow-triad/ArrowTriad.vue +368 -0
- package/components/arrow-triad/ArrowTriadCallout.vue +300 -0
- package/components/arrow-triad/ArrowTriadContent.vue +38 -0
- package/components/arrow-triad/ArrowTriadHeading.vue +38 -0
- package/components/arrow-triad/ArrowTriadIcon.vue +96 -0
- package/components/chevron-card/ChevronCard.vue +237 -0
- package/components/chevron-card/ChevronCardBadge.vue +74 -0
- package/components/chevron-card/ChevronCardContent.vue +39 -0
- package/components/chevron-card/ChevronCardHeading.vue +39 -0
- package/components/comparison-table/ComparisonTable.vue +244 -0
- package/components/comparison-table/ComparisonTableCell.vue +88 -0
- package/components/comparison-table/ComparisonTableCol.vue +97 -0
- package/components/comparison-table/ComparisonTableCols.vue +74 -0
- package/components/comparison-table/ComparisonTableRow.vue +92 -0
- package/components/comparison-table/ComparisonTableRows.vue +21 -0
- package/components/hex-triad/HexTriad.vue +438 -0
- package/components/hex-triad/HexTriadBadge.vue +110 -0
- package/components/hex-triad/HexTriadCallout.vue +200 -0
- package/components/hex-triad/HexTriadCenterBadge.vue +51 -0
- package/components/hex-triad/HexTriadContent.vue +20 -0
- package/components/hex-triad/HexTriadHeading.vue +28 -0
- package/components/hex-triad/HexTriadLayer.vue +28 -0
- package/components/horiz-card/HorizCard.vue +318 -0
- package/components/horiz-card/HorizCardBadge.vue +75 -0
- package/components/horiz-card/HorizCardContent.vue +46 -0
- package/components/horiz-card/HorizCardHeading.vue +47 -0
- package/components/horiz-card/HorizCardIcon.vue +118 -0
- package/components/quad-hub/QuadHub.vue +642 -0
- package/components/quad-hub/QuadHubCallout.vue +267 -0
- package/components/quad-hub/QuadHubCenter.vue +53 -0
- package/components/quad-hub/QuadHubContent.vue +39 -0
- package/components/quad-hub/QuadHubHeading.vue +44 -0
- package/components/quad-hub/QuadHubIcon.vue +112 -0
- package/components/shifting-heading/TransitionHeading.vue +2 -2
- package/components/vert-card/VertCard.vue +389 -0
- package/components/vert-card/VertCardBadge.vue +72 -0
- package/components/vert-card/VertCardContent.vue +45 -0
- package/components/vert-card/VertCardHeading.vue +68 -0
- package/components/vert-card/VertCardIcon.vue +126 -0
- package/components/vert-card/VertCardTitle.vue +76 -0
- package/layouts/core/arc-toc.vue +76 -113
- package/layouts/core/bg-center.vue +32 -4
- package/layouts/shifting-heading/shifting-intro.vue +35 -7
- package/package.json +3 -2
- package/utils/arcArrowProcess/context.ts +28 -0
- package/utils/arcArrowProcess/createArcArrowProcessGeometry.ts +137 -0
- package/utils/arcArrowProcess/index.ts +3 -0
- package/utils/arcArrowProcess/resolveArcArrowProcessItems.ts +189 -0
- package/utils/arcCompare/context.ts +36 -0
- package/utils/arcCompare/createArcCompareGeometry.ts +254 -0
- package/utils/arcCompare/index.ts +3 -0
- package/utils/arcCompare/resolveArcCompareItems.ts +123 -0
- package/utils/arrowTriad/context.ts +38 -0
- package/utils/arrowTriad/createArrowTriadGeometry.ts +63 -0
- package/utils/arrowTriad/index.ts +3 -0
- package/utils/arrowTriad/resolveArrowTriadItems.ts +121 -0
- package/utils/chevronCard/context.ts +12 -0
- package/utils/chevronCard/createChevronCardGeometry.ts +48 -0
- package/utils/chevronCard/index.ts +2 -0
- package/utils/comparisonTable/constants.ts +72 -0
- package/utils/comparisonTable/context.ts +24 -0
- package/utils/comparisonTable/index.ts +2 -0
- package/utils/hexTriad/context.ts +25 -0
- package/utils/hexTriad/createHexTriadGeometry.ts +182 -0
- package/utils/hexTriad/index.ts +3 -0
- package/utils/hexTriad/resolveHexTriadItems.ts +63 -0
- package/utils/horizCard/context.ts +13 -0
- package/utils/horizCard/createHorizCardGeometry.ts +243 -0
- package/utils/horizCard/index.ts +2 -0
- package/utils/quadHub/context.ts +26 -0
- package/utils/quadHub/createQuadHubGeometry.ts +331 -0
- package/utils/quadHub/index.ts +3 -0
- package/utils/quadHub/resolveQuadHubItems.ts +214 -0
- package/utils/useDiagramAutoScale.ts +300 -0
- package/utils/vertCard/context.ts +18 -0
- package/utils/vertCard/createVertCardGeometry.ts +242 -0
- package/utils/vertCard/index.ts +2 -0
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
<script setup lang="ts">
|
|
2
|
+
import { computed, inject } from 'vue';
|
|
3
|
+
|
|
4
|
+
import {
|
|
5
|
+
COMPARISON_TABLE_KEY,
|
|
6
|
+
DEFAULT_ROW_HEADER_COLOR,
|
|
7
|
+
DEFAULT_ROW_HEADER_TEXT_COLOR,
|
|
8
|
+
resolveDimension,
|
|
9
|
+
} from '../../utils/comparisonTable';
|
|
10
|
+
import { useMergedUnoAttrs } from '../../utils/useMergedUnoAttrs';
|
|
11
|
+
|
|
12
|
+
defineOptions({
|
|
13
|
+
inheritAttrs: false,
|
|
14
|
+
name: 'ComparisonTableRow',
|
|
15
|
+
});
|
|
16
|
+
|
|
17
|
+
export interface IComparisonTableRowProps {
|
|
18
|
+
readonly title?: string;
|
|
19
|
+
readonly color?: string;
|
|
20
|
+
readonly textColor?: string;
|
|
21
|
+
readonly borderRadius?: number | string;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
const props = withDefaults(defineProps<IComparisonTableRowProps>(), {
|
|
25
|
+
title: undefined,
|
|
26
|
+
color: undefined,
|
|
27
|
+
textColor: undefined,
|
|
28
|
+
borderRadius: undefined,
|
|
29
|
+
});
|
|
30
|
+
|
|
31
|
+
const tableContext = inject(COMPARISON_TABLE_KEY, undefined);
|
|
32
|
+
|
|
33
|
+
const resolvedBg = computed(() => {
|
|
34
|
+
return (
|
|
35
|
+
props.color ??
|
|
36
|
+
tableContext?.rowHeaderColor.value ??
|
|
37
|
+
DEFAULT_ROW_HEADER_COLOR
|
|
38
|
+
);
|
|
39
|
+
});
|
|
40
|
+
|
|
41
|
+
const resolvedTextColor = computed(() => {
|
|
42
|
+
return (
|
|
43
|
+
props.textColor ??
|
|
44
|
+
tableContext?.rowHeaderTextColor.value ??
|
|
45
|
+
DEFAULT_ROW_HEADER_TEXT_COLOR
|
|
46
|
+
);
|
|
47
|
+
});
|
|
48
|
+
|
|
49
|
+
const resolvedBorderRadius = computed(() => {
|
|
50
|
+
return (
|
|
51
|
+
resolveDimension(props.borderRadius) ??
|
|
52
|
+
tableContext?.borderRadius.value ??
|
|
53
|
+
'8px'
|
|
54
|
+
);
|
|
55
|
+
});
|
|
56
|
+
|
|
57
|
+
const resolvedPadding = computed(() => {
|
|
58
|
+
return tableContext?.dense.value ? 'py-2 px-3' : 'py-3 px-4';
|
|
59
|
+
});
|
|
60
|
+
|
|
61
|
+
const headerStyle = computed(() => {
|
|
62
|
+
return {
|
|
63
|
+
backgroundColor: resolvedBg.value,
|
|
64
|
+
color: resolvedTextColor.value,
|
|
65
|
+
borderRadius: resolvedBorderRadius.value,
|
|
66
|
+
fontSize: '1rem',
|
|
67
|
+
textAlign: 'center' as const,
|
|
68
|
+
verticalAlign: 'middle' as const,
|
|
69
|
+
};
|
|
70
|
+
});
|
|
71
|
+
|
|
72
|
+
const { className, forwardedAttrs } = useMergedUnoAttrs(
|
|
73
|
+
'alpha-comparison-table-row',
|
|
74
|
+
);
|
|
75
|
+
</script>
|
|
76
|
+
|
|
77
|
+
<template>
|
|
78
|
+
<tr
|
|
79
|
+
v-bind="forwardedAttrs()"
|
|
80
|
+
:class="className()"
|
|
81
|
+
>
|
|
82
|
+
<th
|
|
83
|
+
scope="row"
|
|
84
|
+
class="alpha-comparison-table-row-title font-bold uppercase tracking-wider text-[1rem] leading-snug text-center align-middle select-text transition-all duration-200 [&_p]:text-[1rem] [&_p]:text-center [&_p]:m-0"
|
|
85
|
+
:class="resolvedPadding"
|
|
86
|
+
:style="headerStyle"
|
|
87
|
+
>
|
|
88
|
+
<slot name="title">{{ title }}</slot>
|
|
89
|
+
</th>
|
|
90
|
+
<slot />
|
|
91
|
+
</tr>
|
|
92
|
+
</template>
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
<script setup lang="ts">
|
|
2
|
+
import { useMergedUnoAttrs } from '../../utils/useMergedUnoAttrs';
|
|
3
|
+
|
|
4
|
+
defineOptions({
|
|
5
|
+
inheritAttrs: false,
|
|
6
|
+
name: 'ComparisonTableRows',
|
|
7
|
+
});
|
|
8
|
+
|
|
9
|
+
const { className, forwardedAttrs } = useMergedUnoAttrs(
|
|
10
|
+
'alpha-comparison-table-rows',
|
|
11
|
+
);
|
|
12
|
+
</script>
|
|
13
|
+
|
|
14
|
+
<template>
|
|
15
|
+
<tbody
|
|
16
|
+
v-bind="forwardedAttrs()"
|
|
17
|
+
:class="className()"
|
|
18
|
+
>
|
|
19
|
+
<slot />
|
|
20
|
+
</tbody>
|
|
21
|
+
</template>
|
|
@@ -0,0 +1,438 @@
|
|
|
1
|
+
<script setup lang="ts">
|
|
2
|
+
import {
|
|
3
|
+
type ComputedRef,
|
|
4
|
+
computed,
|
|
5
|
+
inject,
|
|
6
|
+
onBeforeUpdate,
|
|
7
|
+
provide,
|
|
8
|
+
ref,
|
|
9
|
+
} from 'vue';
|
|
10
|
+
|
|
11
|
+
import {
|
|
12
|
+
calculateHexTriadCoordinates,
|
|
13
|
+
createRoundedHexagonPath,
|
|
14
|
+
HEX_TRIAD_ROOT_KEY,
|
|
15
|
+
type IHexTriadItem,
|
|
16
|
+
resolveHexTriadItems,
|
|
17
|
+
} from '../../utils/hexTriad';
|
|
18
|
+
import { useMergedUnoAttrs } from '../../utils/useMergedUnoAttrs';
|
|
19
|
+
|
|
20
|
+
defineOptions({
|
|
21
|
+
inheritAttrs: false,
|
|
22
|
+
});
|
|
23
|
+
|
|
24
|
+
export interface IHexTriadProps {
|
|
25
|
+
readonly title?: string;
|
|
26
|
+
readonly subtitle?: string;
|
|
27
|
+
readonly animation?: boolean;
|
|
28
|
+
readonly items?: readonly IHexTriadItem[];
|
|
29
|
+
/**
|
|
30
|
+
* Additional delay (ms) before animation starts.
|
|
31
|
+
* Defaults to 600ms inside `shifting-intro` layout, 0ms otherwise.
|
|
32
|
+
*/
|
|
33
|
+
readonly startDelay?: number;
|
|
34
|
+
/**
|
|
35
|
+
* Manually control whether animation runs.
|
|
36
|
+
* Defaults to true, or automatically tracks `$clicks > 0` inside `shifting-intro`.
|
|
37
|
+
*/
|
|
38
|
+
readonly active?: boolean;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
const props = withDefaults(defineProps<IHexTriadProps>(), {
|
|
42
|
+
animation: true,
|
|
43
|
+
title: undefined,
|
|
44
|
+
items: undefined,
|
|
45
|
+
active: undefined,
|
|
46
|
+
subtitle: undefined,
|
|
47
|
+
startDelay: undefined,
|
|
48
|
+
});
|
|
49
|
+
|
|
50
|
+
const shiftingIntro = inject<
|
|
51
|
+
| {
|
|
52
|
+
active: ComputedRef<boolean>;
|
|
53
|
+
isShifting?: ComputedRef<boolean>;
|
|
54
|
+
}
|
|
55
|
+
| undefined
|
|
56
|
+
>('SLIDEV_LAYOUT_SHIFTING_INTRO', undefined);
|
|
57
|
+
|
|
58
|
+
const isAnimated = computed(() => {
|
|
59
|
+
if (!props.animation) {
|
|
60
|
+
return false;
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
if (props.active !== undefined) {
|
|
64
|
+
return props.active;
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
if (shiftingIntro) {
|
|
68
|
+
return shiftingIntro.active.value;
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
return true;
|
|
72
|
+
});
|
|
73
|
+
|
|
74
|
+
const resolvedStartDelay = computed(() => {
|
|
75
|
+
if (props.startDelay !== undefined) {
|
|
76
|
+
return props.startDelay;
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
if (shiftingIntro) {
|
|
80
|
+
// Only delay 600ms when the heading is actively shifting up from click 0.
|
|
81
|
+
// On reload at click >= 1, heading is already at the top -> 0ms delay!
|
|
82
|
+
return shiftingIntro.isShifting?.value ? 600 : 0;
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
return 0;
|
|
86
|
+
});
|
|
87
|
+
|
|
88
|
+
const resolvedItems = computed(() => resolveHexTriadItems(props.items));
|
|
89
|
+
|
|
90
|
+
let calloutCounter = 0;
|
|
91
|
+
const customBadgeTexts = ref<(string | number)[]>([]);
|
|
92
|
+
|
|
93
|
+
const registerCallout = () => {
|
|
94
|
+
const idx = calloutCounter++;
|
|
95
|
+
return {
|
|
96
|
+
index: idx,
|
|
97
|
+
item: computed(() => resolvedItems.value[idx] ?? resolvedItems.value[0]),
|
|
98
|
+
setBadgeText: (text: string | number) => {
|
|
99
|
+
customBadgeTexts.value[idx] = text;
|
|
100
|
+
},
|
|
101
|
+
};
|
|
102
|
+
};
|
|
103
|
+
|
|
104
|
+
onBeforeUpdate(() => {
|
|
105
|
+
calloutCounter = 0;
|
|
106
|
+
});
|
|
107
|
+
|
|
108
|
+
provide(HEX_TRIAD_ROOT_KEY, {
|
|
109
|
+
registerCallout,
|
|
110
|
+
items: resolvedItems,
|
|
111
|
+
animation: isAnimated,
|
|
112
|
+
});
|
|
113
|
+
|
|
114
|
+
const item1 = computed(() => {
|
|
115
|
+
return resolvedItems.value[0];
|
|
116
|
+
});
|
|
117
|
+
const item2 = computed(() => {
|
|
118
|
+
return resolvedItems.value[1];
|
|
119
|
+
});
|
|
120
|
+
const item3 = computed(() => {
|
|
121
|
+
return resolvedItems.value[2];
|
|
122
|
+
});
|
|
123
|
+
|
|
124
|
+
// Central diagram coordinates
|
|
125
|
+
const coords = calculateHexTriadCoordinates();
|
|
126
|
+
const {
|
|
127
|
+
hex1,
|
|
128
|
+
hex2,
|
|
129
|
+
hex3,
|
|
130
|
+
badge1,
|
|
131
|
+
badge2,
|
|
132
|
+
badge3,
|
|
133
|
+
centerX,
|
|
134
|
+
centerY,
|
|
135
|
+
hexRadius,
|
|
136
|
+
triadRadius,
|
|
137
|
+
badgeRadius,
|
|
138
|
+
} = coords;
|
|
139
|
+
|
|
140
|
+
const hex1X = hex1.x;
|
|
141
|
+
const hex1Y = hex1.y;
|
|
142
|
+
const hex2X = hex2.x;
|
|
143
|
+
const hex2Y = hex2.y;
|
|
144
|
+
const hex3X = hex3.x;
|
|
145
|
+
const hex3Y = hex3.y;
|
|
146
|
+
|
|
147
|
+
const badge1X = badge1.x;
|
|
148
|
+
const badge1Y = badge1.y;
|
|
149
|
+
const badge2X = badge2.x;
|
|
150
|
+
const badge2Y = badge2.y;
|
|
151
|
+
const badge3X = badge3.x;
|
|
152
|
+
const badge3Y = badge3.y;
|
|
153
|
+
|
|
154
|
+
const HEX_CORNER_RADIUS = 16;
|
|
155
|
+
|
|
156
|
+
// Second layer (background pastel hexagons):
|
|
157
|
+
// Aligned to first layer, then moved 1/4 block outward:
|
|
158
|
+
// - Red: top (-32px)
|
|
159
|
+
// - Orange: right-bottom (+27.71px, +16px)
|
|
160
|
+
// - Blue: left-bottom (-27.71px, +16px)
|
|
161
|
+
const QUARTER_SHIFT = 32;
|
|
162
|
+
const shiftCos30 = Number(
|
|
163
|
+
(QUARTER_SHIFT * Math.cos((30 * Math.PI) / 180)).toFixed(2),
|
|
164
|
+
);
|
|
165
|
+
const shiftSin30 = Number(
|
|
166
|
+
(QUARTER_SHIFT * Math.sin((30 * Math.PI) / 180)).toFixed(2),
|
|
167
|
+
);
|
|
168
|
+
|
|
169
|
+
const hex1BgPath = createRoundedHexagonPath(
|
|
170
|
+
hex1X,
|
|
171
|
+
hex1Y - QUARTER_SHIFT,
|
|
172
|
+
hexRadius,
|
|
173
|
+
HEX_CORNER_RADIUS,
|
|
174
|
+
);
|
|
175
|
+
const hex2BgPath = createRoundedHexagonPath(
|
|
176
|
+
hex2X + shiftCos30,
|
|
177
|
+
hex2Y + shiftSin30,
|
|
178
|
+
hexRadius,
|
|
179
|
+
HEX_CORNER_RADIUS,
|
|
180
|
+
);
|
|
181
|
+
const hex3BgPath = createRoundedHexagonPath(
|
|
182
|
+
hex3X - shiftCos30,
|
|
183
|
+
hex3Y + shiftSin30,
|
|
184
|
+
hexRadius,
|
|
185
|
+
HEX_CORNER_RADIUS,
|
|
186
|
+
);
|
|
187
|
+
|
|
188
|
+
// Middle layer (solid base at the same position as front layer)
|
|
189
|
+
const hex1BasePath = createRoundedHexagonPath(
|
|
190
|
+
hex1X,
|
|
191
|
+
hex1Y,
|
|
192
|
+
hexRadius,
|
|
193
|
+
HEX_CORNER_RADIUS,
|
|
194
|
+
);
|
|
195
|
+
const hex2BasePath = createRoundedHexagonPath(
|
|
196
|
+
hex2X,
|
|
197
|
+
hex2Y,
|
|
198
|
+
hexRadius,
|
|
199
|
+
HEX_CORNER_RADIUS,
|
|
200
|
+
);
|
|
201
|
+
const hex3BasePath = createRoundedHexagonPath(
|
|
202
|
+
hex3X,
|
|
203
|
+
hex3Y,
|
|
204
|
+
hexRadius,
|
|
205
|
+
HEX_CORNER_RADIUS,
|
|
206
|
+
);
|
|
207
|
+
|
|
208
|
+
// Foreground hexagons with rounded borders
|
|
209
|
+
const hex1TopPath = createRoundedHexagonPath(
|
|
210
|
+
hex1X,
|
|
211
|
+
hex1Y,
|
|
212
|
+
hexRadius,
|
|
213
|
+
HEX_CORNER_RADIUS,
|
|
214
|
+
);
|
|
215
|
+
const hex2TopPath = createRoundedHexagonPath(
|
|
216
|
+
hex2X,
|
|
217
|
+
hex2Y,
|
|
218
|
+
hexRadius,
|
|
219
|
+
HEX_CORNER_RADIUS,
|
|
220
|
+
);
|
|
221
|
+
const hex3TopPath = createRoundedHexagonPath(
|
|
222
|
+
hex3X,
|
|
223
|
+
hex3Y,
|
|
224
|
+
hexRadius,
|
|
225
|
+
HEX_CORNER_RADIUS,
|
|
226
|
+
);
|
|
227
|
+
|
|
228
|
+
const { className, forwardedAttrs } = useMergedUnoAttrs(
|
|
229
|
+
'alpha-hex-triad w-full flex flex-col items-center justify-center select-none font-sans',
|
|
230
|
+
);
|
|
231
|
+
</script>
|
|
232
|
+
|
|
233
|
+
<template>
|
|
234
|
+
<div
|
|
235
|
+
v-bind="forwardedAttrs()"
|
|
236
|
+
:class="className()"
|
|
237
|
+
:style="{ '--hex-start-delay': `${resolvedStartDelay}ms` }"
|
|
238
|
+
>
|
|
239
|
+
<header v-if="title || $slots.title" class="alpha-hex-triad__header mb-4 text-center">
|
|
240
|
+
<slot name="title">
|
|
241
|
+
<h2 class="alpha-hex-triad__title text-2xl font-bold font-sans tracking-tight">
|
|
242
|
+
{{ title }}
|
|
243
|
+
</h2>
|
|
244
|
+
</slot>
|
|
245
|
+
<p v-if="subtitle || $slots.subtitle" class="alpha-hex-triad__subtitle text-sm font-sans">
|
|
246
|
+
<slot name="subtitle">{{ subtitle }}</slot>
|
|
247
|
+
</p>
|
|
248
|
+
</header>
|
|
249
|
+
<div class="alpha-hex-triad__stage relative w-full max-w-5xl h-[440px] flex items-center justify-center">
|
|
250
|
+
<!-- Center Column: Overlapping 3D Rounded Hexagon SVG -->
|
|
251
|
+
<div class="alpha-hex-triad__center relative flex items-center justify-center">
|
|
252
|
+
<svg
|
|
253
|
+
class="alpha-hex-triad__svg w-[450px] h-[420px] overflow-visible"
|
|
254
|
+
viewBox="0 0 540 440"
|
|
255
|
+
>
|
|
256
|
+
<defs>
|
|
257
|
+
<!-- Drop shadow for badges -->
|
|
258
|
+
<filter id="hex-badge-shadow" x="-30%" y="-30%" width="160%" height="160%">
|
|
259
|
+
<feDropShadow dx="0" dy="3" stdDeviation="4" flood-opacity="0.35" />
|
|
260
|
+
</filter>
|
|
261
|
+
<!-- 3D extrusion shadow for base layer -->
|
|
262
|
+
<filter id="hex-triad-depth" x="-20%" y="-20%" width="140%" height="140%">
|
|
263
|
+
<feDropShadow dx="0" dy="6" stdDeviation="6" flood-opacity="0.3" />
|
|
264
|
+
</filter>
|
|
265
|
+
<!-- Gradients for Hex 01 -->
|
|
266
|
+
<linearGradient id="grad-hex-1" x1="0%" y1="0%" x2="0%" y2="100%">
|
|
267
|
+
<stop offset="0%" :stop-color="item1.color" stop-opacity="0.95" />
|
|
268
|
+
<stop offset="100%" :stop-color="item1.depthColor" stop-opacity="0.9" />
|
|
269
|
+
</linearGradient>
|
|
270
|
+
<!-- Gradients for Hex 02 -->
|
|
271
|
+
<linearGradient id="grad-hex-2" x1="0%" y1="0%" x2="100%" y2="100%">
|
|
272
|
+
<stop offset="0%" :stop-color="item2.color" stop-opacity="0.95" />
|
|
273
|
+
<stop offset="100%" :stop-color="item2.depthColor" stop-opacity="0.9" />
|
|
274
|
+
</linearGradient>
|
|
275
|
+
<!-- Gradients for Hex 03 -->
|
|
276
|
+
<linearGradient id="grad-hex-3" x1="0%" y1="0%" x2="100%" y2="100%">
|
|
277
|
+
<stop offset="0%" :stop-color="item3.color" stop-opacity="0.95" />
|
|
278
|
+
<stop offset="100%" :stop-color="item3.depthColor" stop-opacity="0.9" />
|
|
279
|
+
</linearGradient>
|
|
280
|
+
</defs>
|
|
281
|
+
<!-- LAYER 1: Background Pastel Offset Hexagons (Animated: slides out from behind solid hexagon to offset position) -->
|
|
282
|
+
<g
|
|
283
|
+
class="alpha-hex-layer1 alpha-hex-layer1--3"
|
|
284
|
+
:class="{ 'alpha-hex-layer1--animated': isAnimated }"
|
|
285
|
+
>
|
|
286
|
+
<HexTriadLayer
|
|
287
|
+
:d="hex3BgPath"
|
|
288
|
+
:fill="item3.lightColor ?? item3.color"
|
|
289
|
+
:opacity="0.38"
|
|
290
|
+
/>
|
|
291
|
+
</g>
|
|
292
|
+
<g
|
|
293
|
+
class="alpha-hex-layer1 alpha-hex-layer1--2"
|
|
294
|
+
:class="{ 'alpha-hex-layer1--animated': isAnimated }"
|
|
295
|
+
>
|
|
296
|
+
<HexTriadLayer
|
|
297
|
+
:d="hex2BgPath"
|
|
298
|
+
:fill="item2.lightColor ?? item2.color"
|
|
299
|
+
:opacity="0.38"
|
|
300
|
+
/>
|
|
301
|
+
</g>
|
|
302
|
+
<g
|
|
303
|
+
class="alpha-hex-layer1 alpha-hex-layer1--1"
|
|
304
|
+
:class="{ 'alpha-hex-layer1--animated': isAnimated }"
|
|
305
|
+
>
|
|
306
|
+
<HexTriadLayer
|
|
307
|
+
:d="hex1BgPath"
|
|
308
|
+
:fill="item1.lightColor ?? item1.color"
|
|
309
|
+
:opacity="0.38"
|
|
310
|
+
/>
|
|
311
|
+
</g>
|
|
312
|
+
<!-- LAYER 2: Middle 3D Depth Base Hexagons (3 hexa blocks) -->
|
|
313
|
+
<HexTriadLayer
|
|
314
|
+
:d="hex3BasePath"
|
|
315
|
+
:fill="item3.depthColor"
|
|
316
|
+
filter="url(#hex-triad-depth)"
|
|
317
|
+
:opacity="0.85"
|
|
318
|
+
/>
|
|
319
|
+
<HexTriadLayer
|
|
320
|
+
:d="hex2BasePath"
|
|
321
|
+
:fill="item2.depthColor"
|
|
322
|
+
filter="url(#hex-triad-depth)"
|
|
323
|
+
:opacity="0.85"
|
|
324
|
+
/>
|
|
325
|
+
<HexTriadLayer
|
|
326
|
+
:d="hex1BasePath"
|
|
327
|
+
:fill="item1.depthColor"
|
|
328
|
+
filter="url(#hex-triad-depth)"
|
|
329
|
+
:opacity="0.85"
|
|
330
|
+
/>
|
|
331
|
+
<!-- LAYER 3: Foreground Hexagons with Gradients (3 hexa blocks) -->
|
|
332
|
+
<HexTriadLayer
|
|
333
|
+
:d="hex3TopPath"
|
|
334
|
+
fill="url(#grad-hex-3)"
|
|
335
|
+
:opacity="0.9"
|
|
336
|
+
/>
|
|
337
|
+
<HexTriadLayer
|
|
338
|
+
:d="hex2TopPath"
|
|
339
|
+
fill="url(#grad-hex-2)"
|
|
340
|
+
:opacity="0.9"
|
|
341
|
+
/>
|
|
342
|
+
<HexTriadLayer
|
|
343
|
+
:d="hex1TopPath"
|
|
344
|
+
fill="url(#grad-hex-1)"
|
|
345
|
+
:opacity="0.9"
|
|
346
|
+
/>
|
|
347
|
+
<!-- LAYER 4: White Interconnecting Ring (Circumcircle) -->
|
|
348
|
+
<circle
|
|
349
|
+
class="alpha-hex-triad__circumcircle"
|
|
350
|
+
:cx="centerX"
|
|
351
|
+
:cy="centerY"
|
|
352
|
+
:r="triadRadius"
|
|
353
|
+
fill="none"
|
|
354
|
+
stroke="#ffffff"
|
|
355
|
+
stroke-width="2.5"
|
|
356
|
+
stroke-linecap="round"
|
|
357
|
+
:style="{ opacity: 0.95 }"
|
|
358
|
+
/>
|
|
359
|
+
<!-- LAYER 5: Center Circular Badges (Centered Directly on the White Circle) -->
|
|
360
|
+
<!-- Badge 03 (Bottom-Left) -->
|
|
361
|
+
<HexTriadCenterBadge
|
|
362
|
+
:x="badge3X"
|
|
363
|
+
:y="badge3Y"
|
|
364
|
+
:radius="badgeRadius"
|
|
365
|
+
:color="item3.color"
|
|
366
|
+
:text="customBadgeTexts[2] || item3.id"
|
|
367
|
+
/>
|
|
368
|
+
<!-- Badge 02 (Bottom-Right) -->
|
|
369
|
+
<HexTriadCenterBadge
|
|
370
|
+
:x="badge2X"
|
|
371
|
+
:y="badge2Y"
|
|
372
|
+
:radius="badgeRadius"
|
|
373
|
+
:color="item2.color"
|
|
374
|
+
:text="customBadgeTexts[1] || item2.id"
|
|
375
|
+
/>
|
|
376
|
+
<!-- Badge 01 (Top) -->
|
|
377
|
+
<HexTriadCenterBadge
|
|
378
|
+
:x="badge1X"
|
|
379
|
+
:y="badge1Y"
|
|
380
|
+
:radius="badgeRadius"
|
|
381
|
+
:color="item1.color"
|
|
382
|
+
:text="customBadgeTexts[0] || item1.id"
|
|
383
|
+
/>
|
|
384
|
+
</svg>
|
|
385
|
+
</div>
|
|
386
|
+
<!-- If default slot provided, render user's <HexTriadCallout> components -->
|
|
387
|
+
<slot v-if="$slots.default" />
|
|
388
|
+
<!-- Fallback: render 3 default callouts if no slots provided -->
|
|
389
|
+
<template v-else>
|
|
390
|
+
<HexTriadCallout />
|
|
391
|
+
<HexTriadCallout />
|
|
392
|
+
<HexTriadCallout />
|
|
393
|
+
</template>
|
|
394
|
+
</div>
|
|
395
|
+
</div>
|
|
396
|
+
</template>
|
|
397
|
+
|
|
398
|
+
<style scoped>
|
|
399
|
+
/* Layer 1 (Pastel Hexagons) slides out with overlapping cascading stagger */
|
|
400
|
+
.alpha-hex-layer1--1.alpha-hex-layer1--animated {
|
|
401
|
+
animation: hex-layer1-slide-1 500ms cubic-bezier(0.25, 1, 0.5, 1) calc(var(--hex-start-delay, 0ms) + 100ms) both;
|
|
402
|
+
}
|
|
403
|
+
|
|
404
|
+
.alpha-hex-layer1--2.alpha-hex-layer1--animated {
|
|
405
|
+
animation: hex-layer1-slide-2 500ms cubic-bezier(0.25, 1, 0.5, 1) calc(var(--hex-start-delay, 0ms) + 300ms) both;
|
|
406
|
+
}
|
|
407
|
+
|
|
408
|
+
.alpha-hex-layer1--3.alpha-hex-layer1--animated {
|
|
409
|
+
animation: hex-layer1-slide-3 500ms cubic-bezier(0.25, 1, 0.5, 1) calc(var(--hex-start-delay, 0ms) + 500ms) both;
|
|
410
|
+
}
|
|
411
|
+
|
|
412
|
+
@keyframes hex-layer1-slide-1 {
|
|
413
|
+
0% {
|
|
414
|
+
transform: translate(0px, 32px);
|
|
415
|
+
}
|
|
416
|
+
100% {
|
|
417
|
+
transform: translate(0px, 0px);
|
|
418
|
+
}
|
|
419
|
+
}
|
|
420
|
+
|
|
421
|
+
@keyframes hex-layer1-slide-2 {
|
|
422
|
+
0% {
|
|
423
|
+
transform: translate(-27.71px, -16px);
|
|
424
|
+
}
|
|
425
|
+
100% {
|
|
426
|
+
transform: translate(0px, 0px);
|
|
427
|
+
}
|
|
428
|
+
}
|
|
429
|
+
|
|
430
|
+
@keyframes hex-layer1-slide-3 {
|
|
431
|
+
0% {
|
|
432
|
+
transform: translate(27.71px, -16px);
|
|
433
|
+
}
|
|
434
|
+
100% {
|
|
435
|
+
transform: translate(0px, 0px);
|
|
436
|
+
}
|
|
437
|
+
}
|
|
438
|
+
</style>
|
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
<script setup lang="ts">
|
|
2
|
+
import { computed, inject, useSlots, watchEffect } from 'vue';
|
|
3
|
+
|
|
4
|
+
import {
|
|
5
|
+
createRoundedHexagonPath,
|
|
6
|
+
HEX_TRIAD_CALLOUT_KEY,
|
|
7
|
+
} from '../../utils/hexTriad';
|
|
8
|
+
|
|
9
|
+
defineOptions({
|
|
10
|
+
name: 'HexTriadBadge',
|
|
11
|
+
});
|
|
12
|
+
|
|
13
|
+
export interface IHexTriadBadgeProps {
|
|
14
|
+
readonly id?: string | number;
|
|
15
|
+
readonly color?: string;
|
|
16
|
+
readonly lightColor?: string;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
const props = withDefaults(defineProps<IHexTriadBadgeProps>(), {
|
|
20
|
+
id: undefined,
|
|
21
|
+
color: undefined,
|
|
22
|
+
lightColor: undefined,
|
|
23
|
+
});
|
|
24
|
+
|
|
25
|
+
defineSlots<{
|
|
26
|
+
default?: () => unknown;
|
|
27
|
+
}>();
|
|
28
|
+
|
|
29
|
+
const calloutContext = inject(HEX_TRIAD_CALLOUT_KEY, undefined);
|
|
30
|
+
const slots = useSlots();
|
|
31
|
+
|
|
32
|
+
const miniHexPath = createRoundedHexagonPath(18, 18, 17, 4.5);
|
|
33
|
+
|
|
34
|
+
const badgeColor = computed(() => {
|
|
35
|
+
return props.color ?? calloutContext?.item.value.color ?? '#e11d48';
|
|
36
|
+
});
|
|
37
|
+
|
|
38
|
+
const badgeLightColor = computed(() => {
|
|
39
|
+
return (
|
|
40
|
+
props.lightColor ??
|
|
41
|
+
calloutContext?.item.value.lightColor ??
|
|
42
|
+
calloutContext?.item.value.color ??
|
|
43
|
+
'#fb7185'
|
|
44
|
+
);
|
|
45
|
+
});
|
|
46
|
+
|
|
47
|
+
const fallbackId = computed(() => {
|
|
48
|
+
return props.id ?? calloutContext?.item.value.id ?? '01';
|
|
49
|
+
});
|
|
50
|
+
|
|
51
|
+
// Extract text from default slot or prop if available
|
|
52
|
+
const badgeText = computed<string | number>(() => {
|
|
53
|
+
if (props.id !== undefined) {
|
|
54
|
+
return props.id;
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
if (!slots.default) {
|
|
58
|
+
return fallbackId.value;
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
const nodes = slots.default();
|
|
62
|
+
const text = nodes
|
|
63
|
+
.map((node) => {
|
|
64
|
+
if (typeof node.children === 'string') {
|
|
65
|
+
return node.children;
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
if (typeof node.children === 'number') {
|
|
69
|
+
return String(node.children);
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
return '';
|
|
73
|
+
})
|
|
74
|
+
.join('')
|
|
75
|
+
.trim();
|
|
76
|
+
return text || fallbackId.value;
|
|
77
|
+
});
|
|
78
|
+
|
|
79
|
+
watchEffect(() => {
|
|
80
|
+
if (calloutContext?.setBadgeText) {
|
|
81
|
+
calloutContext.setBadgeText(badgeText.value);
|
|
82
|
+
}
|
|
83
|
+
});
|
|
84
|
+
</script>
|
|
85
|
+
|
|
86
|
+
<template>
|
|
87
|
+
<svg class="alpha-hex-triad-badge w-10 h-10 drop-shadow flex-shrink-0" viewBox="0 0 36 36">
|
|
88
|
+
<path class="alpha-hex-triad-badge__bg" :d="miniHexPath" :fill="badgeLightColor" :style="{ opacity: 0.45 }" />
|
|
89
|
+
<path
|
|
90
|
+
class="alpha-hex-triad-badge__border"
|
|
91
|
+
:d="miniHexPath"
|
|
92
|
+
fill="none"
|
|
93
|
+
:stroke="badgeLightColor"
|
|
94
|
+
stroke-width="1"
|
|
95
|
+
:style="{ opacity: 0.8 }"
|
|
96
|
+
/>
|
|
97
|
+
<circle class="alpha-hex-triad-badge__circle" cx="18" cy="18" r="11" :fill="badgeColor" />
|
|
98
|
+
<text
|
|
99
|
+
class="alpha-hex-triad-badge__text font-black text-[10px] font-sans select-none"
|
|
100
|
+
x="18"
|
|
101
|
+
y="21.5"
|
|
102
|
+
text-anchor="middle"
|
|
103
|
+
fill="#ffffff"
|
|
104
|
+
>
|
|
105
|
+
<tspan>
|
|
106
|
+
<slot>{{ fallbackId }}</slot>
|
|
107
|
+
</tspan>
|
|
108
|
+
</text>
|
|
109
|
+
</svg>
|
|
110
|
+
</template>
|