pixelize-design-library 2.3.19 → 2.3.21

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.
Files changed (56) hide show
  1. package/.cursor/modules/overlays/MODULE.md +18 -1
  2. package/.cursor/modules/utils-hooks/MODULE.md +12 -2
  3. package/dist/Components/Toaster/Toaster.d.ts.map +1 -1
  4. package/dist/Components/Toaster/Toaster.js +54 -12
  5. package/dist/Components/Toaster/ToasterProps.d.ts +7 -0
  6. package/dist/Components/Toaster/ToasterProps.d.ts.map +1 -1
  7. package/dist/Components/ToolTip/OverflowToolTip.d.ts +18 -0
  8. package/dist/Components/ToolTip/OverflowToolTip.d.ts.map +1 -0
  9. package/dist/Components/ToolTip/OverflowToolTip.js +26 -0
  10. package/dist/Components/ToolTip/ToolTip.d.ts +1 -1
  11. package/dist/Components/ToolTip/ToolTip.d.ts.map +1 -1
  12. package/dist/Components/ToolTip/ToolTip.js +21 -3
  13. package/dist/Components/ToolTip/ToolTipProps.d.ts +9 -0
  14. package/dist/Components/ToolTip/ToolTipProps.d.ts.map +1 -1
  15. package/dist/Components/WorkspaceWindow/WorkspaceTrayPreview.d.ts +16 -0
  16. package/dist/Components/WorkspaceWindow/WorkspaceTrayPreview.d.ts.map +1 -0
  17. package/dist/Components/WorkspaceWindow/WorkspaceTrayPreview.js +83 -0
  18. package/dist/Components/WorkspaceWindow/WorkspaceWindow.d.ts +15 -0
  19. package/dist/Components/WorkspaceWindow/WorkspaceWindow.d.ts.map +1 -0
  20. package/dist/Components/WorkspaceWindow/WorkspaceWindow.js +40 -0
  21. package/dist/Components/WorkspaceWindow/WorkspaceWindowProps.d.ts +72 -0
  22. package/dist/Components/WorkspaceWindow/WorkspaceWindowProps.d.ts.map +1 -0
  23. package/dist/Components/WorkspaceWindow/WorkspaceWindowProps.js +2 -0
  24. package/dist/Hooks/useIsTruncated.d.ts +36 -0
  25. package/dist/Hooks/useIsTruncated.d.ts.map +1 -0
  26. package/dist/Hooks/useIsTruncated.js +57 -0
  27. package/dist/Utils/mergeRefs.d.ts +11 -0
  28. package/dist/Utils/mergeRefs.d.ts.map +1 -0
  29. package/dist/Utils/mergeRefs.js +20 -0
  30. package/dist/index.d.ts +6 -1
  31. package/dist/index.d.ts.map +1 -1
  32. package/dist/index.js +11 -2
  33. package/package.json +1 -1
  34. package/dist/Assets/defaultLogo.tsx +0 -30
  35. package/dist/Components/Input/textInputIconSize.test.d.ts +0 -1
  36. package/dist/Components/Input/textInputIconSize.test.js +0 -27
  37. package/dist/Components/KanbanBoard/AccountCard.test.d.ts +0 -1
  38. package/dist/Components/KanbanBoard/AccountCard.test.js +0 -68
  39. package/dist/Components/KanbanBoard/KanbanActions/KanbanActions.test.d.ts +0 -1
  40. package/dist/Components/KanbanBoard/KanbanActions/KanbanActions.test.js +0 -49
  41. package/dist/Components/KanbanBoard/KanbanBoard.test.d.ts +0 -1
  42. package/dist/Components/KanbanBoard/KanbanBoard.test.js +0 -185
  43. package/dist/Components/SearchSelect/searchSelectSize.test.d.ts +0 -1
  44. package/dist/Components/SearchSelect/searchSelectSize.test.js +0 -22
  45. package/dist/Components/SideBar/components/OtherApps.test.d.ts +0 -1
  46. package/dist/Components/SideBar/components/OtherApps.test.js +0 -111
  47. package/dist/Components/Table/components/TableBody.virtualize.test.d.ts +0 -1
  48. package/dist/Components/Table/components/TableBody.virtualize.test.js +0 -93
  49. package/dist/Components/Table/settings/ManageColumns.test.d.ts +0 -1
  50. package/dist/Components/Table/settings/ManageColumns.test.js +0 -146
  51. package/dist/Theme/buildBrandTokens.test.d.ts +0 -1
  52. package/dist/Theme/buildBrandTokens.test.js +0 -31
  53. package/dist/Theme/chartColorsFromTheme.test.d.ts +0 -1
  54. package/dist/Theme/chartColorsFromTheme.test.js +0 -35
  55. package/dist/Utils/tableNormalizeCellValue.test.d.ts +0 -1
  56. package/dist/Utils/tableNormalizeCellValue.test.js +0 -41
@@ -2,7 +2,7 @@
2
2
 
3
3
  ## Purpose
4
4
 
5
- Modal, AlertDialog, ToolTip, Toaster (+ `useToaster` hook).
5
+ Modal, AlertDialog, ToolTip / OverflowToolTip, Toaster (+ `useToaster` hook).
6
6
 
7
7
  ## Key paths
8
8
 
@@ -10,4 +10,21 @@ Modal, AlertDialog, ToolTip, Toaster (+ `useToaster` hook).
10
10
 
11
11
  ## Key rules
12
12
 
13
+ - **Toaster `showToast({ actions })`:** optional `actions?: (onClose) => ReactNode`
14
+ renders action buttons under the message (e.g. Jira-style "View" / "Copy link").
15
+ The render-prop receives the toast's own `onClose` so an action can dismiss it;
16
+ callers style the buttons with their app theme. Prefer this over a bespoke Chakra
17
+ `useToast` in a consumer app — a second `useToast` renders into a *different* toast
18
+ portal that a `Modal`'s overlay/focus-trap can hide, so the toast silently never
19
+ appears. The toast card slides in (framer tween), pulses the status icon once on
20
+ mount, and **pauses the auto-dismiss countdown on hover** so the user can read and
21
+ click an action before it dismisses.
13
22
  - Modal exports ModalHeader, ModalBody, ModalFooter subcomponents
23
+ - **ToolTip `overflowOnly`:** pass `overflowOnly` to show the tooltip **only**
24
+ when the child text is actually truncated (ellipsis active) — no tooltip when
25
+ it fits. The child must be the single clamping element (e.g. `Text` with
26
+ `noOfLines`); its ref is managed internally. Works for single- and multi-line
27
+ clamps and combines with `isDisabled`. **`OverflowToolTip`** is sugar for
28
+ `<ToolTip overflowOnly>`. Powered by the `useIsTruncated` hook (see
29
+ `utils-hooks`). Inert unless `overflowOnly` is set — no measurement/observer
30
+ for ordinary tooltips, and it never measures on hover/scroll.
@@ -2,12 +2,22 @@
2
2
 
3
3
  ## Purpose
4
4
 
5
- Shared utilities and hooks: debounce, table helpers, preferences.
5
+ Shared utilities and hooks: debounce, table helpers, preferences, ref merging,
6
+ truncation detection.
6
7
 
7
8
  ## Key paths
8
9
 
9
- - `src/Utils/table.ts`, `src/Hooks/usePreferences.ts`, `src/services/feedback.ts`
10
+ - `src/Utils/table.ts`, `src/Utils/mergeRefs.ts`, `src/Hooks/usePreferences.ts`,
11
+ `src/Hooks/useIsTruncated.ts`, `src/services/feedback.ts`
10
12
 
11
13
  ## Key rules
12
14
 
13
15
  - `debounce` exported from index.ts
