jvetrau-ds 0.1.31 → 0.1.32
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/components/attach/attach.cjs +21 -4
- package/components/attach/attach.cjs.map +1 -1
- package/components/attach/attach.css +46 -8
- package/components/attach/attach.d.cts +3 -1
- package/components/attach/attach.d.ts +3 -1
- package/components/attach/attach.js +21 -4
- package/components/attach/attach.js.map +1 -1
- package/package.json +1 -1
- package/styles.css +46 -8
|
@@ -7,6 +7,9 @@ var classnames = require('../helpers/classnames');
|
|
|
7
7
|
function isImageAttach(item) {
|
|
8
8
|
return item.mimeType?.startsWith("image/") ?? false;
|
|
9
9
|
}
|
|
10
|
+
function isLinkAttach(item) {
|
|
11
|
+
return item.kind === "link";
|
|
12
|
+
}
|
|
10
13
|
function formatFileSize(sizeBytes) {
|
|
11
14
|
if (sizeBytes === void 0) {
|
|
12
15
|
return "Size unknown";
|
|
@@ -19,6 +22,13 @@ function formatFileSize(sizeBytes) {
|
|
|
19
22
|
}
|
|
20
23
|
return `${(sizeBytes / 1024 / 1024).toFixed(1)} MB`;
|
|
21
24
|
}
|
|
25
|
+
function getLinkHostname(url) {
|
|
26
|
+
try {
|
|
27
|
+
return new URL(url).hostname.replace(/^www\./u, "");
|
|
28
|
+
} catch {
|
|
29
|
+
return url;
|
|
30
|
+
}
|
|
31
|
+
}
|
|
22
32
|
const Attach = ({
|
|
23
33
|
items,
|
|
24
34
|
onRemove,
|
|
@@ -37,11 +47,18 @@ const Attach = ({
|
|
|
37
47
|
className: classes,
|
|
38
48
|
...props,
|
|
39
49
|
children: /* @__PURE__ */ jsxRuntime.jsx("ul", { className: "attach__list", children: items.map((item) => {
|
|
40
|
-
const
|
|
50
|
+
const isLink = isLinkAttach(item);
|
|
51
|
+
const isImage = !isLink && isImageAttach(item);
|
|
52
|
+
const itemClasses = classnames.classnames("attach__item", {
|
|
53
|
+
"attach__item--link": isLink,
|
|
54
|
+
"attach__item--image": isImage,
|
|
55
|
+
"attach__item--file": !isLink && !isImage
|
|
56
|
+
});
|
|
57
|
+
const meta = isLink ? getLinkHostname(item.url) : formatFileSize(item.sizeBytes);
|
|
41
58
|
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
42
59
|
"li",
|
|
43
60
|
{
|
|
44
|
-
className:
|
|
61
|
+
className: itemClasses,
|
|
45
62
|
children: [
|
|
46
63
|
/* @__PURE__ */ jsxRuntime.jsx(
|
|
47
64
|
"a",
|
|
@@ -59,7 +76,7 @@ const Attach = ({
|
|
|
59
76
|
}
|
|
60
77
|
) : /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "attach__file", children: [
|
|
61
78
|
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "attach__name", children: item.name }),
|
|
62
|
-
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "
|
|
79
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "attach__meta", children: meta })
|
|
63
80
|
] })
|
|
64
81
|
}
|
|
65
82
|
),
|
|
@@ -68,7 +85,7 @@ const Attach = ({
|
|
|
68
85
|
{
|
|
69
86
|
className: "attach__remove",
|
|
70
87
|
type: "button",
|
|
71
|
-
"aria-label": `${removeLabel}
|
|
88
|
+
"aria-label": `${removeLabel}: ${item.name}`,
|
|
72
89
|
onClick: () => onRemove(item.id),
|
|
73
90
|
children: removeLabel
|
|
74
91
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../src/components/attach/attach.tsx"],"names":["classnames","jsx","jsxs"],"mappings":";;;;;;
|
|
1
|
+
{"version":3,"sources":["../../../src/components/attach/attach.tsx"],"names":["classnames","jsx","jsxs"],"mappings":"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","file":"attach.cjs","sourcesContent":["import React from 'react';\nimport './attach.css';\nimport { classnames } from '../helpers/classnames';\n\nexport type AttachItemKind = 'file' | 'link';\n\nexport interface AttachItem {\n id: string;\n name: string;\n url: string;\n kind?: AttachItemKind;\n mimeType?: string;\n sizeBytes?: number;\n}\n\nexport interface AttachProps\n extends React.HTMLAttributes<HTMLDivElement> {\n items: AttachItem[];\n onRemove?: (id: string) => void;\n removeLabel?: string;\n emptyLabel?: string;\n}\n\nfunction isImageAttach(item: AttachItem) {\n return item.mimeType?.startsWith('image/') ?? false;\n}\n\nfunction isLinkAttach(item: AttachItem) {\n return item.kind === 'link';\n}\n\nfunction formatFileSize(sizeBytes?: number) {\n if (sizeBytes === undefined) {\n return 'Size unknown';\n }\n\n if (sizeBytes < 1024) {\n return `${sizeBytes} B`;\n }\n\n if (sizeBytes < 1024 * 1024) {\n return `${Math.round(sizeBytes / 1024)} KB`;\n }\n\n return `${(sizeBytes / 1024 / 1024).toFixed(1)} MB`;\n}\n\nfunction getLinkHostname(url: string) {\n try {\n return new URL(url).hostname.replace(/^www\\./u, '');\n } catch {\n return url;\n }\n}\n\nconst Attach: React.FC<AttachProps> = ({\n items,\n onRemove,\n removeLabel = 'Удалить',\n emptyLabel,\n className = '',\n ...props\n}) => {\n if (items.length === 0) {\n return null;\n }\n\n const classes = classnames('attach', className, {});\n\n return (\n <div\n className={classes}\n {...props}\n >\n <ul className=\"attach__list\">\n {items.map((item) => {\n const isLink = isLinkAttach(item);\n const isImage = !isLink && isImageAttach(item);\n\n const itemClasses = classnames('attach__item', {\n 'attach__item--link': isLink,\n 'attach__item--image': isImage,\n 'attach__item--file': !isLink && !isImage,\n });\n\n const meta = isLink\n ? getLinkHostname(item.url)\n : formatFileSize(item.sizeBytes);\n\n return (\n <li\n key={item.id}\n className={itemClasses}\n >\n <a\n className=\"attach__link\"\n href={item.url}\n target=\"_blank\"\n rel=\"noreferrer\"\n >\n {isImage ? (\n <img\n className=\"attach__preview\"\n src={item.url}\n alt={item.name}\n />\n ) : (\n <span className=\"attach__file\">\n <span className=\"attach__name\">\n {item.name}\n </span>\n\n <span className=\"attach__meta\">\n {meta}\n </span>\n </span>\n )}\n </a>\n\n {onRemove && (\n <button\n className=\"attach__remove\"\n type=\"button\"\n aria-label={`${removeLabel}: ${item.name}`}\n onClick={() => onRemove(item.id)}\n >\n {removeLabel}\n </button>\n )}\n </li>\n );\n })}\n </ul>\n </div>\n );\n};\n\nexport default Attach;"]}
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
--attachment-color: var(--color-text);
|
|
4
4
|
--attachment-item-bg: var(--color-control);
|
|
5
5
|
--attachment-border-color: var(--color-line);
|
|
6
|
-
--attachment-
|
|
6
|
+
--attachment-meta-color: var(--color-text-note);
|
|
7
7
|
|
|
8
8
|
color: var(--attachment-color);
|
|
9
9
|
|
|
@@ -65,20 +65,31 @@
|
|
|
65
65
|
solid
|
|
66
66
|
var(--attachment-border-color);
|
|
67
67
|
border-radius: var(--attachment-radius);
|
|
68
|
+
|
|
69
|
+
/* depth */
|
|
70
|
+
|
|
71
|
+
/* motion */
|
|
68
72
|
}
|
|
69
73
|
|
|
70
74
|
.attach__link {
|
|
71
75
|
/* color */
|
|
72
76
|
color: inherit;
|
|
73
77
|
|
|
78
|
+
/* typography */
|
|
79
|
+
text-decoration: none;
|
|
80
|
+
|
|
74
81
|
/* size */
|
|
75
82
|
min-width: 0;
|
|
76
83
|
|
|
77
|
-
/*
|
|
78
|
-
|
|
84
|
+
/* border */
|
|
85
|
+
|
|
86
|
+
/* depth */
|
|
87
|
+
|
|
88
|
+
/* motion */
|
|
79
89
|
}
|
|
80
90
|
|
|
81
91
|
.attach__link:hover .attach__name {
|
|
92
|
+
/* typography */
|
|
82
93
|
text-decoration: underline;
|
|
83
94
|
}
|
|
84
95
|
|
|
@@ -91,6 +102,10 @@
|
|
|
91
102
|
|
|
92
103
|
/* border */
|
|
93
104
|
border-radius: var(--attachment-radius);
|
|
105
|
+
|
|
106
|
+
/* depth */
|
|
107
|
+
|
|
108
|
+
/* motion */
|
|
94
109
|
}
|
|
95
110
|
|
|
96
111
|
.attach__file {
|
|
@@ -98,23 +113,43 @@
|
|
|
98
113
|
display: flex;
|
|
99
114
|
flex-direction: column;
|
|
100
115
|
min-width: 0;
|
|
116
|
+
|
|
117
|
+
/* border */
|
|
118
|
+
|
|
119
|
+
/* depth */
|
|
120
|
+
|
|
121
|
+
/* motion */
|
|
101
122
|
}
|
|
102
123
|
|
|
103
124
|
.attach__name {
|
|
104
|
-
/* size */
|
|
105
|
-
overflow: hidden;
|
|
106
|
-
|
|
107
125
|
/* typography */
|
|
108
126
|
text-overflow: ellipsis;
|
|
109
127
|
white-space: nowrap;
|
|
128
|
+
|
|
129
|
+
/* size */
|
|
130
|
+
overflow: hidden;
|
|
131
|
+
|
|
132
|
+
/* border */
|
|
133
|
+
|
|
134
|
+
/* depth */
|
|
135
|
+
|
|
136
|
+
/* motion */
|
|
110
137
|
}
|
|
111
138
|
|
|
112
|
-
.
|
|
139
|
+
.attach__meta {
|
|
113
140
|
/* color */
|
|
114
|
-
color: var(--attachment-
|
|
141
|
+
color: var(--attachment-meta-color);
|
|
115
142
|
|
|
116
143
|
/* typography */
|
|
117
144
|
font-size: 0.85em;
|
|
145
|
+
|
|
146
|
+
/* size */
|
|
147
|
+
|
|
148
|
+
/* border */
|
|
149
|
+
|
|
150
|
+
/* depth */
|
|
151
|
+
|
|
152
|
+
/* motion */
|
|
118
153
|
}
|
|
119
154
|
|
|
120
155
|
.attach__remove {
|
|
@@ -132,10 +167,13 @@
|
|
|
132
167
|
/* border */
|
|
133
168
|
border: 0;
|
|
134
169
|
|
|
170
|
+
/* depth */
|
|
171
|
+
|
|
135
172
|
/* motion */
|
|
136
173
|
cursor: pointer;
|
|
137
174
|
}
|
|
138
175
|
|
|
139
176
|
.attach__remove:hover {
|
|
177
|
+
/* typography */
|
|
140
178
|
text-decoration: underline;
|
|
141
179
|
}
|
|
@@ -1,9 +1,11 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
2
|
|
|
3
|
+
type AttachItemKind = 'file' | 'link';
|
|
3
4
|
interface AttachItem {
|
|
4
5
|
id: string;
|
|
5
6
|
name: string;
|
|
6
7
|
url: string;
|
|
8
|
+
kind?: AttachItemKind;
|
|
7
9
|
mimeType?: string;
|
|
8
10
|
sizeBytes?: number;
|
|
9
11
|
}
|
|
@@ -15,4 +17,4 @@ interface AttachProps extends React.HTMLAttributes<HTMLDivElement> {
|
|
|
15
17
|
}
|
|
16
18
|
declare const Attach: React.FC<AttachProps>;
|
|
17
19
|
|
|
18
|
-
export { type AttachItem, type AttachProps, Attach as default };
|
|
20
|
+
export { type AttachItem, type AttachItemKind, type AttachProps, Attach as default };
|
|
@@ -1,9 +1,11 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
2
|
|
|
3
|
+
type AttachItemKind = 'file' | 'link';
|
|
3
4
|
interface AttachItem {
|
|
4
5
|
id: string;
|
|
5
6
|
name: string;
|
|
6
7
|
url: string;
|
|
8
|
+
kind?: AttachItemKind;
|
|
7
9
|
mimeType?: string;
|
|
8
10
|
sizeBytes?: number;
|
|
9
11
|
}
|
|
@@ -15,4 +17,4 @@ interface AttachProps extends React.HTMLAttributes<HTMLDivElement> {
|
|
|
15
17
|
}
|
|
16
18
|
declare const Attach: React.FC<AttachProps>;
|
|
17
19
|
|
|
18
|
-
export { type AttachItem, type AttachProps, Attach as default };
|
|
20
|
+
export { type AttachItem, type AttachItemKind, type AttachProps, Attach as default };
|
|
@@ -5,6 +5,9 @@ import { classnames } from '../helpers/classnames';
|
|
|
5
5
|
function isImageAttach(item) {
|
|
6
6
|
return item.mimeType?.startsWith("image/") ?? false;
|
|
7
7
|
}
|
|
8
|
+
function isLinkAttach(item) {
|
|
9
|
+
return item.kind === "link";
|
|
10
|
+
}
|
|
8
11
|
function formatFileSize(sizeBytes) {
|
|
9
12
|
if (sizeBytes === void 0) {
|
|
10
13
|
return "Size unknown";
|
|
@@ -17,6 +20,13 @@ function formatFileSize(sizeBytes) {
|
|
|
17
20
|
}
|
|
18
21
|
return `${(sizeBytes / 1024 / 1024).toFixed(1)} MB`;
|
|
19
22
|
}
|
|
23
|
+
function getLinkHostname(url) {
|
|
24
|
+
try {
|
|
25
|
+
return new URL(url).hostname.replace(/^www\./u, "");
|
|
26
|
+
} catch {
|
|
27
|
+
return url;
|
|
28
|
+
}
|
|
29
|
+
}
|
|
20
30
|
const Attach = ({
|
|
21
31
|
items,
|
|
22
32
|
onRemove,
|
|
@@ -35,11 +45,18 @@ const Attach = ({
|
|
|
35
45
|
className: classes,
|
|
36
46
|
...props,
|
|
37
47
|
children: /* @__PURE__ */ jsx("ul", { className: "attach__list", children: items.map((item) => {
|
|
38
|
-
const
|
|
48
|
+
const isLink = isLinkAttach(item);
|
|
49
|
+
const isImage = !isLink && isImageAttach(item);
|
|
50
|
+
const itemClasses = classnames("attach__item", {
|
|
51
|
+
"attach__item--link": isLink,
|
|
52
|
+
"attach__item--image": isImage,
|
|
53
|
+
"attach__item--file": !isLink && !isImage
|
|
54
|
+
});
|
|
55
|
+
const meta = isLink ? getLinkHostname(item.url) : formatFileSize(item.sizeBytes);
|
|
39
56
|
return /* @__PURE__ */ jsxs(
|
|
40
57
|
"li",
|
|
41
58
|
{
|
|
42
|
-
className:
|
|
59
|
+
className: itemClasses,
|
|
43
60
|
children: [
|
|
44
61
|
/* @__PURE__ */ jsx(
|
|
45
62
|
"a",
|
|
@@ -57,7 +74,7 @@ const Attach = ({
|
|
|
57
74
|
}
|
|
58
75
|
) : /* @__PURE__ */ jsxs("span", { className: "attach__file", children: [
|
|
59
76
|
/* @__PURE__ */ jsx("span", { className: "attach__name", children: item.name }),
|
|
60
|
-
/* @__PURE__ */ jsx("span", { className: "
|
|
77
|
+
/* @__PURE__ */ jsx("span", { className: "attach__meta", children: meta })
|
|
61
78
|
] })
|
|
62
79
|
}
|
|
63
80
|
),
|
|
@@ -66,7 +83,7 @@ const Attach = ({
|
|
|
66
83
|
{
|
|
67
84
|
className: "attach__remove",
|
|
68
85
|
type: "button",
|
|
69
|
-
"aria-label": `${removeLabel}
|
|
86
|
+
"aria-label": `${removeLabel}: ${item.name}`,
|
|
70
87
|
onClick: () => onRemove(item.id),
|
|
71
88
|
children: removeLabel
|
|
72
89
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../src/components/attach/attach.tsx"],"names":[],"mappings":";;;;
|
|
1
|
+
{"version":3,"sources":["../../../src/components/attach/attach.tsx"],"names":[],"mappings":"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","file":"attach.js","sourcesContent":["import React from 'react';\nimport './attach.css';\nimport { classnames } from '../helpers/classnames';\n\nexport type AttachItemKind = 'file' | 'link';\n\nexport interface AttachItem {\n id: string;\n name: string;\n url: string;\n kind?: AttachItemKind;\n mimeType?: string;\n sizeBytes?: number;\n}\n\nexport interface AttachProps\n extends React.HTMLAttributes<HTMLDivElement> {\n items: AttachItem[];\n onRemove?: (id: string) => void;\n removeLabel?: string;\n emptyLabel?: string;\n}\n\nfunction isImageAttach(item: AttachItem) {\n return item.mimeType?.startsWith('image/') ?? false;\n}\n\nfunction isLinkAttach(item: AttachItem) {\n return item.kind === 'link';\n}\n\nfunction formatFileSize(sizeBytes?: number) {\n if (sizeBytes === undefined) {\n return 'Size unknown';\n }\n\n if (sizeBytes < 1024) {\n return `${sizeBytes} B`;\n }\n\n if (sizeBytes < 1024 * 1024) {\n return `${Math.round(sizeBytes / 1024)} KB`;\n }\n\n return `${(sizeBytes / 1024 / 1024).toFixed(1)} MB`;\n}\n\nfunction getLinkHostname(url: string) {\n try {\n return new URL(url).hostname.replace(/^www\\./u, '');\n } catch {\n return url;\n }\n}\n\nconst Attach: React.FC<AttachProps> = ({\n items,\n onRemove,\n removeLabel = 'Удалить',\n emptyLabel,\n className = '',\n ...props\n}) => {\n if (items.length === 0) {\n return null;\n }\n\n const classes = classnames('attach', className, {});\n\n return (\n <div\n className={classes}\n {...props}\n >\n <ul className=\"attach__list\">\n {items.map((item) => {\n const isLink = isLinkAttach(item);\n const isImage = !isLink && isImageAttach(item);\n\n const itemClasses = classnames('attach__item', {\n 'attach__item--link': isLink,\n 'attach__item--image': isImage,\n 'attach__item--file': !isLink && !isImage,\n });\n\n const meta = isLink\n ? getLinkHostname(item.url)\n : formatFileSize(item.sizeBytes);\n\n return (\n <li\n key={item.id}\n className={itemClasses}\n >\n <a\n className=\"attach__link\"\n href={item.url}\n target=\"_blank\"\n rel=\"noreferrer\"\n >\n {isImage ? (\n <img\n className=\"attach__preview\"\n src={item.url}\n alt={item.name}\n />\n ) : (\n <span className=\"attach__file\">\n <span className=\"attach__name\">\n {item.name}\n </span>\n\n <span className=\"attach__meta\">\n {meta}\n </span>\n </span>\n )}\n </a>\n\n {onRemove && (\n <button\n className=\"attach__remove\"\n type=\"button\"\n aria-label={`${removeLabel}: ${item.name}`}\n onClick={() => onRemove(item.id)}\n >\n {removeLabel}\n </button>\n )}\n </li>\n );\n })}\n </ul>\n </div>\n );\n};\n\nexport default Attach;"]}
|
package/package.json
CHANGED
package/styles.css
CHANGED
|
@@ -32,7 +32,7 @@
|
|
|
32
32
|
--attachment-color: var(--color-text);
|
|
33
33
|
--attachment-item-bg: var(--color-control);
|
|
34
34
|
--attachment-border-color: var(--color-line);
|
|
35
|
-
--attachment-
|
|
35
|
+
--attachment-meta-color: var(--color-text-note);
|
|
36
36
|
|
|
37
37
|
color: var(--attachment-color);
|
|
38
38
|
|
|
@@ -94,20 +94,31 @@
|
|
|
94
94
|
solid
|
|
95
95
|
var(--attachment-border-color);
|
|
96
96
|
border-radius: var(--attachment-radius);
|
|
97
|
+
|
|
98
|
+
/* depth */
|
|
99
|
+
|
|
100
|
+
/* motion */
|
|
97
101
|
}
|
|
98
102
|
|
|
99
103
|
.attach__link {
|
|
100
104
|
/* color */
|
|
101
105
|
color: inherit;
|
|
102
106
|
|
|
107
|
+
/* typography */
|
|
108
|
+
text-decoration: none;
|
|
109
|
+
|
|
103
110
|
/* size */
|
|
104
111
|
min-width: 0;
|
|
105
112
|
|
|
106
|
-
/*
|
|
107
|
-
|
|
113
|
+
/* border */
|
|
114
|
+
|
|
115
|
+
/* depth */
|
|
116
|
+
|
|
117
|
+
/* motion */
|
|
108
118
|
}
|
|
109
119
|
|
|
110
120
|
.attach__link:hover .attach__name {
|
|
121
|
+
/* typography */
|
|
111
122
|
text-decoration: underline;
|
|
112
123
|
}
|
|
113
124
|
|
|
@@ -120,6 +131,10 @@
|
|
|
120
131
|
|
|
121
132
|
/* border */
|
|
122
133
|
border-radius: var(--attachment-radius);
|
|
134
|
+
|
|
135
|
+
/* depth */
|
|
136
|
+
|
|
137
|
+
/* motion */
|
|
123
138
|
}
|
|
124
139
|
|
|
125
140
|
.attach__file {
|
|
@@ -127,23 +142,43 @@
|
|
|
127
142
|
display: flex;
|
|
128
143
|
flex-direction: column;
|
|
129
144
|
min-width: 0;
|
|
145
|
+
|
|
146
|
+
/* border */
|
|
147
|
+
|
|
148
|
+
/* depth */
|
|
149
|
+
|
|
150
|
+
/* motion */
|
|
130
151
|
}
|
|
131
152
|
|
|
132
153
|
.attach__name {
|
|
133
|
-
/* size */
|
|
134
|
-
overflow: hidden;
|
|
135
|
-
|
|
136
154
|
/* typography */
|
|
137
155
|
text-overflow: ellipsis;
|
|
138
156
|
white-space: nowrap;
|
|
157
|
+
|
|
158
|
+
/* size */
|
|
159
|
+
overflow: hidden;
|
|
160
|
+
|
|
161
|
+
/* border */
|
|
162
|
+
|
|
163
|
+
/* depth */
|
|
164
|
+
|
|
165
|
+
/* motion */
|
|
139
166
|
}
|
|
140
167
|
|
|
141
|
-
.
|
|
168
|
+
.attach__meta {
|
|
142
169
|
/* color */
|
|
143
|
-
color: var(--attachment-
|
|
170
|
+
color: var(--attachment-meta-color);
|
|
144
171
|
|
|
145
172
|
/* typography */
|
|
146
173
|
font-size: 0.85em;
|
|
174
|
+
|
|
175
|
+
/* size */
|
|
176
|
+
|
|
177
|
+
/* border */
|
|
178
|
+
|
|
179
|
+
/* depth */
|
|
180
|
+
|
|
181
|
+
/* motion */
|
|
147
182
|
}
|
|
148
183
|
|
|
149
184
|
.attach__remove {
|
|
@@ -161,11 +196,14 @@
|
|
|
161
196
|
/* border */
|
|
162
197
|
border: 0;
|
|
163
198
|
|
|
199
|
+
/* depth */
|
|
200
|
+
|
|
164
201
|
/* motion */
|
|
165
202
|
cursor: pointer;
|
|
166
203
|
}
|
|
167
204
|
|
|
168
205
|
.attach__remove:hover {
|
|
206
|
+
/* typography */
|
|
169
207
|
text-decoration: underline;
|
|
170
208
|
}
|
|
171
209
|
|