@wire-dsl/engine 0.6.0 → 0.7.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 +1 -1
- package/dist/index.cjs +923 -138
- package/dist/index.d.cts +2 -4
- package/dist/index.d.ts +2 -4
- package/dist/index.js +923 -138
- package/package.json +2 -2
package/dist/index.js
CHANGED
|
@@ -2543,13 +2543,13 @@ ${messages}`);
|
|
|
2543
2543
|
"Heading",
|
|
2544
2544
|
"Text",
|
|
2545
2545
|
"Label",
|
|
2546
|
+
"Paragraph",
|
|
2546
2547
|
"Image",
|
|
2547
2548
|
"Card",
|
|
2548
2549
|
"Stat",
|
|
2549
2550
|
"Topbar",
|
|
2550
2551
|
"Table",
|
|
2551
2552
|
"Chart",
|
|
2552
|
-
"ChartPlaceholder",
|
|
2553
2553
|
"Textarea",
|
|
2554
2554
|
"Select",
|
|
2555
2555
|
"Checkbox",
|
|
@@ -2884,19 +2884,19 @@ var ICON_SIZES_BY_DENSITY = {
|
|
|
2884
2884
|
comfortable: { xs: 14, sm: 16, md: 20, lg: 28, xl: 36 }
|
|
2885
2885
|
};
|
|
2886
2886
|
var ICON_BUTTON_SIZES_BY_DENSITY = {
|
|
2887
|
-
compact: { sm: 20, md: 24, lg: 32 },
|
|
2888
|
-
normal: { sm: 24, md: 32, lg: 40 },
|
|
2889
|
-
comfortable: { sm: 28, md: 40, lg: 48 }
|
|
2887
|
+
compact: { xs: 16, sm: 20, md: 24, lg: 32, xl: 40 },
|
|
2888
|
+
normal: { xs: 20, sm: 24, md: 32, lg: 40, xl: 48 },
|
|
2889
|
+
comfortable: { xs: 24, sm: 28, md: 40, lg: 48, xl: 56 }
|
|
2890
2890
|
};
|
|
2891
2891
|
var CONTROL_HEIGHTS_BY_DENSITY = {
|
|
2892
|
-
compact: { sm: 28, md: 32, lg: 36 },
|
|
2893
|
-
normal: { sm: 36, md: 40, lg: 48 },
|
|
2894
|
-
comfortable: { sm: 40, md: 48, lg: 56 }
|
|
2892
|
+
compact: { xs: 24, sm: 28, md: 32, lg: 36, xl: 44 },
|
|
2893
|
+
normal: { xs: 28, sm: 36, md: 40, lg: 48, xl: 56 },
|
|
2894
|
+
comfortable: { xs: 32, sm: 40, md: 48, lg: 56, xl: 64 }
|
|
2895
2895
|
};
|
|
2896
2896
|
var ACTION_CONTROL_HEIGHTS_BY_DENSITY = {
|
|
2897
|
-
compact: { sm:
|
|
2898
|
-
normal: { sm:
|
|
2899
|
-
comfortable: { sm:
|
|
2897
|
+
compact: { xs: 24, sm: 28, md: 32, lg: 36, xl: 44 },
|
|
2898
|
+
normal: { xs: 28, sm: 36, md: 40, lg: 48, xl: 56 },
|
|
2899
|
+
comfortable: { xs: 32, sm: 40, md: 48, lg: 56, xl: 64 }
|
|
2900
2900
|
};
|
|
2901
2901
|
var CONTROL_PADDING_BY_DENSITY = {
|
|
2902
2902
|
compact: { none: 0, xs: 4, sm: 8, md: 10, lg: 14, xl: 18 },
|
|
@@ -3569,7 +3569,7 @@ var LayoutEngine = class {
|
|
|
3569
3569
|
wrapTextToLines(text, maxWidth, fontSize) {
|
|
3570
3570
|
const normalized = text.replace(/\r\n/g, "\n");
|
|
3571
3571
|
const paragraphs = normalized.split("\n");
|
|
3572
|
-
const charWidth = fontSize * 0.
|
|
3572
|
+
const charWidth = fontSize * 0.5;
|
|
3573
3573
|
const safeWidth = Math.max(maxWidth, charWidth);
|
|
3574
3574
|
const maxCharsPerLine = Math.max(1, Math.floor(safeWidth / charWidth));
|
|
3575
3575
|
const lines = [];
|
|
@@ -3607,12 +3607,14 @@ var LayoutEngine = class {
|
|
|
3607
3607
|
getIntrinsicComponentHeight(node, availableWidth) {
|
|
3608
3608
|
if (node.kind !== "component") return this.getComponentHeight();
|
|
3609
3609
|
const controlSize = String(node.props.size || "md");
|
|
3610
|
+
const actionControlSize = String(node.props.size || "sm");
|
|
3610
3611
|
const density = this.style.density || "normal";
|
|
3611
3612
|
const inputControlHeight = resolveControlHeight(controlSize, density);
|
|
3612
|
-
const actionControlHeight = resolveActionControlHeight(
|
|
3613
|
+
const actionControlHeight = resolveActionControlHeight(actionControlSize, density);
|
|
3613
3614
|
const controlLabelOffset = node.componentType === "Input" || node.componentType === "Textarea" || node.componentType === "Select" ? this.getControlLabelOffset(String(node.props.label || "")) : (node.componentType === "Button" || node.componentType === "IconButton") && this.parseBooleanProp(node.props.labelSpace, false) ? 18 : 0;
|
|
3614
3615
|
if (node.componentType === "Image") {
|
|
3615
3616
|
const placeholder = String(node.props.placeholder || "landscape");
|
|
3617
|
+
const isCircle = this.parseBooleanProp(node.props.circle, false);
|
|
3616
3618
|
const aspectRatios = {
|
|
3617
3619
|
landscape: 16 / 9,
|
|
3618
3620
|
portrait: 2 / 3,
|
|
@@ -3620,7 +3622,7 @@ var LayoutEngine = class {
|
|
|
3620
3622
|
icon: 1,
|
|
3621
3623
|
avatar: 1
|
|
3622
3624
|
};
|
|
3623
|
-
const ratio = aspectRatios[placeholder] || 16 / 9;
|
|
3625
|
+
const ratio = isCircle ? 1 : aspectRatios[placeholder] || 16 / 9;
|
|
3624
3626
|
const explicitHeight = Number(node.props.height);
|
|
3625
3627
|
if (!isNaN(explicitHeight) && explicitHeight > 0) {
|
|
3626
3628
|
return explicitHeight;
|
|
@@ -3672,13 +3674,19 @@ var LayoutEngine = class {
|
|
|
3672
3674
|
}
|
|
3673
3675
|
return Math.max(1, Math.ceil(wrappedHeight + verticalPadding * 2));
|
|
3674
3676
|
}
|
|
3675
|
-
if (node.componentType === "Text") {
|
|
3677
|
+
if (node.componentType === "Text" || node.componentType === "Paragraph") {
|
|
3676
3678
|
const content = String(node.props.text || "");
|
|
3677
|
-
const { fontSize, lineHeight } = this.getTextMetricsForDensity();
|
|
3679
|
+
const { fontSize: defaultFontSize, lineHeight } = this.getTextMetricsForDensity();
|
|
3680
|
+
const sizeProp = String(node.props.size || "");
|
|
3681
|
+
const textFontSizeMap = { xs: 10, sm: 12, lg: 16, xl: 20 };
|
|
3682
|
+
const fontSize = textFontSizeMap[sizeProp] ?? defaultFontSize;
|
|
3678
3683
|
const lineHeightPx = Math.ceil(fontSize * lineHeight);
|
|
3679
3684
|
const maxWidth = availableWidth && availableWidth > 0 ? availableWidth : 200;
|
|
3680
3685
|
const lines = this.wrapTextToLines(content, maxWidth, fontSize);
|
|
3681
3686
|
const wrappedHeight = Math.max(1, lines.length) * lineHeightPx;
|
|
3687
|
+
if (sizeProp) {
|
|
3688
|
+
return wrappedHeight;
|
|
3689
|
+
}
|
|
3682
3690
|
return Math.max(this.getComponentHeight(), wrappedHeight);
|
|
3683
3691
|
}
|
|
3684
3692
|
if (node.componentType === "Alert") {
|
|
@@ -3707,7 +3715,7 @@ var LayoutEngine = class {
|
|
|
3707
3715
|
if (node.componentType === "Modal") return 300;
|
|
3708
3716
|
if (node.componentType === "Card") return 120;
|
|
3709
3717
|
if (node.componentType === "Stat") return 120;
|
|
3710
|
-
if (node.componentType === "Chart"
|
|
3718
|
+
if (node.componentType === "Chart") return 250;
|
|
3711
3719
|
if (node.componentType === "List") {
|
|
3712
3720
|
const itemsFromProps = String(node.props.items || "").split(",").map((item) => item.trim()).filter(Boolean);
|
|
3713
3721
|
const parsedItemsMock = Number(node.props.itemsMock ?? 4);
|
|
@@ -3718,7 +3726,14 @@ var LayoutEngine = class {
|
|
|
3718
3726
|
const contentHeight = titleHeight + itemCount * itemHeight;
|
|
3719
3727
|
return Math.max(this.getComponentHeight(), contentHeight);
|
|
3720
3728
|
}
|
|
3721
|
-
if (node.componentType === "Topbar")
|
|
3729
|
+
if (node.componentType === "Topbar") {
|
|
3730
|
+
const TOPBAR_HEIGHTS = { sm: 44, md: 56, lg: 72 };
|
|
3731
|
+
return TOPBAR_HEIGHTS[String(node.props.size || "md")] ?? 56;
|
|
3732
|
+
}
|
|
3733
|
+
if (node.componentType === "Tabs") {
|
|
3734
|
+
const TABS_HEIGHTS = { sm: 32, md: 44, lg: 52 };
|
|
3735
|
+
return TABS_HEIGHTS[String(node.props.size || "md")] ?? 44;
|
|
3736
|
+
}
|
|
3722
3737
|
if (node.componentType === "Divider") return 1;
|
|
3723
3738
|
if (node.componentType === "Separate") return this.getSeparateSize(node);
|
|
3724
3739
|
if (node.componentType === "Input" || node.componentType === "Select") {
|
|
@@ -3727,6 +3742,11 @@ var LayoutEngine = class {
|
|
|
3727
3742
|
if (node.componentType === "Button" || node.componentType === "IconButton" || node.componentType === "Link") {
|
|
3728
3743
|
return actionControlHeight + controlLabelOffset;
|
|
3729
3744
|
}
|
|
3745
|
+
if (node.componentType === "Badge" || node.componentType === "Chip") {
|
|
3746
|
+
const BADGE_HEIGHTS = { xs: 28, sm: 36, md: 40, lg: 48, xl: 56 };
|
|
3747
|
+
const badgeSize = String(node.props.size || "md");
|
|
3748
|
+
return BADGE_HEIGHTS[badgeSize] ?? 40;
|
|
3749
|
+
}
|
|
3730
3750
|
return this.getComponentHeight();
|
|
3731
3751
|
}
|
|
3732
3752
|
getControlLabelOffset(label) {
|
|
@@ -3782,7 +3802,7 @@ var LayoutEngine = class {
|
|
|
3782
3802
|
return resolveIconSize(size, this.style.density || "normal");
|
|
3783
3803
|
}
|
|
3784
3804
|
if (node.componentType === "IconButton") {
|
|
3785
|
-
const size = String(node.props.size || "
|
|
3805
|
+
const size = String(node.props.size || "sm");
|
|
3786
3806
|
const density = this.style.density || "normal";
|
|
3787
3807
|
const baseSize = resolveIconButtonSize(size, density);
|
|
3788
3808
|
const extraPadding = resolveControlHorizontalPadding(String(node.props.padding || "none"), density);
|
|
@@ -3840,7 +3860,13 @@ var LayoutEngine = class {
|
|
|
3840
3860
|
}
|
|
3841
3861
|
if (node.componentType === "Badge" || node.componentType === "Chip") {
|
|
3842
3862
|
const text = String(node.props.text || "");
|
|
3843
|
-
|
|
3863
|
+
const size = String(node.props.size || "md");
|
|
3864
|
+
const BADGE_CHAR_W = { xs: 6, sm: 6.5, md: 7, lg: 7.5, xl: 8.5 };
|
|
3865
|
+
const BADGE_PAD_X = { xs: 5, sm: 6, md: 8, lg: 10, xl: 14 };
|
|
3866
|
+
const customPadding = node.props.padding !== void 0 ? Number(node.props.padding) : void 0;
|
|
3867
|
+
const padX = customPadding !== void 0 && !isNaN(customPadding) ? customPadding : BADGE_PAD_X[size] ?? 8;
|
|
3868
|
+
const charW = BADGE_CHAR_W[size] ?? 7;
|
|
3869
|
+
return Math.max(padX * 4, text.length * charW + padX * 2);
|
|
3844
3870
|
}
|
|
3845
3871
|
return 120;
|
|
3846
3872
|
}
|
|
@@ -4124,34 +4150,358 @@ MockDataGenerator.HEADER_TO_MOCK = {
|
|
|
4124
4150
|
var ColorResolver = class {
|
|
4125
4151
|
constructor() {
|
|
4126
4152
|
this.customColors = {};
|
|
4127
|
-
// Named colors palette
|
|
4153
|
+
// Named colors palette — Full Material Design + utility aliases
|
|
4128
4154
|
this.namedColors = {
|
|
4129
|
-
//
|
|
4155
|
+
// ── Utility ──────────────────────────────────────────────────────────────
|
|
4130
4156
|
white: "#FFFFFF",
|
|
4131
4157
|
black: "#000000",
|
|
4132
|
-
gray: "#
|
|
4133
|
-
|
|
4158
|
+
gray: "#9E9E9E",
|
|
4159
|
+
// alias for grey 500
|
|
4160
|
+
grey: "#9E9E9E",
|
|
4161
|
+
slate: "#607D8B",
|
|
4162
|
+
// alias for blue_grey 500
|
|
4134
4163
|
zinc: "#71717A",
|
|
4135
|
-
//
|
|
4136
|
-
red: "#EF4444",
|
|
4137
|
-
orange: "#F97316",
|
|
4138
|
-
yellow: "#EAB308",
|
|
4139
|
-
lime: "#84CC16",
|
|
4140
|
-
green: "#22C55E",
|
|
4164
|
+
// Extra well-known non-Material names (kept for backward compat)
|
|
4141
4165
|
emerald: "#10B981",
|
|
4142
|
-
teal: "#14B8A6",
|
|
4143
|
-
cyan: "#06B6D4",
|
|
4144
|
-
blue: "#3B82F6",
|
|
4145
|
-
indigo: "#6366F1",
|
|
4146
4166
|
violet: "#8B5CF6",
|
|
4147
|
-
purple: "#A855F7",
|
|
4148
4167
|
fuchsia: "#D946EF",
|
|
4149
|
-
pink: "#EC4899",
|
|
4150
4168
|
rose: "#F43F5E",
|
|
4151
|
-
// Light variants
|
|
4152
|
-
"red-light": "#
|
|
4153
|
-
"blue-light": "#
|
|
4154
|
-
"green-light": "#
|
|
4169
|
+
// Light utility variants
|
|
4170
|
+
"red-light": "#FFCDD2",
|
|
4171
|
+
"blue-light": "#BBDEFB",
|
|
4172
|
+
"green-light": "#C8E6C9",
|
|
4173
|
+
// ── Red ──────────────────────────────────────────────────────────────────
|
|
4174
|
+
red: "#F44336",
|
|
4175
|
+
// 500
|
|
4176
|
+
red_50: "#FFEBEE",
|
|
4177
|
+
red_100: "#FFCDD2",
|
|
4178
|
+
red_200: "#EF9A9A",
|
|
4179
|
+
red_300: "#E57373",
|
|
4180
|
+
red_400: "#EF5350",
|
|
4181
|
+
red_500: "#F44336",
|
|
4182
|
+
red_600: "#E53935",
|
|
4183
|
+
red_700: "#D32F2F",
|
|
4184
|
+
red_800: "#C62828",
|
|
4185
|
+
red_900: "#B71C1C",
|
|
4186
|
+
red_A100: "#FF8A80",
|
|
4187
|
+
red_A200: "#FF5252",
|
|
4188
|
+
red_A400: "#FF1744",
|
|
4189
|
+
red_A700: "#D50000",
|
|
4190
|
+
// ── Pink ─────────────────────────────────────────────────────────────────
|
|
4191
|
+
pink: "#E91E63",
|
|
4192
|
+
// 500
|
|
4193
|
+
pink_50: "#FCE4EC",
|
|
4194
|
+
pink_100: "#F8BBD0",
|
|
4195
|
+
pink_200: "#F48FB1",
|
|
4196
|
+
pink_300: "#F06292",
|
|
4197
|
+
pink_400: "#EC407A",
|
|
4198
|
+
pink_500: "#E91E63",
|
|
4199
|
+
pink_600: "#D81B60",
|
|
4200
|
+
pink_700: "#C2185B",
|
|
4201
|
+
pink_800: "#AD1457",
|
|
4202
|
+
pink_900: "#880E4F",
|
|
4203
|
+
pink_A100: "#FF80AB",
|
|
4204
|
+
pink_A200: "#FF4081",
|
|
4205
|
+
pink_A400: "#F50057",
|
|
4206
|
+
pink_A700: "#C51162",
|
|
4207
|
+
// ── Purple ───────────────────────────────────────────────────────────────
|
|
4208
|
+
purple: "#9C27B0",
|
|
4209
|
+
// 500
|
|
4210
|
+
purple_50: "#F3E5F5",
|
|
4211
|
+
purple_100: "#E1BEE7",
|
|
4212
|
+
purple_200: "#CE93D8",
|
|
4213
|
+
purple_300: "#BA68C8",
|
|
4214
|
+
purple_400: "#AB47BC",
|
|
4215
|
+
purple_500: "#9C27B0",
|
|
4216
|
+
purple_600: "#8E24AA",
|
|
4217
|
+
purple_700: "#7B1FA2",
|
|
4218
|
+
purple_800: "#6A1B9A",
|
|
4219
|
+
purple_900: "#4A148C",
|
|
4220
|
+
purple_A100: "#EA80FC",
|
|
4221
|
+
purple_A200: "#E040FB",
|
|
4222
|
+
purple_A400: "#D500F9",
|
|
4223
|
+
purple_A700: "#AA00FF",
|
|
4224
|
+
// ── Deep Purple ──────────────────────────────────────────────────────────
|
|
4225
|
+
deep_purple: "#673AB7",
|
|
4226
|
+
// 500
|
|
4227
|
+
deep_purple_50: "#EDE7F6",
|
|
4228
|
+
deep_purple_100: "#D1C4E9",
|
|
4229
|
+
deep_purple_200: "#B39DDB",
|
|
4230
|
+
deep_purple_300: "#9575CD",
|
|
4231
|
+
deep_purple_400: "#7E57C2",
|
|
4232
|
+
deep_purple_500: "#673AB7",
|
|
4233
|
+
deep_purple_600: "#5E35B1",
|
|
4234
|
+
deep_purple_700: "#512DA8",
|
|
4235
|
+
deep_purple_800: "#4527A0",
|
|
4236
|
+
deep_purple_900: "#311B92",
|
|
4237
|
+
deep_purple_A100: "#B388FF",
|
|
4238
|
+
deep_purple_A200: "#7C4DFF",
|
|
4239
|
+
deep_purple_A400: "#651FFF",
|
|
4240
|
+
deep_purple_A700: "#6200EA",
|
|
4241
|
+
// ── Indigo ───────────────────────────────────────────────────────────────
|
|
4242
|
+
indigo: "#3F51B5",
|
|
4243
|
+
// 500
|
|
4244
|
+
indigo_50: "#E8EAF6",
|
|
4245
|
+
indigo_100: "#C5CAE9",
|
|
4246
|
+
indigo_200: "#9FA8DA",
|
|
4247
|
+
indigo_300: "#7986CB",
|
|
4248
|
+
indigo_400: "#5C6BC0",
|
|
4249
|
+
indigo_500: "#3F51B5",
|
|
4250
|
+
indigo_600: "#3949AB",
|
|
4251
|
+
indigo_700: "#303F9F",
|
|
4252
|
+
indigo_800: "#283593",
|
|
4253
|
+
indigo_900: "#1A237E",
|
|
4254
|
+
indigo_A100: "#8C9EFF",
|
|
4255
|
+
indigo_A200: "#536DFE",
|
|
4256
|
+
indigo_A400: "#3D5AFE",
|
|
4257
|
+
indigo_A700: "#304FFE",
|
|
4258
|
+
// ── Blue ─────────────────────────────────────────────────────────────────
|
|
4259
|
+
blue: "#2196F3",
|
|
4260
|
+
// 500
|
|
4261
|
+
blue_50: "#E3F2FD",
|
|
4262
|
+
blue_100: "#BBDEFB",
|
|
4263
|
+
blue_200: "#90CAF9",
|
|
4264
|
+
blue_300: "#64B5F6",
|
|
4265
|
+
blue_400: "#42A5F5",
|
|
4266
|
+
blue_500: "#2196F3",
|
|
4267
|
+
blue_600: "#1E88E5",
|
|
4268
|
+
blue_700: "#1976D2",
|
|
4269
|
+
blue_800: "#1565C0",
|
|
4270
|
+
blue_900: "#0D47A1",
|
|
4271
|
+
blue_A100: "#82B1FF",
|
|
4272
|
+
blue_A200: "#448AFF",
|
|
4273
|
+
blue_A400: "#2979FF",
|
|
4274
|
+
blue_A700: "#2962FF",
|
|
4275
|
+
// ── Light Blue ───────────────────────────────────────────────────────────
|
|
4276
|
+
light_blue: "#03A9F4",
|
|
4277
|
+
// 500
|
|
4278
|
+
light_blue_50: "#E1F5FE",
|
|
4279
|
+
light_blue_100: "#B3E5FC",
|
|
4280
|
+
light_blue_200: "#81D4FA",
|
|
4281
|
+
light_blue_300: "#4FC3F7",
|
|
4282
|
+
light_blue_400: "#29B6F6",
|
|
4283
|
+
light_blue_500: "#03A9F4",
|
|
4284
|
+
light_blue_600: "#039BE5",
|
|
4285
|
+
light_blue_700: "#0288D1",
|
|
4286
|
+
light_blue_800: "#0277BD",
|
|
4287
|
+
light_blue_900: "#01579B",
|
|
4288
|
+
light_blue_A100: "#80D8FF",
|
|
4289
|
+
light_blue_A200: "#40C4FF",
|
|
4290
|
+
light_blue_A400: "#00B0FF",
|
|
4291
|
+
light_blue_A700: "#0091EA",
|
|
4292
|
+
// ── Cyan ─────────────────────────────────────────────────────────────────
|
|
4293
|
+
cyan: "#00BCD4",
|
|
4294
|
+
// 500
|
|
4295
|
+
cyan_50: "#E0F7FA",
|
|
4296
|
+
cyan_100: "#B2EBF2",
|
|
4297
|
+
cyan_200: "#80DEEA",
|
|
4298
|
+
cyan_300: "#4DD0E1",
|
|
4299
|
+
cyan_400: "#26C6DA",
|
|
4300
|
+
cyan_500: "#00BCD4",
|
|
4301
|
+
cyan_600: "#00ACC1",
|
|
4302
|
+
cyan_700: "#0097A7",
|
|
4303
|
+
cyan_800: "#00838F",
|
|
4304
|
+
cyan_900: "#006064",
|
|
4305
|
+
cyan_A100: "#84FFFF",
|
|
4306
|
+
cyan_A200: "#18FFFF",
|
|
4307
|
+
cyan_A400: "#00E5FF",
|
|
4308
|
+
cyan_A700: "#00B8D4",
|
|
4309
|
+
// ── Teal ─────────────────────────────────────────────────────────────────
|
|
4310
|
+
teal: "#009688",
|
|
4311
|
+
// 500
|
|
4312
|
+
teal_50: "#E0F2F1",
|
|
4313
|
+
teal_100: "#B2DFDB",
|
|
4314
|
+
teal_200: "#80CBC4",
|
|
4315
|
+
teal_300: "#4DB6AC",
|
|
4316
|
+
teal_400: "#26A69A",
|
|
4317
|
+
teal_500: "#009688",
|
|
4318
|
+
teal_600: "#00897B",
|
|
4319
|
+
teal_700: "#00796B",
|
|
4320
|
+
teal_800: "#00695C",
|
|
4321
|
+
teal_900: "#004D40",
|
|
4322
|
+
teal_A100: "#A7FFEB",
|
|
4323
|
+
teal_A200: "#64FFDA",
|
|
4324
|
+
teal_A400: "#1DE9B6",
|
|
4325
|
+
teal_A700: "#00BFA5",
|
|
4326
|
+
// ── Green ────────────────────────────────────────────────────────────────
|
|
4327
|
+
green: "#4CAF50",
|
|
4328
|
+
// 500
|
|
4329
|
+
green_50: "#E8F5E9",
|
|
4330
|
+
green_100: "#C8E6C9",
|
|
4331
|
+
green_200: "#A5D6A7",
|
|
4332
|
+
green_300: "#81C784",
|
|
4333
|
+
green_400: "#66BB6A",
|
|
4334
|
+
green_500: "#4CAF50",
|
|
4335
|
+
green_600: "#43A047",
|
|
4336
|
+
green_700: "#388E3C",
|
|
4337
|
+
green_800: "#2E7D32",
|
|
4338
|
+
green_900: "#1B5E20",
|
|
4339
|
+
green_A100: "#B9F6CA",
|
|
4340
|
+
green_A200: "#69F0AE",
|
|
4341
|
+
green_A400: "#00E676",
|
|
4342
|
+
green_A700: "#00C853",
|
|
4343
|
+
// ── Light Green ──────────────────────────────────────────────────────────
|
|
4344
|
+
light_green: "#8BC34A",
|
|
4345
|
+
// 500
|
|
4346
|
+
light_green_50: "#F1F8E9",
|
|
4347
|
+
light_green_100: "#DCEDC8",
|
|
4348
|
+
light_green_200: "#C5E1A5",
|
|
4349
|
+
light_green_300: "#AED581",
|
|
4350
|
+
light_green_400: "#9CCC65",
|
|
4351
|
+
light_green_500: "#8BC34A",
|
|
4352
|
+
light_green_600: "#7CB342",
|
|
4353
|
+
light_green_700: "#689F38",
|
|
4354
|
+
light_green_800: "#558B2F",
|
|
4355
|
+
light_green_900: "#33691E",
|
|
4356
|
+
light_green_A100: "#CCFF90",
|
|
4357
|
+
light_green_A200: "#B2FF59",
|
|
4358
|
+
light_green_A400: "#76FF03",
|
|
4359
|
+
light_green_A700: "#64DD17",
|
|
4360
|
+
// ── Lime ─────────────────────────────────────────────────────────────────
|
|
4361
|
+
lime: "#CDDC39",
|
|
4362
|
+
// 500
|
|
4363
|
+
lime_50: "#F9FBE7",
|
|
4364
|
+
lime_100: "#F0F4C3",
|
|
4365
|
+
lime_200: "#E6EE9C",
|
|
4366
|
+
lime_300: "#DCE775",
|
|
4367
|
+
lime_400: "#D4E157",
|
|
4368
|
+
lime_500: "#CDDC39",
|
|
4369
|
+
lime_600: "#C0CA33",
|
|
4370
|
+
lime_700: "#AFB42B",
|
|
4371
|
+
lime_800: "#9E9D24",
|
|
4372
|
+
lime_900: "#827717",
|
|
4373
|
+
lime_A100: "#F4FF81",
|
|
4374
|
+
lime_A200: "#EEFF41",
|
|
4375
|
+
lime_A400: "#C6FF00",
|
|
4376
|
+
lime_A700: "#AEEA00",
|
|
4377
|
+
// ── Yellow ───────────────────────────────────────────────────────────────
|
|
4378
|
+
yellow: "#FFEB3B",
|
|
4379
|
+
// 500
|
|
4380
|
+
yellow_50: "#FFFDE7",
|
|
4381
|
+
yellow_100: "#FFF9C4",
|
|
4382
|
+
yellow_200: "#FFF59D",
|
|
4383
|
+
yellow_300: "#FFF176",
|
|
4384
|
+
yellow_400: "#FFEE58",
|
|
4385
|
+
yellow_500: "#FFEB3B",
|
|
4386
|
+
yellow_600: "#FDD835",
|
|
4387
|
+
yellow_700: "#F9A825",
|
|
4388
|
+
yellow_800: "#F57F17",
|
|
4389
|
+
yellow_900: "#F57F17",
|
|
4390
|
+
yellow_A100: "#FFFF8D",
|
|
4391
|
+
yellow_A200: "#FFFF00",
|
|
4392
|
+
yellow_A400: "#FFEA00",
|
|
4393
|
+
yellow_A700: "#FFD600",
|
|
4394
|
+
// ── Amber ────────────────────────────────────────────────────────────────
|
|
4395
|
+
amber: "#FFC107",
|
|
4396
|
+
// 500
|
|
4397
|
+
amber_50: "#FFF8E1",
|
|
4398
|
+
amber_100: "#FFECB3",
|
|
4399
|
+
amber_200: "#FFE082",
|
|
4400
|
+
amber_300: "#FFD54F",
|
|
4401
|
+
amber_400: "#FFCA28",
|
|
4402
|
+
amber_500: "#FFC107",
|
|
4403
|
+
amber_600: "#FFB300",
|
|
4404
|
+
amber_700: "#FFA000",
|
|
4405
|
+
amber_800: "#FF8F00",
|
|
4406
|
+
amber_900: "#FF6F00",
|
|
4407
|
+
amber_A100: "#FFE57F",
|
|
4408
|
+
amber_A200: "#FFD740",
|
|
4409
|
+
amber_A400: "#FFC400",
|
|
4410
|
+
amber_A700: "#FFAB00",
|
|
4411
|
+
// ── Orange ───────────────────────────────────────────────────────────────
|
|
4412
|
+
orange: "#FF9800",
|
|
4413
|
+
// 500
|
|
4414
|
+
orange_50: "#FFF3E0",
|
|
4415
|
+
orange_100: "#FFE0B2",
|
|
4416
|
+
orange_200: "#FFCC80",
|
|
4417
|
+
orange_300: "#FFB74D",
|
|
4418
|
+
orange_400: "#FFA726",
|
|
4419
|
+
orange_500: "#FF9800",
|
|
4420
|
+
orange_600: "#FB8C00",
|
|
4421
|
+
orange_700: "#F57C00",
|
|
4422
|
+
orange_800: "#EF6C00",
|
|
4423
|
+
orange_900: "#E65100",
|
|
4424
|
+
orange_A100: "#FFD180",
|
|
4425
|
+
orange_A200: "#FFAB40",
|
|
4426
|
+
orange_A400: "#FF9100",
|
|
4427
|
+
orange_A700: "#FF6D00",
|
|
4428
|
+
// ── Deep Orange ──────────────────────────────────────────────────────────
|
|
4429
|
+
deep_orange: "#FF5722",
|
|
4430
|
+
// 500
|
|
4431
|
+
deep_orange_50: "#FBE9E7",
|
|
4432
|
+
deep_orange_100: "#FFCCBC",
|
|
4433
|
+
deep_orange_200: "#FFAB91",
|
|
4434
|
+
deep_orange_300: "#FF8A65",
|
|
4435
|
+
deep_orange_400: "#FF7043",
|
|
4436
|
+
deep_orange_500: "#FF5722",
|
|
4437
|
+
deep_orange_600: "#F4511E",
|
|
4438
|
+
deep_orange_700: "#E64A19",
|
|
4439
|
+
deep_orange_800: "#D84315",
|
|
4440
|
+
deep_orange_900: "#BF360C",
|
|
4441
|
+
deep_orange_A100: "#FF9E80",
|
|
4442
|
+
deep_orange_A200: "#FF6E40",
|
|
4443
|
+
deep_orange_A400: "#FF3D00",
|
|
4444
|
+
deep_orange_A700: "#DD2C00",
|
|
4445
|
+
// ── Brown ────────────────────────────────────────────────────────────────
|
|
4446
|
+
brown: "#795548",
|
|
4447
|
+
// 500
|
|
4448
|
+
brown_50: "#EFEBE9",
|
|
4449
|
+
brown_100: "#D7CCC8",
|
|
4450
|
+
brown_200: "#BCAAA4",
|
|
4451
|
+
brown_300: "#A1887F",
|
|
4452
|
+
brown_400: "#8D6E63",
|
|
4453
|
+
brown_500: "#795548",
|
|
4454
|
+
brown_600: "#6D4C41",
|
|
4455
|
+
brown_700: "#5D4037",
|
|
4456
|
+
brown_800: "#4E342E",
|
|
4457
|
+
brown_900: "#3E2723",
|
|
4458
|
+
// ── Grey ─────────────────────────────────────────────────────────────────
|
|
4459
|
+
grey_50: "#FAFAFA",
|
|
4460
|
+
grey_100: "#F5F5F5",
|
|
4461
|
+
grey_200: "#EEEEEE",
|
|
4462
|
+
grey_300: "#E0E0E0",
|
|
4463
|
+
grey_400: "#BDBDBD",
|
|
4464
|
+
grey_500: "#9E9E9E",
|
|
4465
|
+
grey_600: "#757575",
|
|
4466
|
+
grey_700: "#616161",
|
|
4467
|
+
grey_800: "#424242",
|
|
4468
|
+
grey_900: "#212121",
|
|
4469
|
+
// aliases
|
|
4470
|
+
gray_50: "#FAFAFA",
|
|
4471
|
+
gray_100: "#F5F5F5",
|
|
4472
|
+
gray_200: "#EEEEEE",
|
|
4473
|
+
gray_300: "#E0E0E0",
|
|
4474
|
+
gray_400: "#BDBDBD",
|
|
4475
|
+
gray_500: "#9E9E9E",
|
|
4476
|
+
gray_600: "#757575",
|
|
4477
|
+
gray_700: "#616161",
|
|
4478
|
+
gray_800: "#424242",
|
|
4479
|
+
gray_900: "#212121",
|
|
4480
|
+
// ── Blue Grey ────────────────────────────────────────────────────────────
|
|
4481
|
+
blue_grey: "#607D8B",
|
|
4482
|
+
// 500
|
|
4483
|
+
blue_grey_50: "#ECEFF1",
|
|
4484
|
+
blue_grey_100: "#CFD8DC",
|
|
4485
|
+
blue_grey_200: "#B0BEC5",
|
|
4486
|
+
blue_grey_300: "#90A4AE",
|
|
4487
|
+
blue_grey_400: "#78909C",
|
|
4488
|
+
blue_grey_500: "#607D8B",
|
|
4489
|
+
blue_grey_600: "#546E7A",
|
|
4490
|
+
blue_grey_700: "#455A64",
|
|
4491
|
+
blue_grey_800: "#37474F",
|
|
4492
|
+
blue_grey_900: "#263238",
|
|
4493
|
+
// aliases
|
|
4494
|
+
blue_gray: "#607D8B",
|
|
4495
|
+
blue_gray_50: "#ECEFF1",
|
|
4496
|
+
blue_gray_100: "#CFD8DC",
|
|
4497
|
+
blue_gray_200: "#B0BEC5",
|
|
4498
|
+
blue_gray_300: "#90A4AE",
|
|
4499
|
+
blue_gray_400: "#78909C",
|
|
4500
|
+
blue_gray_500: "#607D8B",
|
|
4501
|
+
blue_gray_600: "#546E7A",
|
|
4502
|
+
blue_gray_700: "#455A64",
|
|
4503
|
+
blue_gray_800: "#37474F",
|
|
4504
|
+
blue_gray_900: "#263238"
|
|
4155
4505
|
};
|
|
4156
4506
|
}
|
|
4157
4507
|
/**
|
|
@@ -4799,7 +5149,8 @@ var SVGRenderer = class {
|
|
|
4799
5149
|
if (node.containerType === "split") {
|
|
4800
5150
|
this.renderSplitDecoration(node, pos, containerGroup);
|
|
4801
5151
|
}
|
|
4802
|
-
|
|
5152
|
+
const isCellContainer = node.meta?.source === "cell";
|
|
5153
|
+
if (node.children.length === 0 && this.options.showDiagnostics && !isCellContainer) {
|
|
4803
5154
|
containerGroup.push(this.renderEmptyContainerDiagnostic(pos, node.containerType));
|
|
4804
5155
|
} else {
|
|
4805
5156
|
node.children.forEach((childRef) => {
|
|
@@ -4846,7 +5197,6 @@ var SVGRenderer = class {
|
|
|
4846
5197
|
case "Table":
|
|
4847
5198
|
return this.renderTable(node, pos);
|
|
4848
5199
|
case "Chart":
|
|
4849
|
-
case "ChartPlaceholder":
|
|
4850
5200
|
return this.renderChartPlaceholder(node, pos);
|
|
4851
5201
|
case "Breadcrumbs":
|
|
4852
5202
|
return this.renderBreadcrumbs(node, pos);
|
|
@@ -4855,6 +5205,8 @@ var SVGRenderer = class {
|
|
|
4855
5205
|
// Text/Content components
|
|
4856
5206
|
case "Text":
|
|
4857
5207
|
return this.renderText(node, pos);
|
|
5208
|
+
case "Paragraph":
|
|
5209
|
+
return this.renderParagraph(node, pos);
|
|
4858
5210
|
case "Label":
|
|
4859
5211
|
return this.renderLabel(node, pos);
|
|
4860
5212
|
case "Code":
|
|
@@ -4934,7 +5286,7 @@ var SVGRenderer = class {
|
|
|
4934
5286
|
renderButton(node, pos) {
|
|
4935
5287
|
const text = String(node.props.text || "Button");
|
|
4936
5288
|
const variant = String(node.props.variant || "default");
|
|
4937
|
-
const size = String(node.props.size || "
|
|
5289
|
+
const size = String(node.props.size || "sm");
|
|
4938
5290
|
const disabled = this.parseBooleanProp(node.props.disabled, false);
|
|
4939
5291
|
const density = this.ir.project.style.density || "normal";
|
|
4940
5292
|
const extraPadding = resolveControlHorizontalPadding(String(node.props.padding || "none"), density);
|
|
@@ -5009,7 +5361,7 @@ var SVGRenderer = class {
|
|
|
5009
5361
|
renderLink(node, pos) {
|
|
5010
5362
|
const text = String(node.props.text || "Link");
|
|
5011
5363
|
const variant = String(node.props.variant || "primary");
|
|
5012
|
-
const size = String(node.props.size || "
|
|
5364
|
+
const size = String(node.props.size || "sm");
|
|
5013
5365
|
const density = this.ir.project.style.density || "normal";
|
|
5014
5366
|
const fontSize = this.tokens.button.fontSize;
|
|
5015
5367
|
const fontWeight = this.tokens.button.fontWeight;
|
|
@@ -5115,7 +5467,33 @@ var SVGRenderer = class {
|
|
|
5115
5467
|
const variant = String(node.props.variant || "default");
|
|
5116
5468
|
const accentColor = variant === "default" ? this.resolveAccentColor() : this.resolveVariantColor(variant, this.resolveAccentColor());
|
|
5117
5469
|
const showBorder = this.parseBooleanProp(node.props.border, false);
|
|
5118
|
-
const
|
|
5470
|
+
const bgPropStr = String(node.props.background ?? "");
|
|
5471
|
+
let resolvedBg = null;
|
|
5472
|
+
if (bgPropStr === "true") {
|
|
5473
|
+
resolvedBg = this.renderTheme.cardBg;
|
|
5474
|
+
} else if (bgPropStr && bgPropStr !== "false") {
|
|
5475
|
+
if (bgPropStr.startsWith("#") || bgPropStr.startsWith("rgb")) {
|
|
5476
|
+
resolvedBg = bgPropStr;
|
|
5477
|
+
} else if (this.colorResolver.hasColor(bgPropStr)) {
|
|
5478
|
+
resolvedBg = this.colorResolver.resolveColor(bgPropStr, this.renderTheme.cardBg);
|
|
5479
|
+
}
|
|
5480
|
+
}
|
|
5481
|
+
const showBackground = resolvedBg !== null;
|
|
5482
|
+
const colorPropStr = String(node.props.color ?? "");
|
|
5483
|
+
let titleColor = this.renderTheme.text;
|
|
5484
|
+
let subtitleColor = this.renderTheme.textMuted;
|
|
5485
|
+
if (colorPropStr && colorPropStr !== "false") {
|
|
5486
|
+
let resolvedTitleColor = null;
|
|
5487
|
+
if (colorPropStr.startsWith("#") || colorPropStr.startsWith("rgb")) {
|
|
5488
|
+
resolvedTitleColor = colorPropStr;
|
|
5489
|
+
} else if (this.colorResolver.hasColor(colorPropStr)) {
|
|
5490
|
+
resolvedTitleColor = this.colorResolver.resolveColor(colorPropStr, this.renderTheme.text);
|
|
5491
|
+
}
|
|
5492
|
+
if (resolvedTitleColor) {
|
|
5493
|
+
titleColor = resolvedTitleColor;
|
|
5494
|
+
subtitleColor = this.hexToRgba(resolvedTitleColor, 0.65);
|
|
5495
|
+
}
|
|
5496
|
+
}
|
|
5119
5497
|
const radiusMap = {
|
|
5120
5498
|
none: 0,
|
|
5121
5499
|
sm: 4,
|
|
@@ -5127,7 +5505,7 @@ var SVGRenderer = class {
|
|
|
5127
5505
|
const topbar = this.calculateTopbarLayout(node, pos, title, subtitle, actions, user);
|
|
5128
5506
|
let svg = `<g${this.getDataNodeId(node)}>`;
|
|
5129
5507
|
if (showBorder || showBackground) {
|
|
5130
|
-
const bg =
|
|
5508
|
+
const bg = resolvedBg ?? "none";
|
|
5131
5509
|
const stroke = showBorder ? this.renderTheme.border : "none";
|
|
5132
5510
|
svg += `
|
|
5133
5511
|
<rect x="${pos.x}" y="${pos.y}"
|
|
@@ -5143,13 +5521,13 @@ var SVGRenderer = class {
|
|
|
5143
5521
|
font-family="Arial, Helvetica, sans-serif"
|
|
5144
5522
|
font-size="18"
|
|
5145
5523
|
font-weight="600"
|
|
5146
|
-
fill="${
|
|
5524
|
+
fill="${titleColor}">${this.escapeXml(topbar.visibleTitle)}</text>`;
|
|
5147
5525
|
if (topbar.hasSubtitle) {
|
|
5148
5526
|
svg += `
|
|
5149
5527
|
<text x="${topbar.textX}" y="${topbar.subtitleY}"
|
|
5150
5528
|
font-family="Arial, Helvetica, sans-serif"
|
|
5151
5529
|
font-size="13"
|
|
5152
|
-
fill="${
|
|
5530
|
+
fill="${subtitleColor}">${this.escapeXml(topbar.visibleSubtitle)}</text>`;
|
|
5153
5531
|
}
|
|
5154
5532
|
if (topbar.leftIcon) {
|
|
5155
5533
|
svg += `
|
|
@@ -5630,8 +6008,13 @@ var SVGRenderer = class {
|
|
|
5630
6008
|
// ============================================================================
|
|
5631
6009
|
renderText(node, pos) {
|
|
5632
6010
|
const text = String(node.props.text || "Text content");
|
|
5633
|
-
const
|
|
6011
|
+
const sizeProp = String(node.props.size || "");
|
|
6012
|
+
const defaultFontSize = this.tokens.text.fontSize;
|
|
6013
|
+
const textFontSizeMap = { xs: 10, sm: 12, lg: 16, xl: 20 };
|
|
6014
|
+
const fontSize = textFontSizeMap[sizeProp] ?? defaultFontSize;
|
|
5634
6015
|
const lineHeightPx = Math.ceil(fontSize * this.tokens.text.lineHeight);
|
|
6016
|
+
const bold = this.parseBooleanProp(node.props.bold, false);
|
|
6017
|
+
const italic = this.parseBooleanProp(node.props.italic, false);
|
|
5635
6018
|
const lines = this.wrapTextToLines(text, pos.width, fontSize);
|
|
5636
6019
|
const totalTextHeight = lines.length * lineHeightPx;
|
|
5637
6020
|
const firstLineY = pos.y + Math.round(Math.max(0, (pos.height - totalTextHeight) / 2)) + fontSize;
|
|
@@ -5642,9 +6025,49 @@ var SVGRenderer = class {
|
|
|
5642
6025
|
<text x="${pos.x}" y="${firstLineY}"
|
|
5643
6026
|
font-family="Arial, Helvetica, sans-serif"
|
|
5644
6027
|
font-size="${fontSize}"
|
|
6028
|
+
font-weight="${bold ? "700" : "400"}"
|
|
6029
|
+
font-style="${italic ? "italic" : "normal"}"
|
|
5645
6030
|
fill="${this.renderTheme.text}">${tspans}</text>
|
|
5646
6031
|
</g>`;
|
|
5647
6032
|
}
|
|
6033
|
+
renderParagraph(node, pos) {
|
|
6034
|
+
const text = String(node.props.text || "");
|
|
6035
|
+
const sizeProp = String(node.props.size || "");
|
|
6036
|
+
const defaultFontSize = this.tokens.text.fontSize;
|
|
6037
|
+
const textFontSizeMap = { xs: 10, sm: 12, lg: 16, xl: 20 };
|
|
6038
|
+
const fontSize = textFontSizeMap[sizeProp] ?? defaultFontSize;
|
|
6039
|
+
const lineHeightPx = Math.ceil(fontSize * this.tokens.text.lineHeight);
|
|
6040
|
+
const bold = this.parseBooleanProp(node.props.bold, false);
|
|
6041
|
+
const italic = this.parseBooleanProp(node.props.italic, false);
|
|
6042
|
+
const align = String(node.props.align || "left");
|
|
6043
|
+
const lines = this.wrapTextToLines(text, pos.width, fontSize);
|
|
6044
|
+
const totalTextHeight = lines.length * lineHeightPx;
|
|
6045
|
+
const firstLineY = pos.y + Math.round(Math.max(0, (pos.height - totalTextHeight) / 2)) + fontSize;
|
|
6046
|
+
let textX;
|
|
6047
|
+
let textAnchor;
|
|
6048
|
+
if (align === "center") {
|
|
6049
|
+
textX = pos.x + pos.width / 2;
|
|
6050
|
+
textAnchor = "middle";
|
|
6051
|
+
} else if (align === "right") {
|
|
6052
|
+
textX = pos.x + pos.width;
|
|
6053
|
+
textAnchor = "end";
|
|
6054
|
+
} else {
|
|
6055
|
+
textX = pos.x;
|
|
6056
|
+
textAnchor = "start";
|
|
6057
|
+
}
|
|
6058
|
+
const tspans = lines.map(
|
|
6059
|
+
(line, index) => `<tspan x="${textX}" dy="${index === 0 ? 0 : lineHeightPx}">${this.escapeXml(line)}</tspan>`
|
|
6060
|
+
).join("");
|
|
6061
|
+
return `<g${this.getDataNodeId(node)}>
|
|
6062
|
+
<text x="${textX}" y="${firstLineY}"
|
|
6063
|
+
font-family="Arial, Helvetica, sans-serif"
|
|
6064
|
+
font-size="${fontSize}"
|
|
6065
|
+
font-weight="${bold ? "700" : "400"}"
|
|
6066
|
+
font-style="${italic ? "italic" : "normal"}"
|
|
6067
|
+
fill="${this.renderTheme.text}"
|
|
6068
|
+
text-anchor="${textAnchor}">${tspans}</text>
|
|
6069
|
+
</g>`;
|
|
6070
|
+
}
|
|
5648
6071
|
renderLabel(node, pos) {
|
|
5649
6072
|
const text = String(node.props.text || "Label");
|
|
5650
6073
|
const textY = pos.y + Math.round(pos.height / 2) + 4;
|
|
@@ -5887,34 +6310,145 @@ var SVGRenderer = class {
|
|
|
5887
6310
|
const tabs = itemsStr ? itemsStr.split(",").map((t) => t.trim()) : ["Tab 1", "Tab 2", "Tab 3"];
|
|
5888
6311
|
const activeProp = node.props.active ?? 0;
|
|
5889
6312
|
const activeIndex = Number.isFinite(Number(activeProp)) ? Math.max(0, Math.floor(Number(activeProp))) : 0;
|
|
5890
|
-
const
|
|
6313
|
+
const variant = String(node.props.variant || "default");
|
|
6314
|
+
const accentColor = variant === "default" ? this.resolveAccentColor() : this.resolveVariantColor(variant, this.resolveAccentColor());
|
|
6315
|
+
const radiusMap = { none: 0, sm: 4, md: 6, lg: 10, full: 20 };
|
|
6316
|
+
const tabRadius = radiusMap[String(node.props.radius || "md")] ?? 6;
|
|
6317
|
+
const sizeMap = { sm: 32, md: 44, lg: 52 };
|
|
6318
|
+
const tabHeight = pos.height > 0 ? pos.height : sizeMap[String(node.props.size || "md")] ?? 44;
|
|
6319
|
+
const fontSize = 13;
|
|
6320
|
+
const textY = pos.y + Math.round(tabHeight / 2) + Math.round(fontSize * 0.4);
|
|
6321
|
+
const iconsStr = String(node.props.icons || "");
|
|
6322
|
+
const iconList = iconsStr ? iconsStr.split(",").map((s) => s.trim()) : [];
|
|
6323
|
+
const isFlat = this.parseBooleanProp(node.props.flat, false);
|
|
6324
|
+
const showBorder = this.parseBooleanProp(node.props.border, true);
|
|
5891
6325
|
const tabWidth = pos.width / tabs.length;
|
|
5892
|
-
|
|
5893
|
-
|
|
6326
|
+
const colorPropStr = String(node.props.color ?? "");
|
|
6327
|
+
let textColorOverride = null;
|
|
6328
|
+
if (colorPropStr && colorPropStr !== "false") {
|
|
6329
|
+
if (colorPropStr.startsWith("#") || colorPropStr.startsWith("rgb")) {
|
|
6330
|
+
textColorOverride = colorPropStr;
|
|
6331
|
+
} else if (this.colorResolver.hasColor(colorPropStr)) {
|
|
6332
|
+
textColorOverride = this.colorResolver.resolveColor(colorPropStr, this.renderTheme.text);
|
|
6333
|
+
}
|
|
6334
|
+
}
|
|
6335
|
+
const activeTextColor = textColorOverride ?? (isFlat ? accentColor : "white");
|
|
6336
|
+
const inactiveTextColor = textColorOverride ? this.hexToRgba(textColorOverride, 0.55) : this.renderTheme.textMuted;
|
|
6337
|
+
const hasRadius = tabRadius > 0;
|
|
6338
|
+
const clipId = hasRadius ? `tc${String(node.meta?.nodeId ?? "").replace(/\W/g, "").slice(0, 12) || `${Math.round(Math.abs(pos.x))}x${Math.round(Math.abs(pos.y))}`}` : "";
|
|
6339
|
+
let svg = "";
|
|
6340
|
+
if (hasRadius) {
|
|
6341
|
+
svg += `<defs><clipPath id="${clipId}"><rect x="${pos.x}" y="${pos.y}" width="${pos.width}" height="${pos.height}" rx="${tabRadius}"/></clipPath></defs>`;
|
|
6342
|
+
}
|
|
6343
|
+
svg += `<g${this.getDataNodeId(node)}>`;
|
|
6344
|
+
if (hasRadius) {
|
|
6345
|
+
svg += `<g clip-path="url(#${clipId})">`;
|
|
6346
|
+
}
|
|
6347
|
+
if (!isFlat) {
|
|
6348
|
+
svg += `
|
|
6349
|
+
<rect x="${pos.x}" y="${pos.y}" width="${pos.width}" height="${tabHeight}"
|
|
6350
|
+
fill="${this.renderTheme.bg}"/>`;
|
|
6351
|
+
}
|
|
5894
6352
|
tabs.forEach((tab, i) => {
|
|
5895
6353
|
const tabX = pos.x + i * tabWidth;
|
|
5896
6354
|
const isActive = i === activeIndex;
|
|
5897
|
-
|
|
5898
|
-
|
|
5899
|
-
|
|
5900
|
-
|
|
5901
|
-
|
|
5902
|
-
|
|
5903
|
-
|
|
5904
|
-
|
|
5905
|
-
|
|
5906
|
-
|
|
5907
|
-
|
|
6355
|
+
const iconName = iconList[i] || "";
|
|
6356
|
+
const tabIconSvg = iconName ? getIcon(iconName) : null;
|
|
6357
|
+
const iconSize = 14;
|
|
6358
|
+
const iconGap = 4;
|
|
6359
|
+
const charW = fontSize * 0.58;
|
|
6360
|
+
const textEst = tab.length * charW;
|
|
6361
|
+
const totalW = tabIconSvg ? iconSize + iconGap + textEst : textEst;
|
|
6362
|
+
const groupX = tabX + Math.round((tabWidth - totalW) / 2);
|
|
6363
|
+
const iconOffY = pos.y + Math.round((tabHeight - iconSize) / 2);
|
|
6364
|
+
if (isFlat) {
|
|
6365
|
+
if (isActive) {
|
|
6366
|
+
svg += `
|
|
6367
|
+
<rect x="${tabX + 6}" y="${pos.y + tabHeight - 3}"
|
|
6368
|
+
width="${tabWidth - 12}" height="3"
|
|
6369
|
+
rx="1.5"
|
|
6370
|
+
fill="${accentColor}"/>`;
|
|
6371
|
+
}
|
|
6372
|
+
if (tabIconSvg) {
|
|
6373
|
+
svg += `
|
|
6374
|
+
<g transform="translate(${groupX}, ${iconOffY})">
|
|
6375
|
+
<svg width="${iconSize}" height="${iconSize}" viewBox="0 0 24 24" fill="none"
|
|
6376
|
+
stroke="${isActive ? accentColor : this.renderTheme.textMuted}"
|
|
6377
|
+
stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
|
|
6378
|
+
${this.extractSvgContent(tabIconSvg)}
|
|
6379
|
+
</svg>
|
|
6380
|
+
</g>
|
|
6381
|
+
<text x="${groupX + iconSize + iconGap}" y="${textY}"
|
|
6382
|
+
font-family="Arial, Helvetica, sans-serif"
|
|
6383
|
+
font-size="${fontSize}"
|
|
6384
|
+
font-weight="${isActive ? "600" : "500"}"
|
|
6385
|
+
fill="${isActive ? activeTextColor : inactiveTextColor}">${this.escapeXml(tab)}</text>`;
|
|
6386
|
+
} else {
|
|
6387
|
+
svg += `
|
|
6388
|
+
<text x="${tabX + tabWidth / 2}" y="${textY}"
|
|
6389
|
+
font-family="Arial, Helvetica, sans-serif"
|
|
6390
|
+
font-size="${fontSize}"
|
|
6391
|
+
font-weight="${isActive ? "600" : "500"}"
|
|
6392
|
+
fill="${isActive ? activeTextColor : inactiveTextColor}"
|
|
6393
|
+
text-anchor="middle">${this.escapeXml(tab)}</text>`;
|
|
6394
|
+
}
|
|
6395
|
+
} else {
|
|
6396
|
+
svg += `
|
|
6397
|
+
<rect x="${tabX}" y="${pos.y}"
|
|
6398
|
+
width="${tabWidth}" height="${tabHeight}"
|
|
6399
|
+
rx="${!showBorder && hasRadius && isActive ? tabRadius : 0}"
|
|
6400
|
+
fill="${isActive ? accentColor : "transparent"}"
|
|
6401
|
+
${!isActive && showBorder ? `stroke="${this.renderTheme.border}" stroke-width="0.5"` : ""}/>`;
|
|
6402
|
+
if (tabIconSvg) {
|
|
6403
|
+
svg += `
|
|
6404
|
+
<g transform="translate(${groupX}, ${iconOffY})">
|
|
6405
|
+
<svg width="${iconSize}" height="${iconSize}" viewBox="0 0 24 24" fill="none"
|
|
6406
|
+
stroke="${isActive ? activeTextColor : this.renderTheme.textMuted}"
|
|
6407
|
+
stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
|
|
6408
|
+
${this.extractSvgContent(tabIconSvg)}
|
|
6409
|
+
</svg>
|
|
6410
|
+
</g>
|
|
6411
|
+
<text x="${groupX + iconSize + iconGap}" y="${textY}"
|
|
6412
|
+
font-family="Arial, Helvetica, sans-serif"
|
|
6413
|
+
font-size="${fontSize}"
|
|
6414
|
+
font-weight="${isActive ? "600" : "500"}"
|
|
6415
|
+
fill="${isActive ? activeTextColor : this.renderTheme.text}">${this.escapeXml(tab)}</text>`;
|
|
6416
|
+
} else {
|
|
6417
|
+
svg += `
|
|
6418
|
+
<text x="${tabX + tabWidth / 2}" y="${textY}"
|
|
6419
|
+
font-family="Arial, Helvetica, sans-serif"
|
|
6420
|
+
font-size="${fontSize}"
|
|
6421
|
+
font-weight="${isActive ? "600" : "500"}"
|
|
6422
|
+
fill="${isActive ? activeTextColor : this.renderTheme.text}"
|
|
5908
6423
|
text-anchor="middle">${this.escapeXml(tab)}</text>`;
|
|
6424
|
+
}
|
|
6425
|
+
}
|
|
5909
6426
|
});
|
|
5910
|
-
|
|
6427
|
+
const contentY = pos.y + tabHeight;
|
|
6428
|
+
const contentH = pos.height - tabHeight;
|
|
6429
|
+
if (contentH >= 20 && !isFlat) {
|
|
6430
|
+
svg += `
|
|
5911
6431
|
<!-- Tab content area -->
|
|
5912
|
-
<rect x="${pos.x}" y="${
|
|
5913
|
-
width="${pos.width}" height="${
|
|
5914
|
-
fill="${this.renderTheme.cardBg}"
|
|
5915
|
-
stroke="${this.renderTheme.border}"
|
|
5916
|
-
|
|
6432
|
+
<rect x="${pos.x}" y="${contentY}"
|
|
6433
|
+
width="${pos.width}" height="${contentH}"
|
|
6434
|
+
fill="${this.renderTheme.cardBg}"
|
|
6435
|
+
${showBorder ? `stroke="${this.renderTheme.border}" stroke-width="1"` : ""}/>`;
|
|
6436
|
+
} else if (isFlat && showBorder) {
|
|
6437
|
+
svg += `
|
|
6438
|
+
<line x1="${pos.x}" y1="${contentY}" x2="${pos.x + pos.width}" y2="${contentY}"
|
|
6439
|
+
stroke="${this.renderTheme.border}" stroke-width="1"/>`;
|
|
6440
|
+
}
|
|
6441
|
+
if (hasRadius) {
|
|
6442
|
+
svg += `
|
|
5917
6443
|
</g>`;
|
|
6444
|
+
if (!isFlat && showBorder) {
|
|
6445
|
+
svg += `
|
|
6446
|
+
<rect x="${pos.x}" y="${pos.y}" width="${pos.width}" height="${pos.height}"
|
|
6447
|
+
rx="${tabRadius}" fill="none"
|
|
6448
|
+
stroke="${this.renderTheme.border}" stroke-width="1"/>`;
|
|
6449
|
+
}
|
|
6450
|
+
}
|
|
6451
|
+
svg += "\n </g>";
|
|
5918
6452
|
return svg;
|
|
5919
6453
|
}
|
|
5920
6454
|
renderDivider(node, pos) {
|
|
@@ -5981,15 +6515,20 @@ var SVGRenderer = class {
|
|
|
5981
6515
|
const hasExplicitVariantColor = semanticBase !== void 0 || this.colorResolver.hasColor(variant);
|
|
5982
6516
|
const bgColor = hasExplicitVariantColor ? this.resolveVariantColor(variant, this.renderTheme.primary) : this.renderTheme.border;
|
|
5983
6517
|
const textColor = hasExplicitVariantColor ? "white" : this.renderTheme.text;
|
|
6518
|
+
const size = String(node.props.size || "md");
|
|
6519
|
+
const BADGE_FONT_SIZES = { xs: 9, sm: 11, md: 12, lg: 13, xl: 15 };
|
|
6520
|
+
const fontSize = BADGE_FONT_SIZES[size] ?? this.tokens.badge.fontSize;
|
|
6521
|
+
const customPadding = node.props.padding !== void 0 ? Number(node.props.padding) : void 0;
|
|
6522
|
+
const BADGE_PAD_X = { xs: 5, sm: 6, md: 8, lg: 10, xl: 14 };
|
|
6523
|
+
const paddingX = customPadding !== void 0 && !isNaN(customPadding) ? customPadding : BADGE_PAD_X[size] ?? this.tokens.badge.paddingX;
|
|
5984
6524
|
const badgeRadius = this.tokens.badge.radius === "pill" ? pos.height / 2 : this.tokens.badge.radius;
|
|
5985
|
-
const fontSize = this.tokens.badge.fontSize;
|
|
5986
6525
|
return `<g${this.getDataNodeId(node)}>
|
|
5987
6526
|
<rect x="${pos.x}" y="${pos.y}"
|
|
5988
6527
|
width="${pos.width}" height="${pos.height}"
|
|
5989
6528
|
rx="${badgeRadius}"
|
|
5990
6529
|
fill="${bgColor}"
|
|
5991
6530
|
stroke="none"/>
|
|
5992
|
-
<text x="${pos.x + pos.width / 2}" y="${pos.y + pos.height / 2 +
|
|
6531
|
+
<text x="${pos.x + paddingX + (pos.width - paddingX * 2) / 2}" y="${pos.y + pos.height / 2 + fontSize * 0.35}"
|
|
5993
6532
|
font-family="Arial, Helvetica, sans-serif"
|
|
5994
6533
|
font-size="${fontSize}"
|
|
5995
6534
|
font-weight="600"
|
|
@@ -6198,11 +6737,20 @@ var SVGRenderer = class {
|
|
|
6198
6737
|
return svg;
|
|
6199
6738
|
}
|
|
6200
6739
|
renderImage(node, pos) {
|
|
6201
|
-
const placeholder = String(node.props.
|
|
6740
|
+
const placeholder = String(node.props.type || "landscape").toLowerCase();
|
|
6202
6741
|
const placeholderIcon = String(node.props.icon || "").trim();
|
|
6203
6742
|
const variant = String(node.props.variant || "").trim();
|
|
6204
6743
|
const placeholderIconSvg = placeholder === "icon" && placeholderIcon ? getIcon(placeholderIcon) : null;
|
|
6205
6744
|
const imageBg = this.options.theme === "dark" ? "#2A2A2A" : "#E8E8E8";
|
|
6745
|
+
const hasExplicitHeight = node.props.height !== void 0 && !isNaN(Number(node.props.height)) && Number(node.props.height) > 0;
|
|
6746
|
+
const isCircle = this.parseBooleanProp(node.props.circle, false);
|
|
6747
|
+
const useClip = isCircle || hasExplicitHeight;
|
|
6748
|
+
const clipId = useClip ? `iclip${String(node.meta?.nodeId ?? "").replace(/\W/g, "").slice(0, 16) || `${Math.round(Math.abs(pos.x))}x${Math.round(Math.abs(pos.y))}`}` : "";
|
|
6749
|
+
const imgCx = pos.x + pos.width / 2;
|
|
6750
|
+
const imgCy = pos.y + pos.height / 2;
|
|
6751
|
+
const imgR = Math.min(pos.width, pos.height) / 2;
|
|
6752
|
+
const defsHtml = useClip ? `<defs><clipPath id="${clipId}">${isCircle ? `<circle cx="${imgCx}" cy="${imgCy}" r="${imgR}"/>` : `<rect x="${pos.x}" y="${pos.y}" width="${pos.width}" height="${pos.height}" rx="4"/>`}</clipPath></defs>` : "";
|
|
6753
|
+
const clipAttr = useClip ? ` clip-path="url(#${clipId})"` : "";
|
|
6206
6754
|
const aspectRatios = {
|
|
6207
6755
|
landscape: 16 / 9,
|
|
6208
6756
|
portrait: 2 / 3,
|
|
@@ -6211,12 +6759,24 @@ var SVGRenderer = class {
|
|
|
6211
6759
|
avatar: 1
|
|
6212
6760
|
};
|
|
6213
6761
|
const ratio = aspectRatios[placeholder] || 16 / 9;
|
|
6214
|
-
|
|
6215
|
-
let
|
|
6216
|
-
|
|
6217
|
-
|
|
6218
|
-
|
|
6219
|
-
|
|
6762
|
+
let iconWidth;
|
|
6763
|
+
let iconHeight;
|
|
6764
|
+
if (isCircle) {
|
|
6765
|
+
const diameter = 2 * imgR;
|
|
6766
|
+
iconWidth = diameter;
|
|
6767
|
+
iconHeight = diameter / ratio;
|
|
6768
|
+
if (iconHeight < diameter) {
|
|
6769
|
+
iconHeight = diameter;
|
|
6770
|
+
iconWidth = diameter * ratio;
|
|
6771
|
+
}
|
|
6772
|
+
} else {
|
|
6773
|
+
const maxSize = Math.min(pos.width, pos.height) * 0.8;
|
|
6774
|
+
iconWidth = maxSize;
|
|
6775
|
+
iconHeight = maxSize / ratio;
|
|
6776
|
+
if (iconHeight > pos.height * 0.8) {
|
|
6777
|
+
iconHeight = pos.height * 0.8;
|
|
6778
|
+
iconWidth = iconHeight * ratio;
|
|
6779
|
+
}
|
|
6220
6780
|
}
|
|
6221
6781
|
const offsetX = pos.x + (pos.width - iconWidth) / 2;
|
|
6222
6782
|
const offsetY = pos.y + (pos.height - iconHeight) / 2;
|
|
@@ -6229,17 +6789,18 @@ var SVGRenderer = class {
|
|
|
6229
6789
|
const iconSize = Math.max(16, Math.min(pos.width, pos.height) * 0.6);
|
|
6230
6790
|
const iconOffsetX = pos.x + (pos.width - iconSize) / 2;
|
|
6231
6791
|
const iconOffsetY = pos.y + (pos.height - iconSize) / 2;
|
|
6232
|
-
|
|
6792
|
+
const iconBorderShape = isCircle ? `<circle cx="${imgCx}" cy="${imgCy}" r="${imgR}" fill="none" stroke="${this.renderTheme.border}" stroke-width="1"/>` : `<rect x="${pos.x}" y="${pos.y}" width="${pos.width}" height="${pos.height}" fill="none" stroke="${this.renderTheme.border}" stroke-width="1" rx="4"/>`;
|
|
6793
|
+
return `${defsHtml}<g${this.getDataNodeId(node)}${clipAttr}>
|
|
6233
6794
|
<rect x="${pos.x}" y="${pos.y}" width="${pos.width}" height="${pos.height}" fill="${bgColor}" rx="4"/>
|
|
6234
6795
|
<g transform="translate(${iconOffsetX}, ${iconOffsetY})">
|
|
6235
6796
|
<svg width="${iconSize}" height="${iconSize}" viewBox="0 0 24 24" fill="none" stroke="${iconColor}" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
|
|
6236
6797
|
${this.extractSvgContent(placeholderIconSvg)}
|
|
6237
6798
|
</svg>
|
|
6238
6799
|
</g>
|
|
6239
|
-
|
|
6800
|
+
${iconBorderShape}
|
|
6240
6801
|
</g>`;
|
|
6241
6802
|
}
|
|
6242
|
-
let svg =
|
|
6803
|
+
let svg = `${defsHtml}<g${this.getDataNodeId(node)}${clipAttr}>
|
|
6243
6804
|
<!-- Image Background -->
|
|
6244
6805
|
<rect x="${pos.x}" y="${pos.y}" width="${pos.width}" height="${pos.height}" fill="${imageBg}"/>`;
|
|
6245
6806
|
if (["landscape", "portrait", "square"].includes(placeholder)) {
|
|
@@ -6297,10 +6858,10 @@ var SVGRenderer = class {
|
|
|
6297
6858
|
width="${personWidth * 0.6}" height="${personHeight * 0.5}"
|
|
6298
6859
|
fill="#666" rx="3"/>`;
|
|
6299
6860
|
}
|
|
6861
|
+
const borderShape = isCircle ? `<circle cx="${imgCx}" cy="${imgCy}" r="${imgR}" fill="none" stroke="${this.renderTheme.border}" stroke-width="1"/>` : `<rect x="${pos.x}" y="${pos.y}" width="${pos.width}" height="${pos.height}" fill="none" stroke="${this.renderTheme.border}" stroke-width="1" rx="4"/>`;
|
|
6300
6862
|
svg += `
|
|
6301
6863
|
<!-- Border -->
|
|
6302
|
-
|
|
6303
|
-
fill="none" stroke="${this.renderTheme.border}" stroke-width="1" rx="4"/>
|
|
6864
|
+
${borderShape}
|
|
6304
6865
|
</g>`;
|
|
6305
6866
|
return svg;
|
|
6306
6867
|
}
|
|
@@ -6404,10 +6965,29 @@ var SVGRenderer = class {
|
|
|
6404
6965
|
</g>`;
|
|
6405
6966
|
}
|
|
6406
6967
|
const iconSize = this.getIconSize(size);
|
|
6407
|
-
const
|
|
6408
|
-
const
|
|
6968
|
+
const paddingPx = Math.max(0, Number(node.props.padding || 0));
|
|
6969
|
+
const renderedIconSize = Math.max(4, iconSize - paddingPx * 2);
|
|
6970
|
+
const offsetX = pos.x + (pos.width - renderedIconSize) / 2;
|
|
6971
|
+
const offsetY = pos.y + (pos.height - renderedIconSize) / 2;
|
|
6972
|
+
const isIconCircle = this.parseBooleanProp(node.props.circle, false);
|
|
6973
|
+
if (isIconCircle) {
|
|
6974
|
+
const cx = pos.x + pos.width / 2;
|
|
6975
|
+
const cy = pos.y + pos.height / 2;
|
|
6976
|
+
const r = Math.min(pos.width, pos.height) / 2;
|
|
6977
|
+
const iconClipId = `iconclip${String(node.meta?.nodeId ?? "").replace(/\W/g, "").slice(0, 16) || `${Math.round(Math.abs(pos.x))}x${Math.round(Math.abs(pos.y))}`}`;
|
|
6978
|
+
const bgColor = this.hexToRgba(iconColor, 0.12);
|
|
6979
|
+
return `<defs><clipPath id="${iconClipId}"><circle cx="${cx}" cy="${cy}" r="${r}"/></clipPath></defs><g${this.getDataNodeId(node)} clip-path="url(#${iconClipId})">
|
|
6980
|
+
<circle cx="${cx}" cy="${cy}" r="${r}" fill="${bgColor}"/>
|
|
6981
|
+
<g transform="translate(${offsetX}, ${offsetY})">
|
|
6982
|
+
<svg width="${renderedIconSize}" height="${renderedIconSize}" viewBox="0 0 24 24" fill="none" stroke="${iconColor}" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
|
|
6983
|
+
${this.extractSvgContent(iconSvg)}
|
|
6984
|
+
</svg>
|
|
6985
|
+
</g>
|
|
6986
|
+
</g>
|
|
6987
|
+
<circle cx="${cx}" cy="${cy}" r="${r}" fill="none" stroke="${this.hexToRgba(iconColor, 0.35)}" stroke-width="1"/>`;
|
|
6988
|
+
}
|
|
6409
6989
|
const wrappedSvg = `<g${this.getDataNodeId(node)} transform="translate(${offsetX}, ${offsetY})">
|
|
6410
|
-
<svg width="${
|
|
6990
|
+
<svg width="${renderedIconSize}" height="${renderedIconSize}" viewBox="0 0 24 24" fill="none" stroke="${iconColor}" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
|
|
6411
6991
|
${this.extractSvgContent(iconSvg)}
|
|
6412
6992
|
</svg>
|
|
6413
6993
|
</g>`;
|
|
@@ -6416,7 +6996,7 @@ var SVGRenderer = class {
|
|
|
6416
6996
|
renderIconButton(node, pos) {
|
|
6417
6997
|
const iconName = String(node.props.icon || "help-circle");
|
|
6418
6998
|
const variant = String(node.props.variant || "default");
|
|
6419
|
-
const size = String(node.props.size || "
|
|
6999
|
+
const size = String(node.props.size || "sm");
|
|
6420
7000
|
const disabled = String(node.props.disabled || "false") === "true";
|
|
6421
7001
|
const density = this.ir.project.style.density || "normal";
|
|
6422
7002
|
const labelOffset = this.parseBooleanProp(node.props.labelSpace, false) ? 18 : 0;
|
|
@@ -6544,7 +7124,7 @@ var SVGRenderer = class {
|
|
|
6544
7124
|
wrapTextToLines(text, maxWidth, fontSize) {
|
|
6545
7125
|
const normalized = text.replace(/\r\n/g, "\n");
|
|
6546
7126
|
const paragraphs = normalized.split("\n");
|
|
6547
|
-
const charWidth = fontSize * 0.
|
|
7127
|
+
const charWidth = fontSize * 0.5;
|
|
6548
7128
|
const safeWidth = Math.max(maxWidth || 0, charWidth);
|
|
6549
7129
|
const maxCharsPerLine = Math.max(1, Math.floor(safeWidth / charWidth));
|
|
6550
7130
|
const lines = [];
|
|
@@ -7659,7 +8239,7 @@ var SketchSVGRenderer = class extends SVGRenderer {
|
|
|
7659
8239
|
renderButton(node, pos) {
|
|
7660
8240
|
const text = String(node.props.text || "Button");
|
|
7661
8241
|
const variant = String(node.props.variant || "default");
|
|
7662
|
-
const size = String(node.props.size || "
|
|
8242
|
+
const size = String(node.props.size || "sm");
|
|
7663
8243
|
const density = this.ir.project.style.density || "normal";
|
|
7664
8244
|
const extraPadding = resolveControlHorizontalPadding(String(node.props.padding || "none"), density);
|
|
7665
8245
|
const labelOffset = this.parseBooleanProp(node.props.labelSpace, false) ? 18 : 0;
|
|
@@ -7766,7 +8346,7 @@ var SketchSVGRenderer = class extends SVGRenderer {
|
|
|
7766
8346
|
renderIconButton(node, pos) {
|
|
7767
8347
|
const iconName = String(node.props.icon || "help-circle");
|
|
7768
8348
|
const variant = String(node.props.variant || "default");
|
|
7769
|
-
const size = String(node.props.size || "
|
|
8349
|
+
const size = String(node.props.size || "sm");
|
|
7770
8350
|
const density = this.ir.project.style.density || "normal";
|
|
7771
8351
|
const labelOffset = this.parseBooleanProp(node.props.labelSpace, false) ? 18 : 0;
|
|
7772
8352
|
const extraPadding = resolveControlHorizontalPadding(String(node.props.padding || "none"), density);
|
|
@@ -8019,26 +8599,58 @@ var SketchSVGRenderer = class extends SVGRenderer {
|
|
|
8019
8599
|
const variant = String(node.props.variant || "default");
|
|
8020
8600
|
const accentColor = variant === "default" ? this.resolveAccentColor() : this.resolveVariantColor(variant, this.resolveAccentColor());
|
|
8021
8601
|
const topbar = this.calculateTopbarLayout(node, pos, title, subtitle, actions, user);
|
|
8022
|
-
|
|
8602
|
+
const bgPropStr = String(node.props.background ?? "");
|
|
8603
|
+
let sketchTopbarBg = this.renderTheme.cardBg;
|
|
8604
|
+
if (bgPropStr && bgPropStr !== "false" && bgPropStr !== "true") {
|
|
8605
|
+
if (bgPropStr.startsWith("#") || bgPropStr.startsWith("rgb")) {
|
|
8606
|
+
sketchTopbarBg = bgPropStr;
|
|
8607
|
+
} else if (this.colorResolver.hasColor(bgPropStr)) {
|
|
8608
|
+
sketchTopbarBg = this.colorResolver.resolveColor(bgPropStr, this.renderTheme.cardBg);
|
|
8609
|
+
}
|
|
8610
|
+
}
|
|
8611
|
+
const colorPropStr = String(node.props.color ?? "");
|
|
8612
|
+
let titleColor = this.renderTheme.text;
|
|
8613
|
+
let subtitleColor = this.renderTheme.textMuted;
|
|
8614
|
+
if (colorPropStr && colorPropStr !== "false") {
|
|
8615
|
+
let resolvedTitleColor = null;
|
|
8616
|
+
if (colorPropStr.startsWith("#") || colorPropStr.startsWith("rgb")) {
|
|
8617
|
+
resolvedTitleColor = colorPropStr;
|
|
8618
|
+
} else if (this.colorResolver.hasColor(colorPropStr)) {
|
|
8619
|
+
resolvedTitleColor = this.colorResolver.resolveColor(colorPropStr, this.renderTheme.text);
|
|
8620
|
+
}
|
|
8621
|
+
if (resolvedTitleColor) {
|
|
8622
|
+
titleColor = resolvedTitleColor;
|
|
8623
|
+
subtitleColor = this.hexToRgba(resolvedTitleColor, 0.65);
|
|
8624
|
+
}
|
|
8625
|
+
}
|
|
8626
|
+
const showBorder = this.parseBooleanProp(node.props.border, false);
|
|
8627
|
+
const hasBgProp = bgPropStr === "true" || bgPropStr && bgPropStr !== "false" && bgPropStr !== "";
|
|
8628
|
+
const showBackground = hasBgProp;
|
|
8629
|
+
let svg = `<g${this.getDataNodeId(node)}>`;
|
|
8630
|
+
if (showBorder || showBackground) {
|
|
8631
|
+
const stroke = showBorder ? "#2D3748" : "none";
|
|
8632
|
+
svg += `
|
|
8023
8633
|
<rect x="${pos.x}" y="${pos.y}"
|
|
8024
8634
|
width="${pos.width}" height="${pos.height}"
|
|
8025
|
-
fill="${
|
|
8026
|
-
stroke="
|
|
8635
|
+
fill="${sketchTopbarBg}"
|
|
8636
|
+
stroke="${stroke}"
|
|
8027
8637
|
stroke-width="0.5"
|
|
8028
|
-
filter="url(#sketch-rough)"
|
|
8029
|
-
|
|
8030
|
-
|
|
8638
|
+
filter="url(#sketch-rough)"/>`;
|
|
8639
|
+
}
|
|
8640
|
+
svg += `
|
|
8641
|
+
<!-- Title -->`;
|
|
8642
|
+
svg += `
|
|
8031
8643
|
<text x="${topbar.textX}" y="${topbar.titleY}"
|
|
8032
8644
|
font-family="${this.fontFamily}"
|
|
8033
8645
|
font-size="18"
|
|
8034
8646
|
font-weight="600"
|
|
8035
|
-
fill="${
|
|
8647
|
+
fill="${titleColor}">${this.escapeXml(topbar.visibleTitle)}</text>`;
|
|
8036
8648
|
if (topbar.hasSubtitle) {
|
|
8037
8649
|
svg += `
|
|
8038
8650
|
<text x="${topbar.textX}" y="${topbar.subtitleY}"
|
|
8039
8651
|
font-family="${this.fontFamily}"
|
|
8040
8652
|
font-size="13"
|
|
8041
|
-
fill="${
|
|
8653
|
+
fill="${subtitleColor}">${this.escapeXml(topbar.visibleSubtitle)}</text>`;
|
|
8042
8654
|
}
|
|
8043
8655
|
if (topbar.leftIcon) {
|
|
8044
8656
|
svg += `
|
|
@@ -8118,8 +8730,13 @@ var SketchSVGRenderer = class extends SVGRenderer {
|
|
|
8118
8730
|
*/
|
|
8119
8731
|
renderText(node, pos) {
|
|
8120
8732
|
const text = String(node.props.text || "Text content");
|
|
8121
|
-
const
|
|
8733
|
+
const sizeProp = String(node.props.size || "");
|
|
8734
|
+
const defaultFontSize = this.tokens.text.fontSize;
|
|
8735
|
+
const textFontSizeMap = { xs: 10, sm: 12, lg: 16, xl: 20 };
|
|
8736
|
+
const fontSize = textFontSizeMap[sizeProp] ?? defaultFontSize;
|
|
8122
8737
|
const lineHeightPx = Math.ceil(fontSize * this.tokens.text.lineHeight);
|
|
8738
|
+
const bold = this.parseBooleanProp(node.props.bold, false);
|
|
8739
|
+
const italic = this.parseBooleanProp(node.props.italic, false);
|
|
8123
8740
|
const lines = this.wrapTextToLines(text, pos.width, fontSize);
|
|
8124
8741
|
const firstLineY = pos.y + fontSize;
|
|
8125
8742
|
const tspans = lines.map(
|
|
@@ -8129,9 +8746,48 @@ var SketchSVGRenderer = class extends SVGRenderer {
|
|
|
8129
8746
|
<text x="${pos.x}" y="${firstLineY}"
|
|
8130
8747
|
font-family="${this.fontFamily}"
|
|
8131
8748
|
font-size="${fontSize}"
|
|
8749
|
+
font-weight="${bold ? "700" : "400"}"
|
|
8750
|
+
font-style="${italic ? "italic" : "normal"}"
|
|
8132
8751
|
fill="${this.renderTheme.text}">${tspans}</text>
|
|
8133
8752
|
</g>`;
|
|
8134
8753
|
}
|
|
8754
|
+
renderParagraph(node, pos) {
|
|
8755
|
+
const text = String(node.props.text || "");
|
|
8756
|
+
const sizeProp = String(node.props.size || "");
|
|
8757
|
+
const defaultFontSize = this.tokens.text.fontSize;
|
|
8758
|
+
const textFontSizeMap = { xs: 10, sm: 12, lg: 16, xl: 20 };
|
|
8759
|
+
const fontSize = textFontSizeMap[sizeProp] ?? defaultFontSize;
|
|
8760
|
+
const lineHeightPx = Math.ceil(fontSize * this.tokens.text.lineHeight);
|
|
8761
|
+
const bold = this.parseBooleanProp(node.props.bold, false);
|
|
8762
|
+
const italic = this.parseBooleanProp(node.props.italic, false);
|
|
8763
|
+
const align = String(node.props.align || "left");
|
|
8764
|
+
const lines = this.wrapTextToLines(text, pos.width, fontSize);
|
|
8765
|
+
const firstLineY = pos.y + fontSize;
|
|
8766
|
+
let textX;
|
|
8767
|
+
let textAnchor;
|
|
8768
|
+
if (align === "center") {
|
|
8769
|
+
textX = pos.x + pos.width / 2;
|
|
8770
|
+
textAnchor = "middle";
|
|
8771
|
+
} else if (align === "right") {
|
|
8772
|
+
textX = pos.x + pos.width;
|
|
8773
|
+
textAnchor = "end";
|
|
8774
|
+
} else {
|
|
8775
|
+
textX = pos.x;
|
|
8776
|
+
textAnchor = "start";
|
|
8777
|
+
}
|
|
8778
|
+
const tspans = lines.map(
|
|
8779
|
+
(line, index) => `<tspan x="${textX}" dy="${index === 0 ? 0 : lineHeightPx}">${this.escapeXml(line)}</tspan>`
|
|
8780
|
+
).join("");
|
|
8781
|
+
return `<g${this.getDataNodeId(node)}>
|
|
8782
|
+
<text x="${textX}" y="${firstLineY}"
|
|
8783
|
+
font-family="${this.fontFamily}"
|
|
8784
|
+
font-size="${fontSize}"
|
|
8785
|
+
font-weight="${bold ? "700" : "400"}"
|
|
8786
|
+
font-style="${italic ? "italic" : "normal"}"
|
|
8787
|
+
fill="${this.renderTheme.text}"
|
|
8788
|
+
text-anchor="${textAnchor}">${tspans}</text>
|
|
8789
|
+
</g>`;
|
|
8790
|
+
}
|
|
8135
8791
|
/**
|
|
8136
8792
|
* Render label with Comic Sans
|
|
8137
8793
|
*/
|
|
@@ -8362,36 +9018,150 @@ var SketchSVGRenderer = class extends SVGRenderer {
|
|
|
8362
9018
|
renderTabs(node, pos) {
|
|
8363
9019
|
const itemsStr = String(node.props.items || "");
|
|
8364
9020
|
const tabs = itemsStr ? itemsStr.split(",").map((t) => t.trim()) : ["Tab 1", "Tab 2", "Tab 3"];
|
|
8365
|
-
const
|
|
9021
|
+
const activeProp = node.props.active ?? 0;
|
|
9022
|
+
const activeIndex = Number.isFinite(Number(activeProp)) ? Math.max(0, Math.floor(Number(activeProp))) : 0;
|
|
9023
|
+
const variant = String(node.props.variant || "default");
|
|
9024
|
+
const accentColor = variant === "default" ? this.resolveAccentColor() : this.resolveVariantColor(variant, this.resolveAccentColor());
|
|
9025
|
+
const radiusMap = { none: 0, sm: 4, md: 6, lg: 10, full: 20 };
|
|
9026
|
+
const tabRadius = radiusMap[String(node.props.radius || "md")] ?? 6;
|
|
9027
|
+
const sizeMap = { sm: 32, md: 44, lg: 52 };
|
|
9028
|
+
const tabHeight = pos.height > 0 ? pos.height : sizeMap[String(node.props.size || "md")] ?? 44;
|
|
9029
|
+
const fontSize = 13;
|
|
9030
|
+
const textY = pos.y + Math.round(tabHeight / 2) + Math.round(fontSize * 0.4);
|
|
9031
|
+
const iconsStr = String(node.props.icons || "");
|
|
9032
|
+
const iconList = iconsStr ? iconsStr.split(",").map((s) => s.trim()) : [];
|
|
9033
|
+
const isFlat = this.parseBooleanProp(node.props.flat, false);
|
|
9034
|
+
const showBorder = this.parseBooleanProp(node.props.border, true);
|
|
8366
9035
|
const tabWidth = pos.width / tabs.length;
|
|
8367
|
-
|
|
8368
|
-
|
|
9036
|
+
const colorPropStr = String(node.props.color ?? "");
|
|
9037
|
+
let textColorOverride = null;
|
|
9038
|
+
if (colorPropStr && colorPropStr !== "false") {
|
|
9039
|
+
if (colorPropStr.startsWith("#") || colorPropStr.startsWith("rgb")) {
|
|
9040
|
+
textColorOverride = colorPropStr;
|
|
9041
|
+
} else if (this.colorResolver.hasColor(colorPropStr)) {
|
|
9042
|
+
textColorOverride = this.colorResolver.resolveColor(colorPropStr, this.renderTheme.text);
|
|
9043
|
+
}
|
|
9044
|
+
}
|
|
9045
|
+
const activeTextColor = textColorOverride ?? (isFlat ? accentColor : "white");
|
|
9046
|
+
const inactiveTextColor = textColorOverride ? this.hexToRgba(textColorOverride, 0.55) : this.renderTheme.textMuted;
|
|
9047
|
+
const hasRadius = tabRadius > 0;
|
|
9048
|
+
const clipId = hasRadius ? `stc${String(node.meta?.nodeId ?? "").replace(/\W/g, "").slice(0, 12) || `${Math.round(Math.abs(pos.x))}x${Math.round(Math.abs(pos.y))}`}` : "";
|
|
9049
|
+
let svg = "";
|
|
9050
|
+
if (hasRadius) {
|
|
9051
|
+
svg += `<defs><clipPath id="${clipId}"><rect x="${pos.x}" y="${pos.y}" width="${pos.width}" height="${pos.height}" rx="${tabRadius}"/></clipPath></defs>`;
|
|
9052
|
+
}
|
|
9053
|
+
svg += `<g${this.getDataNodeId(node)}>`;
|
|
9054
|
+
if (hasRadius) {
|
|
9055
|
+
svg += `<g clip-path="url(#${clipId})">`;
|
|
9056
|
+
}
|
|
9057
|
+
if (!isFlat) {
|
|
9058
|
+
svg += `
|
|
9059
|
+
<rect x="${pos.x}" y="${pos.y}" width="${pos.width}" height="${tabHeight}"
|
|
9060
|
+
fill="${this.renderTheme.bg}"/>`;
|
|
9061
|
+
}
|
|
8369
9062
|
tabs.forEach((tab, i) => {
|
|
8370
9063
|
const tabX = pos.x + i * tabWidth;
|
|
8371
|
-
const isActive = i ===
|
|
8372
|
-
|
|
9064
|
+
const isActive = i === activeIndex;
|
|
9065
|
+
const iconName = iconList[i] || "";
|
|
9066
|
+
const tabIconSvg = iconName ? getIcon(iconName) : null;
|
|
9067
|
+
const iconSize = 14;
|
|
9068
|
+
const iconGap = 4;
|
|
9069
|
+
const charW = fontSize * 0.58;
|
|
9070
|
+
const textEst = tab.length * charW;
|
|
9071
|
+
const totalW = tabIconSvg ? iconSize + iconGap + textEst : textEst;
|
|
9072
|
+
const groupX = tabX + Math.round((tabWidth - totalW) / 2);
|
|
9073
|
+
const iconOffY = pos.y + Math.round((tabHeight - iconSize) / 2);
|
|
9074
|
+
if (isFlat) {
|
|
9075
|
+
if (isActive) {
|
|
9076
|
+
svg += `
|
|
9077
|
+
<rect x="${tabX + 6}" y="${pos.y + tabHeight - 3}"
|
|
9078
|
+
width="${tabWidth - 12}" height="3"
|
|
9079
|
+
rx="1.5"
|
|
9080
|
+
fill="${accentColor}"
|
|
9081
|
+
filter="url(#sketch-rough)"/>`;
|
|
9082
|
+
}
|
|
9083
|
+
if (tabIconSvg) {
|
|
9084
|
+
svg += `
|
|
9085
|
+
<g transform="translate(${groupX}, ${iconOffY})">
|
|
9086
|
+
<svg width="${iconSize}" height="${iconSize}" viewBox="0 0 24 24" fill="none"
|
|
9087
|
+
stroke="${isActive ? accentColor : this.renderTheme.textMuted}"
|
|
9088
|
+
stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round">
|
|
9089
|
+
${this.extractSvgContent(tabIconSvg)}
|
|
9090
|
+
</svg>
|
|
9091
|
+
</g>
|
|
9092
|
+
<text x="${groupX + iconSize + iconGap}" y="${textY}"
|
|
9093
|
+
font-family="${this.fontFamily}"
|
|
9094
|
+
font-size="${fontSize}"
|
|
9095
|
+
font-weight="${isActive ? "600" : "500"}"
|
|
9096
|
+
fill="${isActive ? activeTextColor : inactiveTextColor}">${this.escapeXml(tab)}</text>`;
|
|
9097
|
+
} else {
|
|
9098
|
+
svg += `
|
|
9099
|
+
<text x="${tabX + tabWidth / 2}" y="${textY}"
|
|
9100
|
+
font-family="${this.fontFamily}"
|
|
9101
|
+
font-size="${fontSize}"
|
|
9102
|
+
font-weight="${isActive ? "600" : "500"}"
|
|
9103
|
+
fill="${isActive ? activeTextColor : inactiveTextColor}"
|
|
9104
|
+
text-anchor="middle">${this.escapeXml(tab)}</text>`;
|
|
9105
|
+
}
|
|
9106
|
+
} else {
|
|
9107
|
+
svg += `
|
|
8373
9108
|
<rect x="${tabX}" y="${pos.y}"
|
|
8374
|
-
width="${tabWidth}" height="
|
|
9109
|
+
width="${tabWidth}" height="${tabHeight}"
|
|
9110
|
+
rx="${!showBorder && hasRadius && isActive ? tabRadius : 0}"
|
|
8375
9111
|
fill="${isActive ? accentColor : "transparent"}"
|
|
8376
|
-
stroke="${isActive ? accentColor : "#2D3748"}"
|
|
9112
|
+
stroke="${isActive ? accentColor : showBorder ? "#2D3748" : "none"}"
|
|
8377
9113
|
stroke-width="0.5"
|
|
8378
|
-
filter="url(#sketch-rough)"
|
|
8379
|
-
|
|
9114
|
+
filter="url(#sketch-rough)"/>`;
|
|
9115
|
+
if (tabIconSvg) {
|
|
9116
|
+
svg += `
|
|
9117
|
+
<g transform="translate(${groupX}, ${iconOffY})">
|
|
9118
|
+
<svg width="${iconSize}" height="${iconSize}" viewBox="0 0 24 24" fill="none"
|
|
9119
|
+
stroke="${isActive ? activeTextColor : this.renderTheme.textMuted}"
|
|
9120
|
+
stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round">
|
|
9121
|
+
${this.extractSvgContent(tabIconSvg)}
|
|
9122
|
+
</svg>
|
|
9123
|
+
</g>
|
|
9124
|
+
<text x="${groupX + iconSize + iconGap}" y="${textY}"
|
|
8380
9125
|
font-family="${this.fontFamily}"
|
|
8381
|
-
font-size="
|
|
9126
|
+
font-size="${fontSize}"
|
|
9127
|
+
font-weight="${isActive ? "600" : "500"}"
|
|
9128
|
+
fill="${isActive ? activeTextColor : this.renderTheme.text}">${this.escapeXml(tab)}</text>`;
|
|
9129
|
+
} else {
|
|
9130
|
+
svg += `
|
|
9131
|
+
<text x="${tabX + tabWidth / 2}" y="${textY}"
|
|
9132
|
+
font-family="${this.fontFamily}"
|
|
9133
|
+
font-size="${fontSize}"
|
|
8382
9134
|
font-weight="${isActive ? "600" : "500"}"
|
|
8383
|
-
fill="${isActive ?
|
|
9135
|
+
fill="${isActive ? activeTextColor : this.renderTheme.text}"
|
|
8384
9136
|
text-anchor="middle">${this.escapeXml(tab)}</text>`;
|
|
9137
|
+
}
|
|
9138
|
+
}
|
|
8385
9139
|
});
|
|
8386
|
-
|
|
9140
|
+
const contentY = pos.y + tabHeight;
|
|
9141
|
+
const contentH = pos.height - tabHeight;
|
|
9142
|
+
if (contentH >= 20 && !isFlat) {
|
|
9143
|
+
svg += `
|
|
8387
9144
|
<!-- Tab content area -->
|
|
8388
|
-
<rect x="${pos.x}" y="${
|
|
8389
|
-
width="${pos.width}" height="${
|
|
9145
|
+
<rect x="${pos.x}" y="${contentY}"
|
|
9146
|
+
width="${pos.width}" height="${contentH}"
|
|
8390
9147
|
fill="${this.renderTheme.cardBg}"
|
|
8391
|
-
stroke="#2D3748"
|
|
8392
|
-
|
|
8393
|
-
|
|
9148
|
+
${showBorder ? 'stroke="#2D3748" stroke-width="0.5" filter="url(#sketch-rough)"' : ""}/>`;
|
|
9149
|
+
} else if (isFlat && showBorder) {
|
|
9150
|
+
svg += `
|
|
9151
|
+
<line x1="${pos.x}" y1="${contentY}" x2="${pos.x + pos.width}" y2="${contentY}"
|
|
9152
|
+
stroke="#2D3748" stroke-width="0.5" filter="url(#sketch-rough)"/>`;
|
|
9153
|
+
}
|
|
9154
|
+
if (hasRadius) {
|
|
9155
|
+
svg += `
|
|
8394
9156
|
</g>`;
|
|
9157
|
+
if (!isFlat && showBorder) {
|
|
9158
|
+
svg += `
|
|
9159
|
+
<rect x="${pos.x}" y="${pos.y}" width="${pos.width}" height="${pos.height}"
|
|
9160
|
+
rx="${tabRadius}" fill="none" stroke="#2D3748" stroke-width="0.5"
|
|
9161
|
+
filter="url(#sketch-rough)"/>`;
|
|
9162
|
+
}
|
|
9163
|
+
}
|
|
9164
|
+
svg += "\n </g>";
|
|
8395
9165
|
return svg;
|
|
8396
9166
|
}
|
|
8397
9167
|
/**
|
|
@@ -8628,11 +9398,20 @@ var SketchSVGRenderer = class extends SVGRenderer {
|
|
|
8628
9398
|
* Render image with sketch filter
|
|
8629
9399
|
*/
|
|
8630
9400
|
renderImage(node, pos) {
|
|
8631
|
-
const placeholder = String(node.props.
|
|
9401
|
+
const placeholder = String(node.props.type || "landscape").toLowerCase();
|
|
8632
9402
|
const iconType = String(node.props.icon || "").trim();
|
|
8633
9403
|
const variant = String(node.props.variant || "").trim();
|
|
8634
9404
|
const iconSvg = placeholder === "icon" && iconType.length > 0 ? getIcon(iconType) : null;
|
|
8635
9405
|
const imageBg = this.options.theme === "dark" ? "#2A2A2A" : "#E8E8E8";
|
|
9406
|
+
const hasExplicitHeight = node.props.height !== void 0 && !isNaN(Number(node.props.height)) && Number(node.props.height) > 0;
|
|
9407
|
+
const isCircle = this.parseBooleanProp(node.props.circle, false);
|
|
9408
|
+
const useClip = isCircle || hasExplicitHeight;
|
|
9409
|
+
const clipId = useClip ? `sclip${String(node.meta?.nodeId ?? "").replace(/\W/g, "").slice(0, 16) || `${Math.round(Math.abs(pos.x))}x${Math.round(Math.abs(pos.y))}`}` : "";
|
|
9410
|
+
const imgCx = pos.x + pos.width / 2;
|
|
9411
|
+
const imgCy = pos.y + pos.height / 2;
|
|
9412
|
+
const imgR = Math.min(pos.width, pos.height) / 2;
|
|
9413
|
+
const defsHtml = useClip ? `<defs><clipPath id="${clipId}">${isCircle ? `<circle cx="${imgCx}" cy="${imgCy}" r="${imgR}"/>` : `<rect x="${pos.x}" y="${pos.y}" width="${pos.width}" height="${pos.height}" rx="4"/>`}</clipPath></defs>` : "";
|
|
9414
|
+
const clipAttr = useClip ? ` clip-path="url(#${clipId})"` : "";
|
|
8636
9415
|
if (iconSvg) {
|
|
8637
9416
|
const semanticBase = variant ? this.getSemanticVariantColor(variant) : void 0;
|
|
8638
9417
|
const hasVariant = variant.length > 0 && (semanticBase !== void 0 || this.colorResolver.hasColor(variant));
|
|
@@ -8642,7 +9421,8 @@ var SketchSVGRenderer = class extends SVGRenderer {
|
|
|
8642
9421
|
const iconSize = Math.max(16, Math.min(pos.width, pos.height) * 0.6);
|
|
8643
9422
|
const iconOffsetX = pos.x + (pos.width - iconSize) / 2;
|
|
8644
9423
|
const iconOffsetY = pos.y + (pos.height - iconSize) / 2;
|
|
8645
|
-
|
|
9424
|
+
const sketchIconBorder = isCircle ? `<circle cx="${imgCx}" cy="${imgCy}" r="${imgR}" fill="none" stroke="#2D3748" stroke-width="0.5" filter="url(#sketch-rough)"/>` : `<rect x="${pos.x}" y="${pos.y}" width="${pos.width}" height="${pos.height}" fill="none" stroke="#2D3748" stroke-width="0.5" rx="4" filter="url(#sketch-rough)"/>`;
|
|
9425
|
+
return `${defsHtml}<g${this.getDataNodeId(node)}${clipAttr}>
|
|
8646
9426
|
<rect x="${pos.x}" y="${pos.y}"
|
|
8647
9427
|
width="${pos.width}" height="${pos.height}"
|
|
8648
9428
|
fill="${bgColor}"
|
|
@@ -8653,17 +9433,11 @@ var SketchSVGRenderer = class extends SVGRenderer {
|
|
|
8653
9433
|
${this.extractSvgContent(iconSvg)}
|
|
8654
9434
|
</svg>
|
|
8655
9435
|
</g>
|
|
8656
|
-
|
|
8657
|
-
width="${pos.width}" height="${pos.height}"
|
|
8658
|
-
fill="none"
|
|
8659
|
-
stroke="#2D3748"
|
|
8660
|
-
stroke-width="0.5"
|
|
8661
|
-
rx="4"
|
|
8662
|
-
filter="url(#sketch-rough)"/>
|
|
9436
|
+
${sketchIconBorder}
|
|
8663
9437
|
</g>`;
|
|
8664
9438
|
}
|
|
8665
|
-
|
|
8666
|
-
|
|
9439
|
+
const sketchCircleBorder = isCircle ? `<circle cx="${imgCx}" cy="${imgCy}" r="${imgR}" fill="none" stroke="#2D3748" stroke-width="0.5"/>` : "";
|
|
9440
|
+
return `${defsHtml}<g${this.getDataNodeId(node)}${clipAttr}>
|
|
8667
9441
|
<rect x="${pos.x}" y="${pos.y}"
|
|
8668
9442
|
width="${pos.width}" height="${pos.height}"
|
|
8669
9443
|
fill="${imageBg}"
|
|
@@ -8671,14 +9445,12 @@ var SketchSVGRenderer = class extends SVGRenderer {
|
|
|
8671
9445
|
stroke-width="0.5"
|
|
8672
9446
|
rx="4"
|
|
8673
9447
|
filter="url(#sketch-rough)"/>
|
|
8674
|
-
|
|
8675
|
-
<!-- Placeholder icon -->
|
|
8676
9448
|
<text x="${pos.x + pos.width / 2}" y="${pos.y + pos.height / 2}"
|
|
8677
9449
|
font-family="${this.fontFamily}"
|
|
8678
9450
|
font-size="24"
|
|
8679
9451
|
fill="#666"
|
|
8680
9452
|
text-anchor="middle">\u{1F5BC}</text>
|
|
8681
|
-
</g
|
|
9453
|
+
</g>${sketchCircleBorder}`;
|
|
8682
9454
|
}
|
|
8683
9455
|
/**
|
|
8684
9456
|
* Render breadcrumbs with Comic Sans
|
|
@@ -8794,20 +9566,33 @@ var SketchSVGRenderer = class extends SVGRenderer {
|
|
|
8794
9566
|
}
|
|
8795
9567
|
const iconSize = this.getIconSize(size);
|
|
8796
9568
|
const iconColor = variant === "default" ? this.resolveTextColor() : this.resolveVariantColor(variant, this.resolveTextColor());
|
|
8797
|
-
const
|
|
8798
|
-
const
|
|
9569
|
+
const paddingPx = Math.max(0, Number(node.props.padding || 0));
|
|
9570
|
+
const renderedIconSize = Math.max(4, iconSize - paddingPx * 2);
|
|
9571
|
+
const offsetX = pos.x + (pos.width - renderedIconSize) / 2;
|
|
9572
|
+
const offsetY = pos.y + (pos.height - renderedIconSize) / 2;
|
|
9573
|
+
const isIconCircle = this.parseBooleanProp(node.props.circle, false);
|
|
9574
|
+
if (isIconCircle) {
|
|
9575
|
+
const cx = pos.x + pos.width / 2;
|
|
9576
|
+
const cy = pos.y + pos.height / 2;
|
|
9577
|
+
const r = Math.min(pos.width, pos.height) / 2;
|
|
9578
|
+
const iconClipId = `sconclip${String(node.meta?.nodeId ?? "").replace(/\W/g, "").slice(0, 16) || `${Math.round(Math.abs(pos.x))}x${Math.round(Math.abs(pos.y))}`}`;
|
|
9579
|
+
const bgColor = this.hexToRgba(iconColor, 0.1);
|
|
9580
|
+
return `<defs><clipPath id="${iconClipId}"><circle cx="${cx}" cy="${cy}" r="${r}"/></clipPath></defs><g${this.getDataNodeId(node)} clip-path="url(#${iconClipId})">
|
|
9581
|
+
<circle cx="${cx}" cy="${cy}" r="${r}" fill="${bgColor}"/>
|
|
9582
|
+
<g transform="translate(${offsetX}, ${offsetY})">
|
|
9583
|
+
<svg width="${renderedIconSize}" height="${renderedIconSize}" viewBox="0 0 24 24" fill="none" stroke="${iconColor}" stroke-width="0.5" stroke-linecap="round" stroke-linejoin="round">
|
|
9584
|
+
${this.extractSvgContent(iconSvg)}
|
|
9585
|
+
</svg>
|
|
9586
|
+
</g>
|
|
9587
|
+
</g>
|
|
9588
|
+
<circle cx="${cx}" cy="${cy}" r="${r}" fill="none" stroke="${this.hexToRgba(iconColor, 0.35)}" stroke-width="0.5"/>`;
|
|
9589
|
+
}
|
|
8799
9590
|
return `<g${this.getDataNodeId(node)} transform="translate(${offsetX}, ${offsetY})">
|
|
8800
|
-
<svg width="${
|
|
9591
|
+
<svg width="${renderedIconSize}" height="${renderedIconSize}" viewBox="0 0 24 24" fill="none" stroke="${iconColor}" stroke-width="0.5" stroke-linecap="round" stroke-linejoin="round">
|
|
8801
9592
|
${this.extractSvgContent(iconSvg)}
|
|
8802
9593
|
</svg>
|
|
8803
9594
|
</g>`;
|
|
8804
9595
|
}
|
|
8805
|
-
/**
|
|
8806
|
-
* Render chart placeholder with sketch filter and Comic Sans
|
|
8807
|
-
*/
|
|
8808
|
-
renderChartPlaceholder(node, pos) {
|
|
8809
|
-
return super.renderChartPlaceholder(node, pos);
|
|
8810
|
-
}
|
|
8811
9596
|
/**
|
|
8812
9597
|
* Helper method to get icon SVG
|
|
8813
9598
|
*/
|