16
+ - **`useIsTruncated(content?, enabled?)`** (exported) — returns `{ ref, isTruncated }`;
17
+ attach `ref` to a clamped element to detect real overflow (`scrollWidth/Height`
18
+ vs `clientWidth/Height`, single- and multi-line). Re-measures on mount, element
19
+ resize (`ResizeObserver`), and `content` change — never on hover/scroll. Pass
20
+ `enabled=false` to make it fully inert. Powers `ToolTip overflowOnly` (see
21
+ `overlays`).
22
+ - **`mergeRefs(...refs)`** (internal) — combine a caller ref with an injected one
23
+ when cloning an element.
@@ -1 +1 @@
1
- {"version":3,"file":"Toaster.d.ts","sourceRoot":"","sources":["../../../src/Components/Toaster/Toaster.tsx"],"names":[],"mappings":"AAiBA,OAAO,EAAE,eAAe,EAAE,kBAAkB,EAAE,MAAM,gBAAgB,CAAC;AAUrE,MAAM,CAAC,OAAO,UAAU,eAAe,CAAC,EAAE,QAAQ,EAAE,EAAE,eAAe,2CAyIpE;AAED,eAAO,MAAM,UAAU,0BAMtB,CAAC"}
1
+ {"version":3,"file":"Toaster.d.ts","sourceRoot":"","sources":["../../../src/Components/Toaster/Toaster.tsx"],"names":[],"mappings":"AAkBA,OAAO,EAAE,eAAe,EAAE,kBAAkB,EAAqB,MAAM,gBAAgB,CAAC;AAyKxF,MAAM,CAAC,OAAO,UAAU,eAAe,CAAC,EAAE,QAAQ,EAAE,EAAE,eAAe,2CAkEpE;AAED,eAAO,MAAM,UAAU,0BAMtB,CAAC"}
@@ -6,20 +6,68 @@ const jsx_runtime_1 = require("react/jsx-runtime");
6
6
  const react_1 = require("react");
7
7
  const react_2 = require("@chakra-ui/react");
8
8
  const react_3 = require("@emotion/react");
9
+ const framer_motion_1 = require("framer-motion");
9
10
  const lucide_react_1 = require("lucide-react");
10
11
  const ToasterContext = (0, react_1.createContext)(undefined);
11
12
  const shrink = (0, react_3.keyframes) `
12
13
  from { transform: scaleX(1); }
13
14
  to { transform: scaleX(0); }
14
15
  `;
