@ai-matrx/kit 0.7.4 → 0.9.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.
@@ -0,0 +1,40 @@
1
+ /**
2
+ * @ai-matrx/kit/html-escape — ONE HTML escaper, with a decided character set.
3
+ *
4
+ * WHY THIS FILE EXISTS (2026-09-07 duplication census, row 14). Nine copies of
5
+ * `escapeHtml` were live across the fleet — six in matrx-frontend, one in
6
+ * matrx-extend, one in aidream's dashboard, and one private to
7
+ * `@ai-matrx/print/core` — and **they did not escape the same characters**.
8
+ * Three escaped only `& < >`; two added `"`; four added `'` (two as `&#39;`,
9
+ * two as `&#039;`). A string that is safe through one of them is an attribute
10
+ * break-out through another. That is not a style difference; it is a latent
11
+ * XSS class with nine independent chances to be wrong.
12
+ *
13
+ * The print package was the wrong owner (an HTML escaper must not require the
14
+ * print engine's `jspdf` + `html2canvas` graph), so it lives here, in the
15
+ * package with no sibling dependencies that everything can reach.
16
+ *
17
+ * THE DECIDED SET: `& < > " '` → `&amp; &lt; &gt; &quot; &#39;`.
18
+ *
19
+ * All five, always. Escaping the two quote characters is what makes the result
20
+ * safe to interpolate into an unquoted-or-quoted HTML *attribute*, not just
21
+ * into element text — and every caller that only escaped three was one
22
+ * refactor away from being an attribute caller. `'` uses the numeric `&#39;`
23
+ * rather than the named `&apos;`, which is XML, not HTML 4, and rather than
24
+ * `&#039;`, which is the same character with a pointless leading zero.
25
+ *
26
+ * WHAT THIS IS NOT. This escapes text for an HTML *document* context. It is
27
+ * not a sanitiser for untrusted HTML markup (use a real sanitiser), not a
28
+ * JavaScript-string escaper (a `</script>` inside a JSON blob needs
29
+ * `<`), and not a URL encoder.
30
+ */
31
+ /**
32
+ * Escape `& < > " '` so `value` is safe as HTML element text or as the
33
+ * contents of a quoted HTML attribute.
34
+ *
35
+ * Non-string input returns the empty string rather than `"undefined"` — a
36
+ * literal "undefined" rendered into a page is a screen telling a lie.
37
+ */
38
+ declare function escapeHtml(value: string | null | undefined): string;
39
+
40
+ export { escapeHtml };
@@ -0,0 +1,40 @@
1
+ /**
2
+ * @ai-matrx/kit/html-escape — ONE HTML escaper, with a decided character set.
3
+ *
4
+ * WHY THIS FILE EXISTS (2026-09-07 duplication census, row 14). Nine copies of
5
+ * `escapeHtml` were live across the fleet — six in matrx-frontend, one in
6
+ * matrx-extend, one in aidream's dashboard, and one private to
7
+ * `@ai-matrx/print/core` — and **they did not escape the same characters**.
8
+ * Three escaped only `& < >`; two added `"`; four added `'` (two as `&#39;`,
9
+ * two as `&#039;`). A string that is safe through one of them is an attribute
10
+ * break-out through another. That is not a style difference; it is a latent
11
+ * XSS class with nine independent chances to be wrong.
12
+ *
13
+ * The print package was the wrong owner (an HTML escaper must not require the
14
+ * print engine's `jspdf` + `html2canvas` graph), so it lives here, in the
15
+ * package with no sibling dependencies that everything can reach.
16
+ *
17
+ * THE DECIDED SET: `& < > " '` → `&amp; &lt; &gt; &quot; &#39;`.
18
+ *
19
+ * All five, always. Escaping the two quote characters is what makes the result
20
+ * safe to interpolate into an unquoted-or-quoted HTML *attribute*, not just
21
+ * into element text — and every caller that only escaped three was one
22
+ * refactor away from being an attribute caller. `'` uses the numeric `&#39;`
23
+ * rather than the named `&apos;`, which is XML, not HTML 4, and rather than
24
+ * `&#039;`, which is the same character with a pointless leading zero.
25
+ *
26
+ * WHAT THIS IS NOT. This escapes text for an HTML *document* context. It is
27
+ * not a sanitiser for untrusted HTML markup (use a real sanitiser), not a
28
+ * JavaScript-string escaper (a `</script>` inside a JSON blob needs
29
+ * `<`), and not a URL encoder.
30
+ */
31
+ /**
32
+ * Escape `& < > " '` so `value` is safe as HTML element text or as the
33
+ * contents of a quoted HTML attribute.
34
+ *
35
+ * Non-string input returns the empty string rather than `"undefined"` — a
36
+ * literal "undefined" rendered into a page is a screen telling a lie.
37
+ */
38
+ declare function escapeHtml(value: string | null | undefined): string;
39
+
40
+ export { escapeHtml };
@@ -0,0 +1,17 @@
1
+ // src/html-escape.ts
2
+ var HTML_ESCAPES = {
3
+ "&": "&amp;",
4
+ "<": "&lt;",
5
+ ">": "&gt;",
6
+ '"': "&quot;",
7
+ "'": "&#39;"
8
+ };
9
+ var HTML_ESCAPE_RE = /[&<>"']/g;
10
+ function escapeHtml(value) {
11
+ if (typeof value !== "string") return "";
12
+ return value.replace(HTML_ESCAPE_RE, (char) => HTML_ESCAPES[char] ?? char);
13
+ }
14
+ export {
15
+ escapeHtml
16
+ };
17
+ //# sourceMappingURL=html-escape.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/html-escape.ts"],"sourcesContent":["/**\n * @ai-matrx/kit/html-escape — ONE HTML escaper, with a decided character set.\n *\n * WHY THIS FILE EXISTS (2026-09-07 duplication census, row 14). Nine copies of\n * `escapeHtml` were live across the fleet — six in matrx-frontend, one in\n * matrx-extend, one in aidream's dashboard, and one private to\n * `@ai-matrx/print/core` — and **they did not escape the same characters**.\n * Three escaped only `& < >`; two added `\"`; four added `'` (two as `&#39;`,\n * two as `&#039;`). A string that is safe through one of them is an attribute\n * break-out through another. That is not a style difference; it is a latent\n * XSS class with nine independent chances to be wrong.\n *\n * The print package was the wrong owner (an HTML escaper must not require the\n * print engine's `jspdf` + `html2canvas` graph), so it lives here, in the\n * package with no sibling dependencies that everything can reach.\n *\n * THE DECIDED SET: `& < > \" '` → `&amp; &lt; &gt; &quot; &#39;`.\n *\n * All five, always. Escaping the two quote characters is what makes the result\n * safe to interpolate into an unquoted-or-quoted HTML *attribute*, not just\n * into element text — and every caller that only escaped three was one\n * refactor away from being an attribute caller. `'` uses the numeric `&#39;`\n * rather than the named `&apos;`, which is XML, not HTML 4, and rather than\n * `&#039;`, which is the same character with a pointless leading zero.\n *\n * WHAT THIS IS NOT. This escapes text for an HTML *document* context. It is\n * not a sanitiser for untrusted HTML markup (use a real sanitiser), not a\n * JavaScript-string escaper (a `</script>` inside a JSON blob needs\n * `<`), and not a URL encoder.\n */\n\nconst HTML_ESCAPES: Readonly<Record<string, string>> = {\n \"&\": \"&amp;\",\n \"<\": \"&lt;\",\n \">\": \"&gt;\",\n '\"': \"&quot;\",\n \"'\": \"&#39;\",\n};\n\nconst HTML_ESCAPE_RE = /[&<>\"']/g;\n\n/**\n * Escape `& < > \" '` so `value` is safe as HTML element text or as the\n * contents of a quoted HTML attribute.\n *\n * Non-string input returns the empty string rather than `\"undefined\"` — a\n * literal \"undefined\" rendered into a page is a screen telling a lie.\n */\nexport function escapeHtml(value: string | null | undefined): string {\n if (typeof value !== \"string\") return \"\";\n return value.replace(HTML_ESCAPE_RE, (char) => HTML_ESCAPES[char] ?? char);\n}\n"],"mappings":";AA+BA,IAAM,eAAiD;AAAA,EACrD,KAAK;AAAA,EACL,KAAK;AAAA,EACL,KAAK;AAAA,EACL,KAAK;AAAA,EACL,KAAK;AACP;AAEA,IAAM,iBAAiB;AAShB,SAAS,WAAW,OAA0C;AACnE,MAAI,OAAO,UAAU,SAAU,QAAO;AACtC,SAAO,MAAM,QAAQ,gBAAgB,CAAC,SAAS,aAAa,IAAI,KAAK,IAAI;AAC3E;","names":[]}
package/dist/index.cjs CHANGED
@@ -31,8 +31,6 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
31
31
  // src/index.ts
32
32
  var src_exports = {};
33
33
  __export(src_exports, {
34
- ConfirmDialog: () => ConfirmDialog,
35
- ConfirmDialogHost: () => ConfirmDialogHost,
36
34
  DBStoreManager: () => DBStoreManager,
37
35
  DEFAULT_JSON_INDENT: () => DEFAULT_JSON_INDENT,
38
36
  DEFAULT_JSON_WIDTH: () => DEFAULT_JSON_WIDTH,
@@ -44,7 +42,6 @@ __export(src_exports, {
44
42
  captureDrafts: () => captureDrafts,
45
43
  commitUrlParams: () => commitUrlParams,
46
44
  computeSearchScore: () => computeSearchScore,
47
- confirm: () => confirm,
48
45
  createColorNormalizer: () => createColorNormalizer,
49
46
  createFormatter: () => createFormatter,
50
47
  createMatrxToast: () => createMatrxToast,
@@ -925,320 +922,6 @@ function isLocalDraft(value) {
925
922
  return typeof d.key === "string" && typeof d.namespace === "string" && typeof d.entityId === "string" && typeof d.content === "string" && typeof d.capturedAt === "number";
926
923
  }
927
924
 
928
- // src/confirm/opener.ts
929
- var STATE_SLOT = /* @__PURE__ */ Symbol.for("ai-matrx.kit.confirm-opener-state");
930
- function getState() {
931
- const holder = globalThis;
932
- let state = holder[STATE_SLOT];
933
- if (!state) {
934
- state = { host: null, queue: [] };
935
- holder[STATE_SLOT] = state;
936
- }
937
- return state;
938
- }
939
- function _registerHost(controller) {
940
- const state = getState();
941
- state.host = controller;
942
- while (state.queue.length > 0) {
943
- const next = state.queue.shift();
944
- controller.show(next.opts, next.resolve);
945
- }
946
- }
947
- function _unregisterHost(controller) {
948
- const state = getState();
949
- if (state.host === controller) state.host = null;
950
- }
951
- function confirm(opts) {
952
- return new Promise((resolve) => {
953
- const state = getState();
954
- if (state.host) {
955
- state.host.show(opts, resolve);
956
- } else {
957
- state.queue.push({ opts, resolve });
958
- }
959
- });
960
- }
961
-
962
- // src/confirm/host.tsx
963
- var React3 = __toESM(require("react"), 1);
964
-
965
- // src/confirm/cn.ts
966
- var import_tailwind_merge = require("tailwind-merge");
967
- function cn(...values) {
968
- return (0, import_tailwind_merge.twMerge)(values.filter(Boolean).join(" "));
969
- }
970
-
971
- // src/confirm/alert-dialog.tsx
972
- var React2 = __toESM(require("react"), 1);
973
- var AlertDialogPrimitive = __toESM(require("@radix-ui/react-alert-dialog"), 1);
974
-
975
- // src/react-tree.ts
976
- var React = __toESM(require("react"), 1);
977
- var REACT_PORTAL_TYPE = /* @__PURE__ */ Symbol.for("react.portal");
978
- function treeContainsComponent(node, Component) {
979
- if (node == null || typeof node === "boolean") return false;
980
- if (Array.isArray(node)) {
981
- return node.some((child) => treeContainsComponent(child, Component));
982
- }
983
- if (React.isValidElement(node)) {
984
- if (node.type === Component) return true;
985
- const props = node.props;
986
- return props.children != null ? treeContainsComponent(props.children, Component) : false;
987
- }
988
- if (typeof node === "string" || typeof node === "number") return false;
989
- if (typeof node === "object" && node.$$typeof === REACT_PORTAL_TYPE) {
990
- return treeContainsComponent(
991
- node.children,
992
- Component
993
- );
994
- }
995
- if (typeof node === "object" && Symbol.iterator in node) {
996
- return Array.from(node).some(
997
- (child) => treeContainsComponent(child, Component)
998
- );
999
- }
1000
- const runtimeProcess = globalThis.process;
1001
- if (runtimeProcess?.env?.NODE_ENV !== "production") {
1002
- const keys = typeof node === "object" ? ` with keys {${Object.keys(node).join(", ")}}` : "";
1003
- console.error(
1004
- `[treeContainsComponent] A non-renderable value${keys} is being passed as a React child. React will throw 'Objects are not valid as a React child' at the real render site. Stringify it (e.g. JSON.stringify) before rendering.`,
1005
- node
1006
- );
1007
- }
1008
- return false;
1009
- }
1010
-
1011
- // src/confirm/alert-dialog.tsx
1012
- var import_jsx_runtime = require("react/jsx-runtime");
1013
- var buttonBase = "inline-flex cursor-pointer items-center justify-center gap-2 whitespace-nowrap rounded-md text-sm font-medium transition-all duration-200 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-0 disabled:pointer-events-none disabled:opacity-50 active:scale-[0.98] [&_svg]:pointer-events-none [&_svg]:size-4 [&_svg]:shrink-0 h-9 px-4 py-2";
1014
- var buttonDefault = "bg-primary text-primary-foreground shadow-sm hover:bg-primary/90";
1015
- var buttonOutline = "border border-border bg-card shadow-sm hover:bg-accent hover:text-accent-foreground";
1016
- var AlertDialog = AlertDialogPrimitive.Root;
1017
- var AlertDialogPortal = AlertDialogPrimitive.Portal;
1018
- var AlertDialogOverlay = React2.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
1019
- AlertDialogPrimitive.Overlay,
1020
- {
1021
- className: cn(
1022
- "fixed inset-0 z-[10000] bg-black/80 data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0",
1023
- className
1024
- ),
1025
- ...props,
1026
- ref
1027
- }
1028
- ));
1029
- AlertDialogOverlay.displayName = AlertDialogPrimitive.Overlay.displayName;
1030
- var AlertDialogContentPrimitive = React2.forwardRef(({ ...props }, ref) => /* @__PURE__ */ (0, import_jsx_runtime.jsx)(AlertDialogPrimitive.Content, { ...props, ref, "aria-modal": "true" }));
1031
- AlertDialogContentPrimitive.displayName = "AlertDialogContentPrimitive";
1032
- var AlertDialogDescription = React2.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
1033
- AlertDialogPrimitive.Description,
1034
- {
1035
- ref,
1036
- className: cn("text-sm text-muted-foreground", className),
1037
- ...props
1038
- }
1039
- ));
1040
- AlertDialogDescription.displayName = AlertDialogPrimitive.Description.displayName;
1041
- var AlertDialogContent = React2.forwardRef(({ className, children, container, ...props }, ref) => {
1042
- const hasDescription = treeContainsComponent(children, AlertDialogDescription) || treeContainsComponent(children, AlertDialogPrimitive.Description);
1043
- return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(AlertDialogPortal, { container: container ?? void 0, children: [
1044
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)(AlertDialogOverlay, {}),
1045
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
1046
- AlertDialogContentPrimitive,
1047
- {
1048
- ref,
1049
- className: cn(
1050
- "fixed left-[50%] top-[50%] z-[10000] grid w-full max-w-lg translate-x-[-50%] translate-y-[-50%] gap-4 border bg-background p-6 shadow-lg duration-200 data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[state=closed]:slide-out-to-left-1/2 data-[state=closed]:slide-out-to-top-[48%] data-[state=open]:slide-in-from-left-1/2 data-[state=open]:slide-in-from-top-[48%] sm:rounded-lg",
1051
- className
1052
- ),
1053
- ...props,
1054
- children: [
1055
- !hasDescription && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(AlertDialogPrimitive.Description, { className: "sr-only", children: "Please confirm the action described in this dialog." }),
1056
- children
1057
- ]
1058
- }
1059
- )
1060
- ] });
1061
- });
1062
- AlertDialogContent.displayName = AlertDialogPrimitive.Content.displayName;
1063
- var AlertDialogHeader = ({
1064
- className,
1065
- ...props
1066
- }) => /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
1067
- "div",
1068
- {
1069
- className: cn(
1070
- "flex flex-col space-y-2 text-center sm:text-left",
1071
- className
1072
- ),
1073
- ...props
1074
- }
1075
- );
1076
- AlertDialogHeader.displayName = "AlertDialogHeader";
1077
- var AlertDialogFooter = ({
1078
- className,
1079
- ...props
1080
- }) => /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
1081
- "div",
1082
- {
1083
- className: cn(
1084
- "flex flex-col-reverse sm:flex-row sm:justify-end sm:space-x-2",
1085
- className
1086
- ),
1087
- ...props
1088
- }
1089
- );
1090
- AlertDialogFooter.displayName = "AlertDialogFooter";
1091
- var AlertDialogTitle = React2.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
1092
- AlertDialogPrimitive.Title,
1093
- {
1094
- ref,
1095
- className: cn("text-lg font-semibold", className),
1096
- ...props
1097
- }
1098
- ));
1099
- AlertDialogTitle.displayName = AlertDialogPrimitive.Title.displayName;
1100
- var AlertDialogAction = React2.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
1101
- AlertDialogPrimitive.Action,
1102
- {
1103
- ref,
1104
- className: cn(buttonBase, buttonDefault, className),
1105
- ...props
1106
- }
1107
- ));
1108
- AlertDialogAction.displayName = AlertDialogPrimitive.Action.displayName;
1109
- var AlertDialogCancel = React2.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
1110
- AlertDialogPrimitive.Cancel,
1111
- {
1112
- ref,
1113
- className: cn(buttonBase, buttonOutline, "mt-2 sm:mt-0", className),
1114
- ...props
1115
- }
1116
- ));
1117
- AlertDialogCancel.displayName = AlertDialogPrimitive.Cancel.displayName;
1118
-
1119
- // src/confirm/confirm-dialog.tsx
1120
- var import_jsx_runtime2 = require("react/jsx-runtime");
1121
- function SpinnerIcon({ className }) {
1122
- return /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
1123
- "svg",
1124
- {
1125
- xmlns: "http://www.w3.org/2000/svg",
1126
- width: 24,
1127
- height: 24,
1128
- viewBox: "0 0 24 24",
1129
- fill: "none",
1130
- stroke: "currentColor",
1131
- strokeWidth: 2,
1132
- strokeLinecap: "round",
1133
- strokeLinejoin: "round",
1134
- "aria-hidden": "true",
1135
- className,
1136
- children: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("path", { d: "M21 12a9 9 0 1 1-6.219-8.56" })
1137
- }
1138
- );
1139
- }
1140
- function ConfirmDialog({
1141
- open,
1142
- onOpenChange,
1143
- title,
1144
- description,
1145
- content,
1146
- contentClassName,
1147
- confirmLabel = "Confirm",
1148
- cancelLabel = "Cancel",
1149
- variant = "default",
1150
- busy = false,
1151
- confirmDisabled = false,
1152
- portalContainer,
1153
- onConfirm
1154
- }) {
1155
- return /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(AlertDialog, { open, onOpenChange, children: /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(
1156
- AlertDialogContent,
1157
- {
1158
- className: contentClassName,
1159
- container: portalContainer ?? void 0,
1160
- children: [
1161
- /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(AlertDialogHeader, { children: [
1162
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(AlertDialogTitle, { children: title }),
1163
- description ? /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(AlertDialogDescription, { children: description }) : null
1164
- ] }),
1165
- content ?? null,
1166
- /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(AlertDialogFooter, { children: [
1167
- cancelLabel === null ? null : /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(AlertDialogCancel, { className: "max-lg:min-h-11", disabled: busy, children: cancelLabel }),
1168
- /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(
1169
- AlertDialogAction,
1170
- {
1171
- disabled: busy || confirmDisabled,
1172
- onClick: (event) => {
1173
- event.preventDefault();
1174
- void onConfirm();
1175
- },
1176
- className: cn(
1177
- "max-lg:min-h-11",
1178
- variant === "destructive" && "bg-destructive text-destructive-foreground hover:bg-destructive/90"
1179
- ),
1180
- children: [
1181
- busy ? /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(SpinnerIcon, { className: "mr-2 h-4 w-4 animate-spin" }) : null,
1182
- confirmLabel
1183
- ]
1184
- }
1185
- )
1186
- ] })
1187
- ]
1188
- }
1189
- ) });
1190
- }
1191
-
1192
- // src/confirm/host.tsx
1193
- var import_jsx_runtime3 = require("react/jsx-runtime");
1194
- function ConfirmDialogHost() {
1195
- const [active, setActive] = React3.useState(null);
1196
- const [tick, setTick] = React3.useState(0);
1197
- const queueRef = React3.useRef([]);
1198
- React3.useEffect(() => {
1199
- const controller = {
1200
- show: (opts, resolve) => {
1201
- queueRef.current.push({ opts, resolve });
1202
- setTick((n) => n + 1);
1203
- }
1204
- };
1205
- _registerHost(controller);
1206
- return () => _unregisterHost(controller);
1207
- }, []);
1208
- React3.useEffect(() => {
1209
- if (active === null && queueRef.current.length > 0) {
1210
- setActive(queueRef.current.shift());
1211
- }
1212
- }, [active, tick]);
1213
- const handleConfirm = React3.useCallback(() => {
1214
- if (!active) return;
1215
- active.resolve(true);
1216
- setActive(null);
1217
- }, [active]);
1218
- const handleOpenChange = React3.useCallback(
1219
- (open) => {
1220
- if (!open && active) {
1221
- active.resolve(false);
1222
- setActive(null);
1223
- }
1224
- },
1225
- [active]
1226
- );
1227
- return /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
1228
- ConfirmDialog,
1229
- {
1230
- open: !!active,
1231
- onOpenChange: handleOpenChange,
1232
- title: active?.opts.title ?? "",
1233
- description: active?.opts.description,
1234
- confirmLabel: active?.opts.confirmLabel,
1235
- cancelLabel: active?.opts.cancelLabel,
1236
- variant: active?.opts.variant,
1237
- onConfirm: handleConfirm
1238
- }
1239
- );
1240
- }
1241
-
1242
925
  // src/toast.ts
