@ai-matrx/content-ir-react 0.23.0 → 0.24.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/kind-kit.js CHANGED
@@ -657,10 +657,135 @@ function KindHeaderBar({
657
657
  );
658
658
  }
659
659
 
660
- // kind-kit/StreamingSkeleton.tsx
660
+ // kind-kit/KindActionButton.tsx
661
661
  import * as React8 from "react";
662
- import { cn as cn6, Skeleton } from "@ai-matrx/design-system";
662
+ import { Button as Button2, cn as cn6 } from "@ai-matrx/design-system";
663
663
  import { jsx as jsx7, jsxs as jsxs6 } from "react/jsx-runtime";
664
+ var ERROR_MAX = 60;
665
+ function KindActionButton({
666
+ runAction,
667
+ action,
668
+ input,
669
+ run: runChain,
670
+ label,
671
+ icon,
672
+ busyLabel,
673
+ confirm,
674
+ onDone,
675
+ onError,
676
+ variant = "outline",
677
+ compact = false,
678
+ disabled = false,
679
+ className
680
+ }) {
681
+ const [busy, setBusy] = React8.useState(false);
682
+ const [asking, setAsking] = React8.useState(false);
683
+ const [error, setError] = React8.useState(null);
684
+ const inFlight = React8.useRef(false);
685
+ const mounted = React8.useRef(true);
686
+ const errorTimer = React8.useRef(null);
687
+ React8.useEffect(() => {
688
+ mounted.current = true;
689
+ return () => {
690
+ mounted.current = false;
691
+ if (errorTimer.current) clearTimeout(errorTimer.current);
692
+ };
693
+ }, []);
694
+ const run = React8.useCallback(async () => {
695
+ if (inFlight.current) return;
696
+ inFlight.current = true;
697
+ setAsking(false);
698
+ setError(null);
699
+ setBusy(true);
700
+ try {
701
+ let res;
702
+ if (runChain) {
703
+ res = await runChain();
704
+ } else {
705
+ const payload = typeof input === "function" ? input() : input;
706
+ res = await runAction(action, payload);
707
+ }
708
+ if (res && res.ok) {
709
+ onDone?.(res.result);
710
+ } else {
711
+ const message = res && "error" in res && res.error || "Action failed";
712
+ if (mounted.current) {
713
+ setError(message);
714
+ if (errorTimer.current) clearTimeout(errorTimer.current);
715
+ errorTimer.current = setTimeout(() => {
716
+ if (mounted.current) setError(null);
717
+ }, 8e3);
718
+ }
719
+ onError?.(message);
720
+ }
721
+ } catch (e) {
722
+ const message = e instanceof Error ? e.message : "Action failed";
723
+ if (mounted.current) setError(message);
724
+ onError?.(message);
725
+ } finally {
726
+ inFlight.current = false;
727
+ if (mounted.current) setBusy(false);
728
+ }
729
+ }, [action, input, onDone, onError, runAction, runChain]);
730
+ const onClick = () => {
731
+ if (busy || disabled || inFlight.current) return;
732
+ if (confirm) setAsking(true);
733
+ else void run();
734
+ };
735
+ if (asking && !busy) {
736
+ return /* @__PURE__ */ jsxs6(
737
+ "span",
738
+ {
739
+ role: "group",
740
+ "aria-label": label,
741
+ className: cn6(
742
+ "inline-flex flex-wrap items-center gap-x-2 gap-y-1 rounded-md border border-border bg-card px-2 py-1 text-xs",
743
+ className
744
+ ),
745
+ children: [
746
+ /* @__PURE__ */ jsx7("span", { className: "text-foreground", children: confirm }),
747
+ /* @__PURE__ */ jsx7(Button2, { type: "button", size: "xs", variant: variant === "outline" ? "default" : variant, onClick: () => void run(), children: label }),
748
+ /* @__PURE__ */ jsx7(Button2, { type: "button", size: "xs", variant: "ghost", onClick: () => setAsking(false), children: "Cancel" })
749
+ ]
750
+ }
751
+ );
752
+ }
753
+ const shownLabel = busy ? busyLabel ?? label : label;
754
+ const glyph = busy ? /* @__PURE__ */ jsx7(Loader2, { className: "h-4 w-4 animate-spin" }) : renderKindKitIcon(icon, "h-4 w-4");
755
+ return /* @__PURE__ */ jsxs6("span", { className: cn6("inline-flex min-w-0 items-center gap-2", className), children: [
756
+ /* @__PURE__ */ jsxs6(
757
+ Button2,
758
+ {
759
+ type: "button",
760
+ variant,
761
+ size: compact ? "icon-sm" : "sm",
762
+ disabled: disabled || busy,
763
+ "aria-busy": busy || void 0,
764
+ "aria-label": compact ? shownLabel : void 0,
765
+ title: compact ? label : void 0,
766
+ onClick,
767
+ children: [
768
+ glyph,
769
+ !compact && /* @__PURE__ */ jsx7("span", { children: shownLabel })
770
+ ]
771
+ }
772
+ ),
773
+ error && /* @__PURE__ */ jsx7(
774
+ "span",
775
+ {
776
+ role: "alert",
777
+ title: error,
778
+ className: "min-w-0 text-xs text-destructive",
779
+ children: error.length > ERROR_MAX ? `${error.slice(0, ERROR_MAX - 1)}\u2026` : error
780
+ }
781
+ )
782
+ ] });
783
+ }
784
+
785
+ // kind-kit/StreamingSkeleton.tsx
786
+ import * as React9 from "react";
787
+ import { cn as cn7, Skeleton } from "@ai-matrx/design-system";
788
+ import { jsx as jsx8, jsxs as jsxs7 } from "react/jsx-runtime";
664
789
  function StreamingSkeleton({
665
790
  layout = "list",
666
791
  rows = 3,
@@ -671,72 +796,72 @@ function StreamingSkeleton({
671
796
  }) {
672
797
  const n = Math.max(1, rows);
673
798
  const cols = Math.max(1, columns ?? (layout === "cards" ? 2 : 3));
674
- return /* @__PURE__ */ jsxs6(
799
+ return /* @__PURE__ */ jsxs7(
675
800
  "div",
676
801
  {
677
802
  role: "status",
678
803
  "aria-busy": "true",
679
804
  "aria-label": label,
680
- className: cn6("space-y-2", className),
805
+ className: cn7("space-y-2", className),
681
806
  children: [
682
- header && /* @__PURE__ */ jsxs6("div", { className: "flex items-center gap-2", children: [
683
- /* @__PURE__ */ jsx7(Skeleton, { className: "h-4 w-4 rounded" }),
684
- /* @__PURE__ */ jsx7(Skeleton, { className: "h-4 w-40" }),
685
- /* @__PURE__ */ jsx7(Skeleton, { className: "ml-auto h-6 w-16" })
807
+ header && /* @__PURE__ */ jsxs7("div", { className: "flex items-center gap-2", children: [
808
+ /* @__PURE__ */ jsx8(Skeleton, { className: "h-4 w-4 rounded" }),
809
+ /* @__PURE__ */ jsx8(Skeleton, { className: "h-4 w-40" }),
810
+ /* @__PURE__ */ jsx8(Skeleton, { className: "ml-auto h-6 w-16" })
686
811
  ] }),
687
- layout === "list" && Array.from({ length: n }).map((_, i) => /* @__PURE__ */ jsxs6("div", { className: "flex items-center gap-2 rounded-md border border-border px-2 py-2", children: [
688
- /* @__PURE__ */ jsx7(Skeleton, { className: "h-4 w-4 rounded" }),
689
- /* @__PURE__ */ jsx7(Skeleton, { className: cn6("h-3.5", i % 3 === 0 ? "w-2/3" : i % 3 === 1 ? "w-1/2" : "w-3/4") })
812
+ layout === "list" && Array.from({ length: n }).map((_, i) => /* @__PURE__ */ jsxs7("div", { className: "flex items-center gap-2 rounded-md border border-border px-2 py-2", children: [
813
+ /* @__PURE__ */ jsx8(Skeleton, { className: "h-4 w-4 rounded" }),
814
+ /* @__PURE__ */ jsx8(Skeleton, { className: cn7("h-3.5", i % 3 === 0 ? "w-2/3" : i % 3 === 1 ? "w-1/2" : "w-3/4") })
690
815
  ] }, i)),
691
- layout === "cards" && /* @__PURE__ */ jsx7(
816
+ layout === "cards" && /* @__PURE__ */ jsx8(
692
817
  "div",
693
818
  {
694
819
  className: "grid gap-3",
695
820
  style: { gridTemplateColumns: `repeat(auto-fit, minmax(min(100%, 240px), 1fr))` },
696
- children: Array.from({ length: Math.max(n, cols) }).map((_, i) => /* @__PURE__ */ jsxs6("div", { className: "space-y-2 rounded-lg border border-border p-3", children: [
697
- /* @__PURE__ */ jsx7(Skeleton, { className: "h-3.5 w-1/2" }),
698
- /* @__PURE__ */ jsx7(Skeleton, { className: "h-3 w-full" }),
699
- /* @__PURE__ */ jsxs6("div", { className: "flex flex-wrap gap-1.5 pt-1", children: [
700
- /* @__PURE__ */ jsx7(Skeleton, { className: "h-5 w-16 rounded-full" }),
701
- /* @__PURE__ */ jsx7(Skeleton, { className: "h-5 w-24 rounded-full" }),
702
- /* @__PURE__ */ jsx7(Skeleton, { className: "h-5 w-12 rounded-full" })
821
+ children: Array.from({ length: Math.max(n, cols) }).map((_, i) => /* @__PURE__ */ jsxs7("div", { className: "space-y-2 rounded-lg border border-border p-3", children: [
822
+ /* @__PURE__ */ jsx8(Skeleton, { className: "h-3.5 w-1/2" }),
823
+ /* @__PURE__ */ jsx8(Skeleton, { className: "h-3 w-full" }),
824
+ /* @__PURE__ */ jsxs7("div", { className: "flex flex-wrap gap-1.5 pt-1", children: [
825
+ /* @__PURE__ */ jsx8(Skeleton, { className: "h-5 w-16 rounded-full" }),
826
+ /* @__PURE__ */ jsx8(Skeleton, { className: "h-5 w-24 rounded-full" }),
827
+ /* @__PURE__ */ jsx8(Skeleton, { className: "h-5 w-12 rounded-full" })
703
828
  ] })
704
829
  ] }, i))
705
830
  }
706
831
  ),
707
- layout === "table" && /* @__PURE__ */ jsxs6("div", { className: "overflow-hidden rounded-md border border-border", children: [
708
- /* @__PURE__ */ jsx7(
832
+ layout === "table" && /* @__PURE__ */ jsxs7("div", { className: "overflow-hidden rounded-md border border-border", children: [
833
+ /* @__PURE__ */ jsx8(
709
834
  "div",
710
835
  {
711
836
  className: "grid gap-2 border-b border-border bg-muted/40 px-2 py-1.5",
712
837
  style: { gridTemplateColumns: `repeat(${cols}, minmax(0, 1fr))` },
713
- children: Array.from({ length: cols }).map((_, c) => /* @__PURE__ */ jsx7(Skeleton, { className: "h-3 w-2/3" }, c))
838
+ children: Array.from({ length: cols }).map((_, c) => /* @__PURE__ */ jsx8(Skeleton, { className: "h-3 w-2/3" }, c))
714
839
  }
715
840
  ),
716
- Array.from({ length: n }).map((_, r) => /* @__PURE__ */ jsx7(
841
+ Array.from({ length: n }).map((_, r) => /* @__PURE__ */ jsx8(
717
842
  "div",
718
843
  {
719
844
  className: "grid gap-2 px-2 py-2",
720
845
  style: { gridTemplateColumns: `repeat(${cols}, minmax(0, 1fr))` },
721
- children: Array.from({ length: cols }).map((_2, c) => /* @__PURE__ */ jsx7(Skeleton, { className: cn6("h-3", c === 0 ? "w-3/4" : "w-1/2") }, c))
846
+ children: Array.from({ length: cols }).map((_2, c) => /* @__PURE__ */ jsx8(Skeleton, { className: cn7("h-3", c === 0 ? "w-3/4" : "w-1/2") }, c))
722
847
  },
723
848
  r
724
849
  ))
725
850
  ] }),
726
- layout === "text" && Array.from({ length: n }).map((_, i) => /* @__PURE__ */ jsx7(
851
+ layout === "text" && Array.from({ length: n }).map((_, i) => /* @__PURE__ */ jsx8(
727
852
  Skeleton,
728
853
  {
729
- className: cn6("h-3", i === n - 1 ? "w-2/5" : i % 2 === 0 ? "w-full" : "w-11/12")
854
+ className: cn7("h-3", i === n - 1 ? "w-2/5" : i % 2 === 0 ? "w-full" : "w-11/12")
730
855
  },
731
856
  i
732
857
  )),
733
- /* @__PURE__ */ jsx7("span", { className: "sr-only", children: label })
858
+ /* @__PURE__ */ jsx8("span", { className: "sr-only", children: label })
734
859
  ]
735
860
  }
736
861
  );
737
862
  }
738
863
  function useStreamingValue(value, fallback) {
739
- const [last, setLast] = React8.useState({
864
+ const [last, setLast] = React9.useState({
740
865
  value: fallback,
741
866
  arrived: false
742
867
  });
@@ -756,9 +881,9 @@ function streamText(value, fallback = "") {
756
881
  }
757
882
 
758
883
  // kind-kit/TagList.tsx
759
- import * as React9 from "react";
760
- import { cn as cn7 } from "@ai-matrx/design-system";
761
- import { jsx as jsx8, jsxs as jsxs7 } from "react/jsx-runtime";
884
+ import * as React10 from "react";
885
+ import { cn as cn8 } from "@ai-matrx/design-system";
886
+ import { jsx as jsx9, jsxs as jsxs8 } from "react/jsx-runtime";
762
887
  var TONE = {
763
888
  default: "border-border bg-background text-foreground",
764
889
  primary: "border-primary/40 bg-primary/5 text-foreground",
@@ -777,9 +902,9 @@ function KeywordChip({
777
902
  size = "sm",
778
903
  className
779
904
  }) {
780
- const [editing, setEditing] = React9.useState(false);
781
- const [draft, setDraft] = React9.useState(label);
782
- const inputRef = React9.useRef(null);
905
+ const [editing, setEditing] = React10.useState(false);
906
+ const [draft, setDraft] = React10.useState(label);
907
+ const inputRef = React10.useRef(null);
783
908
  const selectable = !!onSelect && !disabled;
784
909
  const editable = !!onEdit && !disabled;
785
910
  const startEdit = () => {
@@ -800,10 +925,10 @@ function KeywordChip({
800
925
  const pad = size === "md" ? "px-2.5 py-1 text-sm" : "px-2 py-0.5 text-xs";
801
926
  const inputText = size === "md" ? "text-[16px] sm:text-sm" : "text-[16px] sm:text-xs";
802
927
  const ctl = size === "md" ? "h-4 w-4" : "h-3.5 w-3.5";
803
- return /* @__PURE__ */ jsxs7(
928
+ return /* @__PURE__ */ jsxs8(
804
929
  "span",
805
930
  {
806
- className: cn7(
931
+ className: cn8(
807
932
  // max-w-full + min-w-0 + break-words: the text wraps INSIDE the chip.
808
933
  "inline-flex max-w-full min-w-0 items-center gap-1 rounded-full border leading-snug",
809
934
  pad,
@@ -812,7 +937,7 @@ function KeywordChip({
812
937
  className
813
938
  ),
814
939
  children: [
815
- selectable && /* @__PURE__ */ jsx8(
940
+ selectable && /* @__PURE__ */ jsx9(
816
941
  "button",
817
942
  {
818
943
  type: "button",
@@ -820,19 +945,19 @@ function KeywordChip({
820
945
  "aria-checked": selected,
821
946
  "aria-label": `${selected ? "Deselect" : "Select"} ${label}`,
822
947
  onClick: () => onSelect?.(!selected),
823
- className: cn7(
948
+ className: cn8(
824
949
  "flex shrink-0 items-center justify-center rounded-sm border",
825
950
  size === "md" ? "h-4 w-4" : "h-3.5 w-3.5",
826
951
  selected ? "border-primary bg-primary text-primary-foreground" : "border-muted-foreground/50 bg-background"
827
952
  ),
828
- children: selected && /* @__PURE__ */ jsx8(Check, { className: "h-2.5 w-2.5" })
953
+ children: selected && /* @__PURE__ */ jsx9(Check, { className: "h-2.5 w-2.5" })
829
954
  }
830
955
  ),
831
956
  renderKindKitIcon(
832
957
  icon,
833
- cn7("shrink-0 text-muted-foreground", ctl)
958
+ cn8("shrink-0 text-muted-foreground", ctl)
834
959
  ),
835
- editing ? /* @__PURE__ */ jsx8(
960
+ editing ? /* @__PURE__ */ jsx9(
836
961
  "input",
837
962
  {
838
963
  ref: inputRef,
@@ -850,9 +975,9 @@ function KeywordChip({
850
975
  },
851
976
  "aria-label": `Edit ${label}`,
852
977
  size: Math.max(4, draft.length + 1),
853
- className: cn7("min-w-0 bg-transparent outline-none", inputText)
978
+ className: cn8("min-w-0 bg-transparent outline-none", inputText)
854
979
  }
855
- ) : /* @__PURE__ */ jsx8(
980
+ ) : /* @__PURE__ */ jsx9(
856
981
  "span",
857
982
  {
858
983
  className: "min-w-0 whitespace-normal break-words text-left",
@@ -860,18 +985,18 @@ function KeywordChip({
860
985
  children: label
861
986
  }
862
987
  ),
863
- meta !== void 0 && meta !== null && /* @__PURE__ */ jsx8("span", { className: "shrink-0 tabular-nums text-muted-foreground", children: meta }),
864
- editable && !editing && /* @__PURE__ */ jsx8(
988
+ meta !== void 0 && meta !== null && /* @__PURE__ */ jsx9("span", { className: "shrink-0 tabular-nums text-muted-foreground", children: meta }),
989
+ editable && !editing && /* @__PURE__ */ jsx9(
865
990
  "button",
866
991
  {
867
992
  type: "button",
868
993
  "aria-label": `Edit ${label}`,
869
994
  onClick: startEdit,
870
995
  className: "shrink-0 rounded-full text-muted-foreground hover:text-foreground",
871
- children: /* @__PURE__ */ jsx8(Pencil, { className: cn7("h-3 w-3", size === "md" && "h-3.5 w-3.5") })
996
+ children: /* @__PURE__ */ jsx9(Pencil, { className: cn8("h-3 w-3", size === "md" && "h-3.5 w-3.5") })
872
997
  }
873
998
  ),
874
- onRemove && /* @__PURE__ */ jsx8(
999
+ onRemove && /* @__PURE__ */ jsx9(
875
1000
  "button",
876
1001
  {
877
1002
  type: "button",
@@ -879,7 +1004,7 @@ function KeywordChip({
879
1004
  disabled,
880
1005
  onClick: onRemove,
881
1006
  className: "-mr-0.5 shrink-0 rounded-full text-muted-foreground hover:text-destructive disabled:pointer-events-none",
882
- children: /* @__PURE__ */ jsx8(X, { className: ctl })
1007
+ children: /* @__PURE__ */ jsx9(X, { className: ctl })
883
1008
  }
884
1009
  )
885
1010
  ]
@@ -905,8 +1030,8 @@ function TagList({
905
1030
  className
906
1031
  }) {
907
1032
  const { ReadEmpty, ReadStaleNotice } = getKindKitHost();
908
- const [adding, setAdding] = React9.useState(false);
909
- const [draft, setDraft] = React9.useState("");
1033
+ const [adding, setAdding] = React10.useState(false);
1034
+ const [draft, setDraft] = React10.useState("");
910
1035
  const inputText = size === "md" ? "text-[16px] sm:text-sm" : "text-[16px] sm:text-xs";
911
1036
  const selectedSet = new Set(selected ?? []);
912
1037
  const commitAdd = () => {
@@ -915,16 +1040,16 @@ function TagList({
915
1040
  setDraft("");
916
1041
  setAdding(false);
917
1042
  };
918
- if (items.length === 0 && read && read.status !== "ready") return /* @__PURE__ */ jsx8(ReadEmpty, { read });
1043
+ if (items.length === 0 && read && read.status !== "ready") return /* @__PURE__ */ jsx9(ReadEmpty, { read });
919
1044
  if (items.length === 0 && !onAdd) {
920
- return emptyState !== void 0 ? /* @__PURE__ */ jsx8("div", { className: cn7("text-xs text-muted-foreground", className), children: emptyState }) : null;
1045
+ return emptyState !== void 0 ? /* @__PURE__ */ jsx9("div", { className: cn8("text-xs text-muted-foreground", className), children: emptyState }) : null;
921
1046
  }
922
- return /* @__PURE__ */ jsxs7("div", { className: cn7("flex flex-wrap items-center gap-1.5", className), children: [
923
- /* @__PURE__ */ jsx8(ReadStaleNotice, { read, className: "w-full" }),
1047
+ return /* @__PURE__ */ jsxs8("div", { className: cn8("flex flex-wrap items-center gap-1.5", className), children: [
1048
+ /* @__PURE__ */ jsx9(ReadStaleNotice, { read, className: "w-full" }),
924
1049
  items.map((raw, index) => {
925
1050
  const item = normalize(raw);
926
1051
  const key = item.key ?? item.label;
927
- return /* @__PURE__ */ jsx8(
1052
+ return /* @__PURE__ */ jsx9(
928
1053
  KeywordChip,
929
1054
  {
930
1055
  label: item.label,
@@ -940,15 +1065,15 @@ function TagList({
940
1065
  `${key}-${index}`
941
1066
  );
942
1067
  }),
943
- items.length === 0 && emptyState !== void 0 && /* @__PURE__ */ jsx8("span", { className: "text-xs text-muted-foreground", children: emptyState }),
944
- onAdd && !disabled && (adding ? /* @__PURE__ */ jsx8(
1068
+ items.length === 0 && emptyState !== void 0 && /* @__PURE__ */ jsx9("span", { className: "text-xs text-muted-foreground", children: emptyState }),
1069
+ onAdd && !disabled && (adding ? /* @__PURE__ */ jsx9(
945
1070
  "span",
946
1071
  {
947
- className: cn7(
1072
+ className: cn8(
948
1073
  "inline-flex items-center gap-1 rounded-full border border-dashed border-primary/60 bg-background",
949
1074
  size === "md" ? "px-2.5 py-1 text-sm" : "px-2 py-0.5 text-xs"
950
1075
  ),
951
- children: /* @__PURE__ */ jsx8(
1076
+ children: /* @__PURE__ */ jsx9(
952
1077
  "input",
953
1078
  {
954
1079
  autoFocus: true,
@@ -968,21 +1093,21 @@ function TagList({
968
1093
  },
969
1094
  "aria-label": addPlaceholder,
970
1095
  size: Math.max(6, draft.length + 1),
971
- className: cn7("min-w-0 bg-transparent outline-none placeholder:text-muted-foreground", inputText)
1096
+ className: cn8("min-w-0 bg-transparent outline-none placeholder:text-muted-foreground", inputText)
972
1097
  }
973
1098
  )
974
1099
  }
975
- ) : /* @__PURE__ */ jsxs7(
1100
+ ) : /* @__PURE__ */ jsxs8(
976
1101
  "button",
977
1102
  {
978
1103
  type: "button",
979
1104
  onClick: () => setAdding(true),
980
- className: cn7(
1105
+ className: cn8(
981
1106
  "inline-flex items-center gap-1 rounded-full border border-dashed border-border text-muted-foreground hover:border-primary/60 hover:text-foreground",
982
1107
  size === "md" ? "px-2.5 py-1 text-sm" : "px-2 py-0.5 text-xs"
983
1108
  ),
984
1109
  children: [
985
- /* @__PURE__ */ jsx8(Plus, { className: "h-3 w-3" }),
1110
+ /* @__PURE__ */ jsx9(Plus, { className: "h-3 w-3" }),
986
1111
  addPlaceholder.replace(/…$/, "")
987
1112
  ]
988
1113
  }
@@ -994,6 +1119,7 @@ export {
994
1119
  DefaultReadEmpty,
995
1120
  DefaultReadStaleNotice,
996
1121
  KeywordChip,
1122
+ KindActionButton,
997
1123
  KindHeaderBar,
998
1124
  KindPanel,
999
1125
  KindPanelGrid,