16
+ // One-shot ring pulse on the status icon — a subtle "just happened" beat.
17
+ const iconPulse = (0, react_3.keyframes) `
18
+ 0% { box-shadow: 0 0 0 0 var(--toast-pulse-color); }
19
+ 70% { box-shadow: 0 0 0 0.5rem transparent; }
20
+ 100% { box-shadow: 0 0 0 0 transparent; }
21
+ `;
22
+ const MotionBox = (0, framer_motion_1.motion)(react_2.Box);
23
+ /**
24
+ * Presentational toast card. Owns hover state so the auto-dismiss countdown
25
+ * pauses while the pointer is over the toast — the user can read and click an
26
+ * action without the toast vanishing mid-reach.
27
+ */
28
+ function ToastCard({ onClose, title, description, actions, isClosable, duration, meta, colors: c, shadowLg, }) {
29
+ var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o, _p, _q, _r, _s, _t, _u, _v, _w, _x, _y, _z, _0, _1, _2, _3, _4, _5, _6;
30
+ const [paused, setPaused] = (0, react_1.useState)(false);
31
+ const solid = (_d = (_b = (_a = meta.scale) === null || _a === void 0 ? void 0 : _a[500]) !== null && _b !== void 0 ? _b : (_c = c === null || c === void 0 ? void 0 : c.gray) === null || _c === void 0 ? void 0 : _c[500]) !== null && _d !== void 0 ? _d : "#718096";
32
+ const soft = (_h = (_f = (_e = meta.scale) === null || _e === void 0 ? void 0 : _e[50]) !== null && _f !== void 0 ? _f : (_g = c === null || c === void 0 ? void 0 : c.gray) === null || _g === void 0 ? void 0 : _g[50]) !== null && _h !== void 0 ? _h : "#f7fafc";
33
+ const accent = (_k = (_j = meta.scale) === null || _j === void 0 ? void 0 : _j[600]) !== null && _k !== void 0 ? _k : solid;
34
+ const ringTint = (_m = (_l = meta.scale) === null || _l === void 0 ? void 0 : _l[200]) !== null && _m !== void 0 ? _m : soft;
35
+ const showProgress = typeof duration === "number" && duration > 0;
36
+ return ((0, jsx_runtime_1.jsxs)(MotionBox
37
+ // Refined entrance — slides in from the right and settles, never a hard pop.
38
+ // framer owns ALL transform animation; the CSS transition below is limited to
39
+ // box-shadow so it never tweens the same `transform` framer is driving frame
40
+ // by frame (that double-drive is what caused the ~200ms entry flicker). A
41
+ // tween (not spring) lands on an exact end transform, so there's no residual
42
+ // sub-pixel settle to shimmer.
43
+ , {
44
+ // Refined entrance — slides in from the right and settles, never a hard pop.
45
+ // framer owns ALL transform animation; the CSS transition below is limited to
46
+ // box-shadow so it never tweens the same `transform` framer is driving frame
47
+ // by frame (that double-drive is what caused the ~200ms entry flicker). A
48
+ // tween (not spring) lands on an exact end transform, so there's no residual
49
+ // sub-pixel settle to shimmer.
50
+ initial: { opacity: 0, x: 24 }, animate: { opacity: 1, x: 0 }, exit: { opacity: 0, x: 24 }, transition: { duration: 0.24, ease: [0.22, 1, 0.36, 1] }, onHoverStart: () => setPaused(true), onHoverEnd: () => setPaused(false), position: "relative", bg: (_o = c === null || c === void 0 ? void 0 : c.white) !== null && _o !== void 0 ? _o : "#fff", border: `0.063rem solid ${(_s = (_q = (_p = c === null || c === void 0 ? void 0 : c.boxborder) === null || _p === void 0 ? void 0 : _p[300]) !== null && _q !== void 0 ? _q : (_r = c === null || c === void 0 ? void 0 : c.gray) === null || _r === void 0 ? void 0 : _r[200]) !== null && _s !== void 0 ? _s : "#e2e8f0"}`, boxShadow: shadowLg !== null && shadowLg !== void 0 ? shadowLg : "lg", borderRadius: "0.875rem", overflow: "hidden", minW: "22.5rem", maxW: "26rem", willChange: "transform, opacity", sx: {
51
+ transition: "box-shadow 0.18s ease",
52
+ _hover: { boxShadow: "xl" },
53
+ }, children: [(0, jsx_runtime_1.jsxs)(react_2.Flex, { p: 3.5, gap: 3, align: actions ? "flex-start" : "center", children: [(0, jsx_runtime_1.jsx)(react_2.Flex, { align: "center", justify: "center", boxSize: "2rem", minW: "2rem", borderRadius: "full", bg: soft, color: accent, sx: {
54
+ ["--toast-pulse-color"]: ringTint,
55
+ animation: `${iconPulse} 900ms ease-out 1`,
56
+ }, children: meta.icon }), (0, jsx_runtime_1.jsxs)(react_2.Box, { flex: "1", minW: 0, children: [title && ((0, jsx_runtime_1.jsx)(react_2.Text, { fontWeight: 600, fontSize: "0.875rem", lineHeight: "1.3", color: (_w = (_u = (_t = c === null || c === void 0 ? void 0 : c.text) === null || _t === void 0 ? void 0 : _t[800]) !== null && _u !== void 0 ? _u : (_v = c === null || c === void 0 ? void 0 : c.gray) === null || _v === void 0 ? void 0 : _v[800]) !== null && _w !== void 0 ? _w : "#2d3748", children: title })), description && ((0, jsx_runtime_1.jsx)(react_2.Text, { fontSize: "0.8125rem", lineHeight: "1.45", color: (_0 = (_y = (_x = c === null || c === void 0 ? void 0 : c.gray) === null || _x === void 0 ? void 0 : _x[600]) !== null && _y !== void 0 ? _y : (_z = c === null || c === void 0 ? void 0 : c.text) === null || _z === void 0 ? void 0 : _z[600]) !== null && _0 !== void 0 ? _0 : "#718096", mt: title ? "0.125rem" : 0, children: description })), actions && ((0, jsx_runtime_1.jsx)(react_2.Flex, { gap: 2, mt: 2.5, align: "center", wrap: "wrap", children: actions(onClose) }))] }), isClosable && ((0, jsx_runtime_1.jsx)(react_2.CloseButton, { onClick: onClose, size: "sm", color: (_2 = (_1 = c === null || c === void 0 ? void 0 : c.gray) === null || _1 === void 0 ? void 0 : _1[400]) !== null && _2 !== void 0 ? _2 : "#a0aec0", borderRadius: "md", alignSelf: "flex-start", _hover: {
57
+ bg: (_4 = (_3 = c === null || c === void 0 ? void 0 : c.gray) === null || _3 === void 0 ? void 0 : _3[100]) !== null && _4 !== void 0 ? _4 : "#edf2f7",
58
+ color: (_6 = (_5 = c === null || c === void 0 ? void 0 : c.gray) === null || _5 === void 0 ? void 0 : _5[700]) !== null && _6 !== void 0 ? _6 : "#4a5568",
59
+ } }))] }), showProgress && ((0, jsx_runtime_1.jsx)(react_2.Box, { position: "absolute", bottom: 0, left: 0, right: 0, h: "0.1875rem", bg: solid, opacity: 0.85, transformOrigin: "left", sx: {
60
+ animation: `${shrink} ${duration}ms linear forwards`,
61
+ animationPlayState: paused ? "paused" : "running",
62
+ } }))] }));
63
+ }
15
64
  function ToasterProvider({ children }) {
16
65
  var _a;
17
66
  const toast = (0, react_2.useToast)();
18
67
  const theme = (0, react_2.useTheme)();
19
68
  const c = (_a = theme.colors) !== null && _a !== void 0 ? _a : {};
20
- const showToast = ({ title, description, status = "info", duration = 5000, isClosable = true, position = "top-right", onClose, }) => {
21
- var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o, _p, _q, _r;
22
- // Status → semantic color scale + icon (falls back to legacy palettes).
69
+ const showToast = ({ title, description, status = "info", duration = 5000, isClosable = true, position = "top-right", onClose, actions, }) => {
70
+ var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l;
23
71
  const statusConfig = {
24
72
  success: {
25
73
  scale: (_b = (_a = c.semantic) === null || _a === void 0 ? void 0 : _a.success) !== null && _b !== void 0 ? _b : c.green,
@@ -42,21 +90,15 @@ function ToasterProvider({ children }) {
42
90
  icon: (0, jsx_runtime_1.jsx)(react_2.Spinner, { size: "sm", thickness: "0.125rem", speed: "0.7s" }),
43
91
  },
44
92
  };
45
- const { scale, icon } = (_l = statusConfig[status]) !== null && _l !== void 0 ? _l : statusConfig.info;
46
- const solid = (_m = scale === null || scale === void 0 ? void 0 : scale[500]) !== null && _m !== void 0 ? _m : (_o = c.gray) === null || _o === void 0 ? void 0 : _o[500];
47
- const soft = (_p = scale === null || scale === void 0 ? void 0 : scale[50]) !== null && _p !== void 0 ? _p : (_q = c.gray) === null || _q === void 0 ? void 0 : _q[50];
48
- const accent = (_r = scale === null || scale === void 0 ? void 0 : scale[600]) !== null && _r !== void 0 ? _r : solid;
49
- const showProgress = typeof duration === "number" && duration > 0;
93
+ const meta = (_l = statusConfig[status]) !== null && _l !== void 0 ? _l : statusConfig.info;
50
94
  toast({
51
95
  duration,
52
96
  isClosable,
53
97
  position,
54
98
  onCloseComplete: onClose,
55
99
  render: ({ onClose }) => {
56
- var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o, _p, _q;
57
- return ((0, jsx_runtime_1.jsxs)(react_2.Box, { position: "relative", bg: (_a = c.white) !== null && _a !== void 0 ? _a : "#fff", border: `0.063rem solid ${(_c = (_b = c.boxborder) === null || _b === void 0 ? void 0 : _b[300]) !== null && _c !== void 0 ? _c : (_d = c.gray) === null || _d === void 0 ? void 0 : _d[200]}`, boxShadow: (_f = (_e = theme.shadows) === null || _e === void 0 ? void 0 : _e.lg) !== null && _f !== void 0 ? _f : "lg", borderRadius: "0.75rem", overflow: "hidden", minW: "22.5rem", maxW: "26rem", children: [(0, jsx_runtime_1.jsxs)(react_2.Flex, { p: 3.5, gap: 3, align: "center", children: [(0, jsx_runtime_1.jsx)(react_2.Flex, { align: "center", justify: "center", boxSize: "2rem", minW: "2rem", borderRadius: "full", bg: soft, color: accent, children: icon }), (0, jsx_runtime_1.jsxs)(react_2.Box, { flex: "1", minW: 0, children: [title && ((0, jsx_runtime_1.jsx)(react_2.Text, { fontWeight: 600, fontSize: "0.875rem", lineHeight: "1.3", color: (_h = (_g = c.text) === null || _g === void 0 ? void 0 : _g[800]) !== null && _h !== void 0 ? _h : (_j = c.gray) === null || _j === void 0 ? void 0 : _j[800], children: title })), description && ((0, jsx_runtime_1.jsx)(react_2.Text, { fontSize: "0.8125rem", lineHeight: "1.45", color: (_l = (_k = c.gray) === null || _k === void 0 ? void 0 : _k[600]) !== null && _l !== void 0 ? _l : (_m = c.text) === null || _m === void 0 ? void 0 : _m[600], mt: title ? "0.125rem" : 0, children: description }))] }), isClosable && ((0, jsx_runtime_1.jsx)(react_2.CloseButton, { onClick: onClose, size: "sm", color: (_o = c.gray) === null || _o === void 0 ? void 0 : _o[500], borderRadius: "md", _hover: { bg: (_p = c.gray) === null || _p === void 0 ? void 0 : _p[100], color: (_q = c.gray) === null || _q === void 0 ? void 0 : _q[700] } }))] }), showProgress && ((0, jsx_runtime_1.jsx)(react_2.Box, { position: "absolute", bottom: 0, left: 0, right: 0, h: "0.1875rem", bg: solid, transformOrigin: "left", sx: {
58
- animation: `${shrink} ${duration}ms linear forwards`,
59
- } }))] }));
100
+ var _a;
101
+ return ((0, jsx_runtime_1.jsx)(ToastCard, { onClose: onClose, title: title, description: description, actions: actions, isClosable: isClosable, duration: duration, meta: meta, colors: c, shadowLg: (_a = theme.shadows) === null || _a === void 0 ? void 0 : _a.lg }));
60
102
  },
61
103
  });
62
104
  };
@@ -3,6 +3,13 @@ import { ReactNode } from "react";
3
3
  export type ToasterToastProps = Pick<ToastProps, 'description' | 'title' | 'isClosable' | 'duration' | 'children' | 'onClose'> & {
4
4
  position?: "top" | "bottom" | "top-right" | "top-left" | "bottom-right" | "bottom-left";
5
5
  status?: "success" | "error" | "warning" | "info" | "loading";
6
+ /**
7
+ * Optional action buttons rendered under the message (Jira-style "View" /
8
+ * "Copy link" affordances). Receives the toast's own `onClose` so an action
9
+ * can dismiss the toast. Kept a render-prop so callers style buttons with
10
+ * their app theme; the Toaster only positions them.
11
+ */
12
+ actions?: (onClose: () => void) => ReactNode;
6
13
  };
7
14
  export interface ToasterContextType {
8
15
  showToast: (children: ToasterToastProps) => void;
@@ -1 +1 @@
1
- {"version":3,"file":"ToasterProps.d.ts","sourceRoot":"","sources":["../../../src/Components/Toaster/ToasterProps.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AAC9C,OAAO,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AAElC,MAAM,MAAM,iBAAiB,GAAG,IAAI,CAAC,UAAU,EAAE,aAAa,GAAG,OAAO,GAAG,YAAY,GAAG,UAAU,GAAG,UAAU,GAAG,SAAS,CAAC,GAAG;IAC7H,QAAQ,CAAC,EAAE,KAAK,GAAG,QAAQ,GAAG,WAAW,GAAG,UAAU,GAAG,cAAc,GAAG,aAAa,CAAA;IACvF,MAAM,CAAC,EAAE,SAAS,GAAG,OAAO,GAAG,SAAS,GAAG,MAAM,GAAG,SAAS,CAAA;CAChE,CAAA;AAED,MAAM,WAAW,kBAAkB;IAC/B,SAAS,EAAE,CAAC,QAAQ,EAAE,iBAAiB,KAAK,IAAI,CAAA;CACnD;AAED,MAAM,WAAW,eAAe;IAC5B,QAAQ,EAAE,SAAS,CAAC;CACvB"}
1
+ {"version":3,"file":"ToasterProps.d.ts","sourceRoot":"","sources":["../../../src/Components/Toaster/ToasterProps.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AAC9C,OAAO,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AAElC,MAAM,MAAM,iBAAiB,GAAG,IAAI,CAAC,UAAU,EAAE,aAAa,GAAG,OAAO,GAAG,YAAY,GAAG,UAAU,GAAG,UAAU,GAAG,SAAS,CAAC,GAAG;IAC7H,QAAQ,CAAC,EAAE,KAAK,GAAG,QAAQ,GAAG,WAAW,GAAG,UAAU,GAAG,cAAc,GAAG,aAAa,CAAA;IACvF,MAAM,CAAC,EAAE,SAAS,GAAG,OAAO,GAAG,SAAS,GAAG,MAAM,GAAG,SAAS,CAAA;IAC7D;;;;;OAKG;IACH,OAAO,CAAC,EAAE,CAAC,OAAO,EAAE,MAAM,IAAI,KAAK,SAAS,CAAA;CAC/C,CAAA;AAED,MAAM,WAAW,kBAAkB;IAC/B,SAAS,EAAE,CAAC,QAAQ,EAAE,iBAAiB,KAAK,IAAI,CAAA;CACnD;AAED,MAAM,WAAW,eAAe;IAC5B,QAAQ,EAAE,SAAS,CAAC;CACvB"}
@@ -0,0 +1,18 @@
1
+ import { ToolTipProps } from "./ToolTipProps";
2
+ /**
3
+ * A tooltip that only appears when its child text is actually truncated
4
+ * (ellipsis active) — no tooltip when the text fully fits. Thin sugar over
5
+ * `<ToolTip overflowOnly>`; use it wherever you clamp text with `noOfLines` /
6
+ * ellipsis and want the full text revealed only when it's cut off.
7
+ *
8
+ * The child must be the single element that clamps the text (e.g. a Chakra
9
+ * `Text` with `noOfLines`); its ref is managed internally. Works for both
10
+ * single-line and multi-line clamps.
11
+ *
12
+ * @example
13
+ * <OverflowToolTip label={title}>
14
+ * <Text noOfLines={1}>{title}</Text>
15
+ * </OverflowToolTip>
16
+ */
17
+ export default function OverflowToolTip(props: ToolTipProps): import("react/jsx-runtime").JSX.Element;
18
+ //# sourceMappingURL=OverflowToolTip.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"OverflowToolTip.d.ts","sourceRoot":"","sources":["../../../src/Components/ToolTip/OverflowToolTip.tsx"],"names":[],"mappings":"AACA,OAAO,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AAE9C;;;;;;;;;;;;;;GAcG;AACH,MAAM,CAAC,OAAO,UAAU,eAAe,CAAC,KAAK,EAAE,YAAY,2CAE1D"}
@@ -0,0 +1,26 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.default = OverflowToolTip;
7
+ const jsx_runtime_1 = require("react/jsx-runtime");
8
+ const ToolTip_1 = __importDefault(require("./ToolTip"));
9
+ /**
10
+ * A tooltip that only appears when its child text is actually truncated
11
+ * (ellipsis active) — no tooltip when the text fully fits. Thin sugar over
12
+ * `<ToolTip overflowOnly>`; use it wherever you clamp text with `noOfLines` /
13
+ * ellipsis and want the full text revealed only when it's cut off.
14
+ *
15
+ * The child must be the single element that clamps the text (e.g. a Chakra
16
+ * `Text` with `noOfLines`); its ref is managed internally. Works for both
17
+ * single-line and multi-line clamps.
18
+ *
19
+ * @example
20
+ * <OverflowToolTip label={title}>
21
+ * <Text noOfLines={1}>{title}</Text>
22
+ * </OverflowToolTip>
23
+ */
24
+ function OverflowToolTip(props) {
25
+ return (0, jsx_runtime_1.jsx)(ToolTip_1.default, { ...props, overflowOnly: true });
26
+ }
@@ -1,3 +1,3 @@
1
1
  import { ToolTipProps } from "./ToolTipProps";
2
- export default function ToolTip({ placement, label, children, hasArrow, fontSize, bg, color, isDisabled, isOpen, defaultIsOpen, openDelay, closeDelay, arrowSize, closeOnClick, size, width, height, arrowPadding, arrowShadowColor, direction, gutter, onClose, modifiers, closeOnPointerDown, styles, }: ToolTipProps): import("react/jsx-runtime").JSX.Element;
2
+ export default function ToolTip({ placement, label, children, hasArrow, fontSize, bg, color, isDisabled, overflowOnly, isOpen, defaultIsOpen, openDelay, closeDelay, arrowSize, closeOnClick, size, width, height, arrowPadding, arrowShadowColor, direction, gutter, onClose, modifiers, closeOnPointerDown, styles, }: ToolTipProps): import("react/jsx-runtime").JSX.Element;
3
3
  //# sourceMappingURL=ToolTip.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"ToolTip.d.ts","sourceRoot":"","sources":["../../../src/Components/ToolTip/ToolTip.tsx"],"names":[],"mappings":"AACA,OAAO,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AAE9C,MAAM,CAAC,OAAO,UAAU,OAAO,CAAC,EAC9B,SAAiB,EACjB,KAAK,EACL,QAAQ,EACR,QAAe,EACf,QAAiB,EACjB,EAAc,EACd,KAAe,EACf,UAAU,EACV,MAAM,EACN,aAAa,EACb,SAAa,EACb,UAAc,EACd,SAAc,EACd,YAAoB,EACpB,IAAI,EACJ,KAAK,EACL,MAAM,EACN,YAAY,EACZ,gBAAgB,EAChB,SAAS,EACT,MAAU,EACV,OAAO,EACP,SAAS,EACT,kBAAkB,EAClB,MAAM,GACP,EAAE,YAAY,2CAqCd"}
1
+ {"version":3,"file":"ToolTip.d.ts","sourceRoot":"","sources":["../../../src/Components/ToolTip/ToolTip.tsx"],"names":[],"mappings":"AAEA,OAAO,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AAI9C,MAAM,CAAC,OAAO,UAAU,OAAO,CAAC,EAC9B,SAAiB,EACjB,KAAK,EACL,QAAQ,EACR,QAAe,EACf,QAAiB,EACjB,EAAc,EACd,KAAe,EACf,UAAU,EACV,YAAoB,EACpB,MAAM,EACN,aAAa,EACb,SAAa,EACb,UAAc,EACd,SAAc,EACd,YAAoB,EACpB,IAAI,EACJ,KAAK,EACL,MAAM,EACN,YAAY,EACZ,gBAAgB,EAChB,SAAS,EACT,MAAU,EACV,OAAO,EACP,SAAS,EACT,kBAAkB,EAClB,MAAM,GACP,EAAE,YAAY,2CA4Dd"}
@@ -2,7 +2,25 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.default = ToolTip;
4
4
  const jsx_runtime_1 = require("react/jsx-runtime");
5
- const react_1 = require("@chakra-ui/react");
6
- function ToolTip({ placement = "top", label, children, hasArrow = true, fontSize = "14px", bg = "#12161B", color = "white", isDisabled, isOpen, defaultIsOpen, openDelay = 0, closeDelay = 0, arrowSize = 10, closeOnClick = false, size, width, height, arrowPadding, arrowShadowColor, direction, gutter = 8, onClose, modifiers, closeOnPointerDown, styles, }) {
7
- return ((0, jsx_runtime_1.jsx)(react_1.Tooltip, { label: label, placement: placement, hasArrow: hasArrow, fontSize: fontSize, bg: bg, color: color, isDisabled: isDisabled, isOpen: isOpen, defaultIsOpen: defaultIsOpen, openDelay: openDelay, closeDelay: closeDelay, arrowSize: arrowSize, closeOnClick: closeOnClick, size: size, width: width, height: height, arrowPadding: arrowPadding, arrowShadowColor: arrowShadowColor, direction: direction, gutter: gutter, onClose: onClose, modifiers: modifiers, closeOnPointerDown: closeOnPointerDown, style: styles, px: 3, py: 2, borderRadius: "8px", fontWeight: "400", lineHeight: "1.5", maxW: "300px", children: children }));
5
+ const react_1 = require("react");
6
+ const react_2 = require("@chakra-ui/react");
7
+ const useIsTruncated_1 = require("../../Hooks/useIsTruncated");
8
+ const mergeRefs_1 = require("../../Utils/mergeRefs");
9
+ function ToolTip({ placement = "top", label, children, hasArrow = true, fontSize = "14px", bg = "#12161B", color = "white", isDisabled, overflowOnly = false, isOpen, defaultIsOpen, openDelay = 0, closeDelay = 0, arrowSize = 10, closeOnClick = false, size, width, height, arrowPadding, arrowShadowColor, direction, gutter = 8, onClose, modifiers, closeOnPointerDown, styles, }) {
10
+ // Measure the child for `overflowOnly`. The hook is always called (Rules of
11
+ // Hooks) but is fully inert unless `overflowOnly` is set — no layout reads,
12
+ // no ResizeObserver, no re-renders for ordinary tooltips. Measurement never
13
+ // runs on hover/scroll, so showing the tooltip stays as cheap as before.
14
+ const { ref, isTruncated } = (0, useIsTruncated_1.useIsTruncated)(label, overflowOnly && (0, react_1.isValidElement)(children));
15
+ let content = children;
16
+ let effectiveDisabled = isDisabled;
17
+ if (overflowOnly && (0, react_1.isValidElement)(children)) {
18
+ const child = children;
19
+ const childRef = child.ref;
20
+ content = (0, react_1.cloneElement)(child, {
21
+ ref: (0, mergeRefs_1.mergeRefs)(ref, childRef),
22
+ });
23
+ effectiveDisabled = Boolean(isDisabled) || !isTruncated;
24
+ }
25
+ return ((0, jsx_runtime_1.jsx)(react_2.Tooltip, { label: label, placement: placement, hasArrow: hasArrow, fontSize: fontSize, bg: bg, color: color, isDisabled: effectiveDisabled, isOpen: isOpen, defaultIsOpen: defaultIsOpen, openDelay: openDelay, closeDelay: closeDelay, arrowSize: arrowSize, closeOnClick: closeOnClick, size: size, width: width, height: height, arrowPadding: arrowPadding, arrowShadowColor: arrowShadowColor, direction: direction, gutter: gutter, onClose: onClose, modifiers: modifiers, closeOnPointerDown: closeOnPointerDown, style: styles, px: 3, py: 2, borderRadius: "8px", fontWeight: "400", lineHeight: "1.5", maxW: "300px", children: content }));
8
26
  }
@@ -2,6 +2,15 @@ import { TooltipProps as ChakraTooltip } from "@chakra-ui/react";
2
2
  export type ToolTipProps = Pick<ChakraTooltip, "placement" | "label" | "hasArrow" | "fontSize" | "bg" | "color" | "isDisabled" | "isOpen" | "defaultIsOpen" | "openDelay" | "closeDelay" | "arrowSize" | "closeOnClick" | "size" | "width" | "height" | "arrowPadding" | "arrowShadowColor" | "direction" | "gutter" | "onClose" | "modifiers" | "closeOnPointerDown"> & {
3
3
  children: React.ReactNode;
4
4
  styles?: React.CSSProperties;
5
+ /**
6
+ * When `true`, the tooltip is shown **only** while its child is actually
7
+ * truncated (ellipsis active) — no tooltip when the text fully fits. The
8
+ * child must be the single element that clamps the text (e.g. a `Text` with
9
+ * `noOfLines` / `isTruncated`); its ref is managed internally. Combines with
10
+ * `isDisabled` (either disabling condition hides the tooltip). Works for both
11
+ * single-line and multi-line clamps.
12
+ */
13
+ overflowOnly?: boolean;
5
14
  placement?: "auto" | "auto-start" | "auto-end" | "top" | "top-start" | "top-end" | "right" | "right-start" | "right-end" | "bottom" | "bottom-start" | "bottom-end" | "left" | "left-start" | "left-end";
6
15
  };
7
16
  //# sourceMappingURL=ToolTipProps.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"ToolTipProps.d.ts","sourceRoot":"","sources":["../../../src/Components/ToolTip/ToolTipProps.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,IAAI,aAAa,EAAE,MAAM,kBAAkB,CAAC;AACjE,MAAM,MAAM,YAAY,GAAG,IAAI,CAC7B,aAAa,EACX,WAAW,GACX,OAAO,GACP,UAAU,GACV,UAAU,GACV,IAAI,GACJ,OAAO,GACP,YAAY,GACZ,QAAQ,GACR,eAAe,GACf,WAAW,GACX,YAAY,GACZ,WAAW,GACX,cAAc,GACd,MAAM,GACN,OAAO,GACP,QAAQ,GACR,cAAc,GACd,kBAAkB,GAClB,WAAW,GACX,QAAQ,GACR,SAAS,GACT,WAAW,GACX,oBAAoB,CACvB,GAAG;IACF,QAAQ,EAAE,KAAK,CAAC,SAAS,CAAC;IAC1B,MAAM,CAAC,EAAE,KAAK,CAAC,aAAa,CAAC;IAC7B,SAAS,CAAC,EACN,MAAM,GACN,YAAY,GACZ,UAAU,GACV,KAAK,GACL,WAAW,GACX,SAAS,GACT,OAAO,GACP,aAAa,GACb,WAAW,GACX,QAAQ,GACR,cAAc,GACd,YAAY,GACZ,MAAM,GACN,YAAY,GACZ,UAAU,CAAC;CAChB,CAAC"}
1
+ {"version":3,"file":"ToolTipProps.d.ts","sourceRoot":"","sources":["../../../src/Components/ToolTip/ToolTipProps.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,IAAI,aAAa,EAAE,MAAM,kBAAkB,CAAC;AACjE,MAAM,MAAM,YAAY,GAAG,IAAI,CAC7B,aAAa,EACX,WAAW,GACX,OAAO,GACP,UAAU,GACV,UAAU,GACV,IAAI,GACJ,OAAO,GACP,YAAY,GACZ,QAAQ,GACR,eAAe,GACf,WAAW,GACX,YAAY,GACZ,WAAW,GACX,cAAc,GACd,MAAM,GACN,OAAO,GACP,QAAQ,GACR,cAAc,GACd,kBAAkB,GAClB,WAAW,GACX,QAAQ,GACR,SAAS,GACT,WAAW,GACX,oBAAoB,CACvB,GAAG;IACF,QAAQ,EAAE,KAAK,CAAC,SAAS,CAAC;IAC1B,MAAM,CAAC,EAAE,KAAK,CAAC,aAAa,CAAC;IAC7B;;;;;;;OAOG;IACH,YAAY,CAAC,EAAE,OAAO,CAAC;IACvB,SAAS,CAAC,EACN,MAAM,GACN,YAAY,GACZ,UAAU,GACV,KAAK,GACL,WAAW,GACX,SAAS,GACT,OAAO,GACP,aAAa,GACb,WAAW,GACX,QAAQ,GACR,cAAc,GACd,YAAY,GACZ,MAAM,GACN,YAAY,GACZ,UAAU,CAAC;CAChB,CAAC"}
@@ -0,0 +1,16 @@
1
+ import type { WorkspaceTrayPreviewProps } from "./WorkspaceWindowProps";
2
+ /**
3
+ * Presentational, app-agnostic hover-preview for a "workspace tray" pill (or any
4
+ * trigger). Headless of any data: the consumer passes the trigger as `children`
5
+ * and the card body as `preview` (node or render-prop receiving `close()`), so
6
+ * this can preview a ticket, a doc, a chat — anything — with the same intent-safe
7
+ * hover behavior.
8
+ *
9
+ * Intent-safe hover (hover-bridge): hovering the trigger opens the card after a
10
+ * short delay (anti-flash); a shared open/close timer + small gap let the cursor
11
+ * travel trigger ⇄ card without the card closing; leaving both (with a grace
12
+ * delay) closes it; Escape dismisses. Fetch/render the preview lazily via
13
+ * `onOpenChange`.
14
+ */
15
+ export default function WorkspaceTrayPreview({ children, preview, enabled, openDelayMs, closeDelayMs, placement, onOpenChange, width, testId, }: WorkspaceTrayPreviewProps): import("react/jsx-runtime").JSX.Element;
16
+ //# sourceMappingURL=WorkspaceTrayPreview.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"WorkspaceTrayPreview.d.ts","sourceRoot":"","sources":["../../../src/Components/WorkspaceWindow/WorkspaceTrayPreview.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,yBAAyB,EAAE,MAAM,wBAAwB,CAAC;AAcxE;;;;;;;;;;;;GAYG;AACH,MAAM,CAAC,OAAO,UAAU,oBAAoB,CAAC,EAC3C,QAAQ,EACR,OAAO,EACP,OAAc,EACd,WAAiB,EACjB,YAAkB,EAClB,SAAqB,EACrB,YAAY,EACZ,KAAe,EACf,MAAiC,GAClC,EAAE,yBAAyB,2CAuG3B"}
@@ -0,0 +1,83 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.default = WorkspaceTrayPreview;
4
+ const jsx_runtime_1 = require("react/jsx-runtime");
5
+ const react_1 = require("react");
6
+ const react_2 = require("@chakra-ui/react");
7
+ const PLACEMENT_STYLE = {
8
+ "top-end": { bottom: "100%", right: 0, marginBottom: "6px" },
9
+ "top-start": { bottom: "100%", left: 0, marginBottom: "6px" },
10
+ "bottom-end": { top: "100%", right: 0, marginTop: "6px" },
11
+ "bottom-start": { top: "100%", left: 0, marginTop: "6px" },
12
+ };
13
+ /**
14
+ * Presentational, app-agnostic hover-preview for a "workspace tray" pill (or any
15
+ * trigger). Headless of any data: the consumer passes the trigger as `children`
16
+ * and the card body as `preview` (node or render-prop receiving `close()`), so
17
+ * this can preview a ticket, a doc, a chat — anything — with the same intent-safe
18
+ * hover behavior.
19
+ *
20
+ * Intent-safe hover (hover-bridge): hovering the trigger opens the card after a
21
+ * short delay (anti-flash); a shared open/close timer + small gap let the cursor
22
+ * travel trigger ⇄ card without the card closing; leaving both (with a grace
23
+ * delay) closes it; Escape dismisses. Fetch/render the preview lazily via
24
+ * `onOpenChange`.
25
+ */
26
+ function WorkspaceTrayPreview({ children, preview, enabled = true, openDelayMs = 350, closeDelayMs = 200, placement = "top-end", onOpenChange, width = "340px", testId = "workspace-tray-preview", }) {
27
+ const [open, setOpen] = (0, react_1.useState)(false);
28
+ const openTimer = (0, react_1.useRef)(null);
29
+ const closeTimer = (0, react_1.useRef)(null);
30
+ const setOpenState = (0, react_1.useCallback)((next) => {
31
+ setOpen(next);
32
+ onOpenChange === null || onOpenChange === void 0 ? void 0 : onOpenChange(next);
33
+ }, [onOpenChange]);
34
+ const clearOpenTimer = (0, react_1.useCallback)(() => {
35
+ if (openTimer.current) {
36
+ clearTimeout(openTimer.current);
37
+ openTimer.current = null;
38
+ }
39
+ }, []);
40
+ const clearCloseTimer = (0, react_1.useCallback)(() => {
41
+ if (closeTimer.current) {
42
+ clearTimeout(closeTimer.current);
43
+ closeTimer.current = null;
44
+ }
45
+ }, []);
46
+ const scheduleOpen = (0, react_1.useCallback)(() => {
47
+ if (!enabled)
48
+ return;
49
+ clearCloseTimer();
50
+ if (open || openTimer.current)
51
+ return;
52
+ openTimer.current = setTimeout(() => {
53
+ openTimer.current = null;
54
+ setOpenState(true);
55
+ }, openDelayMs);
56
+ }, [enabled, clearCloseTimer, open, openDelayMs, setOpenState]);
57
+ const scheduleClose = (0, react_1.useCallback)(() => {
58
+ clearOpenTimer();
59
+ if (closeTimer.current)
60
+ return;
61
+ closeTimer.current = setTimeout(() => {
62
+ closeTimer.current = null;
63
+ setOpenState(false);
64
+ }, closeDelayMs);
65
+ }, [clearOpenTimer, closeDelayMs, setOpenState]);
66
+ const closeNow = (0, react_1.useCallback)(() => {
67
+ clearOpenTimer();
68
+ clearCloseTimer();
69
+ setOpenState(false);
70
+ }, [clearOpenTimer, clearCloseTimer, setOpenState]);
71
+ (0, react_1.useEffect)(() => () => {
72
+ clearOpenTimer();
73
+ clearCloseTimer();
74
+ }, [clearOpenTimer, clearCloseTimer]);
75
+ return ((0, jsx_runtime_1.jsxs)(react_2.Box, { position: "relative", onMouseEnter: scheduleOpen, onMouseLeave: scheduleClose, onFocus: scheduleOpen, onBlur: scheduleClose, onKeyDown: (e) => {
76
+ if (e.key === "Escape" && open) {
77
+ e.stopPropagation();
78
+ closeNow();
79
+ }
80
+ }, children: [children, open && ((0, jsx_runtime_1.jsx)(react_2.Box, { position: "absolute", ...PLACEMENT_STYLE[placement], w: typeof width === "number" ? `${width}px` : width, maxW: "min(360px, calc(100vw - 2rem))", bg: "white", borderWidth: "1px", borderColor: "gray.200", borderRadius: "lg", boxShadow: "xl", zIndex: 1500, pointerEvents: "auto", p: 3, textAlign: "left", color: "gray.800", cursor: "default", onMouseEnter: clearCloseTimer, onMouseLeave: scheduleClose, "data-testid": testId, children: typeof preview === "function"
81
+ ? preview({ close: closeNow })
82
+ : preview }))] }));
83
+ }
@@ -0,0 +1,15 @@
1
+ import type { WorkspaceTrayProps, WorkspaceWindowProps } from "./WorkspaceWindowProps";
2
+ /**
3
+ * Presentational floating "workspace window" — a Jira-style dialog with
4
+ * minimize / close controls and an optional "open full page" affordance, at a
5
+ * single fixed size (no maximize/restore toggle). Headless of any state
6
+ * management: the parent owns the window state and passes callbacks. Render
7
+ * minimized windows with the companion WorkspaceTray.
8
+ */
9
+ export default function WorkspaceWindow({ title, state, children, onMinimize, onClose, onOpenFullPage, headerActions, testId, }: WorkspaceWindowProps): import("react/jsx-runtime").JSX.Element | null;
10
+ /**
11
+ * Bottom tray of restore pills for minimized WorkspaceWindows. Presentational —
12
+ * the parent supplies the minimized items and restore/close handlers.
13
+ */
14
+ export declare function WorkspaceTray({ items, onRestore, onClose, testId, }: WorkspaceTrayProps): import("react/jsx-runtime").JSX.Element | null;
15
+ //# sourceMappingURL=WorkspaceWindow.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"WorkspaceWindow.d.ts","sourceRoot":"","sources":["../../../src/Components/WorkspaceWindow/WorkspaceWindow.tsx"],"names":[],"mappings":"AAYA,OAAO,KAAK,EACV,kBAAkB,EAClB,oBAAoB,EACrB,MAAM,wBAAwB,CAAC;AAOhC;;;;;;GAMG;AACH,MAAM,CAAC,OAAO,UAAU,eAAe,CAAC,EACtC,KAAK,EACL,KAAK,EACL,QAAQ,EACR,UAAU,EACV,OAAO,EACP,cAAc,EACd,aAAa,EACb,MAA2B,GAC5B,EAAE,oBAAoB,kDAqGtB;AAED;;;GAGG;AACH,wBAAgB,aAAa,CAAC,EAC5B,KAAK,EACL,SAAS,EACT,OAAO,EACP,MAAyB,GAC1B,EAAE,kBAAkB,kDAkEpB"}
@@ -0,0 +1,40 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.default = WorkspaceWindow;
4
+ exports.WorkspaceTray = WorkspaceTray;
5
+ const jsx_runtime_1 = require("react/jsx-runtime");
6
+ const react_1 = require("@chakra-ui/react");
7
+ const lucide_react_1 = require("lucide-react");
8
+ // One in-between windowed size — wider than a cramped dialog but not near-full
9
+ // screen. There is no maximize/restore toggle (removed by product decision); the
10
+ // `onMedium`/`onMaximize` props are kept optional for back-compat but unused.
11
+ const WINDOW_SIZE = { maxW: "88rem", h: "92vh" };
12
+ /**
13
+ * Presentational floating "workspace window" — a Jira-style dialog with
14
+ * minimize / close controls and an optional "open full page" affordance, at a
15
+ * single fixed size (no maximize/restore toggle). Headless of any state
16
+ * management: the parent owns the window state and passes callbacks. Render
17
+ * minimized windows with the companion WorkspaceTray.
18
+ */
19
+ function WorkspaceWindow({ title, state, children, onMinimize, onClose, onOpenFullPage, headerActions, testId = "workspace-window", }) {
20
+ if (state === "minimized")
21
+ return null;
22
+ const size = WINDOW_SIZE;
23
+ return ((0, jsx_runtime_1.jsxs)(react_1.Modal, { isOpen: true, onClose: () => onClose === null || onClose === void 0 ? void 0 : onClose(), size: "full", isCentered: true, scrollBehavior: "inside",
24
+ // Don't discard unsaved work on an accidental overlay click / Esc — the
25
+ // parent decides via the explicit Close control.
26
+ closeOnOverlayClick: false, closeOnEsc: false, children: [(0, jsx_runtime_1.jsx)(react_1.ModalOverlay, { backdropFilter: "blur(3px)" }), (0, jsx_runtime_1.jsx)(react_1.ModalContent, { bg: "transparent", boxShadow: "none", m: 0, display: "flex", alignItems: "center", justifyContent: "center", children: (0, jsx_runtime_1.jsxs)(react_1.Box, { bg: "white", borderRadius: "0.75rem", boxShadow: "2xl", overflow: "hidden", w: "100%", maxW: size.maxW, h: size.h, display: "flex", flexDirection: "column", "data-testid": testId, "data-window-state": state, children: [(0, jsx_runtime_1.jsxs)(react_1.Flex, { align: "center", justify: "space-between", px: 3, py: 2, borderBottomWidth: "1px", borderColor: "gray.100", bg: "gray.50", flexShrink: 0, children: [(0, jsx_runtime_1.jsx)(react_1.Text, { fontSize: "sm", fontWeight: 600, color: "gray.700", noOfLines: 1, "data-testid": `${testId}-title`, children: title }), (0, jsx_runtime_1.jsxs)(react_1.HStack, { spacing: 1, children: [headerActions, onOpenFullPage ? ((0, jsx_runtime_1.jsx)(react_1.IconButton, { "aria-label": "Open full page", size: "xs", variant: "ghost", icon: (0, jsx_runtime_1.jsx)(lucide_react_1.ExternalLink, { size: 14 }), onClick: onOpenFullPage, "data-testid": `${testId}-fullpage` })) : null, onMinimize ? ((0, jsx_runtime_1.jsx)(react_1.IconButton, { "aria-label": "Minimize", size: "xs", variant: "ghost", icon: (0, jsx_runtime_1.jsx)(lucide_react_1.Minus, { size: 15 }), onClick: onMinimize, "data-testid": `${testId}-minimize` })) : null, onClose ? ((0, jsx_runtime_1.jsx)(react_1.IconButton, { "aria-label": "Close", size: "xs", variant: "ghost", colorScheme: "red", icon: (0, jsx_runtime_1.jsx)(lucide_react_1.X, { size: 15 }), onClick: onClose, "data-testid": `${testId}-close` })) : null] })] }), (0, jsx_runtime_1.jsx)(react_1.Box, { flex: "1", overflow: "auto", px: { base: 3, md: 5 }, py: 4, children: children })] }) })] }));
27
+ }
28
+ /**
29
+ * Bottom tray of restore pills for minimized WorkspaceWindows. Presentational —
30
+ * the parent supplies the minimized items and restore/close handlers.
31
+ */
32
+ function WorkspaceTray({ items, onRestore, onClose, testId = "workspace-tray", }) {
33
+ if (!items.length)
34
+ return null;
35
+ return (
36
+ // Floating bottom-right cluster (Gmail/Jira minimized-window pattern) rather
37
+ // than a full-width docked bar, so it never covers the bottom strip of page
38
+ // content and needs no reserved page gutter. Pills wrap upward.
39
+ (0, jsx_runtime_1.jsx)(react_1.Flex, { position: "fixed", bottom: 4, right: 4, zIndex: 1400, direction: "row-reverse", wrap: "wrap-reverse", justify: "flex-start", gap: 2, maxW: { base: "calc(100vw - 2rem)", md: "36rem" }, "data-testid": testId, children: items.map((item) => ((0, jsx_runtime_1.jsxs)(react_1.HStack, { spacing: 1, pl: 3, pr: 1, py: 1, borderRadius: "full", bg: "blue.100", color: "blue.700", boxShadow: "md", borderWidth: "1px", borderColor: "blue.200", "data-testid": `${testId}-pill`, children: [(0, jsx_runtime_1.jsx)(react_1.Box, { as: "button", type: "button", fontSize: "sm", onClick: () => onRestore === null || onRestore === void 0 ? void 0 : onRestore(item.id), "data-testid": `${testId}-restore`, maxW: "16rem", overflow: "hidden", textOverflow: "ellipsis", whiteSpace: "nowrap", children: item.title }), onClose ? ((0, jsx_runtime_1.jsx)(react_1.IconButton, { "aria-label": "Close", size: "xs", variant: "ghost", borderRadius: "full", minW: "auto", h: "auto", p: 1, color: "inherit", icon: (0, jsx_runtime_1.jsx)(lucide_react_1.X, { size: 13 }), onClick: () => onClose(item.id), "data-testid": `${testId}-close` })) : null] }, item.id))) }));
40
+ }
@@ -0,0 +1,72 @@
1
+ import type { ReactNode } from "react";
2
+ /**
3
+ * Window state for a WorkspaceWindow.
4
+ * - "medium": default centered dialog (Jira-style)
5
+ * - "maximized": near-full-screen
6
+ * - "minimized": collapsed to a tray pill (rendered by WorkspaceTray, not the window)
7
+ */
8
+ export type WorkspaceWindowState = "medium" | "maximized" | "minimized";
9
+ export interface WorkspaceWindowProps {
10
+ /** Title shown in the window's control bar. */
11
+ title: ReactNode;
12
+ /** Current window state. When "minimized", the window renders nothing. */
13
+ state: WorkspaceWindowState;
14
+ /** Window body. */
15
+ children: ReactNode;
16
+ onMinimize?: () => void;
17
+ onMedium?: () => void;
18
+ onMaximize?: () => void;
19
+ onClose?: () => void;
20
+ /** Optional "pop out to full page" affordance; hidden when omitted. */
21
+ onOpenFullPage?: () => void;
22
+ /** Extra controls rendered in the control bar, left of the window buttons. */
23
+ headerActions?: ReactNode;
24
+ /** data-testid for the window container. */
25
+ testId?: string;
26
+ }
27
+ export interface WorkspaceTrayItem {
28
+ id: string;
29
+ title: ReactNode;
30
+ }
31
+ export interface WorkspaceTrayProps {
32
+ /** Minimized items rendered as restore pills along the bottom. */
33
+ items: WorkspaceTrayItem[];
34
+ onRestore?: (id: string) => void;
35
+ onClose?: (id: string) => void;
36
+ testId?: string;
37
+ }
38
+ export interface WorkspaceTrayPreviewProps {
39
+ /**
40
+ * The trigger markup (typically a tray pill). The preview + trigger share one
41
+ * open/close timer so the cursor can travel pill ⇄ preview without the card
42
+ * closing (hover-bridge pattern).
43
+ */
44
+ children: ReactNode;
45
+ /**
46
+ * The preview body, rendered inside the floating card. Headless: the consumer
47
+ * supplies whatever it wants to show (ticket summary, chips, actions, etc.).
48
+ * A render-prop form receives the card's own `close()` so an action inside
49
+ * the preview can dismiss it.
50
+ */
51
+ preview: ReactNode | ((api: {
52
+ close: () => void;
53
+ }) => ReactNode);
54
+ /** Whether the preview is enabled at all (e.g. disable on touch devices). */
55
+ enabled?: boolean;
56
+ /** ms before the card opens on hover/focus (anti-flash). Default 350. */
57
+ openDelayMs?: number;
58
+ /** ms grace before the card closes on leave (bridge). Default 200. */
59
+ closeDelayMs?: number;
60
+ /**
61
+ * Where the card opens relative to the trigger. Default "top-end" (above,
62
+ * right-aligned) — matches a bottom-right tray.
63
+ */
64
+ placement?: "top-start" | "top-end" | "bottom-start" | "bottom-end";
65
+ /** Fires when the card actually opens — use to lazy-load the preview data. */
66
+ onOpenChange?: (open: boolean) => void;
67
+ /** Card width. Default 340px, capped to the viewport on small screens. */
68
+ width?: string | number;
69
+ /** data-testid for the floating card. */
70
+ testId?: string;
71
+ }
72
+ //# sourceMappingURL=WorkspaceWindowProps.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"WorkspaceWindowProps.d.ts","sourceRoot":"","sources":["../../../src/Components/WorkspaceWindow/WorkspaceWindowProps.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AAEvC;;;;;GAKG;AACH,MAAM,MAAM,oBAAoB,GAAG,QAAQ,GAAG,WAAW,GAAG,WAAW,CAAC;AAExE,MAAM,WAAW,oBAAoB;IACnC,+CAA+C;IAC/C,KAAK,EAAE,SAAS,CAAC;IACjB,0EAA0E;IAC1E,KAAK,EAAE,oBAAoB,CAAC;IAC5B,mBAAmB;IACnB,QAAQ,EAAE,SAAS,CAAC;IAEpB,UAAU,CAAC,EAAE,MAAM,IAAI,CAAC;IACxB,QAAQ,CAAC,EAAE,MAAM,IAAI,CAAC;IACtB,UAAU,CAAC,EAAE,MAAM,IAAI,CAAC;IACxB,OAAO,CAAC,EAAE,MAAM,IAAI,CAAC;IACrB,uEAAuE;IACvE,cAAc,CAAC,EAAE,MAAM,IAAI,CAAC;IAE5B,8EAA8E;IAC9E,aAAa,CAAC,EAAE,SAAS,CAAC;IAC1B,4CAA4C;IAC5C,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,WAAW,iBAAiB;IAChC,EAAE,EAAE,MAAM,CAAC;IACX,KAAK,EAAE,SAAS,CAAC;CAClB;AAED,MAAM,WAAW,kBAAkB;IACjC,kEAAkE;IAClE,KAAK,EAAE,iBAAiB,EAAE,CAAC;IAC3B,SAAS,CAAC,EAAE,CAAC,EAAE,EAAE,MAAM,KAAK,IAAI,CAAC;IACjC,OAAO,CAAC,EAAE,CAAC,EAAE,EAAE,MAAM,KAAK,IAAI,CAAC;IAC/B,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,WAAW,yBAAyB;IACxC;;;;OAIG;IACH,QAAQ,EAAE,SAAS,CAAC;IACpB;;;;;OAKG;IACH,OAAO,EAAE,SAAS,GAAG,CAAC,CAAC,GAAG,EAAE;QAAE,KAAK,EAAE,MAAM,IAAI,CAAA;KAAE,KAAK,SAAS,CAAC,CAAC;IACjE,6EAA6E;IAC7E,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,yEAAyE;IACzE,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,sEAAsE;IACtE,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB;;;OAGG;IACH,SAAS,CAAC,EAAE,WAAW,GAAG,SAAS,GAAG,cAAc,GAAG,YAAY,CAAC;IACpE,8EAA8E;IAC9E,YAAY,CAAC,EAAE,CAAC,IAAI,EAAE,OAAO,KAAK,IAAI,CAAC;IACvC,0EAA0E;IAC1E,KAAK,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC;IACxB,yCAAyC;IACzC,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB"}
@@ -0,0 +1,2 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
@@ -0,0 +1,36 @@
1
+ /**
2
+ * Detects whether an element's text is *actually* visually truncated — i.e. the
3
+ * ellipsis is active. Works for both single-line clamps
4
+ * (`overflow: hidden; white-space: nowrap; text-overflow: ellipsis`) and
5
+ * multi-line clamps (`-webkit-line-clamp` / Chakra `noOfLines`), by comparing
6
+ * the scroll size against the visible client size.
7
+ *
8
+ * Attach the returned `ref` to the element that clamps the text, then read
9
+ * `isTruncated` to decide whether a tooltip is worth showing. Re-measures on
10
+ * element resize (via `ResizeObserver`) and whenever `content` changes.
11
+ *
12
+ * @param content Pass the rendered text (or anything that changes with it) so
13
+ * the measurement re-runs when the content changes — the clamp box can keep
14
+ * the same size while the text length changes, which a `ResizeObserver` alone
15
+ * would not catch.
16
+ * @param enabled Set to `false` to fully disable measurement — no layout reads,
17
+ * no `ResizeObserver`, no state updates. Use it to keep the hook cheap when
18
+ * the caller isn't in truncation mode (`isTruncated` stays `false`).
19
+ *
20
+ * Performance: measurement runs only on mount, on element **resize**, and when
21
+ * `content` changes — never on hover, scroll, or re-render. Each run does a
22
+ * single batched layout read (four properties) on one element. When `enabled`
23
+ * is `false` the hook does nothing at all.
24
+ *
25
+ * @example
26
+ * const { ref, isTruncated } = useIsTruncated(title);
27
+ * <ToolTip label={title} isDisabled={!isTruncated}>
28
+ * <Text ref={ref} noOfLines={1}>{title}</Text>
29
+ * </ToolTip>
30
+ */
31
+ export declare function useIsTruncated<T extends HTMLElement = HTMLElement>(content?: unknown, enabled?: boolean): {
32
+ ref: React.MutableRefObject<T | null>;
33
+ isTruncated: boolean;
34
+ };
35
+ export default useIsTruncated;
36
+ //# sourceMappingURL=useIsTruncated.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"useIsTruncated.d.ts","sourceRoot":"","sources":["../../src/Hooks/useIsTruncated.ts"],"names":[],"mappings":"AAEA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA6BG;AACH,wBAAgB,cAAc,CAAC,CAAC,SAAS,WAAW,GAAG,WAAW,EAChE,OAAO,CAAC,EAAE,OAAO,EACjB,OAAO,GAAE,OAAc,GACtB;IAAE,GAAG,EAAE,KAAK,CAAC,gBAAgB,CAAC,CAAC,GAAG,IAAI,CAAC,CAAC;IAAC,WAAW,EAAE,OAAO,CAAA;CAAE,CAuBjE;AAED,eAAe,cAAc,CAAC"}