@tightknitai/block-kitchen 0.8.6 → 0.8.8
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/helpers.d.cts +2 -2
- package/dist/helpers.d.ts +2 -2
- package/dist/index.cjs +650 -3
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +2 -2
- package/dist/index.d.ts +2 -2
- package/dist/index.js +651 -4
- package/dist/index.js.map +1 -1
- package/dist/{palette-DToUE_3J.d.cts → palette-5_Tx97Gk.d.cts} +117 -3
- package/dist/{palette-DToUE_3J.d.ts → palette-5_Tx97Gk.d.ts} +117 -3
- package/dist/palette.cjs +180 -0
- package/dist/palette.cjs.map +1 -1
- package/dist/palette.d.cts +1 -1
- package/dist/palette.d.ts +1 -1
- package/dist/palette.js +181 -1
- package/dist/palette.js.map +1 -1
- package/dist/styles.css +1 -1
- package/package.json +7 -5
package/dist/index.cjs
CHANGED
|
@@ -1014,6 +1014,186 @@ var defaultPalette = [
|
|
|
1014
1014
|
})
|
|
1015
1015
|
}
|
|
1016
1016
|
]
|
|
1017
|
+
},
|
|
1018
|
+
{
|
|
1019
|
+
name: "Data Visualization",
|
|
1020
|
+
icon: lucideReact.ChartColumnBig,
|
|
1021
|
+
variants: [
|
|
1022
|
+
{
|
|
1023
|
+
id: "dataviz_line",
|
|
1024
|
+
label: "Line chart",
|
|
1025
|
+
factory: () => ({
|
|
1026
|
+
type: "data_visualization",
|
|
1027
|
+
title: "Weekly active users by platform",
|
|
1028
|
+
chart: {
|
|
1029
|
+
type: "line",
|
|
1030
|
+
series: [
|
|
1031
|
+
{
|
|
1032
|
+
name: "Desktop",
|
|
1033
|
+
data: [
|
|
1034
|
+
{ label: "Mon", value: 800 },
|
|
1035
|
+
{ label: "Tue", value: 920 },
|
|
1036
|
+
{ label: "Wed", value: 880 },
|
|
1037
|
+
{ label: "Thu", value: 1010 },
|
|
1038
|
+
{ label: "Fri", value: 1120 }
|
|
1039
|
+
]
|
|
1040
|
+
},
|
|
1041
|
+
{
|
|
1042
|
+
name: "Mobile",
|
|
1043
|
+
data: [
|
|
1044
|
+
{ label: "Mon", value: 400 },
|
|
1045
|
+
{ label: "Tue", value: 530 },
|
|
1046
|
+
{ label: "Wed", value: 500 },
|
|
1047
|
+
{ label: "Thu", value: 590 },
|
|
1048
|
+
{ label: "Fri", value: 600 }
|
|
1049
|
+
]
|
|
1050
|
+
}
|
|
1051
|
+
],
|
|
1052
|
+
axis_config: {
|
|
1053
|
+
categories: ["Mon", "Tue", "Wed", "Thu", "Fri"],
|
|
1054
|
+
x_label: "Day",
|
|
1055
|
+
y_label: "Users"
|
|
1056
|
+
}
|
|
1057
|
+
}
|
|
1058
|
+
})
|
|
1059
|
+
},
|
|
1060
|
+
{
|
|
1061
|
+
id: "dataviz_bar",
|
|
1062
|
+
label: "Bar chart",
|
|
1063
|
+
factory: () => ({
|
|
1064
|
+
type: "data_visualization",
|
|
1065
|
+
title: "Messages sent by platform",
|
|
1066
|
+
chart: {
|
|
1067
|
+
type: "bar",
|
|
1068
|
+
series: [
|
|
1069
|
+
{
|
|
1070
|
+
name: "Desktop",
|
|
1071
|
+
data: [
|
|
1072
|
+
{ label: "Mon", value: 1500 },
|
|
1073
|
+
{ label: "Tue", value: 1400 },
|
|
1074
|
+
{ label: "Wed", value: 1700 },
|
|
1075
|
+
{ label: "Thu", value: 1600 },
|
|
1076
|
+
{ label: "Fri", value: 1280 }
|
|
1077
|
+
]
|
|
1078
|
+
},
|
|
1079
|
+
{
|
|
1080
|
+
name: "Mobile",
|
|
1081
|
+
data: [
|
|
1082
|
+
{ label: "Mon", value: 800 },
|
|
1083
|
+
{ label: "Tue", value: 750 },
|
|
1084
|
+
{ label: "Wed", value: 920 },
|
|
1085
|
+
{ label: "Thu", value: 880 },
|
|
1086
|
+
{ label: "Fri", value: 700 }
|
|
1087
|
+
]
|
|
1088
|
+
}
|
|
1089
|
+
],
|
|
1090
|
+
axis_config: {
|
|
1091
|
+
categories: ["Mon", "Tue", "Wed", "Thu", "Fri"],
|
|
1092
|
+
x_label: "Day",
|
|
1093
|
+
y_label: "Messages"
|
|
1094
|
+
}
|
|
1095
|
+
}
|
|
1096
|
+
})
|
|
1097
|
+
},
|
|
1098
|
+
{
|
|
1099
|
+
id: "dataviz_area",
|
|
1100
|
+
label: "Area chart",
|
|
1101
|
+
factory: () => ({
|
|
1102
|
+
type: "data_visualization",
|
|
1103
|
+
title: "Concurrent users by platform",
|
|
1104
|
+
chart: {
|
|
1105
|
+
type: "area",
|
|
1106
|
+
series: [
|
|
1107
|
+
{
|
|
1108
|
+
name: "Desktop",
|
|
1109
|
+
data: [
|
|
1110
|
+
{ label: "Mon", value: 2800 },
|
|
1111
|
+
{ label: "Tue", value: 3e3 },
|
|
1112
|
+
{ label: "Wed", value: 3400 },
|
|
1113
|
+
{ label: "Thu", value: 3200 },
|
|
1114
|
+
{ label: "Fri", value: 3500 }
|
|
1115
|
+
]
|
|
1116
|
+
},
|
|
1117
|
+
{
|
|
1118
|
+
name: "Mobile",
|
|
1119
|
+
data: [
|
|
1120
|
+
{ label: "Mon", value: 1400 },
|
|
1121
|
+
{ label: "Tue", value: 1500 },
|
|
1122
|
+
{ label: "Wed", value: 1700 },
|
|
1123
|
+
{ label: "Thu", value: 1600 },
|
|
1124
|
+
{ label: "Fri", value: 1800 }
|
|
1125
|
+
]
|
|
1126
|
+
}
|
|
1127
|
+
],
|
|
1128
|
+
axis_config: {
|
|
1129
|
+
categories: ["Mon", "Tue", "Wed", "Thu", "Fri"],
|
|
1130
|
+
x_label: "Day",
|
|
1131
|
+
y_label: "Users"
|
|
1132
|
+
}
|
|
1133
|
+
}
|
|
1134
|
+
})
|
|
1135
|
+
},
|
|
1136
|
+
{
|
|
1137
|
+
id: "dataviz_pie",
|
|
1138
|
+
label: "Pie chart",
|
|
1139
|
+
factory: () => ({
|
|
1140
|
+
type: "data_visualization",
|
|
1141
|
+
title: "Plan distribution by tier",
|
|
1142
|
+
chart: {
|
|
1143
|
+
type: "pie",
|
|
1144
|
+
segments: [
|
|
1145
|
+
{ label: "Free", value: 4200 },
|
|
1146
|
+
{ label: "Pro", value: 2300 },
|
|
1147
|
+
{ label: "Business+", value: 1100 },
|
|
1148
|
+
{ label: "Enterprise", value: 480 }
|
|
1149
|
+
]
|
|
1150
|
+
}
|
|
1151
|
+
})
|
|
1152
|
+
}
|
|
1153
|
+
]
|
|
1154
|
+
},
|
|
1155
|
+
{
|
|
1156
|
+
name: "Container",
|
|
1157
|
+
icon: lucideReact.Container,
|
|
1158
|
+
variants: [
|
|
1159
|
+
{
|
|
1160
|
+
id: "container_collapsible",
|
|
1161
|
+
label: "Collapsible container",
|
|
1162
|
+
factory: () => ({
|
|
1163
|
+
type: "container",
|
|
1164
|
+
title: { type: "plain_text", text: "Bulk update: 2 records selected" },
|
|
1165
|
+
subtitle: { type: "plain_text", text: "Review changes before confirming" },
|
|
1166
|
+
is_collapsible: true,
|
|
1167
|
+
child_blocks: [
|
|
1168
|
+
{
|
|
1169
|
+
type: "section",
|
|
1170
|
+
text: { type: "mrkdwn", text: "*DCW-1024*\nStatus: Open \u2192 Closed" }
|
|
1171
|
+
},
|
|
1172
|
+
{ type: "divider" },
|
|
1173
|
+
{
|
|
1174
|
+
type: "section",
|
|
1175
|
+
text: { type: "mrkdwn", text: "*DCW-1025*\nStatus: In Progress \u2192 Closed" }
|
|
1176
|
+
},
|
|
1177
|
+
{
|
|
1178
|
+
type: "actions",
|
|
1179
|
+
elements: [
|
|
1180
|
+
{
|
|
1181
|
+
type: "button",
|
|
1182
|
+
text: { type: "plain_text", text: "Confirm All", emoji: true },
|
|
1183
|
+
style: "primary",
|
|
1184
|
+
action_id: "bulk_confirm"
|
|
1185
|
+
},
|
|
1186
|
+
{
|
|
1187
|
+
type: "button",
|
|
1188
|
+
text: { type: "plain_text", text: "Cancel", emoji: true },
|
|
1189
|
+
action_id: "bulk_cancel"
|
|
1190
|
+
}
|
|
1191
|
+
]
|
|
1192
|
+
}
|
|
1193
|
+
]
|
|
1194
|
+
})
|
|
1195
|
+
}
|
|
1196
|
+
]
|
|
1017
1197
|
}
|
|
1018
1198
|
];
|
|
1019
1199
|
var legacyInputVariants = [
|
|
@@ -1492,6 +1672,10 @@ function labelForBlockType(type) {
|
|
|
1492
1672
|
return "Plan";
|
|
1493
1673
|
case "task_card":
|
|
1494
1674
|
return "Task Card";
|
|
1675
|
+
case "data_visualization":
|
|
1676
|
+
return "Data Visualization";
|
|
1677
|
+
case "container":
|
|
1678
|
+
return "Container";
|
|
1495
1679
|
}
|
|
1496
1680
|
}
|
|
1497
1681
|
function cn(...inputs) {
|
|
@@ -3406,6 +3590,160 @@ function CarouselEditor({ block, onChange }) {
|
|
|
3406
3590
|
] })
|
|
3407
3591
|
] });
|
|
3408
3592
|
}
|
|
3593
|
+
var MAX_CHILDREN = 10;
|
|
3594
|
+
var WIDTHS = ["narrow", "standard", "wide", "full"];
|
|
3595
|
+
function ContainerEditor({ block, onChange }) {
|
|
3596
|
+
const children = block.child_blocks ?? [];
|
|
3597
|
+
const iconUrl = block.icon && "image_url" in block.icon ? block.icon.image_url ?? "" : "";
|
|
3598
|
+
const iconAlt = block.icon?.alt_text ?? "";
|
|
3599
|
+
const removeChildAt = (idx) => {
|
|
3600
|
+
onChange({ ...block, child_blocks: children.filter((_, i) => i !== idx) });
|
|
3601
|
+
};
|
|
3602
|
+
const addChild = () => {
|
|
3603
|
+
const child = {
|
|
3604
|
+
type: "section",
|
|
3605
|
+
text: { type: "mrkdwn", text: "New block." }
|
|
3606
|
+
};
|
|
3607
|
+
onChange({ ...block, child_blocks: [...children, child] });
|
|
3608
|
+
};
|
|
3609
|
+
return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col gap-4", children: [
|
|
3610
|
+
/* @__PURE__ */ jsxRuntime.jsx(EditorField, { label: "Title", help: "Heading shown at the top of the container.", htmlFor: "container-title", children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
3611
|
+
Input,
|
|
3612
|
+
{
|
|
3613
|
+
id: "container-title",
|
|
3614
|
+
value: block.title?.text ?? "",
|
|
3615
|
+
maxLength: 150,
|
|
3616
|
+
placeholder: "e.g. Bulk update: 2 records selected",
|
|
3617
|
+
onChange: (e) => onChange({ ...block, title: { type: "plain_text", text: e.target.value } })
|
|
3618
|
+
}
|
|
3619
|
+
) }),
|
|
3620
|
+
/* @__PURE__ */ jsxRuntime.jsx(EditorField, { label: "Subtitle", help: "Optional secondary line under the title.", htmlFor: "container-subtitle", children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
3621
|
+
Input,
|
|
3622
|
+
{
|
|
3623
|
+
id: "container-subtitle",
|
|
3624
|
+
value: block.subtitle?.text ?? "",
|
|
3625
|
+
maxLength: 150,
|
|
3626
|
+
placeholder: "e.g. Review changes before confirming",
|
|
3627
|
+
onChange: (e) => onChange({
|
|
3628
|
+
...block,
|
|
3629
|
+
subtitle: e.target.value ? { type: "plain_text", text: e.target.value } : void 0
|
|
3630
|
+
})
|
|
3631
|
+
}
|
|
3632
|
+
) }),
|
|
3633
|
+
/* @__PURE__ */ jsxRuntime.jsx(EditorField, { label: "Icon URL", help: "Optional image shown left of the title.", htmlFor: "container-icon", children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
3634
|
+
Input,
|
|
3635
|
+
{
|
|
3636
|
+
id: "container-icon",
|
|
3637
|
+
type: "url",
|
|
3638
|
+
value: iconUrl,
|
|
3639
|
+
placeholder: "https://example.com/icon.png",
|
|
3640
|
+
onChange: (e) => onChange({
|
|
3641
|
+
...block,
|
|
3642
|
+
icon: e.target.value ? { type: "image", image_url: e.target.value, alt_text: iconAlt || "Container icon" } : void 0
|
|
3643
|
+
})
|
|
3644
|
+
}
|
|
3645
|
+
) }),
|
|
3646
|
+
/* @__PURE__ */ jsxRuntime.jsx(EditorField, { label: "Width", help: "How wide the container renders in the message.", children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
3647
|
+
RadioGroup,
|
|
3648
|
+
{
|
|
3649
|
+
value: block.width ?? "standard",
|
|
3650
|
+
onValueChange: (v) => onChange({ ...block, width: v }),
|
|
3651
|
+
className: "flex flex-row flex-wrap gap-3",
|
|
3652
|
+
children: WIDTHS.map((w) => /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-1.5", children: [
|
|
3653
|
+
/* @__PURE__ */ jsxRuntime.jsx(RadioGroupItem, { value: w, id: `container-width-${w}` }),
|
|
3654
|
+
/* @__PURE__ */ jsxRuntime.jsx(Label, { htmlFor: `container-width-${w}`, className: "text-xs capitalize", children: w })
|
|
3655
|
+
] }, w))
|
|
3656
|
+
}
|
|
3657
|
+
) }),
|
|
3658
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
3659
|
+
Checkbox,
|
|
3660
|
+
{
|
|
3661
|
+
id: "container-collapsible",
|
|
3662
|
+
label: "Collapsible",
|
|
3663
|
+
help: "Let readers expand and collapse the container.",
|
|
3664
|
+
checked: !!block.is_collapsible,
|
|
3665
|
+
onChange: (checked) => onChange({
|
|
3666
|
+
...block,
|
|
3667
|
+
is_collapsible: checked || void 0,
|
|
3668
|
+
default_collapsed: checked ? block.default_collapsed : void 0
|
|
3669
|
+
})
|
|
3670
|
+
}
|
|
3671
|
+
),
|
|
3672
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
3673
|
+
Checkbox,
|
|
3674
|
+
{
|
|
3675
|
+
id: "container-default-collapsed",
|
|
3676
|
+
label: "Collapsed by default",
|
|
3677
|
+
help: "Start collapsed on first render. Requires Collapsible.",
|
|
3678
|
+
checked: !!block.default_collapsed,
|
|
3679
|
+
disabled: !block.is_collapsible,
|
|
3680
|
+
onChange: (checked) => onChange({ ...block, default_collapsed: checked || void 0 })
|
|
3681
|
+
}
|
|
3682
|
+
),
|
|
3683
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col gap-2", children: [
|
|
3684
|
+
/* @__PURE__ */ jsxRuntime.jsx(Label, { children: "Child blocks" }),
|
|
3685
|
+
/* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-[11px] leading-snug text-muted-foreground", children: "A container holds 1-10 blocks. To edit a child's content, use the View JSON drawer." }),
|
|
3686
|
+
children.map((child, idx) => /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center justify-between gap-2 rounded-md border bg-muted/20 px-3 py-2", children: [
|
|
3687
|
+
/* @__PURE__ */ jsxRuntime.jsxs("span", { className: "text-xs font-medium text-foreground", children: [
|
|
3688
|
+
idx + 1,
|
|
3689
|
+
". ",
|
|
3690
|
+
labelForBlockType(child.type)
|
|
3691
|
+
] }),
|
|
3692
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
3693
|
+
"button",
|
|
3694
|
+
{
|
|
3695
|
+
type: "button",
|
|
3696
|
+
"aria-label": "Remove child block",
|
|
3697
|
+
onClick: () => removeChildAt(idx),
|
|
3698
|
+
disabled: children.length <= 1,
|
|
3699
|
+
className: "rounded p-1 text-muted-foreground hover:bg-destructive/10 hover:text-destructive disabled:cursor-not-allowed disabled:opacity-40",
|
|
3700
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Trash2, { className: "h-3.5 w-3.5" })
|
|
3701
|
+
}
|
|
3702
|
+
)
|
|
3703
|
+
] }, idx)),
|
|
3704
|
+
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
3705
|
+
Button,
|
|
3706
|
+
{
|
|
3707
|
+
type: "button",
|
|
3708
|
+
size: "sm",
|
|
3709
|
+
onClick: addChild,
|
|
3710
|
+
disabled: children.length >= MAX_CHILDREN,
|
|
3711
|
+
className: "self-start",
|
|
3712
|
+
children: [
|
|
3713
|
+
/* @__PURE__ */ jsxRuntime.jsx(lucideReact.Plus, { className: "h-3.5 w-3.5" }),
|
|
3714
|
+
" Add block"
|
|
3715
|
+
]
|
|
3716
|
+
}
|
|
3717
|
+
)
|
|
3718
|
+
] })
|
|
3719
|
+
] });
|
|
3720
|
+
}
|
|
3721
|
+
function Checkbox({
|
|
3722
|
+
id,
|
|
3723
|
+
label,
|
|
3724
|
+
help,
|
|
3725
|
+
checked,
|
|
3726
|
+
disabled,
|
|
3727
|
+
onChange
|
|
3728
|
+
}) {
|
|
3729
|
+
return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col gap-1", children: [
|
|
3730
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-2", children: [
|
|
3731
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
3732
|
+
"input",
|
|
3733
|
+
{
|
|
3734
|
+
id,
|
|
3735
|
+
type: "checkbox",
|
|
3736
|
+
checked,
|
|
3737
|
+
disabled,
|
|
3738
|
+
onChange: (e) => onChange(e.target.checked),
|
|
3739
|
+
className: "h-3.5 w-3.5 cursor-pointer rounded border-input disabled:cursor-not-allowed disabled:opacity-40"
|
|
3740
|
+
}
|
|
3741
|
+
),
|
|
3742
|
+
/* @__PURE__ */ jsxRuntime.jsx(Label, { htmlFor: id, className: "cursor-pointer text-xs", children: label })
|
|
3743
|
+
] }),
|
|
3744
|
+
help ? /* @__PURE__ */ jsxRuntime.jsx("p", { className: "ml-5 text-[11px] leading-snug text-muted-foreground", children: help }) : null
|
|
3745
|
+
] });
|
|
3746
|
+
}
|
|
3409
3747
|
var MAX_ELEMENTS = 5;
|
|
3410
3748
|
function ContextActionsEditor({ block, onChange }) {
|
|
3411
3749
|
const elements = block.elements ?? [];
|
|
@@ -3844,6 +4182,294 @@ function ImageItemCard({
|
|
|
3844
4182
|
) })
|
|
3845
4183
|
] });
|
|
3846
4184
|
}
|
|
4185
|
+
var CHART_TYPES = ["line", "bar", "area", "pie"];
|
|
4186
|
+
function isCartesian(chart) {
|
|
4187
|
+
return chart.type !== "pie";
|
|
4188
|
+
}
|
|
4189
|
+
function cartesianToSegments(chart) {
|
|
4190
|
+
return (chart.series[0]?.data ?? []).map((d) => ({ label: d.label, value: d.value }));
|
|
4191
|
+
}
|
|
4192
|
+
function segmentsToCartesian(type, segments) {
|
|
4193
|
+
return {
|
|
4194
|
+
type,
|
|
4195
|
+
series: [{ name: "Series 1", data: segments.map((s) => ({ label: s.label, value: s.value })) }],
|
|
4196
|
+
axis_config: { categories: segments.map((s) => s.label) }
|
|
4197
|
+
};
|
|
4198
|
+
}
|
|
4199
|
+
function convertChart(chart, nextType) {
|
|
4200
|
+
if (nextType === chart.type) {
|
|
4201
|
+
return chart;
|
|
4202
|
+
}
|
|
4203
|
+
if (nextType === "pie") {
|
|
4204
|
+
return { type: "pie", segments: isCartesian(chart) ? cartesianToSegments(chart) : chart.segments };
|
|
4205
|
+
}
|
|
4206
|
+
if (isCartesian(chart)) {
|
|
4207
|
+
return { ...chart, type: nextType };
|
|
4208
|
+
}
|
|
4209
|
+
return segmentsToCartesian(nextType, chart.segments);
|
|
4210
|
+
}
|
|
4211
|
+
function DataVisualizationEditor({ block, onChange }) {
|
|
4212
|
+
const { chart } = block;
|
|
4213
|
+
const setChart = (next) => onChange({ ...block, chart: next });
|
|
4214
|
+
return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col gap-4", children: [
|
|
4215
|
+
/* @__PURE__ */ jsxRuntime.jsx(EditorField, { label: "Title", help: "Heading shown above the chart.", htmlFor: "dataviz-title", children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
4216
|
+
Input,
|
|
4217
|
+
{
|
|
4218
|
+
id: "dataviz-title",
|
|
4219
|
+
value: block.title,
|
|
4220
|
+
placeholder: "e.g. Weekly active users",
|
|
4221
|
+
onChange: (e) => onChange({ ...block, title: e.target.value })
|
|
4222
|
+
}
|
|
4223
|
+
) }),
|
|
4224
|
+
/* @__PURE__ */ jsxRuntime.jsx(EditorField, { label: "Chart type", children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
4225
|
+
RadioGroup,
|
|
4226
|
+
{
|
|
4227
|
+
value: chart.type,
|
|
4228
|
+
onValueChange: (v) => setChart(convertChart(chart, v)),
|
|
4229
|
+
className: "flex flex-row flex-wrap gap-3",
|
|
4230
|
+
children: CHART_TYPES.map((t) => /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-1.5", children: [
|
|
4231
|
+
/* @__PURE__ */ jsxRuntime.jsx(RadioGroupItem, { value: t, id: `dataviz-type-${t}` }),
|
|
4232
|
+
/* @__PURE__ */ jsxRuntime.jsx(Label, { htmlFor: `dataviz-type-${t}`, className: "text-xs capitalize", children: t })
|
|
4233
|
+
] }, t))
|
|
4234
|
+
}
|
|
4235
|
+
) }),
|
|
4236
|
+
isCartesian(chart) ? /* @__PURE__ */ jsxRuntime.jsx(CartesianFields, { chart, onChange: setChart }) : /* @__PURE__ */ jsxRuntime.jsx(PieFields, { chart, onChange: setChart })
|
|
4237
|
+
] });
|
|
4238
|
+
}
|
|
4239
|
+
function NumberInput({
|
|
4240
|
+
id,
|
|
4241
|
+
value,
|
|
4242
|
+
onCommit,
|
|
4243
|
+
ariaLabel,
|
|
4244
|
+
className
|
|
4245
|
+
}) {
|
|
4246
|
+
const [draft, setDraft] = React.useState(String(value));
|
|
4247
|
+
React.useEffect(() => {
|
|
4248
|
+
setDraft(String(value));
|
|
4249
|
+
}, [value]);
|
|
4250
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
4251
|
+
Input,
|
|
4252
|
+
{
|
|
4253
|
+
id,
|
|
4254
|
+
type: "number",
|
|
4255
|
+
inputMode: "numeric",
|
|
4256
|
+
"aria-label": ariaLabel,
|
|
4257
|
+
value: draft,
|
|
4258
|
+
className,
|
|
4259
|
+
onChange: (e) => {
|
|
4260
|
+
const raw = e.target.value;
|
|
4261
|
+
setDraft(raw);
|
|
4262
|
+
if (raw === "" || raw === "-" || raw === "." || raw === "-.") {
|
|
4263
|
+
return;
|
|
4264
|
+
}
|
|
4265
|
+
const next = Number(raw);
|
|
4266
|
+
if (!Number.isNaN(next)) {
|
|
4267
|
+
onCommit(next);
|
|
4268
|
+
}
|
|
4269
|
+
},
|
|
4270
|
+
onBlur: () => {
|
|
4271
|
+
const next = Number(draft);
|
|
4272
|
+
const safe = draft.trim() === "" || Number.isNaN(next) ? 0 : next;
|
|
4273
|
+
onCommit(safe);
|
|
4274
|
+
setDraft(String(safe));
|
|
4275
|
+
}
|
|
4276
|
+
}
|
|
4277
|
+
);
|
|
4278
|
+
}
|
|
4279
|
+
function CartesianFields({ chart, onChange }) {
|
|
4280
|
+
const series = chart.series;
|
|
4281
|
+
const categories = chart.axis_config?.categories && chart.axis_config.categories.length > 0 ? chart.axis_config.categories : series[0]?.data.map((d) => d.label) ?? [];
|
|
4282
|
+
const xLabel = chart.axis_config?.x_label ?? "";
|
|
4283
|
+
const yLabel = chart.axis_config?.y_label ?? "";
|
|
4284
|
+
const commit = (nextCategories, nextSeries, axis) => {
|
|
4285
|
+
const aligned = nextSeries.map((s) => ({
|
|
4286
|
+
name: s.name,
|
|
4287
|
+
data: nextCategories.map((label, i) => ({ label, value: s.data[i]?.value ?? 0 }))
|
|
4288
|
+
}));
|
|
4289
|
+
const x = axis?.x_label ?? xLabel;
|
|
4290
|
+
const y = axis?.y_label ?? yLabel;
|
|
4291
|
+
onChange({
|
|
4292
|
+
type: chart.type,
|
|
4293
|
+
series: aligned,
|
|
4294
|
+
axis_config: {
|
|
4295
|
+
categories: nextCategories,
|
|
4296
|
+
...x ? { x_label: x } : {},
|
|
4297
|
+
...y ? { y_label: y } : {}
|
|
4298
|
+
}
|
|
4299
|
+
});
|
|
4300
|
+
};
|
|
4301
|
+
const setCategory = (col, label) => commit(
|
|
4302
|
+
categories.map((c, i) => i === col ? label : c),
|
|
4303
|
+
series
|
|
4304
|
+
);
|
|
4305
|
+
const addCategory = () => commit([...categories, `Cat ${categories.length + 1}`], series);
|
|
4306
|
+
const removeCategory = (col) => commit(
|
|
4307
|
+
categories.filter((_, i) => i !== col),
|
|
4308
|
+
series.map((s) => ({ name: s.name, data: s.data.filter((_, i) => i !== col) }))
|
|
4309
|
+
);
|
|
4310
|
+
const setCell = (seriesIdx, col, value) => commit(
|
|
4311
|
+
categories,
|
|
4312
|
+
series.map(
|
|
4313
|
+
(s, i) => i === seriesIdx ? { name: s.name, data: s.data.map((d, j) => j === col ? { ...d, value } : d) } : s
|
|
4314
|
+
)
|
|
4315
|
+
);
|
|
4316
|
+
const setSeriesName = (seriesIdx, name) => commit(
|
|
4317
|
+
categories,
|
|
4318
|
+
series.map((s, i) => i === seriesIdx ? { ...s, name } : s)
|
|
4319
|
+
);
|
|
4320
|
+
const addSeries = () => commit(categories, [
|
|
4321
|
+
...series,
|
|
4322
|
+
{ name: `Series ${series.length + 1}`, data: categories.map((label) => ({ label, value: 0 })) }
|
|
4323
|
+
]);
|
|
4324
|
+
const removeSeries = (seriesIdx) => commit(
|
|
4325
|
+
categories,
|
|
4326
|
+
series.filter((_, i) => i !== seriesIdx)
|
|
4327
|
+
);
|
|
4328
|
+
return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col gap-4", children: [
|
|
4329
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex gap-2", children: [
|
|
4330
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex-1", children: /* @__PURE__ */ jsxRuntime.jsx(EditorField, { label: "X-axis label", htmlFor: "dataviz-x-label", children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
4331
|
+
Input,
|
|
4332
|
+
{
|
|
4333
|
+
id: "dataviz-x-label",
|
|
4334
|
+
value: xLabel,
|
|
4335
|
+
placeholder: "e.g. Day",
|
|
4336
|
+
onChange: (e) => commit(categories, series, { x_label: e.target.value })
|
|
4337
|
+
}
|
|
4338
|
+
) }) }),
|
|
4339
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex-1", children: /* @__PURE__ */ jsxRuntime.jsx(EditorField, { label: "Y-axis label", htmlFor: "dataviz-y-label", children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
4340
|
+
Input,
|
|
4341
|
+
{
|
|
4342
|
+
id: "dataviz-y-label",
|
|
4343
|
+
value: yLabel,
|
|
4344
|
+
placeholder: "e.g. Users",
|
|
4345
|
+
onChange: (e) => commit(categories, series, { y_label: e.target.value })
|
|
4346
|
+
}
|
|
4347
|
+
) }) })
|
|
4348
|
+
] }),
|
|
4349
|
+
/* @__PURE__ */ jsxRuntime.jsx(EditorField, { label: "Data", help: "Categories are the x-axis; each series is plotted across them.", children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col gap-2 overflow-x-auto", children: [
|
|
4350
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-1", children: [
|
|
4351
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "w-36 shrink-0", "aria-hidden": "true" }),
|
|
4352
|
+
categories.map((cat, c) => /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex min-w-[88px] flex-1 items-center gap-1", children: [
|
|
4353
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
4354
|
+
Input,
|
|
4355
|
+
{
|
|
4356
|
+
"aria-label": `Category ${c + 1}`,
|
|
4357
|
+
value: cat,
|
|
4358
|
+
placeholder: `Cat ${c + 1}`,
|
|
4359
|
+
onChange: (e) => setCategory(c, e.target.value),
|
|
4360
|
+
className: "h-8 text-xs"
|
|
4361
|
+
}
|
|
4362
|
+
),
|
|
4363
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
4364
|
+
"button",
|
|
4365
|
+
{
|
|
4366
|
+
type: "button",
|
|
4367
|
+
"aria-label": `Remove category ${c + 1}`,
|
|
4368
|
+
onClick: () => removeCategory(c),
|
|
4369
|
+
className: "flex h-6 w-6 shrink-0 items-center justify-center rounded text-muted-foreground hover:bg-destructive/10 hover:text-destructive",
|
|
4370
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Trash2, { className: "h-3 w-3" })
|
|
4371
|
+
}
|
|
4372
|
+
)
|
|
4373
|
+
] }, c))
|
|
4374
|
+
] }),
|
|
4375
|
+
series.map((s, si) => /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-1", children: [
|
|
4376
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex w-36 shrink-0 items-center gap-1", children: [
|
|
4377
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
4378
|
+
Input,
|
|
4379
|
+
{
|
|
4380
|
+
"aria-label": `Series ${si + 1} name`,
|
|
4381
|
+
value: s.name,
|
|
4382
|
+
placeholder: `Series ${si + 1}`,
|
|
4383
|
+
onChange: (e) => setSeriesName(si, e.target.value),
|
|
4384
|
+
className: "h-8 text-xs"
|
|
4385
|
+
}
|
|
4386
|
+
),
|
|
4387
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
4388
|
+
"button",
|
|
4389
|
+
{
|
|
4390
|
+
type: "button",
|
|
4391
|
+
"aria-label": `Remove series ${si + 1}`,
|
|
4392
|
+
onClick: () => removeSeries(si),
|
|
4393
|
+
className: "flex h-6 w-6 shrink-0 items-center justify-center rounded text-muted-foreground hover:bg-destructive/10 hover:text-destructive",
|
|
4394
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Trash2, { className: "h-3 w-3" })
|
|
4395
|
+
}
|
|
4396
|
+
)
|
|
4397
|
+
] }),
|
|
4398
|
+
categories.map((cat, c) => /* @__PURE__ */ jsxRuntime.jsx("div", { className: "min-w-[88px] flex-1", children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
4399
|
+
NumberInput,
|
|
4400
|
+
{
|
|
4401
|
+
value: s.data[c]?.value ?? 0,
|
|
4402
|
+
onCommit: (n) => setCell(si, c, n),
|
|
4403
|
+
ariaLabel: `${s.name || `Series ${si + 1}`} value for ${cat || `category ${c + 1}`}`,
|
|
4404
|
+
className: "h-8 text-xs"
|
|
4405
|
+
}
|
|
4406
|
+
) }, c))
|
|
4407
|
+
] }, si))
|
|
4408
|
+
] }) }),
|
|
4409
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex gap-2", children: [
|
|
4410
|
+
/* @__PURE__ */ jsxRuntime.jsxs(Button, { type: "button", size: "sm", onClick: addSeries, className: "self-start", children: [
|
|
4411
|
+
/* @__PURE__ */ jsxRuntime.jsx(lucideReact.Plus, { className: "h-3.5 w-3.5" }),
|
|
4412
|
+
" Add series"
|
|
4413
|
+
] }),
|
|
4414
|
+
/* @__PURE__ */ jsxRuntime.jsxs(Button, { type: "button", size: "sm", variant: "outline", onClick: addCategory, className: "self-start", children: [
|
|
4415
|
+
/* @__PURE__ */ jsxRuntime.jsx(lucideReact.Plus, { className: "h-3.5 w-3.5" }),
|
|
4416
|
+
" Add category"
|
|
4417
|
+
] })
|
|
4418
|
+
] })
|
|
4419
|
+
] });
|
|
4420
|
+
}
|
|
4421
|
+
function PieFields({ chart, onChange }) {
|
|
4422
|
+
const segments = chart.segments;
|
|
4423
|
+
const setSegment = (idx, change) => onChange({ ...chart, segments: segments.map((s, i) => i === idx ? { ...s, ...change } : s) });
|
|
4424
|
+
const removeSegment = (idx) => onChange({ ...chart, segments: segments.filter((_, i) => i !== idx) });
|
|
4425
|
+
const addSegment = () => onChange({ ...chart, segments: [...segments, { label: `Segment ${segments.length + 1}`, value: 0 }] });
|
|
4426
|
+
return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col gap-2 rounded-md border bg-muted/20 p-3", children: [
|
|
4427
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-xs font-medium text-foreground", children: "Segments" }),
|
|
4428
|
+
segments.length === 0 ? /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-[11px] leading-snug text-muted-foreground", children: "No segments. Add one to render a slice." }) : null,
|
|
4429
|
+
segments.map((seg, idx) => /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col gap-2 rounded border bg-background p-2", children: [
|
|
4430
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center justify-between", children: [
|
|
4431
|
+
/* @__PURE__ */ jsxRuntime.jsxs("span", { className: "text-xs font-medium text-foreground", children: [
|
|
4432
|
+
"Segment ",
|
|
4433
|
+
idx + 1
|
|
4434
|
+
] }),
|
|
4435
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
4436
|
+
"button",
|
|
4437
|
+
{
|
|
4438
|
+
type: "button",
|
|
4439
|
+
"aria-label": "Remove segment",
|
|
4440
|
+
onClick: () => removeSegment(idx),
|
|
4441
|
+
className: "rounded p-1 text-muted-foreground hover:bg-destructive/10 hover:text-destructive",
|
|
4442
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Trash2, { className: "h-3.5 w-3.5" })
|
|
4443
|
+
}
|
|
4444
|
+
)
|
|
4445
|
+
] }),
|
|
4446
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex gap-2", children: [
|
|
4447
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex-1", children: /* @__PURE__ */ jsxRuntime.jsx(EditorField, { label: "Label", htmlFor: `pie-label-${idx}`, children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
4448
|
+
Input,
|
|
4449
|
+
{
|
|
4450
|
+
id: `pie-label-${idx}`,
|
|
4451
|
+
value: seg.label,
|
|
4452
|
+
placeholder: "e.g. Free",
|
|
4453
|
+
onChange: (e) => setSegment(idx, { label: e.target.value })
|
|
4454
|
+
}
|
|
4455
|
+
) }) }),
|
|
4456
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "w-28", children: /* @__PURE__ */ jsxRuntime.jsx(EditorField, { label: "Value", htmlFor: `pie-value-${idx}`, children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
4457
|
+
NumberInput,
|
|
4458
|
+
{
|
|
4459
|
+
id: `pie-value-${idx}`,
|
|
4460
|
+
value: seg.value,
|
|
4461
|
+
onCommit: (n) => setSegment(idx, { value: n }),
|
|
4462
|
+
ariaLabel: `Segment ${idx + 1} value`
|
|
4463
|
+
}
|
|
4464
|
+
) }) })
|
|
4465
|
+
] })
|
|
4466
|
+
] }, idx)),
|
|
4467
|
+
/* @__PURE__ */ jsxRuntime.jsxs(Button, { type: "button", size: "sm", onClick: addSegment, className: "self-start", children: [
|
|
4468
|
+
/* @__PURE__ */ jsxRuntime.jsx(lucideReact.Plus, { className: "h-3.5 w-3.5" }),
|
|
4469
|
+
" Add segment"
|
|
4470
|
+
] })
|
|
4471
|
+
] });
|
|
4472
|
+
}
|
|
3847
4473
|
function DividerEditor() {
|
|
3848
4474
|
return /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-xs text-muted-foreground", children: "A horizontal line that separates content. This block has no options to configure." });
|
|
3849
4475
|
}
|
|
@@ -5292,7 +5918,7 @@ var SUPPORTED_BLOCK_KINDS = /* @__PURE__ */ new Set([
|
|
|
5292
5918
|
"rich_text_preformatted"
|
|
5293
5919
|
]);
|
|
5294
5920
|
var SUPPORTED_INLINE_KINDS = /* @__PURE__ */ new Set(["text", "link", "emoji"]);
|
|
5295
|
-
var SUPPORTED_TEXT_STYLE_KEYS = /* @__PURE__ */ new Set(["bold", "italic", "strike", "code"]);
|
|
5921
|
+
var SUPPORTED_TEXT_STYLE_KEYS = /* @__PURE__ */ new Set(["bold", "italic", "strike", "underline", "code"]);
|
|
5296
5922
|
var MAX_LIST_INDENT = 8;
|
|
5297
5923
|
function detectLossy(block) {
|
|
5298
5924
|
const out = [];
|
|
@@ -5476,6 +6102,9 @@ function styleToMarks(style) {
|
|
|
5476
6102
|
if (style.strike) {
|
|
5477
6103
|
marks.push({ type: "strike" });
|
|
5478
6104
|
}
|
|
6105
|
+
if (style.underline) {
|
|
6106
|
+
marks.push({ type: "underline" });
|
|
6107
|
+
}
|
|
5479
6108
|
if (style.code) {
|
|
5480
6109
|
marks.push({ type: "code" });
|
|
5481
6110
|
}
|
|
@@ -5622,6 +6251,9 @@ function marksToStyle(marks) {
|
|
|
5622
6251
|
if (m.type === "strike") {
|
|
5623
6252
|
style.strike = true;
|
|
5624
6253
|
}
|
|
6254
|
+
if (m.type === "underline") {
|
|
6255
|
+
style.underline = true;
|
|
6256
|
+
}
|
|
5625
6257
|
if (m.type === "code") {
|
|
5626
6258
|
style.code = true;
|
|
5627
6259
|
}
|
|
@@ -5709,7 +6341,7 @@ var INLINE_LABEL = {
|
|
|
5709
6341
|
broadcast: "Broadcast",
|
|
5710
6342
|
usergroup: "User group"
|
|
5711
6343
|
};
|
|
5712
|
-
var STYLE_KEYS = ["bold", "italic", "strike", "code"];
|
|
6344
|
+
var STYLE_KEYS = ["bold", "italic", "strike", "underline", "code"];
|
|
5713
6345
|
function RichTextStructuredEditor({ block, onChange }) {
|
|
5714
6346
|
const elements = block.elements ?? [];
|
|
5715
6347
|
const replaceElements = (next) => {
|
|
@@ -6388,6 +7020,15 @@ function Toolbar({ editor }) {
|
|
|
6388
7020
|
Icon: lucideReact.Strikethrough
|
|
6389
7021
|
}
|
|
6390
7022
|
),
|
|
7023
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
7024
|
+
ToolbarButton,
|
|
7025
|
+
{
|
|
7026
|
+
label: "Underline",
|
|
7027
|
+
active: editor.isActive("underline"),
|
|
7028
|
+
onClick: () => editor.chain().focus().toggleUnderline().run(),
|
|
7029
|
+
Icon: lucideReact.Underline
|
|
7030
|
+
}
|
|
7031
|
+
),
|
|
6391
7032
|
/* @__PURE__ */ jsxRuntime.jsx(
|
|
6392
7033
|
ToolbarButton,
|
|
6393
7034
|
{
|
|
@@ -7270,6 +7911,10 @@ function dispatch(block, onChange) {
|
|
|
7270
7911
|
return /* @__PURE__ */ jsxRuntime.jsx(PlanEditor, { block, onChange: (next) => onChange(next) });
|
|
7271
7912
|
case "task_card":
|
|
7272
7913
|
return /* @__PURE__ */ jsxRuntime.jsx(TaskCardEditor, { block, onChange: (next) => onChange(next) });
|
|
7914
|
+
case "data_visualization":
|
|
7915
|
+
return /* @__PURE__ */ jsxRuntime.jsx(DataVisualizationEditor, { block, onChange: (next) => onChange(next) });
|
|
7916
|
+
case "container":
|
|
7917
|
+
return /* @__PURE__ */ jsxRuntime.jsx(ContainerEditor, { block, onChange: (next) => onChange(next) });
|
|
7273
7918
|
default:
|
|
7274
7919
|
return null;
|
|
7275
7920
|
}
|
|
@@ -7345,7 +7990,9 @@ var BLOCK_TYPE_LABELS = {
|
|
|
7345
7990
|
input: "Input",
|
|
7346
7991
|
video: "Video",
|
|
7347
7992
|
plan: "Plan",
|
|
7348
|
-
task_card: "Task Card"
|
|
7993
|
+
task_card: "Task Card",
|
|
7994
|
+
data_visualization: "Data Visualization",
|
|
7995
|
+
container: "Container"
|
|
7349
7996
|
};
|
|
7350
7997
|
function BlockRow({
|
|
7351
7998
|
builderBlock,
|