@reopt-ai/opt-ui 1.9.0 → 1.11.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/COMPONENT_CATALOG.md +177 -66
- package/README.md +21 -5
- package/dist/core/index.cjs +106 -104
- package/dist/core/index.d.cts +3 -3
- package/dist/core/index.d.ts +3 -3
- package/dist/core/index.js +3 -3
- package/dist/docs/02-components/01-core.md +92 -41
- package/dist/docs/02-components/02-visuals.md +1 -1
- package/dist/docs/02-components/03-shells.md +96 -26
- package/dist/docs/02-components/04-surfaces.md +1 -1
- package/dist/docs/02-components/index.md +5 -5
- package/dist/{field-sidebar-B5vk3luQ.d.cts → field-sidebar-B5SQC35J.d.cts} +226 -3
- package/dist/field-sidebar-B5SQC35J.d.cts.map +1 -0
- package/dist/{field-sidebar-B7QkWvMG.js → field-sidebar-BXl5RJ3q.js} +599 -43
- package/dist/field-sidebar-BXl5RJ3q.js.map +1 -0
- package/dist/{field-sidebar-Dk9gJGA_.d.ts → field-sidebar-CBeWE8xX.d.ts} +226 -3
- package/dist/field-sidebar-CBeWE8xX.d.ts.map +1 -0
- package/dist/{field-sidebar-mFHemxBz.cjs → field-sidebar-DAuN4jPV.cjs} +883 -309
- package/dist/id-registry.cjs +46 -6
- package/dist/id-registry.d.cts.map +1 -1
- package/dist/id-registry.d.ts.map +1 -1
- package/dist/id-registry.js +46 -6
- package/dist/id-registry.js.map +1 -1
- package/dist/id-registry.json +97 -12
- package/dist/index.cjs +593 -587
- package/dist/index.d.cts +10 -6
- package/dist/index.d.cts.map +1 -1
- package/dist/index.d.ts +10 -6
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +20 -19
- package/dist/index.js.map +1 -1
- package/dist/{key-pad-menu-D8OS_VCT.d.cts → key-pad-menu-BxTy_u0Q.d.cts} +152 -51
- package/dist/key-pad-menu-BxTy_u0Q.d.cts.map +1 -0
- package/dist/{key-pad-menu-DoGskWbp.cjs → key-pad-menu-Cg6rZBie.cjs} +670 -923
- package/dist/{key-pad-menu-EEb6Ho5h.d.ts → key-pad-menu-u5GTJl9B.d.ts} +152 -51
- package/dist/key-pad-menu-u5GTJl9B.d.ts.map +1 -0
- package/dist/{key-pad-menu-BFd79JoS.js → key-pad-menu-wXkWn1I1.js} +500 -699
- package/dist/key-pad-menu-wXkWn1I1.js.map +1 -0
- package/dist/meta.cjs +486 -9
- package/dist/meta.d.cts.map +1 -1
- package/dist/meta.d.ts.map +1 -1
- package/dist/meta.js +486 -9
- package/dist/meta.js.map +1 -1
- package/dist/shells/index.cjs +4 -1
- package/dist/shells/index.d.cts +2 -2
- package/dist/shells/index.d.ts +2 -2
- package/dist/shells/index.js +2 -2
- package/dist/{highlight-CGcrYGMC.cjs → text-truncate-BZdL1k5Z.cjs} +608 -83
- package/dist/{highlight-C2sfnJN8.js → text-truncate-C17HHCR-.js} +534 -87
- package/dist/text-truncate-C17HHCR-.js.map +1 -0
- package/dist/{field-token-CSOrU5gl.d.ts → text-truncate-DW78lg4S.d.cts} +63 -4
- package/dist/text-truncate-DW78lg4S.d.cts.map +1 -0
- package/dist/{field-token-CSOrU5gl.d.cts → text-truncate-DW78lg4S.d.ts} +63 -4
- package/dist/text-truncate-DW78lg4S.d.ts.map +1 -0
- package/package.json +2 -2
- package/dist/field-sidebar-B5vk3luQ.d.cts.map +0 -1
- package/dist/field-sidebar-B7QkWvMG.js.map +0 -1
- package/dist/field-sidebar-Dk9gJGA_.d.ts.map +0 -1
- package/dist/field-token-CSOrU5gl.d.cts.map +0 -1
- package/dist/field-token-CSOrU5gl.d.ts.map +0 -1
- package/dist/highlight-C2sfnJN8.js.map +0 -1
- package/dist/key-pad-menu-BFd79JoS.js.map +0 -1
- package/dist/key-pad-menu-D8OS_VCT.d.cts.map +0 -1
- package/dist/key-pad-menu-EEb6Ho5h.d.ts.map +0 -1
|
@@ -1,15 +1,15 @@
|
|
|
1
1
|
"use client";
|
|
2
|
-
import { $
|
|
2
|
+
import { $n as OPT_TEXT_PRIMARY, Bn as OPT_FOCUS_VISIBLE, Bt as SelectPopover$1, Gn as OPT_SURFACE, Hn as OPT_INPUT, Ht as SelectTrigger$1, Rt as SelectItem$1, Sn as getDescribedBy, Tn as OPT_ANIMATE_ENTER_EXIT, Vt as SelectRoot$1, Zn as OPT_TEXTAREA_SIZE, _t as MenuSeparator$1, bn as FieldMessages, d as formatOptNumber, er as OPT_TEXT_SECONDARY, ft as MenuItem$1, gt as MenuRoot$1, ht as MenuPopover$1, in as useInputId, ir as _objectWithoutProperties, jn as OPT_BORDER, ln as Button, on as Spinner, or as cn, rr as _objectSpread2, sn as Badge, tr as OPT_TEXT_TERTIARY, un as koBreadcrumbLabels, vt as MenuTrigger$1, wn as OPT_ANIMATE_DRAWER, xn as RequiredMark, yn as useControlledState, zn as OPT_FOCUS } from "./text-truncate-C17HHCR-.js";
|
|
3
3
|
import { Fragment, jsx, jsxs } from "react/jsx-runtime";
|
|
4
4
|
import * as React from "react";
|
|
5
5
|
import { createContext, createElement, forwardRef, useCallback, useContext, useEffect, useId, useImperativeHandle, useLayoutEffect, useMemo, useRef, useState } from "react";
|
|
6
|
-
import { AccordionContent, AccordionItem, AccordionRoot, AccordionTrigger, DialogDismiss, DialogPanel, DialogRoot,
|
|
7
|
-
import { Check, ChevronDown, GripVertical, Pencil, X } from "lucide-react";
|
|
6
|
+
import { AccordionContent, AccordionItem, AccordionRoot, AccordionTrigger, DialogDismiss, DialogPanel, DialogRoot, RadioGroupRoot, Separator, Toggle, ToggleGroup, useDialogClose, useRadioGroupContext } from "@reopt-ai/opt-ui-primitives";
|
|
7
|
+
import { Check, ChevronDown, Copy, GripVertical, Pencil, X } from "lucide-react";
|
|
8
8
|
import { Group, Panel, Separator as Separator$1 } from "react-resizable-panels";
|
|
9
9
|
import { Mesh, Program, Renderer, Triangle } from "ogl";
|
|
10
10
|
import { hexToSrgb } from "@reopt-ai/opt-palette";
|
|
11
11
|
//#region src/core/text.tsx
|
|
12
|
-
const _excluded$
|
|
12
|
+
const _excluded$15 = [
|
|
13
13
|
"as",
|
|
14
14
|
"variant",
|
|
15
15
|
"tone",
|
|
@@ -25,7 +25,7 @@ const toneStyles$1 = {
|
|
|
25
25
|
};
|
|
26
26
|
/** Semantic body text whose visual role is controlled by foundation tokens. */
|
|
27
27
|
function Text(_ref) {
|
|
28
|
-
let { as, variant = "body", tone = "primary", truncate = false, className, children } = _ref, props = _objectWithoutProperties(_ref, _excluded$
|
|
28
|
+
let { as, variant = "body", tone = "primary", truncate = false, className, children } = _ref, props = _objectWithoutProperties(_ref, _excluded$15);
|
|
29
29
|
const Component = as !== null && as !== void 0 ? as : "span";
|
|
30
30
|
const elementProps = _objectSpread2(_objectSpread2({}, props), {}, {
|
|
31
31
|
className: cn(`opt-type-${variant}`, toneStyles$1[tone], truncate && "truncate", className),
|
|
@@ -40,7 +40,7 @@ function Text(_ref) {
|
|
|
40
40
|
}
|
|
41
41
|
//#endregion
|
|
42
42
|
//#region src/core/heading.tsx
|
|
43
|
-
const _excluded$
|
|
43
|
+
const _excluded$14 = [
|
|
44
44
|
"level",
|
|
45
45
|
"variant",
|
|
46
46
|
"className",
|
|
@@ -48,7 +48,7 @@ const _excluded$16 = [
|
|
|
48
48
|
];
|
|
49
49
|
/** Semantic heading with independently selectable visual hierarchy. */
|
|
50
50
|
function Heading(_ref) {
|
|
51
|
-
let { level = 2, variant = `heading-${level}`, className, children } = _ref, props = _objectWithoutProperties(_ref, _excluded$
|
|
51
|
+
let { level = 2, variant = `heading-${level}`, className, children } = _ref, props = _objectWithoutProperties(_ref, _excluded$14);
|
|
52
52
|
const Component = {
|
|
53
53
|
1: "h1",
|
|
54
54
|
2: "h2",
|
|
@@ -267,25 +267,25 @@ function OtpField({ length = 6, value: controlledValue, defaultValue = "", onCha
|
|
|
267
267
|
OtpField.displayName = "OtpField";
|
|
268
268
|
//#endregion
|
|
269
269
|
//#region src/core/toggle.tsx
|
|
270
|
-
const _excluded$
|
|
270
|
+
const _excluded$13 = [
|
|
271
271
|
"size",
|
|
272
272
|
"className",
|
|
273
273
|
"children"
|
|
274
274
|
];
|
|
275
|
-
const _excluded2$
|
|
275
|
+
const _excluded2$7 = [
|
|
276
276
|
"className",
|
|
277
277
|
"children",
|
|
278
278
|
"orientation"
|
|
279
279
|
];
|
|
280
|
-
const sizeStyles$
|
|
280
|
+
const sizeStyles$7 = {
|
|
281
281
|
sm: "h-8 min-w-8 px-2 text-xs gap-1.5",
|
|
282
282
|
md: "h-10 min-w-10 px-3 text-sm gap-2"
|
|
283
283
|
};
|
|
284
284
|
const toggleBase = cn("inline-flex cursor-pointer items-center justify-center rounded-md border border-border bg-surface font-medium text-text-secondary", "hover:bg-bg-subtle hover:text-text-primary", "data-[pressed]:border-accent data-[pressed]:bg-accent-subtle data-[pressed]:text-accent", "disabled:pointer-events-none disabled:opacity-40", OPT_FOCUS_VISIBLE);
|
|
285
285
|
/** A two-state (pressed) button. Use standalone or inside `ToggleGroup`. */
|
|
286
286
|
function Toggle$1(_ref) {
|
|
287
|
-
let { size = "md", className, children } = _ref, props = _objectWithoutProperties(_ref, _excluded$
|
|
288
|
-
return /* @__PURE__ */ jsx(Toggle, _objectSpread2(_objectSpread2({ className: cn(toggleBase, sizeStyles$
|
|
287
|
+
let { size = "md", className, children } = _ref, props = _objectWithoutProperties(_ref, _excluded$13);
|
|
288
|
+
return /* @__PURE__ */ jsx(Toggle, _objectSpread2(_objectSpread2({ className: cn(toggleBase, sizeStyles$7[size], className) }, props), {}, {
|
|
289
289
|
"data-opt-id": "GFCMY",
|
|
290
290
|
"data-opt-slug": "toggle.Toggle",
|
|
291
291
|
children
|
|
@@ -294,7 +294,7 @@ function Toggle$1(_ref) {
|
|
|
294
294
|
Toggle$1.displayName = "Toggle";
|
|
295
295
|
/** A set of related toggles with shared selection and keyboard navigation. */
|
|
296
296
|
function ToggleGroup$1(_ref2) {
|
|
297
|
-
let { className, children, orientation = "horizontal" } = _ref2, props = _objectWithoutProperties(_ref2, _excluded2$
|
|
297
|
+
let { className, children, orientation = "horizontal" } = _ref2, props = _objectWithoutProperties(_ref2, _excluded2$7);
|
|
298
298
|
return /* @__PURE__ */ jsx(ToggleGroup, _objectSpread2(_objectSpread2({
|
|
299
299
|
orientation,
|
|
300
300
|
"aria-orientation": orientation,
|
|
@@ -308,15 +308,15 @@ function ToggleGroup$1(_ref2) {
|
|
|
308
308
|
ToggleGroup$1.displayName = "ToggleGroup";
|
|
309
309
|
//#endregion
|
|
310
310
|
//#region src/core/accordion.tsx
|
|
311
|
-
const _excluded$
|
|
312
|
-
const _excluded2$
|
|
313
|
-
const _excluded3$
|
|
314
|
-
const _excluded4$
|
|
311
|
+
const _excluded$12 = ["className"];
|
|
312
|
+
const _excluded2$6 = ["className"];
|
|
313
|
+
const _excluded3$3 = ["className", "children"];
|
|
314
|
+
const _excluded4$2 = ["className", "children"];
|
|
315
315
|
const triggerClass = `group/acc-trigger flex w-full cursor-pointer items-center justify-between gap-2 py-4 text-left text-sm font-medium text-text-primary transition-colors hover:text-text-secondary ${OPT_FOCUS} disabled:cursor-not-allowed disabled:opacity-50`;
|
|
316
316
|
const contentClass = `overflow-hidden text-sm text-text-secondary ${OPT_ANIMATE_ENTER_EXIT}`;
|
|
317
317
|
/** A vertically stacked set of expandable panels (single or multiple open). */
|
|
318
318
|
function AccordionRoot$1(_ref) {
|
|
319
|
-
let { className } = _ref, props = _objectWithoutProperties(_ref, _excluded$
|
|
319
|
+
let { className } = _ref, props = _objectWithoutProperties(_ref, _excluded$12);
|
|
320
320
|
return /* @__PURE__ */ jsx("div", {
|
|
321
321
|
className: cn("border-border border-y", className),
|
|
322
322
|
"data-opt-id": "CSBA9",
|
|
@@ -327,7 +327,7 @@ function AccordionRoot$1(_ref) {
|
|
|
327
327
|
AccordionRoot$1.displayName = "AccordionRoot";
|
|
328
328
|
/** A single accordion entry, identified by its `value`. */
|
|
329
329
|
function AccordionItem$1(_ref2) {
|
|
330
|
-
let { className } = _ref2, props = _objectWithoutProperties(_ref2, _excluded2$
|
|
330
|
+
let { className } = _ref2, props = _objectWithoutProperties(_ref2, _excluded2$6);
|
|
331
331
|
return /* @__PURE__ */ jsx(AccordionItem, _objectSpread2(_objectSpread2({ className: cn("border-border border-b last:border-b-0", className) }, props), {}, {
|
|
332
332
|
"data-opt-id": "JTY9M",
|
|
333
333
|
"data-opt-slug": "accordion.AccordionItem"
|
|
@@ -336,7 +336,7 @@ function AccordionItem$1(_ref2) {
|
|
|
336
336
|
AccordionItem$1.displayName = "AccordionItem";
|
|
337
337
|
/** The clickable header that expands/collapses its panel. */
|
|
338
338
|
function AccordionTrigger$1(_ref3) {
|
|
339
|
-
let { className, children } = _ref3, props = _objectWithoutProperties(_ref3, _excluded3$
|
|
339
|
+
let { className, children } = _ref3, props = _objectWithoutProperties(_ref3, _excluded3$3);
|
|
340
340
|
return /* @__PURE__ */ jsxs(AccordionTrigger, _objectSpread2(_objectSpread2({ className: cn(triggerClass, className) }, props), {}, {
|
|
341
341
|
"data-opt-id": "CWJZZ",
|
|
342
342
|
"data-opt-slug": "accordion.AccordionTrigger",
|
|
@@ -352,7 +352,7 @@ function AccordionTrigger$1(_ref3) {
|
|
|
352
352
|
AccordionTrigger$1.displayName = "AccordionTrigger";
|
|
353
353
|
/** The collapsible panel body associated with a trigger. */
|
|
354
354
|
function AccordionContent$1(_ref4) {
|
|
355
|
-
let { className, children } = _ref4, props = _objectWithoutProperties(_ref4, _excluded4$
|
|
355
|
+
let { className, children } = _ref4, props = _objectWithoutProperties(_ref4, _excluded4$2);
|
|
356
356
|
return /* @__PURE__ */ jsx(AccordionContent, _objectSpread2(_objectSpread2({ className: cn(contentClass, className) }, props), {}, {
|
|
357
357
|
"data-opt-id": "J98AG",
|
|
358
358
|
"data-opt-slug": "accordion.AccordionContent",
|
|
@@ -410,427 +410,111 @@ function Breadcrumb({ items, separator = "/", className, onNavigate, "aria-label
|
|
|
410
410
|
});
|
|
411
411
|
}
|
|
412
412
|
//#endregion
|
|
413
|
-
//#region src/core/
|
|
414
|
-
const
|
|
415
|
-
|
|
416
|
-
"
|
|
417
|
-
"
|
|
418
|
-
"selectable",
|
|
419
|
-
"selected",
|
|
420
|
-
"onSelectedChange",
|
|
421
|
-
"className",
|
|
422
|
-
"children",
|
|
423
|
-
"onClick",
|
|
424
|
-
"onKeyDown",
|
|
425
|
-
"role",
|
|
426
|
-
"tabIndex"
|
|
427
|
-
];
|
|
428
|
-
const _excluded2$6 = [
|
|
429
|
-
"gap",
|
|
430
|
-
"className",
|
|
431
|
-
"children"
|
|
432
|
-
];
|
|
433
|
-
const _excluded3$3 = [
|
|
434
|
-
"as",
|
|
435
|
-
"className",
|
|
436
|
-
"children"
|
|
437
|
-
];
|
|
438
|
-
const _excluded4$2 = ["className", "children"];
|
|
439
|
-
const _excluded5 = [
|
|
440
|
-
"spacing",
|
|
441
|
-
"className",
|
|
442
|
-
"children"
|
|
443
|
-
];
|
|
444
|
-
const _excluded6 = [
|
|
445
|
-
"divider",
|
|
446
|
-
"className",
|
|
447
|
-
"children"
|
|
448
|
-
];
|
|
449
|
-
/** Renders the card component. */
|
|
450
|
-
function Card(_ref) {
|
|
451
|
-
let { variant = "default", padding = "md", shadow = true, selectable = false, selected = false, onSelectedChange, className, children, onClick, onKeyDown, role, tabIndex } = _ref, props = _objectWithoutProperties(_ref, _excluded$13);
|
|
452
|
-
const isInteractive = selectable || !!onClick;
|
|
453
|
-
const handleClick = selectable ? (e) => {
|
|
454
|
-
onSelectedChange === null || onSelectedChange === void 0 || onSelectedChange(!selected);
|
|
455
|
-
onClick === null || onClick === void 0 || onClick(e);
|
|
456
|
-
} : onClick;
|
|
457
|
-
const handleKeyDown = selectable ? (e) => {
|
|
458
|
-
if (e.key === "Enter" || e.key === " ") {
|
|
459
|
-
e.preventDefault();
|
|
460
|
-
onSelectedChange === null || onSelectedChange === void 0 || onSelectedChange(!selected);
|
|
461
|
-
}
|
|
462
|
-
onKeyDown === null || onKeyDown === void 0 || onKeyDown(e);
|
|
463
|
-
} : isInteractive ? (e) => {
|
|
464
|
-
if (e.key === "Enter" || e.key === " ") {
|
|
465
|
-
e.preventDefault();
|
|
466
|
-
e.currentTarget.click();
|
|
467
|
-
}
|
|
468
|
-
onKeyDown === null || onKeyDown === void 0 || onKeyDown(e);
|
|
469
|
-
} : onKeyDown;
|
|
470
|
-
return /* @__PURE__ */ jsx("div", _objectSpread2(_objectSpread2(_objectSpread2({}, props), {}, { className: cn("rounded-xl", variant === "default" && cn(`border border-border bg-surface`, shadow && "shadow-sm"), variant === "outline" && "border-border border-2 bg-transparent", variant === "ghost" && "bg-bg-subtle", padding === "none" && "p-0", padding === "sm" && "p-3", padding === "md" && "p-5", padding === "lg" && "p-8", selectable && "cursor-pointer transition-colors", selectable && selected && "ring-accent border-accent ring-2 ring-offset-1", selectable && !selected && "hover:border-accent/50", className) }, isInteractive ? {
|
|
471
|
-
role: selectable ? "option" : "button",
|
|
472
|
-
tabIndex: 0,
|
|
473
|
-
"aria-selected": selectable ? selected : void 0,
|
|
474
|
-
onClick: handleClick,
|
|
475
|
-
onKeyDown: handleKeyDown
|
|
476
|
-
} : {
|
|
477
|
-
role,
|
|
478
|
-
tabIndex,
|
|
479
|
-
"aria-selected": selectable ? selected : void 0,
|
|
480
|
-
onKeyDown
|
|
481
|
-
}), {}, {
|
|
482
|
-
"data-opt-id": "0A18R",
|
|
483
|
-
"data-opt-slug": "card.Card",
|
|
484
|
-
children
|
|
485
|
-
}));
|
|
486
|
-
}
|
|
487
|
-
const headerGapClasses = {
|
|
488
|
-
sm: "gap-1",
|
|
489
|
-
md: "gap-1.5",
|
|
490
|
-
lg: "gap-2"
|
|
413
|
+
//#region src/core/description-list.tsx
|
|
414
|
+
const defaultLabels$3 = {
|
|
415
|
+
copy: (term) => `Copy ${term}`,
|
|
416
|
+
copied: "Copied",
|
|
417
|
+
empty: "—"
|
|
491
418
|
};
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
"data-opt-slug": "card.CardHeader",
|
|
498
|
-
children
|
|
499
|
-
}));
|
|
500
|
-
}
|
|
501
|
-
/** Renders the card title component. */
|
|
502
|
-
function CardTitle(_ref3) {
|
|
503
|
-
let { as: Tag = "h3", className, children } = _ref3, props = _objectWithoutProperties(_ref3, _excluded3$3);
|
|
504
|
-
return /* @__PURE__ */ jsx(Tag, _objectSpread2(_objectSpread2({ className: cn(`text-lg font-semibold ${OPT_TEXT_PRIMARY}`, className) }, props), {}, {
|
|
505
|
-
"data-opt-id": "V15TX",
|
|
506
|
-
"data-opt-slug": "card.CardTitle",
|
|
507
|
-
children
|
|
508
|
-
}));
|
|
509
|
-
}
|
|
510
|
-
/** Renders the card description component. */
|
|
511
|
-
function CardDescription(_ref4) {
|
|
512
|
-
let { className, children } = _ref4, props = _objectWithoutProperties(_ref4, _excluded4$2);
|
|
513
|
-
return /* @__PURE__ */ jsx("p", _objectSpread2(_objectSpread2({ className: cn(`text-sm ${OPT_TEXT_SECONDARY}`, className) }, props), {}, {
|
|
514
|
-
"data-opt-id": "YB1RN",
|
|
515
|
-
"data-opt-slug": "card.CardDescription",
|
|
516
|
-
children
|
|
517
|
-
}));
|
|
518
|
-
}
|
|
519
|
-
const contentSpacingClasses = {
|
|
520
|
-
none: "",
|
|
521
|
-
sm: "mt-2",
|
|
522
|
-
md: "mt-4",
|
|
523
|
-
lg: "mt-6"
|
|
419
|
+
const columnsClass = {
|
|
420
|
+
1: "grid-cols-1",
|
|
421
|
+
2: "grid-cols-1 sm:grid-cols-2",
|
|
422
|
+
3: "grid-cols-1 sm:grid-cols-2 lg:grid-cols-3",
|
|
423
|
+
4: "grid-cols-2 sm:grid-cols-3 lg:grid-cols-4"
|
|
524
424
|
};
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
}
|
|
534
|
-
|
|
535
|
-
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
"
|
|
539
|
-
|
|
540
|
-
|
|
541
|
-
|
|
425
|
+
function CopyButton({ value, label, copiedLabel }) {
|
|
426
|
+
const [copied, setCopied] = useState(false);
|
|
427
|
+
const handleCopy = useCallback(() => {
|
|
428
|
+
var _navigator$clipboard;
|
|
429
|
+
(_navigator$clipboard = navigator.clipboard) === null || _navigator$clipboard === void 0 || _navigator$clipboard.writeText(value).then(() => {
|
|
430
|
+
setCopied(true);
|
|
431
|
+
window.setTimeout(() => setCopied(false), 1500);
|
|
432
|
+
});
|
|
433
|
+
}, [value]);
|
|
434
|
+
return /* @__PURE__ */ jsx("button", {
|
|
435
|
+
type: "button",
|
|
436
|
+
onClick: handleCopy,
|
|
437
|
+
"aria-label": copied ? copiedLabel : label,
|
|
438
|
+
className: cn(OPT_FOCUS_VISIBLE, OPT_TEXT_TERTIARY, "hover:text-text-primary shrink-0 rounded p-0.5 transition-colors"),
|
|
439
|
+
children: copied ? /* @__PURE__ */ jsx(Check, {
|
|
440
|
+
className: "size-3.5",
|
|
441
|
+
"aria-hidden": "true"
|
|
442
|
+
}) : /* @__PURE__ */ jsx(Copy, {
|
|
443
|
+
className: "size-3.5",
|
|
444
|
+
"aria-hidden": "true"
|
|
445
|
+
})
|
|
446
|
+
});
|
|
542
447
|
}
|
|
543
|
-
|
|
544
|
-
|
|
545
|
-
|
|
546
|
-
|
|
547
|
-
|
|
548
|
-
|
|
549
|
-
|
|
550
|
-
|
|
551
|
-
|
|
552
|
-
|
|
553
|
-
|
|
554
|
-
|
|
555
|
-
|
|
556
|
-
|
|
557
|
-
|
|
558
|
-
|
|
559
|
-
|
|
560
|
-
|
|
561
|
-
|
|
562
|
-
|
|
563
|
-
|
|
564
|
-
|
|
565
|
-
|
|
566
|
-
|
|
567
|
-
|
|
568
|
-
|
|
569
|
-
|
|
570
|
-
|
|
571
|
-
|
|
572
|
-
|
|
573
|
-
|
|
574
|
-
|
|
575
|
-
|
|
576
|
-
|
|
577
|
-
|
|
578
|
-
};
|
|
579
|
-
const Switch = forwardRef((_ref, ref) => {
|
|
580
|
-
var _useInputId;
|
|
581
|
-
let { label, required, error, hint, description, checked: controlledChecked, defaultChecked = false, onChange, size = "md", disabled, className, id, onClick, "aria-label": ariaLabel, "aria-labelledby": ariaLabelledBy } = _ref, props = _objectWithoutProperties(_ref, _excluded$12);
|
|
582
|
-
const fallbackId = useId();
|
|
583
|
-
const switchId = (_useInputId = useInputId(id, label, "switch")) !== null && _useInputId !== void 0 ? _useInputId : `switch-${fallbackId}`;
|
|
584
|
-
const hintText = hint !== null && hint !== void 0 ? hint : description;
|
|
585
|
-
const hasError = Boolean(error);
|
|
586
|
-
const styles = sizeStyles$7[size];
|
|
587
|
-
const labelId = label ? `${switchId}-label` : void 0;
|
|
588
|
-
const switchLabelledBy = ariaLabelledBy !== null && ariaLabelledBy !== void 0 ? ariaLabelledBy : ariaLabel ? void 0 : labelId;
|
|
589
|
-
const switchAriaLabel = ariaLabel !== null && ariaLabel !== void 0 ? ariaLabel : switchLabelledBy ? void 0 : "Switch";
|
|
590
|
-
const isControlled = controlledChecked !== void 0;
|
|
591
|
-
const [internalChecked, setInternalChecked] = useState(defaultChecked);
|
|
592
|
-
const checked = isControlled ? controlledChecked : internalChecked;
|
|
593
|
-
const handleClick = useCallback((e) => {
|
|
594
|
-
const next = !checked;
|
|
595
|
-
if (!isControlled) setInternalChecked(next);
|
|
596
|
-
onChange === null || onChange === void 0 || onChange(next);
|
|
597
|
-
onClick === null || onClick === void 0 || onClick(e);
|
|
598
|
-
}, [
|
|
599
|
-
checked,
|
|
600
|
-
isControlled,
|
|
601
|
-
onChange,
|
|
602
|
-
onClick
|
|
603
|
-
]);
|
|
604
|
-
return /* @__PURE__ */ jsxs("div", {
|
|
605
|
-
className: cn("flex flex-col gap-1.5", className),
|
|
606
|
-
"data-opt-id": "51Z9R",
|
|
607
|
-
"data-opt-slug": "switch.Switch",
|
|
608
|
-
children: [/* @__PURE__ */ jsxs("div", {
|
|
609
|
-
className: "flex items-start gap-3",
|
|
610
|
-
children: [/* @__PURE__ */ jsx("button", _objectSpread2(_objectSpread2({
|
|
611
|
-
ref,
|
|
612
|
-
type: "button",
|
|
613
|
-
role: "switch",
|
|
614
|
-
id: switchId,
|
|
615
|
-
"aria-checked": checked,
|
|
616
|
-
"aria-label": switchAriaLabel,
|
|
617
|
-
"aria-labelledby": switchLabelledBy,
|
|
618
|
-
disabled,
|
|
619
|
-
className: cn("group relative inline-flex shrink-0 cursor-pointer rounded-full p-0.5 transition-colors", styles.track, "bg-bg-muted", "aria-[checked=true]:bg-accent", "disabled:cursor-not-allowed disabled:opacity-50", OPT_FOCUS_VISIBLE),
|
|
620
|
-
"aria-invalid": hasError,
|
|
621
|
-
"aria-required": required,
|
|
622
|
-
"aria-describedby": getDescribedBy(switchId, error, hintText),
|
|
623
|
-
onClick: handleClick
|
|
624
|
-
}, props), {}, { children: /* @__PURE__ */ jsx("span", { className: cn("pointer-events-none inline-block transform rounded-full bg-white shadow-sm ring-0 transition-transform", styles.thumb, "translate-x-0", size === "sm" && "group-aria-[checked=true]:translate-x-4", size === "md" && "group-aria-[checked=true]:translate-x-5", size === "lg" && "group-aria-[checked=true]:translate-x-7") }) })), (label || hintText) && /* @__PURE__ */ jsxs("div", {
|
|
625
|
-
className: "flex flex-col",
|
|
626
|
-
children: [label && /* @__PURE__ */ jsxs("span", {
|
|
627
|
-
id: labelId,
|
|
628
|
-
className: cn("text-text-primary text-sm font-medium", disabled && "opacity-50"),
|
|
629
|
-
children: [label, required && /* @__PURE__ */ jsx(RequiredMark, {})]
|
|
630
|
-
}), hintText && /* @__PURE__ */ jsx("p", {
|
|
631
|
-
id: `${switchId}-hint`,
|
|
632
|
-
className: cn("text-text-tertiary text-sm", disabled && "opacity-50"),
|
|
633
|
-
children: hintText
|
|
634
|
-
})]
|
|
448
|
+
/**
|
|
449
|
+
* DescriptionList — the labelled facts about one thing.
|
|
450
|
+
*
|
|
451
|
+
* Detail views collect a dozen short fields that each mean nothing without
|
|
452
|
+
* their label, and hand-rolling them as a `<div>` grid loses the term/value
|
|
453
|
+
* association that assistive tech needs. This keeps the pairs in a real `<dl>`
|
|
454
|
+
* while still laying them out as boxed cells.
|
|
455
|
+
*
|
|
456
|
+
* @example
|
|
457
|
+
* ```tsx
|
|
458
|
+
* <DescriptionList
|
|
459
|
+
* layout="grid"
|
|
460
|
+
* columns={2}
|
|
461
|
+
* items={[
|
|
462
|
+
* { id: "id", term: "Session ID", description: session.id, copyValue: session.id },
|
|
463
|
+
* { id: "entry", term: "Entry path", description: session.entryPath },
|
|
464
|
+
* ]}
|
|
465
|
+
* />
|
|
466
|
+
* ```
|
|
467
|
+
*/
|
|
468
|
+
function DescriptionList({ items, layout = "grid", columns = 2, compressed = false, labels: customLabels, className }) {
|
|
469
|
+
const labels = _objectSpread2(_objectSpread2({}, defaultLabels$3), customLabels);
|
|
470
|
+
if (layout === "inline") return /* @__PURE__ */ jsx("dl", {
|
|
471
|
+
className: cn("flex flex-wrap items-baseline gap-x-6 gap-y-2", className),
|
|
472
|
+
"data-opt-id": "1NPD2",
|
|
473
|
+
"data-opt-slug": "description-list.DescriptionList",
|
|
474
|
+
children: items.map((item) => /* @__PURE__ */ jsxs("div", {
|
|
475
|
+
className: "flex items-baseline gap-2",
|
|
476
|
+
children: [/* @__PURE__ */ jsx("dt", {
|
|
477
|
+
className: cn(OPT_TEXT_TERTIARY, "text-xs"),
|
|
478
|
+
title: item.hint,
|
|
479
|
+
children: item.term
|
|
480
|
+
}), /* @__PURE__ */ jsx("dd", {
|
|
481
|
+
className: cn(OPT_TEXT_PRIMARY, "text-sm font-medium"),
|
|
482
|
+
children: item.description || labels.empty
|
|
635
483
|
})]
|
|
636
|
-
}
|
|
637
|
-
id: switchId,
|
|
638
|
-
error
|
|
639
|
-
})]
|
|
484
|
+
}, item.id))
|
|
640
485
|
});
|
|
641
|
-
|
|
642
|
-
|
|
643
|
-
|
|
644
|
-
|
|
645
|
-
|
|
646
|
-
|
|
647
|
-
|
|
648
|
-
|
|
649
|
-
|
|
650
|
-
|
|
651
|
-
|
|
652
|
-
|
|
653
|
-
|
|
654
|
-
|
|
655
|
-
|
|
656
|
-
|
|
657
|
-
|
|
658
|
-
|
|
659
|
-
|
|
660
|
-
|
|
661
|
-
|
|
662
|
-
|
|
663
|
-
|
|
664
|
-
|
|
665
|
-
|
|
666
|
-
|
|
667
|
-
width: typeof width === "number" ? `${width}px` : width,
|
|
668
|
-
height: typeof height === "number" ? `${height}px` : height
|
|
669
|
-
}, style);
|
|
670
|
-
if (variant === "text" && lines > 1) return /* @__PURE__ */ jsxs("div", {
|
|
671
|
-
className: "gap-element flex flex-col",
|
|
672
|
-
role: "status",
|
|
673
|
-
"aria-label": "Loading",
|
|
674
|
-
"data-opt-id": "EJT87",
|
|
675
|
-
"data-opt-slug": "skeleton.Skeleton",
|
|
676
|
-
children: [Array.from({ length: lines }).map((_, i) => /* @__PURE__ */ jsx("div", _objectSpread2({
|
|
677
|
-
className: cn(baseClass, i === lines - 1 && "w-4/5"),
|
|
678
|
-
style: i === lines - 1 ? void 0 : computedStyle
|
|
679
|
-
}, props), i)), /* @__PURE__ */ jsx("span", {
|
|
680
|
-
className: "sr-only",
|
|
681
|
-
children: "Loading..."
|
|
682
|
-
})]
|
|
683
|
-
});
|
|
684
|
-
return /* @__PURE__ */ jsx("div", _objectSpread2(_objectSpread2({
|
|
685
|
-
className: baseClass,
|
|
686
|
-
style: computedStyle,
|
|
687
|
-
role: "status",
|
|
688
|
-
"aria-label": "Loading"
|
|
689
|
-
}, props), {}, {
|
|
690
|
-
"data-opt-id": "EJT87",
|
|
691
|
-
"data-opt-slug": "skeleton.Skeleton",
|
|
692
|
-
children: /* @__PURE__ */ jsx("span", {
|
|
693
|
-
className: "sr-only",
|
|
694
|
-
children: "Loading..."
|
|
695
|
-
})
|
|
696
|
-
}));
|
|
697
|
-
}
|
|
698
|
-
/** Renders the skeleton text component. */
|
|
699
|
-
function SkeletonText(_ref2) {
|
|
700
|
-
let { lines = 3, className } = _ref2, props = _objectWithoutProperties(_ref2, _excluded2$5);
|
|
701
|
-
return /* @__PURE__ */ jsx(Skeleton, _objectSpread2(_objectSpread2({
|
|
702
|
-
variant: "text",
|
|
703
|
-
lines,
|
|
704
|
-
className
|
|
705
|
-
}, props), {}, {
|
|
706
|
-
"data-opt-id": "MX3D5",
|
|
707
|
-
"data-opt-slug": "skeleton.SkeletonText"
|
|
708
|
-
}));
|
|
709
|
-
}
|
|
710
|
-
/** Renders the skeleton avatar component. */
|
|
711
|
-
function SkeletonAvatar(_ref3) {
|
|
712
|
-
let { size = 40, className } = _ref3, props = _objectWithoutProperties(_ref3, _excluded3$2);
|
|
713
|
-
return /* @__PURE__ */ jsx(Skeleton, _objectSpread2(_objectSpread2({
|
|
714
|
-
variant: "circular",
|
|
715
|
-
width: size,
|
|
716
|
-
height: size,
|
|
717
|
-
className
|
|
718
|
-
}, props), {}, {
|
|
719
|
-
"data-opt-id": "MP0HZ",
|
|
720
|
-
"data-opt-slug": "skeleton.SkeletonAvatar"
|
|
721
|
-
}));
|
|
722
|
-
}
|
|
723
|
-
/** Renders the skeleton card component. */
|
|
724
|
-
function SkeletonCard(_ref4) {
|
|
725
|
-
let { className } = _ref4, props = _objectWithoutProperties(_ref4, _excluded4$1);
|
|
726
|
-
return /* @__PURE__ */ jsxs("div", _objectSpread2(_objectSpread2({ className: cn("gap-group flex flex-col", className) }, props), {}, {
|
|
727
|
-
"data-opt-id": "34V5D",
|
|
728
|
-
"data-opt-slug": "skeleton.SkeletonCard",
|
|
729
|
-
children: [
|
|
730
|
-
/* @__PURE__ */ jsx(Skeleton, {
|
|
731
|
-
variant: "rectangular",
|
|
732
|
-
height: 120
|
|
733
|
-
}),
|
|
734
|
-
/* @__PURE__ */ jsx(Skeleton, {
|
|
735
|
-
variant: "text",
|
|
736
|
-
width: "60%"
|
|
737
|
-
}),
|
|
738
|
-
/* @__PURE__ */ jsx(Skeleton, {
|
|
739
|
-
variant: "text",
|
|
740
|
-
lines: 2
|
|
741
|
-
})
|
|
742
|
-
]
|
|
743
|
-
}));
|
|
744
|
-
}
|
|
745
|
-
/** Renders the skeleton table component. */
|
|
746
|
-
function SkeletonTable({ rows = 5, columns = 4, className }) {
|
|
747
|
-
return /* @__PURE__ */ jsxs("div", {
|
|
748
|
-
className: cn("gap-element flex flex-col", className),
|
|
749
|
-
role: "status",
|
|
750
|
-
"aria-label": "Loading table",
|
|
751
|
-
"data-opt-id": "3KEDN",
|
|
752
|
-
"data-opt-slug": "skeleton.SkeletonTable",
|
|
753
|
-
children: [
|
|
754
|
-
/* @__PURE__ */ jsx("div", {
|
|
755
|
-
className: "border-border-subtle gap-group flex border-b pb-2",
|
|
756
|
-
children: Array.from({ length: columns }).map((_, i) => /* @__PURE__ */ jsx(Skeleton, {
|
|
757
|
-
variant: "text",
|
|
758
|
-
className: "flex-1",
|
|
759
|
-
height: 16
|
|
760
|
-
}, i))
|
|
761
|
-
}),
|
|
762
|
-
Array.from({ length: rows }).map((_, rowIndex) => /* @__PURE__ */ jsx("div", {
|
|
763
|
-
className: "gap-group flex py-2",
|
|
764
|
-
children: Array.from({ length: columns }).map((_, colIndex) => /* @__PURE__ */ jsx(Skeleton, {
|
|
765
|
-
variant: "text",
|
|
766
|
-
className: "flex-1",
|
|
767
|
-
height: 14
|
|
768
|
-
}, colIndex))
|
|
769
|
-
}, rowIndex)),
|
|
770
|
-
/* @__PURE__ */ jsx("span", {
|
|
771
|
-
className: "sr-only",
|
|
772
|
-
children: "Loading..."
|
|
773
|
-
})
|
|
774
|
-
]
|
|
486
|
+
return /* @__PURE__ */ jsx("dl", {
|
|
487
|
+
className: cn("grid", compressed ? "gap-element" : "gap-group", columnsClass[columns], className),
|
|
488
|
+
"data-opt-id": "1NPD2",
|
|
489
|
+
"data-opt-slug": "description-list.DescriptionList",
|
|
490
|
+
children: items.map((item) => /* @__PURE__ */ jsxs("div", {
|
|
491
|
+
className: cn("flex min-w-0 flex-col gap-1", layout === "grid" && [
|
|
492
|
+
"border border-border",
|
|
493
|
+
"bg-bg-subtle rounded-lg",
|
|
494
|
+
compressed ? "px-2.5 py-1.5" : "px-3 py-2"
|
|
495
|
+
]),
|
|
496
|
+
children: [/* @__PURE__ */ jsx("dt", {
|
|
497
|
+
className: cn(OPT_TEXT_TERTIARY, "text-xs"),
|
|
498
|
+
title: item.hint,
|
|
499
|
+
children: item.term
|
|
500
|
+
}), /* @__PURE__ */ jsxs("dd", {
|
|
501
|
+
className: cn(OPT_TEXT_PRIMARY, "flex min-w-0 items-center gap-1.5 text-sm"),
|
|
502
|
+
children: [/* @__PURE__ */ jsx("span", {
|
|
503
|
+
className: cn("min-w-0", item.wrap ? "break-all" : "truncate", !item.description && "text-text-secondary"),
|
|
504
|
+
children: item.description || labels.empty
|
|
505
|
+
}), item.copyValue && /* @__PURE__ */ jsx(CopyButton, {
|
|
506
|
+
value: item.copyValue,
|
|
507
|
+
label: labels.copy(typeof item.term === "string" ? item.term : item.id),
|
|
508
|
+
copiedLabel: labels.copied
|
|
509
|
+
})]
|
|
510
|
+
})]
|
|
511
|
+
}, item.id))
|
|
775
512
|
});
|
|
776
513
|
}
|
|
777
|
-
|
|
778
|
-
//#region src/core/textarea.tsx
|
|
779
|
-
const _excluded$10 = [
|
|
780
|
-
"label",
|
|
781
|
-
"error",
|
|
782
|
-
"hint",
|
|
783
|
-
"fullWidth",
|
|
784
|
-
"required",
|
|
785
|
-
"resize",
|
|
786
|
-
"size",
|
|
787
|
-
"className",
|
|
788
|
-
"id",
|
|
789
|
-
"rows"
|
|
790
|
-
];
|
|
791
|
-
const textareaSizeStyles = OPT_TEXTAREA_SIZE;
|
|
792
|
-
const resizeStyles = {
|
|
793
|
-
none: "resize-none",
|
|
794
|
-
vertical: "resize-y",
|
|
795
|
-
horizontal: "resize-x",
|
|
796
|
-
both: "resize"
|
|
797
|
-
};
|
|
798
|
-
const Textarea = forwardRef((_ref, ref) => {
|
|
799
|
-
var _useInputId;
|
|
800
|
-
let { label, error, hint, fullWidth = false, required, resize = "vertical", size = "md", className, id, rows = 4 } = _ref, props = _objectWithoutProperties(_ref, _excluded$10);
|
|
801
|
-
const fallbackId = useId().replace(/:/g, "");
|
|
802
|
-
const textareaId = (_useInputId = useInputId(id, label, "textarea")) !== null && _useInputId !== void 0 ? _useInputId : `textarea-${fallbackId}`;
|
|
803
|
-
const hasError = Boolean(error);
|
|
804
|
-
return /* @__PURE__ */ jsxs("div", {
|
|
805
|
-
className: cn("flex flex-col gap-1.5", fullWidth && "w-full"),
|
|
806
|
-
"data-opt-id": "6T58H",
|
|
807
|
-
"data-opt-slug": "textarea.Textarea",
|
|
808
|
-
children: [
|
|
809
|
-
label && /* @__PURE__ */ jsxs("label", {
|
|
810
|
-
htmlFor: textareaId,
|
|
811
|
-
className: "text-text-primary text-sm font-medium",
|
|
812
|
-
children: [label, required && /* @__PURE__ */ jsx(RequiredMark, {})]
|
|
813
|
-
}),
|
|
814
|
-
/* @__PURE__ */ jsx("textarea", _objectSpread2({
|
|
815
|
-
ref,
|
|
816
|
-
id: textareaId,
|
|
817
|
-
rows,
|
|
818
|
-
className: cn("border-border bg-surface text-text-primary placeholder:text-text-tertiary w-full rounded-lg border px-4 py-3 text-sm outline-transparent", OPT_FOCUS_VISIBLE, textareaSizeStyles[size], resizeStyles[resize], hasError && "border-danger focus-visible:outline-danger", !fullWidth && "w-auto", className),
|
|
819
|
-
"aria-invalid": hasError,
|
|
820
|
-
"aria-describedby": getDescribedBy(textareaId, error, hint)
|
|
821
|
-
}, props)),
|
|
822
|
-
/* @__PURE__ */ jsx(FieldMessages, {
|
|
823
|
-
id: textareaId,
|
|
824
|
-
error,
|
|
825
|
-
hint
|
|
826
|
-
})
|
|
827
|
-
]
|
|
828
|
-
});
|
|
829
|
-
});
|
|
830
|
-
Textarea.displayName = "Textarea";
|
|
514
|
+
DescriptionList.displayName = "DescriptionList";
|
|
831
515
|
//#endregion
|
|
832
516
|
//#region src/core/avatar.tsx
|
|
833
|
-
const _excluded$
|
|
517
|
+
const _excluded$11 = [
|
|
834
518
|
"src",
|
|
835
519
|
"srcSet",
|
|
836
520
|
"sizes",
|
|
@@ -844,7 +528,7 @@ const _excluded$9 = [
|
|
|
844
528
|
"className",
|
|
845
529
|
"onLoadingStatusChange"
|
|
846
530
|
];
|
|
847
|
-
const _excluded2$
|
|
531
|
+
const _excluded2$5 = [
|
|
848
532
|
"max",
|
|
849
533
|
"size",
|
|
850
534
|
"children",
|
|
@@ -932,7 +616,7 @@ function getColorFromName(name) {
|
|
|
932
616
|
/** Renders the avatar component. */
|
|
933
617
|
function Avatar(_ref) {
|
|
934
618
|
var _ref2, _ref3;
|
|
935
|
-
let { src, srcSet, sizes, crossOrigin, referrerPolicy, alt, name, size = "md", fallback, status, className, onLoadingStatusChange } = _ref, props = _objectWithoutProperties(_ref, _excluded$
|
|
619
|
+
let { src, srcSet, sizes, crossOrigin, referrerPolicy, alt, name, size = "md", fallback, status, className, onLoadingStatusChange } = _ref, props = _objectWithoutProperties(_ref, _excluded$11);
|
|
936
620
|
const loadingStatus = useImageLoadingStatus(src, {
|
|
937
621
|
srcSet,
|
|
938
622
|
sizes,
|
|
@@ -983,27 +667,380 @@ function Avatar(_ref) {
|
|
|
983
667
|
})]
|
|
984
668
|
}));
|
|
985
669
|
}
|
|
986
|
-
/** Renders the avatar group component. */
|
|
987
|
-
function AvatarGroup(_ref5) {
|
|
988
|
-
let { max = 4, size = "md", children, className } = _ref5, props = _objectWithoutProperties(_ref5, _excluded2$
|
|
989
|
-
const avatars = Array.isArray(children) ? children : [children];
|
|
990
|
-
const visibleAvatars = avatars.slice(0, max);
|
|
991
|
-
const remainingCount = avatars.length - max;
|
|
992
|
-
return /* @__PURE__ */ jsxs("div", _objectSpread2(_objectSpread2({ className: cn("flex", className) }, props), {}, {
|
|
993
|
-
"data-opt-id": "MVB53",
|
|
994
|
-
"data-opt-slug": "avatar.AvatarGroup",
|
|
995
|
-
children: [visibleAvatars.map((child, index) => /* @__PURE__ */ jsx("span", {
|
|
996
|
-
className: "ring-surface relative -ml-2 inline-block rounded-full ring-2 first:ml-0",
|
|
997
|
-
children: child
|
|
998
|
-
}, index)), remainingCount > 0 && /* @__PURE__ */ jsxs("span", {
|
|
999
|
-
className: cn("bg-bg-subtle text-text-secondary ring-surface relative inline-flex items-center justify-center rounded-full font-medium ring-2", sizeStyles$6[size]),
|
|
1000
|
-
children: ["+", remainingCount]
|
|
670
|
+
/** Renders the avatar group component. */
|
|
671
|
+
function AvatarGroup(_ref5) {
|
|
672
|
+
let { max = 4, size = "md", children, className } = _ref5, props = _objectWithoutProperties(_ref5, _excluded2$5);
|
|
673
|
+
const avatars = Array.isArray(children) ? children : [children];
|
|
674
|
+
const visibleAvatars = avatars.slice(0, max);
|
|
675
|
+
const remainingCount = avatars.length - max;
|
|
676
|
+
return /* @__PURE__ */ jsxs("div", _objectSpread2(_objectSpread2({ className: cn("flex", className) }, props), {}, {
|
|
677
|
+
"data-opt-id": "MVB53",
|
|
678
|
+
"data-opt-slug": "avatar.AvatarGroup",
|
|
679
|
+
children: [visibleAvatars.map((child, index) => /* @__PURE__ */ jsx("span", {
|
|
680
|
+
className: "ring-surface relative -ml-2 inline-block rounded-full ring-2 first:ml-0",
|
|
681
|
+
children: child
|
|
682
|
+
}, index)), remainingCount > 0 && /* @__PURE__ */ jsxs("span", {
|
|
683
|
+
className: cn("bg-bg-subtle text-text-secondary ring-surface relative inline-flex items-center justify-center rounded-full font-medium ring-2", sizeStyles$6[size]),
|
|
684
|
+
children: ["+", remainingCount]
|
|
685
|
+
})]
|
|
686
|
+
}));
|
|
687
|
+
}
|
|
688
|
+
//#endregion
|
|
689
|
+
//#region src/core/identity.tsx
|
|
690
|
+
const defaultLabels$2 = {
|
|
691
|
+
identified: "Identified",
|
|
692
|
+
anonymous: "Anonymous"
|
|
693
|
+
};
|
|
694
|
+
/** Picks the display name, degrading through the identifiers we do have. */
|
|
695
|
+
function resolveDisplay(name, secondary, id) {
|
|
696
|
+
const trimmedName = name === null || name === void 0 ? void 0 : name.trim();
|
|
697
|
+
const trimmedSecondary = secondary === null || secondary === void 0 ? void 0 : secondary.trim();
|
|
698
|
+
if (trimmedName) return {
|
|
699
|
+
primary: trimmedName,
|
|
700
|
+
sub: trimmedSecondary || null
|
|
701
|
+
};
|
|
702
|
+
if (trimmedSecondary) return {
|
|
703
|
+
primary: trimmedSecondary,
|
|
704
|
+
sub: null
|
|
705
|
+
};
|
|
706
|
+
return {
|
|
707
|
+
primary: id !== null && id !== void 0 ? id : "—",
|
|
708
|
+
sub: null
|
|
709
|
+
};
|
|
710
|
+
}
|
|
711
|
+
/**
|
|
712
|
+
* Identity — one person (or one anonymous device) as a table cell.
|
|
713
|
+
*
|
|
714
|
+
* Every analytics surface renders the same fallback chain — name, then email,
|
|
715
|
+
* then an opaque id — and every hand-rolled copy of it drifts. Centralising it
|
|
716
|
+
* also centralises the anonymity marker, which is the part readers most often
|
|
717
|
+
* lose track of when a table mixes profiles and devices.
|
|
718
|
+
*/
|
|
719
|
+
function Identity({ name, secondary, id, avatarSrc, state, badge, size = "md", hideAvatar = false, labels: customLabels, className }) {
|
|
720
|
+
const labels = _objectSpread2(_objectSpread2({}, defaultLabels$2), customLabels);
|
|
721
|
+
const { primary, sub } = resolveDisplay(name, secondary, id);
|
|
722
|
+
const anonymous = state === "anonymous";
|
|
723
|
+
const badgeContent = badge !== null && badge !== void 0 ? badge : state ? anonymous ? labels.anonymous : labels.identified : null;
|
|
724
|
+
return /* @__PURE__ */ jsxs("span", {
|
|
725
|
+
className: cn("flex min-w-0 items-center gap-2", className),
|
|
726
|
+
title: id,
|
|
727
|
+
"data-opt-id": "BRGG2",
|
|
728
|
+
"data-opt-slug": "identity.Identity",
|
|
729
|
+
children: [!hideAvatar && /* @__PURE__ */ jsx(Avatar, {
|
|
730
|
+
src: avatarSrc !== null && avatarSrc !== void 0 ? avatarSrc : void 0,
|
|
731
|
+
name: anonymous ? void 0 : primary,
|
|
732
|
+
size: size === "sm" ? "xs" : "sm",
|
|
733
|
+
alt: "",
|
|
734
|
+
className: "shrink-0"
|
|
735
|
+
}), /* @__PURE__ */ jsxs("span", {
|
|
736
|
+
className: "flex min-w-0 flex-col",
|
|
737
|
+
children: [/* @__PURE__ */ jsxs("span", {
|
|
738
|
+
className: "flex min-w-0 items-center gap-1.5",
|
|
739
|
+
children: [/* @__PURE__ */ jsx("span", {
|
|
740
|
+
className: cn("truncate text-sm font-medium", anonymous && !name ? OPT_TEXT_SECONDARY : OPT_TEXT_PRIMARY),
|
|
741
|
+
children: primary
|
|
742
|
+
}), badgeContent && /* @__PURE__ */ jsx(Badge, {
|
|
743
|
+
size: "sm",
|
|
744
|
+
variant: anonymous ? "default" : "info",
|
|
745
|
+
className: "shrink-0",
|
|
746
|
+
children: badgeContent
|
|
747
|
+
})]
|
|
748
|
+
}), sub && /* @__PURE__ */ jsx("span", {
|
|
749
|
+
className: cn("text-text-tertiary", "truncate text-xs"),
|
|
750
|
+
children: sub
|
|
751
|
+
})]
|
|
752
|
+
})]
|
|
753
|
+
});
|
|
754
|
+
}
|
|
755
|
+
Identity.displayName = "Identity";
|
|
756
|
+
//#endregion
|
|
757
|
+
//#region src/core/card.tsx
|
|
758
|
+
const _excluded$10 = [
|
|
759
|
+
"variant",
|
|
760
|
+
"padding",
|
|
761
|
+
"shadow",
|
|
762
|
+
"selectable",
|
|
763
|
+
"selected",
|
|
764
|
+
"onSelectedChange",
|
|
765
|
+
"className",
|
|
766
|
+
"children",
|
|
767
|
+
"onClick",
|
|
768
|
+
"onKeyDown",
|
|
769
|
+
"role",
|
|
770
|
+
"tabIndex"
|
|
771
|
+
];
|
|
772
|
+
const _excluded2$4 = [
|
|
773
|
+
"gap",
|
|
774
|
+
"className",
|
|
775
|
+
"children"
|
|
776
|
+
];
|
|
777
|
+
const _excluded3$2 = [
|
|
778
|
+
"as",
|
|
779
|
+
"className",
|
|
780
|
+
"children"
|
|
781
|
+
];
|
|
782
|
+
const _excluded4$1 = ["className", "children"];
|
|
783
|
+
const _excluded5 = [
|
|
784
|
+
"spacing",
|
|
785
|
+
"className",
|
|
786
|
+
"children"
|
|
787
|
+
];
|
|
788
|
+
const _excluded6 = [
|
|
789
|
+
"divider",
|
|
790
|
+
"className",
|
|
791
|
+
"children"
|
|
792
|
+
];
|
|
793
|
+
/** Renders the card component. */
|
|
794
|
+
function Card(_ref) {
|
|
795
|
+
let { variant = "default", padding = "md", shadow = true, selectable = false, selected = false, onSelectedChange, className, children, onClick, onKeyDown, role, tabIndex } = _ref, props = _objectWithoutProperties(_ref, _excluded$10);
|
|
796
|
+
const isInteractive = selectable || !!onClick;
|
|
797
|
+
const handleClick = selectable ? (e) => {
|
|
798
|
+
onSelectedChange === null || onSelectedChange === void 0 || onSelectedChange(!selected);
|
|
799
|
+
onClick === null || onClick === void 0 || onClick(e);
|
|
800
|
+
} : onClick;
|
|
801
|
+
const handleKeyDown = selectable ? (e) => {
|
|
802
|
+
if (e.key === "Enter" || e.key === " ") {
|
|
803
|
+
e.preventDefault();
|
|
804
|
+
onSelectedChange === null || onSelectedChange === void 0 || onSelectedChange(!selected);
|
|
805
|
+
}
|
|
806
|
+
onKeyDown === null || onKeyDown === void 0 || onKeyDown(e);
|
|
807
|
+
} : isInteractive ? (e) => {
|
|
808
|
+
if (e.key === "Enter" || e.key === " ") {
|
|
809
|
+
e.preventDefault();
|
|
810
|
+
e.currentTarget.click();
|
|
811
|
+
}
|
|
812
|
+
onKeyDown === null || onKeyDown === void 0 || onKeyDown(e);
|
|
813
|
+
} : onKeyDown;
|
|
814
|
+
return /* @__PURE__ */ jsx("div", _objectSpread2(_objectSpread2(_objectSpread2({}, props), {}, { className: cn("rounded-xl", variant === "default" && cn(`border border-border bg-surface`, shadow && "shadow-sm"), variant === "outline" && "border-border border-2 bg-transparent", variant === "ghost" && "bg-bg-subtle", padding === "none" && "p-0", padding === "sm" && "p-3", padding === "md" && "p-5", padding === "lg" && "p-8", selectable && "cursor-pointer transition-colors", selectable && selected && "ring-accent border-accent ring-2 ring-offset-1", selectable && !selected && "hover:border-accent/50", className) }, isInteractive ? {
|
|
815
|
+
role: selectable ? "option" : "button",
|
|
816
|
+
tabIndex: 0,
|
|
817
|
+
"aria-selected": selectable ? selected : void 0,
|
|
818
|
+
onClick: handleClick,
|
|
819
|
+
onKeyDown: handleKeyDown
|
|
820
|
+
} : {
|
|
821
|
+
role,
|
|
822
|
+
tabIndex,
|
|
823
|
+
"aria-selected": selectable ? selected : void 0,
|
|
824
|
+
onKeyDown
|
|
825
|
+
}), {}, {
|
|
826
|
+
"data-opt-id": "0A18R",
|
|
827
|
+
"data-opt-slug": "card.Card",
|
|
828
|
+
children
|
|
829
|
+
}));
|
|
830
|
+
}
|
|
831
|
+
const headerGapClasses = {
|
|
832
|
+
sm: "gap-1",
|
|
833
|
+
md: "gap-1.5",
|
|
834
|
+
lg: "gap-2"
|
|
835
|
+
};
|
|
836
|
+
/** Renders the card header component. */
|
|
837
|
+
function CardHeader(_ref2) {
|
|
838
|
+
let { gap = "sm", className, children } = _ref2, props = _objectWithoutProperties(_ref2, _excluded2$4);
|
|
839
|
+
return /* @__PURE__ */ jsx("div", _objectSpread2(_objectSpread2({ className: cn("flex flex-col", headerGapClasses[gap], className) }, props), {}, {
|
|
840
|
+
"data-opt-id": "JST3J",
|
|
841
|
+
"data-opt-slug": "card.CardHeader",
|
|
842
|
+
children
|
|
843
|
+
}));
|
|
844
|
+
}
|
|
845
|
+
/** Renders the card title component. */
|
|
846
|
+
function CardTitle(_ref3) {
|
|
847
|
+
let { as: Tag = "h3", className, children } = _ref3, props = _objectWithoutProperties(_ref3, _excluded3$2);
|
|
848
|
+
return /* @__PURE__ */ jsx(Tag, _objectSpread2(_objectSpread2({ className: cn(`text-lg font-semibold ${OPT_TEXT_PRIMARY}`, className) }, props), {}, {
|
|
849
|
+
"data-opt-id": "V15TX",
|
|
850
|
+
"data-opt-slug": "card.CardTitle",
|
|
851
|
+
children
|
|
852
|
+
}));
|
|
853
|
+
}
|
|
854
|
+
/** Renders the card description component. */
|
|
855
|
+
function CardDescription(_ref4) {
|
|
856
|
+
let { className, children } = _ref4, props = _objectWithoutProperties(_ref4, _excluded4$1);
|
|
857
|
+
return /* @__PURE__ */ jsx("p", _objectSpread2(_objectSpread2({ className: cn(`text-sm ${OPT_TEXT_SECONDARY}`, className) }, props), {}, {
|
|
858
|
+
"data-opt-id": "YB1RN",
|
|
859
|
+
"data-opt-slug": "card.CardDescription",
|
|
860
|
+
children
|
|
861
|
+
}));
|
|
862
|
+
}
|
|
863
|
+
const contentSpacingClasses = {
|
|
864
|
+
none: "",
|
|
865
|
+
sm: "mt-2",
|
|
866
|
+
md: "mt-4",
|
|
867
|
+
lg: "mt-6"
|
|
868
|
+
};
|
|
869
|
+
/** Renders the card content component. */
|
|
870
|
+
function CardContent(_ref5) {
|
|
871
|
+
let { spacing = "md", className, children } = _ref5, props = _objectWithoutProperties(_ref5, _excluded5);
|
|
872
|
+
return /* @__PURE__ */ jsx("div", _objectSpread2(_objectSpread2({ className: cn(contentSpacingClasses[spacing], className) }, props), {}, {
|
|
873
|
+
"data-opt-id": "9Y68R",
|
|
874
|
+
"data-opt-slug": "card.CardContent",
|
|
875
|
+
children
|
|
876
|
+
}));
|
|
877
|
+
}
|
|
878
|
+
/** Renders the card footer component. */
|
|
879
|
+
function CardFooter(_ref6) {
|
|
880
|
+
let { divider = true, className, children } = _ref6, props = _objectWithoutProperties(_ref6, _excluded6);
|
|
881
|
+
return /* @__PURE__ */ jsx("div", _objectSpread2(_objectSpread2({ className: cn("mt-4 flex items-center justify-end gap-2 pt-4", divider && `border-t border border-border`, className) }, props), {}, {
|
|
882
|
+
"data-opt-id": "GRNTR",
|
|
883
|
+
"data-opt-slug": "card.CardFooter",
|
|
884
|
+
children
|
|
885
|
+
}));
|
|
886
|
+
}
|
|
887
|
+
//#endregion
|
|
888
|
+
//#region src/core/switch.tsx
|
|
889
|
+
const _excluded$9 = [
|
|
890
|
+
"label",
|
|
891
|
+
"required",
|
|
892
|
+
"error",
|
|
893
|
+
"hint",
|
|
894
|
+
"description",
|
|
895
|
+
"checked",
|
|
896
|
+
"defaultChecked",
|
|
897
|
+
"onChange",
|
|
898
|
+
"size",
|
|
899
|
+
"disabled",
|
|
900
|
+
"className",
|
|
901
|
+
"id",
|
|
902
|
+
"onClick",
|
|
903
|
+
"aria-label",
|
|
904
|
+
"aria-labelledby"
|
|
905
|
+
];
|
|
906
|
+
const sizeStyles$5 = {
|
|
907
|
+
sm: {
|
|
908
|
+
track: "h-5 w-9",
|
|
909
|
+
thumb: "h-4 w-4",
|
|
910
|
+
translate: "translate-x-4"
|
|
911
|
+
},
|
|
912
|
+
md: {
|
|
913
|
+
track: "h-6 w-11",
|
|
914
|
+
thumb: "h-5 w-5",
|
|
915
|
+
translate: "translate-x-5"
|
|
916
|
+
},
|
|
917
|
+
lg: {
|
|
918
|
+
track: "h-7 w-14",
|
|
919
|
+
thumb: "h-6 w-6",
|
|
920
|
+
translate: "translate-x-7"
|
|
921
|
+
}
|
|
922
|
+
};
|
|
923
|
+
const Switch = forwardRef((_ref, ref) => {
|
|
924
|
+
var _useInputId;
|
|
925
|
+
let { label, required, error, hint, description, checked: controlledChecked, defaultChecked = false, onChange, size = "md", disabled, className, id, onClick, "aria-label": ariaLabel, "aria-labelledby": ariaLabelledBy } = _ref, props = _objectWithoutProperties(_ref, _excluded$9);
|
|
926
|
+
const fallbackId = useId();
|
|
927
|
+
const switchId = (_useInputId = useInputId(id, label, "switch")) !== null && _useInputId !== void 0 ? _useInputId : `switch-${fallbackId}`;
|
|
928
|
+
const hintText = hint !== null && hint !== void 0 ? hint : description;
|
|
929
|
+
const hasError = Boolean(error);
|
|
930
|
+
const styles = sizeStyles$5[size];
|
|
931
|
+
const labelId = label ? `${switchId}-label` : void 0;
|
|
932
|
+
const switchLabelledBy = ariaLabelledBy !== null && ariaLabelledBy !== void 0 ? ariaLabelledBy : ariaLabel ? void 0 : labelId;
|
|
933
|
+
const switchAriaLabel = ariaLabel !== null && ariaLabel !== void 0 ? ariaLabel : switchLabelledBy ? void 0 : "Switch";
|
|
934
|
+
const isControlled = controlledChecked !== void 0;
|
|
935
|
+
const [internalChecked, setInternalChecked] = useState(defaultChecked);
|
|
936
|
+
const checked = isControlled ? controlledChecked : internalChecked;
|
|
937
|
+
const handleClick = useCallback((e) => {
|
|
938
|
+
const next = !checked;
|
|
939
|
+
if (!isControlled) setInternalChecked(next);
|
|
940
|
+
onChange === null || onChange === void 0 || onChange(next);
|
|
941
|
+
onClick === null || onClick === void 0 || onClick(e);
|
|
942
|
+
}, [
|
|
943
|
+
checked,
|
|
944
|
+
isControlled,
|
|
945
|
+
onChange,
|
|
946
|
+
onClick
|
|
947
|
+
]);
|
|
948
|
+
return /* @__PURE__ */ jsxs("div", {
|
|
949
|
+
className: cn("flex flex-col gap-1.5", className),
|
|
950
|
+
"data-opt-id": "51Z9R",
|
|
951
|
+
"data-opt-slug": "switch.Switch",
|
|
952
|
+
children: [/* @__PURE__ */ jsxs("div", {
|
|
953
|
+
className: "flex items-start gap-3",
|
|
954
|
+
children: [/* @__PURE__ */ jsx("button", _objectSpread2(_objectSpread2({
|
|
955
|
+
ref,
|
|
956
|
+
type: "button",
|
|
957
|
+
role: "switch",
|
|
958
|
+
id: switchId,
|
|
959
|
+
"aria-checked": checked,
|
|
960
|
+
"aria-label": switchAriaLabel,
|
|
961
|
+
"aria-labelledby": switchLabelledBy,
|
|
962
|
+
disabled,
|
|
963
|
+
className: cn("group relative inline-flex shrink-0 cursor-pointer rounded-full p-0.5 transition-colors", styles.track, "bg-bg-muted", "aria-[checked=true]:bg-accent", "disabled:cursor-not-allowed disabled:opacity-50", OPT_FOCUS_VISIBLE),
|
|
964
|
+
"aria-invalid": hasError,
|
|
965
|
+
"aria-required": required,
|
|
966
|
+
"aria-describedby": getDescribedBy(switchId, error, hintText),
|
|
967
|
+
onClick: handleClick
|
|
968
|
+
}, props), {}, { children: /* @__PURE__ */ jsx("span", { className: cn("pointer-events-none inline-block transform rounded-full bg-white shadow-sm ring-0 transition-transform", styles.thumb, "translate-x-0", size === "sm" && "group-aria-[checked=true]:translate-x-4", size === "md" && "group-aria-[checked=true]:translate-x-5", size === "lg" && "group-aria-[checked=true]:translate-x-7") }) })), (label || hintText) && /* @__PURE__ */ jsxs("div", {
|
|
969
|
+
className: "flex flex-col",
|
|
970
|
+
children: [label && /* @__PURE__ */ jsxs("span", {
|
|
971
|
+
id: labelId,
|
|
972
|
+
className: cn("text-text-primary text-sm font-medium", disabled && "opacity-50"),
|
|
973
|
+
children: [label, required && /* @__PURE__ */ jsx(RequiredMark, {})]
|
|
974
|
+
}), hintText && /* @__PURE__ */ jsx("p", {
|
|
975
|
+
id: `${switchId}-hint`,
|
|
976
|
+
className: cn("text-text-tertiary text-sm", disabled && "opacity-50"),
|
|
977
|
+
children: hintText
|
|
978
|
+
})]
|
|
979
|
+
})]
|
|
980
|
+
}), /* @__PURE__ */ jsx(FieldMessages, {
|
|
981
|
+
id: switchId,
|
|
982
|
+
error
|
|
1001
983
|
})]
|
|
1002
|
-
})
|
|
1003
|
-
}
|
|
984
|
+
});
|
|
985
|
+
});
|
|
986
|
+
Switch.displayName = "Switch";
|
|
1004
987
|
//#endregion
|
|
1005
|
-
//#region src/core/
|
|
988
|
+
//#region src/core/textarea.tsx
|
|
1006
989
|
const _excluded$8 = [
|
|
990
|
+
"label",
|
|
991
|
+
"error",
|
|
992
|
+
"hint",
|
|
993
|
+
"fullWidth",
|
|
994
|
+
"required",
|
|
995
|
+
"resize",
|
|
996
|
+
"size",
|
|
997
|
+
"className",
|
|
998
|
+
"id",
|
|
999
|
+
"rows"
|
|
1000
|
+
];
|
|
1001
|
+
const textareaSizeStyles = OPT_TEXTAREA_SIZE;
|
|
1002
|
+
const resizeStyles = {
|
|
1003
|
+
none: "resize-none",
|
|
1004
|
+
vertical: "resize-y",
|
|
1005
|
+
horizontal: "resize-x",
|
|
1006
|
+
both: "resize"
|
|
1007
|
+
};
|
|
1008
|
+
const Textarea = forwardRef((_ref, ref) => {
|
|
1009
|
+
var _useInputId;
|
|
1010
|
+
let { label, error, hint, fullWidth = false, required, resize = "vertical", size = "md", className, id, rows = 4 } = _ref, props = _objectWithoutProperties(_ref, _excluded$8);
|
|
1011
|
+
const fallbackId = useId().replace(/:/g, "");
|
|
1012
|
+
const textareaId = (_useInputId = useInputId(id, label, "textarea")) !== null && _useInputId !== void 0 ? _useInputId : `textarea-${fallbackId}`;
|
|
1013
|
+
const hasError = Boolean(error);
|
|
1014
|
+
return /* @__PURE__ */ jsxs("div", {
|
|
1015
|
+
className: cn("flex flex-col gap-1.5", fullWidth && "w-full"),
|
|
1016
|
+
"data-opt-id": "6T58H",
|
|
1017
|
+
"data-opt-slug": "textarea.Textarea",
|
|
1018
|
+
children: [
|
|
1019
|
+
label && /* @__PURE__ */ jsxs("label", {
|
|
1020
|
+
htmlFor: textareaId,
|
|
1021
|
+
className: "text-text-primary text-sm font-medium",
|
|
1022
|
+
children: [label, required && /* @__PURE__ */ jsx(RequiredMark, {})]
|
|
1023
|
+
}),
|
|
1024
|
+
/* @__PURE__ */ jsx("textarea", _objectSpread2({
|
|
1025
|
+
ref,
|
|
1026
|
+
id: textareaId,
|
|
1027
|
+
rows,
|
|
1028
|
+
className: cn("border-border bg-surface text-text-primary placeholder:text-text-tertiary w-full rounded-lg border px-4 py-3 text-sm outline-transparent", OPT_FOCUS_VISIBLE, textareaSizeStyles[size], resizeStyles[resize], hasError && "border-danger focus-visible:outline-danger", !fullWidth && "w-auto", className),
|
|
1029
|
+
"aria-invalid": hasError,
|
|
1030
|
+
"aria-describedby": getDescribedBy(textareaId, error, hint)
|
|
1031
|
+
}, props)),
|
|
1032
|
+
/* @__PURE__ */ jsx(FieldMessages, {
|
|
1033
|
+
id: textareaId,
|
|
1034
|
+
error,
|
|
1035
|
+
hint
|
|
1036
|
+
})
|
|
1037
|
+
]
|
|
1038
|
+
});
|
|
1039
|
+
});
|
|
1040
|
+
Textarea.displayName = "Textarea";
|
|
1041
|
+
//#endregion
|
|
1042
|
+
//#region src/core/progress.tsx
|
|
1043
|
+
const _excluded$7 = [
|
|
1007
1044
|
"value",
|
|
1008
1045
|
"max",
|
|
1009
1046
|
"size",
|
|
@@ -1025,12 +1062,12 @@ const _excluded2$3 = [
|
|
|
1025
1062
|
"indeterminate",
|
|
1026
1063
|
"className"
|
|
1027
1064
|
];
|
|
1028
|
-
const sizeStyles$
|
|
1065
|
+
const sizeStyles$4 = {
|
|
1029
1066
|
sm: "h-1",
|
|
1030
1067
|
md: "h-2",
|
|
1031
1068
|
lg: "h-3"
|
|
1032
1069
|
};
|
|
1033
|
-
const variantStyles
|
|
1070
|
+
const variantStyles = {
|
|
1034
1071
|
default: "bg-accent",
|
|
1035
1072
|
success: "bg-success",
|
|
1036
1073
|
warning: "bg-warning",
|
|
@@ -1049,7 +1086,7 @@ function getProgressValue(value, max) {
|
|
|
1049
1086
|
}
|
|
1050
1087
|
/** Renders the progress component. */
|
|
1051
1088
|
function Progress(_ref) {
|
|
1052
|
-
let { value, max = 100, size = "md", variant = "default", showLabel = false, label, animated = true, indeterminate = false, className } = _ref, props = _objectWithoutProperties(_ref, _excluded$
|
|
1089
|
+
let { value, max = 100, size = "md", variant = "default", showLabel = false, label, animated = true, indeterminate = false, className } = _ref, props = _objectWithoutProperties(_ref, _excluded$7);
|
|
1053
1090
|
const progress = indeterminate || value === void 0 ? null : getProgressValue(value, max);
|
|
1054
1091
|
const shouldRenderHeader = Boolean(label) || showLabel && progress;
|
|
1055
1092
|
return /* @__PURE__ */ jsxs("div", _objectSpread2(_objectSpread2({ className: cn("w-full", className) }, props), {}, {
|
|
@@ -1065,7 +1102,7 @@ function Progress(_ref) {
|
|
|
1065
1102
|
children: progress.valueText
|
|
1066
1103
|
})]
|
|
1067
1104
|
}), /* @__PURE__ */ jsx("div", {
|
|
1068
|
-
className: cn("bg-bg-subtle w-full overflow-hidden rounded-full", sizeStyles$
|
|
1105
|
+
className: cn("bg-bg-subtle w-full overflow-hidden rounded-full", sizeStyles$4[size]),
|
|
1069
1106
|
role: "progressbar",
|
|
1070
1107
|
"aria-valuenow": progress === null || progress === void 0 ? void 0 : progress.clampedValue,
|
|
1071
1108
|
"aria-valuemin": progress ? 0 : void 0,
|
|
@@ -1073,7 +1110,7 @@ function Progress(_ref) {
|
|
|
1073
1110
|
"aria-valuetext": progress === null || progress === void 0 ? void 0 : progress.valueText,
|
|
1074
1111
|
"aria-label": label !== null && label !== void 0 ? label : progress ? `${progress.valueText} complete` : "Loading",
|
|
1075
1112
|
children: /* @__PURE__ */ jsx("div", {
|
|
1076
|
-
className: cn("h-full rounded-full", variantStyles
|
|
1113
|
+
className: cn("h-full rounded-full", variantStyles[variant], !progress && "w-1/3 animate-pulse", animated && (progress ? "transition-all duration-300 ease-out" : "transition-opacity duration-700 ease-in-out")),
|
|
1077
1114
|
style: progress ? { width: `${progress.percentage}%` } : void 0
|
|
1078
1115
|
})
|
|
1079
1116
|
})]
|
|
@@ -1146,65 +1183,6 @@ function CircularProgress(_ref2) {
|
|
|
1146
1183
|
});
|
|
1147
1184
|
}
|
|
1148
1185
|
//#endregion
|
|
1149
|
-
//#region src/core/meter.tsx
|
|
1150
|
-
const _excluded$7 = [
|
|
1151
|
-
"value",
|
|
1152
|
-
"min",
|
|
1153
|
-
"max",
|
|
1154
|
-
"size",
|
|
1155
|
-
"variant",
|
|
1156
|
-
"showValue",
|
|
1157
|
-
"label",
|
|
1158
|
-
"getValueLabel",
|
|
1159
|
-
"className"
|
|
1160
|
-
];
|
|
1161
|
-
const sizeStyles$4 = {
|
|
1162
|
-
sm: "h-1",
|
|
1163
|
-
md: "h-2",
|
|
1164
|
-
lg: "h-3"
|
|
1165
|
-
};
|
|
1166
|
-
const variantStyles = {
|
|
1167
|
-
default: "bg-accent",
|
|
1168
|
-
success: "bg-success",
|
|
1169
|
-
warning: "bg-warning",
|
|
1170
|
-
error: "bg-danger"
|
|
1171
|
-
};
|
|
1172
|
-
/**
|
|
1173
|
-
* A scalar measurement within a known range (disk usage, score, capacity) —
|
|
1174
|
-
* `role="meter"`, distinct from Progress (task completion). Built on the
|
|
1175
|
-
* opt-ui-primitives Meter primitive, which owns the role/aria/valuetext.
|
|
1176
|
-
*/
|
|
1177
|
-
function Meter$1(_ref) {
|
|
1178
|
-
let { value, min = 0, max = 100, size = "md", variant = "default", showValue = false, label, getValueLabel, className } = _ref, props = _objectWithoutProperties(_ref, _excluded$7);
|
|
1179
|
-
const clamped = Math.min(Math.max(value, min), max);
|
|
1180
|
-
const percentage = max === min ? 0 : (clamped - min) / (max - min) * 100;
|
|
1181
|
-
return /* @__PURE__ */ jsxs("div", _objectSpread2(_objectSpread2({ className: cn("w-full", className) }, props), {}, {
|
|
1182
|
-
"data-opt-id": "G01TE",
|
|
1183
|
-
"data-opt-slug": "meter.Meter",
|
|
1184
|
-
children: [(showValue || label) && /* @__PURE__ */ jsxs("div", {
|
|
1185
|
-
className: "mb-1.5 flex items-center justify-between text-sm",
|
|
1186
|
-
children: [label && /* @__PURE__ */ jsx("span", {
|
|
1187
|
-
className: "text-text-primary font-medium",
|
|
1188
|
-
children: label
|
|
1189
|
-
}), showValue && /* @__PURE__ */ jsxs("span", {
|
|
1190
|
-
className: "text-text-tertiary",
|
|
1191
|
-
children: [Math.round(percentage), "%"]
|
|
1192
|
-
})]
|
|
1193
|
-
}), /* @__PURE__ */ jsx(Meter, {
|
|
1194
|
-
value: clamped,
|
|
1195
|
-
min,
|
|
1196
|
-
max,
|
|
1197
|
-
getValueLabel,
|
|
1198
|
-
"aria-label": label !== null && label !== void 0 ? label : `${Math.round(percentage)}%`,
|
|
1199
|
-
className: cn("bg-bg-subtle w-full overflow-hidden rounded-full", sizeStyles$4[size]),
|
|
1200
|
-
children: /* @__PURE__ */ jsx("div", {
|
|
1201
|
-
className: cn("h-full rounded-full transition-all duration-300 ease-out", variantStyles[variant]),
|
|
1202
|
-
style: { width: `${percentage}%` }
|
|
1203
|
-
})
|
|
1204
|
-
})]
|
|
1205
|
-
}));
|
|
1206
|
-
}
|
|
1207
|
-
//#endregion
|
|
1208
1186
|
//#region src/core/step-builder.tsx
|
|
1209
1187
|
/** Renders the step builder component. */
|
|
1210
1188
|
function StepBuilder({ steps, onChange, label, addLabel = "Add step", maxSteps, className, "aria-label": ariaLabel }) {
|
|
@@ -1363,55 +1341,6 @@ function StepBuilder({ steps, onChange, label, addLabel = "Add step", maxSteps,
|
|
|
1363
1341
|
}
|
|
1364
1342
|
StepBuilder.displayName = "StepBuilder";
|
|
1365
1343
|
//#endregion
|
|
1366
|
-
//#region src/lib/formatters.ts
|
|
1367
|
-
const OPT_UI_DEFAULT_LOCALE = "ko-KR";
|
|
1368
|
-
const KST_OFFSET_MS = 324e5;
|
|
1369
|
-
function getKstDateParts(input) {
|
|
1370
|
-
const date = input instanceof Date ? input : new Date(input);
|
|
1371
|
-
if (Number.isNaN(date.getTime())) return null;
|
|
1372
|
-
const kstDate = new Date(date.getTime() + KST_OFFSET_MS);
|
|
1373
|
-
return {
|
|
1374
|
-
year: kstDate.getUTCFullYear(),
|
|
1375
|
-
month: kstDate.getUTCMonth() + 1,
|
|
1376
|
-
day: kstDate.getUTCDate(),
|
|
1377
|
-
hour: kstDate.getUTCHours(),
|
|
1378
|
-
minute: kstDate.getUTCMinutes(),
|
|
1379
|
-
second: kstDate.getUTCSeconds()
|
|
1380
|
-
};
|
|
1381
|
-
}
|
|
1382
|
-
function pad2(value) {
|
|
1383
|
-
return String(value).padStart(2, "0");
|
|
1384
|
-
}
|
|
1385
|
-
function meridiem(hour) {
|
|
1386
|
-
return hour < 12 ? "오전" : "오후";
|
|
1387
|
-
}
|
|
1388
|
-
function hour12(hour) {
|
|
1389
|
-
const normalized = hour % 12;
|
|
1390
|
-
return normalized === 0 ? 12 : normalized;
|
|
1391
|
-
}
|
|
1392
|
-
/** Formats a date as Korean short date text in the opt-ui default timezone. */
|
|
1393
|
-
function formatOptShortDate(input) {
|
|
1394
|
-
const parts = getKstDateParts(input);
|
|
1395
|
-
if (!parts) return "-";
|
|
1396
|
-
return `${parts.month}월 ${parts.day}일`;
|
|
1397
|
-
}
|
|
1398
|
-
/** Formats a date as Korean clock time in the opt-ui default timezone. */
|
|
1399
|
-
function formatOptTime(input) {
|
|
1400
|
-
const parts = getKstDateParts(input);
|
|
1401
|
-
if (!parts) return "-";
|
|
1402
|
-
return `${meridiem(parts.hour)} ${pad2(hour12(parts.hour))}:${pad2(parts.minute)}`;
|
|
1403
|
-
}
|
|
1404
|
-
/** Formats a date as Korean date-time text in the opt-ui default timezone. */
|
|
1405
|
-
function formatOptDateTime(input) {
|
|
1406
|
-
const parts = getKstDateParts(input);
|
|
1407
|
-
if (!parts) return "-";
|
|
1408
|
-
return `${parts.year}. ${parts.month}. ${parts.day}. ${meridiem(parts.hour)} ${hour12(parts.hour)}:${pad2(parts.minute)}:${pad2(parts.second)}`;
|
|
1409
|
-
}
|
|
1410
|
-
/** Formats numbers without depending on the runtime default locale. */
|
|
1411
|
-
function formatOptNumber(value) {
|
|
1412
|
-
return new Intl.NumberFormat(OPT_UI_DEFAULT_LOCALE).format(value);
|
|
1413
|
-
}
|
|
1414
|
-
//#endregion
|
|
1415
1344
|
//#region src/core/condition-builder.tsx
|
|
1416
1345
|
const OPERATOR_LABELS = {
|
|
1417
1346
|
equals: "equals",
|
|
@@ -3915,134 +3844,6 @@ function ExpressionGroup({ children, display = "sentence", className, "aria-labe
|
|
|
3915
3844
|
});
|
|
3916
3845
|
}
|
|
3917
3846
|
//#endregion
|
|
3918
|
-
//#region src/core/text-truncate.tsx
|
|
3919
|
-
const useIsomorphicLayoutEffect = typeof window === "undefined" ? useEffect : useLayoutEffect;
|
|
3920
|
-
/** Measures text in the element's own resolved font, not an assumed one. */
|
|
3921
|
-
function createMeasurer(element) {
|
|
3922
|
-
const context = document.createElement("canvas").getContext("2d");
|
|
3923
|
-
if (!context) return null;
|
|
3924
|
-
const computed = window.getComputedStyle(element);
|
|
3925
|
-
context.font = [
|
|
3926
|
-
computed.fontStyle,
|
|
3927
|
-
computed.fontVariant,
|
|
3928
|
-
computed.fontWeight,
|
|
3929
|
-
`${computed.fontSize}/${computed.lineHeight}`,
|
|
3930
|
-
computed.fontFamily
|
|
3931
|
-
].join(" ");
|
|
3932
|
-
const spacing = Number.parseFloat(computed.letterSpacing) || 0;
|
|
3933
|
-
return (value) => context.measureText(value).width + spacing * value.length;
|
|
3934
|
-
}
|
|
3935
|
-
/** Largest `n` in `[0, max]` for which `fits(n)` holds. */
|
|
3936
|
-
function largestFitting(max, fits) {
|
|
3937
|
-
let low = 0;
|
|
3938
|
-
let high = max;
|
|
3939
|
-
while (low < high) {
|
|
3940
|
-
const mid = Math.ceil((low + high) / 2);
|
|
3941
|
-
if (fits(mid)) low = mid;
|
|
3942
|
-
else high = mid - 1;
|
|
3943
|
-
}
|
|
3944
|
-
return low;
|
|
3945
|
-
}
|
|
3946
|
-
function truncateToWidth(text, side, ellipsis, available, measure) {
|
|
3947
|
-
if (measure(text) <= available) return text;
|
|
3948
|
-
const chars = Array.from(text);
|
|
3949
|
-
if (side === "end") {
|
|
3950
|
-
const keep = largestFitting(chars.length, (n) => measure(chars.slice(0, n).join("") + ellipsis) <= available);
|
|
3951
|
-
return chars.slice(0, keep).join("") + ellipsis;
|
|
3952
|
-
}
|
|
3953
|
-
if (side === "start") {
|
|
3954
|
-
const keep = largestFitting(chars.length, (n) => measure(ellipsis + chars.slice(chars.length - n).join("")) <= available);
|
|
3955
|
-
return ellipsis + chars.slice(chars.length - keep).join("");
|
|
3956
|
-
}
|
|
3957
|
-
if (side === "startEnd") {
|
|
3958
|
-
const keep = largestFitting(Math.floor(chars.length / 2), (n) => {
|
|
3959
|
-
const head = chars.slice(0, n).join("");
|
|
3960
|
-
const tail = chars.slice(chars.length - n).join("");
|
|
3961
|
-
return measure(head + ellipsis + tail) <= available;
|
|
3962
|
-
});
|
|
3963
|
-
if (keep === 0) return ellipsis;
|
|
3964
|
-
return chars.slice(0, keep).join("") + ellipsis + chars.slice(chars.length - keep).join("");
|
|
3965
|
-
}
|
|
3966
|
-
const span = largestFitting(chars.length, (n) => {
|
|
3967
|
-
const start = Math.floor((chars.length - n) / 2);
|
|
3968
|
-
return measure(ellipsis + chars.slice(start, start + n).join("") + ellipsis) <= available;
|
|
3969
|
-
});
|
|
3970
|
-
if (span === 0) return ellipsis;
|
|
3971
|
-
const start = Math.floor((chars.length - span) / 2);
|
|
3972
|
-
return ellipsis + chars.slice(start, start + span).join("") + ellipsis;
|
|
3973
|
-
}
|
|
3974
|
-
/**
|
|
3975
|
-
* TextTruncate — drops characters from the part of a string that identifies it
|
|
3976
|
-
* least.
|
|
3977
|
-
*
|
|
3978
|
-
* CSS can only cut the end. That is the wrong end for the strings analytics
|
|
3979
|
-
* shows most: two URLs that differ in their query string, two ids that share a
|
|
3980
|
-
* prefix, a stack frame whose filename is at the tail. This measures the real
|
|
3981
|
-
* text in the real font against the real available width and cuts where the
|
|
3982
|
-
* caller says.
|
|
3983
|
-
*
|
|
3984
|
-
* The full string stays in the accessibility tree and in `title`, so
|
|
3985
|
-
* truncation never costs the reader information — only space.
|
|
3986
|
-
*
|
|
3987
|
-
* @example
|
|
3988
|
-
* ```tsx
|
|
3989
|
-
* <TextTruncate text={event.url} truncation="startEnd" />
|
|
3990
|
-
* ```
|
|
3991
|
-
*/
|
|
3992
|
-
function TextTruncate({ text, truncation = "startEnd", ellipsis = "…", width, children, className }) {
|
|
3993
|
-
const ref = useRef(null);
|
|
3994
|
-
const [available, setAvailable] = useState(width !== null && width !== void 0 ? width : null);
|
|
3995
|
-
useIsomorphicLayoutEffect(() => {
|
|
3996
|
-
if (width !== void 0) {
|
|
3997
|
-
setAvailable(width);
|
|
3998
|
-
return;
|
|
3999
|
-
}
|
|
4000
|
-
const element = ref.current;
|
|
4001
|
-
if (!element || typeof ResizeObserver === "undefined") return;
|
|
4002
|
-
const observer = new ResizeObserver((entries) => {
|
|
4003
|
-
const entry = entries[0];
|
|
4004
|
-
if (entry) setAvailable(entry.contentRect.width);
|
|
4005
|
-
});
|
|
4006
|
-
observer.observe(element);
|
|
4007
|
-
setAvailable(element.getBoundingClientRect().width);
|
|
4008
|
-
return () => observer.disconnect();
|
|
4009
|
-
}, [width]);
|
|
4010
|
-
const [rendered, setRendered] = useState(text);
|
|
4011
|
-
useIsomorphicLayoutEffect(() => {
|
|
4012
|
-
const element = ref.current;
|
|
4013
|
-
if (!element || available === null || available <= 0) {
|
|
4014
|
-
setRendered(text);
|
|
4015
|
-
return;
|
|
4016
|
-
}
|
|
4017
|
-
const measure = createMeasurer(element);
|
|
4018
|
-
if (!measure) {
|
|
4019
|
-
setRendered(text);
|
|
4020
|
-
return;
|
|
4021
|
-
}
|
|
4022
|
-
setRendered(truncateToWidth(text, truncation, ellipsis, available, measure));
|
|
4023
|
-
}, [
|
|
4024
|
-
text,
|
|
4025
|
-
truncation,
|
|
4026
|
-
ellipsis,
|
|
4027
|
-
available
|
|
4028
|
-
]);
|
|
4029
|
-
const truncated = rendered !== text;
|
|
4030
|
-
return /* @__PURE__ */ jsxs("span", {
|
|
4031
|
-
ref,
|
|
4032
|
-
className: cn("block w-full overflow-hidden whitespace-nowrap", className),
|
|
4033
|
-
title: truncated ? text : void 0,
|
|
4034
|
-
"data-opt-id": "Y6BGX",
|
|
4035
|
-
"data-opt-slug": "text-truncate.TextTruncate",
|
|
4036
|
-
children: [/* @__PURE__ */ jsx("span", {
|
|
4037
|
-
"aria-hidden": truncated ? "true" : void 0,
|
|
4038
|
-
children: children ? children(rendered) : rendered
|
|
4039
|
-
}), truncated && /* @__PURE__ */ jsx("span", {
|
|
4040
|
-
className: "sr-only",
|
|
4041
|
-
children: text
|
|
4042
|
-
})]
|
|
4043
|
-
});
|
|
4044
|
-
}
|
|
4045
|
-
//#endregion
|
|
4046
3847
|
//#region src/core/live-region.tsx
|
|
4047
3848
|
/**
|
|
4048
3849
|
* LiveRegion — says out loud what a live view changed.
|
|
@@ -4329,7 +4130,7 @@ function InlineEdit({ value, onSave, as: Tag = "span", size = "md", placeholder,
|
|
|
4329
4130
|
}
|
|
4330
4131
|
};
|
|
4331
4132
|
if (editing) return /* @__PURE__ */ jsxs("span", {
|
|
4332
|
-
className: cn("inline-flex items-center gap-element", className),
|
|
4133
|
+
className: cn("inline-flex min-w-0 items-center gap-element", className),
|
|
4333
4134
|
"data-opt-id": "RQ0H2",
|
|
4334
4135
|
"data-opt-slug": "inline-edit.InlineEdit",
|
|
4335
4136
|
children: [
|
|
@@ -4381,7 +4182,7 @@ function InlineEdit({ value, onSave, as: Tag = "span", size = "md", placeholder,
|
|
|
4381
4182
|
]
|
|
4382
4183
|
});
|
|
4383
4184
|
return /* @__PURE__ */ jsxs("span", {
|
|
4384
|
-
className: cn("inline-flex items-center gap-element", className),
|
|
4185
|
+
className: cn("inline-flex min-w-0 items-center gap-element", className),
|
|
4385
4186
|
"data-opt-id": "RQ0H2",
|
|
4386
4187
|
"data-opt-slug": "inline-edit.InlineEdit",
|
|
4387
4188
|
children: [/* @__PURE__ */ jsxs("button", {
|
|
@@ -4389,7 +4190,7 @@ function InlineEdit({ value, onSave, as: Tag = "span", size = "md", placeholder,
|
|
|
4389
4190
|
disabled,
|
|
4390
4191
|
onClick: () => setEditing(true),
|
|
4391
4192
|
"aria-label": text.edit(value || emptyText),
|
|
4392
|
-
className: cn("group -mx-1.5 -my-0.5 inline-flex
|
|
4193
|
+
className: cn("group -mx-1.5 -my-0.5 inline-flex min-w-0 items-center gap-element rounded-md px-1.5 py-0.5 text-left", !disabled && "hover:bg-bg-subtle cursor-pointer", disabled && "cursor-default", OPT_FOCUS_VISIBLE),
|
|
4393
4194
|
children: [/* @__PURE__ */ jsx(Tag, {
|
|
4394
4195
|
className: cn("truncate", sizeStyles$1[size], value ? "text-text-primary" : "text-text-tertiary italic"),
|
|
4395
4196
|
children: value || emptyText
|
|
@@ -4485,6 +4286,6 @@ function KeyPadMenu({ items, label, selection = "single", value, onValueChange,
|
|
|
4485
4286
|
});
|
|
4486
4287
|
}
|
|
4487
4288
|
//#endregion
|
|
4488
|
-
export {
|
|
4289
|
+
export { Identity as $, PageHeader as A, DropdownTrigger as B, Logo as C, Section as D, ResizablePanelGroup as E, RadioGroup as F, Textarea as G, StepBuilder as H, DropdownContent as I, CardContent as J, Switch as K, DropdownItem as L, BlockLayout as M, LoadingOverlay as N, Container as O, Radio as P, CardTitle as Q, DropdownMenu as R, DrawerRoot as S, ResizablePanel as T, CircularProgress as U, ConditionBuilder as V, Progress as W, CardFooter as X, CardDescription as Y, CardHeader as Z, getShaderFragment as _, THEME_PALETTES as a, AccordionItem$1 as at, DrawerClose as b, ExpressionGroup as c, Toggle$1 as ct, ShaderSurface as d, Separator$2 as dt, Avatar as et, SHADER_OVERLAY_PARAM_KEYS as f, Heading as ft, SHADER_PRESET_IDS as g, SHADER_PRESETS as h, ColorPalettePicker as i, AccordionContent$1 as it, createBlock as j, ScrollArea as k, Facet as l, ToggleGroup$1 as lt, SHADER_PARAM_KEYS as m, InlineEdit as n, DescriptionList as nt, LiveRegion as o, AccordionRoot$1 as ot, SHADER_PARAM_FALLBACK as p, Text as pt, Card as q, ColorPaletteDisplay as r, Breadcrumb as rt, Expression as s, AccordionTrigger$1 as st, KeyPadMenu as t, AvatarGroup as tt, FacetGroup as u, OtpField as ut, getShaderPreset as v, ResizableHandle as w, DrawerPanel as x, VirtualList as y, DropdownSeparator as z };
|
|
4489
4290
|
|
|
4490
|
-
//# sourceMappingURL=key-pad-menu-
|
|
4291
|
+
//# sourceMappingURL=key-pad-menu-wXkWn1I1.js.map
|