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

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