@tightknitai/block-kitchen 0.8.6 → 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.
@@ -1,5 +1,5 @@
1
- import { u as SupportedBlock } from './palette-DToUE_3J.cjs';
2
- export { v as SupportedBlockType } from './palette-DToUE_3J.cjs';
1
+ import { J as SupportedBlock } from './palette-WZCUVJTn.cjs';
2
+ export { K as SupportedBlockType } from './palette-WZCUVJTn.cjs';
3
3
  import 'react';
4
4
  import 'slack-web-api-client';
5
5
 
package/dist/helpers.d.ts CHANGED
@@ -1,5 +1,5 @@
1
- import { u as SupportedBlock } from './palette-DToUE_3J.js';
2
- export { v as SupportedBlockType } from './palette-DToUE_3J.js';
1
+ import { J as SupportedBlock } from './palette-WZCUVJTn.js';
2
+ export { K as SupportedBlockType } from './palette-WZCUVJTn.js';
3
3
  import 'react';
4
4
  import 'slack-web-api-client';
5
5
 
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) {
@@ -3844,6 +3983,294 @@ function ImageItemCard({
3844
3983
  ) })
3845
3984
  ] });
3846
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
+ }
3847
4274
  function DividerEditor() {
3848
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." });
3849
4276
  }
@@ -5292,7 +5719,7 @@ var SUPPORTED_BLOCK_KINDS = /* @__PURE__ */ new Set([
5292
5719
  "rich_text_preformatted"
5293
5720
  ]);
5294
5721
  var SUPPORTED_INLINE_KINDS = /* @__PURE__ */ new Set(["text", "link", "emoji"]);
5295
- 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"]);
5296
5723
  var MAX_LIST_INDENT = 8;
5297
5724
  function detectLossy(block) {
5298
5725
  const out = [];
@@ -5476,6 +5903,9 @@ function styleToMarks(style) {
5476
5903
  if (style.strike) {
5477
5904
  marks.push({ type: "strike" });
5478
5905
  }
5906
+ if (style.underline) {
5907
+ marks.push({ type: "underline" });
5908
+ }
5479
5909
  if (style.code) {
5480
5910
  marks.push({ type: "code" });
5481
5911
  }
@@ -5622,6 +6052,9 @@ function marksToStyle(marks) {
5622
6052
  if (m.type === "strike") {
5623
6053
  style.strike = true;
5624
6054
  }
6055
+ if (m.type === "underline") {
6056
+ style.underline = true;
6057
+ }
5625
6058
  if (m.type === "code") {
5626
6059
  style.code = true;
5627
6060
  }
@@ -5709,7 +6142,7 @@ var INLINE_LABEL = {
5709
6142
  broadcast: "Broadcast",
5710
6143
  usergroup: "User group"
5711
6144
  };
5712
- var STYLE_KEYS = ["bold", "italic", "strike", "code"];
6145
+ var STYLE_KEYS = ["bold", "italic", "strike", "underline", "code"];
5713
6146
  function RichTextStructuredEditor({ block, onChange }) {
5714
6147
  const elements = block.elements ?? [];
5715
6148
  const replaceElements = (next) => {
@@ -6388,6 +6821,15 @@ function Toolbar({ editor }) {
6388
6821
  Icon: lucideReact.Strikethrough
6389
6822
  }
6390
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
+ ),
6391
6833
  /* @__PURE__ */ jsxRuntime.jsx(
6392
6834
  ToolbarButton,
6393
6835
  {
@@ -7270,6 +7712,8 @@ function dispatch(block, onChange) {
7270
7712
  return /* @__PURE__ */ jsxRuntime.jsx(PlanEditor, { block, onChange: (next) => onChange(next) });
7271
7713
  case "task_card":
7272
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) });
7273
7717
  default:
7274
7718
  return null;
7275
7719
  }
@@ -7345,7 +7789,8 @@ var BLOCK_TYPE_LABELS = {
7345
7789
  input: "Input",
7346
7790
  video: "Video",
7347
7791
  plan: "Plan",
7348
- task_card: "Task Card"
7792
+ task_card: "Task Card",
7793
+ data_visualization: "Data Visualization"
7349
7794
  };
7350
7795
  function BlockRow({
7351
7796
  builderBlock,