@tightknitai/block-kitchen 0.10.19 → 0.10.21
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 +13 -4
- package/dist/helpers.d.cts +2 -2
- package/dist/helpers.d.ts +2 -2
- package/dist/index.cjs +748 -231
- 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 +749 -232
- package/dist/index.js.map +1 -1
- package/dist/{palette-DNUiqoQK.d.cts → palette-CXXqlwIH.d.cts} +82 -15
- package/dist/{palette-DNUiqoQK.d.ts → palette-CXXqlwIH.d.ts} +82 -15
- package/dist/palette.cjs +52 -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 +52 -0
- package/dist/palette.js.map +1 -1
- package/dist/styles.css +1 -1
- package/package.json +4 -3
package/dist/index.cjs
CHANGED
|
@@ -22,6 +22,7 @@ var RadioGroupPrimitive = require('@radix-ui/react-radio-group');
|
|
|
22
22
|
var Link = require('@tiptap/extension-link');
|
|
23
23
|
var react = require('@tiptap/react');
|
|
24
24
|
var StarterKit = require('@tiptap/starter-kit');
|
|
25
|
+
var state = require('@tiptap/pm/state');
|
|
25
26
|
var suggestion = require('@tiptap/suggestion');
|
|
26
27
|
|
|
27
28
|
function _interopDefault (e) { return e && e.__esModule ? e : { default: e }; }
|
|
@@ -1096,6 +1097,58 @@ var defaultPalette = [
|
|
|
1096
1097
|
]
|
|
1097
1098
|
]
|
|
1098
1099
|
})
|
|
1100
|
+
},
|
|
1101
|
+
{
|
|
1102
|
+
// Slack's documented example.
|
|
1103
|
+
id: "data_table_basic",
|
|
1104
|
+
label: "Data table",
|
|
1105
|
+
factory: () => ({
|
|
1106
|
+
type: "data_table",
|
|
1107
|
+
caption: "A Fabulous Table",
|
|
1108
|
+
rows: [
|
|
1109
|
+
[
|
|
1110
|
+
{ type: "raw_text", text: "Name" },
|
|
1111
|
+
{ type: "raw_text", text: "Department" },
|
|
1112
|
+
{ type: "raw_text", text: "Badge" }
|
|
1113
|
+
],
|
|
1114
|
+
[
|
|
1115
|
+
{ type: "raw_text", text: "Data Refinement Department" },
|
|
1116
|
+
{ type: "raw_text", text: "MDR" },
|
|
1117
|
+
{
|
|
1118
|
+
type: "rich_text",
|
|
1119
|
+
elements: [
|
|
1120
|
+
{ type: "rich_text_section", elements: [{ type: "text", text: "Blue", style: { bold: true } }] }
|
|
1121
|
+
]
|
|
1122
|
+
}
|
|
1123
|
+
],
|
|
1124
|
+
[
|
|
1125
|
+
{ type: "raw_text", text: "Art Sourcing Department" },
|
|
1126
|
+
{ type: "raw_text", text: "O&D" },
|
|
1127
|
+
{
|
|
1128
|
+
type: "rich_text",
|
|
1129
|
+
elements: [
|
|
1130
|
+
{
|
|
1131
|
+
type: "rich_text_section",
|
|
1132
|
+
elements: [
|
|
1133
|
+
{ type: "text", text: "Green " },
|
|
1134
|
+
{ type: "text", text: "review", style: { italic: true } }
|
|
1135
|
+
]
|
|
1136
|
+
}
|
|
1137
|
+
]
|
|
1138
|
+
}
|
|
1139
|
+
],
|
|
1140
|
+
[
|
|
1141
|
+
{ type: "raw_text", text: "Wellness Department" },
|
|
1142
|
+
{ type: "raw_text", text: "Wellness Center" },
|
|
1143
|
+
{
|
|
1144
|
+
type: "rich_text",
|
|
1145
|
+
elements: [
|
|
1146
|
+
{ type: "rich_text_section", elements: [{ type: "text", text: "Limited", style: { bold: true } }] }
|
|
1147
|
+
]
|
|
1148
|
+
}
|
|
1149
|
+
]
|
|
1150
|
+
]
|
|
1151
|
+
})
|
|
1099
1152
|
}
|
|
1100
1153
|
]
|
|
1101
1154
|
},
|
|
@@ -1760,6 +1813,8 @@ function labelForBlockType(type) {
|
|
|
1760
1813
|
return "Data Visualization";
|
|
1761
1814
|
case "container":
|
|
1762
1815
|
return "Container";
|
|
1816
|
+
case "data_table":
|
|
1817
|
+
return "Data Table";
|
|
1763
1818
|
}
|
|
1764
1819
|
}
|
|
1765
1820
|
var Sheet = DialogPrimitive__namespace.Root;
|
|
@@ -5220,15 +5275,16 @@ function makeEmojiImportResolver(customByName, index = getEmojiIndex()) {
|
|
|
5220
5275
|
|
|
5221
5276
|
// src/lib/rich-text-tiptap.ts
|
|
5222
5277
|
var USER_MENTION_NODE = "userMention";
|
|
5278
|
+
var CHANNEL_MENTION_NODE = "channelMention";
|
|
5223
5279
|
var SUPPORTED_BLOCK_KINDS = /* @__PURE__ */ new Set([
|
|
5224
5280
|
"rich_text_section",
|
|
5225
5281
|
"rich_text_list",
|
|
5226
5282
|
"rich_text_quote",
|
|
5227
5283
|
"rich_text_preformatted"
|
|
5228
5284
|
]);
|
|
5229
|
-
var SUPPORTED_INLINE_KINDS = /* @__PURE__ */ new Set(["text", "link", "emoji", "user"]);
|
|
5285
|
+
var SUPPORTED_INLINE_KINDS = /* @__PURE__ */ new Set(["text", "link", "emoji", "user", "channel"]);
|
|
5230
5286
|
var SUPPORTED_TEXT_STYLE_KEYS = /* @__PURE__ */ new Set(["bold", "italic", "strike", "underline", "code"]);
|
|
5231
|
-
var
|
|
5287
|
+
var SUPPORTED_MENTION_STYLE_KEYS = /* @__PURE__ */ new Set(["bold", "italic", "strike", "underline"]);
|
|
5232
5288
|
var MAX_LIST_INDENT = 8;
|
|
5233
5289
|
function detectLossy(block) {
|
|
5234
5290
|
const out = [];
|
|
@@ -5283,10 +5339,13 @@ function scanInlines(inlines, where, out) {
|
|
|
5283
5339
|
}
|
|
5284
5340
|
}
|
|
5285
5341
|
}
|
|
5286
|
-
if (inline.type === "user") {
|
|
5342
|
+
if (inline.type === "user" || inline.type === "channel") {
|
|
5343
|
+
if (inline.type === "channel" && !inline.channel_id) {
|
|
5344
|
+
out.push({ label: "Channel without id", where: sub });
|
|
5345
|
+
}
|
|
5287
5346
|
for (const k of Object.keys(inline.style ?? {})) {
|
|
5288
|
-
if (!
|
|
5289
|
-
out.push({ label:
|
|
5347
|
+
if (!SUPPORTED_MENTION_STYLE_KEYS.has(k)) {
|
|
5348
|
+
out.push({ label: `${inline.type === "channel" ? "Channel" : "Mention"} style: ${k}`, where: sub });
|
|
5290
5349
|
}
|
|
5291
5350
|
}
|
|
5292
5351
|
}
|
|
@@ -5412,6 +5471,20 @@ function inlinesToPM(inlines, resolveEmoji) {
|
|
|
5412
5471
|
node.marks = marks;
|
|
5413
5472
|
}
|
|
5414
5473
|
out.push(node);
|
|
5474
|
+
} else if (inline.type === "channel") {
|
|
5475
|
+
const channel = inline;
|
|
5476
|
+
if (!channel.channel_id) {
|
|
5477
|
+
continue;
|
|
5478
|
+
}
|
|
5479
|
+
const node = {
|
|
5480
|
+
type: CHANNEL_MENTION_NODE,
|
|
5481
|
+
attrs: { channelId: channel.channel_id, name: null }
|
|
5482
|
+
};
|
|
5483
|
+
const marks = styleToMarks(channel.style);
|
|
5484
|
+
if (marks.length > 0) {
|
|
5485
|
+
node.marks = marks;
|
|
5486
|
+
}
|
|
5487
|
+
out.push(node);
|
|
5415
5488
|
} else if (inline.type === "link") {
|
|
5416
5489
|
const link = inline;
|
|
5417
5490
|
const text = link.text || link.url || "";
|
|
@@ -5551,13 +5624,26 @@ function proseMirrorInlinesToRichTextElements(nodes) {
|
|
|
5551
5624
|
continue;
|
|
5552
5625
|
}
|
|
5553
5626
|
const user = { type: "user", user_id: userId };
|
|
5554
|
-
const style2 =
|
|
5627
|
+
const style2 = mentionStyle(node.marks ?? []);
|
|
5555
5628
|
if (Object.keys(style2).length > 0) {
|
|
5556
5629
|
user.style = style2;
|
|
5557
5630
|
}
|
|
5558
5631
|
out.push(user);
|
|
5559
5632
|
continue;
|
|
5560
5633
|
}
|
|
5634
|
+
if (node.type === CHANNEL_MENTION_NODE) {
|
|
5635
|
+
const channelId = String(node.attrs?.channelId ?? "");
|
|
5636
|
+
if (!channelId) {
|
|
5637
|
+
continue;
|
|
5638
|
+
}
|
|
5639
|
+
const channel = { type: "channel", channel_id: channelId };
|
|
5640
|
+
const style2 = mentionStyle(node.marks ?? []);
|
|
5641
|
+
if (Object.keys(style2).length > 0) {
|
|
5642
|
+
channel.style = style2;
|
|
5643
|
+
}
|
|
5644
|
+
out.push(channel);
|
|
5645
|
+
continue;
|
|
5646
|
+
}
|
|
5561
5647
|
if (node.type === "hardBreak") {
|
|
5562
5648
|
out.push({ type: "text", text: "\n" });
|
|
5563
5649
|
continue;
|
|
@@ -5612,10 +5698,10 @@ function marksToStyle(marks) {
|
|
|
5612
5698
|
}
|
|
5613
5699
|
return style;
|
|
5614
5700
|
}
|
|
5615
|
-
function
|
|
5701
|
+
function mentionStyle(marks) {
|
|
5616
5702
|
const style = {};
|
|
5617
5703
|
for (const [key, value] of Object.entries(marksToStyle(marks))) {
|
|
5618
|
-
if (
|
|
5704
|
+
if (SUPPORTED_MENTION_STYLE_KEYS.has(key)) {
|
|
5619
5705
|
style[key] = value;
|
|
5620
5706
|
}
|
|
5621
5707
|
}
|
|
@@ -5644,50 +5730,52 @@ function sameStyle(a, b) {
|
|
|
5644
5730
|
}
|
|
5645
5731
|
return ak.every((k, i) => k === bk[i]);
|
|
5646
5732
|
}
|
|
5647
|
-
function
|
|
5648
|
-
|
|
5649
|
-
const label = `:${name}:`;
|
|
5650
|
-
return /* @__PURE__ */ jsxRuntime.jsx(react.NodeViewWrapper, { as: "span", className: "bk-emoji-node", "data-emoji": name, title: label, children: src ? /* @__PURE__ */ jsxRuntime.jsx(
|
|
5651
|
-
"img",
|
|
5652
|
-
{
|
|
5653
|
-
src,
|
|
5654
|
-
alt: label,
|
|
5655
|
-
style: {
|
|
5656
|
-
display: "inline-block",
|
|
5657
|
-
width: "1.25em",
|
|
5658
|
-
height: "1.25em",
|
|
5659
|
-
verticalAlign: "-0.25em",
|
|
5660
|
-
objectFit: "contain"
|
|
5661
|
-
}
|
|
5662
|
-
}
|
|
5663
|
-
) : /* @__PURE__ */ jsxRuntime.jsx("span", { "aria-label": label, role: "img", children: unicode ? codepointsToGlyph(unicode) : label }) });
|
|
5733
|
+
function channelMentionLabel(attrs, getChannelName) {
|
|
5734
|
+
return getChannelName?.(attrs.channelId) ?? attrs.name ?? attrs.channelId;
|
|
5664
5735
|
}
|
|
5665
|
-
|
|
5666
|
-
|
|
5736
|
+
function ChannelMentionNodeView({ node }) {
|
|
5737
|
+
const mentions = useMentions();
|
|
5738
|
+
const attrs = node.attrs;
|
|
5739
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(react.NodeViewWrapper, { as: "span", className: "bk-channel-mention", "data-channel-mention": attrs.channelId, children: [
|
|
5740
|
+
"#",
|
|
5741
|
+
channelMentionLabel(attrs, mentions?.getChannelName)
|
|
5742
|
+
] });
|
|
5743
|
+
}
|
|
5744
|
+
var ChannelMentionNode = react.Node.create({
|
|
5745
|
+
name: CHANNEL_MENTION_NODE,
|
|
5667
5746
|
group: "inline",
|
|
5668
5747
|
inline: true,
|
|
5669
5748
|
atom: true,
|
|
5670
5749
|
selectable: true,
|
|
5671
5750
|
addAttributes() {
|
|
5672
5751
|
return {
|
|
5673
|
-
|
|
5674
|
-
|
|
5675
|
-
|
|
5676
|
-
|
|
5752
|
+
channelId: {
|
|
5753
|
+
default: "",
|
|
5754
|
+
parseHTML: (element) => element.getAttribute("data-channel-mention") ?? "",
|
|
5755
|
+
renderHTML: (attributes) => ({ "data-channel-mention": attributes.channelId })
|
|
5756
|
+
},
|
|
5757
|
+
name: {
|
|
5758
|
+
default: null,
|
|
5759
|
+
parseHTML: (element) => element.getAttribute("data-channel-name"),
|
|
5760
|
+
renderHTML: (attributes) => attributes.name ? { "data-channel-name": attributes.name } : {}
|
|
5761
|
+
}
|
|
5677
5762
|
};
|
|
5678
5763
|
},
|
|
5679
5764
|
parseHTML() {
|
|
5680
|
-
return [{ tag: "span[data-
|
|
5765
|
+
return [{ tag: "span[data-channel-mention]" }];
|
|
5681
5766
|
},
|
|
5682
|
-
renderHTML({ HTMLAttributes }) {
|
|
5683
|
-
|
|
5684
|
-
|
|
5767
|
+
renderHTML({ node, HTMLAttributes }) {
|
|
5768
|
+
return ["span", react.mergeAttributes(HTMLAttributes), `#${channelMentionLabel(node.attrs)}`];
|
|
5769
|
+
},
|
|
5770
|
+
renderText({ node }) {
|
|
5771
|
+
return `#${channelMentionLabel(node.attrs)}`;
|
|
5685
5772
|
},
|
|
5686
5773
|
addNodeView() {
|
|
5687
|
-
return react.ReactNodeViewRenderer(
|
|
5774
|
+
return react.ReactNodeViewRenderer(ChannelMentionNodeView);
|
|
5688
5775
|
}
|
|
5689
5776
|
});
|
|
5690
5777
|
var MENTION_SEARCH_DEBOUNCE_MS = 200;
|
|
5778
|
+
var USER_MENTION_SUGGESTION_PLUGIN_KEY = new state.PluginKey("userMentionSuggestion");
|
|
5691
5779
|
function insertUserMention(editor, range, user) {
|
|
5692
5780
|
const to = editor.state.doc.textBetween(range.to, Math.min(range.to + 1, editor.state.doc.content.size)) === " " ? range.to + 1 : range.to;
|
|
5693
5781
|
editor.chain().focus().insertContentAt({ from: range.from, to }, [
|
|
@@ -5696,13 +5784,16 @@ function insertUserMention(editor, range, user) {
|
|
|
5696
5784
|
]).run();
|
|
5697
5785
|
}
|
|
5698
5786
|
function insertMentionTrigger(editor) {
|
|
5787
|
+
insertSuggestionTrigger(editor, "@");
|
|
5788
|
+
}
|
|
5789
|
+
function insertSuggestionTrigger(editor, char) {
|
|
5699
5790
|
const { from } = editor.state.selection;
|
|
5700
5791
|
const before = from > 1 ? editor.state.doc.textBetween(from - 1, from, void 0, "\uFFFC") : "";
|
|
5701
5792
|
const needsSpace = before !== "" && !/\s/.test(before);
|
|
5702
|
-
editor.chain().focus().insertContent(needsSpace ?
|
|
5793
|
+
editor.chain().focus().insertContent(needsSpace ? ` ${char}` : char).run();
|
|
5703
5794
|
}
|
|
5704
5795
|
function dismissMentionSuggestion(editor) {
|
|
5705
|
-
suggestion.exitSuggestion(editor.view);
|
|
5796
|
+
suggestion.exitSuggestion(editor.view, USER_MENTION_SUGGESTION_PLUGIN_KEY);
|
|
5706
5797
|
}
|
|
5707
5798
|
var MentionSuggestion = react.Extension.create({
|
|
5708
5799
|
name: "userMentionSuggestion",
|
|
@@ -5718,6 +5809,7 @@ var MentionSuggestion = react.Extension.create({
|
|
|
5718
5809
|
return [
|
|
5719
5810
|
suggestion.Suggestion({
|
|
5720
5811
|
editor: this.editor,
|
|
5812
|
+
pluginKey: USER_MENTION_SUGGESTION_PLUGIN_KEY,
|
|
5721
5813
|
char: "@",
|
|
5722
5814
|
debounce: MENTION_SEARCH_DEBOUNCE_MS,
|
|
5723
5815
|
allow: () => isEnabled(),
|
|
@@ -5728,6 +5820,90 @@ var MentionSuggestion = react.Extension.create({
|
|
|
5728
5820
|
];
|
|
5729
5821
|
}
|
|
5730
5822
|
});
|
|
5823
|
+
|
|
5824
|
+
// src/lib/tiptap-channel-suggestion.ts
|
|
5825
|
+
var CHANNEL_MENTION_SUGGESTION_PLUGIN_KEY = new state.PluginKey("channelMentionSuggestion");
|
|
5826
|
+
function insertChannelMention(editor, range, channel) {
|
|
5827
|
+
const to = editor.state.doc.textBetween(range.to, Math.min(range.to + 1, editor.state.doc.content.size)) === " " ? range.to + 1 : range.to;
|
|
5828
|
+
editor.chain().focus().insertContentAt({ from: range.from, to }, [
|
|
5829
|
+
{ type: CHANNEL_MENTION_NODE, attrs: { channelId: channel.id, name: channel.name } },
|
|
5830
|
+
{ type: "text", text: " " }
|
|
5831
|
+
]).run();
|
|
5832
|
+
}
|
|
5833
|
+
function insertChannelTrigger(editor) {
|
|
5834
|
+
insertSuggestionTrigger(editor, "#");
|
|
5835
|
+
}
|
|
5836
|
+
function dismissChannelSuggestion(editor) {
|
|
5837
|
+
suggestion.exitSuggestion(editor.view, CHANNEL_MENTION_SUGGESTION_PLUGIN_KEY);
|
|
5838
|
+
}
|
|
5839
|
+
var ChannelSuggestion = react.Extension.create({
|
|
5840
|
+
name: "channelMentionSuggestion",
|
|
5841
|
+
addOptions() {
|
|
5842
|
+
return {
|
|
5843
|
+
isEnabled: () => false,
|
|
5844
|
+
search: async () => [],
|
|
5845
|
+
render: () => ({})
|
|
5846
|
+
};
|
|
5847
|
+
},
|
|
5848
|
+
addProseMirrorPlugins() {
|
|
5849
|
+
const { isEnabled, search, render } = this.options;
|
|
5850
|
+
return [
|
|
5851
|
+
suggestion.Suggestion({
|
|
5852
|
+
editor: this.editor,
|
|
5853
|
+
pluginKey: CHANNEL_MENTION_SUGGESTION_PLUGIN_KEY,
|
|
5854
|
+
char: "#",
|
|
5855
|
+
debounce: MENTION_SEARCH_DEBOUNCE_MS,
|
|
5856
|
+
allow: () => isEnabled(),
|
|
5857
|
+
items: ({ query, signal }) => search(query, signal),
|
|
5858
|
+
command: ({ editor, range, props }) => insertChannelMention(editor, range, props),
|
|
5859
|
+
render
|
|
5860
|
+
})
|
|
5861
|
+
];
|
|
5862
|
+
}
|
|
5863
|
+
});
|
|
5864
|
+
function EmojiNodeView({ node }) {
|
|
5865
|
+
const { name, src, unicode } = node.attrs;
|
|
5866
|
+
const label = `:${name}:`;
|
|
5867
|
+
return /* @__PURE__ */ jsxRuntime.jsx(react.NodeViewWrapper, { as: "span", className: "bk-emoji-node", "data-emoji": name, title: label, children: src ? /* @__PURE__ */ jsxRuntime.jsx(
|
|
5868
|
+
"img",
|
|
5869
|
+
{
|
|
5870
|
+
src,
|
|
5871
|
+
alt: label,
|
|
5872
|
+
style: {
|
|
5873
|
+
display: "inline-block",
|
|
5874
|
+
width: "1.25em",
|
|
5875
|
+
height: "1.25em",
|
|
5876
|
+
verticalAlign: "-0.25em",
|
|
5877
|
+
objectFit: "contain"
|
|
5878
|
+
}
|
|
5879
|
+
}
|
|
5880
|
+
) : /* @__PURE__ */ jsxRuntime.jsx("span", { "aria-label": label, role: "img", children: unicode ? codepointsToGlyph(unicode) : label }) });
|
|
5881
|
+
}
|
|
5882
|
+
var EmojiNode = react.Node.create({
|
|
5883
|
+
name: "emoji",
|
|
5884
|
+
group: "inline",
|
|
5885
|
+
inline: true,
|
|
5886
|
+
atom: true,
|
|
5887
|
+
selectable: true,
|
|
5888
|
+
addAttributes() {
|
|
5889
|
+
return {
|
|
5890
|
+
name: { default: "" },
|
|
5891
|
+
src: { default: null },
|
|
5892
|
+
unicode: { default: null },
|
|
5893
|
+
skinTone: { default: null }
|
|
5894
|
+
};
|
|
5895
|
+
},
|
|
5896
|
+
parseHTML() {
|
|
5897
|
+
return [{ tag: "span[data-emoji]" }];
|
|
5898
|
+
},
|
|
5899
|
+
renderHTML({ HTMLAttributes }) {
|
|
5900
|
+
const name = HTMLAttributes.name ?? "";
|
|
5901
|
+
return ["span", react.mergeAttributes({ "data-emoji": name }, HTMLAttributes), `:${name}:`];
|
|
5902
|
+
},
|
|
5903
|
+
addNodeView() {
|
|
5904
|
+
return react.ReactNodeViewRenderer(EmojiNodeView);
|
|
5905
|
+
}
|
|
5906
|
+
});
|
|
5731
5907
|
function userMentionLabel(attrs, getUserName) {
|
|
5732
5908
|
return getUserName?.(attrs.userId) ?? attrs.name ?? attrs.userId;
|
|
5733
5909
|
}
|
|
@@ -6063,6 +6239,7 @@ function nextMentionPickerState(props, prev) {
|
|
|
6063
6239
|
}
|
|
6064
6240
|
function MentionPicker({
|
|
6065
6241
|
editor,
|
|
6242
|
+
kind,
|
|
6066
6243
|
state,
|
|
6067
6244
|
keyHandlerRef,
|
|
6068
6245
|
onDismiss
|
|
@@ -6075,6 +6252,27 @@ function MentionPicker({
|
|
|
6075
6252
|
setActiveIndex(0);
|
|
6076
6253
|
}
|
|
6077
6254
|
const listRef = React.useRef(null);
|
|
6255
|
+
const listboxId = React.useId();
|
|
6256
|
+
const activeOptionId = items[activeIndex] ? `${listboxId}-${activeIndex}` : void 0;
|
|
6257
|
+
React.useEffect(() => {
|
|
6258
|
+
const root = editor.view.dom;
|
|
6259
|
+
root.setAttribute("role", "combobox");
|
|
6260
|
+
root.setAttribute("aria-autocomplete", "list");
|
|
6261
|
+
root.setAttribute("aria-expanded", "true");
|
|
6262
|
+
root.setAttribute("aria-controls", listboxId);
|
|
6263
|
+
if (activeOptionId) {
|
|
6264
|
+
root.setAttribute("aria-activedescendant", activeOptionId);
|
|
6265
|
+
} else {
|
|
6266
|
+
root.removeAttribute("aria-activedescendant");
|
|
6267
|
+
}
|
|
6268
|
+
return () => {
|
|
6269
|
+
root.removeAttribute("role");
|
|
6270
|
+
root.removeAttribute("aria-autocomplete");
|
|
6271
|
+
root.removeAttribute("aria-expanded");
|
|
6272
|
+
root.removeAttribute("aria-controls");
|
|
6273
|
+
root.removeAttribute("aria-activedescendant");
|
|
6274
|
+
};
|
|
6275
|
+
}, [activeOptionId, editor, listboxId]);
|
|
6078
6276
|
React.useEffect(() => {
|
|
6079
6277
|
keyHandlerRef.current = (event) => {
|
|
6080
6278
|
if (event.key === "ArrowDown" || event.key === "ArrowUp") {
|
|
@@ -6085,11 +6283,11 @@ function MentionPicker({
|
|
|
6085
6283
|
return true;
|
|
6086
6284
|
}
|
|
6087
6285
|
if (event.key === "Enter" || event.key === "Tab") {
|
|
6088
|
-
const
|
|
6089
|
-
if (!
|
|
6286
|
+
const item = items[activeIndex];
|
|
6287
|
+
if (!item) {
|
|
6090
6288
|
return false;
|
|
6091
6289
|
}
|
|
6092
|
-
command(
|
|
6290
|
+
command(item);
|
|
6093
6291
|
return true;
|
|
6094
6292
|
}
|
|
6095
6293
|
return false;
|
|
@@ -6136,29 +6334,39 @@ function MentionPicker({
|
|
|
6136
6334
|
e.preventDefault();
|
|
6137
6335
|
}
|
|
6138
6336
|
},
|
|
6139
|
-
children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
6140
|
-
|
|
6141
|
-
|
|
6142
|
-
|
|
6143
|
-
|
|
6144
|
-
|
|
6145
|
-
|
|
6146
|
-
|
|
6147
|
-
|
|
6148
|
-
|
|
6149
|
-
|
|
6150
|
-
|
|
6151
|
-
|
|
6152
|
-
|
|
6153
|
-
|
|
6154
|
-
|
|
6155
|
-
|
|
6156
|
-
|
|
6157
|
-
|
|
6158
|
-
|
|
6159
|
-
|
|
6160
|
-
|
|
6161
|
-
|
|
6337
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
6338
|
+
"div",
|
|
6339
|
+
{
|
|
6340
|
+
ref: listRef,
|
|
6341
|
+
id: listboxId,
|
|
6342
|
+
role: "listbox",
|
|
6343
|
+
"aria-label": kind === "channel" ? "Channels to mention" : "People to mention",
|
|
6344
|
+
children: items.length === 0 ? /* @__PURE__ */ jsxRuntime.jsx("p", { className: "px-2 py-3 text-center text-xs text-muted-foreground", children: loading ? "Searching\u2026" : `No ${kind === "channel" ? "channels" : "people"} match that search.` }) : items.map((item, index) => (
|
|
6345
|
+
// biome-ignore lint/a11y/useFocusableInteractive: focus stays in the editor, which drives this list through the suggestion plugin's key handling.
|
|
6346
|
+
// biome-ignore lint/a11y/useKeyWithClickEvents: the keyboard path is the editor's, forwarded via keyHandlerRef.
|
|
6347
|
+
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
6348
|
+
"div",
|
|
6349
|
+
{
|
|
6350
|
+
id: `${listboxId}-${index}`,
|
|
6351
|
+
role: "option",
|
|
6352
|
+
"aria-selected": index === activeIndex,
|
|
6353
|
+
onPointerDown: (e) => e.preventDefault(),
|
|
6354
|
+
onClick: () => command(item),
|
|
6355
|
+
onMouseMove: () => setActiveIndex(index),
|
|
6356
|
+
className: cn(
|
|
6357
|
+
"flex cursor-pointer items-center gap-2 rounded-sm px-2 py-1.5 text-sm text-foreground",
|
|
6358
|
+
index === activeIndex && "bg-accent"
|
|
6359
|
+
),
|
|
6360
|
+
children: [
|
|
6361
|
+
kind === "channel" ? /* @__PURE__ */ jsxRuntime.jsx("span", { className: "flex h-5 w-5 shrink-0 items-center justify-center rounded bg-muted text-muted-foreground", children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Hash, { className: "h-3.5 w-3.5" }) }) : /* @__PURE__ */ jsxRuntime.jsx(MentionAvatar, { user: item }),
|
|
6362
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "truncate", children: kind === "channel" ? `#${item.name}` : item.name })
|
|
6363
|
+
]
|
|
6364
|
+
},
|
|
6365
|
+
item.id
|
|
6366
|
+
)
|
|
6367
|
+
))
|
|
6368
|
+
}
|
|
6369
|
+
)
|
|
6162
6370
|
}
|
|
6163
6371
|
)
|
|
6164
6372
|
]
|
|
@@ -6755,7 +6963,7 @@ function LossyBanner({ reasons }) {
|
|
|
6755
6963
|
] });
|
|
6756
6964
|
}
|
|
6757
6965
|
var RICH_TEXT_INPUT_RULE_ALLOWLIST = ["bold", "italic", "strike", "code"];
|
|
6758
|
-
function buildRichTextExtensions(mentionSuggestion) {
|
|
6966
|
+
function buildRichTextExtensions(mentionSuggestion, channelSuggestion) {
|
|
6759
6967
|
return [
|
|
6760
6968
|
StarterKit__default.default.configure({
|
|
6761
6969
|
heading: false,
|
|
@@ -6789,10 +6997,11 @@ function buildRichTextExtensions(mentionSuggestion) {
|
|
|
6789
6997
|
shouldAutoLink: hasExplicitSafeScheme,
|
|
6790
6998
|
HTMLAttributes: { rel: "noreferrer noopener", target: "_blank" }
|
|
6791
6999
|
}),
|
|
6792
|
-
// Always registered, so mentions already in the content round-trip with
|
|
6793
|
-
// or without the picker.
|
|
7000
|
+
// Always registered, so mentions already in the content round-trip with or without pickers.
|
|
6794
7001
|
UserMentionNode,
|
|
6795
|
-
|
|
7002
|
+
ChannelMentionNode,
|
|
7003
|
+
...mentionSuggestion ? [MentionSuggestion.configure(mentionSuggestion)] : [],
|
|
7004
|
+
...channelSuggestion ? [ChannelSuggestion.configure(channelSuggestion)] : []
|
|
6796
7005
|
];
|
|
6797
7006
|
}
|
|
6798
7007
|
function RichTextWysiwygEditor({ block, onChange }) {
|
|
@@ -6820,24 +7029,39 @@ function RichTextWysiwygEditor({ block, onChange }) {
|
|
|
6820
7029
|
[onChange]
|
|
6821
7030
|
);
|
|
6822
7031
|
const mentions = useMentions();
|
|
6823
|
-
const
|
|
7032
|
+
const userMentionsEnabled = mentions !== null;
|
|
7033
|
+
const channelMentionsEnabled = mentions?.searchChannels !== void 0;
|
|
6824
7034
|
const mentionsRef = React.useRef(mentions);
|
|
6825
7035
|
React.useEffect(() => {
|
|
6826
7036
|
mentionsRef.current = mentions;
|
|
6827
7037
|
}, [mentions]);
|
|
6828
7038
|
const [mentionPicker, setMentionPicker] = React.useState(null);
|
|
6829
7039
|
const mentionKeyHandlerRef = React.useRef(() => false);
|
|
7040
|
+
const [channelPicker, setChannelPicker] = React.useState(null);
|
|
7041
|
+
const channelKeyHandlerRef = React.useRef(() => false);
|
|
6830
7042
|
const editor = react.useEditor({
|
|
6831
|
-
extensions: buildRichTextExtensions(
|
|
6832
|
-
|
|
6833
|
-
|
|
6834
|
-
|
|
6835
|
-
|
|
6836
|
-
|
|
6837
|
-
|
|
6838
|
-
|
|
6839
|
-
|
|
6840
|
-
|
|
7043
|
+
extensions: buildRichTextExtensions(
|
|
7044
|
+
{
|
|
7045
|
+
isEnabled: () => mentionsRef.current !== null,
|
|
7046
|
+
search: async (query, signal) => await mentionsRef.current?.searchUsers(query, { signal }) ?? [],
|
|
7047
|
+
render: () => ({
|
|
7048
|
+
onStart: (props) => setMentionPicker((prev) => nextMentionPickerState(props, prev)),
|
|
7049
|
+
onUpdate: (props) => setMentionPicker((prev) => nextMentionPickerState(props, prev)),
|
|
7050
|
+
onExit: () => setMentionPicker(null),
|
|
7051
|
+
onKeyDown: ({ event }) => mentionKeyHandlerRef.current(event)
|
|
7052
|
+
})
|
|
7053
|
+
},
|
|
7054
|
+
{
|
|
7055
|
+
isEnabled: () => mentionsRef.current?.searchChannels !== void 0,
|
|
7056
|
+
search: async (query, signal) => await mentionsRef.current?.searchChannels?.(query, { signal }) ?? [],
|
|
7057
|
+
render: () => ({
|
|
7058
|
+
onStart: (props) => setChannelPicker((prev) => nextMentionPickerState(props, prev)),
|
|
7059
|
+
onUpdate: (props) => setChannelPicker((prev) => nextMentionPickerState(props, prev)),
|
|
7060
|
+
onExit: () => setChannelPicker(null),
|
|
7061
|
+
onKeyDown: ({ event }) => channelKeyHandlerRef.current(event)
|
|
7062
|
+
})
|
|
7063
|
+
}
|
|
7064
|
+
),
|
|
6841
7065
|
enableInputRules: RICH_TEXT_INPUT_RULE_ALLOWLIST,
|
|
6842
7066
|
content: richTextToProseMirror(block, resolveEmoji),
|
|
6843
7067
|
editorProps: {
|
|
@@ -6872,7 +7096,8 @@ function RichTextWysiwygEditor({ block, onChange }) {
|
|
|
6872
7096
|
Toolbar,
|
|
6873
7097
|
{
|
|
6874
7098
|
editor,
|
|
6875
|
-
mention:
|
|
7099
|
+
mention: userMentionsEnabled ? { active: mentionPicker !== null, insert: () => insertMentionTrigger(editor) } : null,
|
|
7100
|
+
channel: channelMentionsEnabled ? { active: channelPicker !== null, insert: () => insertChannelTrigger(editor) } : null
|
|
6876
7101
|
}
|
|
6877
7102
|
),
|
|
6878
7103
|
/* @__PURE__ */ jsxRuntime.jsx(react.EditorContent, { editor }),
|
|
@@ -6880,14 +7105,29 @@ function RichTextWysiwygEditor({ block, onChange }) {
|
|
|
6880
7105
|
MentionPicker,
|
|
6881
7106
|
{
|
|
6882
7107
|
editor,
|
|
7108
|
+
kind: "user",
|
|
6883
7109
|
state: mentionPicker,
|
|
6884
7110
|
keyHandlerRef: mentionKeyHandlerRef,
|
|
6885
7111
|
onDismiss: () => dismissMentionSuggestion(editor)
|
|
6886
7112
|
}
|
|
7113
|
+
),
|
|
7114
|
+
channelPicker && /* @__PURE__ */ jsxRuntime.jsx(
|
|
7115
|
+
MentionPicker,
|
|
7116
|
+
{
|
|
7117
|
+
editor,
|
|
7118
|
+
kind: "channel",
|
|
7119
|
+
state: channelPicker,
|
|
7120
|
+
keyHandlerRef: channelKeyHandlerRef,
|
|
7121
|
+
onDismiss: () => dismissChannelSuggestion(editor)
|
|
7122
|
+
}
|
|
6887
7123
|
)
|
|
6888
7124
|
] });
|
|
6889
7125
|
}
|
|
6890
|
-
function Toolbar({
|
|
7126
|
+
function Toolbar({
|
|
7127
|
+
editor,
|
|
7128
|
+
mention,
|
|
7129
|
+
channel
|
|
7130
|
+
}) {
|
|
6891
7131
|
return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-wrap items-center gap-0.5 rounded-md border bg-muted/30 p-1", children: [
|
|
6892
7132
|
/* @__PURE__ */ jsxRuntime.jsx(
|
|
6893
7133
|
ToolbarButton,
|
|
@@ -6947,6 +7187,7 @@ function Toolbar({ editor, mention }) {
|
|
|
6947
7187
|
}
|
|
6948
7188
|
),
|
|
6949
7189
|
mention && /* @__PURE__ */ jsxRuntime.jsx(ToolbarButton, { label: "Mention", active: mention.active, onClick: mention.insert, Icon: lucideReact.AtSign }),
|
|
7190
|
+
channel && /* @__PURE__ */ jsxRuntime.jsx(ToolbarButton, { label: "Channel", active: channel.active, onClick: channel.insert, Icon: lucideReact.Hash }),
|
|
6950
7191
|
/* @__PURE__ */ jsxRuntime.jsx(Divider, {}),
|
|
6951
7192
|
/* @__PURE__ */ jsxRuntime.jsx(
|
|
6952
7193
|
ToolbarButton,
|
|
@@ -7810,6 +8051,387 @@ function ImageItemCard({
|
|
|
7810
8051
|
) })
|
|
7811
8052
|
] });
|
|
7812
8053
|
}
|
|
8054
|
+
var REMOVE_BUTTON_CLASS = "flex h-6 w-6 shrink-0 items-center justify-center rounded text-muted-foreground hover:bg-destructive/10 hover:text-destructive disabled:cursor-not-allowed disabled:opacity-40";
|
|
8055
|
+
function CellGrid({
|
|
8056
|
+
label,
|
|
8057
|
+
help,
|
|
8058
|
+
rows,
|
|
8059
|
+
minRows,
|
|
8060
|
+
maxRows,
|
|
8061
|
+
maxColumns,
|
|
8062
|
+
lockFirstRow = false,
|
|
8063
|
+
blankCell,
|
|
8064
|
+
renderCell,
|
|
8065
|
+
renderColumnControl,
|
|
8066
|
+
onChange
|
|
8067
|
+
}) {
|
|
8068
|
+
const columnCount = rows[0]?.length ?? 0;
|
|
8069
|
+
const setCell = (rowIdx, colIdx, next) => {
|
|
8070
|
+
onChange(rows.map((row, r) => r === rowIdx ? row.map((cell, c) => c === colIdx ? next : cell) : row));
|
|
8071
|
+
};
|
|
8072
|
+
const addRow = () => {
|
|
8073
|
+
onChange([...rows, Array.from({ length: columnCount || 1 }, blankCell)]);
|
|
8074
|
+
};
|
|
8075
|
+
const removeRow = (rowIdx) => {
|
|
8076
|
+
if (rows.length <= minRows) {
|
|
8077
|
+
return;
|
|
8078
|
+
}
|
|
8079
|
+
onChange(rows.filter((_, r) => r !== rowIdx));
|
|
8080
|
+
};
|
|
8081
|
+
const addColumn = () => {
|
|
8082
|
+
onChange(
|
|
8083
|
+
rows.map((row) => [...row, blankCell()]),
|
|
8084
|
+
{ kind: "add" }
|
|
8085
|
+
);
|
|
8086
|
+
};
|
|
8087
|
+
const removeColumn = (colIdx) => {
|
|
8088
|
+
if (columnCount <= 1) {
|
|
8089
|
+
return;
|
|
8090
|
+
}
|
|
8091
|
+
onChange(
|
|
8092
|
+
rows.map((row) => row.filter((_, c) => c !== colIdx)),
|
|
8093
|
+
{ kind: "remove", index: colIdx }
|
|
8094
|
+
);
|
|
8095
|
+
};
|
|
8096
|
+
return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col gap-3", children: [
|
|
8097
|
+
/* @__PURE__ */ jsxRuntime.jsx(EditorField, { label, help, children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col gap-2 overflow-x-auto", children: [
|
|
8098
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-1", children: [
|
|
8099
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "w-6 shrink-0", "aria-hidden": "true" }),
|
|
8100
|
+
Array.from({ length: columnCount }, (_, c) => /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex min-w-[120px] flex-1 items-center gap-1", children: [
|
|
8101
|
+
renderColumnControl ? renderColumnControl(c) : /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "flex-1 truncate px-1.5 text-[11px] text-muted-foreground", children: [
|
|
8102
|
+
"Column ",
|
|
8103
|
+
c + 1
|
|
8104
|
+
] }),
|
|
8105
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
8106
|
+
"button",
|
|
8107
|
+
{
|
|
8108
|
+
type: "button",
|
|
8109
|
+
"aria-label": `Remove column ${c + 1}`,
|
|
8110
|
+
onClick: () => removeColumn(c),
|
|
8111
|
+
disabled: columnCount <= 1,
|
|
8112
|
+
className: REMOVE_BUTTON_CLASS,
|
|
8113
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Trash2, { className: "h-3 w-3" })
|
|
8114
|
+
}
|
|
8115
|
+
)
|
|
8116
|
+
] }, c))
|
|
8117
|
+
] }),
|
|
8118
|
+
rows.map((row, r) => /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-1", children: [
|
|
8119
|
+
lockFirstRow && r === 0 ? /* @__PURE__ */ jsxRuntime.jsx("span", { className: "w-6 shrink-0", "aria-hidden": "true" }) : /* @__PURE__ */ jsxRuntime.jsx(
|
|
8120
|
+
"button",
|
|
8121
|
+
{
|
|
8122
|
+
type: "button",
|
|
8123
|
+
"aria-label": `Remove row ${r + 1}`,
|
|
8124
|
+
onClick: () => removeRow(r),
|
|
8125
|
+
disabled: rows.length <= minRows,
|
|
8126
|
+
className: REMOVE_BUTTON_CLASS,
|
|
8127
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Trash2, { className: "h-3 w-3" })
|
|
8128
|
+
}
|
|
8129
|
+
),
|
|
8130
|
+
row.map((cell, c) => /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex min-w-[120px] flex-1 flex-col gap-0.5", children: renderCell(
|
|
8131
|
+
cell,
|
|
8132
|
+
{ row: r, col: c, label: `Row ${r + 1}, column ${c + 1}` },
|
|
8133
|
+
(next) => setCell(r, c, next)
|
|
8134
|
+
) }, c))
|
|
8135
|
+
] }, r))
|
|
8136
|
+
] }) }),
|
|
8137
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex gap-2", children: [
|
|
8138
|
+
/* @__PURE__ */ jsxRuntime.jsxs(Button, { type: "button", size: "sm", onClick: addRow, disabled: rows.length >= maxRows, children: [
|
|
8139
|
+
/* @__PURE__ */ jsxRuntime.jsx(lucideReact.Plus, { className: "h-3.5 w-3.5" }),
|
|
8140
|
+
" Add row"
|
|
8141
|
+
] }),
|
|
8142
|
+
/* @__PURE__ */ jsxRuntime.jsxs(Button, { type: "button", size: "sm", onClick: addColumn, disabled: columnCount >= maxColumns, children: [
|
|
8143
|
+
/* @__PURE__ */ jsxRuntime.jsx(lucideReact.Plus, { className: "h-3.5 w-3.5" }),
|
|
8144
|
+
" Add column"
|
|
8145
|
+
] })
|
|
8146
|
+
] })
|
|
8147
|
+
] });
|
|
8148
|
+
}
|
|
8149
|
+
function CellTextInput({
|
|
8150
|
+
cell,
|
|
8151
|
+
label,
|
|
8152
|
+
placeholder,
|
|
8153
|
+
leading,
|
|
8154
|
+
richTextNote = "Was rich-text; editing replaces with plain text.",
|
|
8155
|
+
onChange
|
|
8156
|
+
}) {
|
|
8157
|
+
const input = /* @__PURE__ */ jsxRuntime.jsx(
|
|
8158
|
+
Input,
|
|
8159
|
+
{
|
|
8160
|
+
"aria-label": label,
|
|
8161
|
+
value: cell.type === "raw_text" ? cell.text : "[rich_text]",
|
|
8162
|
+
placeholder,
|
|
8163
|
+
onChange: (e) => onChange({ type: "raw_text", text: e.target.value }),
|
|
8164
|
+
className: "h-8 text-xs"
|
|
8165
|
+
}
|
|
8166
|
+
);
|
|
8167
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
8168
|
+
leading ? /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-1", children: [
|
|
8169
|
+
leading,
|
|
8170
|
+
input
|
|
8171
|
+
] }) : input,
|
|
8172
|
+
cell.type === "rich_text" ? /* @__PURE__ */ jsxRuntime.jsx("span", { className: cn("text-[10px] text-muted-foreground", leading && "pl-7"), children: richTextNote }) : null
|
|
8173
|
+
] });
|
|
8174
|
+
}
|
|
8175
|
+
function NumberInput({
|
|
8176
|
+
id,
|
|
8177
|
+
value,
|
|
8178
|
+
onCommit,
|
|
8179
|
+
ariaLabel,
|
|
8180
|
+
className
|
|
8181
|
+
}) {
|
|
8182
|
+
const [draft, setDraft] = React.useState(String(value));
|
|
8183
|
+
React.useEffect(() => {
|
|
8184
|
+
setDraft(String(value));
|
|
8185
|
+
}, [value]);
|
|
8186
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
8187
|
+
Input,
|
|
8188
|
+
{
|
|
8189
|
+
id,
|
|
8190
|
+
type: "number",
|
|
8191
|
+
inputMode: "numeric",
|
|
8192
|
+
"aria-label": ariaLabel,
|
|
8193
|
+
value: draft,
|
|
8194
|
+
className,
|
|
8195
|
+
onChange: (e) => {
|
|
8196
|
+
const raw = e.target.value;
|
|
8197
|
+
setDraft(raw);
|
|
8198
|
+
if (raw === "" || raw === "-" || raw === "." || raw === "-.") {
|
|
8199
|
+
return;
|
|
8200
|
+
}
|
|
8201
|
+
const next = Number(raw);
|
|
8202
|
+
if (!Number.isNaN(next)) {
|
|
8203
|
+
onCommit(next);
|
|
8204
|
+
}
|
|
8205
|
+
},
|
|
8206
|
+
onBlur: () => {
|
|
8207
|
+
const next = Number(draft);
|
|
8208
|
+
const safe = draft.trim() === "" || Number.isNaN(next) ? 0 : next;
|
|
8209
|
+
onCommit(safe);
|
|
8210
|
+
setDraft(String(safe));
|
|
8211
|
+
}
|
|
8212
|
+
}
|
|
8213
|
+
);
|
|
8214
|
+
}
|
|
8215
|
+
var MAX_ROWS = 201;
|
|
8216
|
+
var MIN_ROWS = 2;
|
|
8217
|
+
var MAX_COLUMNS = 20;
|
|
8218
|
+
var MAX_PAGE_SIZE = 100;
|
|
8219
|
+
var SELECT_CLASS = "flex h-9 w-full rounded-md border border-input bg-background px-3 py-1 text-sm shadow-sm focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring disabled:cursor-not-allowed disabled:opacity-50";
|
|
8220
|
+
function withOptional(block, key, value) {
|
|
8221
|
+
const next = { ...block };
|
|
8222
|
+
if (value === void 0) {
|
|
8223
|
+
delete next[key];
|
|
8224
|
+
} else {
|
|
8225
|
+
next[key] = value;
|
|
8226
|
+
}
|
|
8227
|
+
return next;
|
|
8228
|
+
}
|
|
8229
|
+
function realignRowHeader(index, edit) {
|
|
8230
|
+
if (index === void 0 || edit.kind === "add" || edit.index > index) {
|
|
8231
|
+
return index;
|
|
8232
|
+
}
|
|
8233
|
+
return edit.index === index ? void 0 : index - 1;
|
|
8234
|
+
}
|
|
8235
|
+
function cellText(cell) {
|
|
8236
|
+
switch (cell?.type) {
|
|
8237
|
+
case "raw_text":
|
|
8238
|
+
return cell.text;
|
|
8239
|
+
case "raw_number":
|
|
8240
|
+
return cell.text ?? String(cell.value);
|
|
8241
|
+
case "action_cell":
|
|
8242
|
+
return cell.element.text.text;
|
|
8243
|
+
default:
|
|
8244
|
+
return "";
|
|
8245
|
+
}
|
|
8246
|
+
}
|
|
8247
|
+
function toNumberCell(cell) {
|
|
8248
|
+
const text = cell.text.trim();
|
|
8249
|
+
const parsed = text === "" ? Number.NaN : Number(text.replace(/,/g, ""));
|
|
8250
|
+
if (Number.isFinite(parsed)) {
|
|
8251
|
+
return String(parsed) === text ? { type: "raw_number", value: parsed } : { type: "raw_number", value: parsed, text };
|
|
8252
|
+
}
|
|
8253
|
+
return text ? { type: "raw_number", value: 0, text } : { type: "raw_number", value: 0 };
|
|
8254
|
+
}
|
|
8255
|
+
function toTextCell(cell) {
|
|
8256
|
+
return { type: "raw_text", text: cell.text ?? String(cell.value) };
|
|
8257
|
+
}
|
|
8258
|
+
function DataTableEditor({ block, onChange }) {
|
|
8259
|
+
const rows = block.rows ?? [];
|
|
8260
|
+
const header = rows[0] ?? [];
|
|
8261
|
+
const rowHeader = block.row_header_column_index ?? 0;
|
|
8262
|
+
return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col gap-4", children: [
|
|
8263
|
+
/* @__PURE__ */ jsxRuntime.jsx(EditorField, { label: "Caption", help: "Required. Names the table for screen readers.", htmlFor: "data-table-caption", children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
8264
|
+
Input,
|
|
8265
|
+
{
|
|
8266
|
+
id: "data-table-caption",
|
|
8267
|
+
value: block.caption,
|
|
8268
|
+
placeholder: "e.g. Open deals by stage",
|
|
8269
|
+
onChange: (e) => onChange({ ...block, caption: e.target.value })
|
|
8270
|
+
}
|
|
8271
|
+
) }),
|
|
8272
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "grid grid-cols-2 gap-2", children: [
|
|
8273
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
8274
|
+
EditorField,
|
|
8275
|
+
{
|
|
8276
|
+
label: "Rows per page",
|
|
8277
|
+
help: "Optional, 1-100. Slack shows 5 when empty.",
|
|
8278
|
+
htmlFor: "data-table-page-size",
|
|
8279
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
8280
|
+
Input,
|
|
8281
|
+
{
|
|
8282
|
+
id: "data-table-page-size",
|
|
8283
|
+
type: "number",
|
|
8284
|
+
min: 1,
|
|
8285
|
+
max: MAX_PAGE_SIZE,
|
|
8286
|
+
value: block.page_size ?? "",
|
|
8287
|
+
placeholder: "5",
|
|
8288
|
+
onChange: (e) => {
|
|
8289
|
+
const n = Math.trunc(Number(e.target.value));
|
|
8290
|
+
const next = e.target.value === "" || Number.isNaN(n) ? void 0 : Math.min(MAX_PAGE_SIZE, Math.max(1, n));
|
|
8291
|
+
onChange(withOptional(block, "page_size", next));
|
|
8292
|
+
}
|
|
8293
|
+
}
|
|
8294
|
+
)
|
|
8295
|
+
}
|
|
8296
|
+
),
|
|
8297
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
8298
|
+
EditorField,
|
|
8299
|
+
{
|
|
8300
|
+
label: "Row header column",
|
|
8301
|
+
help: "The column that identifies each row for screen readers.",
|
|
8302
|
+
htmlFor: "data-table-row-header",
|
|
8303
|
+
children: /* @__PURE__ */ jsxRuntime.jsxs(
|
|
8304
|
+
"select",
|
|
8305
|
+
{
|
|
8306
|
+
id: "data-table-row-header",
|
|
8307
|
+
value: rowHeader,
|
|
8308
|
+
disabled: header.length === 0,
|
|
8309
|
+
onChange: (e) => {
|
|
8310
|
+
const index = Number(e.target.value);
|
|
8311
|
+
onChange(withOptional(block, "row_header_column_index", index === 0 ? void 0 : index));
|
|
8312
|
+
},
|
|
8313
|
+
className: SELECT_CLASS,
|
|
8314
|
+
children: [
|
|
8315
|
+
header.map((cell, c) => {
|
|
8316
|
+
const text = cellText(cell);
|
|
8317
|
+
return /* @__PURE__ */ jsxRuntime.jsx("option", { value: c, children: text ? `Column ${c + 1}: ${text}` : `Column ${c + 1}` }, c);
|
|
8318
|
+
}),
|
|
8319
|
+
rowHeader >= header.length ? /* @__PURE__ */ jsxRuntime.jsxs("option", { value: rowHeader, children: [
|
|
8320
|
+
"Column ",
|
|
8321
|
+
rowHeader + 1,
|
|
8322
|
+
" (missing)"
|
|
8323
|
+
] }) : null
|
|
8324
|
+
]
|
|
8325
|
+
}
|
|
8326
|
+
)
|
|
8327
|
+
}
|
|
8328
|
+
)
|
|
8329
|
+
] }),
|
|
8330
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
8331
|
+
CellGrid,
|
|
8332
|
+
{
|
|
8333
|
+
label: "Cells",
|
|
8334
|
+
help: "The first row is the header. Up to 200 more rows and 20 columns. Use # to make a cell a number; a column of only numbers sorts numerically.",
|
|
8335
|
+
rows,
|
|
8336
|
+
minRows: MIN_ROWS,
|
|
8337
|
+
maxRows: MAX_ROWS,
|
|
8338
|
+
maxColumns: MAX_COLUMNS,
|
|
8339
|
+
lockFirstRow: true,
|
|
8340
|
+
blankCell: () => ({ type: "raw_text", text: "" }),
|
|
8341
|
+
onChange: (nextRows, edit) => {
|
|
8342
|
+
const next = { ...block, rows: nextRows };
|
|
8343
|
+
onChange(
|
|
8344
|
+
edit ? withOptional(next, "row_header_column_index", realignRowHeader(block.row_header_column_index, edit)) : next
|
|
8345
|
+
);
|
|
8346
|
+
},
|
|
8347
|
+
renderCell: (cell, position, update) => /* @__PURE__ */ jsxRuntime.jsx(DataTableCellField, { cell, position, onChange: update })
|
|
8348
|
+
}
|
|
8349
|
+
)
|
|
8350
|
+
] });
|
|
8351
|
+
}
|
|
8352
|
+
function DataTableCellField({
|
|
8353
|
+
cell,
|
|
8354
|
+
position,
|
|
8355
|
+
onChange
|
|
8356
|
+
}) {
|
|
8357
|
+
const { row, col, label } = position;
|
|
8358
|
+
if (cell.type === "action_cell") {
|
|
8359
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
8360
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-1", children: [
|
|
8361
|
+
/* @__PURE__ */ jsxRuntime.jsx(ToggleSpacer, {}),
|
|
8362
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex h-8 min-w-0 flex-1 items-center gap-1.5 rounded-md border border-dashed px-2 text-xs text-muted-foreground", children: [
|
|
8363
|
+
/* @__PURE__ */ jsxRuntime.jsx(lucideReact.MousePointerClick, { className: "h-3 w-3 shrink-0", "aria-hidden": "true" }),
|
|
8364
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "truncate", children: cellText(cell) || "Button" })
|
|
8365
|
+
] })
|
|
8366
|
+
] }),
|
|
8367
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "pl-7 text-[10px] text-muted-foreground", children: "Button cell. Edit it via View JSON." })
|
|
8368
|
+
] });
|
|
8369
|
+
}
|
|
8370
|
+
if (cell.type === "raw_number") {
|
|
8371
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
8372
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-1", children: [
|
|
8373
|
+
/* @__PURE__ */ jsxRuntime.jsx(NumberToggle, { label, pressed: true, onClick: () => onChange(toTextCell(cell)) }),
|
|
8374
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
8375
|
+
NumberInput,
|
|
8376
|
+
{
|
|
8377
|
+
value: cell.value,
|
|
8378
|
+
ariaLabel: `${label} value`,
|
|
8379
|
+
onCommit: (value) => onChange({ ...cell, value }),
|
|
8380
|
+
className: "h-8 text-xs"
|
|
8381
|
+
}
|
|
8382
|
+
)
|
|
8383
|
+
] }),
|
|
8384
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-1", children: [
|
|
8385
|
+
/* @__PURE__ */ jsxRuntime.jsx(ToggleSpacer, {}),
|
|
8386
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
8387
|
+
Input,
|
|
8388
|
+
{
|
|
8389
|
+
"aria-label": `${label} display text`,
|
|
8390
|
+
value: cell.text ?? "",
|
|
8391
|
+
placeholder: "Display as (optional)",
|
|
8392
|
+
onChange: (e) => {
|
|
8393
|
+
const { text: _omit, ...rest } = cell;
|
|
8394
|
+
onChange(e.target.value ? { ...rest, text: e.target.value } : rest);
|
|
8395
|
+
},
|
|
8396
|
+
className: "h-7 text-[11px]"
|
|
8397
|
+
}
|
|
8398
|
+
)
|
|
8399
|
+
] })
|
|
8400
|
+
] });
|
|
8401
|
+
}
|
|
8402
|
+
const isHeader = row === 0;
|
|
8403
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
8404
|
+
CellTextInput,
|
|
8405
|
+
{
|
|
8406
|
+
cell,
|
|
8407
|
+
label,
|
|
8408
|
+
placeholder: isHeader ? `Header ${col + 1}` : "Cell text",
|
|
8409
|
+
richTextNote: isHeader ? "Header cells can't be rich text. Type to replace it." : void 0,
|
|
8410
|
+
leading: !isHeader && cell.type === "raw_text" ? /* @__PURE__ */ jsxRuntime.jsx(NumberToggle, { label, pressed: false, onClick: () => onChange(toNumberCell(cell)) }) : /* @__PURE__ */ jsxRuntime.jsx(ToggleSpacer, {}),
|
|
8411
|
+
onChange
|
|
8412
|
+
}
|
|
8413
|
+
);
|
|
8414
|
+
}
|
|
8415
|
+
function ToggleSpacer() {
|
|
8416
|
+
return /* @__PURE__ */ jsxRuntime.jsx("span", { className: "h-6 w-6 shrink-0", "aria-hidden": "true" });
|
|
8417
|
+
}
|
|
8418
|
+
function NumberToggle({ label, pressed, onClick }) {
|
|
8419
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
8420
|
+
"button",
|
|
8421
|
+
{
|
|
8422
|
+
type: "button",
|
|
8423
|
+
"aria-label": `${label} as number`,
|
|
8424
|
+
"aria-pressed": pressed,
|
|
8425
|
+
title: pressed ? "Number cell. Click to make it text." : "Text cell. Click to make it a number.",
|
|
8426
|
+
onClick,
|
|
8427
|
+
className: cn(
|
|
8428
|
+
"flex h-6 w-6 shrink-0 items-center justify-center rounded transition-colors",
|
|
8429
|
+
pressed ? "bg-primary/10 text-foreground" : "text-muted-foreground hover:bg-accent hover:text-foreground"
|
|
8430
|
+
),
|
|
8431
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Hash, { className: "h-3 w-3" })
|
|
8432
|
+
}
|
|
8433
|
+
);
|
|
8434
|
+
}
|
|
7813
8435
|
var CHART_TYPES = ["line", "bar", "area", "pie"];
|
|
7814
8436
|
function isCartesian(chart) {
|
|
7815
8437
|
return chart.type !== "pie";
|
|
@@ -7864,46 +8486,6 @@ function DataVisualizationEditor({ block, onChange }) {
|
|
|
7864
8486
|
isCartesian(chart) ? /* @__PURE__ */ jsxRuntime.jsx(CartesianFields, { chart, onChange: setChart }) : /* @__PURE__ */ jsxRuntime.jsx(PieFields, { chart, onChange: setChart })
|
|
7865
8487
|
] });
|
|
7866
8488
|
}
|
|
7867
|
-
function NumberInput({
|
|
7868
|
-
id,
|
|
7869
|
-
value,
|
|
7870
|
-
onCommit,
|
|
7871
|
-
ariaLabel,
|
|
7872
|
-
className
|
|
7873
|
-
}) {
|
|
7874
|
-
const [draft, setDraft] = React.useState(String(value));
|
|
7875
|
-
React.useEffect(() => {
|
|
7876
|
-
setDraft(String(value));
|
|
7877
|
-
}, [value]);
|
|
7878
|
-
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
7879
|
-
Input,
|
|
7880
|
-
{
|
|
7881
|
-
id,
|
|
7882
|
-
type: "number",
|
|
7883
|
-
inputMode: "numeric",
|
|
7884
|
-
"aria-label": ariaLabel,
|
|
7885
|
-
value: draft,
|
|
7886
|
-
className,
|
|
7887
|
-
onChange: (e) => {
|
|
7888
|
-
const raw = e.target.value;
|
|
7889
|
-
setDraft(raw);
|
|
7890
|
-
if (raw === "" || raw === "-" || raw === "." || raw === "-.") {
|
|
7891
|
-
return;
|
|
7892
|
-
}
|
|
7893
|
-
const next = Number(raw);
|
|
7894
|
-
if (!Number.isNaN(next)) {
|
|
7895
|
-
onCommit(next);
|
|
7896
|
-
}
|
|
7897
|
-
},
|
|
7898
|
-
onBlur: () => {
|
|
7899
|
-
const next = Number(draft);
|
|
7900
|
-
const safe = draft.trim() === "" || Number.isNaN(next) ? 0 : next;
|
|
7901
|
-
onCommit(safe);
|
|
7902
|
-
setDraft(String(safe));
|
|
7903
|
-
}
|
|
7904
|
-
}
|
|
7905
|
-
);
|
|
7906
|
-
}
|
|
7907
8489
|
function CartesianFields({ chart, onChange }) {
|
|
7908
8490
|
const series = chart.series;
|
|
7909
8491
|
const categories = chart.axis_config?.categories && chart.axis_config.categories.length > 0 ? chart.axis_config.categories : series[0]?.data.map((d) => d.label) ?? [];
|
|
@@ -9446,45 +10028,13 @@ function ImageAccessoryFields({ image, onChange }) {
|
|
|
9446
10028
|
] });
|
|
9447
10029
|
}
|
|
9448
10030
|
var ALIGN_OPTIONS = ["left", "center", "right"];
|
|
9449
|
-
function
|
|
9450
|
-
|
|
9451
|
-
return cell.text;
|
|
9452
|
-
}
|
|
9453
|
-
return "[rich_text]";
|
|
10031
|
+
function alignColumnSettings(settings, edit) {
|
|
10032
|
+
return edit.kind === "add" ? [...settings, null] : settings.filter((_, c) => c !== edit.index);
|
|
9454
10033
|
}
|
|
9455
10034
|
function TableEditor({ block, onChange }) {
|
|
9456
10035
|
const rows = block.rows ?? [];
|
|
9457
10036
|
const columnCount = rows[0]?.length ?? 0;
|
|
9458
10037
|
const columnSettings = block.column_settings ?? [];
|
|
9459
|
-
const setCell = (rowIdx, colIdx, text) => {
|
|
9460
|
-
const nextRows = rows.map(
|
|
9461
|
-
(row, r) => r === rowIdx ? row.map((cell, c) => c === colIdx ? { type: "raw_text", text } : cell) : row
|
|
9462
|
-
);
|
|
9463
|
-
onChange({ ...block, rows: nextRows });
|
|
9464
|
-
};
|
|
9465
|
-
const addRow = () => {
|
|
9466
|
-
const blankRow = Array.from({ length: columnCount || 1 }, () => ({ type: "raw_text", text: "" }));
|
|
9467
|
-
onChange({ ...block, rows: [...rows, blankRow] });
|
|
9468
|
-
};
|
|
9469
|
-
const removeRow = (rowIdx) => {
|
|
9470
|
-
if (rows.length <= 1) {
|
|
9471
|
-
return;
|
|
9472
|
-
}
|
|
9473
|
-
onChange({ ...block, rows: rows.filter((_, r) => r !== rowIdx) });
|
|
9474
|
-
};
|
|
9475
|
-
const addColumn = () => {
|
|
9476
|
-
const nextRows = rows.map((row) => [...row, { type: "raw_text", text: "" }]);
|
|
9477
|
-
const nextSettings = [...columnSettings, null];
|
|
9478
|
-
onChange({ ...block, rows: nextRows, column_settings: nextSettings });
|
|
9479
|
-
};
|
|
9480
|
-
const removeColumn = (colIdx) => {
|
|
9481
|
-
if (columnCount <= 1) {
|
|
9482
|
-
return;
|
|
9483
|
-
}
|
|
9484
|
-
const nextRows = rows.map((row) => row.filter((_, c) => c !== colIdx));
|
|
9485
|
-
const nextSettings = columnSettings.filter((_, c) => c !== colIdx);
|
|
9486
|
-
onChange({ ...block, rows: nextRows, column_settings: nextSettings });
|
|
9487
|
-
};
|
|
9488
10038
|
const setColumnAlign = (colIdx, align) => {
|
|
9489
10039
|
const next = Array.from({ length: columnCount }, (_, i) => columnSettings[i] ?? null);
|
|
9490
10040
|
if (align === "") {
|
|
@@ -9495,81 +10045,45 @@ function TableEditor({ block, onChange }) {
|
|
|
9495
10045
|
}
|
|
9496
10046
|
onChange({ ...block, column_settings: next });
|
|
9497
10047
|
};
|
|
9498
|
-
return /* @__PURE__ */ jsxRuntime.
|
|
9499
|
-
|
|
9500
|
-
|
|
9501
|
-
|
|
9502
|
-
|
|
9503
|
-
|
|
9504
|
-
|
|
9505
|
-
|
|
9506
|
-
|
|
9507
|
-
|
|
9508
|
-
|
|
9509
|
-
|
|
9510
|
-
|
|
9511
|
-
|
|
9512
|
-
|
|
9513
|
-
|
|
9514
|
-
|
|
9515
|
-
|
|
9516
|
-
|
|
9517
|
-
|
|
9518
|
-
|
|
9519
|
-
|
|
9520
|
-
|
|
9521
|
-
|
|
9522
|
-
|
|
9523
|
-
|
|
9524
|
-
|
|
9525
|
-
|
|
9526
|
-
|
|
9527
|
-
|
|
9528
|
-
|
|
9529
|
-
|
|
9530
|
-
|
|
9531
|
-
|
|
9532
|
-
|
|
9533
|
-
|
|
9534
|
-
|
|
9535
|
-
|
|
9536
|
-
|
|
9537
|
-
type: "button",
|
|
9538
|
-
"aria-label": `Remove row ${r + 1}`,
|
|
9539
|
-
onClick: () => removeRow(r),
|
|
9540
|
-
disabled: rows.length <= 1,
|
|
9541
|
-
className: "flex h-6 w-6 shrink-0 items-center justify-center rounded text-muted-foreground hover:bg-destructive/10 hover:text-destructive disabled:cursor-not-allowed disabled:opacity-40",
|
|
9542
|
-
children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Trash2, { className: "h-3 w-3" })
|
|
9543
|
-
}
|
|
9544
|
-
),
|
|
9545
|
-
row.map((cell, c) => {
|
|
9546
|
-
const isRichText = cell.type === "rich_text";
|
|
9547
|
-
return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex min-w-[120px] flex-1 flex-col gap-0.5", children: [
|
|
9548
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
9549
|
-
Input,
|
|
9550
|
-
{
|
|
9551
|
-
value: cellAsText(cell),
|
|
9552
|
-
placeholder: r === 0 ? `Header ${c + 1}` : "Cell text",
|
|
9553
|
-
onChange: (e) => setCell(r, c, e.target.value),
|
|
9554
|
-
className: "h-8 text-xs"
|
|
9555
|
-
}
|
|
9556
|
-
),
|
|
9557
|
-
isRichText ? /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-[10px] text-muted-foreground", children: "Was rich-text; editing replaces with plain text." }) : null
|
|
9558
|
-
] }, c);
|
|
9559
|
-
})
|
|
9560
|
-
] }, r))
|
|
9561
|
-
] }) }),
|
|
9562
|
-
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex gap-2", children: [
|
|
9563
|
-
/* @__PURE__ */ jsxRuntime.jsxs(Button, { type: "button", size: "sm", onClick: addRow, disabled: rows.length >= 100, children: [
|
|
9564
|
-
/* @__PURE__ */ jsxRuntime.jsx(lucideReact.Plus, { className: "h-3.5 w-3.5" }),
|
|
9565
|
-
" Add row"
|
|
9566
|
-
] }),
|
|
9567
|
-
/* @__PURE__ */ jsxRuntime.jsxs(Button, { type: "button", size: "sm", onClick: addColumn, disabled: columnCount >= 20, children: [
|
|
9568
|
-
/* @__PURE__ */ jsxRuntime.jsx(lucideReact.Plus, { className: "h-3.5 w-3.5" }),
|
|
9569
|
-
" Add column"
|
|
9570
|
-
] })
|
|
9571
|
-
] })
|
|
9572
|
-
] });
|
|
10048
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
10049
|
+
CellGrid,
|
|
10050
|
+
{
|
|
10051
|
+
label: "Cells",
|
|
10052
|
+
help: "Up to 100 rows and 20 columns. Slack allows one table per message.",
|
|
10053
|
+
rows,
|
|
10054
|
+
minRows: 1,
|
|
10055
|
+
maxRows: 100,
|
|
10056
|
+
maxColumns: 20,
|
|
10057
|
+
blankCell: () => ({ type: "raw_text", text: "" }),
|
|
10058
|
+
onChange: (nextRows, edit) => onChange({
|
|
10059
|
+
...block,
|
|
10060
|
+
rows: nextRows,
|
|
10061
|
+
...edit ? { column_settings: alignColumnSettings(columnSettings, edit) } : {}
|
|
10062
|
+
}),
|
|
10063
|
+
renderColumnControl: (c) => /* @__PURE__ */ jsxRuntime.jsxs(
|
|
10064
|
+
"select",
|
|
10065
|
+
{
|
|
10066
|
+
"aria-label": `Column ${c + 1} alignment`,
|
|
10067
|
+
value: columnSettings[c]?.align ?? "",
|
|
10068
|
+
onChange: (e) => setColumnAlign(c, e.target.value),
|
|
10069
|
+
className: "h-7 flex-1 rounded-sm border border-input bg-background px-1.5 text-[11px] text-muted-foreground",
|
|
10070
|
+
children: [
|
|
10071
|
+
/* @__PURE__ */ jsxRuntime.jsx("option", { value: "", children: "Default" }),
|
|
10072
|
+
ALIGN_OPTIONS.map((a) => /* @__PURE__ */ jsxRuntime.jsx("option", { value: a, children: a }, a))
|
|
10073
|
+
]
|
|
10074
|
+
}
|
|
10075
|
+
),
|
|
10076
|
+
renderCell: (cell, { row, col, label }, update) => /* @__PURE__ */ jsxRuntime.jsx(
|
|
10077
|
+
CellTextInput,
|
|
10078
|
+
{
|
|
10079
|
+
cell,
|
|
10080
|
+
label,
|
|
10081
|
+
placeholder: row === 0 ? `Header ${col + 1}` : "Cell text",
|
|
10082
|
+
onChange: update
|
|
10083
|
+
}
|
|
10084
|
+
)
|
|
10085
|
+
}
|
|
10086
|
+
);
|
|
9573
10087
|
}
|
|
9574
10088
|
var STATUSES2 = ["pending", "in_progress", "complete", "error"];
|
|
9575
10089
|
function TaskCardEditor({ block, onChange }) {
|
|
@@ -9910,6 +10424,8 @@ function dispatch(block, onChange) {
|
|
|
9910
10424
|
return /* @__PURE__ */ jsxRuntime.jsx(DataVisualizationEditor, { block, onChange: (next) => onChange(next) });
|
|
9911
10425
|
case "container":
|
|
9912
10426
|
return /* @__PURE__ */ jsxRuntime.jsx(ContainerEditor, { block, onChange: (next) => onChange(next) });
|
|
10427
|
+
case "data_table":
|
|
10428
|
+
return /* @__PURE__ */ jsxRuntime.jsx(DataTableEditor, { block, onChange: (next) => onChange(next) });
|
|
9913
10429
|
default:
|
|
9914
10430
|
return null;
|
|
9915
10431
|
}
|
|
@@ -9933,7 +10449,8 @@ var BLOCK_TYPE_LABELS = {
|
|
|
9933
10449
|
plan: "Plan",
|
|
9934
10450
|
task_card: "Task Card",
|
|
9935
10451
|
data_visualization: "Data Visualization",
|
|
9936
|
-
container: "Container"
|
|
10452
|
+
container: "Container",
|
|
10453
|
+
data_table: "Data Table"
|
|
9937
10454
|
};
|
|
9938
10455
|
function BlockRow({
|
|
9939
10456
|
builderBlock,
|