@_linked/primitives 1.1.0 → 1.2.1
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/.gitattributes +1 -0
- package/.github/workflows/pr.yml +18 -0
- package/.github/workflows/publish.yml +16 -63
- package/CHANGELOG.md +61 -0
- package/README.md +62 -0
- package/lib/cjs/components/ConfirmDialog.d.ts +37 -0
- package/lib/cjs/components/ConfirmDialog.js +68 -0
- package/lib/cjs/components/ConfirmDialog.js.map +1 -0
- package/lib/cjs/components/ConfirmDialog.module.css +22 -0
- package/lib/cjs/components/ImageThumb.d.ts +17 -0
- package/lib/cjs/components/ImageThumb.js +90 -0
- package/lib/cjs/components/ImageThumb.js.map +1 -0
- package/lib/cjs/components/ImageThumb.module.css +134 -0
- package/lib/cjs/components/SkeletonLoader.d.ts +14 -0
- package/lib/cjs/components/SkeletonLoader.js +71 -0
- package/lib/cjs/components/SkeletonLoader.js.map +1 -0
- package/lib/cjs/components/SkeletonLoader.module.css +83 -0
- package/lib/cjs/components/Spinner.d.ts +22 -3
- package/lib/cjs/components/Spinner.js +55 -3
- package/lib/cjs/components/Spinner.js.map +1 -1
- package/lib/cjs/components/Spinner.module.css +57 -10
- package/lib/cjs/components/TruncatedText.d.ts +16 -0
- package/lib/cjs/components/TruncatedText.js +130 -0
- package/lib/cjs/components/TruncatedText.js.map +1 -0
- package/lib/cjs/components/TruncatedText.module.css +162 -0
- package/lib/cjs/hooks/useReducedMotion.d.ts +12 -0
- package/lib/cjs/hooks/useReducedMotion.js +35 -0
- package/lib/cjs/hooks/useReducedMotion.js.map +1 -0
- package/lib/cjs/index.d.ts +5 -0
- package/lib/cjs/index.js +21 -0
- package/lib/cjs/index.js.map +1 -1
- package/lib/cjs/motion.d.ts +219 -0
- package/lib/cjs/motion.js +154 -0
- package/lib/cjs/motion.js.map +1 -0
- package/lib/cjs/ontologies/primitives.d.ts +10 -1
- package/lib/cjs/ontologies/primitives.js +1 -1
- package/lib/cjs/ontologies/primitives.js.map +1 -1
- package/lib/cjs/package.json +12 -11
- package/lib/esm/components/ConfirmDialog.d.ts +37 -0
- package/lib/esm/components/ConfirmDialog.js +29 -0
- package/lib/esm/components/ConfirmDialog.js.map +1 -0
- package/lib/esm/components/ConfirmDialog.module.css +22 -0
- package/lib/esm/components/ImageThumb.d.ts +17 -0
- package/lib/esm/components/ImageThumb.js +50 -0
- package/lib/esm/components/ImageThumb.js.map +1 -0
- package/lib/esm/components/ImageThumb.module.css +134 -0
- package/lib/esm/components/SkeletonLoader.d.ts +14 -0
- package/lib/esm/components/SkeletonLoader.js +31 -0
- package/lib/esm/components/SkeletonLoader.js.map +1 -0
- package/lib/esm/components/SkeletonLoader.module.css +83 -0
- package/lib/esm/components/Spinner.d.ts +22 -3
- package/lib/esm/components/Spinner.js +22 -3
- package/lib/esm/components/Spinner.js.map +1 -1
- package/lib/esm/components/Spinner.module.css +57 -10
- package/lib/esm/components/TruncatedText.d.ts +16 -0
- package/lib/esm/components/TruncatedText.js +83 -0
- package/lib/esm/components/TruncatedText.js.map +1 -0
- package/lib/esm/components/TruncatedText.module.css +162 -0
- package/lib/esm/hooks/useReducedMotion.d.ts +12 -0
- package/lib/esm/hooks/useReducedMotion.js +32 -0
- package/lib/esm/hooks/useReducedMotion.js.map +1 -0
- package/lib/esm/index.d.ts +5 -0
- package/lib/esm/index.js +7 -0
- package/lib/esm/index.js.map +1 -1
- package/lib/esm/motion.d.ts +219 -0
- package/lib/esm/motion.js +154 -0
- package/lib/esm/motion.js.map +1 -0
- package/lib/esm/ontologies/primitives.d.ts +10 -1
- package/lib/esm/ontologies/primitives.js +3 -1
- package/lib/esm/ontologies/primitives.js.map +1 -1
- package/lib/esm/package.json +12 -11
- package/package.json +12 -11
- package/.github/workflows/changeset-check.yml +0 -44
- package/.github/workflows/ci.yml +0 -43
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
+
var ownKeys = function(o) {
|
|
20
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
+
var ar = [];
|
|
22
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
+
return ar;
|
|
24
|
+
};
|
|
25
|
+
return ownKeys(o);
|
|
26
|
+
};
|
|
27
|
+
return function (mod) {
|
|
28
|
+
if (mod && mod.__esModule) return mod;
|
|
29
|
+
var result = {};
|
|
30
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
+
__setModuleDefault(result, mod);
|
|
32
|
+
return result;
|
|
33
|
+
};
|
|
34
|
+
})();
|
|
35
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
36
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
37
|
+
};
|
|
38
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
39
|
+
exports.SkeletonLoader = SkeletonLoader;
|
|
40
|
+
exports.TableRowSkeleton = TableRowSkeleton;
|
|
41
|
+
const React = __importStar(require("react"));
|
|
42
|
+
const SkeletonLoader_module_css_1 = __importDefault(require("./SkeletonLoader.module.css"));
|
|
43
|
+
function SkeletonLoader({ width = '100%', height = 18, borderRadius = 4, className = '', lines = 1, animated = true, }) {
|
|
44
|
+
if (lines === 1) {
|
|
45
|
+
return (React.createElement("div", { className: `${SkeletonLoader_module_css_1.default.skeleton} ${animated ? SkeletonLoader_module_css_1.default.animated : ''} ${className}`, style: {
|
|
46
|
+
width,
|
|
47
|
+
height,
|
|
48
|
+
borderRadius,
|
|
49
|
+
} }));
|
|
50
|
+
}
|
|
51
|
+
return (React.createElement("div", { className: className }, Array.from({ length: lines }, (_, index) => (React.createElement("div", { key: index, className: `${SkeletonLoader_module_css_1.default.skeleton} ${animated ? SkeletonLoader_module_css_1.default.animated : ''} ${index < lines - 1 ? SkeletonLoader_module_css_1.default.marginBottom : ''}`, style: {
|
|
52
|
+
width: index === lines - 1 ? '60%' : '100%',
|
|
53
|
+
height,
|
|
54
|
+
borderRadius,
|
|
55
|
+
} })))));
|
|
56
|
+
}
|
|
57
|
+
// Table row skeleton component
|
|
58
|
+
function TableRowSkeleton({ columns = 5 }) {
|
|
59
|
+
return (React.createElement("tr", { className: SkeletonLoader_module_css_1.default.tableRow },
|
|
60
|
+
React.createElement("td", { className: SkeletonLoader_module_css_1.default.tableCell, style: { width: '48px' } },
|
|
61
|
+
React.createElement(SkeletonLoader, { width: 18, height: 18, borderRadius: 6 })),
|
|
62
|
+
Array.from({ length: columns }, (_, index) => (React.createElement("td", { key: index, className: SkeletonLoader_module_css_1.default.tableCell },
|
|
63
|
+
React.createElement(SkeletonLoader, { width: "18vw", height: 18 })))),
|
|
64
|
+
React.createElement("td", { className: SkeletonLoader_module_css_1.default.tableCell },
|
|
65
|
+
React.createElement("div", { className: SkeletonLoader_module_css_1.default.actionButtons },
|
|
66
|
+
React.createElement(SkeletonLoader, { width: 22, height: 18, borderRadius: 6 }),
|
|
67
|
+
React.createElement(SkeletonLoader, { width: 22, height: 18, borderRadius: 6 }),
|
|
68
|
+
React.createElement(SkeletonLoader, { width: 22, height: 18, borderRadius: 6 })))));
|
|
69
|
+
}
|
|
70
|
+
exports.default = SkeletonLoader;
|
|
71
|
+
//# sourceMappingURL=SkeletonLoader.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"SkeletonLoader.js","sourceRoot":"","sources":["../../../src/components/SkeletonLoader.tsx"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAYA,wCAoCC;AAGD,4CAoBC;AAvED,6CAA+B;AAC/B,4FAAgD;AAWhD,SAAgB,cAAc,CAAC,EAC7B,KAAK,GAAG,MAAM,EACd,MAAM,GAAG,EAAE,EACX,YAAY,GAAG,CAAC,EAChB,SAAS,GAAG,EAAE,EACd,KAAK,GAAG,CAAC,EACT,QAAQ,GAAG,IAAI,GACK;IACpB,IAAI,KAAK,KAAK,CAAC,EAAE,CAAC;QAChB,OAAO,CACL,6BACE,SAAS,EAAE,GAAG,mCAAK,CAAC,QAAQ,IAAI,QAAQ,CAAC,CAAC,CAAC,mCAAK,CAAC,QAAQ,CAAC,CAAC,CAAC,EAAE,IAAI,SAAS,EAAE,EAC7E,KAAK,EAAE;gBACL,KAAK;gBACL,MAAM;gBACN,YAAY;aACb,GACD,CACH,CAAC;IACJ,CAAC;IAED,OAAO,CACL,6BAAK,SAAS,EAAE,SAAS,IACtB,KAAK,CAAC,IAAI,CAAC,EAAE,MAAM,EAAE,KAAK,EAAE,EAAE,CAAC,CAAC,EAAE,KAAK,EAAE,EAAE,CAAC,CAC3C,6BACE,GAAG,EAAE,KAAK,EACV,SAAS,EAAE,GAAG,mCAAK,CAAC,QAAQ,IAAI,QAAQ,CAAC,CAAC,CAAC,mCAAK,CAAC,QAAQ,CAAC,CAAC,CAAC,EAAE,IAAI,KAAK,GAAG,KAAK,GAAG,CAAC,CAAC,CAAC,CAAC,mCAAK,CAAC,YAAY,CAAC,CAAC,CAAC,EAAE,EAAE,EAC/G,KAAK,EAAE;YACL,KAAK,EAAE,KAAK,KAAK,KAAK,GAAG,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,MAAM;YAC3C,MAAM;YACN,YAAY;SACb,GACD,CACH,CAAC,CACE,CACP,CAAC;AACJ,CAAC;AAED,+BAA+B;AAC/B,SAAgB,gBAAgB,CAAC,EAAE,OAAO,GAAG,CAAC,EAAwB;IACpE,OAAO,CACL,4BAAI,SAAS,EAAE,mCAAK,CAAC,QAAQ;QAC3B,4BAAI,SAAS,EAAE,mCAAK,CAAC,SAAS,EAAE,KAAK,EAAE,EAAE,KAAK,EAAE,MAAM,EAAE;YACtD,oBAAC,cAAc,IAAC,KAAK,EAAE,EAAE,EAAE,MAAM,EAAE,EAAE,EAAE,YAAY,EAAE,CAAC,GAAI,CACvD;QACJ,KAAK,CAAC,IAAI,CAAC,EAAE,MAAM,EAAE,OAAO,EAAE,EAAE,CAAC,CAAC,EAAE,KAAK,EAAE,EAAE,CAAC,CAC7C,4BAAI,GAAG,EAAE,KAAK,EAAE,SAAS,EAAE,mCAAK,CAAC,SAAS;YACxC,oBAAC,cAAc,IAAC,KAAK,EAAC,MAAM,EAAC,MAAM,EAAE,EAAE,GAAI,CACxC,CACN,CAAC;QACF,4BAAI,SAAS,EAAE,mCAAK,CAAC,SAAS;YAC5B,6BAAK,SAAS,EAAE,mCAAK,CAAC,aAAa;gBACjC,oBAAC,cAAc,IAAC,KAAK,EAAE,EAAE,EAAE,MAAM,EAAE,EAAE,EAAE,YAAY,EAAE,CAAC,GAAI;gBAC1D,oBAAC,cAAc,IAAC,KAAK,EAAE,EAAE,EAAE,MAAM,EAAE,EAAE,EAAE,YAAY,EAAE,CAAC,GAAI;gBAC1D,oBAAC,cAAc,IAAC,KAAK,EAAE,EAAE,EAAE,MAAM,EAAE,EAAE,EAAE,YAAY,EAAE,CAAC,GAAI,CACtD,CACH,CACF,CACN,CAAC;AACJ,CAAC;AAED,kBAAe,cAAc,CAAC"}
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
@import './helpers/mixins.css';
|
|
2
|
+
@import '@_linked/css/package.css';
|
|
3
|
+
|
|
4
|
+
/* ============================================================================
|
|
5
|
+
SkeletonLoader.module.css
|
|
6
|
+
|
|
7
|
+
Loading placeholder with shimmer animation.
|
|
8
|
+
Uses semantic tokens from theme.css.
|
|
9
|
+
============================================================================ */
|
|
10
|
+
|
|
11
|
+
/* === Base Skeleton === */
|
|
12
|
+
.skeleton {
|
|
13
|
+
background: linear-gradient(
|
|
14
|
+
90deg,
|
|
15
|
+
var(--skeleton-bg, var(--color-gray-100)) 25%,
|
|
16
|
+
var(--skeleton-highlight, var(--color-gray-200)) 50%,
|
|
17
|
+
var(--skeleton-bg, var(--color-gray-100)) 75%
|
|
18
|
+
);
|
|
19
|
+
background-size: 200% 100%;
|
|
20
|
+
animation: shimmer 1.5s infinite;
|
|
21
|
+
display: inline-block;
|
|
22
|
+
border-radius: var(--radius-selector, 4px);
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
/* === Animation Variant === */
|
|
26
|
+
.animated {
|
|
27
|
+
animation: shimmer 1.5s infinite;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
/* === Spacing === */
|
|
31
|
+
.marginBottom {
|
|
32
|
+
margin-bottom: 0.5rem;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
/* === Table Row Skeleton === */
|
|
36
|
+
.tableRow {
|
|
37
|
+
border-bottom: 1px solid var(--skeleton-row-border, var(--table-row-border));
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
/* === Table Cell Skeleton === */
|
|
41
|
+
.tableCell {
|
|
42
|
+
padding: var(--skeleton-row-padding-y, var(--surface-gap)) var(--skeleton-row-padding-x, var(--space-sm));
|
|
43
|
+
vertical-align: middle;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
/* === Action Buttons Container === */
|
|
47
|
+
.actionButtons {
|
|
48
|
+
display: flex;
|
|
49
|
+
gap: var(--space-sm);
|
|
50
|
+
align-items: center;
|
|
51
|
+
justify-content: flex-end;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
/* ============================================================================
|
|
55
|
+
Dark Mode
|
|
56
|
+
============================================================================ */
|
|
57
|
+
|
|
58
|
+
[data-theme='dark'] .skeleton {
|
|
59
|
+
background: linear-gradient(
|
|
60
|
+
90deg,
|
|
61
|
+
var(--skeleton-bg, var(--color-gray-800)) 25%,
|
|
62
|
+
var(--skeleton-highlight, var(--color-gray-700)) 50%,
|
|
63
|
+
var(--skeleton-bg, var(--color-gray-800)) 75%
|
|
64
|
+
);
|
|
65
|
+
background-size: 200% 100%;
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
[data-theme='dark'] .tableRow {
|
|
69
|
+
border-bottom-color: var(--skeleton-row-border, var(--table-row-border));
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
/* ============================================================================
|
|
73
|
+
Shimmer Animation
|
|
74
|
+
============================================================================ */
|
|
75
|
+
|
|
76
|
+
@keyframes shimmer {
|
|
77
|
+
0% {
|
|
78
|
+
background-position: -200% 0;
|
|
79
|
+
}
|
|
80
|
+
100% {
|
|
81
|
+
background-position: 200% 0;
|
|
82
|
+
}
|
|
83
|
+
}
|
|
@@ -1,4 +1,23 @@
|
|
|
1
|
-
import React from 'react';
|
|
2
|
-
export
|
|
1
|
+
import * as React from 'react';
|
|
2
|
+
export interface SpinnerProps {
|
|
3
|
+
/** Render nothing when false. */
|
|
3
4
|
active?: boolean;
|
|
4
|
-
|
|
5
|
+
size?: 'small' | 'medium' | 'large' | 'xlarge';
|
|
6
|
+
className?: string;
|
|
7
|
+
/** Announced to assistive technology. */
|
|
8
|
+
label?: string;
|
|
9
|
+
}
|
|
10
|
+
/**
|
|
11
|
+
* A loading indicator: a ring that inherits its colour, so it reads on any background.
|
|
12
|
+
*
|
|
13
|
+
* Two things it does that a bare CSS spin does not. It honours
|
|
14
|
+
* `prefers-reduced-motion` — a spinner is the most common thing to make someone with
|
|
15
|
+
* vestibular sensitivity look away — showing a still ring rather than nothing, so the
|
|
16
|
+
* "busy" signal survives. And it renders **nothing** when inactive, so it can be dropped
|
|
17
|
+
* into a scroll sentinel or a button without reserving space it is not using.
|
|
18
|
+
*
|
|
19
|
+
* The ring is an inner element rather than a border on the container. A border on the
|
|
20
|
+
* container is distorted the moment a flex parent stretches it; an explicitly sized inner
|
|
21
|
+
* element stays circular.
|
|
22
|
+
*/
|
|
23
|
+
export declare function Spinner({ active, size, className, label, }: SpinnerProps): React.JSX.Element;
|
|
@@ -1,12 +1,64 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
+
var ownKeys = function(o) {
|
|
20
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
+
var ar = [];
|
|
22
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
+
return ar;
|
|
24
|
+
};
|
|
25
|
+
return ownKeys(o);
|
|
26
|
+
};
|
|
27
|
+
return function (mod) {
|
|
28
|
+
if (mod && mod.__esModule) return mod;
|
|
29
|
+
var result = {};
|
|
30
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
+
__setModuleDefault(result, mod);
|
|
32
|
+
return result;
|
|
33
|
+
};
|
|
34
|
+
})();
|
|
2
35
|
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
36
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
37
|
};
|
|
5
38
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
39
|
exports.Spinner = Spinner;
|
|
7
|
-
const
|
|
40
|
+
const React = __importStar(require("react"));
|
|
8
41
|
const Spinner_module_css_1 = __importDefault(require("./Spinner.module.css"));
|
|
9
|
-
|
|
10
|
-
|
|
42
|
+
const ClassNames_1 = require("@_linked/react/utils/ClassNames");
|
|
43
|
+
const useReducedMotion_js_1 = require("../hooks/useReducedMotion.js");
|
|
44
|
+
/**
|
|
45
|
+
* A loading indicator: a ring that inherits its colour, so it reads on any background.
|
|
46
|
+
*
|
|
47
|
+
* Two things it does that a bare CSS spin does not. It honours
|
|
48
|
+
* `prefers-reduced-motion` — a spinner is the most common thing to make someone with
|
|
49
|
+
* vestibular sensitivity look away — showing a still ring rather than nothing, so the
|
|
50
|
+
* "busy" signal survives. And it renders **nothing** when inactive, so it can be dropped
|
|
51
|
+
* into a scroll sentinel or a button without reserving space it is not using.
|
|
52
|
+
*
|
|
53
|
+
* The ring is an inner element rather than a border on the container. A border on the
|
|
54
|
+
* container is distorted the moment a flex parent stretches it; an explicitly sized inner
|
|
55
|
+
* element stays circular.
|
|
56
|
+
*/
|
|
57
|
+
function Spinner({ active = true, size = 'small', className, label = 'Loading', }) {
|
|
58
|
+
const reducedMotion = (0, useReducedMotion_js_1.useReducedMotion)();
|
|
59
|
+
if (!active)
|
|
60
|
+
return null;
|
|
61
|
+
return (React.createElement("div", { className: (0, ClassNames_1.cl)(Spinner_module_css_1.default.spinner, Spinner_module_css_1.default[size], className), role: "progressbar", "aria-busy": "true", "aria-label": label },
|
|
62
|
+
React.createElement("span", { className: (0, ClassNames_1.cl)(Spinner_module_css_1.default.ring, reducedMotion && Spinner_module_css_1.default.reducedMotion), "aria-hidden": "true" })));
|
|
11
63
|
}
|
|
12
64
|
//# sourceMappingURL=Spinner.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Spinner.js","sourceRoot":"","sources":["../../../src/components/Spinner.tsx"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"Spinner.js","sourceRoot":"","sources":["../../../src/components/Spinner.tsx"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AA2BA,0BAuBC;AAlDD,6CAA+B;AAC/B,8EAAyC;AACzC,gEAAmD;AACnD,sEAA8D;AAW9D;;;;;;;;;;;;GAYG;AACH,SAAgB,OAAO,CAAC,EACtB,MAAM,GAAG,IAAI,EACb,IAAI,GAAG,OAAO,EACd,SAAS,EACT,KAAK,GAAG,SAAS,GACJ;IACb,MAAM,aAAa,GAAG,IAAA,sCAAgB,GAAE,CAAC;IAEzC,IAAI,CAAC,MAAM;QAAE,OAAO,IAAI,CAAC;IAEzB,OAAO,CACL,6BACE,SAAS,EAAE,IAAA,eAAE,EAAC,4BAAK,CAAC,OAAO,EAAE,4BAAK,CAAC,IAAI,CAAC,EAAE,SAAS,CAAC,EACpD,IAAI,EAAC,aAAa,eACR,MAAM,gBACJ,KAAK;QAEjB,8BACE,SAAS,EAAE,IAAA,eAAE,EAAC,4BAAK,CAAC,IAAI,EAAE,aAAa,IAAI,4BAAK,CAAC,aAAa,CAAC,iBACnD,MAAM,GAClB,CACE,CACP,CAAC;AACJ,CAAC"}
|
|
@@ -2,20 +2,67 @@
|
|
|
2
2
|
@import '@_linked/css/package.css';
|
|
3
3
|
|
|
4
4
|
.spinner {
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
5
|
+
display: inline-flex;
|
|
6
|
+
/* Never grow or shrink in a flex parent — that would distort the ring. */
|
|
7
|
+
flex: 0 0 auto;
|
|
8
|
+
align-items: center;
|
|
9
|
+
justify-content: center;
|
|
10
|
+
color: var(--spinner-indicator-color, var(--meter-indicator-bg, currentColor));
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
/* Sized explicitly rather than filling the container, so the ring stays a circle even when
|
|
14
|
+
a flex parent stretches the box around it. */
|
|
15
|
+
.ring {
|
|
16
|
+
box-sizing: border-box;
|
|
17
|
+
flex: 0 0 auto;
|
|
9
18
|
width: var(--spinner-size, --spacing(4));
|
|
10
19
|
height: var(--spinner-size, --spacing(4));
|
|
11
|
-
|
|
20
|
+
border-radius: 50%;
|
|
21
|
+
border: var(--spinner-border-width, 2px) solid currentColor;
|
|
22
|
+
border-top-color: var(--spinner-track-color, transparent);
|
|
23
|
+
opacity: 0.85;
|
|
24
|
+
animation: spinnerRotate var(--spinner-animation-duration, 0.7s) linear infinite;
|
|
12
25
|
}
|
|
13
26
|
|
|
14
|
-
@keyframes
|
|
15
|
-
|
|
16
|
-
transform: rotate(0deg);
|
|
17
|
-
}
|
|
18
|
-
100% {
|
|
27
|
+
@keyframes spinnerRotate {
|
|
28
|
+
to {
|
|
19
29
|
transform: rotate(360deg);
|
|
20
30
|
}
|
|
21
31
|
}
|
|
32
|
+
|
|
33
|
+
/* Size variants. Each sets `--spinner-size`, so a consumer that sets the variable directly
|
|
34
|
+
still wins — the variants are a shorthand for it, not a replacement. */
|
|
35
|
+
.small {
|
|
36
|
+
--spinner-size: --spacing(4);
|
|
37
|
+
}
|
|
38
|
+
.medium {
|
|
39
|
+
--spinner-size: --spacing(6);
|
|
40
|
+
}
|
|
41
|
+
.large {
|
|
42
|
+
--spinner-size: --spacing(8);
|
|
43
|
+
--spinner-border-width: 3px;
|
|
44
|
+
}
|
|
45
|
+
.xlarge {
|
|
46
|
+
--spinner-size: --spacing(12);
|
|
47
|
+
--spinner-border-width: 3px;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
.small,
|
|
51
|
+
.medium,
|
|
52
|
+
.large,
|
|
53
|
+
.xlarge {
|
|
54
|
+
width: var(--spinner-size);
|
|
55
|
+
height: var(--spinner-size);
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
/* Reduced motion: freeze the ring, keep it visible. Removing it entirely would remove the
|
|
59
|
+
only signal that something is loading. */
|
|
60
|
+
.reducedMotion {
|
|
61
|
+
animation: none;
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
@media (prefers-reduced-motion: reduce) {
|
|
65
|
+
.ring {
|
|
66
|
+
animation: none;
|
|
67
|
+
}
|
|
68
|
+
}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
interface TruncatedTextProps {
|
|
3
|
+
/** The full text content */
|
|
4
|
+
text: string;
|
|
5
|
+
/** Maximum number of characters to show before truncating (default: 80) */
|
|
6
|
+
maxLength?: number;
|
|
7
|
+
}
|
|
8
|
+
/**
|
|
9
|
+
* TruncatedText - Displays truncated text with hover/tap to show full content
|
|
10
|
+
*
|
|
11
|
+
* For long text fields, shows first N characters with ellipsis.
|
|
12
|
+
* On desktop: hover displays full text in a popover with copy button.
|
|
13
|
+
* On mobile: tap opens a dialog with full text and copy button.
|
|
14
|
+
*/
|
|
15
|
+
declare function TruncatedText({ text, maxLength }: TruncatedTextProps): React.JSX.Element;
|
|
16
|
+
export { TruncatedText };
|
|
@@ -0,0 +1,130 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
+
var ownKeys = function(o) {
|
|
20
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
+
var ar = [];
|
|
22
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
+
return ar;
|
|
24
|
+
};
|
|
25
|
+
return ownKeys(o);
|
|
26
|
+
};
|
|
27
|
+
return function (mod) {
|
|
28
|
+
if (mod && mod.__esModule) return mod;
|
|
29
|
+
var result = {};
|
|
30
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
+
__setModuleDefault(result, mod);
|
|
32
|
+
return result;
|
|
33
|
+
};
|
|
34
|
+
})();
|
|
35
|
+
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
36
|
+
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
37
|
+
return new (P || (P = Promise))(function (resolve, reject) {
|
|
38
|
+
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
39
|
+
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
40
|
+
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
41
|
+
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
42
|
+
});
|
|
43
|
+
};
|
|
44
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
45
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
46
|
+
};
|
|
47
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
48
|
+
exports.TruncatedText = TruncatedText;
|
|
49
|
+
const Dialog_js_1 = require("./Dialog.js");
|
|
50
|
+
const HoverCard_js_1 = require("./HoverCard.js");
|
|
51
|
+
const IconButton_js_1 = require("./IconButton.js");
|
|
52
|
+
const react_1 = __importStar(require("react"));
|
|
53
|
+
const TruncatedText_module_css_1 = __importDefault(require("./TruncatedText.module.css"));
|
|
54
|
+
/**
|
|
55
|
+
* Two inline glyphs rather than a dependency on an icon set.
|
|
56
|
+
*
|
|
57
|
+
* This component needs exactly two, and a library whose contract is "a behaviour source plus
|
|
58
|
+
* a stylesheet" should not make every consumer install an icon package to draw a tick. They
|
|
59
|
+
* inherit `currentColor`, so they follow the button they sit in.
|
|
60
|
+
*/
|
|
61
|
+
const CheckGlyph = () => (react_1.default.createElement("svg", { width: "14", height: "14", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", "aria-hidden": "true" },
|
|
62
|
+
react_1.default.createElement("polyline", { points: "20 6 9 17 4 12" })));
|
|
63
|
+
const CopyGlyph = () => (react_1.default.createElement("svg", { width: "14", height: "14", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", "aria-hidden": "true" },
|
|
64
|
+
react_1.default.createElement("rect", { x: "9", y: "9", width: "13", height: "13", rx: "2", ry: "2" }),
|
|
65
|
+
react_1.default.createElement("path", { d: "M5 15H4a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h9a2 2 0 0 1 2 2v1" })));
|
|
66
|
+
/**
|
|
67
|
+
* TruncatedText - Displays truncated text with hover/tap to show full content
|
|
68
|
+
*
|
|
69
|
+
* For long text fields, shows first N characters with ellipsis.
|
|
70
|
+
* On desktop: hover displays full text in a popover with copy button.
|
|
71
|
+
* On mobile: tap opens a dialog with full text and copy button.
|
|
72
|
+
*/
|
|
73
|
+
function TruncatedText({ text, maxLength = 80 }) {
|
|
74
|
+
const [copied, setCopied] = (0, react_1.useState)(false);
|
|
75
|
+
const [isMobile, setIsMobile] = (0, react_1.useState)(false);
|
|
76
|
+
(0, react_1.useEffect)(() => {
|
|
77
|
+
// Check for touch device or small screen
|
|
78
|
+
const checkMobile = () => {
|
|
79
|
+
const hasTouchScreen = 'ontouchstart' in window || navigator.maxTouchPoints > 0;
|
|
80
|
+
const isSmallScreen = window.matchMedia('(max-width: 768px)').matches;
|
|
81
|
+
setIsMobile(hasTouchScreen || isSmallScreen);
|
|
82
|
+
};
|
|
83
|
+
checkMobile();
|
|
84
|
+
window.addEventListener('resize', checkMobile);
|
|
85
|
+
return () => window.removeEventListener('resize', checkMobile);
|
|
86
|
+
}, []);
|
|
87
|
+
// If text is short enough, just render it directly
|
|
88
|
+
if (!text || text.length <= maxLength) {
|
|
89
|
+
return react_1.default.createElement("span", null, text || '-');
|
|
90
|
+
}
|
|
91
|
+
const truncatedText = text.slice(0, maxLength) + '...';
|
|
92
|
+
const handleCopy = (e) => __awaiter(this, void 0, void 0, function* () {
|
|
93
|
+
e.stopPropagation();
|
|
94
|
+
try {
|
|
95
|
+
yield navigator.clipboard.writeText(text);
|
|
96
|
+
setCopied(true);
|
|
97
|
+
setTimeout(() => setCopied(false), 2000);
|
|
98
|
+
}
|
|
99
|
+
catch (err) {
|
|
100
|
+
console.error('Failed to copy text:', err);
|
|
101
|
+
}
|
|
102
|
+
});
|
|
103
|
+
// Mobile: Use Dialog triggered by tap
|
|
104
|
+
if (isMobile) {
|
|
105
|
+
return (react_1.default.createElement(Dialog_js_1.Dialog.Root, null,
|
|
106
|
+
react_1.default.createElement(Dialog_js_1.Dialog.Trigger, { asChild: true },
|
|
107
|
+
react_1.default.createElement("span", { className: TruncatedText_module_css_1.default.truncatedText }, truncatedText)),
|
|
108
|
+
react_1.default.createElement(Dialog_js_1.Dialog.Content, { className: TruncatedText_module_css_1.default.dialogContent },
|
|
109
|
+
react_1.default.createElement(Dialog_js_1.Dialog.Header, null,
|
|
110
|
+
react_1.default.createElement(Dialog_js_1.Dialog.Title, null, "Full Text")),
|
|
111
|
+
react_1.default.createElement("div", { className: TruncatedText_module_css_1.default.dialogBody },
|
|
112
|
+
react_1.default.createElement("div", { className: TruncatedText_module_css_1.default.scrollArea },
|
|
113
|
+
react_1.default.createElement("p", { className: TruncatedText_module_css_1.default.fullText }, text))),
|
|
114
|
+
react_1.default.createElement("div", { className: TruncatedText_module_css_1.default.dialogFooter },
|
|
115
|
+
react_1.default.createElement(IconButton_js_1.IconButton, { size: "small", variant: "ghost", className: TruncatedText_module_css_1.default.copyButton, onClick: handleCopy, "aria-label": copied ? 'Copied!' : 'Copy to clipboard' }, copied ? (react_1.default.createElement(CheckGlyph, null)) : (react_1.default.createElement(CopyGlyph, null)))))));
|
|
116
|
+
}
|
|
117
|
+
// Desktop: Use HoverCard triggered by hover
|
|
118
|
+
return (react_1.default.createElement(HoverCard_js_1.HoverCard.Root, { openDelay: 300, closeDelay: 200 },
|
|
119
|
+
react_1.default.createElement(HoverCard_js_1.HoverCard.Trigger, { asChild: true },
|
|
120
|
+
react_1.default.createElement("span", { className: TruncatedText_module_css_1.default.truncatedText }, truncatedText)),
|
|
121
|
+
react_1.default.createElement(HoverCard_js_1.HoverCard.Portal, null,
|
|
122
|
+
react_1.default.createElement(HoverCard_js_1.HoverCard.Content, { side: "top", align: "start", sideOffset: 8, className: TruncatedText_module_css_1.default.hoverContent },
|
|
123
|
+
react_1.default.createElement("div", { className: TruncatedText_module_css_1.default.contentWrapper },
|
|
124
|
+
react_1.default.createElement("div", { className: TruncatedText_module_css_1.default.scrollArea },
|
|
125
|
+
react_1.default.createElement("p", { className: TruncatedText_module_css_1.default.fullText }, text)),
|
|
126
|
+
react_1.default.createElement("div", { className: TruncatedText_module_css_1.default.copyButtonWrapper },
|
|
127
|
+
react_1.default.createElement(IconButton_js_1.IconButton, { size: "small", variant: "ghost", className: TruncatedText_module_css_1.default.copyButton, onClick: handleCopy, "aria-label": copied ? 'Copied!' : 'Copy to clipboard' }, copied ? (react_1.default.createElement(CheckGlyph, null)) : (react_1.default.createElement(CopyGlyph, null))))),
|
|
128
|
+
react_1.default.createElement(HoverCard_js_1.HoverCard.Arrow, { className: TruncatedText_module_css_1.default.arrow })))));
|
|
129
|
+
}
|
|
130
|
+
//# sourceMappingURL=TruncatedText.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"TruncatedText.js","sourceRoot":"","sources":["../../../src/components/TruncatedText.tsx"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,162 @@
|
|
|
1
|
+
@import './helpers/mixins.css';
|
|
2
|
+
@import '@_linked/css/package.css';
|
|
3
|
+
|
|
4
|
+
/* ============================================================================
|
|
5
|
+
TruncatedText.module.css
|
|
6
|
+
|
|
7
|
+
Truncated text component with hover popover for full content.
|
|
8
|
+
Uses semantic tokens from theme.css.
|
|
9
|
+
============================================================================ */
|
|
10
|
+
|
|
11
|
+
/* === Truncated Text Trigger === */
|
|
12
|
+
.truncatedText {
|
|
13
|
+
cursor: help;
|
|
14
|
+
border-bottom: 1px dotted var(--truncated-text-gray-400, var(--color-gray-400));
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
/* === Hover Card Content === */
|
|
18
|
+
.hoverContent {
|
|
19
|
+
background-color: var(--surface-bg);
|
|
20
|
+
border: 1px solid var(--surface-border);
|
|
21
|
+
border-radius: var(--radius-field);
|
|
22
|
+
box-shadow: var(--surface-shadow);
|
|
23
|
+
padding: var(--space-sm);
|
|
24
|
+
max-width: 400px;
|
|
25
|
+
min-width: 200px;
|
|
26
|
+
z-index: 1000;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
/* === Content Wrapper === */
|
|
30
|
+
.contentWrapper {
|
|
31
|
+
display: flex;
|
|
32
|
+
flex-direction: column;
|
|
33
|
+
gap: var(--space-xs);
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
/* === Scroll Area === */
|
|
37
|
+
.scrollArea {
|
|
38
|
+
max-height: 150px;
|
|
39
|
+
overflow-y: auto;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
/* === Full Text === */
|
|
43
|
+
.fullText {
|
|
44
|
+
font-size: var(--typography-small-size);
|
|
45
|
+
color: var(--text-primary);
|
|
46
|
+
line-height: 1.5;
|
|
47
|
+
margin: 0;
|
|
48
|
+
white-space: pre-wrap;
|
|
49
|
+
word-break: break-word;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
/* === Copy Button Wrapper === */
|
|
53
|
+
.copyButtonWrapper {
|
|
54
|
+
display: flex;
|
|
55
|
+
justify-content: flex-end;
|
|
56
|
+
border-top: 1px solid var(--surface-border);
|
|
57
|
+
padding-top: var(--space-xs);
|
|
58
|
+
margin-top: var(--space-xs);
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
/* === Copy Button === */
|
|
62
|
+
.copyButton {
|
|
63
|
+
color: var(--truncated-text-tertiary-500, var(--color-tertiary-500)) !important;
|
|
64
|
+
padding: var(--space-xs) !important;
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
.copyButton:hover {
|
|
68
|
+
color: var(--truncated-text-tertiary-600, var(--color-tertiary-600)) !important;
|
|
69
|
+
background-color: color-mix(
|
|
70
|
+
in srgb,
|
|
71
|
+
var(--truncated-text-tertiary-500, var(--color-tertiary-500)) 12%,
|
|
72
|
+
transparent
|
|
73
|
+
) !important;
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
/* === Arrow === */
|
|
77
|
+
.arrow {
|
|
78
|
+
fill: var(--surface-bg);
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
/* ============================================================================
|
|
82
|
+
Mobile Dialog Styles
|
|
83
|
+
============================================================================ */
|
|
84
|
+
|
|
85
|
+
.dialogContent {
|
|
86
|
+
max-width: 90vw;
|
|
87
|
+
width: 400px;
|
|
88
|
+
background-color: var(--surface-bg);
|
|
89
|
+
border: 1px solid var(--surface-border);
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
.dialogBody {
|
|
93
|
+
padding: var(--space-sm) 0;
|
|
94
|
+
color: var(--text-primary);
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
.dialogFooter {
|
|
98
|
+
display: flex;
|
|
99
|
+
justify-content: flex-end;
|
|
100
|
+
align-items: center;
|
|
101
|
+
padding-top: var(--space-xs);
|
|
102
|
+
border-top: 1px solid var(--surface-border);
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
/* ============================================================================
|
|
106
|
+
Dark Mode
|
|
107
|
+
============================================================================ */
|
|
108
|
+
|
|
109
|
+
[data-theme='dark'] .truncatedText {
|
|
110
|
+
border-bottom-color: var(--truncated-text-gray-500, var(--color-gray-500));
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
[data-theme='dark'] .hoverContent {
|
|
114
|
+
background-color: var(--surface-bg);
|
|
115
|
+
border-color: var(--surface-border);
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
/* .fullText uses --text-primary which auto-adjusts for dark mode */
|
|
119
|
+
|
|
120
|
+
[data-theme='dark'] .copyButtonWrapper {
|
|
121
|
+
border-top-color: var(--surface-border);
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
[data-theme='dark'] .copyButton {
|
|
125
|
+
color: var(--truncated-text-tertiary-400, var(--color-tertiary-400)) !important;
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
[data-theme='dark'] .copyButton:hover {
|
|
129
|
+
color: var(--truncated-text-tertiary-300, var(--color-tertiary-300)) !important;
|
|
130
|
+
background-color: color-mix(
|
|
131
|
+
in srgb,
|
|
132
|
+
var(--truncated-text-tertiary-500, var(--color-tertiary-500)) 15%,
|
|
133
|
+
transparent
|
|
134
|
+
) !important;
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
[data-theme='dark'] .arrow {
|
|
138
|
+
fill: var(--surface-bg);
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
[data-theme='dark'] .dialogContent {
|
|
142
|
+
background-color: var(--surface-bg);
|
|
143
|
+
border-color: var(--surface-border);
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
/* .dialogBody uses --text-primary which auto-adjusts for dark mode */
|
|
147
|
+
|
|
148
|
+
[data-theme='dark'] .dialogFooter {
|
|
149
|
+
border-top-color: var(--surface-border);
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
/* Dialog close button in dark mode */
|
|
153
|
+
[data-theme='dark'] .dialogContent button[aria-label="Close"],
|
|
154
|
+
[data-theme='dark'] .dialogContent [class*="Close"] {
|
|
155
|
+
color: var(--truncated-text-gray-400, var(--color-gray-400));
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
[data-theme='dark'] .dialogContent button[aria-label="Close"]:hover,
|
|
159
|
+
[data-theme='dark'] .dialogContent [class*="Close"]:hover {
|
|
160
|
+
color: var(--truncated-text-gray-200, var(--color-gray-200));
|
|
161
|
+
background-color: var(--truncated-text-gray-700, var(--color-gray-700));
|
|
162
|
+
}
|