1243
926
  function messageText(message, data) {
1244
927
  const description = data && typeof data.description === "string" ? data.description : "";
@@ -1289,13 +972,13 @@ function createMatrxToast({
1289
972
  }
1290
973
 
1291
974
  // src/invalidation.ts
1292
- var STATE_SLOT2 = /* @__PURE__ */ Symbol.for("ai-matrx.kit.invalidation-registry");
975
+ var STATE_SLOT = /* @__PURE__ */ Symbol.for("ai-matrx.kit.invalidation-registry");
1293
976
  function getCallbacks() {
1294
977
  const holder = globalThis;
1295
- let state = holder[STATE_SLOT2];
978
+ let state = holder[STATE_SLOT];
1296
979
  if (!state) {
1297
980
  state = /* @__PURE__ */ new Map();
1298
- holder[STATE_SLOT2] = state;
981
+ holder[STATE_SLOT] = state;
1299
982
  }
1300
983
  return state;
1301
984
  }
@@ -1749,10 +1432,10 @@ function formatJsonText(text, options) {
1749
1432
  }
1750
1433
 
1751
1434
  // src/idle-scheduler/scheduler.ts
1752
- var STATE_SLOT3 = /* @__PURE__ */ Symbol.for("ai-matrx.kit.idle-scheduler-state");
1753
- function getState2() {
1435
+ var STATE_SLOT2 = /* @__PURE__ */ Symbol.for("ai-matrx.kit.idle-scheduler-state");
1436
+ function getState() {
1754
1437
  const holder = globalThis;
1755
- let state = holder[STATE_SLOT3];
1438
+ let state = holder[STATE_SLOT2];
1756
1439
  if (!state) {
1757
1440
  state = {
1758
1441
  queue: /* @__PURE__ */ new Map(),
@@ -1760,7 +1443,7 @@ function getState2() {
1760
1443
  cleanupFns: [],
1761
1444
  flushListeners: /* @__PURE__ */ new Set()
1762
1445
  };
1763
- holder[STATE_SLOT3] = state;
1446
+ holder[STATE_SLOT2] = state;
1764
1447
  if (typeof window !== "undefined") {
1765
1448
  window.__idleSched = getSchedulerState;
1766
1449
  }
@@ -1768,7 +1451,7 @@ function getState2() {
1768
1451
  return state;
1769
1452
  }
1770
1453
  function registerIdleTask(key, priority, callback) {
1771
- const state = getState2();
1454
+ const state = getState();
1772
1455
  if (state.flushState === "done") {
1773
1456
  scheduleImmediate(callback);
1774
1457
  return () => {
@@ -1783,7 +1466,7 @@ function registerIdleTask(key, priority, callback) {
1783
1466
  };
1784
1467
  }
1785
1468
  function onFlushComplete(listener) {
1786
- const state = getState2();
1469
+ const state = getState();
1787
1470
  if (state.flushState === "done") {
1788
1471
  queueMicrotask(listener);
1789
1472
  return () => {
@@ -1816,7 +1499,7 @@ function whenPageIdle(signal) {
1816
1499
  });
1817
1500
  }
1818
1501
  function getSchedulerState() {
1819
- const state = getState2();
1502
+ const state = getState();
1820
1503
  return {
1821
1504
  flushState: state.flushState,
1822
1505
  pendingCount: state.queue.size,
@@ -1824,7 +1507,7 @@ function getSchedulerState() {
1824
1507
  };
1825
1508
  }
1826
1509
  function resetScheduler() {
1827
- const state = getState2();
1510
+ const state = getState();
1828
1511
  state.cleanupFns.forEach((fn) => fn());
1829
1512
  state.cleanupFns = [];
1830
1513
  state.queue.clear();
@@ -2284,25 +1967,25 @@ var FeatureStore = class extends PublicStoreManager {
2284
1967
  };
2285
1968
 
2286
1969
  // src/idb-store/singleton.ts
2287
- var STATE_SLOT4 = /* @__PURE__ */ Symbol.for("ai-matrx.kit.idb-store-state");
2288
- function getState3() {
1970
+ var STATE_SLOT3 = /* @__PURE__ */ Symbol.for("ai-matrx.kit.idb-store-state");
1971
+ function getState2() {
2289
1972
  const holder = globalThis;
2290
- let state = holder[STATE_SLOT4];
1973
+ let state = holder[STATE_SLOT3];
2291
1974
  if (!state) {
2292
1975
  state = { instances: /* @__PURE__ */ new Map() };
2293
- holder[STATE_SLOT4] = state;
1976
+ holder[STATE_SLOT3] = state;
2294
1977
  }
2295
1978
  return state;
2296
1979
  }
2297
1980
  function getIdbStoreSingleton(key, create) {
2298
- const state = getState3();
1981
+ const state = getState2();
2299
1982
  if (!state.instances.has(key)) {
2300
1983
  state.instances.set(key, create());
2301
1984
  }
2302
1985
  return state.instances.get(key);
2303
1986
  }
2304
1987
  function _resetIdbStoreSingletons() {
2305
- getState3().instances.clear();
1988
+ getState2().instances.clear();
2306
1989
  }
2307
1990
 
2308
1991
  // src/color-util/lab-delta.ts
@@ -3048,6 +2731,42 @@ function createColorNormalizer({ isValid }) {
3048
2731
  };
3049
2732
  }
3050
2733
 
2734
+ // src/react-tree.ts
2735
+ var React = __toESM(require("react"), 1);
2736
+ var REACT_PORTAL_TYPE = /* @__PURE__ */ Symbol.for("react.portal");
2737
+ function treeContainsComponent(node, Component) {
2738
+ if (node == null || typeof node === "boolean") return false;
2739
+ if (Array.isArray(node)) {
2740
+ return node.some((child) => treeContainsComponent(child, Component));
2741
+ }
2742
+ if (React.isValidElement(node)) {
2743
+ if (node.type === Component) return true;
2744
+ const props = node.props;
2745
+ return props.children != null ? treeContainsComponent(props.children, Component) : false;
2746
+ }
2747
+ if (typeof node === "string" || typeof node === "number") return false;
2748
+ if (typeof node === "object" && node.$$typeof === REACT_PORTAL_TYPE) {
2749
+ return treeContainsComponent(
2750
+ node.children,
2751
+ Component
2752
+ );
2753
+ }
2754
+ if (typeof node === "object" && Symbol.iterator in node) {
2755
+ return Array.from(node).some(
2756
+ (child) => treeContainsComponent(child, Component)
2757
+ );
2758
+ }
2759
+ const runtimeProcess = globalThis.process;
2760
+ if (runtimeProcess?.env?.NODE_ENV !== "production") {
2761
+ const keys = typeof node === "object" ? ` with keys {${Object.keys(node).join(", ")}}` : "";
2762
+ console.error(
2763
+ `[treeContainsComponent] A non-renderable value${keys} is being passed as a React child. React will throw 'Objects are not valid as a React child' at the real render site. Stringify it (e.g. JSON.stringify) before rendering.`,
2764
+ node
2765
+ );
2766
+ }
2767
+ return false;
2768
+ }
2769
+
3051
2770
  // src/qr.ts
3052
2771
  var MAX_EDGE = 1600;
3053
2772
  function nativeDetector() {