@aspect-ops/exon-ui 0.2.2 → 0.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +0 -45
- package/dist/components/BottomNav/BottomNavItem.svelte +4 -3
- package/dist/components/BottomNav/BottomNavItem.svelte.d.ts +2 -1
- package/dist/components/CTASection/CTASection.svelte +298 -0
- package/dist/components/CTASection/CTASection.svelte.d.ts +15 -0
- package/dist/components/CTASection/index.d.ts +2 -0
- package/dist/components/CTASection/index.js +1 -0
- package/dist/components/DoughnutChart/DoughnutChart.svelte +4 -4
- package/dist/components/FlexibleGrid/FlexibleGrid.svelte +118 -0
- package/dist/components/FlexibleGrid/FlexibleGrid.svelte.d.ts +7 -0
- package/dist/components/FlexibleGrid/README.md +212 -0
- package/dist/components/FlexibleGrid/index.d.ts +2 -0
- package/dist/components/FlexibleGrid/index.js +1 -0
- package/dist/components/GlobalHeader/GlobalHeader.svelte +806 -0
- package/dist/components/GlobalHeader/GlobalHeader.svelte.d.ts +3 -0
- package/dist/components/GlobalHeader/index.d.ts +2 -0
- package/dist/components/GlobalHeader/index.js +1 -0
- package/dist/components/Hero/Hero.svelte +306 -0
- package/dist/components/Hero/Hero.svelte.d.ts +18 -0
- package/dist/components/Hero/index.d.ts +2 -0
- package/dist/components/Hero/index.js +1 -0
- package/dist/components/HeroLeftAligned/HeroLeftAligned.svelte +182 -0
- package/dist/components/HeroLeftAligned/HeroLeftAligned.svelte.d.ts +8 -0
- package/dist/components/HeroLeftAligned/README.md +168 -0
- package/dist/components/HeroLeftAligned/index.d.ts +2 -0
- package/dist/components/HeroLeftAligned/index.js +1 -0
- package/dist/components/IconFeatureCard/IconFeatureCard.svelte +173 -0
- package/dist/components/IconFeatureCard/IconFeatureCard.svelte.d.ts +4 -0
- package/dist/components/IconFeatureCard/README.md +234 -0
- package/dist/components/IconFeatureCard/index.d.ts +2 -0
- package/dist/components/IconFeatureCard/index.js +1 -0
- package/dist/components/ImageTextCard/ImageTextCard.svelte +149 -0
- package/dist/components/ImageTextCard/ImageTextCard.svelte.d.ts +22 -0
- package/dist/components/ImageTextCard/README.md +177 -0
- package/dist/components/ImageTextCard/index.d.ts +2 -0
- package/dist/components/ImageTextCard/index.js +1 -0
- package/dist/components/LogoCloud/LogoCloud.svelte +333 -0
- package/dist/components/LogoCloud/LogoCloud.svelte.d.ts +20 -0
- package/dist/components/LogoCloud/index.d.ts +2 -0
- package/dist/components/LogoCloud/index.js +1 -0
- package/dist/components/ServiceCard/ServiceCard.svelte +359 -0
- package/dist/components/ServiceCard/ServiceCard.svelte.d.ts +16 -0
- package/dist/components/ServiceCard/index.d.ts +1 -0
- package/dist/components/ServiceCard/index.js +1 -0
- package/dist/components/Sidebar/SidebarGroup.svelte +1 -4
- package/dist/components/SplitSection/SplitSection.svelte +194 -0
- package/dist/components/SplitSection/SplitSection.svelte.d.ts +15 -0
- package/dist/components/SplitSection/index.d.ts +1 -0
- package/dist/components/SplitSection/index.js +1 -0
- package/dist/components/TestimonialCard/TestimonialCard.svelte +290 -0
- package/dist/components/TestimonialCard/TestimonialCard.svelte.d.ts +14 -0
- package/dist/components/TestimonialCard/index.d.ts +1 -0
- package/dist/components/TestimonialCard/index.js +1 -0
- package/dist/components/Timeline/Timeline.svelte +444 -0
- package/dist/components/Timeline/Timeline.svelte.d.ts +19 -0
- package/dist/components/Timeline/index.d.ts +2 -0
- package/dist/components/Timeline/index.js +1 -0
- package/dist/index.d.ts +23 -1
- package/dist/index.js +13 -1
- package/dist/types/index.d.ts +49 -1
- package/dist/types/layout.d.ts +20 -0
- package/package.json +9 -2
- package/dist/components/Mermaid/Mermaid.svelte +0 -320
- package/dist/components/Mermaid/Mermaid.svelte.d.ts +0 -38
- package/dist/components/Mermaid/index.d.ts +0 -1
- package/dist/components/Mermaid/index.js +0 -1
- package/dist/components/Mermaid/mermaid.d.ts +0 -21
package/README.md
CHANGED
|
@@ -1202,51 +1202,6 @@ Pure SVG doughnut chart with interactive legend (no external dependencies).
|
|
|
1202
1202
|
| `showLegend` | `boolean` | `true` | Show legend |
|
|
1203
1203
|
| `showTotal` | `boolean` | `true` | Show center total |
|
|
1204
1204
|
|
|
1205
|
-
### Mermaid
|
|
1206
|
-
|
|
1207
|
-
Render Mermaid diagrams with customizable theming.
|
|
1208
|
-
|
|
1209
|
-
**Note:** Requires `mermaid` package: `npm install mermaid`
|
|
1210
|
-
|
|
1211
|
-
```svelte
|
|
1212
|
-
<script>
|
|
1213
|
-
import { Mermaid } from '@aspect-ops/exon-ui';
|
|
1214
|
-
|
|
1215
|
-
const diagram = `flowchart TD
|
|
1216
|
-
A[Start] --> B{Decision}
|
|
1217
|
-
B -->|Yes| C[Action 1]
|
|
1218
|
-
B -->|No| D[Action 2]
|
|
1219
|
-
C --> E[End]
|
|
1220
|
-
D --> E`;
|
|
1221
|
-
</script>
|
|
1222
|
-
|
|
1223
|
-
<!-- Using code prop -->
|
|
1224
|
-
<Mermaid code={diagram} />
|
|
1225
|
-
|
|
1226
|
-
<!-- Using slot -->
|
|
1227
|
-
<Mermaid>flowchart LR A --> B --> C</Mermaid>
|
|
1228
|
-
```
|
|
1229
|
-
|
|
1230
|
-
**Props:**
|
|
1231
|
-
|
|
1232
|
-
| Prop | Type | Default | Description |
|
|
1233
|
-
| ------- | -------- | ------------- | ---------------------- |
|
|
1234
|
-
| `code` | `string` | - | Mermaid diagram code |
|
|
1235
|
-
| `theme` | `object` | ExonPro theme | Custom theme variables |
|
|
1236
|
-
|
|
1237
|
-
**Theme variables:**
|
|
1238
|
-
|
|
1239
|
-
```javascript
|
|
1240
|
-
const theme = {
|
|
1241
|
-
primaryColor: '#4654A3',
|
|
1242
|
-
primaryTextColor: '#270949',
|
|
1243
|
-
primaryBorderColor: '#4654A3',
|
|
1244
|
-
lineColor: '#270949',
|
|
1245
|
-
secondaryColor: '#FF3131',
|
|
1246
|
-
tertiaryColor: '#f3f4f6'
|
|
1247
|
-
};
|
|
1248
|
-
```
|
|
1249
|
-
|
|
1250
1205
|
## Theming & Customization
|
|
1251
1206
|
|
|
1252
1207
|
### Quick Setup
|
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
<script lang="ts">
|
|
2
2
|
import type { BottomNavItemProps } from '../../types/index.js';
|
|
3
3
|
|
|
4
|
-
interface Props extends BottomNavItemProps {
|
|
4
|
+
interface Props extends Omit<BottomNavItemProps, 'icon'> {
|
|
5
|
+
icon: import('svelte').Snippet;
|
|
5
6
|
onclick?: () => void;
|
|
6
7
|
children?: import('svelte').Snippet;
|
|
7
8
|
}
|
|
@@ -25,7 +26,7 @@
|
|
|
25
26
|
class:bottom-nav-item--active={active}
|
|
26
27
|
aria-current={active ? 'page' : undefined}
|
|
27
28
|
>
|
|
28
|
-
<span class="bottom-nav-item__icon">{icon}</span>
|
|
29
|
+
<span class="bottom-nav-item__icon">{@render icon()}</span>
|
|
29
30
|
{#if children}
|
|
30
31
|
<span class="bottom-nav-item__label">{@render children()}</span>
|
|
31
32
|
{:else}
|
|
@@ -45,7 +46,7 @@
|
|
|
45
46
|
aria-current={active ? 'page' : undefined}
|
|
46
47
|
{onclick}
|
|
47
48
|
>
|
|
48
|
-
<span class="bottom-nav-item__icon">{icon}</span>
|
|
49
|
+
<span class="bottom-nav-item__icon">{@render icon()}</span>
|
|
49
50
|
{#if children}
|
|
50
51
|
<span class="bottom-nav-item__label">{@render children()}</span>
|
|
51
52
|
{:else}
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import type { BottomNavItemProps } from '../../types/index.js';
|
|
2
|
-
interface Props extends BottomNavItemProps {
|
|
2
|
+
interface Props extends Omit<BottomNavItemProps, 'icon'> {
|
|
3
|
+
icon: import('svelte').Snippet;
|
|
3
4
|
onclick?: () => void;
|
|
4
5
|
children?: import('svelte').Snippet;
|
|
5
6
|
}
|
|
@@ -0,0 +1,298 @@
|
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
import type { Snippet } from 'svelte';
|
|
3
|
+
|
|
4
|
+
export interface CTASectionProps {
|
|
5
|
+
title: string;
|
|
6
|
+
description?: string;
|
|
7
|
+
variant?: 'default' | 'gradient' | 'image' | 'split';
|
|
8
|
+
background?: string;
|
|
9
|
+
align?: 'left' | 'center' | 'right';
|
|
10
|
+
size?: 'sm' | 'md' | 'lg';
|
|
11
|
+
class?: string;
|
|
12
|
+
actions: Snippet;
|
|
13
|
+
icon?: Snippet;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
let {
|
|
17
|
+
title,
|
|
18
|
+
description,
|
|
19
|
+
variant = 'default',
|
|
20
|
+
background,
|
|
21
|
+
align = 'center',
|
|
22
|
+
size = 'md',
|
|
23
|
+
class: className = '',
|
|
24
|
+
actions,
|
|
25
|
+
icon
|
|
26
|
+
}: CTASectionProps = $props();
|
|
27
|
+
|
|
28
|
+
const sizeClasses = {
|
|
29
|
+
sm: 'cta-section--sm',
|
|
30
|
+
md: 'cta-section--md',
|
|
31
|
+
lg: 'cta-section--lg'
|
|
32
|
+
};
|
|
33
|
+
</script>
|
|
34
|
+
|
|
35
|
+
<section
|
|
36
|
+
class="cta-section cta-section--{variant} cta-section--{align} {sizeClasses[size]} {className}"
|
|
37
|
+
style:--cta-background={background}
|
|
38
|
+
>
|
|
39
|
+
<div class="cta-section__container">
|
|
40
|
+
{#if variant === 'split' && icon}
|
|
41
|
+
<div class="cta-section__split">
|
|
42
|
+
<div class="cta-section__content">
|
|
43
|
+
<h2 class="cta-section__title">{title}</h2>
|
|
44
|
+
{#if description}
|
|
45
|
+
<p class="cta-section__description">{description}</p>
|
|
46
|
+
{/if}
|
|
47
|
+
<div class="cta-section__actions">
|
|
48
|
+
{@render actions()}
|
|
49
|
+
</div>
|
|
50
|
+
</div>
|
|
51
|
+
<div class="cta-section__icon">
|
|
52
|
+
{@render icon()}
|
|
53
|
+
</div>
|
|
54
|
+
</div>
|
|
55
|
+
{:else}
|
|
56
|
+
<div class="cta-section__content">
|
|
57
|
+
{#if icon && variant !== 'split'}
|
|
58
|
+
<div class="cta-section__icon">
|
|
59
|
+
{@render icon()}
|
|
60
|
+
</div>
|
|
61
|
+
{/if}
|
|
62
|
+
<h2 class="cta-section__title">{title}</h2>
|
|
63
|
+
{#if description}
|
|
64
|
+
<p class="cta-section__description">{description}</p>
|
|
65
|
+
{/if}
|
|
66
|
+
<div class="cta-section__actions">
|
|
67
|
+
{@render actions()}
|
|
68
|
+
</div>
|
|
69
|
+
</div>
|
|
70
|
+
{/if}
|
|
71
|
+
</div>
|
|
72
|
+
</section>
|
|
73
|
+
|
|
74
|
+
<style>
|
|
75
|
+
.cta-section {
|
|
76
|
+
--cta-bg: var(--color-primary, #0066cc);
|
|
77
|
+
--cta-text-color: var(--color-on-primary, #ffffff);
|
|
78
|
+
--cta-padding: 4rem;
|
|
79
|
+
--cta-max-width: 1200px;
|
|
80
|
+
--cta-gradient-from: var(--color-primary, #0066cc);
|
|
81
|
+
--cta-gradient-to: var(--color-primary-dark, #004999);
|
|
82
|
+
|
|
83
|
+
position: relative;
|
|
84
|
+
padding: var(--cta-padding) 1.5rem;
|
|
85
|
+
color: var(--cta-text-color);
|
|
86
|
+
overflow: hidden;
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
/* Variant: Default */
|
|
90
|
+
.cta-section--default {
|
|
91
|
+
background-color: var(--cta-background, var(--cta-bg));
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
/* Variant: Gradient */
|
|
95
|
+
.cta-section--gradient {
|
|
96
|
+
background: linear-gradient(
|
|
97
|
+
135deg,
|
|
98
|
+
var(--cta-background, var(--cta-gradient-from)),
|
|
99
|
+
var(--cta-gradient-to)
|
|
100
|
+
);
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
/* Variant: Image */
|
|
104
|
+
.cta-section--image {
|
|
105
|
+
background-image: var(--cta-background);
|
|
106
|
+
background-size: cover;
|
|
107
|
+
background-position: center;
|
|
108
|
+
background-repeat: no-repeat;
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
.cta-section--image::before {
|
|
112
|
+
content: '';
|
|
113
|
+
position: absolute;
|
|
114
|
+
inset: 0;
|
|
115
|
+
background: rgba(0, 0, 0, 0.5);
|
|
116
|
+
z-index: 0;
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
.cta-section--image .cta-section__container {
|
|
120
|
+
position: relative;
|
|
121
|
+
z-index: 1;
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
/* Variant: Split */
|
|
125
|
+
.cta-section--split {
|
|
126
|
+
background-color: var(--cta-background, var(--cta-bg));
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
.cta-section__split {
|
|
130
|
+
display: grid;
|
|
131
|
+
grid-template-columns: 1fr;
|
|
132
|
+
gap: 2rem;
|
|
133
|
+
align-items: center;
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
@media (min-width: 768px) {
|
|
137
|
+
.cta-section__split {
|
|
138
|
+
grid-template-columns: 1fr 1fr;
|
|
139
|
+
gap: 3rem;
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
/* Size variants */
|
|
144
|
+
.cta-section--sm {
|
|
145
|
+
--cta-padding: 2rem;
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
.cta-section--md {
|
|
149
|
+
--cta-padding: 4rem;
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
.cta-section--lg {
|
|
153
|
+
--cta-padding: 6rem;
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
/* Container */
|
|
157
|
+
.cta-section__container {
|
|
158
|
+
max-width: var(--cta-max-width);
|
|
159
|
+
margin: 0 auto;
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
/* Content */
|
|
163
|
+
.cta-section__content {
|
|
164
|
+
display: flex;
|
|
165
|
+
flex-direction: column;
|
|
166
|
+
gap: 1.5rem;
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
/* Alignment */
|
|
170
|
+
.cta-section--left .cta-section__content {
|
|
171
|
+
align-items: flex-start;
|
|
172
|
+
text-align: left;
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
.cta-section--center .cta-section__content {
|
|
176
|
+
align-items: center;
|
|
177
|
+
text-align: center;
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
.cta-section--right .cta-section__content {
|
|
181
|
+
align-items: flex-end;
|
|
182
|
+
text-align: right;
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
/* Title */
|
|
186
|
+
.cta-section__title {
|
|
187
|
+
margin: 0;
|
|
188
|
+
font-size: clamp(1.75rem, 4vw, 2.5rem);
|
|
189
|
+
font-weight: 700;
|
|
190
|
+
line-height: 1.2;
|
|
191
|
+
color: inherit;
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
/* Description */
|
|
195
|
+
.cta-section__description {
|
|
196
|
+
margin: 0;
|
|
197
|
+
font-size: clamp(1rem, 2vw, 1.25rem);
|
|
198
|
+
line-height: 1.6;
|
|
199
|
+
max-width: 48rem;
|
|
200
|
+
opacity: 0.95;
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
/* Actions */
|
|
204
|
+
.cta-section__actions {
|
|
205
|
+
display: flex;
|
|
206
|
+
flex-wrap: wrap;
|
|
207
|
+
gap: 1rem;
|
|
208
|
+
margin-top: 0.5rem;
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
.cta-section--left .cta-section__actions {
|
|
212
|
+
justify-content: flex-start;
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
.cta-section--center .cta-section__actions {
|
|
216
|
+
justify-content: center;
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
.cta-section--right .cta-section__actions {
|
|
220
|
+
justify-content: flex-end;
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
/* Icon */
|
|
224
|
+
.cta-section__icon {
|
|
225
|
+
display: flex;
|
|
226
|
+
align-items: center;
|
|
227
|
+
justify-content: center;
|
|
228
|
+
margin-bottom: 0.5rem;
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
.cta-section--split .cta-section__icon {
|
|
232
|
+
margin-bottom: 0;
|
|
233
|
+
min-height: 300px;
|
|
234
|
+
}
|
|
235
|
+
|
|
236
|
+
.cta-section--left .cta-section__icon {
|
|
237
|
+
margin-left: 0;
|
|
238
|
+
margin-right: auto;
|
|
239
|
+
}
|
|
240
|
+
|
|
241
|
+
.cta-section--center .cta-section__icon {
|
|
242
|
+
margin-left: auto;
|
|
243
|
+
margin-right: auto;
|
|
244
|
+
}
|
|
245
|
+
|
|
246
|
+
.cta-section--right .cta-section__icon {
|
|
247
|
+
margin-left: auto;
|
|
248
|
+
margin-right: 0;
|
|
249
|
+
}
|
|
250
|
+
|
|
251
|
+
/* Focus visible for interactive elements */
|
|
252
|
+
.cta-section__actions :global(a:focus-visible),
|
|
253
|
+
.cta-section__actions :global(button:focus-visible) {
|
|
254
|
+
outline: 2px solid currentColor;
|
|
255
|
+
outline-offset: 2px;
|
|
256
|
+
}
|
|
257
|
+
|
|
258
|
+
/* Mobile optimization */
|
|
259
|
+
@media (max-width: 767px) {
|
|
260
|
+
.cta-section {
|
|
261
|
+
padding-left: 1rem;
|
|
262
|
+
padding-right: 1rem;
|
|
263
|
+
}
|
|
264
|
+
|
|
265
|
+
.cta-section--sm {
|
|
266
|
+
--cta-padding: 1.5rem;
|
|
267
|
+
}
|
|
268
|
+
|
|
269
|
+
.cta-section--md {
|
|
270
|
+
--cta-padding: 2.5rem;
|
|
271
|
+
}
|
|
272
|
+
|
|
273
|
+
.cta-section--lg {
|
|
274
|
+
--cta-padding: 4rem;
|
|
275
|
+
}
|
|
276
|
+
|
|
277
|
+
.cta-section__actions {
|
|
278
|
+
width: 100%;
|
|
279
|
+
}
|
|
280
|
+
|
|
281
|
+
.cta-section__actions :global(a),
|
|
282
|
+
.cta-section__actions :global(button) {
|
|
283
|
+
min-height: 44px;
|
|
284
|
+
min-width: 44px;
|
|
285
|
+
}
|
|
286
|
+
}
|
|
287
|
+
|
|
288
|
+
/* Dark mode support */
|
|
289
|
+
@media (prefers-color-scheme: dark) {
|
|
290
|
+
.cta-section--default {
|
|
291
|
+
--cta-bg: var(--color-primary-dark, #004999);
|
|
292
|
+
}
|
|
293
|
+
|
|
294
|
+
.cta-section--image::before {
|
|
295
|
+
background: rgba(0, 0, 0, 0.65);
|
|
296
|
+
}
|
|
297
|
+
}
|
|
298
|
+
</style>
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import type { Snippet } from 'svelte';
|
|
2
|
+
export interface CTASectionProps {
|
|
3
|
+
title: string;
|
|
4
|
+
description?: string;
|
|
5
|
+
variant?: 'default' | 'gradient' | 'image' | 'split';
|
|
6
|
+
background?: string;
|
|
7
|
+
align?: 'left' | 'center' | 'right';
|
|
8
|
+
size?: 'sm' | 'md' | 'lg';
|
|
9
|
+
class?: string;
|
|
10
|
+
actions: Snippet;
|
|
11
|
+
icon?: Snippet;
|
|
12
|
+
}
|
|
13
|
+
declare const CTASection: import("svelte").Component<CTASectionProps, {}, "">;
|
|
14
|
+
type CTASection = ReturnType<typeof CTASection>;
|
|
15
|
+
export default CTASection;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { default as CTASection } from './CTASection.svelte';
|
|
@@ -49,6 +49,10 @@
|
|
|
49
49
|
// Calculate total
|
|
50
50
|
const total = $derived(data.reduce((sum, item) => sum + item.value, 0));
|
|
51
51
|
|
|
52
|
+
// Calculate inner radius for doughnut (must be before arcs)
|
|
53
|
+
const innerRadius = $derived((size / 2 - 10) * (1 - thickness));
|
|
54
|
+
const outerRadius = $derived(size / 2 - 10);
|
|
55
|
+
|
|
52
56
|
// Calculate arc data
|
|
53
57
|
interface ArcData extends DataItem {
|
|
54
58
|
percentage: number;
|
|
@@ -87,10 +91,6 @@
|
|
|
87
91
|
return result;
|
|
88
92
|
});
|
|
89
93
|
|
|
90
|
-
// Calculate inner radius for doughnut
|
|
91
|
-
const innerRadius = $derived((size / 2 - 10) * (1 - thickness));
|
|
92
|
-
const outerRadius = $derived(size / 2 - 10);
|
|
93
|
-
|
|
94
94
|
// Helper to convert polar to cartesian coordinates
|
|
95
95
|
function polarToCartesian(
|
|
96
96
|
centerX: number,
|
|
@@ -0,0 +1,118 @@
|
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
import type {
|
|
3
|
+
SpacingToken,
|
|
4
|
+
FlexibleGridCell,
|
|
5
|
+
FlexibleGridRow,
|
|
6
|
+
FlexibleGridProps
|
|
7
|
+
} from '../../types/index.js';
|
|
8
|
+
|
|
9
|
+
interface Props extends Omit<FlexibleGridProps, 'children'> {
|
|
10
|
+
children?: import('svelte').Snippet;
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
let {
|
|
14
|
+
rows,
|
|
15
|
+
gap = 'xs', // Use design token by default
|
|
16
|
+
cellHeight = '80px',
|
|
17
|
+
defaultBgColor = '#6B7A99',
|
|
18
|
+
defaultTextColor = 'white',
|
|
19
|
+
columns = 12,
|
|
20
|
+
class: className = '',
|
|
21
|
+
children
|
|
22
|
+
}: Props = $props();
|
|
23
|
+
|
|
24
|
+
// Convert SpacingToken to CSS value if needed
|
|
25
|
+
const getGapValue = (gapValue: SpacingToken | string): string => {
|
|
26
|
+
const spacingMap: Record<SpacingToken, string> = {
|
|
27
|
+
xs: 'var(--space-xs, 0.25rem)',
|
|
28
|
+
sm: 'var(--space-sm, 0.5rem)',
|
|
29
|
+
md: 'var(--space-md, 1rem)',
|
|
30
|
+
lg: 'var(--space-lg, 1.5rem)',
|
|
31
|
+
xl: 'var(--space-xl, 2rem)',
|
|
32
|
+
'2xl': 'var(--space-2xl, 3rem)',
|
|
33
|
+
'3xl': 'var(--space-3xl, 4rem)'
|
|
34
|
+
};
|
|
35
|
+
return spacingMap[gapValue as SpacingToken] || gapValue;
|
|
36
|
+
};
|
|
37
|
+
</script>
|
|
38
|
+
|
|
39
|
+
<div class="flexible-grid {className}" style="gap: {getGapValue(gap)};">
|
|
40
|
+
{#each rows as row, rowIndex}
|
|
41
|
+
<div
|
|
42
|
+
class="grid-row {row.class || ''}"
|
|
43
|
+
style="gap: {getGapValue(gap)}; grid-template-columns: repeat({columns}, 1fr);"
|
|
44
|
+
>
|
|
45
|
+
{#each row.cells as cell, cellIndex}
|
|
46
|
+
<div
|
|
47
|
+
class="grid-cell {cell.class || ''}"
|
|
48
|
+
style="
|
|
49
|
+
grid-column: span {cell.span};
|
|
50
|
+
height: {cellHeight};
|
|
51
|
+
background-color: {cell.bgColor || defaultBgColor};
|
|
52
|
+
color: {cell.textColor || defaultTextColor};
|
|
53
|
+
"
|
|
54
|
+
>
|
|
55
|
+
{@html cell.content}
|
|
56
|
+
</div>
|
|
57
|
+
{/each}
|
|
58
|
+
</div>
|
|
59
|
+
{/each}
|
|
60
|
+
{#if children}
|
|
61
|
+
{@render children()}
|
|
62
|
+
{/if}
|
|
63
|
+
</div>
|
|
64
|
+
|
|
65
|
+
<style>
|
|
66
|
+
.flexible-grid {
|
|
67
|
+
display: flex;
|
|
68
|
+
flex-direction: column;
|
|
69
|
+
width: 100%;
|
|
70
|
+
background-color: transparent;
|
|
71
|
+
font-family: inherit;
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
.grid-row {
|
|
75
|
+
display: grid;
|
|
76
|
+
width: 100%;
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
.grid-cell {
|
|
80
|
+
display: flex;
|
|
81
|
+
align-items: center;
|
|
82
|
+
justify-content: center;
|
|
83
|
+
font-size: 2rem;
|
|
84
|
+
font-weight: 600;
|
|
85
|
+
border-radius: 4px;
|
|
86
|
+
transition: transform 0.2s ease;
|
|
87
|
+
overflow: hidden;
|
|
88
|
+
box-sizing: border-box;
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
.grid-cell:hover {
|
|
92
|
+
transform: scale(1.02);
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
/* Responsive adjustments */
|
|
96
|
+
@media (max-width: 768px) {
|
|
97
|
+
.grid-cell {
|
|
98
|
+
font-size: 1.5rem;
|
|
99
|
+
min-height: 60px;
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
@media (max-width: 480px) {
|
|
104
|
+
.grid-cell {
|
|
105
|
+
font-size: 1rem;
|
|
106
|
+
min-height: 50px;
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
.grid-row {
|
|
110
|
+
grid-template-columns: repeat(6, 1fr) !important;
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
.grid-cell {
|
|
114
|
+
/* On mobile, adjust span to fit 6 columns */
|
|
115
|
+
grid-column: span min(6, attr(data-span integer, 1)) !important;
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
</style>
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import type { FlexibleGridProps } from '../../types/index.js';
|
|
2
|
+
interface Props extends Omit<FlexibleGridProps, 'children'> {
|
|
3
|
+
children?: import('svelte').Snippet;
|
|
4
|
+
}
|
|
5
|
+
declare const FlexibleGrid: import("svelte").Component<Props, {}, "">;
|
|
6
|
+
type FlexibleGrid = ReturnType<typeof FlexibleGrid>;
|
|
7
|
+
export default FlexibleGrid;
|