@botiverse/raft-ui 0.20.0 → 0.21.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/CHANGELOG.md +105 -0
- package/codemods/button-sizes.mjs +340 -0
- package/dist/cn.mjs +8 -1
- package/dist/foundation.css +13 -0
- package/dist/{index-RFu5pOr7.d.mts → index-CP05_pvu.d.mts} +41 -2
- package/dist/index.d.mts +2 -22
- package/dist/index.mjs +53 -62
- package/dist/styles.css +58 -0
- package/dist/tokens.json +24 -0
- package/dist/{touch-drag-BA_Fxs2Z.mjs → touch-drag-B7uLTWXe.mjs} +205 -26
- package/dist/wip.d.mts +100 -3
- package/dist/wip.mjs +347 -3
- package/package.json +8 -1
package/dist/wip.mjs
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { An as Tooltip, Bn as DialogClose, Fn as TextLink, Gt as readNow, Ht as measureContent, Pn as TooltipTrigger, Rn as Dialog, Ut as measureElement, Vn as DialogContent, Vt as useOverflowTitle, Wt as observeTruncation, Xn as DialogTrigger, Yn as DialogTitle, Zn as Button$1, a as MessageListJumpPillDismiss, ar as useTheme, dt as MessageItemDelegatedAvatar, er as defaultNativeButton, ft as MessageItemDelegatedBy, h as MessageQuotedPreviewAuthorDelegatedBy, i as MessageListJumpPill, ir as useThemeScopeProps, jn as TooltipContent, mt as MessageItemDelegatedByName, o as MessageListJumpPillGroup, pt as MessageItemDelegatedByButton, r as MessageListJumpControls, sr as tv, t as useHoldThenMoveTouchSensor } from "./touch-drag-B7uLTWXe.mjs";
|
|
2
2
|
import { Check, ChevronDown, LoaderCircle, Plus, X } from "lucide-react";
|
|
3
|
-
import { createContext, use, useCallback, useEffect, useId, useLayoutEffect, useMemo, useRef, useState, useSyncExternalStore } from "react";
|
|
3
|
+
import { createContext, use, useCallback, useContext, useEffect, useId, useLayoutEffect, useMemo, useRef, useState, useSyncExternalStore } from "react";
|
|
4
4
|
import { Fragment as Fragment$1, jsx, jsxs } from "react/jsx-runtime";
|
|
5
5
|
import { Button } from "@base-ui/react/button";
|
|
6
6
|
import { mergeProps } from "@base-ui/react/merge-props";
|
|
@@ -1123,4 +1123,348 @@ function useCommentMarginFits(element, { minWidth = 784 } = {}) {
|
|
|
1123
1123
|
return desktop && element !== null && width >= minWidth;
|
|
1124
1124
|
}
|
|
1125
1125
|
//#endregion
|
|
1126
|
-
|
|
1126
|
+
//#region src/components/ellipsis/ellipsis.tsx
|
|
1127
|
+
const ellipsis = tv({
|
|
1128
|
+
slots: {
|
|
1129
|
+
root: ["group/ellipsis min-w-0 max-w-full"],
|
|
1130
|
+
text: ["min-w-0"],
|
|
1131
|
+
content: [],
|
|
1132
|
+
spacer: ["float-end h-[calc(100%-1lh)] w-0", "data-hidden:hidden group-data-measuring/ellipsis:hidden"],
|
|
1133
|
+
after: ["data-hidden:hidden group-data-measuring/ellipsis:hidden"]
|
|
1134
|
+
},
|
|
1135
|
+
variants: {
|
|
1136
|
+
multiline: {
|
|
1137
|
+
true: {
|
|
1138
|
+
root: ["flex"],
|
|
1139
|
+
text: ["flex-1", "wrap-break-word"],
|
|
1140
|
+
after: ["float-end clear-end ps-1"]
|
|
1141
|
+
},
|
|
1142
|
+
false: {
|
|
1143
|
+
root: ["inline-flex items-baseline gap-x-1 align-bottom"],
|
|
1144
|
+
after: ["shrink-0"]
|
|
1145
|
+
}
|
|
1146
|
+
},
|
|
1147
|
+
expanded: {
|
|
1148
|
+
true: {},
|
|
1149
|
+
false: {}
|
|
1150
|
+
},
|
|
1151
|
+
clickable: {
|
|
1152
|
+
true: { text: ["cursor-pointer"] },
|
|
1153
|
+
false: {}
|
|
1154
|
+
}
|
|
1155
|
+
},
|
|
1156
|
+
compoundVariants: [
|
|
1157
|
+
{
|
|
1158
|
+
multiline: false,
|
|
1159
|
+
expanded: false,
|
|
1160
|
+
class: { text: ["truncate", "print:overflow-visible print:whitespace-normal"] }
|
|
1161
|
+
},
|
|
1162
|
+
{
|
|
1163
|
+
multiline: false,
|
|
1164
|
+
expanded: true,
|
|
1165
|
+
class: { text: ["wrap-anywhere whitespace-normal"] }
|
|
1166
|
+
},
|
|
1167
|
+
{
|
|
1168
|
+
multiline: true,
|
|
1169
|
+
expanded: false,
|
|
1170
|
+
class: { text: ["line-clamp-(--ellipsis-lines)", "print:line-clamp-none"] }
|
|
1171
|
+
},
|
|
1172
|
+
{
|
|
1173
|
+
multiline: true,
|
|
1174
|
+
expanded: true,
|
|
1175
|
+
class: { text: ["line-clamp-none"] }
|
|
1176
|
+
}
|
|
1177
|
+
]
|
|
1178
|
+
});
|
|
1179
|
+
const EllipsisContext = createContext(null);
|
|
1180
|
+
const INTERACTIVE = "a[href], button, input, select, textarea, summary, [tabindex], [contenteditable]:not([contenteditable='false']), [role='button'], [role='link']";
|
|
1181
|
+
const TOUCH_MEDIA_QUERY = "(hover: none), (pointer: coarse)";
|
|
1182
|
+
function isTouchScreen() {
|
|
1183
|
+
return typeof window !== "undefined" && typeof window.matchMedia === "function" && window.matchMedia(TOUCH_MEDIA_QUERY).matches;
|
|
1184
|
+
}
|
|
1185
|
+
function contains(ref, target) {
|
|
1186
|
+
return target instanceof Node && ref.current?.contains(target) === true;
|
|
1187
|
+
}
|
|
1188
|
+
function hasSelection(within) {
|
|
1189
|
+
const selection = within.ownerDocument.defaultView?.getSelection();
|
|
1190
|
+
return !!selection && !selection.isCollapsed && selection.anchorNode != null && within.contains(selection.anchorNode);
|
|
1191
|
+
}
|
|
1192
|
+
function useExpanded(expandedProp, defaultExpanded, onExpandedChange) {
|
|
1193
|
+
const [expandedState, setExpandedState] = useState(defaultExpanded);
|
|
1194
|
+
const expanded = expandedProp ?? expandedState;
|
|
1195
|
+
return [expanded, useCallback(() => {
|
|
1196
|
+
const next = !expanded;
|
|
1197
|
+
if (expandedProp === void 0) setExpandedState(next);
|
|
1198
|
+
onExpandedChange?.(next);
|
|
1199
|
+
}, [
|
|
1200
|
+
expanded,
|
|
1201
|
+
expandedProp,
|
|
1202
|
+
onExpandedChange
|
|
1203
|
+
])];
|
|
1204
|
+
}
|
|
1205
|
+
/**
|
|
1206
|
+
* Registers the text with the shared measurer (lib/truncation.ts) and keeps
|
|
1207
|
+
* its answer: whether the text, alone, is cut, and whether it has a control
|
|
1208
|
+
* inside. While it is expanded the last collapsed answer is kept, so the
|
|
1209
|
+
* text and its control stay what they were until it collapses and is
|
|
1210
|
+
* measured again. `layout` names what remounts or reclamps the text.
|
|
1211
|
+
*/
|
|
1212
|
+
function useTruncation(expanded, layout, onNotTruncated) {
|
|
1213
|
+
const rootRef = useRef(null);
|
|
1214
|
+
const textRef = useRef(null);
|
|
1215
|
+
const contentRef = useRef(null);
|
|
1216
|
+
const afterRef = useRef(null);
|
|
1217
|
+
const setTextRef = useCallback((node) => {
|
|
1218
|
+
textRef.current = node;
|
|
1219
|
+
}, []);
|
|
1220
|
+
const [truncation, setTruncation] = useState(void 0);
|
|
1221
|
+
const [interactive, setInteractive] = useState(false);
|
|
1222
|
+
const expandedRef = useRef(expanded);
|
|
1223
|
+
const targetRef = useRef(null);
|
|
1224
|
+
const commit = useCallback((next) => {
|
|
1225
|
+
setInteractive(contentRef.current?.querySelector(INTERACTIVE) != null);
|
|
1226
|
+
if (expandedRef.current) return;
|
|
1227
|
+
setTruncation(next);
|
|
1228
|
+
if (next !== true) onNotTruncated();
|
|
1229
|
+
}, [onNotTruncated]);
|
|
1230
|
+
useLayoutEffect(() => {
|
|
1231
|
+
expandedRef.current = expanded;
|
|
1232
|
+
const root = rootRef.current;
|
|
1233
|
+
const text = textRef.current;
|
|
1234
|
+
const content = contentRef.current;
|
|
1235
|
+
if (!root || !text || !content) return void 0;
|
|
1236
|
+
const target = {
|
|
1237
|
+
observe: () => [text, afterRef.current],
|
|
1238
|
+
watch: () => content,
|
|
1239
|
+
isolate: () => {
|
|
1240
|
+
root.setAttribute("data-measuring", "");
|
|
1241
|
+
return () => root.removeAttribute("data-measuring");
|
|
1242
|
+
},
|
|
1243
|
+
read: () => measureContent(text, content),
|
|
1244
|
+
commit
|
|
1245
|
+
};
|
|
1246
|
+
targetRef.current = target;
|
|
1247
|
+
return observeTruncation(target);
|
|
1248
|
+
}, [
|
|
1249
|
+
commit,
|
|
1250
|
+
expanded,
|
|
1251
|
+
layout
|
|
1252
|
+
]);
|
|
1253
|
+
return {
|
|
1254
|
+
rootRef,
|
|
1255
|
+
textRef,
|
|
1256
|
+
setTextRef,
|
|
1257
|
+
contentRef,
|
|
1258
|
+
afterRef,
|
|
1259
|
+
truncation,
|
|
1260
|
+
interactive,
|
|
1261
|
+
measureNow: useCallback(() => {
|
|
1262
|
+
const target = targetRef.current;
|
|
1263
|
+
if (!target) return void 0;
|
|
1264
|
+
const next = readNow(target);
|
|
1265
|
+
commit(next);
|
|
1266
|
+
return next;
|
|
1267
|
+
}, [commit])
|
|
1268
|
+
};
|
|
1269
|
+
}
|
|
1270
|
+
/** The tooltip's `onOpenChange`: it opens only on a text measured as cut, now. */
|
|
1271
|
+
function useOpenWhenTruncated(setOpen, expanded, afterRef, measureNow) {
|
|
1272
|
+
return useCallback((next, details) => {
|
|
1273
|
+
if (!next) {
|
|
1274
|
+
setOpen(false);
|
|
1275
|
+
return;
|
|
1276
|
+
}
|
|
1277
|
+
if (isTouchScreen() || expanded) return;
|
|
1278
|
+
if (contains(afterRef, details.event?.target)) return;
|
|
1279
|
+
if (measureNow() === true) setOpen(true);
|
|
1280
|
+
}, [
|
|
1281
|
+
afterRef,
|
|
1282
|
+
expanded,
|
|
1283
|
+
measureNow,
|
|
1284
|
+
setOpen
|
|
1285
|
+
]);
|
|
1286
|
+
}
|
|
1287
|
+
/**
|
|
1288
|
+
* Makes the text the button that expands and collapses it, while
|
|
1289
|
+
* `clickable`. It stays one while expanded, `aria-expanded="true"`, so focus
|
|
1290
|
+
* stays on it and it collapses again the same way.
|
|
1291
|
+
*/
|
|
1292
|
+
function useExpandOnClick(clickable, expanded, toggle, textRef) {
|
|
1293
|
+
const onClick = useCallback(() => {
|
|
1294
|
+
if (!clickable) return;
|
|
1295
|
+
if (textRef.current && hasSelection(textRef.current)) return;
|
|
1296
|
+
toggle();
|
|
1297
|
+
}, [
|
|
1298
|
+
clickable,
|
|
1299
|
+
textRef,
|
|
1300
|
+
toggle
|
|
1301
|
+
]);
|
|
1302
|
+
const onKeyDown = useCallback((event) => {
|
|
1303
|
+
if (!clickable || event.target !== event.currentTarget) return;
|
|
1304
|
+
if (event.key === "Enter" || event.key === " ") {
|
|
1305
|
+
event.preventDefault();
|
|
1306
|
+
toggle();
|
|
1307
|
+
}
|
|
1308
|
+
}, [clickable, toggle]);
|
|
1309
|
+
if (!clickable) return {};
|
|
1310
|
+
return {
|
|
1311
|
+
role: "button",
|
|
1312
|
+
tabIndex: 0,
|
|
1313
|
+
"aria-expanded": expanded,
|
|
1314
|
+
onClick,
|
|
1315
|
+
onKeyDown
|
|
1316
|
+
};
|
|
1317
|
+
}
|
|
1318
|
+
function useRootStyle(style, lines) {
|
|
1319
|
+
return useMemo(() => lines > 1 ? {
|
|
1320
|
+
...style,
|
|
1321
|
+
["--ellipsis-lines"]: String(lines)
|
|
1322
|
+
} : style, [style, lines]);
|
|
1323
|
+
}
|
|
1324
|
+
function Ellipsis({ children, lines = 1, tooltip = true, after, expanded: expandedProp, defaultExpanded = false, onExpandedChange, expandOnClick = false, className, style, ...props }) {
|
|
1325
|
+
const textId = useId();
|
|
1326
|
+
const [open, setOpen] = useState(false);
|
|
1327
|
+
const closeTooltip = useCallback(() => setOpen(false), []);
|
|
1328
|
+
const [expanded, toggle] = useExpanded(expandedProp, defaultExpanded, onExpandedChange);
|
|
1329
|
+
const multiline = lines > 1;
|
|
1330
|
+
const hasTooltip = tooltip !== false && tooltip != null;
|
|
1331
|
+
const hasAfter = after != null;
|
|
1332
|
+
const measured = useTruncation(expanded, `${lines} ${hasAfter} ${hasTooltip}`, closeTooltip);
|
|
1333
|
+
const { rootRef, textRef, setTextRef, contentRef, afterRef, truncation } = measured;
|
|
1334
|
+
const handleOpenChange = useOpenWhenTruncated(setOpen, expanded, afterRef, measured.measureNow);
|
|
1335
|
+
const truncated = truncation === true && !expanded;
|
|
1336
|
+
const clickable = expandOnClick && !hasAfter && !measured.interactive && (truncation === true || expanded);
|
|
1337
|
+
const afterNode = typeof after === "function" ? after({
|
|
1338
|
+
truncated,
|
|
1339
|
+
expanded,
|
|
1340
|
+
toggle
|
|
1341
|
+
}) : after;
|
|
1342
|
+
const afterHidden = !truncated && !expanded;
|
|
1343
|
+
const slots = ellipsis({
|
|
1344
|
+
multiline,
|
|
1345
|
+
expanded,
|
|
1346
|
+
clickable
|
|
1347
|
+
});
|
|
1348
|
+
const context = useMemo(() => ({
|
|
1349
|
+
expanded,
|
|
1350
|
+
toggle,
|
|
1351
|
+
textId
|
|
1352
|
+
}), [
|
|
1353
|
+
expanded,
|
|
1354
|
+
toggle,
|
|
1355
|
+
textId
|
|
1356
|
+
]);
|
|
1357
|
+
const rootStyle = useRootStyle(style, lines);
|
|
1358
|
+
const clickProps = useExpandOnClick(clickable, expanded, toggle, textRef);
|
|
1359
|
+
const afterElement = hasAfter ? /* @__PURE__ */ jsx("span", {
|
|
1360
|
+
ref: afterRef,
|
|
1361
|
+
"data-slot": "ellipsis-after",
|
|
1362
|
+
"data-hidden": afterHidden ? "" : void 0,
|
|
1363
|
+
inert: afterHidden,
|
|
1364
|
+
className: slots.after(),
|
|
1365
|
+
onPointerEnter: closeTooltip,
|
|
1366
|
+
children: afterNode
|
|
1367
|
+
}) : null;
|
|
1368
|
+
const floatingAfter = multiline && hasAfter;
|
|
1369
|
+
const textChildren = /* @__PURE__ */ jsxs(Fragment$1, { children: [
|
|
1370
|
+
floatingAfter && /* @__PURE__ */ jsx("span", {
|
|
1371
|
+
"aria-hidden": true,
|
|
1372
|
+
"data-slot": "ellipsis-spacer",
|
|
1373
|
+
"data-hidden": afterHidden ? "" : void 0,
|
|
1374
|
+
className: slots.spacer()
|
|
1375
|
+
}),
|
|
1376
|
+
floatingAfter && afterElement,
|
|
1377
|
+
/* @__PURE__ */ jsx("span", {
|
|
1378
|
+
ref: contentRef,
|
|
1379
|
+
"data-slot": "ellipsis-content",
|
|
1380
|
+
className: slots.content(),
|
|
1381
|
+
children
|
|
1382
|
+
})
|
|
1383
|
+
] });
|
|
1384
|
+
const textProps = {
|
|
1385
|
+
id: textId,
|
|
1386
|
+
"data-slot": "ellipsis-text",
|
|
1387
|
+
"data-truncated": truncated ? "" : void 0,
|
|
1388
|
+
className: slots.text(),
|
|
1389
|
+
...clickProps
|
|
1390
|
+
};
|
|
1391
|
+
const text = hasTooltip ? /* @__PURE__ */ jsxs(Tooltip, {
|
|
1392
|
+
open: open && truncated,
|
|
1393
|
+
onOpenChange: handleOpenChange,
|
|
1394
|
+
children: [/* @__PURE__ */ jsx(TooltipTrigger, {
|
|
1395
|
+
ref: setTextRef,
|
|
1396
|
+
render: /* @__PURE__ */ jsx("span", {}),
|
|
1397
|
+
...textProps,
|
|
1398
|
+
className: slots.text({ class: "select-auto" }),
|
|
1399
|
+
children: textChildren
|
|
1400
|
+
}), /* @__PURE__ */ jsx(TooltipContent, { children: tooltip === true ? children : tooltip })]
|
|
1401
|
+
}) : /* @__PURE__ */ jsx("span", {
|
|
1402
|
+
ref: setTextRef,
|
|
1403
|
+
...textProps,
|
|
1404
|
+
children: textChildren
|
|
1405
|
+
});
|
|
1406
|
+
return /* @__PURE__ */ jsx(EllipsisContext.Provider, {
|
|
1407
|
+
value: context,
|
|
1408
|
+
children: /* @__PURE__ */ jsxs("span", {
|
|
1409
|
+
ref: rootRef,
|
|
1410
|
+
"data-slot": "ellipsis",
|
|
1411
|
+
className: slots.root({ className }),
|
|
1412
|
+
style: rootStyle,
|
|
1413
|
+
...props,
|
|
1414
|
+
children: [text, !multiline ? afterElement : null]
|
|
1415
|
+
})
|
|
1416
|
+
});
|
|
1417
|
+
}
|
|
1418
|
+
/**
|
|
1419
|
+
* The control that expands an Ellipsis and collapses it again, for its
|
|
1420
|
+
* `after`. A real button, with `aria-expanded` and `aria-controls` pointing
|
|
1421
|
+
* at the text. The label is the caller's: "Show More" / "Show Less".
|
|
1422
|
+
*/
|
|
1423
|
+
function EllipsisToggle({ onClick, ...props }) {
|
|
1424
|
+
const context = useContext(EllipsisContext);
|
|
1425
|
+
if (!context) throw new Error("EllipsisToggle must be inside an Ellipsis `after`.");
|
|
1426
|
+
const { expanded, toggle, textId } = context;
|
|
1427
|
+
const handleClick = useCallback((event) => {
|
|
1428
|
+
onClick?.(event);
|
|
1429
|
+
if (!event.defaultPrevented) toggle();
|
|
1430
|
+
}, [onClick, toggle]);
|
|
1431
|
+
return /* @__PURE__ */ jsx(TextLink, {
|
|
1432
|
+
"aria-expanded": expanded,
|
|
1433
|
+
"aria-controls": textId,
|
|
1434
|
+
onClick: handleClick,
|
|
1435
|
+
...props
|
|
1436
|
+
});
|
|
1437
|
+
}
|
|
1438
|
+
//#endregion
|
|
1439
|
+
//#region src/lib/use-truncated.ts
|
|
1440
|
+
/**
|
|
1441
|
+
* Whether the text in the element `ref` points at is cut off by its CSS
|
|
1442
|
+
* (`truncate`, `line-clamp`, a fixed size with `overflow: hidden`): `true`,
|
|
1443
|
+
* `false`, or `undefined` until it is measured or while it has no box.
|
|
1444
|
+
*
|
|
1445
|
+
* It measures fractional sizes with a 0.5px tolerance, past either inline
|
|
1446
|
+
* edge and below the bottom edge, so it needs no line count. It measures again
|
|
1447
|
+
* when the element changes size, when its text changes and when a web font
|
|
1448
|
+
* finishes loading, in one batched frame for every measured element on the
|
|
1449
|
+
* page (lib/truncation.ts), before that frame paints.
|
|
1450
|
+
*
|
|
1451
|
+
* The element is read when the component mounts: keep `ref` on one element
|
|
1452
|
+
* for the component's life, or give the component a `key` that changes with
|
|
1453
|
+
* the element.
|
|
1454
|
+
*/
|
|
1455
|
+
function useTruncated(ref) {
|
|
1456
|
+
const [truncated, setTruncated] = useState(void 0);
|
|
1457
|
+
useLayoutEffect(() => {
|
|
1458
|
+
const element = ref.current;
|
|
1459
|
+
if (!element) return void 0;
|
|
1460
|
+
return observeTruncation({
|
|
1461
|
+
observe: () => [element],
|
|
1462
|
+
watch: () => element,
|
|
1463
|
+
read: () => measureElement(element),
|
|
1464
|
+
commit: setTruncated
|
|
1465
|
+
});
|
|
1466
|
+
}, [ref]);
|
|
1467
|
+
return truncated;
|
|
1468
|
+
}
|
|
1469
|
+
//#endregion
|
|
1470
|
+
export { Dialog as AnnouncementDialog, AnnouncementDialogAction, AnnouncementDialogBody, DialogClose as AnnouncementDialogClose, AnnouncementDialogContent, AnnouncementDialogFooter, AnnouncementDialogHeader, AnnouncementDialogLabel, AnnouncementDialogPicture, AnnouncementDialogSecondaryAction, AnnouncementDialogText, AnnouncementDialogTitle, DialogTrigger as AnnouncementDialogTrigger, COMMENT_HIGHLIGHT, COMMENT_HIGHLIGHT_ACTIVE, ComboboxSelect, CommentCard, CommentCardMeta, CommentCardQuote, CommentCardTrigger, CommentEntry, CommentEntryAuthor, CommentEntryBody, CommentEntryHeader, CommentEntryTime, CommentMargin, CommentMarginItem, CommentMarker, Ellipsis, EllipsisToggle, MessageItemDelegatedAvatar, MessageItemDelegatedBy, MessageItemDelegatedByButton, MessageItemDelegatedByName, MessageListJumpControls, MessageListJumpPill, MessageListJumpPillDismiss, MessageListJumpPillGroup, MessageQuotedPreviewAuthorDelegatedBy, resolveCommentMarginLayout, setCommentHighlights, useCommentMarginFits, useHoldThenMoveTouchSensor, useTruncated };
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@botiverse/raft-ui",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.21.0",
|
|
4
4
|
"description": "React components and CSS foundations for the Raft Design System.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"agent-skills",
|
|
@@ -62,6 +62,7 @@
|
|
|
62
62
|
"tailwind-variants": "^3.3.1"
|
|
63
63
|
},
|
|
64
64
|
"devDependencies": {
|
|
65
|
+
"@babel/parser": "^7.29.9",
|
|
65
66
|
"@tailwindcss/vite": "^4.3.3",
|
|
66
67
|
"@testing-library/dom": "^10.4.2",
|
|
67
68
|
"@testing-library/react": "^16.3.3",
|
|
@@ -82,9 +83,15 @@
|
|
|
82
83
|
"vitest": "5.0.1"
|
|
83
84
|
},
|
|
84
85
|
"peerDependencies": {
|
|
86
|
+
"@babel/parser": "^7.29.9",
|
|
85
87
|
"react": "^19",
|
|
86
88
|
"react-dom": "^19"
|
|
87
89
|
},
|
|
90
|
+
"peerDependenciesMeta": {
|
|
91
|
+
"@babel/parser": {
|
|
92
|
+
"optional": true
|
|
93
|
+
}
|
|
94
|
+
},
|
|
88
95
|
"scripts": {
|
|
89
96
|
"bench:virtual-list": "node bench/virtual-list/run.mjs",
|
|
90
97
|
"build:tokens": "node scripts/build-tokens.mjs",
|