@gnome-ui/react 1.43.0 → 1.45.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/README.md +8 -1
- package/dist/components/Badge/Badge.module.css.cjs +1 -1
- package/dist/components/Badge/Badge.module.css.cjs.map +1 -1
- package/dist/components/Badge/Badge.module.css.js +9 -9
- package/dist/components/Badge/Badge.module.css.js.map +1 -1
- package/dist/components/ContributionGraph/ContributionGraph.cjs +1 -1
- package/dist/components/ContributionGraph/ContributionGraph.cjs.map +1 -1
- package/dist/components/ContributionGraph/ContributionGraph.d.ts +11 -6
- package/dist/components/ContributionGraph/ContributionGraph.js +211 -130
- package/dist/components/ContributionGraph/ContributionGraph.js.map +1 -1
- package/dist/components/ContributionGraph/ContributionGraph.module.css.cjs +1 -1
- package/dist/components/ContributionGraph/ContributionGraph.module.css.cjs.map +1 -1
- package/dist/components/ContributionGraph/ContributionGraph.module.css.js +9 -8
- package/dist/components/ContributionGraph/ContributionGraph.module.css.js.map +1 -1
- package/dist/components/ContributionGraph/index.d.ts +1 -1
- package/dist/components/Drawer/Drawer.cjs +2 -0
- package/dist/components/Drawer/Drawer.cjs.map +1 -0
- package/dist/components/Drawer/Drawer.d.ts +28 -0
- package/dist/components/Drawer/Drawer.js +66 -0
- package/dist/components/Drawer/Drawer.js.map +1 -0
- package/dist/components/Drawer/Drawer.module.css.cjs +2 -0
- package/dist/components/Drawer/Drawer.module.css.cjs.map +1 -0
- package/dist/components/Drawer/Drawer.module.css.js +19 -0
- package/dist/components/Drawer/Drawer.module.css.js.map +1 -0
- package/dist/components/Drawer/index.d.ts +2 -0
- package/dist/components/Drawer.cjs +1 -0
- package/dist/components/Drawer.d.ts +2 -0
- package/dist/components/Drawer.js +2 -0
- package/dist/components/SegmentedBar/SegmentedBar.cjs +2 -0
- package/dist/components/SegmentedBar/SegmentedBar.cjs.map +1 -0
- package/dist/components/SegmentedBar/SegmentedBar.d.ts +42 -0
- package/dist/components/SegmentedBar/SegmentedBar.js +40 -0
- package/dist/components/SegmentedBar/SegmentedBar.js.map +1 -0
- package/dist/components/SegmentedBar/SegmentedBar.module.css.cjs +2 -0
- package/dist/components/SegmentedBar/SegmentedBar.module.css.cjs.map +1 -0
- package/dist/components/SegmentedBar/SegmentedBar.module.css.js +18 -0
- package/dist/components/SegmentedBar/SegmentedBar.module.css.js.map +1 -0
- package/dist/components/SegmentedBar/index.d.ts +2 -0
- package/dist/components/SegmentedBar.cjs +1 -0
- package/dist/components/SegmentedBar.d.ts +2 -0
- package/dist/components/SegmentedBar.js +2 -0
- package/dist/components/StatusBadge/StatusBadge.module.css.cjs +1 -1
- package/dist/components/StatusBadge/StatusBadge.module.css.cjs.map +1 -1
- package/dist/components/StatusBadge/StatusBadge.module.css.js +7 -7
- package/dist/components/StatusBadge/StatusBadge.module.css.js.map +1 -1
- package/dist/components/Tabs/TabItem.cjs +1 -1
- package/dist/components/Tabs/TabItem.cjs.map +1 -1
- package/dist/components/Tabs/TabItem.d.ts +3 -1
- package/dist/components/Tabs/TabItem.js +34 -32
- package/dist/components/Tabs/TabItem.js.map +1 -1
- package/dist/components/Tabs/Tabs.module.css.cjs +1 -1
- package/dist/components/Tabs/Tabs.module.css.cjs.map +1 -1
- package/dist/components/Tabs/Tabs.module.css.js +10 -9
- package/dist/components/Tabs/Tabs.module.css.js.map +1 -1
- package/dist/index.cjs +1 -1
- package/dist/index.d.ts +5 -1
- package/dist/index.js +65 -63
- package/dist/style.css +1 -1
- package/package.json +11 -1
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import { HTMLAttributes, ReactNode } from 'react';
|
|
2
|
+
export type DrawerSide = "left" | "right";
|
|
3
|
+
export type DrawerSize = "classic" | "wide";
|
|
4
|
+
export interface DrawerProps extends Omit<HTMLAttributes<HTMLDivElement>, "content" | "title"> {
|
|
5
|
+
/** Whether the drawer is visible. */
|
|
6
|
+
open: boolean;
|
|
7
|
+
/** Edge that the drawer slides in from. Defaults to `"right"`. */
|
|
8
|
+
side?: DrawerSide;
|
|
9
|
+
/** Preset drawer width. Defaults to `"classic"`. */
|
|
10
|
+
size?: DrawerSize;
|
|
11
|
+
/** Optional drawer heading. */
|
|
12
|
+
title?: ReactNode;
|
|
13
|
+
/** Drawer content when a prop is preferred over `children`. */
|
|
14
|
+
content?: ReactNode;
|
|
15
|
+
/** Drawer content. Used when `content` is not provided. */
|
|
16
|
+
children?: ReactNode;
|
|
17
|
+
/** Called when the user dismisses the drawer with Escape or the backdrop. */
|
|
18
|
+
onClose?: () => void;
|
|
19
|
+
/** Whether clicking the backdrop closes the drawer. Defaults to `true`. */
|
|
20
|
+
closeOnBackdrop?: boolean;
|
|
21
|
+
}
|
|
22
|
+
/**
|
|
23
|
+
* Slide-over panel for supplementary content.
|
|
24
|
+
*
|
|
25
|
+
* The drawer is controlled through `open`, renders into `document.body`, and
|
|
26
|
+
* accepts its body as either `content` or `children`.
|
|
27
|
+
*/
|
|
28
|
+
export declare function Drawer({ open, side, size, title, content, children, onClose, closeOnBackdrop, className, ...props }: DrawerProps): import("react/jsx-runtime").JSX.Element | null;
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
import { FOCUSABLE as e, trapFocus as t, useVisualViewport as n } from "../Dialog/dialogUtils.js";
|
|
2
|
+
import { Button as r } from "../Button/Button.js";
|
|
3
|
+
import i from "./Drawer.module.css.js";
|
|
4
|
+
import { useCallback as a, useEffect as o, useId as s, useRef as c } from "react";
|
|
5
|
+
import { createPortal as l } from "react-dom";
|
|
6
|
+
import { jsx as u, jsxs as d } from "react/jsx-runtime";
|
|
7
|
+
//#region src/components/Drawer/Drawer.tsx
|
|
8
|
+
function f({ open: f, side: p = "right", size: m = "classic", title: h, content: g, children: _, onClose: v, closeOnBackdrop: y = !0, className: b, ...x }) {
|
|
9
|
+
let S = c(null), C = s(), w = c(null), T = n(), E = g === void 0 ? _ : g;
|
|
10
|
+
o(() => {
|
|
11
|
+
f ? (w.current = document.activeElement, S.current?.querySelector(e)?.focus()) : w.current?.focus();
|
|
12
|
+
}, [f]);
|
|
13
|
+
let D = a((e) => {
|
|
14
|
+
if (e.key === "Escape") {
|
|
15
|
+
e.preventDefault(), v?.();
|
|
16
|
+
return;
|
|
17
|
+
}
|
|
18
|
+
t(e, S);
|
|
19
|
+
}, [v]);
|
|
20
|
+
if (!f) return null;
|
|
21
|
+
let O = /* @__PURE__ */ u("div", {
|
|
22
|
+
className: i.backdrop,
|
|
23
|
+
style: T,
|
|
24
|
+
onClick: y ? v : void 0,
|
|
25
|
+
children: /* @__PURE__ */ d("div", {
|
|
26
|
+
ref: S,
|
|
27
|
+
role: "dialog",
|
|
28
|
+
"aria-modal": "true",
|
|
29
|
+
"aria-labelledby": h ? C : void 0,
|
|
30
|
+
"data-side": p,
|
|
31
|
+
"data-size": m,
|
|
32
|
+
className: [
|
|
33
|
+
i.drawer,
|
|
34
|
+
p === "left" ? i.left : i.right,
|
|
35
|
+
m === "wide" ? i.wide : i.classic,
|
|
36
|
+
b
|
|
37
|
+
].filter(Boolean).join(" "),
|
|
38
|
+
onKeyDown: D,
|
|
39
|
+
onClick: (e) => e.stopPropagation(),
|
|
40
|
+
...x,
|
|
41
|
+
children: [h && /* @__PURE__ */ d("div", {
|
|
42
|
+
id: C,
|
|
43
|
+
className: i.title,
|
|
44
|
+
children: [/* @__PURE__ */ u("span", {
|
|
45
|
+
className: i.titleText,
|
|
46
|
+
children: h
|
|
47
|
+
}), v && /* @__PURE__ */ u(r, {
|
|
48
|
+
variant: "flat",
|
|
49
|
+
shape: "circular",
|
|
50
|
+
size: "sm",
|
|
51
|
+
"aria-label": "Close",
|
|
52
|
+
onClick: v,
|
|
53
|
+
children: "✕"
|
|
54
|
+
})]
|
|
55
|
+
}), E !== void 0 && /* @__PURE__ */ u("div", {
|
|
56
|
+
className: i.content,
|
|
57
|
+
children: E
|
|
58
|
+
})]
|
|
59
|
+
})
|
|
60
|
+
});
|
|
61
|
+
return typeof document > "u" ? O : l(O, document.body);
|
|
62
|
+
}
|
|
63
|
+
//#endregion
|
|
64
|
+
export { f as Drawer };
|
|
65
|
+
|
|
66
|
+
//# sourceMappingURL=Drawer.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Drawer.js","names":[],"sources":["../../../src/components/Drawer/Drawer.tsx"],"sourcesContent":["import {\n useCallback,\n useEffect,\n useId,\n useRef,\n type HTMLAttributes,\n type KeyboardEvent,\n type ReactNode,\n} from \"react\";\nimport { createPortal } from \"react-dom\";\nimport { Button } from \"../Button/Button\";\nimport { FOCUSABLE, trapFocus, useVisualViewport } from \"../Dialog/dialogUtils\";\nimport styles from \"./Drawer.module.css\";\n\nexport type DrawerSide = \"left\" | \"right\";\nexport type DrawerSize = \"classic\" | \"wide\";\n\nexport interface DrawerProps extends Omit<HTMLAttributes<HTMLDivElement>, \"content\" | \"title\"> {\n /** Whether the drawer is visible. */\n open: boolean;\n /** Edge that the drawer slides in from. Defaults to `\"right\"`. */\n side?: DrawerSide;\n /** Preset drawer width. Defaults to `\"classic\"`. */\n size?: DrawerSize;\n /** Optional drawer heading. */\n title?: ReactNode;\n /** Drawer content when a prop is preferred over `children`. */\n content?: ReactNode;\n /** Drawer content. Used when `content` is not provided. */\n children?: ReactNode;\n /** Called when the user dismisses the drawer with Escape or the backdrop. */\n onClose?: () => void;\n /** Whether clicking the backdrop closes the drawer. Defaults to `true`. */\n closeOnBackdrop?: boolean;\n}\n\n/**\n * Slide-over panel for supplementary content.\n *\n * The drawer is controlled through `open`, renders into `document.body`, and\n * accepts its body as either `content` or `children`.\n */\nexport function Drawer({\n open,\n side = \"right\",\n size = \"classic\",\n title,\n content,\n children,\n onClose,\n closeOnBackdrop = true,\n className,\n ...props\n}: DrawerProps) {\n const drawerRef = useRef<HTMLDivElement>(null);\n const titleId = useId();\n const previouslyFocused = useRef<Element | null>(null);\n const viewportStyle = useVisualViewport();\n const body = content !== undefined ? content : children;\n\n useEffect(() => {\n if (open) {\n previouslyFocused.current = document.activeElement;\n drawerRef.current?.querySelector<HTMLElement>(FOCUSABLE)?.focus();\n } else {\n (previouslyFocused.current as HTMLElement | null)?.focus();\n }\n }, [open]);\n\n const handleKeyDown = useCallback(\n (event: KeyboardEvent<HTMLDivElement>) => {\n if (event.key === \"Escape\") {\n event.preventDefault();\n onClose?.();\n return;\n }\n\n trapFocus(event, drawerRef);\n },\n [onClose],\n );\n\n if (!open) return null;\n\n const node = (\n <div\n className={styles.backdrop}\n style={viewportStyle}\n onClick={closeOnBackdrop ? onClose : undefined}\n >\n <div\n ref={drawerRef}\n role=\"dialog\"\n aria-modal=\"true\"\n aria-labelledby={title ? titleId : undefined}\n data-side={side}\n data-size={size}\n className={[\n styles.drawer,\n side === \"left\" ? styles.left : styles.right,\n size === \"wide\" ? styles.wide : styles.classic,\n className,\n ]\n .filter(Boolean)\n .join(\" \")}\n onKeyDown={handleKeyDown}\n onClick={(event) => event.stopPropagation()}\n {...props}\n >\n {title && (\n <div id={titleId} className={styles.title}>\n <span className={styles.titleText}>{title}</span>\n {onClose && (\n <Button\n variant=\"flat\"\n shape=\"circular\"\n size=\"sm\"\n aria-label=\"Close\"\n onClick={onClose}\n >\n ✕\n </Button>\n )}\n </div>\n )}\n {body !== undefined && <div className={styles.content}>{body}</div>}\n </div>\n </div>\n );\n\n if (typeof document === \"undefined\") return node;\n return createPortal(node, document.body);\n}\n"],"mappings":";;;;;;;AA0CA,SAAgB,EAAO,EACrB,SACA,UAAO,SACP,UAAO,WACP,UACA,YACA,aACA,YACA,qBAAkB,IAClB,cACA,GAAG,KACW;CACd,IAAM,IAAY,EAAuB,KAAK,EACxC,IAAU,GAAO,EACjB,IAAoB,EAAuB,KAAK,EAChD,IAAgB,GAAmB,EACnC,IAAO,MAAY,KAAA,IAAsB,IAAV;AAErC,SAAgB;AACd,EAAI,KACF,EAAkB,UAAU,SAAS,eACrC,EAAU,SAAS,cAA2B,EAAU,EAAE,OAAO,IAEhE,EAAkB,SAAgC,OAAO;IAE3D,CAAC,EAAK,CAAC;CAEV,IAAM,IAAgB,GACnB,MAAyC;AACxC,MAAI,EAAM,QAAQ,UAAU;AAE1B,GADA,EAAM,gBAAgB,EACtB,KAAW;AACX;;AAGF,IAAU,GAAO,EAAU;IAE7B,CAAC,EAAQ,CACV;AAED,KAAI,CAAC,EAAM,QAAO;CAElB,IAAM,IACJ,kBAAC,OAAD;EACE,WAAW,EAAO;EAClB,OAAO;EACP,SAAS,IAAkB,IAAU,KAAA;YAErC,kBAAC,OAAD;GACE,KAAK;GACL,MAAK;GACL,cAAW;GACX,mBAAiB,IAAQ,IAAU,KAAA;GACnC,aAAW;GACX,aAAW;GACX,WAAW;IACT,EAAO;IACP,MAAS,SAAS,EAAO,OAAO,EAAO;IACvC,MAAS,SAAS,EAAO,OAAO,EAAO;IACvC;IACD,CACE,OAAO,QAAQ,CACf,KAAK,IAAI;GACZ,WAAW;GACX,UAAU,MAAU,EAAM,iBAAiB;GAC3C,GAAI;aAjBN,CAmBG,KACC,kBAAC,OAAD;IAAK,IAAI;IAAS,WAAW,EAAO;cAApC,CACE,kBAAC,QAAD;KAAM,WAAW,EAAO;eAAY;KAAa,CAAA,EAChD,KACC,kBAAC,GAAD;KACE,SAAQ;KACR,OAAM;KACN,MAAK;KACL,cAAW;KACX,SAAS;eACV;KAEQ,CAAA,CAEP;OAEP,MAAS,KAAA,KAAa,kBAAC,OAAD;IAAK,WAAW,EAAO;cAAU;IAAW,CAAA,CAC/D;;EACF,CAAA;AAIR,QADI,OAAO,WAAa,MAAoB,IACrC,EAAa,GAAM,SAAS,KAAK"}
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
var e=`_backdrop_om06g_3`,t=`_drawer_om06g_24`,n=`_classic_om06g_36`,r=`_wide_om06g_40`,i=`_left_om06g_44`,a=`_right_om06g_53`,o=`_title_om06g_72`,s=`_titleText_om06g_80`,c=`_content_om06g_90`,l={backdrop:e,"backdrop-in":`_backdrop-in_om06g_1`,drawer:t,classic:n,wide:r,left:i,"drawer-in-left":`_drawer-in-left_om06g_1`,right:a,"drawer-in-right":`_drawer-in-right_om06g_1`,title:o,titleText:s,content:c};exports.default=l;
|
|
2
|
+
//# sourceMappingURL=Drawer.module.css.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Drawer.module.css.cjs","names":[],"sources":["../../../src/components/Drawer/Drawer.module.css"],"sourcesContent":["/* ─── Backdrop ─────────────────────────────────────────────────────────────── */\n\n.backdrop {\n position: fixed;\n inset: 0;\n z-index: 10000;\n\n display: flex;\n\n background-color: rgba(0, 0, 0, 0.5);\n backdrop-filter: blur(4px);\n -webkit-backdrop-filter: blur(4px);\n\n animation: backdrop-in var(--gnome-duration-normal, 200ms) var(--gnome-easing-default, ease) both;\n}\n\n@keyframes backdrop-in {\n from { opacity: 0; }\n to { opacity: 1; }\n}\n\n/* ─── Drawer ──────────────────────────────────────────────────────────────── */\n\n.drawer {\n display: flex;\n flex-direction: column;\n width: min(var(--gnome-drawer-width, var(--gnome-drawer-preset-width, 420px)), 100vw);\n height: 100dvh;\n min-width: 0;\n overflow: hidden;\n\n background-color: var(--gnome-dialog-bg-color, var(--gnome-window-bg-color, #fafafa));\n color: var(--gnome-window-fg-color, rgba(0, 0, 0, 0.8));\n}\n\n.classic {\n --gnome-drawer-preset-width: 420px;\n}\n\n.wide {\n --gnome-drawer-preset-width: 640px;\n}\n\n.left {\n margin-right: auto;\n border-radius: 0 var(--gnome-radius-xl, 16px) var(--gnome-radius-xl, 16px) 0;\n box-shadow:\n 4px 0 24px rgba(0, 0, 0, 0.18),\n 0 0 0 1px rgba(0, 0, 0, 0.06);\n animation: drawer-in-left var(--gnome-duration-normal, 200ms) var(--gnome-easing-default, ease) both;\n}\n\n.right {\n margin-left: auto;\n border-radius: var(--gnome-radius-xl, 16px) 0 0 var(--gnome-radius-xl, 16px);\n box-shadow:\n -4px 0 24px rgba(0, 0, 0, 0.18),\n 0 0 0 1px rgba(0, 0, 0, 0.06);\n animation: drawer-in-right var(--gnome-duration-normal, 200ms) var(--gnome-easing-default, ease) both;\n}\n\n@keyframes drawer-in-left {\n from { transform: translateX(-100%); }\n to { transform: translateX(0); }\n}\n\n@keyframes drawer-in-right {\n from { transform: translateX(100%); }\n to { transform: translateX(0); }\n}\n\n.title {\n flex-shrink: 0;\n display: flex;\n align-items: center;\n gap: var(--gnome-space-2, 12px);\n padding: var(--gnome-space-4, 24px) var(--gnome-space-4, 24px) var(--gnome-space-2, 12px);\n}\n\n.titleText {\n flex: 1;\n min-width: 0;\n\n font-family: var(--gnome-font-family);\n font-size: var(--gnome-font-size-title-4, 1.125rem);\n font-weight: var(--gnome-font-weight-bold, 700);\n line-height: var(--gnome-line-height-title, 1.3);\n}\n\n.content {\n flex: 1;\n min-height: 0;\n overflow: auto;\n padding: var(--gnome-space-4, 24px);\n}\n\n.title + .content {\n padding-top: 0;\n}\n\n/* ─── Dark mode ────────────────────────────────────────────────────────────── */\n\n@media (prefers-color-scheme: dark) {\n .backdrop {\n background-color: rgba(0, 0, 0, 0.65);\n }\n\n .drawer {\n background-color: var(--gnome-dialog-bg-color, var(--gnome-window-bg-color, #242424));\n }\n\n\n .left {\n box-shadow:\n 4px 0 24px rgba(0, 0, 0, 0.45),\n 0 0 0 1px rgba(255, 255, 255, 0.06);\n }\n\n .right {\n box-shadow:\n -4px 0 24px rgba(0, 0, 0, 0.45),\n 0 0 0 1px rgba(255, 255, 255, 0.06);\n }\n}\n\n/* ─── Reduced motion ──────────────────────────────────────────────────────── */\n\n@media (prefers-reduced-motion: reduce) {\n .backdrop,\n .left,\n .right {\n animation: none;\n }\n}\n"],"mappings":""}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
//#region src/components/Drawer/Drawer.module.css
|
|
2
|
+
var e = "_backdrop_om06g_3", t = "_drawer_om06g_24", n = "_classic_om06g_36", r = "_wide_om06g_40", i = "_left_om06g_44", a = "_right_om06g_53", o = "_title_om06g_72", s = "_titleText_om06g_80", c = "_content_om06g_90", l = {
|
|
3
|
+
backdrop: e,
|
|
4
|
+
"backdrop-in": "_backdrop-in_om06g_1",
|
|
5
|
+
drawer: t,
|
|
6
|
+
classic: n,
|
|
7
|
+
wide: r,
|
|
8
|
+
left: i,
|
|
9
|
+
"drawer-in-left": "_drawer-in-left_om06g_1",
|
|
10
|
+
right: a,
|
|
11
|
+
"drawer-in-right": "_drawer-in-right_om06g_1",
|
|
12
|
+
title: o,
|
|
13
|
+
titleText: s,
|
|
14
|
+
content: c
|
|
15
|
+
};
|
|
16
|
+
//#endregion
|
|
17
|
+
export { l as default };
|
|
18
|
+
|
|
19
|
+
//# sourceMappingURL=Drawer.module.css.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Drawer.module.css.js","names":[],"sources":["../../../src/components/Drawer/Drawer.module.css"],"sourcesContent":["/* ─── Backdrop ─────────────────────────────────────────────────────────────── */\n\n.backdrop {\n position: fixed;\n inset: 0;\n z-index: 10000;\n\n display: flex;\n\n background-color: rgba(0, 0, 0, 0.5);\n backdrop-filter: blur(4px);\n -webkit-backdrop-filter: blur(4px);\n\n animation: backdrop-in var(--gnome-duration-normal, 200ms) var(--gnome-easing-default, ease) both;\n}\n\n@keyframes backdrop-in {\n from { opacity: 0; }\n to { opacity: 1; }\n}\n\n/* ─── Drawer ──────────────────────────────────────────────────────────────── */\n\n.drawer {\n display: flex;\n flex-direction: column;\n width: min(var(--gnome-drawer-width, var(--gnome-drawer-preset-width, 420px)), 100vw);\n height: 100dvh;\n min-width: 0;\n overflow: hidden;\n\n background-color: var(--gnome-dialog-bg-color, var(--gnome-window-bg-color, #fafafa));\n color: var(--gnome-window-fg-color, rgba(0, 0, 0, 0.8));\n}\n\n.classic {\n --gnome-drawer-preset-width: 420px;\n}\n\n.wide {\n --gnome-drawer-preset-width: 640px;\n}\n\n.left {\n margin-right: auto;\n border-radius: 0 var(--gnome-radius-xl, 16px) var(--gnome-radius-xl, 16px) 0;\n box-shadow:\n 4px 0 24px rgba(0, 0, 0, 0.18),\n 0 0 0 1px rgba(0, 0, 0, 0.06);\n animation: drawer-in-left var(--gnome-duration-normal, 200ms) var(--gnome-easing-default, ease) both;\n}\n\n.right {\n margin-left: auto;\n border-radius: var(--gnome-radius-xl, 16px) 0 0 var(--gnome-radius-xl, 16px);\n box-shadow:\n -4px 0 24px rgba(0, 0, 0, 0.18),\n 0 0 0 1px rgba(0, 0, 0, 0.06);\n animation: drawer-in-right var(--gnome-duration-normal, 200ms) var(--gnome-easing-default, ease) both;\n}\n\n@keyframes drawer-in-left {\n from { transform: translateX(-100%); }\n to { transform: translateX(0); }\n}\n\n@keyframes drawer-in-right {\n from { transform: translateX(100%); }\n to { transform: translateX(0); }\n}\n\n.title {\n flex-shrink: 0;\n display: flex;\n align-items: center;\n gap: var(--gnome-space-2, 12px);\n padding: var(--gnome-space-4, 24px) var(--gnome-space-4, 24px) var(--gnome-space-2, 12px);\n}\n\n.titleText {\n flex: 1;\n min-width: 0;\n\n font-family: var(--gnome-font-family);\n font-size: var(--gnome-font-size-title-4, 1.125rem);\n font-weight: var(--gnome-font-weight-bold, 700);\n line-height: var(--gnome-line-height-title, 1.3);\n}\n\n.content {\n flex: 1;\n min-height: 0;\n overflow: auto;\n padding: var(--gnome-space-4, 24px);\n}\n\n.title + .content {\n padding-top: 0;\n}\n\n/* ─── Dark mode ────────────────────────────────────────────────────────────── */\n\n@media (prefers-color-scheme: dark) {\n .backdrop {\n background-color: rgba(0, 0, 0, 0.65);\n }\n\n .drawer {\n background-color: var(--gnome-dialog-bg-color, var(--gnome-window-bg-color, #242424));\n }\n\n\n .left {\n box-shadow:\n 4px 0 24px rgba(0, 0, 0, 0.45),\n 0 0 0 1px rgba(255, 255, 255, 0.06);\n }\n\n .right {\n box-shadow:\n -4px 0 24px rgba(0, 0, 0, 0.45),\n 0 0 0 1px rgba(255, 255, 255, 0.06);\n }\n}\n\n/* ─── Reduced motion ──────────────────────────────────────────────────────── */\n\n@media (prefers-reduced-motion: reduce) {\n .backdrop,\n .left,\n .right {\n animation: none;\n }\n}\n"],"mappings":""}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`});const e=require(`./Drawer/Drawer.cjs`);exports.Drawer=e.Drawer;
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
const e=require(`../Tooltip/Tooltip.cjs`),t=require(`./SegmentedBar.module.css.cjs`);let n=require(`react`),r=require(`react/jsx-runtime`);var i=8,a=(0,n.memo)(function({values:a,className:o,"aria-label":s,...c}){let[l,u]=(0,n.useState)(null),d=a.reduce((e,t)=>e+t.value,0)||100,f=a.map(e=>`${e.label} ${e.value}%`).join(`, `);return(0,r.jsx)(`div`,{role:`img`,"aria-label":s??f,className:[t.default.track,o].filter(Boolean).join(` `),...c,children:a.map((n,a)=>{let o=`${n.value/d*100}%`,s=n.value%1==0?n.value:n.value.toFixed(1);return(0,r.jsx)(e.Tooltip,{label:`${n.label}: ${s}%`,placement:`top`,delay:200,children:(0,r.jsx)(`div`,{className:[t.default.segment,n.color?null:t.default[`color${a%i}`],l!==null&&l!==a?t.default.dimmed:null,l===a?t.default.highlighted:null].filter(Boolean).join(` `),style:{width:o,...n.color?{backgroundColor:n.color}:{}},onMouseEnter:()=>u(a),onMouseLeave:()=>u(null)})},n.label)})})});exports.SegmentedBar=a;
|
|
2
|
+
//# sourceMappingURL=SegmentedBar.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"SegmentedBar.cjs","names":[],"sources":["../../../src/components/SegmentedBar/SegmentedBar.tsx"],"sourcesContent":["import { useState, memo } from \"react\";\nimport type { HTMLAttributes } from \"react\";\nimport { Tooltip } from \"../Tooltip\";\nimport styles from \"./SegmentedBar.module.css\";\n\nexport interface SegmentedBarSegment {\n /** Category name shown in the tooltip. */\n label: string;\n /**\n * Percentage value 0–100.\n * The sum of all segments should equal 100.\n * If it does not, values are redistributed proportionally.\n */\n value: number;\n /**\n * CSS color string for this segment.\n * When omitted, a cycling palette of GNOME design tokens is used.\n */\n color?: string;\n}\n\nexport interface SegmentedBarProps extends HTMLAttributes<HTMLDivElement> {\n /** Segments to display. Each segment contributes its share of the full bar width. */\n values: SegmentedBarSegment[];\n /**\n * Accessible label for the bar as a whole.\n * Auto-generated from `values` when omitted (e.g. \"TypeScript 45%, JavaScript 30%\").\n */\n \"aria-label\"?: string;\n}\n\nconst COLOR_COUNT = 8;\n\n/**\n * Horizontal bar split into proportional segments, one per category.\n *\n * Hover a segment to highlight it and see its tooltip with label and percentage.\n * Typical use case: repository language distribution.\n *\n * ```tsx\n * <SegmentedBar\n * values={[\n * { label: \"TypeScript\", value: 60, color: \"#3178c6\" },\n * { label: \"JavaScript\", value: 30, color: \"#f7df1e\" },\n * { label: \"CSS\", value: 10, color: \"#563d7c\" },\n * ]}\n * />\n * ```\n */\nexport const SegmentedBar = memo(function SegmentedBar({\n values,\n className,\n \"aria-label\": ariaLabel,\n ...props\n}: SegmentedBarProps) {\n const [activeIndex, setActiveIndex] = useState<number | null>(null);\n\n const total = values.reduce((sum, s) => sum + s.value, 0) || 100;\n\n const defaultLabel = values.map((s) => `${s.label} ${s.value}%`).join(\", \");\n\n return (\n <div\n role=\"img\"\n aria-label={ariaLabel ?? defaultLabel}\n className={[styles.track, className].filter(Boolean).join(\" \")}\n {...props}\n >\n {values.map((segment, i) => {\n const width = `${(segment.value / total) * 100}%`;\n const pct = segment.value % 1 === 0 ? segment.value : segment.value.toFixed(1);\n const tooltipLabel = `${segment.label}: ${pct}%`;\n\n return (\n <Tooltip key={segment.label} label={tooltipLabel} placement=\"top\" delay={200}>\n <div\n className={[\n styles.segment,\n !segment.color ? styles[`color${i % COLOR_COUNT}`] : null,\n activeIndex !== null && activeIndex !== i ? styles.dimmed : null,\n activeIndex === i ? styles.highlighted : null,\n ]\n .filter(Boolean)\n .join(\" \")}\n style={{\n width,\n ...(segment.color ? { backgroundColor: segment.color } : {}),\n }}\n onMouseEnter={() => setActiveIndex(i)}\n onMouseLeave={() => setActiveIndex(null)}\n />\n </Tooltip>\n );\n })}\n </div>\n );\n});\n"],"mappings":"2IA+BA,IAAM,EAAc,EAkBP,GAAA,EAAA,EAAA,MAAoB,SAAsB,CACrD,SACA,YACA,aAAc,EACd,GAAG,GACiB,CACpB,GAAM,CAAC,EAAa,IAAA,EAAA,EAAA,UAA0C,KAAK,CAE7D,EAAQ,EAAO,QAAQ,EAAK,IAAM,EAAM,EAAE,MAAO,EAAE,EAAI,IAEvD,EAAe,EAAO,IAAK,GAAM,GAAG,EAAE,MAAM,GAAG,EAAE,MAAM,GAAG,CAAC,KAAK,KAAK,CAE3E,OACE,EAAA,EAAA,KAAC,MAAD,CACE,KAAK,MACL,aAAY,GAAa,EACzB,UAAW,CAAC,EAAA,QAAO,MAAO,EAAU,CAAC,OAAO,QAAQ,CAAC,KAAK,IAAI,CAC9D,GAAI,WAEH,EAAO,KAAK,EAAS,IAAM,CAC1B,IAAM,EAAQ,GAAI,EAAQ,MAAQ,EAAS,IAAI,GACzC,EAAM,EAAQ,MAAQ,GAAM,EAAI,EAAQ,MAAQ,EAAQ,MAAM,QAAQ,EAAE,CAG9E,OACE,EAAA,EAAA,KAAC,EAAA,QAAD,CAA6B,MAHV,GAAG,EAAQ,MAAM,IAAI,EAAI,GAGM,UAAU,MAAM,MAAO,cACvE,EAAA,EAAA,KAAC,MAAD,CACE,UAAW,CACT,EAAA,QAAO,QACN,EAAQ,MAA4C,KAApC,EAAA,QAAO,QAAQ,EAAI,KACpC,IAAgB,MAAQ,IAAgB,EAAI,EAAA,QAAO,OAAS,KAC5D,IAAgB,EAAI,EAAA,QAAO,YAAc,KAC1C,CACE,OAAO,QAAQ,CACf,KAAK,IAAI,CACZ,MAAO,CACL,QACA,GAAI,EAAQ,MAAQ,CAAE,gBAAiB,EAAQ,MAAO,CAAG,EAAE,CAC5D,CACD,iBAAoB,EAAe,EAAE,CACrC,iBAAoB,EAAe,KAAK,CACxC,CAAA,CACM,CAjBI,EAAQ,MAiBZ,EAEZ,CACE,CAAA,EAER"}
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import { HTMLAttributes } from 'react';
|
|
2
|
+
export interface SegmentedBarSegment {
|
|
3
|
+
/** Category name shown in the tooltip. */
|
|
4
|
+
label: string;
|
|
5
|
+
/**
|
|
6
|
+
* Percentage value 0–100.
|
|
7
|
+
* The sum of all segments should equal 100.
|
|
8
|
+
* If it does not, values are redistributed proportionally.
|
|
9
|
+
*/
|
|
10
|
+
value: number;
|
|
11
|
+
/**
|
|
12
|
+
* CSS color string for this segment.
|
|
13
|
+
* When omitted, a cycling palette of GNOME design tokens is used.
|
|
14
|
+
*/
|
|
15
|
+
color?: string;
|
|
16
|
+
}
|
|
17
|
+
export interface SegmentedBarProps extends HTMLAttributes<HTMLDivElement> {
|
|
18
|
+
/** Segments to display. Each segment contributes its share of the full bar width. */
|
|
19
|
+
values: SegmentedBarSegment[];
|
|
20
|
+
/**
|
|
21
|
+
* Accessible label for the bar as a whole.
|
|
22
|
+
* Auto-generated from `values` when omitted (e.g. "TypeScript 45%, JavaScript 30%").
|
|
23
|
+
*/
|
|
24
|
+
"aria-label"?: string;
|
|
25
|
+
}
|
|
26
|
+
/**
|
|
27
|
+
* Horizontal bar split into proportional segments, one per category.
|
|
28
|
+
*
|
|
29
|
+
* Hover a segment to highlight it and see its tooltip with label and percentage.
|
|
30
|
+
* Typical use case: repository language distribution.
|
|
31
|
+
*
|
|
32
|
+
* ```tsx
|
|
33
|
+
* <SegmentedBar
|
|
34
|
+
* values={[
|
|
35
|
+
* { label: "TypeScript", value: 60, color: "#3178c6" },
|
|
36
|
+
* { label: "JavaScript", value: 30, color: "#f7df1e" },
|
|
37
|
+
* { label: "CSS", value: 10, color: "#563d7c" },
|
|
38
|
+
* ]}
|
|
39
|
+
* />
|
|
40
|
+
* ```
|
|
41
|
+
*/
|
|
42
|
+
export declare const SegmentedBar: import('react').NamedExoticComponent<SegmentedBarProps>;
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import { Tooltip as e } from "../Tooltip/Tooltip.js";
|
|
2
|
+
import t from "./SegmentedBar.module.css.js";
|
|
3
|
+
import { memo as n, useState as r } from "react";
|
|
4
|
+
import { jsx as i } from "react/jsx-runtime";
|
|
5
|
+
//#region src/components/SegmentedBar/SegmentedBar.tsx
|
|
6
|
+
var a = 8, o = n(function({ values: n, className: o, "aria-label": s, ...c }) {
|
|
7
|
+
let [l, u] = r(null), d = n.reduce((e, t) => e + t.value, 0) || 100, f = n.map((e) => `${e.label} ${e.value}%`).join(", ");
|
|
8
|
+
return /* @__PURE__ */ i("div", {
|
|
9
|
+
role: "img",
|
|
10
|
+
"aria-label": s ?? f,
|
|
11
|
+
className: [t.track, o].filter(Boolean).join(" "),
|
|
12
|
+
...c,
|
|
13
|
+
children: n.map((n, r) => {
|
|
14
|
+
let o = `${n.value / d * 100}%`, s = n.value % 1 == 0 ? n.value : n.value.toFixed(1);
|
|
15
|
+
return /* @__PURE__ */ i(e, {
|
|
16
|
+
label: `${n.label}: ${s}%`,
|
|
17
|
+
placement: "top",
|
|
18
|
+
delay: 200,
|
|
19
|
+
children: /* @__PURE__ */ i("div", {
|
|
20
|
+
className: [
|
|
21
|
+
t.segment,
|
|
22
|
+
n.color ? null : t[`color${r % a}`],
|
|
23
|
+
l !== null && l !== r ? t.dimmed : null,
|
|
24
|
+
l === r ? t.highlighted : null
|
|
25
|
+
].filter(Boolean).join(" "),
|
|
26
|
+
style: {
|
|
27
|
+
width: o,
|
|
28
|
+
...n.color ? { backgroundColor: n.color } : {}
|
|
29
|
+
},
|
|
30
|
+
onMouseEnter: () => u(r),
|
|
31
|
+
onMouseLeave: () => u(null)
|
|
32
|
+
})
|
|
33
|
+
}, n.label);
|
|
34
|
+
})
|
|
35
|
+
});
|
|
36
|
+
});
|
|
37
|
+
//#endregion
|
|
38
|
+
export { o as SegmentedBar };
|
|
39
|
+
|
|
40
|
+
//# sourceMappingURL=SegmentedBar.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"SegmentedBar.js","names":[],"sources":["../../../src/components/SegmentedBar/SegmentedBar.tsx"],"sourcesContent":["import { useState, memo } from \"react\";\nimport type { HTMLAttributes } from \"react\";\nimport { Tooltip } from \"../Tooltip\";\nimport styles from \"./SegmentedBar.module.css\";\n\nexport interface SegmentedBarSegment {\n /** Category name shown in the tooltip. */\n label: string;\n /**\n * Percentage value 0–100.\n * The sum of all segments should equal 100.\n * If it does not, values are redistributed proportionally.\n */\n value: number;\n /**\n * CSS color string for this segment.\n * When omitted, a cycling palette of GNOME design tokens is used.\n */\n color?: string;\n}\n\nexport interface SegmentedBarProps extends HTMLAttributes<HTMLDivElement> {\n /** Segments to display. Each segment contributes its share of the full bar width. */\n values: SegmentedBarSegment[];\n /**\n * Accessible label for the bar as a whole.\n * Auto-generated from `values` when omitted (e.g. \"TypeScript 45%, JavaScript 30%\").\n */\n \"aria-label\"?: string;\n}\n\nconst COLOR_COUNT = 8;\n\n/**\n * Horizontal bar split into proportional segments, one per category.\n *\n * Hover a segment to highlight it and see its tooltip with label and percentage.\n * Typical use case: repository language distribution.\n *\n * ```tsx\n * <SegmentedBar\n * values={[\n * { label: \"TypeScript\", value: 60, color: \"#3178c6\" },\n * { label: \"JavaScript\", value: 30, color: \"#f7df1e\" },\n * { label: \"CSS\", value: 10, color: \"#563d7c\" },\n * ]}\n * />\n * ```\n */\nexport const SegmentedBar = memo(function SegmentedBar({\n values,\n className,\n \"aria-label\": ariaLabel,\n ...props\n}: SegmentedBarProps) {\n const [activeIndex, setActiveIndex] = useState<number | null>(null);\n\n const total = values.reduce((sum, s) => sum + s.value, 0) || 100;\n\n const defaultLabel = values.map((s) => `${s.label} ${s.value}%`).join(\", \");\n\n return (\n <div\n role=\"img\"\n aria-label={ariaLabel ?? defaultLabel}\n className={[styles.track, className].filter(Boolean).join(\" \")}\n {...props}\n >\n {values.map((segment, i) => {\n const width = `${(segment.value / total) * 100}%`;\n const pct = segment.value % 1 === 0 ? segment.value : segment.value.toFixed(1);\n const tooltipLabel = `${segment.label}: ${pct}%`;\n\n return (\n <Tooltip key={segment.label} label={tooltipLabel} placement=\"top\" delay={200}>\n <div\n className={[\n styles.segment,\n !segment.color ? styles[`color${i % COLOR_COUNT}`] : null,\n activeIndex !== null && activeIndex !== i ? styles.dimmed : null,\n activeIndex === i ? styles.highlighted : null,\n ]\n .filter(Boolean)\n .join(\" \")}\n style={{\n width,\n ...(segment.color ? { backgroundColor: segment.color } : {}),\n }}\n onMouseEnter={() => setActiveIndex(i)}\n onMouseLeave={() => setActiveIndex(null)}\n />\n </Tooltip>\n );\n })}\n </div>\n );\n});\n"],"mappings":";;;;;AA+BA,IAAM,IAAc,GAkBP,IAAe,EAAK,SAAsB,EACrD,WACA,cACA,cAAc,GACd,GAAG,KACiB;CACpB,IAAM,CAAC,GAAa,KAAkB,EAAwB,KAAK,EAE7D,IAAQ,EAAO,QAAQ,GAAK,MAAM,IAAM,EAAE,OAAO,EAAE,IAAI,KAEvD,IAAe,EAAO,KAAK,MAAM,GAAG,EAAE,MAAM,GAAG,EAAE,MAAM,GAAG,CAAC,KAAK,KAAK;AAE3E,QACE,kBAAC,OAAD;EACE,MAAK;EACL,cAAY,KAAa;EACzB,WAAW,CAAC,EAAO,OAAO,EAAU,CAAC,OAAO,QAAQ,CAAC,KAAK,IAAI;EAC9D,GAAI;YAEH,EAAO,KAAK,GAAS,MAAM;GAC1B,IAAM,IAAQ,GAAI,EAAQ,QAAQ,IAAS,IAAI,IACzC,IAAM,EAAQ,QAAQ,KAAM,IAAI,EAAQ,QAAQ,EAAQ,MAAM,QAAQ,EAAE;AAG9E,UACE,kBAAC,GAAD;IAA6B,OAHV,GAAG,EAAQ,MAAM,IAAI,EAAI;IAGM,WAAU;IAAM,OAAO;cACvE,kBAAC,OAAD;KACE,WAAW;MACT,EAAO;MACN,EAAQ,QAA4C,OAApC,EAAO,QAAQ,IAAI;MACpC,MAAgB,QAAQ,MAAgB,IAAI,EAAO,SAAS;MAC5D,MAAgB,IAAI,EAAO,cAAc;MAC1C,CACE,OAAO,QAAQ,CACf,KAAK,IAAI;KACZ,OAAO;MACL;MACA,GAAI,EAAQ,QAAQ,EAAE,iBAAiB,EAAQ,OAAO,GAAG,EAAE;MAC5D;KACD,oBAAoB,EAAe,EAAE;KACrC,oBAAoB,EAAe,KAAK;KACxC,CAAA;IACM,EAjBI,EAAQ,MAiBZ;IAEZ;EACE,CAAA;EAER"}
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
var e={track:`_track_1ahtp_3`,segment:`_segment_1ahtp_16`,dimmed:`_dimmed_1ahtp_24`,highlighted:`_highlighted_1ahtp_25`,color0:`_color0_1ahtp_29`,color1:`_color1_1ahtp_30`,color2:`_color2_1ahtp_31`,color3:`_color3_1ahtp_32`,color4:`_color4_1ahtp_33`,color5:`_color5_1ahtp_34`,color6:`_color6_1ahtp_35`,color7:`_color7_1ahtp_36`};exports.default=e;
|
|
2
|
+
//# sourceMappingURL=SegmentedBar.module.css.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"SegmentedBar.module.css.cjs","names":[],"sources":["../../../src/components/SegmentedBar/SegmentedBar.module.css"],"sourcesContent":["/* ─── Track ─────────────────────────────────────────────────────────────────── */\n\n.track {\n display: flex;\n width: 100%;\n height: 8px;\n border-radius: var(--gnome-radius-pill);\n overflow: hidden;\n gap: 2px;\n /* Track color is visible in the 2 px gaps between segments */\n background-color: var(--gnome-light-3, #deddda);\n}\n\n/* ─── Segment ───────────────────────────────────────────────────────────────── */\n\n.segment {\n height: 100%;\n cursor: default;\n transition:\n opacity var(--gnome-duration-fast, 150ms) var(--gnome-easing-default, ease),\n filter var(--gnome-duration-fast, 150ms) var(--gnome-easing-default, ease);\n}\n\n.dimmed { opacity: 0.35; }\n.highlighted { filter: brightness(1.15); }\n\n/* ─── Default palette (GNOME tokens, cycling across color families) ─────────── */\n\n.color0 { background-color: var(--gnome-blue-3, #3584e4); }\n.color1 { background-color: var(--gnome-green-3, #33d17a); }\n.color2 { background-color: var(--gnome-purple-3, #9141ac); }\n.color3 { background-color: var(--gnome-orange-3, #ff7800); }\n.color4 { background-color: var(--gnome-red-3, #e01b24); }\n.color5 { background-color: var(--gnome-brown-3, #986a44); }\n.color6 { background-color: var(--gnome-blue-5, #1a5fb4); }\n.color7 { background-color: var(--gnome-green-5, #26a269); }\n\n/* ─── Dark mode ─────────────────────────────────────────────────────────────── */\n\n@media (prefers-color-scheme: dark) {\n .track {\n background-color: var(--gnome-dark-2, #5e5c64);\n }\n}\n\n/* ─── Reduced motion ────────────────────────────────────────────────────────── */\n\n@media (prefers-reduced-motion: reduce) {\n .segment {\n transition: none;\n }\n}\n"],"mappings":""}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
var e = {
|
|
2
|
+
track: "_track_1ahtp_3",
|
|
3
|
+
segment: "_segment_1ahtp_16",
|
|
4
|
+
dimmed: "_dimmed_1ahtp_24",
|
|
5
|
+
highlighted: "_highlighted_1ahtp_25",
|
|
6
|
+
color0: "_color0_1ahtp_29",
|
|
7
|
+
color1: "_color1_1ahtp_30",
|
|
8
|
+
color2: "_color2_1ahtp_31",
|
|
9
|
+
color3: "_color3_1ahtp_32",
|
|
10
|
+
color4: "_color4_1ahtp_33",
|
|
11
|
+
color5: "_color5_1ahtp_34",
|
|
12
|
+
color6: "_color6_1ahtp_35",
|
|
13
|
+
color7: "_color7_1ahtp_36"
|
|
14
|
+
};
|
|
15
|
+
//#endregion
|
|
16
|
+
export { e as default };
|
|
17
|
+
|
|
18
|
+
//# sourceMappingURL=SegmentedBar.module.css.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"SegmentedBar.module.css.js","names":[],"sources":["../../../src/components/SegmentedBar/SegmentedBar.module.css"],"sourcesContent":["/* ─── Track ─────────────────────────────────────────────────────────────────── */\n\n.track {\n display: flex;\n width: 100%;\n height: 8px;\n border-radius: var(--gnome-radius-pill);\n overflow: hidden;\n gap: 2px;\n /* Track color is visible in the 2 px gaps between segments */\n background-color: var(--gnome-light-3, #deddda);\n}\n\n/* ─── Segment ───────────────────────────────────────────────────────────────── */\n\n.segment {\n height: 100%;\n cursor: default;\n transition:\n opacity var(--gnome-duration-fast, 150ms) var(--gnome-easing-default, ease),\n filter var(--gnome-duration-fast, 150ms) var(--gnome-easing-default, ease);\n}\n\n.dimmed { opacity: 0.35; }\n.highlighted { filter: brightness(1.15); }\n\n/* ─── Default palette (GNOME tokens, cycling across color families) ─────────── */\n\n.color0 { background-color: var(--gnome-blue-3, #3584e4); }\n.color1 { background-color: var(--gnome-green-3, #33d17a); }\n.color2 { background-color: var(--gnome-purple-3, #9141ac); }\n.color3 { background-color: var(--gnome-orange-3, #ff7800); }\n.color4 { background-color: var(--gnome-red-3, #e01b24); }\n.color5 { background-color: var(--gnome-brown-3, #986a44); }\n.color6 { background-color: var(--gnome-blue-5, #1a5fb4); }\n.color7 { background-color: var(--gnome-green-5, #26a269); }\n\n/* ─── Dark mode ─────────────────────────────────────────────────────────────── */\n\n@media (prefers-color-scheme: dark) {\n .track {\n background-color: var(--gnome-dark-2, #5e5c64);\n }\n}\n\n/* ─── Reduced motion ────────────────────────────────────────────────────────── */\n\n@media (prefers-reduced-motion: reduce) {\n .segment {\n transition: none;\n }\n}\n"],"mappings":""}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`});const e=require(`./SegmentedBar/SegmentedBar.cjs`);exports.SegmentedBar=e.SegmentedBar;
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
var e={badge:`
|
|
1
|
+
var e={badge:`_badge_mc2uh_3`,success:`_success_mc2uh_19`,warning:`_warning_mc2uh_24`,error:`_error_mc2uh_29`,new:`_new_mc2uh_34`,accent:`_accent_mc2uh_39`,neutral:`_neutral_mc2uh_44`};exports.default=e;
|
|
2
2
|
//# sourceMappingURL=StatusBadge.module.css.cjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"StatusBadge.module.css.cjs","names":[],"sources":["../../../src/components/StatusBadge/StatusBadge.module.css"],"sourcesContent":["/* ─── Base ────────────────────────────────────────────────────────────────── */\n\n.badge {\n display: inline-flex;\n align-items: center;\n padding: 2px 8px;\n border-radius: var(--gnome-radius-pill, 9999px);\n font-family: var(--gnome-font-family);\n font-size: 0.6875rem;\n font-weight: 600;\n line-height: 1.4;\n white-space: nowrap;\n letter-spacing: 0.02em;\n}\n\n/* ─── Variants ────────────────────────────────────────────────────────────── */\n\n.success {\n background-color: var(--gnome-success-bg-color, #2ec27e);\n color: var(--gnome-success-fg-color, #ffffff);\n}\n\n.warning {\n background-color: var(--gnome-warning-bg-color, #f6d32d);\n color: var(--gnome-warning-fg-color, rgba(0, 0, 0, 0.8));\n}\n\n.error {\n background-color: var(--gnome-error-bg-color, #e01b24);\n color: var(--gnome-error-fg-color, #ffffff);\n}\n\n.new {\n background-color: var(--gnome-new-bg-color, #9141ac);\n color: var(--gnome-new-fg-color, #ffffff);\n}\n\n.accent {\n background-color: var(--gnome-accent-bg-color, #3584e4);\n color: var(--gnome-accent-fg-color, #ffffff);\n}\n\n.neutral {\n background-color: var(--gnome-hover-overlay, rgba(0, 0, 0, 0.08));\n color: var(--gnome-window-fg-color, rgba(0, 0, 0, 0.8));\n}\n"],"mappings":""}
|
|
1
|
+
{"version":3,"file":"StatusBadge.module.css.cjs","names":[],"sources":["../../../src/components/StatusBadge/StatusBadge.module.css"],"sourcesContent":["/* ─── Base ────────────────────────────────────────────────────────────────── */\n\n.badge {\n display: inline-flex;\n align-items: center;\n vertical-align: middle;\n padding: 2px 8px;\n border-radius: var(--gnome-radius-pill, 9999px);\n font-family: var(--gnome-font-family);\n font-size: 0.6875rem;\n font-weight: 600;\n line-height: 1.4;\n white-space: nowrap;\n letter-spacing: 0.02em;\n}\n\n/* ─── Variants ────────────────────────────────────────────────────────────── */\n\n.success {\n background-color: var(--gnome-success-bg-color, #2ec27e);\n color: var(--gnome-success-fg-color, #ffffff);\n}\n\n.warning {\n background-color: var(--gnome-warning-bg-color, #f6d32d);\n color: var(--gnome-warning-fg-color, rgba(0, 0, 0, 0.8));\n}\n\n.error {\n background-color: var(--gnome-error-bg-color, #e01b24);\n color: var(--gnome-error-fg-color, #ffffff);\n}\n\n.new {\n background-color: var(--gnome-new-bg-color, #9141ac);\n color: var(--gnome-new-fg-color, #ffffff);\n}\n\n.accent {\n background-color: var(--gnome-accent-bg-color, #3584e4);\n color: var(--gnome-accent-fg-color, #ffffff);\n}\n\n.neutral {\n background-color: var(--gnome-hover-overlay, rgba(0, 0, 0, 0.08));\n color: var(--gnome-window-fg-color, rgba(0, 0, 0, 0.8));\n}\n"],"mappings":""}
|
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
var e = {
|
|
2
|
-
badge: "
|
|
3
|
-
success: "
|
|
4
|
-
warning: "
|
|
5
|
-
error: "
|
|
6
|
-
new: "
|
|
7
|
-
accent: "
|
|
8
|
-
neutral: "
|
|
2
|
+
badge: "_badge_mc2uh_3",
|
|
3
|
+
success: "_success_mc2uh_19",
|
|
4
|
+
warning: "_warning_mc2uh_24",
|
|
5
|
+
error: "_error_mc2uh_29",
|
|
6
|
+
new: "_new_mc2uh_34",
|
|
7
|
+
accent: "_accent_mc2uh_39",
|
|
8
|
+
neutral: "_neutral_mc2uh_44"
|
|
9
9
|
};
|
|
10
10
|
//#endregion
|
|
11
11
|
export { e as default };
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"StatusBadge.module.css.js","names":[],"sources":["../../../src/components/StatusBadge/StatusBadge.module.css"],"sourcesContent":["/* ─── Base ────────────────────────────────────────────────────────────────── */\n\n.badge {\n display: inline-flex;\n align-items: center;\n padding: 2px 8px;\n border-radius: var(--gnome-radius-pill, 9999px);\n font-family: var(--gnome-font-family);\n font-size: 0.6875rem;\n font-weight: 600;\n line-height: 1.4;\n white-space: nowrap;\n letter-spacing: 0.02em;\n}\n\n/* ─── Variants ────────────────────────────────────────────────────────────── */\n\n.success {\n background-color: var(--gnome-success-bg-color, #2ec27e);\n color: var(--gnome-success-fg-color, #ffffff);\n}\n\n.warning {\n background-color: var(--gnome-warning-bg-color, #f6d32d);\n color: var(--gnome-warning-fg-color, rgba(0, 0, 0, 0.8));\n}\n\n.error {\n background-color: var(--gnome-error-bg-color, #e01b24);\n color: var(--gnome-error-fg-color, #ffffff);\n}\n\n.new {\n background-color: var(--gnome-new-bg-color, #9141ac);\n color: var(--gnome-new-fg-color, #ffffff);\n}\n\n.accent {\n background-color: var(--gnome-accent-bg-color, #3584e4);\n color: var(--gnome-accent-fg-color, #ffffff);\n}\n\n.neutral {\n background-color: var(--gnome-hover-overlay, rgba(0, 0, 0, 0.08));\n color: var(--gnome-window-fg-color, rgba(0, 0, 0, 0.8));\n}\n"],"mappings":""}
|
|
1
|
+
{"version":3,"file":"StatusBadge.module.css.js","names":[],"sources":["../../../src/components/StatusBadge/StatusBadge.module.css"],"sourcesContent":["/* ─── Base ────────────────────────────────────────────────────────────────── */\n\n.badge {\n display: inline-flex;\n align-items: center;\n vertical-align: middle;\n padding: 2px 8px;\n border-radius: var(--gnome-radius-pill, 9999px);\n font-family: var(--gnome-font-family);\n font-size: 0.6875rem;\n font-weight: 600;\n line-height: 1.4;\n white-space: nowrap;\n letter-spacing: 0.02em;\n}\n\n/* ─── Variants ────────────────────────────────────────────────────────────── */\n\n.success {\n background-color: var(--gnome-success-bg-color, #2ec27e);\n color: var(--gnome-success-fg-color, #ffffff);\n}\n\n.warning {\n background-color: var(--gnome-warning-bg-color, #f6d32d);\n color: var(--gnome-warning-fg-color, rgba(0, 0, 0, 0.8));\n}\n\n.error {\n background-color: var(--gnome-error-bg-color, #e01b24);\n color: var(--gnome-error-fg-color, #ffffff);\n}\n\n.new {\n background-color: var(--gnome-new-bg-color, #9141ac);\n color: var(--gnome-new-fg-color, #ffffff);\n}\n\n.accent {\n background-color: var(--gnome-accent-bg-color, #3584e4);\n color: var(--gnome-accent-fg-color, #ffffff);\n}\n\n.neutral {\n background-color: var(--gnome-hover-overlay, rgba(0, 0, 0, 0.08));\n color: var(--gnome-window-fg-color, rgba(0, 0, 0, 0.8));\n}\n"],"mappings":""}
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
const e=require(`../Icon/Icon.cjs`),
|
|
1
|
+
const e=require(`../Badge/Badge.cjs`),t=require(`../Icon/Icon.cjs`),n=require(`./Tabs.module.css.cjs`);let r=require(`react`),i=require(`react/jsx-runtime`);var a=(0,r.memo)(function({label:r,icon:a,active:o=!1,panelId:s,onClose:c,closeLabel:l=`Close tab`,count:u,className:d,disabled:f,...p}){return(0,i.jsxs)(`button`,{role:`tab`,type:`button`,"aria-selected":o,"aria-controls":s,tabIndex:o?0:-1,disabled:f,className:[n.default.tab,o?n.default.active:null,c?n.default.closeable:null,d].filter(Boolean).join(` `),...p,children:[a&&(0,i.jsx)(`span`,{className:n.default.tabIcon,children:(0,i.jsx)(t.Icon,{icon:a,size:`sm`,"aria-hidden":!0})}),(0,i.jsx)(`span`,{className:n.default.tabLabel,children:r}),u!==void 0&&(0,i.jsx)(e.Badge,{className:n.default.tabBadge,children:u>99?`99+`:u}),c&&(0,i.jsx)(`button`,{type:`button`,"aria-label":l,className:n.default.closeBtn,onClick:e=>{e.stopPropagation(),c()},children:`×`})]})});exports.TabItem=a;
|
|
2
2
|
//# sourceMappingURL=TabItem.cjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"TabItem.cjs","names":[],"sources":["../../../src/components/Tabs/TabItem.tsx"],"sourcesContent":["import type { ButtonHTMLAttributes, ReactNode } from \"react\";\nimport type { IconDefinition } from \"@gnome-ui/icons\";\nimport { Icon } from \"../Icon\";\nimport styles from \"./Tabs.module.css\";\n\nexport interface TabItemProps extends ButtonHTMLAttributes<HTMLButtonElement> {\n /** Tab label. */\n label: string;\n /** Optional icon from `@gnome-ui/icons`. */\n icon?: IconDefinition;\n /** Marks this tab as the currently selected one. */\n active?: boolean;\n /**\n * id of the `TabPanel` this tab controls.\n * Sets `aria-controls` automatically.\n */\n panelId?: string;\n /**\n * When provided, a close (×) button is rendered at the trailing edge.\n * Called when the user clicks the close button.\n */\n onClose?: () => void;\n /** Accessible label for the close button. Defaults to `\"Close tab\"`. */\n closeLabel?: string;\n children?: ReactNode;\n}\n\n/**\n * Individual tab button inside a `TabBar`.\n */\nexport function TabItem({\n label,\n icon,\n active = false,\n panelId,\n onClose,\n closeLabel = \"Close tab\",\n className,\n disabled,\n ...props\n}: TabItemProps) {\n return (\n <button\n role=\"tab\"\n type=\"button\"\n aria-selected={active}\n aria-controls={panelId}\n tabIndex={active ? 0 : -1}\n disabled={disabled}\n className={[\n styles.tab,\n active ? styles.active : null,\n onClose ? styles.closeable : null,\n className,\n ]\n .filter(Boolean)\n .join(\" \")}\n {...props}\n >\n {icon && (\n <span className={styles.tabIcon}>\n <Icon icon={icon} size=\"sm\" aria-hidden />\n </span>\n )}\n <span className={styles.tabLabel}>{label}</span>\n\n {onClose && (\n <
|
|
1
|
+
{"version":3,"file":"TabItem.cjs","names":[],"sources":["../../../src/components/Tabs/TabItem.tsx"],"sourcesContent":["import { memo } from \"react\";\nimport type { ButtonHTMLAttributes, ReactNode } from \"react\";\nimport type { IconDefinition } from \"@gnome-ui/icons\";\nimport { Icon } from \"../Icon\";\nimport { Badge } from \"../Badge\";\nimport styles from \"./Tabs.module.css\";\n\nexport interface TabItemProps extends ButtonHTMLAttributes<HTMLButtonElement> {\n /** Tab label. */\n label: string;\n /** Optional icon from `@gnome-ui/icons`. */\n icon?: IconDefinition;\n /** Marks this tab as the currently selected one. */\n active?: boolean;\n /**\n * id of the `TabPanel` this tab controls.\n * Sets `aria-controls` automatically.\n */\n panelId?: string;\n /**\n * When provided, a close (×) button is rendered at the trailing edge.\n * Called when the user clicks the close button.\n */\n onClose?: () => void;\n /** Accessible label for the close button. Defaults to `\"Close tab\"`. */\n closeLabel?: string;\n /** Optional count shown as a badge next to the label (e.g. unread messages). Values above 99 render as \"99+\". */\n count?: number;\n children?: ReactNode;\n}\n\n/**\n * Individual tab button inside a `TabBar`.\n */\nexport const TabItem = memo(function TabItem({\n label,\n icon,\n active = false,\n panelId,\n onClose,\n closeLabel = \"Close tab\",\n count,\n className,\n disabled,\n ...props\n}: TabItemProps) {\n return (\n <button\n role=\"tab\"\n type=\"button\"\n aria-selected={active}\n aria-controls={panelId}\n tabIndex={active ? 0 : -1}\n disabled={disabled}\n className={[\n styles.tab,\n active ? styles.active : null,\n onClose ? styles.closeable : null,\n className,\n ]\n .filter(Boolean)\n .join(\" \")}\n {...props}\n >\n {icon && (\n <span className={styles.tabIcon}>\n <Icon icon={icon} size=\"sm\" aria-hidden />\n </span>\n )}\n <span className={styles.tabLabel}>{label}</span>\n\n {count !== undefined && (\n <Badge className={styles.tabBadge}>\n {count > 99 ? \"99+\" : count}\n </Badge>\n )}\n\n {onClose && (\n <button\n type=\"button\"\n aria-label={closeLabel}\n className={styles.closeBtn}\n onClick={(e) => { e.stopPropagation(); onClose(); }}\n >\n ×\n </button>\n )}\n </button>\n );\n});\n"],"mappings":"6JAkCA,IAAa,GAAA,EAAA,EAAA,MAAe,SAAiB,CAC3C,QACA,OACA,SAAS,GACT,UACA,UACA,aAAa,YACb,QACA,YACA,WACA,GAAG,GACY,CACf,OACE,EAAA,EAAA,MAAC,SAAD,CACE,KAAK,MACL,KAAK,SACL,gBAAe,EACf,gBAAe,EACf,SAAU,EAAS,EAAI,GACb,WACV,UAAW,CACT,EAAA,QAAO,IACP,EAAS,EAAA,QAAO,OAAS,KACzB,EAAU,EAAA,QAAO,UAAY,KAC7B,EACD,CACE,OAAO,QAAQ,CACf,KAAK,IAAI,CACZ,GAAI,WAfN,CAiBG,IACC,EAAA,EAAA,KAAC,OAAD,CAAM,UAAW,EAAA,QAAO,kBACtB,EAAA,EAAA,KAAC,EAAA,KAAD,CAAY,OAAM,KAAK,KAAK,cAAA,GAAc,CAAA,CACrC,CAAA,EAET,EAAA,EAAA,KAAC,OAAD,CAAM,UAAW,EAAA,QAAO,kBAAW,EAAa,CAAA,CAE/C,IAAU,IAAA,KACT,EAAA,EAAA,KAAC,EAAA,MAAD,CAAO,UAAW,EAAA,QAAO,kBACtB,EAAQ,GAAK,MAAQ,EAChB,CAAA,CAGT,IACC,EAAA,EAAA,KAAC,SAAD,CACE,KAAK,SACL,aAAY,EACZ,UAAW,EAAA,QAAO,SAClB,QAAU,GAAM,CAAE,EAAE,iBAAiB,CAAE,GAAS,WACjD,IAEQ,CAAA,CAEJ,IAEX"}
|
|
@@ -19,9 +19,11 @@ export interface TabItemProps extends ButtonHTMLAttributes<HTMLButtonElement> {
|
|
|
19
19
|
onClose?: () => void;
|
|
20
20
|
/** Accessible label for the close button. Defaults to `"Close tab"`. */
|
|
21
21
|
closeLabel?: string;
|
|
22
|
+
/** Optional count shown as a badge next to the label (e.g. unread messages). Values above 99 render as "99+". */
|
|
23
|
+
count?: number;
|
|
22
24
|
children?: ReactNode;
|
|
23
25
|
}
|
|
24
26
|
/**
|
|
25
27
|
* Individual tab button inside a `TabBar`.
|
|
26
28
|
*/
|
|
27
|
-
export declare
|
|
29
|
+
export declare const TabItem: import('react').NamedExoticComponent<TabItemProps>;
|
|
@@ -1,52 +1,54 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import t from "
|
|
3
|
-
import
|
|
1
|
+
import { Badge as e } from "../Badge/Badge.js";
|
|
2
|
+
import { Icon as t } from "../Icon/Icon.js";
|
|
3
|
+
import n from "./Tabs.module.css.js";
|
|
4
|
+
import { memo as r } from "react";
|
|
5
|
+
import { jsx as i, jsxs as a } from "react/jsx-runtime";
|
|
4
6
|
//#region src/components/Tabs/TabItem.tsx
|
|
5
|
-
|
|
6
|
-
return /* @__PURE__ */
|
|
7
|
+
var o = r(function({ label: r, icon: o, active: s = !1, panelId: c, onClose: l, closeLabel: u = "Close tab", count: d, className: f, disabled: p, ...m }) {
|
|
8
|
+
return /* @__PURE__ */ a("button", {
|
|
7
9
|
role: "tab",
|
|
8
10
|
type: "button",
|
|
9
|
-
"aria-selected":
|
|
10
|
-
"aria-controls":
|
|
11
|
-
tabIndex:
|
|
12
|
-
disabled:
|
|
11
|
+
"aria-selected": s,
|
|
12
|
+
"aria-controls": c,
|
|
13
|
+
tabIndex: s ? 0 : -1,
|
|
14
|
+
disabled: p,
|
|
13
15
|
className: [
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
16
|
+
n.tab,
|
|
17
|
+
s ? n.active : null,
|
|
18
|
+
l ? n.closeable : null,
|
|
19
|
+
f
|
|
18
20
|
].filter(Boolean).join(" "),
|
|
19
|
-
...
|
|
21
|
+
...m,
|
|
20
22
|
children: [
|
|
21
|
-
|
|
22
|
-
className:
|
|
23
|
-
children: /* @__PURE__ */
|
|
24
|
-
icon:
|
|
23
|
+
o && /* @__PURE__ */ i("span", {
|
|
24
|
+
className: n.tabIcon,
|
|
25
|
+
children: /* @__PURE__ */ i(t, {
|
|
26
|
+
icon: o,
|
|
25
27
|
size: "sm",
|
|
26
28
|
"aria-hidden": !0
|
|
27
29
|
})
|
|
28
30
|
}),
|
|
29
|
-
/* @__PURE__ */
|
|
30
|
-
className:
|
|
31
|
-
children:
|
|
31
|
+
/* @__PURE__ */ i("span", {
|
|
32
|
+
className: n.tabLabel,
|
|
33
|
+
children: r
|
|
32
34
|
}),
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
35
|
+
d !== void 0 && /* @__PURE__ */ i(e, {
|
|
36
|
+
className: n.tabBadge,
|
|
37
|
+
children: d > 99 ? "99+" : d
|
|
38
|
+
}),
|
|
39
|
+
l && /* @__PURE__ */ i("button", {
|
|
40
|
+
type: "button",
|
|
41
|
+
"aria-label": u,
|
|
42
|
+
className: n.closeBtn,
|
|
38
43
|
onClick: (e) => {
|
|
39
|
-
e.stopPropagation(),
|
|
40
|
-
},
|
|
41
|
-
onKeyDown: (e) => {
|
|
42
|
-
(e.key === "Enter" || e.key === " ") && (e.preventDefault(), e.stopPropagation(), c());
|
|
44
|
+
e.stopPropagation(), l();
|
|
43
45
|
},
|
|
44
46
|
children: "×"
|
|
45
47
|
})
|
|
46
48
|
]
|
|
47
49
|
});
|
|
48
|
-
}
|
|
50
|
+
});
|
|
49
51
|
//#endregion
|
|
50
|
-
export {
|
|
52
|
+
export { o as TabItem };
|
|
51
53
|
|
|
52
54
|
//# sourceMappingURL=TabItem.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"TabItem.js","names":[],"sources":["../../../src/components/Tabs/TabItem.tsx"],"sourcesContent":["import type { ButtonHTMLAttributes, ReactNode } from \"react\";\nimport type { IconDefinition } from \"@gnome-ui/icons\";\nimport { Icon } from \"../Icon\";\nimport styles from \"./Tabs.module.css\";\n\nexport interface TabItemProps extends ButtonHTMLAttributes<HTMLButtonElement> {\n /** Tab label. */\n label: string;\n /** Optional icon from `@gnome-ui/icons`. */\n icon?: IconDefinition;\n /** Marks this tab as the currently selected one. */\n active?: boolean;\n /**\n * id of the `TabPanel` this tab controls.\n * Sets `aria-controls` automatically.\n */\n panelId?: string;\n /**\n * When provided, a close (×) button is rendered at the trailing edge.\n * Called when the user clicks the close button.\n */\n onClose?: () => void;\n /** Accessible label for the close button. Defaults to `\"Close tab\"`. */\n closeLabel?: string;\n children?: ReactNode;\n}\n\n/**\n * Individual tab button inside a `TabBar`.\n */\nexport function TabItem({\n label,\n icon,\n active = false,\n panelId,\n onClose,\n closeLabel = \"Close tab\",\n className,\n disabled,\n ...props\n}: TabItemProps) {\n return (\n <button\n role=\"tab\"\n type=\"button\"\n aria-selected={active}\n aria-controls={panelId}\n tabIndex={active ? 0 : -1}\n disabled={disabled}\n className={[\n styles.tab,\n active ? styles.active : null,\n onClose ? styles.closeable : null,\n className,\n ]\n .filter(Boolean)\n .join(\" \")}\n {...props}\n >\n {icon && (\n <span className={styles.tabIcon}>\n <Icon icon={icon} size=\"sm\" aria-hidden />\n </span>\n )}\n <span className={styles.tabLabel}>{label}</span>\n\n {onClose && (\n <
|
|
1
|
+
{"version":3,"file":"TabItem.js","names":[],"sources":["../../../src/components/Tabs/TabItem.tsx"],"sourcesContent":["import { memo } from \"react\";\nimport type { ButtonHTMLAttributes, ReactNode } from \"react\";\nimport type { IconDefinition } from \"@gnome-ui/icons\";\nimport { Icon } from \"../Icon\";\nimport { Badge } from \"../Badge\";\nimport styles from \"./Tabs.module.css\";\n\nexport interface TabItemProps extends ButtonHTMLAttributes<HTMLButtonElement> {\n /** Tab label. */\n label: string;\n /** Optional icon from `@gnome-ui/icons`. */\n icon?: IconDefinition;\n /** Marks this tab as the currently selected one. */\n active?: boolean;\n /**\n * id of the `TabPanel` this tab controls.\n * Sets `aria-controls` automatically.\n */\n panelId?: string;\n /**\n * When provided, a close (×) button is rendered at the trailing edge.\n * Called when the user clicks the close button.\n */\n onClose?: () => void;\n /** Accessible label for the close button. Defaults to `\"Close tab\"`. */\n closeLabel?: string;\n /** Optional count shown as a badge next to the label (e.g. unread messages). Values above 99 render as \"99+\". */\n count?: number;\n children?: ReactNode;\n}\n\n/**\n * Individual tab button inside a `TabBar`.\n */\nexport const TabItem = memo(function TabItem({\n label,\n icon,\n active = false,\n panelId,\n onClose,\n closeLabel = \"Close tab\",\n count,\n className,\n disabled,\n ...props\n}: TabItemProps) {\n return (\n <button\n role=\"tab\"\n type=\"button\"\n aria-selected={active}\n aria-controls={panelId}\n tabIndex={active ? 0 : -1}\n disabled={disabled}\n className={[\n styles.tab,\n active ? styles.active : null,\n onClose ? styles.closeable : null,\n className,\n ]\n .filter(Boolean)\n .join(\" \")}\n {...props}\n >\n {icon && (\n <span className={styles.tabIcon}>\n <Icon icon={icon} size=\"sm\" aria-hidden />\n </span>\n )}\n <span className={styles.tabLabel}>{label}</span>\n\n {count !== undefined && (\n <Badge className={styles.tabBadge}>\n {count > 99 ? \"99+\" : count}\n </Badge>\n )}\n\n {onClose && (\n <button\n type=\"button\"\n aria-label={closeLabel}\n className={styles.closeBtn}\n onClick={(e) => { e.stopPropagation(); onClose(); }}\n >\n ×\n </button>\n )}\n </button>\n );\n});\n"],"mappings":";;;;;;AAkCA,IAAa,IAAU,EAAK,SAAiB,EAC3C,UACA,SACA,YAAS,IACT,YACA,YACA,gBAAa,aACb,UACA,cACA,aACA,GAAG,KACY;AACf,QACE,kBAAC,UAAD;EACE,MAAK;EACL,MAAK;EACL,iBAAe;EACf,iBAAe;EACf,UAAU,IAAS,IAAI;EACb;EACV,WAAW;GACT,EAAO;GACP,IAAS,EAAO,SAAS;GACzB,IAAU,EAAO,YAAY;GAC7B;GACD,CACE,OAAO,QAAQ,CACf,KAAK,IAAI;EACZ,GAAI;YAfN;GAiBG,KACC,kBAAC,QAAD;IAAM,WAAW,EAAO;cACtB,kBAAC,GAAD;KAAY;KAAM,MAAK;KAAK,eAAA;KAAc,CAAA;IACrC,CAAA;GAET,kBAAC,QAAD;IAAM,WAAW,EAAO;cAAW;IAAa,CAAA;GAE/C,MAAU,KAAA,KACT,kBAAC,GAAD;IAAO,WAAW,EAAO;cACtB,IAAQ,KAAK,QAAQ;IAChB,CAAA;GAGT,KACC,kBAAC,UAAD;IACE,MAAK;IACL,cAAY;IACZ,WAAW,EAAO;IAClB,UAAU,MAAM;AAAuB,KAArB,EAAE,iBAAiB,EAAE,GAAS;;cACjD;IAEQ,CAAA;GAEJ;;EAEX"}
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
var e={bar:`
|
|
1
|
+
var e={bar:`_bar_1qubq_3`,list:`_list_1qubq_10`,tab:`_tab_1qubq_26`,active:`_active_1qubq_81`,tabIcon:`_tabIcon_1qubq_102`,tabLabel:`_tabLabel_1qubq_110`,tabBadge:`_tabBadge_1qubq_119`,closeBtn:`_closeBtn_1qubq_126`,panel:`_panel_1qubq_163`,inline:`_inline_1qubq_173`};exports.default=e;
|
|
2
2
|
//# sourceMappingURL=Tabs.module.css.cjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Tabs.module.css.cjs","names":[],"sources":["../../../src/components/Tabs/Tabs.module.css"],"sourcesContent":["/* ─── Bar (outer wrapper) ──────────────────────────────────────────────────── */\n\n.bar {\n background-color: var(--gnome-headerbar-bg-color, #ebebeb);\n border-bottom: 1px solid var(--gnome-headerbar-border-color, rgba(0, 0, 0, 0.12));\n}\n\n/* ─── Tab list ─────────────────────────────────────────────────────────────── */\n\n.list {\n display: flex;\n align-items: stretch;\n overflow-x: auto;\n scrollbar-width: none;\n padding: 0 var(--gnome-space-1, 6px);\n gap: 2px;\n min-height: 40px;\n}\n\n.list::-webkit-scrollbar {\n display: none;\n}\n\n/* ─── Tab button ───────────────────────────────────────────────────────────── */\n\n.tab {\n appearance: none;\n -webkit-appearance: none;\n border: none;\n background: transparent;\n font: inherit;\n cursor: pointer;\n outline: none;\n\n position: relative;\n display: inline-flex;\n align-items: center;\n gap: var(--gnome-space-1, 6px);\n padding: 0 var(--gnome-space-2, 12px);\n min-width: 80px;\n max-width: 200px;\n white-space: nowrap;\n\n font-family: var(--gnome-font-family);\n font-size: var(--gnome-font-size-body, 1rem);\n font-weight: var(--gnome-font-weight-normal, 400);\n color: var(--gnome-headerbar-fg-color, rgba(0, 0, 0, 0.8));\n opacity: 0.7;\n\n border-radius: var(--gnome-radius-md, 8px) var(--gnome-radius-md, 8px) 0 0;\n transition:\n background-color var(--gnome-duration-fast) var(--gnome-easing-default),\n opacity var(--gnome-duration-fast) var(--gnome-easing-default);\n}\n\n.tab::after {\n content: \"\";\n position: absolute;\n bottom: 0;\n left: var(--gnome-space-2, 12px);\n right: var(--gnome-space-2, 12px);\n height: 2px;\n border-radius: 1px 1px 0 0;\n background-color: var(--gnome-accent-bg-color, #3584e4);\n opacity: 0;\n transition: opacity var(--gnome-duration-fast) var(--gnome-easing-default);\n}\n\n.tab:hover {\n opacity: 1;\n background-color: var(--gnome-hover-overlay);\n}\n\n.tab:disabled {\n opacity: var(--gnome-opacity-disabled, 0.5);\n cursor: not-allowed;\n}\n\n/* ─── Active tab ───────────────────────────────────────────────────────────── */\n\n.active {\n opacity: 1;\n font-weight: var(--gnome-font-weight-semibold, 600);\n background-color: var(--gnome-active-overlay);\n}\n\n.active::after {\n opacity: 1;\n}\n\n/* ─── Focus ────────────────────────────────────────────────────────────────── */\n\n.tab:focus-visible {\n box-shadow:\n inset 0 0 0 var(--gnome-focus-ring-offset, 2px) var(--gnome-headerbar-bg-color, #ebebeb),\n inset 0 0 0 calc(var(--gnome-focus-ring-offset, 2px) + var(--gnome-focus-ring-width, 3px))\n var(--gnome-focus-ring-color, #3584e4);\n}\n\n/* ─── Icon inside tab ──────────────────────────────────────────────────────── */\n\n.tabIcon {\n display: flex;\n align-items: center;\n flex-shrink: 0;\n}\n\n/* ─── Label inside tab ─────────────────────────────────────────────────────── */\n\n.tabLabel {\n flex: 1;\n min-width: 0;\n overflow: hidden;\n text-overflow: ellipsis;\n}\n\n/* ─── Close button ─────────────────────────────────────────────────────────── */\n\n.closeBtn {\n flex-shrink: 0;\n display: flex;\n align-items: center;\n justify-content: center;\n width: 18px;\n height: 18px;\n border-radius: var(--gnome-radius-sm, 4px);\n font-size: 1rem;\n line-height: 1;\n opacity: 0.5;\n margin-left: 2px;\n transition: opacity var(--gnome-duration-fast) var(--gnome-easing-default),\n background-color var(--gnome-duration-fast) var(--gnome-easing-default);\n}\n\n.closeBtn:hover {\n opacity: 1;\n background-color: var(--gnome-active-overlay);\n}\n\n.closeBtn:focus-visible {\n outline: 2px solid var(--gnome-focus-ring-color, #3584e4);\n outline-offset: 1px;\n opacity: 1;\n}\n\n/* ─── Panel ────────────────────────────────────────────────────────────────── */\n\n.panel {\n outline: none;\n}\n\n.panel:focus-visible {\n box-shadow: inset 0 0 0 2px var(--gnome-focus-ring-color, #3584e4);\n}\n\n/* ─── Inline variant ───────────────────────────────────────────────────────── */\n\n.inline {\n background-color: transparent;\n border-bottom-color: transparent;\n}\n\n.inline .tab:focus-visible {\n box-shadow:\n inset 0 0 0 var(--gnome-focus-ring-offset, 2px) var(--gnome-window-bg-color, #fafafa),\n inset 0 0 0 calc(var(--gnome-focus-ring-offset, 2px) + var(--gnome-focus-ring-width, 3px))\n var(--gnome-focus-ring-color, #3584e4);\n}\n\n/* ─── High contrast ────────────────────────────────────────────────────────── */\n\n@media (prefers-contrast: more) {\n .bar {\n border-bottom-width: 2px;\n }\n\n .tab::after {\n height: 3px;\n }\n}\n\n/* ─── Reduced motion ───────────────────────────────────────────────────────── */\n\n@media (prefers-reduced-motion: reduce) {\n .tab,\n .tab::after,\n .closeBtn {\n transition: none;\n }\n}\n"],"mappings":""}
|
|
1
|
+
{"version":3,"file":"Tabs.module.css.cjs","names":[],"sources":["../../../src/components/Tabs/Tabs.module.css"],"sourcesContent":["/* ─── Bar (outer wrapper) ──────────────────────────────────────────────────── */\n\n.bar {\n background-color: var(--gnome-headerbar-bg-color, #ebebeb);\n border-bottom: 1px solid var(--gnome-headerbar-border-color, rgba(0, 0, 0, 0.12));\n}\n\n/* ─── Tab list ─────────────────────────────────────────────────────────────── */\n\n.list {\n display: flex;\n align-items: stretch;\n overflow-x: auto;\n scrollbar-width: none;\n padding: 0 var(--gnome-space-1, 6px);\n gap: 2px;\n min-height: 40px;\n}\n\n.list::-webkit-scrollbar {\n display: none;\n}\n\n/* ─── Tab button ───────────────────────────────────────────────────────────── */\n\n.tab {\n appearance: none;\n -webkit-appearance: none;\n border: none;\n background: transparent;\n font: inherit;\n cursor: pointer;\n outline: none;\n\n position: relative;\n display: inline-flex;\n align-items: center;\n gap: var(--gnome-space-1, 6px);\n padding: 0 var(--gnome-space-2, 12px);\n min-width: 80px;\n max-width: 200px;\n white-space: nowrap;\n\n font-family: var(--gnome-font-family);\n font-size: var(--gnome-font-size-body, 1rem);\n font-weight: var(--gnome-font-weight-normal, 400);\n color: var(--gnome-headerbar-fg-color, rgba(0, 0, 0, 0.8));\n opacity: 0.7;\n\n border-radius: var(--gnome-radius-md, 8px) var(--gnome-radius-md, 8px) 0 0;\n transition:\n background-color var(--gnome-duration-fast) var(--gnome-easing-default),\n opacity var(--gnome-duration-fast) var(--gnome-easing-default);\n}\n\n.tab::after {\n content: \"\";\n position: absolute;\n bottom: 0;\n left: var(--gnome-space-2, 12px);\n right: var(--gnome-space-2, 12px);\n height: 2px;\n border-radius: 1px 1px 0 0;\n background-color: var(--gnome-accent-bg-color, #3584e4);\n opacity: 0;\n transition: opacity var(--gnome-duration-fast) var(--gnome-easing-default);\n}\n\n.tab:hover {\n opacity: 1;\n background-color: var(--gnome-hover-overlay);\n}\n\n.tab:disabled {\n opacity: var(--gnome-opacity-disabled, 0.5);\n cursor: not-allowed;\n}\n\n/* ─── Active tab ───────────────────────────────────────────────────────────── */\n\n.active {\n opacity: 1;\n font-weight: var(--gnome-font-weight-semibold, 600);\n background-color: var(--gnome-active-overlay);\n}\n\n.active::after {\n opacity: 1;\n}\n\n/* ─── Focus ────────────────────────────────────────────────────────────────── */\n\n.tab:focus-visible {\n box-shadow:\n inset 0 0 0 var(--gnome-focus-ring-offset, 2px) var(--gnome-headerbar-bg-color, #ebebeb),\n inset 0 0 0 calc(var(--gnome-focus-ring-offset, 2px) + var(--gnome-focus-ring-width, 3px))\n var(--gnome-focus-ring-color, #3584e4);\n}\n\n/* ─── Icon inside tab ──────────────────────────────────────────────────────── */\n\n.tabIcon {\n display: flex;\n align-items: center;\n flex-shrink: 0;\n}\n\n/* ─── Label inside tab ─────────────────────────────────────────────────────── */\n\n.tabLabel {\n flex: 1;\n min-width: 0;\n overflow: hidden;\n text-overflow: ellipsis;\n}\n\n/* ─── Badge inside tab ─────────────────────────────────────────────────────── */\n\n.tabBadge {\n margin-inline-start: var(--gnome-space-1, 6px);\n flex-shrink: 0;\n}\n\n/* ─── Close button ─────────────────────────────────────────────────────────── */\n\n.closeBtn {\n appearance: none;\n -webkit-appearance: none;\n border: none;\n background: transparent;\n font: inherit;\n cursor: pointer;\n padding: 0;\n\n flex-shrink: 0;\n display: flex;\n align-items: center;\n justify-content: center;\n width: 18px;\n height: 18px;\n border-radius: var(--gnome-radius-sm, 4px);\n font-size: 1rem;\n line-height: 1;\n opacity: 0.5;\n margin-left: 2px;\n transition: opacity var(--gnome-duration-fast) var(--gnome-easing-default),\n background-color var(--gnome-duration-fast) var(--gnome-easing-default);\n}\n\n.closeBtn:hover {\n opacity: 1;\n background-color: var(--gnome-active-overlay);\n}\n\n.closeBtn:focus-visible {\n outline: 2px solid var(--gnome-focus-ring-color, #3584e4);\n outline-offset: 1px;\n opacity: 1;\n}\n\n/* ─── Panel ────────────────────────────────────────────────────────────────── */\n\n.panel {\n outline: none;\n}\n\n.panel:focus-visible {\n box-shadow: inset 0 0 0 2px var(--gnome-focus-ring-color, #3584e4);\n}\n\n/* ─── Inline variant ───────────────────────────────────────────────────────── */\n\n.inline {\n background-color: transparent;\n border-bottom-color: transparent;\n}\n\n.inline .tab:focus-visible {\n box-shadow:\n inset 0 0 0 var(--gnome-focus-ring-offset, 2px) var(--gnome-window-bg-color, #fafafa),\n inset 0 0 0 calc(var(--gnome-focus-ring-offset, 2px) + var(--gnome-focus-ring-width, 3px))\n var(--gnome-focus-ring-color, #3584e4);\n}\n\n/* ─── High contrast ────────────────────────────────────────────────────────── */\n\n@media (prefers-contrast: more) {\n .bar {\n border-bottom-width: 2px;\n }\n\n .tab::after {\n height: 3px;\n }\n}\n\n/* ─── Reduced motion ───────────────────────────────────────────────────────── */\n\n@media (prefers-reduced-motion: reduce) {\n .tab,\n .tab::after,\n .closeBtn {\n transition: none;\n }\n}\n"],"mappings":""}
|