@lablup/ui-common 0.1.0-alpha.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/LICENSE +202 -0
- package/NOTICE +10 -0
- package/README.md +145 -0
- package/dist/assets/components/Badge/Badge.css +1 -0
- package/dist/assets/components/BaseCard/BaseCard.css +1 -0
- package/dist/assets/components/Button/Button.css +1 -0
- package/dist/assets/components/DataTable/DataTable.css +1 -0
- package/dist/assets/components/Drawer/Drawer.css +1 -0
- package/dist/assets/components/EmptyState/EmptyState.css +1 -0
- package/dist/assets/components/ErrorState/ErrorState.css +1 -0
- package/dist/assets/components/PageHeader/PageHeader.css +1 -0
- package/dist/assets/components/PageLayout/PageLayout.css +1 -0
- package/dist/assets/components/ProgressBar/ProgressBar.css +1 -0
- package/dist/assets/components/Skeleton/Skeleton.css +1 -0
- package/dist/assets/components/Skeleton/SkeletonCard.css +1 -0
- package/dist/assets/components/Skeleton/SkeletonChart.css +1 -0
- package/dist/assets/components/Skeleton/SkeletonRow.css +1 -0
- package/dist/assets/components/Skeleton/SkeletonText.css +1 -0
- package/dist/assets/components/SmoothHeight/SmoothHeight.css +1 -0
- package/dist/assets/components/StatCard/StatCard.css +1 -0
- package/dist/assets/components/StatusTag/StatusTag.css +1 -0
- package/dist/assets/components/Tabs/Tabs.css +1 -0
- package/dist/assets/components/Tooltip/Tooltip.css +1 -0
- package/dist/components/Badge/Badge.d.ts +7 -0
- package/dist/components/Badge/Badge2.js +19 -0
- package/dist/components/Badge/Badge2.js.map +1 -0
- package/dist/components/Badge/index.d.ts +2 -0
- package/dist/components/Badge/index.js +2 -0
- package/dist/components/BaseCard/BaseCard.d.ts +57 -0
- package/dist/components/BaseCard/BaseCard2.js +36 -0
- package/dist/components/BaseCard/BaseCard2.js.map +1 -0
- package/dist/components/BaseCard/index.d.ts +2 -0
- package/dist/components/BaseCard/index.js +2 -0
- package/dist/components/Button/Button.d.ts +54 -0
- package/dist/components/Button/Button2.js +74 -0
- package/dist/components/Button/Button2.js.map +1 -0
- package/dist/components/Button/index.d.ts +5 -0
- package/dist/components/Button/index.js +2 -0
- package/dist/components/DataTable/DataTable.d.ts +133 -0
- package/dist/components/DataTable/DataTable2.js +276 -0
- package/dist/components/DataTable/DataTable2.js.map +1 -0
- package/dist/components/DataTable/index.d.ts +2 -0
- package/dist/components/DataTable/index.js +2 -0
- package/dist/components/Drawer/Drawer.d.ts +25 -0
- package/dist/components/Drawer/Drawer2.js +106 -0
- package/dist/components/Drawer/Drawer2.js.map +1 -0
- package/dist/components/Drawer/index.d.ts +2 -0
- package/dist/components/Drawer/index.js +2 -0
- package/dist/components/EmptyState/EmptyState.d.ts +45 -0
- package/dist/components/EmptyState/EmptyState.example.d.ts +8 -0
- package/dist/components/EmptyState/EmptyState2.js +78 -0
- package/dist/components/EmptyState/EmptyState2.js.map +1 -0
- package/dist/components/EmptyState/illustrations.d.ts +51 -0
- package/dist/components/EmptyState/illustrations.js +571 -0
- package/dist/components/EmptyState/illustrations.js.map +1 -0
- package/dist/components/EmptyState/index.d.ts +5 -0
- package/dist/components/EmptyState/index.js +2 -0
- package/dist/components/ErrorState/ErrorState.d.ts +25 -0
- package/dist/components/ErrorState/ErrorState.example.d.ts +46 -0
- package/dist/components/ErrorState/ErrorState2.js +58 -0
- package/dist/components/ErrorState/ErrorState2.js.map +1 -0
- package/dist/components/ErrorState/index.d.ts +5 -0
- package/dist/components/ErrorState/index.js +2 -0
- package/dist/components/PageHeader/PageHeader.d.ts +18 -0
- package/dist/components/PageHeader/PageHeader2.js +42 -0
- package/dist/components/PageHeader/PageHeader2.js.map +1 -0
- package/dist/components/PageHeader/index.d.ts +2 -0
- package/dist/components/PageHeader/index.js +2 -0
- package/dist/components/PageLayout/PageLayout.d.ts +11 -0
- package/dist/components/PageLayout/PageLayout2.js +19 -0
- package/dist/components/PageLayout/PageLayout2.js.map +1 -0
- package/dist/components/PageLayout/index.d.ts +2 -0
- package/dist/components/PageLayout/index.js +2 -0
- package/dist/components/ProgressBar/ProgressBar.d.ts +22 -0
- package/dist/components/ProgressBar/ProgressBar2.js +36 -0
- package/dist/components/ProgressBar/ProgressBar2.js.map +1 -0
- package/dist/components/ProgressBar/index.d.ts +2 -0
- package/dist/components/ProgressBar/index.js +2 -0
- package/dist/components/Skeleton/Skeleton.d.ts +25 -0
- package/dist/components/Skeleton/Skeleton2.js +26 -0
- package/dist/components/Skeleton/Skeleton2.js.map +1 -0
- package/dist/components/Skeleton/SkeletonCard.d.ts +18 -0
- package/dist/components/Skeleton/SkeletonCard2.js +73 -0
- package/dist/components/Skeleton/SkeletonCard2.js.map +1 -0
- package/dist/components/Skeleton/SkeletonChart.d.ts +23 -0
- package/dist/components/Skeleton/SkeletonChart2.js +66 -0
- package/dist/components/Skeleton/SkeletonChart2.js.map +1 -0
- package/dist/components/Skeleton/SkeletonRow.d.ts +22 -0
- package/dist/components/Skeleton/SkeletonRow2.js +47 -0
- package/dist/components/Skeleton/SkeletonRow2.js.map +1 -0
- package/dist/components/Skeleton/SkeletonText.d.ts +20 -0
- package/dist/components/Skeleton/SkeletonText2.js +26 -0
- package/dist/components/Skeleton/SkeletonText2.js.map +1 -0
- package/dist/components/Skeleton/index.d.ts +15 -0
- package/dist/components/Skeleton/index.js +6 -0
- package/dist/components/SmoothHeight/SmoothHeight.d.ts +9 -0
- package/dist/components/SmoothHeight/SmoothHeight2.js +38 -0
- package/dist/components/SmoothHeight/SmoothHeight2.js.map +1 -0
- package/dist/components/SmoothHeight/index.d.ts +2 -0
- package/dist/components/SmoothHeight/index.js +2 -0
- package/dist/components/StatCard/StatCard.d.ts +59 -0
- package/dist/components/StatCard/StatCard2.js +111 -0
- package/dist/components/StatCard/StatCard2.js.map +1 -0
- package/dist/components/StatCard/formatters.d.ts +12 -0
- package/dist/components/StatCard/formatters.js +8 -0
- package/dist/components/StatCard/formatters.js.map +1 -0
- package/dist/components/StatCard/index.d.ts +3 -0
- package/dist/components/StatCard/index.js +3 -0
- package/dist/components/StatusTag/StatusTag.d.ts +38 -0
- package/dist/components/StatusTag/StatusTag2.js +44 -0
- package/dist/components/StatusTag/StatusTag2.js.map +1 -0
- package/dist/components/StatusTag/index.d.ts +2 -0
- package/dist/components/StatusTag/index.js +2 -0
- package/dist/components/Tabs/Tabs.d.ts +107 -0
- package/dist/components/Tabs/Tabs2.js +430 -0
- package/dist/components/Tabs/Tabs2.js.map +1 -0
- package/dist/components/Tabs/index.d.ts +2 -0
- package/dist/components/Tabs/index.js +3 -0
- package/dist/components/Tabs/tabTags.d.ts +9 -0
- package/dist/components/Tabs/tabTags.js +11 -0
- package/dist/components/Tabs/tabTags.js.map +1 -0
- package/dist/components/Tooltip/Tooltip.d.ts +16 -0
- package/dist/components/Tooltip/Tooltip2.js +67 -0
- package/dist/components/Tooltip/Tooltip2.js.map +1 -0
- package/dist/components/Tooltip/index.d.ts +2 -0
- package/dist/components/Tooltip/index.js +2 -0
- package/dist/hooks/index.d.ts +1 -0
- package/dist/hooks/index.js +2 -0
- package/dist/hooks/usePrefersReducedMotion.d.ts +12 -0
- package/dist/hooks/usePrefersReducedMotion.js +22 -0
- package/dist/hooks/usePrefersReducedMotion.js.map +1 -0
- package/dist/icons/AlertCircleIcon.d.ts +11 -0
- package/dist/icons/AlertCircleIcon.js +26 -0
- package/dist/icons/AlertCircleIcon.js.map +1 -0
- package/dist/index.d.ts +29 -0
- package/dist/index.js +24 -0
- package/dist/styles/base.css +169 -0
- package/dist/styles/themes/bliss-dark.css +123 -0
- package/dist/styles/themes/bliss-light.css +123 -0
- package/dist/styles/themes/glass-dark.css +124 -0
- package/dist/styles/themes/glass-light.css +125 -0
- package/dist/styles/themes/orange-dark.css +70 -0
- package/dist/styles/themes/orange-light.css +70 -0
- package/dist/styles/themes/reverie-dark.css +104 -0
- package/dist/styles/themes/reverie-light.css +104 -0
- package/dist/styles/themes/stained-dark.css +80 -0
- package/dist/styles/themes/stained-light.css +80 -0
- package/package.json +87 -0
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
import { default as React } from 'react';
|
|
2
|
+
export type BaseCardVariant = "default" | "installed" | "available";
|
|
3
|
+
export type BaseCardState = "idle" | "loading" | "active" | "disabled" | "warning";
|
|
4
|
+
export type BaseCardDirection = "column" | "row";
|
|
5
|
+
export interface BaseCardProps {
|
|
6
|
+
/** Card content */
|
|
7
|
+
children: React.ReactNode;
|
|
8
|
+
/** Additional CSS class names */
|
|
9
|
+
className?: string;
|
|
10
|
+
/**
|
|
11
|
+
* Inline style escape hatch. Intended for passing dynamic CSS custom
|
|
12
|
+
* properties (e.g. `{ "--corner-accent-color": brandColor }`) that cannot be
|
|
13
|
+
* expressed as a static class. Avoid using it for static layout.
|
|
14
|
+
*/
|
|
15
|
+
style?: React.CSSProperties;
|
|
16
|
+
/** Click handler - also enables clickable styling */
|
|
17
|
+
onClick?: () => void;
|
|
18
|
+
/** Keyboard event handler */
|
|
19
|
+
onKeyDown?: (e: React.KeyboardEvent) => void;
|
|
20
|
+
/** Whether the card should have clickable styling (auto-enabled if onClick provided) */
|
|
21
|
+
clickable?: boolean;
|
|
22
|
+
/** Card visual variant */
|
|
23
|
+
variant?: BaseCardVariant;
|
|
24
|
+
/**
|
|
25
|
+
* Flex layout direction of the card's content.
|
|
26
|
+
* Defaults to `"column"` (content stacks vertically). Pass `"row"` for a
|
|
27
|
+
* horizontal layout (icon + content, text + badge, info + actions). Without
|
|
28
|
+
* this, a horizontal layout silently collapses into a centered vertical
|
|
29
|
+
* stack because the base style forces `flex-direction: column`.
|
|
30
|
+
*/
|
|
31
|
+
direction?: BaseCardDirection;
|
|
32
|
+
/** Card state for animations and visual feedback */
|
|
33
|
+
state?: BaseCardState;
|
|
34
|
+
/** Whether to show hover effects (default: true) */
|
|
35
|
+
hoverable?: boolean;
|
|
36
|
+
/** Accessibility label */
|
|
37
|
+
ariaLabel?: string;
|
|
38
|
+
/** ARIA role override (default: "button" when clickable) */
|
|
39
|
+
role?: string;
|
|
40
|
+
/** ARIA checked state for radio/checkbox roles */
|
|
41
|
+
ariaChecked?: boolean;
|
|
42
|
+
/** Tab index for keyboard navigation */
|
|
43
|
+
tabIndex?: number;
|
|
44
|
+
/** Test ID for testing */
|
|
45
|
+
testId?: string;
|
|
46
|
+
}
|
|
47
|
+
/**
|
|
48
|
+
* BaseCard provides a consistent foundation for card-style UI components.
|
|
49
|
+
*
|
|
50
|
+
* Features:
|
|
51
|
+
* - Unified hover effects (lift, shadow, border)
|
|
52
|
+
* - State-based styling (loading, active, disabled)
|
|
53
|
+
* - Accessibility support (keyboard navigation, focus styles)
|
|
54
|
+
* - Reduced motion preference support
|
|
55
|
+
*/
|
|
56
|
+
export declare const BaseCard: React.ForwardRefExoticComponent<BaseCardProps & React.RefAttributes<HTMLDivElement>>;
|
|
57
|
+
export default BaseCard;
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
/* empty css */
|
|
2
|
+
import { forwardRef as e } from "react";
|
|
3
|
+
import { jsx as t } from "react/jsx-runtime";
|
|
4
|
+
//#region src/components/BaseCard/BaseCard.tsx
|
|
5
|
+
var n = e(({ children: e, className: n = "", style: r, onClick: i, onKeyDown: a, clickable: o, variant: s = "default", direction: c = "column", state: l = "idle", hoverable: u = !0, ariaLabel: d, role: f, ariaChecked: p, tabIndex: m, testId: h }, g) => {
|
|
6
|
+
let _ = o ?? !!i, v = (e) => {
|
|
7
|
+
a && a(e), _ && i && (e.key === "Enter" || e.key === " ") && (e.preventDefault(), i());
|
|
8
|
+
}, y = [
|
|
9
|
+
"base-card",
|
|
10
|
+
`base-card--${s}`,
|
|
11
|
+
c === "row" && "base-card--row",
|
|
12
|
+
u && "base-card--hoverable",
|
|
13
|
+
_ && "base-card--clickable",
|
|
14
|
+
l !== "idle" && `base-card--${l}`,
|
|
15
|
+
n
|
|
16
|
+
].filter(Boolean).join(" ");
|
|
17
|
+
return /* @__PURE__ */ t("div", {
|
|
18
|
+
ref: g,
|
|
19
|
+
className: y,
|
|
20
|
+
style: r,
|
|
21
|
+
onClick: i,
|
|
22
|
+
onKeyDown: v,
|
|
23
|
+
role: f ?? (_ ? "button" : void 0),
|
|
24
|
+
tabIndex: _ ? m ?? 0 : m,
|
|
25
|
+
"aria-label": d,
|
|
26
|
+
"aria-checked": p,
|
|
27
|
+
"aria-disabled": l === "disabled" || void 0,
|
|
28
|
+
"data-testid": h,
|
|
29
|
+
children: e
|
|
30
|
+
});
|
|
31
|
+
});
|
|
32
|
+
n.displayName = "BaseCard";
|
|
33
|
+
//#endregion
|
|
34
|
+
export { n as BaseCard, n as default };
|
|
35
|
+
|
|
36
|
+
//# sourceMappingURL=BaseCard2.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"BaseCard2.js","names":[],"sources":["../../../src/components/BaseCard/BaseCard.tsx"],"sourcesContent":["/**\n * BaseCard Component\n *\n * Common card foundation providing unified hover, animation, and state effects.\n * Use this component to ensure consistent UI/UX across all card-style components.\n *\n * @example\n * // Basic usage\n * <BaseCard>\n * <h3>Card Title</h3>\n * <p>Card content</p>\n * </BaseCard>\n *\n * @example\n * // Clickable card with loading state\n * <BaseCard\n * clickable\n * onClick={handleClick}\n * state=\"loading\"\n * >\n * <CardContent />\n * </BaseCard>\n */\n\nimport React, { forwardRef } from \"react\";\nimport \"./BaseCard.css\";\n\nexport type BaseCardVariant = \"default\" | \"installed\" | \"available\";\nexport type BaseCardState = \"idle\" | \"loading\" | \"active\" | \"disabled\" | \"warning\";\nexport type BaseCardDirection = \"column\" | \"row\";\n\nexport interface BaseCardProps {\n /** Card content */\n children: React.ReactNode;\n /** Additional CSS class names */\n className?: string;\n /**\n * Inline style escape hatch. Intended for passing dynamic CSS custom\n * properties (e.g. `{ \"--corner-accent-color\": brandColor }`) that cannot be\n * expressed as a static class. Avoid using it for static layout.\n */\n style?: React.CSSProperties;\n /** Click handler - also enables clickable styling */\n onClick?: () => void;\n /** Keyboard event handler */\n onKeyDown?: (e: React.KeyboardEvent) => void;\n /** Whether the card should have clickable styling (auto-enabled if onClick provided) */\n clickable?: boolean;\n /** Card visual variant */\n variant?: BaseCardVariant;\n /**\n * Flex layout direction of the card's content.\n * Defaults to `\"column\"` (content stacks vertically). Pass `\"row\"` for a\n * horizontal layout (icon + content, text + badge, info + actions). Without\n * this, a horizontal layout silently collapses into a centered vertical\n * stack because the base style forces `flex-direction: column`.\n */\n direction?: BaseCardDirection;\n /** Card state for animations and visual feedback */\n state?: BaseCardState;\n /** Whether to show hover effects (default: true) */\n hoverable?: boolean;\n /** Accessibility label */\n ariaLabel?: string;\n /** ARIA role override (default: \"button\" when clickable) */\n role?: string;\n /** ARIA checked state for radio/checkbox roles */\n ariaChecked?: boolean;\n /** Tab index for keyboard navigation */\n tabIndex?: number;\n /** Test ID for testing */\n testId?: string;\n}\n\n/**\n * BaseCard provides a consistent foundation for card-style UI components.\n *\n * Features:\n * - Unified hover effects (lift, shadow, border)\n * - State-based styling (loading, active, disabled)\n * - Accessibility support (keyboard navigation, focus styles)\n * - Reduced motion preference support\n */\nexport const BaseCard = forwardRef<HTMLDivElement, BaseCardProps>(\n (\n {\n children,\n className = \"\",\n style,\n onClick,\n onKeyDown,\n clickable,\n variant = \"default\",\n direction = \"column\",\n state = \"idle\",\n hoverable = true,\n ariaLabel,\n role,\n ariaChecked,\n tabIndex,\n testId,\n },\n ref,\n ) => {\n const isClickable = clickable ?? !!onClick;\n\n const handleKeyDown = (e: React.KeyboardEvent) => {\n if (onKeyDown) {\n onKeyDown(e);\n }\n // Allow Enter or Space to trigger click for accessibility\n if (isClickable && onClick && (e.key === \"Enter\" || e.key === \" \")) {\n e.preventDefault();\n onClick();\n }\n };\n\n const classNames = [\n \"base-card\",\n `base-card--${variant}`,\n direction === \"row\" && \"base-card--row\",\n hoverable && \"base-card--hoverable\",\n isClickable && \"base-card--clickable\",\n state !== \"idle\" && `base-card--${state}`,\n className,\n ]\n .filter(Boolean)\n .join(\" \");\n\n // Determine the role: explicit role > \"button\" for clickable > undefined\n const effectiveRole = role ?? (isClickable ? \"button\" : undefined);\n\n return (\n <div\n ref={ref}\n className={classNames}\n style={style}\n onClick={onClick}\n onKeyDown={handleKeyDown}\n role={effectiveRole}\n tabIndex={isClickable ? (tabIndex ?? 0) : tabIndex}\n aria-label={ariaLabel}\n aria-checked={ariaChecked}\n aria-disabled={state === \"disabled\" ? true : undefined}\n data-testid={testId}\n >\n {children}\n </div>\n );\n },\n);\n\nBaseCard.displayName = \"BaseCard\";\n\nexport default BaseCard;\n"],"mappings":";;;;AAmFA,IAAa,IAAW,GAEpB,EACE,aACA,eAAY,IACZ,UACA,YACA,cACA,cACA,aAAU,WACV,eAAY,UACZ,WAAQ,QACR,eAAY,IACZ,cACA,SACA,gBACA,aACA,aAEF,MACG;CACH,IAAM,IAAc,KAAa,CAAC,CAAC,GAE7B,KAAiB,MAA2B;EAKhD,AAJI,KACF,EAAU,CAAC,GAGT,KAAe,MAAY,EAAE,QAAQ,WAAW,EAAE,QAAQ,SAC5D,EAAE,eAAe,GACjB,EAAQ;CAEZ,GAEM,IAAa;EACjB;EACA,cAAc;EACd,MAAc,SAAS;EACvB,KAAa;EACb,KAAe;EACf,MAAU,UAAU,cAAc;EAClC;CACF,CAAC,CACE,OAAO,OAAO,CAAC,CACf,KAAK,GAAG;CAKX,OACE,kBAAC,OAAD;EACO;EACL,WAAW;EACJ;EACE;EACT,WAAW;EACX,MATkB,MAAS,IAAc,WAAW,KAAA;EAUpD,UAAU,IAAe,KAAY,IAAK;EAC1C,cAAY;EACZ,gBAAc;EACd,iBAAe,MAAU,cAAoB,KAAA;EAC7C,eAAa;EAEZ;CACE,CAAA;AAET,CACF;AAEA,EAAS,cAAc"}
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
export interface ButtonProps {
|
|
2
|
+
children?: React.ReactNode;
|
|
3
|
+
onClick?: (e: React.MouseEvent<HTMLButtonElement>) => void;
|
|
4
|
+
onDoubleClick?: (e: React.MouseEvent<HTMLButtonElement>) => void;
|
|
5
|
+
onMouseDown?: (e: React.MouseEvent<HTMLButtonElement>) => void;
|
|
6
|
+
onMouseEnter?: (e: React.MouseEvent<HTMLButtonElement>) => void;
|
|
7
|
+
onKeyDown?: (e: React.KeyboardEvent<HTMLButtonElement>) => void;
|
|
8
|
+
type?: "button" | "submit" | "reset";
|
|
9
|
+
disabled?: boolean;
|
|
10
|
+
variant?: "primary" | "secondary" | "danger" | "success" | "ghost" | "text" | "outline";
|
|
11
|
+
size?: "xsmall" | "small" | "medium" | "large";
|
|
12
|
+
shape?: "default" | "circle";
|
|
13
|
+
fullWidth?: boolean;
|
|
14
|
+
icon?: React.ReactNode;
|
|
15
|
+
iconPosition?: "left" | "right";
|
|
16
|
+
iconOnly?: boolean;
|
|
17
|
+
/**
|
|
18
|
+
* Inline mode (default: false). When true, the Button acts as a thin
|
|
19
|
+
* styling shell over a consumer-owned layout:
|
|
20
|
+
*
|
|
21
|
+
* - `min-height` is reset to `auto` so the host CSS controls height
|
|
22
|
+
* - the ghost-variant hover/active translate + box-shadow are
|
|
23
|
+
* suppressed (no jitter)
|
|
24
|
+
* - children render directly inside the `<button>` element, without
|
|
25
|
+
* being wrapped in `<span class="button__text">` — useful when the
|
|
26
|
+
* consumer needs the icon and label to sit on the same baseline
|
|
27
|
+
* using its own flex/grid layout
|
|
28
|
+
*
|
|
29
|
+
* Use this for compact triggers (selector trigger, badge button,
|
|
30
|
+
* inline action button) that have their own padding, height, and
|
|
31
|
+
* icon+text layout and only want Button for variant theming and
|
|
32
|
+
* accessibility wiring.
|
|
33
|
+
*/
|
|
34
|
+
inline?: boolean;
|
|
35
|
+
loading?: boolean;
|
|
36
|
+
active?: boolean;
|
|
37
|
+
ariaLabel?: string;
|
|
38
|
+
title?: string;
|
|
39
|
+
role?: React.AriaRole;
|
|
40
|
+
id?: string;
|
|
41
|
+
tabIndex?: number;
|
|
42
|
+
"aria-pressed"?: boolean;
|
|
43
|
+
"aria-checked"?: boolean;
|
|
44
|
+
"aria-selected"?: boolean;
|
|
45
|
+
"aria-expanded"?: boolean;
|
|
46
|
+
"aria-haspopup"?: boolean | "menu" | "listbox" | "tree" | "grid" | "dialog";
|
|
47
|
+
"aria-controls"?: string;
|
|
48
|
+
"aria-describedby"?: string;
|
|
49
|
+
"aria-busy"?: boolean;
|
|
50
|
+
className?: string;
|
|
51
|
+
style?: React.CSSProperties;
|
|
52
|
+
"data-testid"?: string;
|
|
53
|
+
}
|
|
54
|
+
export declare const Button: import('react').ForwardRefExoticComponent<ButtonProps & import('react').RefAttributes<HTMLButtonElement>>;
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
/* empty css */
|
|
2
|
+
import { forwardRef as e, useCallback as t } from "react";
|
|
3
|
+
import { jsx as n, jsxs as r } from "react/jsx-runtime";
|
|
4
|
+
//#region src/components/Button/Button.tsx
|
|
5
|
+
var i = e(function({ children: e, onClick: i, onDoubleClick: a, onMouseDown: o, onMouseEnter: s, onKeyDown: c, type: l = "button", disabled: u = !1, variant: d = "secondary", size: f = "medium", shape: p = "default", fullWidth: m = !1, icon: h, iconPosition: g = "left", iconOnly: _ = !1, inline: v = !1, loading: y = !1, active: b = !1, ariaLabel: x, title: S, role: C, id: w, tabIndex: T, className: E = "", style: D, "aria-pressed": O, "aria-checked": k, "aria-selected": A, "aria-expanded": j, "aria-haspopup": M, "aria-controls": N, "aria-describedby": P, "aria-busy": F, "data-testid": I }, L) {
|
|
6
|
+
let R = t((e) => {
|
|
7
|
+
!u && !y && i && i(e);
|
|
8
|
+
}, [
|
|
9
|
+
u,
|
|
10
|
+
y,
|
|
11
|
+
i
|
|
12
|
+
]), z = [
|
|
13
|
+
"button",
|
|
14
|
+
`button--${d}`,
|
|
15
|
+
`button--${f}`,
|
|
16
|
+
p !== "default" && `button--${p}`,
|
|
17
|
+
m && "button--full-width",
|
|
18
|
+
_ && "button--icon-only",
|
|
19
|
+
v && "button--inline",
|
|
20
|
+
y && "button--loading",
|
|
21
|
+
b && "button--active",
|
|
22
|
+
E
|
|
23
|
+
].filter(Boolean).join(" "), B = h ?? (_ ? e : void 0), V = !_ && e, H = B && !y;
|
|
24
|
+
return /* @__PURE__ */ r("button", {
|
|
25
|
+
ref: L,
|
|
26
|
+
type: l,
|
|
27
|
+
onClick: R,
|
|
28
|
+
onDoubleClick: a,
|
|
29
|
+
onMouseDown: o,
|
|
30
|
+
onMouseEnter: s,
|
|
31
|
+
onKeyDown: c,
|
|
32
|
+
disabled: u || y,
|
|
33
|
+
className: z,
|
|
34
|
+
"aria-label": x ?? (_ && typeof e == "string" ? e : void 0),
|
|
35
|
+
title: S,
|
|
36
|
+
role: C,
|
|
37
|
+
id: w,
|
|
38
|
+
tabIndex: T,
|
|
39
|
+
style: D,
|
|
40
|
+
"aria-pressed": O,
|
|
41
|
+
"aria-checked": k,
|
|
42
|
+
"aria-selected": A,
|
|
43
|
+
"aria-expanded": j,
|
|
44
|
+
"aria-haspopup": M,
|
|
45
|
+
"aria-controls": N,
|
|
46
|
+
"aria-describedby": P,
|
|
47
|
+
"aria-busy": F,
|
|
48
|
+
"data-testid": I,
|
|
49
|
+
children: [
|
|
50
|
+
y && /* @__PURE__ */ n("span", {
|
|
51
|
+
className: "button__loading-spinner",
|
|
52
|
+
"aria-hidden": "true"
|
|
53
|
+
}),
|
|
54
|
+
H && g === "left" && /* @__PURE__ */ n("span", {
|
|
55
|
+
className: "button__icon",
|
|
56
|
+
"aria-hidden": "true",
|
|
57
|
+
children: B
|
|
58
|
+
}),
|
|
59
|
+
V && (v ? e : /* @__PURE__ */ n("span", {
|
|
60
|
+
className: "button__text",
|
|
61
|
+
children: e
|
|
62
|
+
})),
|
|
63
|
+
H && g === "right" && /* @__PURE__ */ n("span", {
|
|
64
|
+
className: "button__icon",
|
|
65
|
+
"aria-hidden": "true",
|
|
66
|
+
children: B
|
|
67
|
+
})
|
|
68
|
+
]
|
|
69
|
+
});
|
|
70
|
+
});
|
|
71
|
+
//#endregion
|
|
72
|
+
export { i as Button };
|
|
73
|
+
|
|
74
|
+
//# sourceMappingURL=Button2.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Button2.js","names":[],"sources":["../../../src/components/Button/Button.tsx"],"sourcesContent":["/**\n * Button Component\n *\n * Shared button component that consolidates all button styles across the application.\n * Supports multiple variants, sizes, shapes, icons, loading and active states.\n */\n\nimport { forwardRef, useCallback } from \"react\";\nimport \"./Button.css\";\n\nexport interface ButtonProps {\n children?: React.ReactNode;\n onClick?: (e: React.MouseEvent<HTMLButtonElement>) => void;\n onDoubleClick?: (e: React.MouseEvent<HTMLButtonElement>) => void;\n onMouseDown?: (e: React.MouseEvent<HTMLButtonElement>) => void;\n onMouseEnter?: (e: React.MouseEvent<HTMLButtonElement>) => void;\n onKeyDown?: (e: React.KeyboardEvent<HTMLButtonElement>) => void;\n type?: \"button\" | \"submit\" | \"reset\";\n disabled?: boolean;\n\n // Styling variants\n variant?:\n \"primary\" | \"secondary\" | \"danger\" | \"success\" | \"ghost\" | \"text\" | \"outline\";\n size?: \"xsmall\" | \"small\" | \"medium\" | \"large\";\n shape?: \"default\" | \"circle\";\n fullWidth?: boolean;\n\n // Icon support\n icon?: React.ReactNode;\n iconPosition?: \"left\" | \"right\";\n iconOnly?: boolean;\n\n /**\n * Inline mode (default: false). When true, the Button acts as a thin\n * styling shell over a consumer-owned layout:\n *\n * - `min-height` is reset to `auto` so the host CSS controls height\n * - the ghost-variant hover/active translate + box-shadow are\n * suppressed (no jitter)\n * - children render directly inside the `<button>` element, without\n * being wrapped in `<span class=\"button__text\">` — useful when the\n * consumer needs the icon and label to sit on the same baseline\n * using its own flex/grid layout\n *\n * Use this for compact triggers (selector trigger, badge button,\n * inline action button) that have their own padding, height, and\n * icon+text layout and only want Button for variant theming and\n * accessibility wiring.\n */\n inline?: boolean;\n\n // States\n loading?: boolean;\n active?: boolean;\n\n // Accessibility\n ariaLabel?: string;\n title?: string;\n role?: React.AriaRole;\n id?: string;\n tabIndex?: number;\n \"aria-pressed\"?: boolean;\n \"aria-checked\"?: boolean;\n \"aria-selected\"?: boolean;\n \"aria-expanded\"?: boolean;\n \"aria-haspopup\"?: boolean | \"menu\" | \"listbox\" | \"tree\" | \"grid\" | \"dialog\";\n \"aria-controls\"?: string;\n \"aria-describedby\"?: string;\n \"aria-busy\"?: boolean;\n\n // Additional\n className?: string;\n style?: React.CSSProperties;\n \"data-testid\"?: string;\n}\n\nexport const Button = forwardRef<HTMLButtonElement, ButtonProps>(function Button(\n {\n children,\n onClick,\n onDoubleClick,\n onMouseDown,\n onMouseEnter,\n onKeyDown,\n type = \"button\",\n disabled = false,\n variant = \"secondary\",\n size = \"medium\",\n shape = \"default\",\n fullWidth = false,\n icon,\n iconPosition = \"left\",\n iconOnly = false,\n inline = false,\n loading = false,\n active = false,\n ariaLabel,\n title,\n role,\n id,\n tabIndex,\n className = \"\",\n style,\n \"aria-pressed\": ariaPressed,\n \"aria-checked\": ariaChecked,\n \"aria-selected\": ariaSelected,\n \"aria-expanded\": ariaExpanded,\n \"aria-haspopup\": ariaHasPopup,\n \"aria-controls\": ariaControls,\n \"aria-describedby\": ariaDescribedBy,\n \"aria-busy\": ariaBusy,\n \"data-testid\": dataTestId,\n },\n ref,\n) {\n const handleClick = useCallback(\n (e: React.MouseEvent<HTMLButtonElement>) => {\n if (!disabled && !loading && onClick) {\n onClick(e);\n }\n },\n [disabled, loading, onClick],\n );\n\n const classNames = [\n \"button\",\n `button--${variant}`,\n `button--${size}`,\n shape !== \"default\" && `button--${shape}`,\n fullWidth && \"button--full-width\",\n iconOnly && \"button--icon-only\",\n inline && \"button--inline\",\n loading && \"button--loading\",\n active && \"button--active\",\n className,\n ]\n .filter(Boolean)\n .join(\" \");\n\n // When iconOnly but no icon prop provided, treat children as icon content\n // This supports both patterns: icon={<Svg/>} and <Button iconOnly><Svg/></Button>\n const iconContent = icon ?? (iconOnly ? children : undefined);\n const hasText = !iconOnly && children;\n const showIcon = iconContent && !loading;\n const showLoadingSpinner = loading;\n\n return (\n <button\n ref={ref}\n type={type}\n onClick={handleClick}\n onDoubleClick={onDoubleClick}\n onMouseDown={onMouseDown}\n onMouseEnter={onMouseEnter}\n onKeyDown={onKeyDown}\n disabled={disabled || loading}\n className={classNames}\n aria-label={\n ariaLabel ?? (iconOnly && typeof children === \"string\" ? children : undefined)\n }\n title={title}\n role={role}\n id={id}\n tabIndex={tabIndex}\n style={style}\n aria-pressed={ariaPressed}\n aria-checked={ariaChecked}\n aria-selected={ariaSelected}\n aria-expanded={ariaExpanded}\n aria-haspopup={ariaHasPopup}\n aria-controls={ariaControls}\n aria-describedby={ariaDescribedBy}\n aria-busy={ariaBusy}\n data-testid={dataTestId}\n >\n {showLoadingSpinner && (\n <span className=\"button__loading-spinner\" aria-hidden=\"true\" />\n )}\n\n {showIcon && iconPosition === \"left\" && (\n <span className=\"button__icon\" aria-hidden=\"true\">\n {iconContent}\n </span>\n )}\n\n {hasText &&\n (inline ? children : <span className=\"button__text\">{children}</span>)}\n\n {showIcon && iconPosition === \"right\" && (\n <span className=\"button__icon\" aria-hidden=\"true\">\n {iconContent}\n </span>\n )}\n </button>\n );\n});\n"],"mappings":";;;;AA4EA,IAAa,IAAS,EAA2C,SAC/D,EACE,aACA,YACA,kBACA,gBACA,iBACA,cACA,UAAO,UACP,cAAW,IACX,aAAU,aACV,UAAO,UACP,WAAQ,WACR,eAAY,IACZ,SACA,kBAAe,QACf,cAAW,IACX,YAAS,IACT,aAAU,IACV,YAAS,IACT,cACA,UACA,SACA,OACA,aACA,eAAY,IACZ,UACA,gBAAgB,GAChB,gBAAgB,GAChB,iBAAiB,GACjB,iBAAiB,GACjB,iBAAiB,GACjB,iBAAiB,GACjB,oBAAoB,GACpB,aAAa,GACb,eAAe,KAEjB,GACA;CACA,IAAM,IAAc,GACjB,MAA2C;EAC1C,AAAI,CAAC,KAAY,CAAC,KAAW,KAC3B,EAAQ,CAAC;CAEb,GACA;EAAC;EAAU;EAAS;CAAO,CAC7B,GAEM,IAAa;EACjB;EACA,WAAW;EACX,WAAW;EACX,MAAU,aAAa,WAAW;EAClC,KAAa;EACb,KAAY;EACZ,KAAU;EACV,KAAW;EACX,KAAU;EACV;CACF,CAAC,CACE,OAAO,OAAO,CAAC,CACf,KAAK,GAAG,GAIL,IAAc,MAAS,IAAW,IAAW,KAAA,IAC7C,IAAU,CAAC,KAAY,GACvB,IAAW,KAAe,CAAC;CAGjC,OACE,kBAAC,UAAD;EACO;EACC;EACN,SAAS;EACM;EACF;EACC;EACH;EACX,UAAU,KAAY;EACtB,WAAW;EACX,cACE,MAAc,KAAY,OAAO,KAAa,WAAW,IAAW,KAAA;EAE/D;EACD;EACF;EACM;EACH;EACP,gBAAc;EACd,gBAAc;EACd,iBAAe;EACf,iBAAe;EACf,iBAAe;EACf,iBAAe;EACf,oBAAkB;EAClB,aAAW;EACX,eAAa;EA1Bf,UAAA;GA4BG,KACC,kBAAC,QAAD;IAAM,WAAU;IAA0B,eAAY;GAAQ,CAAA;GAG/D,KAAY,MAAiB,UAC5B,kBAAC,QAAD;IAAM,WAAU;IAAe,eAAY;IACxC,UAAA;GACG,CAAA;GAGP,MACE,IAAS,IAAW,kBAAC,QAAD;IAAM,WAAU;IAAgB;GAAe,CAAA;GAErE,KAAY,MAAiB,WAC5B,kBAAC,QAAD;IAAM,WAAU;IAAe,eAAY;IACxC,UAAA;GACG,CAAA;EAEF;;AAEZ,CAAC"}
|
|
@@ -0,0 +1,133 @@
|
|
|
1
|
+
import { ReactNode } from 'react';
|
|
2
|
+
/** Direction a column is currently sorted. */
|
|
3
|
+
export type SortDirection = "asc" | "desc";
|
|
4
|
+
export interface DataTableColumn<T> {
|
|
5
|
+
/** Unique identifier for the column. Used for visibility + width persistence. */
|
|
6
|
+
id: string;
|
|
7
|
+
/** Header label. */
|
|
8
|
+
header: ReactNode;
|
|
9
|
+
/**
|
|
10
|
+
* Cell renderer. Receives the row and returns a React node. Pure
|
|
11
|
+
* functions are encouraged so memoization stays effective.
|
|
12
|
+
*/
|
|
13
|
+
render: (row: T, index: number) => ReactNode;
|
|
14
|
+
/** Optional minimum column width in pixels. Defaults to 80. */
|
|
15
|
+
minWidth?: number;
|
|
16
|
+
/** Optional initial width in pixels (only honored on the first paint). */
|
|
17
|
+
initialWidth?: number;
|
|
18
|
+
/** When `true`, the column cannot be resized. Defaults to `false`. */
|
|
19
|
+
noResize?: boolean;
|
|
20
|
+
/** When `true`, the column cannot be hidden by the user. Defaults to `false`. */
|
|
21
|
+
alwaysVisible?: boolean;
|
|
22
|
+
/** Extra `class` for the column's `<th>` and `<td>` cells. */
|
|
23
|
+
className?: string;
|
|
24
|
+
/**
|
|
25
|
+
* When provided, the value is exposed via the `align` style on the
|
|
26
|
+
* column's cells. Useful for right-aligned numeric columns.
|
|
27
|
+
*/
|
|
28
|
+
align?: "left" | "right" | "center";
|
|
29
|
+
/**
|
|
30
|
+
* When `true`, the column header renders a sort affordance and clicking
|
|
31
|
+
* (or pressing Enter / Space) cycles through ascending → descending →
|
|
32
|
+
* unsorted states. Defaults to `false`.
|
|
33
|
+
*/
|
|
34
|
+
sortable?: boolean;
|
|
35
|
+
/**
|
|
36
|
+
* Extracts a primitive comparable value from a row for sorting purposes.
|
|
37
|
+
* Used when the default ascending/descending behavior is sufficient.
|
|
38
|
+
* Mutually exclusive with `sortComparator` — if both are provided,
|
|
39
|
+
* `sortComparator` takes precedence.
|
|
40
|
+
*
|
|
41
|
+
* @example
|
|
42
|
+
* ```tsx
|
|
43
|
+
* sortValueAccessor: (row) => row.name.toLowerCase()
|
|
44
|
+
* ```
|
|
45
|
+
*/
|
|
46
|
+
sortValueAccessor?: (row: T) => string | number | boolean | null | undefined;
|
|
47
|
+
/**
|
|
48
|
+
* Custom comparator used for sorting. Receives two rows and the active
|
|
49
|
+
* sort direction. Return a negative number if `a` should come first, a
|
|
50
|
+
* positive number if `b` should come first, or `0` if they are equal.
|
|
51
|
+
* The table applies a stable fallback on `0` to preserve original order.
|
|
52
|
+
*
|
|
53
|
+
* @example
|
|
54
|
+
* ```tsx
|
|
55
|
+
* sortComparator: (a, b, dir) =>
|
|
56
|
+
* dir === "asc"
|
|
57
|
+
* ? a.createdAt - b.createdAt
|
|
58
|
+
* : b.createdAt - a.createdAt
|
|
59
|
+
* ```
|
|
60
|
+
*/
|
|
61
|
+
sortComparator?: (a: T, b: T, direction: SortDirection) => number;
|
|
62
|
+
/**
|
|
63
|
+
* The sort direction applied when this column is first activated.
|
|
64
|
+
* Defaults to `"asc"`.
|
|
65
|
+
*/
|
|
66
|
+
defaultSortDirection?: SortDirection;
|
|
67
|
+
}
|
|
68
|
+
export interface DataTablePersistedState {
|
|
69
|
+
/** column id → user-overridden width in pixels. */
|
|
70
|
+
widths: Record<string, number>;
|
|
71
|
+
/** column id → visibility flag. Missing keys count as visible. */
|
|
72
|
+
visibility: Record<string, boolean>;
|
|
73
|
+
}
|
|
74
|
+
export interface DataTableProps<T> {
|
|
75
|
+
/** Column definitions, in display order. */
|
|
76
|
+
columns: DataTableColumn<T>[];
|
|
77
|
+
/** Row data. */
|
|
78
|
+
rows: T[];
|
|
79
|
+
/**
|
|
80
|
+
* Stable identifier accessor — used as the React key for each row.
|
|
81
|
+
* Must be deterministic for the lifetime of the row.
|
|
82
|
+
*/
|
|
83
|
+
getRowKey: (row: T, index: number) => string;
|
|
84
|
+
/** Render this node when `rows` is empty. */
|
|
85
|
+
emptyState?: ReactNode;
|
|
86
|
+
/** Render this node when `loading` is `true`. */
|
|
87
|
+
loadingState?: ReactNode;
|
|
88
|
+
/** When `true`, the loading slot replaces the table body. */
|
|
89
|
+
loading?: boolean;
|
|
90
|
+
/**
|
|
91
|
+
* When provided, column widths and visibility settings are persisted
|
|
92
|
+
* to `localStorage` under this key. Use a stable, namespaced string
|
|
93
|
+
* (e.g. `"sessions.activeTab"`).
|
|
94
|
+
*/
|
|
95
|
+
persistKey?: string;
|
|
96
|
+
/** Extra class for the table's wrapping element. */
|
|
97
|
+
className?: string;
|
|
98
|
+
/** ARIA label for the table. Defaults to "Data table". */
|
|
99
|
+
ariaLabel?: string;
|
|
100
|
+
/** Test ID for testing harnesses. */
|
|
101
|
+
testId?: string;
|
|
102
|
+
/**
|
|
103
|
+
* Callback invoked when a row is clicked. When provided, rows render
|
|
104
|
+
* with a clickable affordance (cursor: pointer + keyboard binding).
|
|
105
|
+
*/
|
|
106
|
+
onRowClick?: (row: T) => void;
|
|
107
|
+
/**
|
|
108
|
+
* Controlled — the column currently being sorted. Pass `undefined` to
|
|
109
|
+
* indicate no active sort. When this prop is present, the component
|
|
110
|
+
* operates in controlled mode: the caller is responsible for updating
|
|
111
|
+
* the sort state via `onSortChange`.
|
|
112
|
+
*/
|
|
113
|
+
sortColumnId?: string;
|
|
114
|
+
/**
|
|
115
|
+
* Controlled — the direction of the active sort. Ignored when
|
|
116
|
+
* `sortColumnId` is `undefined`.
|
|
117
|
+
*/
|
|
118
|
+
sortDirection?: SortDirection;
|
|
119
|
+
/**
|
|
120
|
+
* Called when the user activates a sortable column header. In
|
|
121
|
+
* controlled mode the caller must propagate this back as
|
|
122
|
+
* `sortColumnId` / `sortDirection`. In uncontrolled mode this prop is
|
|
123
|
+
* purely observational.
|
|
124
|
+
*
|
|
125
|
+
* @param columnId The column being sorted, or `undefined` when the
|
|
126
|
+
* sort is cleared.
|
|
127
|
+
* @param direction The new direction.
|
|
128
|
+
*/
|
|
129
|
+
onSortChange?: (columnId: string | undefined, direction: SortDirection | undefined) => void;
|
|
130
|
+
}
|
|
131
|
+
declare function DataTableInner<T>({ columns, rows, getRowKey, emptyState, loadingState, loading, persistKey, className, ariaLabel, testId, onRowClick, sortColumnId: controlledSortColumnId, sortDirection: controlledSortDirection, onSortChange, }: DataTableProps<T>): import("react").JSX.Element;
|
|
132
|
+
export declare const DataTable: typeof DataTableInner;
|
|
133
|
+
export default DataTable;
|