@tightknitai/block-kitchen 0.8.5 → 0.8.7
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +6 -3
- package/dist/helpers.d.cts +2 -2
- package/dist/helpers.d.ts +2 -2
- package/dist/index.cjs +483 -16
- 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 +484 -17
- package/dist/index.js.map +1 -1
- package/dist/{palette-Dco-CVMi.d.cts → palette-WZCUVJTn.d.cts} +112 -8
- package/dist/{palette-Dco-CVMi.d.ts → palette-WZCUVJTn.d.ts} +112 -8
- package/dist/palette.cjs +137 -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 +138 -1
- package/dist/palette.js.map +1 -1
- package/dist/styles.css +1 -1
- package/package.json +12 -4
package/dist/index.cjs
CHANGED
|
@@ -1014,6 +1014,143 @@ 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
|
+
]
|
|
1017
1154
|
}
|
|
1018
1155
|
];
|
|
1019
1156
|
var legacyInputVariants = [
|
|
@@ -1492,6 +1629,8 @@ function labelForBlockType(type) {
|
|
|
1492
1629
|
return "Plan";
|
|
1493
1630
|
case "task_card":
|
|
1494
1631
|
return "Task Card";
|
|
1632
|
+
case "data_visualization":
|
|
1633
|
+
return "Data Visualization";
|
|
1495
1634
|
}
|
|
1496
1635
|
}
|
|
1497
1636
|
function cn(...inputs) {
|
|
@@ -2274,6 +2413,18 @@ function IssuesSheet({
|
|
|
2274
2413
|
] })
|
|
2275
2414
|
] }) });
|
|
2276
2415
|
}
|
|
2416
|
+
|
|
2417
|
+
// src/lib/parse-blocks-input.ts
|
|
2418
|
+
var BLOCKS_INPUT_SHAPE_ERROR = "Expected an array of blocks, or an object with a `blocks` array.";
|
|
2419
|
+
function unwrapBlocksInput(parsed) {
|
|
2420
|
+
if (Array.isArray(parsed)) {
|
|
2421
|
+
return parsed;
|
|
2422
|
+
}
|
|
2423
|
+
if (parsed && typeof parsed === "object" && Array.isArray(parsed.blocks)) {
|
|
2424
|
+
return parsed.blocks;
|
|
2425
|
+
}
|
|
2426
|
+
return null;
|
|
2427
|
+
}
|
|
2277
2428
|
var MAX_JSON_BYTES = 1024 * 1024;
|
|
2278
2429
|
function JsonDrawer({
|
|
2279
2430
|
open,
|
|
@@ -2312,14 +2463,15 @@ function JsonDrawer({
|
|
|
2312
2463
|
setValidationErrors([]);
|
|
2313
2464
|
return;
|
|
2314
2465
|
}
|
|
2315
|
-
|
|
2316
|
-
|
|
2466
|
+
const blocks2 = unwrapBlocksInput(parsed);
|
|
2467
|
+
if (!blocks2) {
|
|
2468
|
+
setParseError(BLOCKS_INPUT_SHAPE_ERROR);
|
|
2317
2469
|
setValidationErrors([]);
|
|
2318
2470
|
return;
|
|
2319
2471
|
}
|
|
2320
2472
|
setParseError(null);
|
|
2321
|
-
onApply(
|
|
2322
|
-
const result = slackBlockKitValidator.validateBlockKit(
|
|
2473
|
+
onApply(blocks2);
|
|
2474
|
+
const result = slackBlockKitValidator.validateBlockKit(blocks2, {
|
|
2323
2475
|
target: "blocks",
|
|
2324
2476
|
surface: "message"
|
|
2325
2477
|
});
|
|
@@ -2697,6 +2849,7 @@ function SendDialog({
|
|
|
2697
2849
|
loadChannels,
|
|
2698
2850
|
loadSendAsUserStatus,
|
|
2699
2851
|
onSend,
|
|
2852
|
+
confirmSendLabel = "Send",
|
|
2700
2853
|
errorCount,
|
|
2701
2854
|
onShowIssues
|
|
2702
2855
|
}) {
|
|
@@ -2870,7 +3023,7 @@ function SendDialog({
|
|
|
2870
3023
|
type: "button",
|
|
2871
3024
|
onClick: handleSubmit,
|
|
2872
3025
|
disabled: status.kind === "sending" || !channelId || blocks.length === 0 || errorCount > 0,
|
|
2873
|
-
children: status.kind === "sending" ? "Sending\u2026" :
|
|
3026
|
+
children: status.kind === "sending" ? "Sending\u2026" : confirmSendLabel
|
|
2874
3027
|
}
|
|
2875
3028
|
)
|
|
2876
3029
|
] })
|
|
@@ -3830,6 +3983,294 @@ function ImageItemCard({
|
|
|
3830
3983
|
) })
|
|
3831
3984
|
] });
|
|
3832
3985
|
}
|
|
3986
|
+
var CHART_TYPES = ["line", "bar", "area", "pie"];
|
|
3987
|
+
function isCartesian(chart) {
|
|
3988
|
+
return chart.type !== "pie";
|
|
3989
|
+
}
|
|
3990
|
+
function cartesianToSegments(chart) {
|
|
3991
|
+
return (chart.series[0]?.data ?? []).map((d) => ({ label: d.label, value: d.value }));
|
|
3992
|
+
}
|
|
3993
|
+
function segmentsToCartesian(type, segments) {
|
|
3994
|
+
return {
|
|
3995
|
+
type,
|
|
3996
|
+
series: [{ name: "Series 1", data: segments.map((s) => ({ label: s.label, value: s.value })) }],
|
|
3997
|
+
axis_config: { categories: segments.map((s) => s.label) }
|
|
3998
|
+
};
|
|
3999
|
+
}
|
|
4000
|
+
function convertChart(chart, nextType) {
|
|
4001
|
+
if (nextType === chart.type) {
|
|
4002
|
+
return chart;
|
|
4003
|
+
}
|
|
4004
|
+
if (nextType === "pie") {
|
|
4005
|
+
return { type: "pie", segments: isCartesian(chart) ? cartesianToSegments(chart) : chart.segments };
|
|
4006
|
+
}
|
|
4007
|
+
if (isCartesian(chart)) {
|
|
4008
|
+
return { ...chart, type: nextType };
|
|
4009
|
+
}
|
|
4010
|
+
return segmentsToCartesian(nextType, chart.segments);
|
|
4011
|
+
}
|
|
4012
|
+
function DataVisualizationEditor({ block, onChange }) {
|
|
4013
|
+
const { chart } = block;
|
|
4014
|
+
const setChart = (next) => onChange({ ...block, chart: next });
|
|
4015
|
+
return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col gap-4", children: [
|
|
4016
|
+
/* @__PURE__ */ jsxRuntime.jsx(EditorField, { label: "Title", help: "Heading shown above the chart.", htmlFor: "dataviz-title", children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
4017
|
+
Input,
|
|
4018
|
+
{
|
|
4019
|
+
id: "dataviz-title",
|
|
4020
|
+
value: block.title,
|
|
4021
|
+
placeholder: "e.g. Weekly active users",
|
|
4022
|
+
onChange: (e) => onChange({ ...block, title: e.target.value })
|
|
4023
|
+
}
|
|
4024
|
+
) }),
|
|
4025
|
+
/* @__PURE__ */ jsxRuntime.jsx(EditorField, { label: "Chart type", children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
4026
|
+
RadioGroup,
|
|
4027
|
+
{
|
|
4028
|
+
value: chart.type,
|
|
4029
|
+
onValueChange: (v) => setChart(convertChart(chart, v)),
|
|
4030
|
+
className: "flex flex-row flex-wrap gap-3",
|
|
4031
|
+
children: CHART_TYPES.map((t) => /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-1.5", children: [
|
|
4032
|
+
/* @__PURE__ */ jsxRuntime.jsx(RadioGroupItem, { value: t, id: `dataviz-type-${t}` }),
|
|
4033
|
+
/* @__PURE__ */ jsxRuntime.jsx(Label, { htmlFor: `dataviz-type-${t}`, className: "text-xs capitalize", children: t })
|
|
4034
|
+
] }, t))
|
|
4035
|
+
}
|
|
4036
|
+
) }),
|
|
4037
|
+
isCartesian(chart) ? /* @__PURE__ */ jsxRuntime.jsx(CartesianFields, { chart, onChange: setChart }) : /* @__PURE__ */ jsxRuntime.jsx(PieFields, { chart, onChange: setChart })
|
|
4038
|
+
] });
|
|
4039
|
+
}
|
|
4040
|
+
function NumberInput({
|
|
4041
|
+
id,
|
|
4042
|
+
value,
|
|
4043
|
+
onCommit,
|
|
4044
|
+
ariaLabel,
|
|
4045
|
+
className
|
|
4046
|
+
}) {
|
|
4047
|
+
const [draft, setDraft] = React.useState(String(value));
|
|
4048
|
+
React.useEffect(() => {
|
|
4049
|
+
setDraft(String(value));
|
|
4050
|
+
}, [value]);
|
|
4051
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
4052
|
+
Input,
|
|
4053
|
+
{
|
|
4054
|
+
id,
|
|
4055
|
+
type: "number",
|
|
4056
|
+
inputMode: "numeric",
|
|
4057
|
+
"aria-label": ariaLabel,
|
|
4058
|
+
value: draft,
|
|
4059
|
+
className,
|
|
4060
|
+
onChange: (e) => {
|
|
4061
|
+
const raw = e.target.value;
|
|
4062
|
+
setDraft(raw);
|
|
4063
|
+
if (raw === "" || raw === "-" || raw === "." || raw === "-.") {
|
|
4064
|
+
return;
|
|
4065
|
+
}
|
|
4066
|
+
const next = Number(raw);
|
|
4067
|
+
if (!Number.isNaN(next)) {
|
|
4068
|
+
onCommit(next);
|
|
4069
|
+
}
|
|
4070
|
+
},
|
|
4071
|
+
onBlur: () => {
|
|
4072
|
+
const next = Number(draft);
|
|
4073
|
+
const safe = draft.trim() === "" || Number.isNaN(next) ? 0 : next;
|
|
4074
|
+
onCommit(safe);
|
|
4075
|
+
setDraft(String(safe));
|
|
4076
|
+
}
|
|
4077
|
+
}
|
|
4078
|
+
);
|
|
4079
|
+
}
|
|
4080
|
+
function CartesianFields({ chart, onChange }) {
|
|
4081
|
+
const series = chart.series;
|
|
4082
|
+
const categories = chart.axis_config?.categories && chart.axis_config.categories.length > 0 ? chart.axis_config.categories : series[0]?.data.map((d) => d.label) ?? [];
|
|
4083
|
+
const xLabel = chart.axis_config?.x_label ?? "";
|
|
4084
|
+
const yLabel = chart.axis_config?.y_label ?? "";
|
|
4085
|
+
const commit = (nextCategories, nextSeries, axis) => {
|
|
4086
|
+
const aligned = nextSeries.map((s) => ({
|
|
4087
|
+
name: s.name,
|
|
4088
|
+
data: nextCategories.map((label, i) => ({ label, value: s.data[i]?.value ?? 0 }))
|
|
4089
|
+
}));
|
|
4090
|
+
const x = axis?.x_label ?? xLabel;
|
|
4091
|
+
const y = axis?.y_label ?? yLabel;
|
|
4092
|
+
onChange({
|
|
4093
|
+
type: chart.type,
|
|
4094
|
+
series: aligned,
|
|
4095
|
+
axis_config: {
|
|
4096
|
+
categories: nextCategories,
|
|
4097
|
+
...x ? { x_label: x } : {},
|
|
4098
|
+
...y ? { y_label: y } : {}
|
|
4099
|
+
}
|
|
4100
|
+
});
|
|
4101
|
+
};
|
|
4102
|
+
const setCategory = (col, label) => commit(
|
|
4103
|
+
categories.map((c, i) => i === col ? label : c),
|
|
4104
|
+
series
|
|
4105
|
+
);
|
|
4106
|
+
const addCategory = () => commit([...categories, `Cat ${categories.length + 1}`], series);
|
|
4107
|
+
const removeCategory = (col) => commit(
|
|
4108
|
+
categories.filter((_, i) => i !== col),
|
|
4109
|
+
series.map((s) => ({ name: s.name, data: s.data.filter((_, i) => i !== col) }))
|
|
4110
|
+
);
|
|
4111
|
+
const setCell = (seriesIdx, col, value) => commit(
|
|
4112
|
+
categories,
|
|
4113
|
+
series.map(
|
|
4114
|
+
(s, i) => i === seriesIdx ? { name: s.name, data: s.data.map((d, j) => j === col ? { ...d, value } : d) } : s
|
|
4115
|
+
)
|
|
4116
|
+
);
|
|
4117
|
+
const setSeriesName = (seriesIdx, name) => commit(
|
|
4118
|
+
categories,
|
|
4119
|
+
series.map((s, i) => i === seriesIdx ? { ...s, name } : s)
|
|
4120
|
+
);
|
|
4121
|
+
const addSeries = () => commit(categories, [
|
|
4122
|
+
...series,
|
|
4123
|
+
{ name: `Series ${series.length + 1}`, data: categories.map((label) => ({ label, value: 0 })) }
|
|
4124
|
+
]);
|
|
4125
|
+
const removeSeries = (seriesIdx) => commit(
|
|
4126
|
+
categories,
|
|
4127
|
+
series.filter((_, i) => i !== seriesIdx)
|
|
4128
|
+
);
|
|
4129
|
+
return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col gap-4", children: [
|
|
4130
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex gap-2", children: [
|
|
4131
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex-1", children: /* @__PURE__ */ jsxRuntime.jsx(EditorField, { label: "X-axis label", htmlFor: "dataviz-x-label", children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
4132
|
+
Input,
|
|
4133
|
+
{
|
|
4134
|
+
id: "dataviz-x-label",
|
|
4135
|
+
value: xLabel,
|
|
4136
|
+
placeholder: "e.g. Day",
|
|
4137
|
+
onChange: (e) => commit(categories, series, { x_label: e.target.value })
|
|
4138
|
+
}
|
|
4139
|
+
) }) }),
|
|
4140
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex-1", children: /* @__PURE__ */ jsxRuntime.jsx(EditorField, { label: "Y-axis label", htmlFor: "dataviz-y-label", children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
4141
|
+
Input,
|
|
4142
|
+
{
|
|
4143
|
+
id: "dataviz-y-label",
|
|
4144
|
+
value: yLabel,
|
|
4145
|
+
placeholder: "e.g. Users",
|
|
4146
|
+
onChange: (e) => commit(categories, series, { y_label: e.target.value })
|
|
4147
|
+
}
|
|
4148
|
+
) }) })
|
|
4149
|
+
] }),
|
|
4150
|
+
/* @__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: [
|
|
4151
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-1", children: [
|
|
4152
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "w-36 shrink-0", "aria-hidden": "true" }),
|
|
4153
|
+
categories.map((cat, c) => /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex min-w-[88px] flex-1 items-center gap-1", children: [
|
|
4154
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
4155
|
+
Input,
|
|
4156
|
+
{
|
|
4157
|
+
"aria-label": `Category ${c + 1}`,
|
|
4158
|
+
value: cat,
|
|
4159
|
+
placeholder: `Cat ${c + 1}`,
|
|
4160
|
+
onChange: (e) => setCategory(c, e.target.value),
|
|
4161
|
+
className: "h-8 text-xs"
|
|
4162
|
+
}
|
|
4163
|
+
),
|
|
4164
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
4165
|
+
"button",
|
|
4166
|
+
{
|
|
4167
|
+
type: "button",
|
|
4168
|
+
"aria-label": `Remove category ${c + 1}`,
|
|
4169
|
+
onClick: () => removeCategory(c),
|
|
4170
|
+
className: "flex h-6 w-6 shrink-0 items-center justify-center rounded text-muted-foreground hover:bg-destructive/10 hover:text-destructive",
|
|
4171
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Trash2, { className: "h-3 w-3" })
|
|
4172
|
+
}
|
|
4173
|
+
)
|
|
4174
|
+
] }, c))
|
|
4175
|
+
] }),
|
|
4176
|
+
series.map((s, si) => /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-1", children: [
|
|
4177
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex w-36 shrink-0 items-center gap-1", children: [
|
|
4178
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
4179
|
+
Input,
|
|
4180
|
+
{
|
|
4181
|
+
"aria-label": `Series ${si + 1} name`,
|
|
4182
|
+
value: s.name,
|
|
4183
|
+
placeholder: `Series ${si + 1}`,
|
|
4184
|
+
onChange: (e) => setSeriesName(si, e.target.value),
|
|
4185
|
+
className: "h-8 text-xs"
|
|
4186
|
+
}
|
|
4187
|
+
),
|
|
4188
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
4189
|
+
"button",
|
|
4190
|
+
{
|
|
4191
|
+
type: "button",
|
|
4192
|
+
"aria-label": `Remove series ${si + 1}`,
|
|
4193
|
+
onClick: () => removeSeries(si),
|
|
4194
|
+
className: "flex h-6 w-6 shrink-0 items-center justify-center rounded text-muted-foreground hover:bg-destructive/10 hover:text-destructive",
|
|
4195
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Trash2, { className: "h-3 w-3" })
|
|
4196
|
+
}
|
|
4197
|
+
)
|
|
4198
|
+
] }),
|
|
4199
|
+
categories.map((cat, c) => /* @__PURE__ */ jsxRuntime.jsx("div", { className: "min-w-[88px] flex-1", children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
4200
|
+
NumberInput,
|
|
4201
|
+
{
|
|
4202
|
+
value: s.data[c]?.value ?? 0,
|
|
4203
|
+
onCommit: (n) => setCell(si, c, n),
|
|
4204
|
+
ariaLabel: `${s.name || `Series ${si + 1}`} value for ${cat || `category ${c + 1}`}`,
|
|
4205
|
+
className: "h-8 text-xs"
|
|
4206
|
+
}
|
|
4207
|
+
) }, c))
|
|
4208
|
+
] }, si))
|
|
4209
|
+
] }) }),
|
|
4210
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex gap-2", children: [
|
|
4211
|
+
/* @__PURE__ */ jsxRuntime.jsxs(Button, { type: "button", size: "sm", onClick: addSeries, className: "self-start", children: [
|
|
4212
|
+
/* @__PURE__ */ jsxRuntime.jsx(lucideReact.Plus, { className: "h-3.5 w-3.5" }),
|
|
4213
|
+
" Add series"
|
|
4214
|
+
] }),
|
|
4215
|
+
/* @__PURE__ */ jsxRuntime.jsxs(Button, { type: "button", size: "sm", variant: "outline", onClick: addCategory, className: "self-start", children: [
|
|
4216
|
+
/* @__PURE__ */ jsxRuntime.jsx(lucideReact.Plus, { className: "h-3.5 w-3.5" }),
|
|
4217
|
+
" Add category"
|
|
4218
|
+
] })
|
|
4219
|
+
] })
|
|
4220
|
+
] });
|
|
4221
|
+
}
|
|
4222
|
+
function PieFields({ chart, onChange }) {
|
|
4223
|
+
const segments = chart.segments;
|
|
4224
|
+
const setSegment = (idx, change) => onChange({ ...chart, segments: segments.map((s, i) => i === idx ? { ...s, ...change } : s) });
|
|
4225
|
+
const removeSegment = (idx) => onChange({ ...chart, segments: segments.filter((_, i) => i !== idx) });
|
|
4226
|
+
const addSegment = () => onChange({ ...chart, segments: [...segments, { label: `Segment ${segments.length + 1}`, value: 0 }] });
|
|
4227
|
+
return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col gap-2 rounded-md border bg-muted/20 p-3", children: [
|
|
4228
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-xs font-medium text-foreground", children: "Segments" }),
|
|
4229
|
+
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,
|
|
4230
|
+
segments.map((seg, idx) => /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col gap-2 rounded border bg-background p-2", children: [
|
|
4231
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center justify-between", children: [
|
|
4232
|
+
/* @__PURE__ */ jsxRuntime.jsxs("span", { className: "text-xs font-medium text-foreground", children: [
|
|
4233
|
+
"Segment ",
|
|
4234
|
+
idx + 1
|
|
4235
|
+
] }),
|
|
4236
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
4237
|
+
"button",
|
|
4238
|
+
{
|
|
4239
|
+
type: "button",
|
|
4240
|
+
"aria-label": "Remove segment",
|
|
4241
|
+
onClick: () => removeSegment(idx),
|
|
4242
|
+
className: "rounded p-1 text-muted-foreground hover:bg-destructive/10 hover:text-destructive",
|
|
4243
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Trash2, { className: "h-3.5 w-3.5" })
|
|
4244
|
+
}
|
|
4245
|
+
)
|
|
4246
|
+
] }),
|
|
4247
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex gap-2", children: [
|
|
4248
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex-1", children: /* @__PURE__ */ jsxRuntime.jsx(EditorField, { label: "Label", htmlFor: `pie-label-${idx}`, children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
4249
|
+
Input,
|
|
4250
|
+
{
|
|
4251
|
+
id: `pie-label-${idx}`,
|
|
4252
|
+
value: seg.label,
|
|
4253
|
+
placeholder: "e.g. Free",
|
|
4254
|
+
onChange: (e) => setSegment(idx, { label: e.target.value })
|
|
4255
|
+
}
|
|
4256
|
+
) }) }),
|
|
4257
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "w-28", children: /* @__PURE__ */ jsxRuntime.jsx(EditorField, { label: "Value", htmlFor: `pie-value-${idx}`, children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
4258
|
+
NumberInput,
|
|
4259
|
+
{
|
|
4260
|
+
id: `pie-value-${idx}`,
|
|
4261
|
+
value: seg.value,
|
|
4262
|
+
onCommit: (n) => setSegment(idx, { value: n }),
|
|
4263
|
+
ariaLabel: `Segment ${idx + 1} value`
|
|
4264
|
+
}
|
|
4265
|
+
) }) })
|
|
4266
|
+
] })
|
|
4267
|
+
] }, idx)),
|
|
4268
|
+
/* @__PURE__ */ jsxRuntime.jsxs(Button, { type: "button", size: "sm", onClick: addSegment, className: "self-start", children: [
|
|
4269
|
+
/* @__PURE__ */ jsxRuntime.jsx(lucideReact.Plus, { className: "h-3.5 w-3.5" }),
|
|
4270
|
+
" Add segment"
|
|
4271
|
+
] })
|
|
4272
|
+
] });
|
|
4273
|
+
}
|
|
3833
4274
|
function DividerEditor() {
|
|
3834
4275
|
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." });
|
|
3835
4276
|
}
|
|
@@ -5278,7 +5719,7 @@ var SUPPORTED_BLOCK_KINDS = /* @__PURE__ */ new Set([
|
|
|
5278
5719
|
"rich_text_preformatted"
|
|
5279
5720
|
]);
|
|
5280
5721
|
var SUPPORTED_INLINE_KINDS = /* @__PURE__ */ new Set(["text", "link", "emoji"]);
|
|
5281
|
-
var SUPPORTED_TEXT_STYLE_KEYS = /* @__PURE__ */ new Set(["bold", "italic", "strike", "code"]);
|
|
5722
|
+
var SUPPORTED_TEXT_STYLE_KEYS = /* @__PURE__ */ new Set(["bold", "italic", "strike", "underline", "code"]);
|
|
5282
5723
|
var MAX_LIST_INDENT = 8;
|
|
5283
5724
|
function detectLossy(block) {
|
|
5284
5725
|
const out = [];
|
|
@@ -5462,6 +5903,9 @@ function styleToMarks(style) {
|
|
|
5462
5903
|
if (style.strike) {
|
|
5463
5904
|
marks.push({ type: "strike" });
|
|
5464
5905
|
}
|
|
5906
|
+
if (style.underline) {
|
|
5907
|
+
marks.push({ type: "underline" });
|
|
5908
|
+
}
|
|
5465
5909
|
if (style.code) {
|
|
5466
5910
|
marks.push({ type: "code" });
|
|
5467
5911
|
}
|
|
@@ -5608,6 +6052,9 @@ function marksToStyle(marks) {
|
|
|
5608
6052
|
if (m.type === "strike") {
|
|
5609
6053
|
style.strike = true;
|
|
5610
6054
|
}
|
|
6055
|
+
if (m.type === "underline") {
|
|
6056
|
+
style.underline = true;
|
|
6057
|
+
}
|
|
5611
6058
|
if (m.type === "code") {
|
|
5612
6059
|
style.code = true;
|
|
5613
6060
|
}
|
|
@@ -5695,7 +6142,7 @@ var INLINE_LABEL = {
|
|
|
5695
6142
|
broadcast: "Broadcast",
|
|
5696
6143
|
usergroup: "User group"
|
|
5697
6144
|
};
|
|
5698
|
-
var STYLE_KEYS = ["bold", "italic", "strike", "code"];
|
|
6145
|
+
var STYLE_KEYS = ["bold", "italic", "strike", "underline", "code"];
|
|
5699
6146
|
function RichTextStructuredEditor({ block, onChange }) {
|
|
5700
6147
|
const elements = block.elements ?? [];
|
|
5701
6148
|
const replaceElements = (next) => {
|
|
@@ -6374,6 +6821,15 @@ function Toolbar({ editor }) {
|
|
|
6374
6821
|
Icon: lucideReact.Strikethrough
|
|
6375
6822
|
}
|
|
6376
6823
|
),
|
|
6824
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
6825
|
+
ToolbarButton,
|
|
6826
|
+
{
|
|
6827
|
+
label: "Underline",
|
|
6828
|
+
active: editor.isActive("underline"),
|
|
6829
|
+
onClick: () => editor.chain().focus().toggleUnderline().run(),
|
|
6830
|
+
Icon: lucideReact.Underline
|
|
6831
|
+
}
|
|
6832
|
+
),
|
|
6377
6833
|
/* @__PURE__ */ jsxRuntime.jsx(
|
|
6378
6834
|
ToolbarButton,
|
|
6379
6835
|
{
|
|
@@ -7256,6 +7712,8 @@ function dispatch(block, onChange) {
|
|
|
7256
7712
|
return /* @__PURE__ */ jsxRuntime.jsx(PlanEditor, { block, onChange: (next) => onChange(next) });
|
|
7257
7713
|
case "task_card":
|
|
7258
7714
|
return /* @__PURE__ */ jsxRuntime.jsx(TaskCardEditor, { block, onChange: (next) => onChange(next) });
|
|
7715
|
+
case "data_visualization":
|
|
7716
|
+
return /* @__PURE__ */ jsxRuntime.jsx(DataVisualizationEditor, { block, onChange: (next) => onChange(next) });
|
|
7259
7717
|
default:
|
|
7260
7718
|
return null;
|
|
7261
7719
|
}
|
|
@@ -7331,7 +7789,8 @@ var BLOCK_TYPE_LABELS = {
|
|
|
7331
7789
|
input: "Input",
|
|
7332
7790
|
video: "Video",
|
|
7333
7791
|
plan: "Plan",
|
|
7334
|
-
task_card: "Task Card"
|
|
7792
|
+
task_card: "Task Card",
|
|
7793
|
+
data_visualization: "Data Visualization"
|
|
7335
7794
|
};
|
|
7336
7795
|
function BlockRow({
|
|
7337
7796
|
builderBlock,
|
|
@@ -7944,7 +8403,8 @@ function Toolbar2({
|
|
|
7944
8403
|
allowedSurfaces,
|
|
7945
8404
|
showThemeControl = true,
|
|
7946
8405
|
docsLink,
|
|
7947
|
-
errorCount
|
|
8406
|
+
errorCount,
|
|
8407
|
+
sendButtonLabel = "Send"
|
|
7948
8408
|
}) {
|
|
7949
8409
|
const activeTheme = THEME_OPTIONS.find((t) => t.value === previewTheme) ?? THEME_OPTIONS[0];
|
|
7950
8410
|
const activeSurface = SURFACE_OPTIONS.find((s) => s.value === previewSurface) ?? SURFACE_OPTIONS[0];
|
|
@@ -8034,7 +8494,7 @@ function Toolbar2({
|
|
|
8034
8494
|
variant: "ghost",
|
|
8035
8495
|
size: "sm",
|
|
8036
8496
|
onClick: onOpenIssues,
|
|
8037
|
-
className: "text-
|
|
8497
|
+
className: "border border-red-200! bg-red-50 text-red-700 hover:bg-red-100 hover:text-red-700",
|
|
8038
8498
|
"aria-label": `${errorCount} ${errorCount === 1 ? "issue" : "issues"}`,
|
|
8039
8499
|
children: [
|
|
8040
8500
|
/* @__PURE__ */ jsxRuntime.jsx(lucideReact.AlertTriangle, { className: "h-3.5 w-3.5" }),
|
|
@@ -8127,9 +8587,9 @@ function Toolbar2({
|
|
|
8127
8587
|
) : null
|
|
8128
8588
|
] }) })
|
|
8129
8589
|
] }),
|
|
8130
|
-
/* @__PURE__ */ jsxRuntime.jsxs(Button, { type: "button", size: "sm", onClick: onOpenSend, disabled: !canSend, "aria-label":
|
|
8590
|
+
/* @__PURE__ */ jsxRuntime.jsxs(Button, { type: "button", size: "sm", onClick: onOpenSend, disabled: !canSend, "aria-label": sendButtonLabel, children: [
|
|
8131
8591
|
/* @__PURE__ */ jsxRuntime.jsx(lucideReact.Send, { className: "h-3.5 w-3.5" }),
|
|
8132
|
-
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "hidden sm:inline", children:
|
|
8592
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "hidden sm:inline", children: sendButtonLabel })
|
|
8133
8593
|
] })
|
|
8134
8594
|
] })
|
|
8135
8595
|
] });
|
|
@@ -8255,6 +8715,9 @@ function BlockKitchen(props) {
|
|
|
8255
8715
|
showThemeControl = true,
|
|
8256
8716
|
docsLink,
|
|
8257
8717
|
defaultPreviewTheme = "light",
|
|
8718
|
+
previewTheme: controlledPreviewTheme,
|
|
8719
|
+
sendButtonLabel,
|
|
8720
|
+
confirmSendLabel,
|
|
8258
8721
|
theme
|
|
8259
8722
|
} = props;
|
|
8260
8723
|
const paletteSections = React.useMemo(() => {
|
|
@@ -8282,7 +8745,9 @@ function BlockKitchen(props) {
|
|
|
8282
8745
|
const [issuesOpen, setIssuesOpen] = React.useState(false);
|
|
8283
8746
|
const [paletteOpen, setPaletteOpen] = React.useState(false);
|
|
8284
8747
|
const [openBlockId, setOpenBlockId] = React.useState(null);
|
|
8285
|
-
const [
|
|
8748
|
+
const [uncontrolledPreviewTheme, setUncontrolledPreviewTheme] = React.useState(defaultPreviewTheme);
|
|
8749
|
+
const isPreviewThemeControlled = controlledPreviewTheme !== void 0;
|
|
8750
|
+
const previewTheme = controlledPreviewTheme ?? uncontrolledPreviewTheme;
|
|
8286
8751
|
const [previewSurface, setPreviewSurface] = React.useState(allowedSurfaces[0]);
|
|
8287
8752
|
const [activePaletteVariantId, setActivePaletteVariantId] = React.useState(null);
|
|
8288
8753
|
const isMobile = useIsMobile();
|
|
@@ -8364,12 +8829,13 @@ function BlockKitchen(props) {
|
|
|
8364
8829
|
canClear: blocks.length > 0,
|
|
8365
8830
|
errorCount: validation.total,
|
|
8366
8831
|
previewTheme,
|
|
8367
|
-
onPreviewThemeChange:
|
|
8832
|
+
onPreviewThemeChange: setUncontrolledPreviewTheme,
|
|
8368
8833
|
previewSurface,
|
|
8369
8834
|
onPreviewSurfaceChange: setPreviewSurface,
|
|
8370
8835
|
allowedSurfaces,
|
|
8371
|
-
showThemeControl,
|
|
8372
|
-
docsLink
|
|
8836
|
+
showThemeControl: isPreviewThemeControlled ? false : showThemeControl,
|
|
8837
|
+
docsLink,
|
|
8838
|
+
sendButtonLabel
|
|
8373
8839
|
}
|
|
8374
8840
|
),
|
|
8375
8841
|
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex min-h-0 flex-1 items-stretch", children: [
|
|
@@ -8445,6 +8911,7 @@ function BlockKitchen(props) {
|
|
|
8445
8911
|
loadChannels,
|
|
8446
8912
|
loadSendAsUserStatus,
|
|
8447
8913
|
onSend,
|
|
8914
|
+
confirmSendLabel,
|
|
8448
8915
|
errorCount: validation.total,
|
|
8449
8916
|
onShowIssues: () => {
|
|
8450
8917
|
setSendOpen(false);
|