@almadar/ui 5.9.1 → 5.9.2

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.
@@ -37088,6 +37088,8 @@ var init_ReplyTree = __esm({
37088
37088
  const hasReplies = !!node.replies && node.replies.length > 0;
37089
37089
  const isCollapsed = collapsedSet.has(node.id);
37090
37090
  const atMaxDepth = depth >= maxDepth;
37091
+ const [replyOpen, setReplyOpen] = React98.useState(false);
37092
+ const [draft, setDraft] = React98.useState("");
37091
37093
  const handleVote = React98.useCallback(
37092
37094
  (next) => {
37093
37095
  onVote?.(node.id, next);
@@ -37097,8 +37099,19 @@ var init_ReplyTree = __esm({
37097
37099
  );
37098
37100
  const handleReply = React98.useCallback(() => {
37099
37101
  onReply?.(node.id);
37100
- if (replyEvent) eventBus.emit(`UI:${replyEvent}`, { parentNodeId: node.id });
37101
- }, [node.id, onReply, replyEvent, eventBus]);
37102
+ setReplyOpen((open) => !open);
37103
+ }, [node.id, onReply]);
37104
+ const handleSubmitReply = React98.useCallback(() => {
37105
+ const content = draft.trim();
37106
+ if (!content) return;
37107
+ if (replyEvent) eventBus.emit(`UI:${replyEvent}`, { parentNodeId: node.id, content });
37108
+ setDraft("");
37109
+ setReplyOpen(false);
37110
+ }, [node.id, draft, replyEvent, eventBus]);
37111
+ const handleCancelReply = React98.useCallback(() => {
37112
+ setDraft("");
37113
+ setReplyOpen(false);
37114
+ }, []);
37102
37115
  const handleFlag = React98.useCallback(() => {
37103
37116
  onFlag?.(node.id);
37104
37117
  if (flagEvent) eventBus.emit(`UI:${flagEvent}`, { nodeId: node.id });
@@ -37185,6 +37198,33 @@ var init_ReplyTree = __esm({
37185
37198
  }
37186
37199
  )
37187
37200
  ] }),
37201
+ replyOpen && /* @__PURE__ */ jsxRuntime.jsxs(Box, { className: "flex flex-col gap-2 mt-1", children: [
37202
+ /* @__PURE__ */ jsxRuntime.jsx(
37203
+ Input,
37204
+ {
37205
+ inputType: "textarea",
37206
+ rows: 2,
37207
+ value: draft,
37208
+ placeholder: `Reply to ${node.authorName}\u2026`,
37209
+ onChange: (e) => setDraft(e.target.value),
37210
+ "aria-label": `Reply to ${node.authorName}`
37211
+ }
37212
+ ),
37213
+ /* @__PURE__ */ jsxRuntime.jsxs(Box, { className: "flex flex-row gap-2 items-center", children: [
37214
+ /* @__PURE__ */ jsxRuntime.jsx(
37215
+ Button,
37216
+ {
37217
+ variant: "primary",
37218
+ size: "sm",
37219
+ leftIcon: "send",
37220
+ onClick: handleSubmitReply,
37221
+ disabled: !draft.trim(),
37222
+ children: "Send"
37223
+ }
37224
+ ),
37225
+ /* @__PURE__ */ jsxRuntime.jsx(Button, { variant: "ghost", size: "sm", onClick: handleCancelReply, children: "Cancel" })
37226
+ ] })
37227
+ ] }),
37188
37228
  hasReplies && !isCollapsed && (atMaxDepth ? /* @__PURE__ */ jsxRuntime.jsx(
37189
37229
  Button,
37190
37230
  {
package/dist/avl/index.js CHANGED
@@ -37039,6 +37039,8 @@ var init_ReplyTree = __esm({
37039
37039
  const hasReplies = !!node.replies && node.replies.length > 0;
37040
37040
  const isCollapsed = collapsedSet.has(node.id);
37041
37041
  const atMaxDepth = depth >= maxDepth;
37042
+ const [replyOpen, setReplyOpen] = useState(false);
37043
+ const [draft, setDraft] = useState("");
37042
37044
  const handleVote = useCallback(
37043
37045
  (next) => {
37044
37046
  onVote?.(node.id, next);
@@ -37048,8 +37050,19 @@ var init_ReplyTree = __esm({
37048
37050
  );
37049
37051
  const handleReply = useCallback(() => {
37050
37052
  onReply?.(node.id);
37051
- if (replyEvent) eventBus.emit(`UI:${replyEvent}`, { parentNodeId: node.id });
37052
- }, [node.id, onReply, replyEvent, eventBus]);
37053
+ setReplyOpen((open) => !open);
37054
+ }, [node.id, onReply]);
37055
+ const handleSubmitReply = useCallback(() => {
37056
+ const content = draft.trim();
37057
+ if (!content) return;
37058
+ if (replyEvent) eventBus.emit(`UI:${replyEvent}`, { parentNodeId: node.id, content });
37059
+ setDraft("");
37060
+ setReplyOpen(false);
37061
+ }, [node.id, draft, replyEvent, eventBus]);
37062
+ const handleCancelReply = useCallback(() => {
37063
+ setDraft("");
37064
+ setReplyOpen(false);
37065
+ }, []);
37053
37066
  const handleFlag = useCallback(() => {
37054
37067
  onFlag?.(node.id);
37055
37068
  if (flagEvent) eventBus.emit(`UI:${flagEvent}`, { nodeId: node.id });
@@ -37136,6 +37149,33 @@ var init_ReplyTree = __esm({
37136
37149
  }
37137
37150
  )
37138
37151
  ] }),
37152
+ replyOpen && /* @__PURE__ */ jsxs(Box, { className: "flex flex-col gap-2 mt-1", children: [
37153
+ /* @__PURE__ */ jsx(
37154
+ Input,
37155
+ {
37156
+ inputType: "textarea",
37157
+ rows: 2,
37158
+ value: draft,
37159
+ placeholder: `Reply to ${node.authorName}\u2026`,
37160
+ onChange: (e) => setDraft(e.target.value),
37161
+ "aria-label": `Reply to ${node.authorName}`
37162
+ }
37163
+ ),
37164
+ /* @__PURE__ */ jsxs(Box, { className: "flex flex-row gap-2 items-center", children: [
37165
+ /* @__PURE__ */ jsx(
37166
+ Button,
37167
+ {
37168
+ variant: "primary",
37169
+ size: "sm",
37170
+ leftIcon: "send",
37171
+ onClick: handleSubmitReply,
37172
+ disabled: !draft.trim(),
37173
+ children: "Send"
37174
+ }
37175
+ ),
37176
+ /* @__PURE__ */ jsx(Button, { variant: "ghost", size: "sm", onClick: handleCancelReply, children: "Cancel" })
37177
+ ] })
37178
+ ] }),
37139
37179
  hasReplies && !isCollapsed && (atMaxDepth ? /* @__PURE__ */ jsx(
37140
37180
  Button,
37141
37181
  {
@@ -32547,6 +32547,8 @@ var init_ReplyTree = __esm({
32547
32547
  const hasReplies = !!node.replies && node.replies.length > 0;
32548
32548
  const isCollapsed = collapsedSet.has(node.id);
32549
32549
  const atMaxDepth = depth >= maxDepth;
32550
+ const [replyOpen, setReplyOpen] = React80.useState(false);
32551
+ const [draft, setDraft] = React80.useState("");
32550
32552
  const handleVote = React80.useCallback(
32551
32553
  (next) => {
32552
32554
  onVote?.(node.id, next);
@@ -32556,8 +32558,19 @@ var init_ReplyTree = __esm({
32556
32558
  );
32557
32559
  const handleReply = React80.useCallback(() => {
32558
32560
  onReply?.(node.id);
32559
- if (replyEvent) eventBus.emit(`UI:${replyEvent}`, { parentNodeId: node.id });
32560
- }, [node.id, onReply, replyEvent, eventBus]);
32561
+ setReplyOpen((open) => !open);
32562
+ }, [node.id, onReply]);
32563
+ const handleSubmitReply = React80.useCallback(() => {
32564
+ const content = draft.trim();
32565
+ if (!content) return;
32566
+ if (replyEvent) eventBus.emit(`UI:${replyEvent}`, { parentNodeId: node.id, content });
32567
+ setDraft("");
32568
+ setReplyOpen(false);
32569
+ }, [node.id, draft, replyEvent, eventBus]);
32570
+ const handleCancelReply = React80.useCallback(() => {
32571
+ setDraft("");
32572
+ setReplyOpen(false);
32573
+ }, []);
32561
32574
  const handleFlag = React80.useCallback(() => {
32562
32575
  onFlag?.(node.id);
32563
32576
  if (flagEvent) eventBus.emit(`UI:${flagEvent}`, { nodeId: node.id });
@@ -32644,6 +32657,33 @@ var init_ReplyTree = __esm({
32644
32657
  }
32645
32658
  )
32646
32659
  ] }),
32660
+ replyOpen && /* @__PURE__ */ jsxRuntime.jsxs(exports.Box, { className: "flex flex-col gap-2 mt-1", children: [
32661
+ /* @__PURE__ */ jsxRuntime.jsx(
32662
+ exports.Input,
32663
+ {
32664
+ inputType: "textarea",
32665
+ rows: 2,
32666
+ value: draft,
32667
+ placeholder: `Reply to ${node.authorName}\u2026`,
32668
+ onChange: (e) => setDraft(e.target.value),
32669
+ "aria-label": `Reply to ${node.authorName}`
32670
+ }
32671
+ ),
32672
+ /* @__PURE__ */ jsxRuntime.jsxs(exports.Box, { className: "flex flex-row gap-2 items-center", children: [
32673
+ /* @__PURE__ */ jsxRuntime.jsx(
32674
+ exports.Button,
32675
+ {
32676
+ variant: "primary",
32677
+ size: "sm",
32678
+ leftIcon: "send",
32679
+ onClick: handleSubmitReply,
32680
+ disabled: !draft.trim(),
32681
+ children: "Send"
32682
+ }
32683
+ ),
32684
+ /* @__PURE__ */ jsxRuntime.jsx(exports.Button, { variant: "ghost", size: "sm", onClick: handleCancelReply, children: "Cancel" })
32685
+ ] })
32686
+ ] }),
32647
32687
  hasReplies && !isCollapsed && (atMaxDepth ? /* @__PURE__ */ jsxRuntime.jsx(
32648
32688
  exports.Button,
32649
32689
  {
@@ -32498,6 +32498,8 @@ var init_ReplyTree = __esm({
32498
32498
  const hasReplies = !!node.replies && node.replies.length > 0;
32499
32499
  const isCollapsed = collapsedSet.has(node.id);
32500
32500
  const atMaxDepth = depth >= maxDepth;
32501
+ const [replyOpen, setReplyOpen] = useState(false);
32502
+ const [draft, setDraft] = useState("");
32501
32503
  const handleVote = useCallback(
32502
32504
  (next) => {
32503
32505
  onVote?.(node.id, next);
@@ -32507,8 +32509,19 @@ var init_ReplyTree = __esm({
32507
32509
  );
32508
32510
  const handleReply = useCallback(() => {
32509
32511
  onReply?.(node.id);
32510
- if (replyEvent) eventBus.emit(`UI:${replyEvent}`, { parentNodeId: node.id });
32511
- }, [node.id, onReply, replyEvent, eventBus]);
32512
+ setReplyOpen((open) => !open);
32513
+ }, [node.id, onReply]);
32514
+ const handleSubmitReply = useCallback(() => {
32515
+ const content = draft.trim();
32516
+ if (!content) return;
32517
+ if (replyEvent) eventBus.emit(`UI:${replyEvent}`, { parentNodeId: node.id, content });
32518
+ setDraft("");
32519
+ setReplyOpen(false);
32520
+ }, [node.id, draft, replyEvent, eventBus]);
32521
+ const handleCancelReply = useCallback(() => {
32522
+ setDraft("");
32523
+ setReplyOpen(false);
32524
+ }, []);
32512
32525
  const handleFlag = useCallback(() => {
32513
32526
  onFlag?.(node.id);
32514
32527
  if (flagEvent) eventBus.emit(`UI:${flagEvent}`, { nodeId: node.id });
@@ -32595,6 +32608,33 @@ var init_ReplyTree = __esm({
32595
32608
  }
32596
32609
  )
32597
32610
  ] }),
32611
+ replyOpen && /* @__PURE__ */ jsxs(Box, { className: "flex flex-col gap-2 mt-1", children: [
32612
+ /* @__PURE__ */ jsx(
32613
+ Input,
32614
+ {
32615
+ inputType: "textarea",
32616
+ rows: 2,
32617
+ value: draft,
32618
+ placeholder: `Reply to ${node.authorName}\u2026`,
32619
+ onChange: (e) => setDraft(e.target.value),
32620
+ "aria-label": `Reply to ${node.authorName}`
32621
+ }
32622
+ ),
32623
+ /* @__PURE__ */ jsxs(Box, { className: "flex flex-row gap-2 items-center", children: [
32624
+ /* @__PURE__ */ jsx(
32625
+ Button,
32626
+ {
32627
+ variant: "primary",
32628
+ size: "sm",
32629
+ leftIcon: "send",
32630
+ onClick: handleSubmitReply,
32631
+ disabled: !draft.trim(),
32632
+ children: "Send"
32633
+ }
32634
+ ),
32635
+ /* @__PURE__ */ jsx(Button, { variant: "ghost", size: "sm", onClick: handleCancelReply, children: "Cancel" })
32636
+ ] })
32637
+ ] }),
32598
32638
  hasReplies && !isCollapsed && (atMaxDepth ? /* @__PURE__ */ jsx(
32599
32639
  Button,
32600
32640
  {
@@ -31,6 +31,7 @@ export interface ReplyTreeProps {
31
31
  }>;
32
32
  replyEvent?: EventEmit<{
33
33
  parentNodeId: string;
34
+ content: string;
34
35
  }>;
35
36
  flagEvent?: EventEmit<{
36
37
  nodeId: string;
@@ -33500,6 +33500,8 @@ var init_ReplyTree = __esm({
33500
33500
  const hasReplies = !!node.replies && node.replies.length > 0;
33501
33501
  const isCollapsed = collapsedSet.has(node.id);
33502
33502
  const atMaxDepth = depth >= maxDepth;
33503
+ const [replyOpen, setReplyOpen] = React86.useState(false);
33504
+ const [draft, setDraft] = React86.useState("");
33503
33505
  const handleVote = React86.useCallback(
33504
33506
  (next) => {
33505
33507
  onVote?.(node.id, next);
@@ -33509,8 +33511,19 @@ var init_ReplyTree = __esm({
33509
33511
  );
33510
33512
  const handleReply = React86.useCallback(() => {
33511
33513
  onReply?.(node.id);
33512
- if (replyEvent) eventBus.emit(`UI:${replyEvent}`, { parentNodeId: node.id });
33513
- }, [node.id, onReply, replyEvent, eventBus]);
33514
+ setReplyOpen((open) => !open);
33515
+ }, [node.id, onReply]);
33516
+ const handleSubmitReply = React86.useCallback(() => {
33517
+ const content = draft.trim();
33518
+ if (!content) return;
33519
+ if (replyEvent) eventBus.emit(`UI:${replyEvent}`, { parentNodeId: node.id, content });
33520
+ setDraft("");
33521
+ setReplyOpen(false);
33522
+ }, [node.id, draft, replyEvent, eventBus]);
33523
+ const handleCancelReply = React86.useCallback(() => {
33524
+ setDraft("");
33525
+ setReplyOpen(false);
33526
+ }, []);
33514
33527
  const handleFlag = React86.useCallback(() => {
33515
33528
  onFlag?.(node.id);
33516
33529
  if (flagEvent) eventBus.emit(`UI:${flagEvent}`, { nodeId: node.id });
@@ -33597,6 +33610,33 @@ var init_ReplyTree = __esm({
33597
33610
  }
33598
33611
  )
33599
33612
  ] }),
33613
+ replyOpen && /* @__PURE__ */ jsxRuntime.jsxs(Box, { className: "flex flex-col gap-2 mt-1", children: [
33614
+ /* @__PURE__ */ jsxRuntime.jsx(
33615
+ Input,
33616
+ {
33617
+ inputType: "textarea",
33618
+ rows: 2,
33619
+ value: draft,
33620
+ placeholder: `Reply to ${node.authorName}\u2026`,
33621
+ onChange: (e) => setDraft(e.target.value),
33622
+ "aria-label": `Reply to ${node.authorName}`
33623
+ }
33624
+ ),
33625
+ /* @__PURE__ */ jsxRuntime.jsxs(Box, { className: "flex flex-row gap-2 items-center", children: [
33626
+ /* @__PURE__ */ jsxRuntime.jsx(
33627
+ Button,
33628
+ {
33629
+ variant: "primary",
33630
+ size: "sm",
33631
+ leftIcon: "send",
33632
+ onClick: handleSubmitReply,
33633
+ disabled: !draft.trim(),
33634
+ children: "Send"
33635
+ }
33636
+ ),
33637
+ /* @__PURE__ */ jsxRuntime.jsx(Button, { variant: "ghost", size: "sm", onClick: handleCancelReply, children: "Cancel" })
33638
+ ] })
33639
+ ] }),
33600
33640
  hasReplies && !isCollapsed && (atMaxDepth ? /* @__PURE__ */ jsxRuntime.jsx(
33601
33641
  Button,
33602
33642
  {
@@ -33451,6 +33451,8 @@ var init_ReplyTree = __esm({
33451
33451
  const hasReplies = !!node.replies && node.replies.length > 0;
33452
33452
  const isCollapsed = collapsedSet.has(node.id);
33453
33453
  const atMaxDepth = depth >= maxDepth;
33454
+ const [replyOpen, setReplyOpen] = useState(false);
33455
+ const [draft, setDraft] = useState("");
33454
33456
  const handleVote = useCallback(
33455
33457
  (next) => {
33456
33458
  onVote?.(node.id, next);
@@ -33460,8 +33462,19 @@ var init_ReplyTree = __esm({
33460
33462
  );
33461
33463
  const handleReply = useCallback(() => {
33462
33464
  onReply?.(node.id);
33463
- if (replyEvent) eventBus.emit(`UI:${replyEvent}`, { parentNodeId: node.id });
33464
- }, [node.id, onReply, replyEvent, eventBus]);
33465
+ setReplyOpen((open) => !open);
33466
+ }, [node.id, onReply]);
33467
+ const handleSubmitReply = useCallback(() => {
33468
+ const content = draft.trim();
33469
+ if (!content) return;
33470
+ if (replyEvent) eventBus.emit(`UI:${replyEvent}`, { parentNodeId: node.id, content });
33471
+ setDraft("");
33472
+ setReplyOpen(false);
33473
+ }, [node.id, draft, replyEvent, eventBus]);
33474
+ const handleCancelReply = useCallback(() => {
33475
+ setDraft("");
33476
+ setReplyOpen(false);
33477
+ }, []);
33465
33478
  const handleFlag = useCallback(() => {
33466
33479
  onFlag?.(node.id);
33467
33480
  if (flagEvent) eventBus.emit(`UI:${flagEvent}`, { nodeId: node.id });
@@ -33548,6 +33561,33 @@ var init_ReplyTree = __esm({
33548
33561
  }
33549
33562
  )
33550
33563
  ] }),
33564
+ replyOpen && /* @__PURE__ */ jsxs(Box, { className: "flex flex-col gap-2 mt-1", children: [
33565
+ /* @__PURE__ */ jsx(
33566
+ Input,
33567
+ {
33568
+ inputType: "textarea",
33569
+ rows: 2,
33570
+ value: draft,
33571
+ placeholder: `Reply to ${node.authorName}\u2026`,
33572
+ onChange: (e) => setDraft(e.target.value),
33573
+ "aria-label": `Reply to ${node.authorName}`
33574
+ }
33575
+ ),
33576
+ /* @__PURE__ */ jsxs(Box, { className: "flex flex-row gap-2 items-center", children: [
33577
+ /* @__PURE__ */ jsx(
33578
+ Button,
33579
+ {
33580
+ variant: "primary",
33581
+ size: "sm",
33582
+ leftIcon: "send",
33583
+ onClick: handleSubmitReply,
33584
+ disabled: !draft.trim(),
33585
+ children: "Send"
33586
+ }
33587
+ ),
33588
+ /* @__PURE__ */ jsx(Button, { variant: "ghost", size: "sm", onClick: handleCancelReply, children: "Cancel" })
33589
+ ] })
33590
+ ] }),
33551
33591
  hasReplies && !isCollapsed && (atMaxDepth ? /* @__PURE__ */ jsx(
33552
33592
  Button,
33553
33593
  {
@@ -33067,6 +33067,8 @@ var init_ReplyTree = __esm({
33067
33067
  const hasReplies = !!node.replies && node.replies.length > 0;
33068
33068
  const isCollapsed = collapsedSet.has(node.id);
33069
33069
  const atMaxDepth = depth >= maxDepth;
33070
+ const [replyOpen, setReplyOpen] = React85.useState(false);
33071
+ const [draft, setDraft] = React85.useState("");
33070
33072
  const handleVote = React85.useCallback(
33071
33073
  (next) => {
33072
33074
  onVote?.(node.id, next);
@@ -33076,8 +33078,19 @@ var init_ReplyTree = __esm({
33076
33078
  );
33077
33079
  const handleReply = React85.useCallback(() => {
33078
33080
  onReply?.(node.id);
33079
- if (replyEvent) eventBus.emit(`UI:${replyEvent}`, { parentNodeId: node.id });
33080
- }, [node.id, onReply, replyEvent, eventBus]);
33081
+ setReplyOpen((open) => !open);
33082
+ }, [node.id, onReply]);
33083
+ const handleSubmitReply = React85.useCallback(() => {
33084
+ const content = draft.trim();
33085
+ if (!content) return;
33086
+ if (replyEvent) eventBus.emit(`UI:${replyEvent}`, { parentNodeId: node.id, content });
33087
+ setDraft("");
33088
+ setReplyOpen(false);
33089
+ }, [node.id, draft, replyEvent, eventBus]);
33090
+ const handleCancelReply = React85.useCallback(() => {
33091
+ setDraft("");
33092
+ setReplyOpen(false);
33093
+ }, []);
33081
33094
  const handleFlag = React85.useCallback(() => {
33082
33095
  onFlag?.(node.id);
33083
33096
  if (flagEvent) eventBus.emit(`UI:${flagEvent}`, { nodeId: node.id });
@@ -33164,6 +33177,33 @@ var init_ReplyTree = __esm({
33164
33177
  }
33165
33178
  )
33166
33179
  ] }),
33180
+ replyOpen && /* @__PURE__ */ jsxRuntime.jsxs(Box, { className: "flex flex-col gap-2 mt-1", children: [
33181
+ /* @__PURE__ */ jsxRuntime.jsx(
33182
+ Input,
33183
+ {
33184
+ inputType: "textarea",
33185
+ rows: 2,
33186
+ value: draft,
33187
+ placeholder: `Reply to ${node.authorName}\u2026`,
33188
+ onChange: (e) => setDraft(e.target.value),
33189
+ "aria-label": `Reply to ${node.authorName}`
33190
+ }
33191
+ ),
33192
+ /* @__PURE__ */ jsxRuntime.jsxs(Box, { className: "flex flex-row gap-2 items-center", children: [
33193
+ /* @__PURE__ */ jsxRuntime.jsx(
33194
+ Button,
33195
+ {
33196
+ variant: "primary",
33197
+ size: "sm",
33198
+ leftIcon: "send",
33199
+ onClick: handleSubmitReply,
33200
+ disabled: !draft.trim(),
33201
+ children: "Send"
33202
+ }
33203
+ ),
33204
+ /* @__PURE__ */ jsxRuntime.jsx(Button, { variant: "ghost", size: "sm", onClick: handleCancelReply, children: "Cancel" })
33205
+ ] })
33206
+ ] }),
33167
33207
  hasReplies && !isCollapsed && (atMaxDepth ? /* @__PURE__ */ jsxRuntime.jsx(
33168
33208
  Button,
33169
33209
  {
@@ -33018,6 +33018,8 @@ var init_ReplyTree = __esm({
33018
33018
  const hasReplies = !!node.replies && node.replies.length > 0;
33019
33019
  const isCollapsed = collapsedSet.has(node.id);
33020
33020
  const atMaxDepth = depth >= maxDepth;
33021
+ const [replyOpen, setReplyOpen] = useState(false);
33022
+ const [draft, setDraft] = useState("");
33021
33023
  const handleVote = useCallback(
33022
33024
  (next) => {
33023
33025
  onVote?.(node.id, next);
@@ -33027,8 +33029,19 @@ var init_ReplyTree = __esm({
33027
33029
  );
33028
33030
  const handleReply = useCallback(() => {
33029
33031
  onReply?.(node.id);
33030
- if (replyEvent) eventBus.emit(`UI:${replyEvent}`, { parentNodeId: node.id });
33031
- }, [node.id, onReply, replyEvent, eventBus]);
33032
+ setReplyOpen((open) => !open);
33033
+ }, [node.id, onReply]);
33034
+ const handleSubmitReply = useCallback(() => {
33035
+ const content = draft.trim();
33036
+ if (!content) return;
33037
+ if (replyEvent) eventBus.emit(`UI:${replyEvent}`, { parentNodeId: node.id, content });
33038
+ setDraft("");
33039
+ setReplyOpen(false);
33040
+ }, [node.id, draft, replyEvent, eventBus]);
33041
+ const handleCancelReply = useCallback(() => {
33042
+ setDraft("");
33043
+ setReplyOpen(false);
33044
+ }, []);
33032
33045
  const handleFlag = useCallback(() => {
33033
33046
  onFlag?.(node.id);
33034
33047
  if (flagEvent) eventBus.emit(`UI:${flagEvent}`, { nodeId: node.id });
@@ -33115,6 +33128,33 @@ var init_ReplyTree = __esm({
33115
33128
  }
33116
33129
  )
33117
33130
  ] }),
33131
+ replyOpen && /* @__PURE__ */ jsxs(Box, { className: "flex flex-col gap-2 mt-1", children: [
33132
+ /* @__PURE__ */ jsx(
33133
+ Input,
33134
+ {
33135
+ inputType: "textarea",
33136
+ rows: 2,
33137
+ value: draft,
33138
+ placeholder: `Reply to ${node.authorName}\u2026`,
33139
+ onChange: (e) => setDraft(e.target.value),
33140
+ "aria-label": `Reply to ${node.authorName}`
33141
+ }
33142
+ ),
33143
+ /* @__PURE__ */ jsxs(Box, { className: "flex flex-row gap-2 items-center", children: [
33144
+ /* @__PURE__ */ jsx(
33145
+ Button,
33146
+ {
33147
+ variant: "primary",
33148
+ size: "sm",
33149
+ leftIcon: "send",
33150
+ onClick: handleSubmitReply,
33151
+ disabled: !draft.trim(),
33152
+ children: "Send"
33153
+ }
33154
+ ),
33155
+ /* @__PURE__ */ jsx(Button, { variant: "ghost", size: "sm", onClick: handleCancelReply, children: "Cancel" })
33156
+ ] })
33157
+ ] }),
33118
33158
  hasReplies && !isCollapsed && (atMaxDepth ? /* @__PURE__ */ jsx(
33119
33159
  Button,
33120
33160
  {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@almadar/ui",
3
- "version": "5.9.1",
3
+ "version": "5.9.2",
4
4
  "description": "React UI components, hooks, and providers for Almadar",
5
5
  "type": "module",
6
6
  "sideEffects": [