@sproutsocial/seeds-react-icon 1.0.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.
@@ -0,0 +1,67 @@
1
+ import * as React from 'react';
2
+ import { EnumIconNames } from '@sproutsocial/seeds-icons';
3
+ import { EnumLogoNamesWithoutVariants } from '@sproutsocial/seeds-partner-logos';
4
+ import { TypeStyledComponentsCommonProps, TypeSystemCommonProps } from '@sproutsocial/seeds-react-system-props';
5
+ import { TypeBoxProps } from '@sproutsocial/seeds-react-box';
6
+ import * as styled_components from 'styled-components';
7
+
8
+ type TypeIconName = EnumIconNames | EnumLogoNamesWithoutVariants;
9
+ type TypeIconSize = "mini" | "default" | "small" | "medium" | "large" | "jumbo";
10
+ interface TypeIconProps extends TypeStyledComponentsCommonProps, TypeSystemCommonProps, Omit<React.ComponentPropsWithoutRef<"span">, "color"> {
11
+ /** Name of the icon in the svg sprite */
12
+ name: TypeIconName;
13
+ size?: TypeIconSize;
14
+ /** Whether the icon should have a fixed width or not. Use this when you need to align icons/text vertically in a list. */
15
+ fixedWidth?: boolean;
16
+ /** Label used to describe the icon if not used with an accompanying visual label */
17
+ ariaLabel?: string;
18
+ svgProps?: React.ComponentPropsWithoutRef<"svg">;
19
+ }
20
+ interface TypeToggleProps extends TypeBoxProps {
21
+ /** Name of the icon to be shown in the active state */
22
+ activeName: TypeIconName;
23
+ /** Name of the icon to be shown in the inactive state */
24
+ inactiveName: TypeIconName;
25
+ /** Whether the active icon should be shown or not */
26
+ isActive: boolean;
27
+ /** The size of the icon. `small` is the default */
28
+ size?: TypeIconSize;
29
+ fixedWidth?: boolean;
30
+ ariaLabel?: string;
31
+ }
32
+
33
+ declare const Icon: {
34
+ ({ name, size, fixedWidth, ariaLabel, color, svgProps, ...rest }: TypeIconProps): React.JSX.Element;
35
+ /**
36
+ * **Accessibility note:** It is best practice to wrap `<Icon.Toggle />` in a button. The button must include `aria-label` and `aria-pressed` in order for a screen reader to properly communicate the icon's state. See example below.
37
+ *
38
+ * @link https://www.w3.org/TR/wai-aria-practices-1.1/#button
39
+ * @example
40
+ * const [toggleState, setToggleState] = useState(false);
41
+ * <Button // Wrap Icon.Toggle with Button
42
+ * appearance='pill'
43
+ * aria-label='like' // required for accessibility
44
+ * aria-pressed={toggleState} // required for accessibility
45
+ * onClick={() => setToggleState(!toggleState)}
46
+ * >
47
+ * <Icon.Toggle
48
+ * activeName="heart-solid"
49
+ * inactiveName="heart-outline"
50
+ * isActive={toggleState}
51
+ * />
52
+ * </Button>
53
+ */
54
+ Toggle: {
55
+ ({ activeName, inactiveName, isActive, size, fixedWidth, ariaLabel, ...rest }: TypeToggleProps): React.JSX.Element;
56
+ displayName: string;
57
+ };
58
+ };
59
+
60
+ declare const Container: styled_components.StyledComponent<"span", any, {
61
+ className: "Icon";
62
+ } & {
63
+ iconSize: TypeIconSize;
64
+ fixedWidth: boolean;
65
+ }, "className">;
66
+
67
+ export { Icon, Container as IconContainer, type TypeIconName, type TypeIconProps, type TypeIconSize, type TypeToggleProps, Icon as default };
@@ -0,0 +1,67 @@
1
+ import * as React from 'react';
2
+ import { EnumIconNames } from '@sproutsocial/seeds-icons';
3
+ import { EnumLogoNamesWithoutVariants } from '@sproutsocial/seeds-partner-logos';
4
+ import { TypeStyledComponentsCommonProps, TypeSystemCommonProps } from '@sproutsocial/seeds-react-system-props';
5
+ import { TypeBoxProps } from '@sproutsocial/seeds-react-box';
6
+ import * as styled_components from 'styled-components';
7
+
8
+ type TypeIconName = EnumIconNames | EnumLogoNamesWithoutVariants;
9
+ type TypeIconSize = "mini" | "default" | "small" | "medium" | "large" | "jumbo";
10
+ interface TypeIconProps extends TypeStyledComponentsCommonProps, TypeSystemCommonProps, Omit<React.ComponentPropsWithoutRef<"span">, "color"> {
11
+ /** Name of the icon in the svg sprite */
12
+ name: TypeIconName;
13
+ size?: TypeIconSize;
14
+ /** Whether the icon should have a fixed width or not. Use this when you need to align icons/text vertically in a list. */
15
+ fixedWidth?: boolean;
16
+ /** Label used to describe the icon if not used with an accompanying visual label */
17
+ ariaLabel?: string;
18
+ svgProps?: React.ComponentPropsWithoutRef<"svg">;
19
+ }
20
+ interface TypeToggleProps extends TypeBoxProps {
21
+ /** Name of the icon to be shown in the active state */
22
+ activeName: TypeIconName;
23
+ /** Name of the icon to be shown in the inactive state */
24
+ inactiveName: TypeIconName;
25
+ /** Whether the active icon should be shown or not */
26
+ isActive: boolean;
27
+ /** The size of the icon. `small` is the default */
28
+ size?: TypeIconSize;
29
+ fixedWidth?: boolean;
30
+ ariaLabel?: string;
31
+ }
32
+
33
+ declare const Icon: {
34
+ ({ name, size, fixedWidth, ariaLabel, color, svgProps, ...rest }: TypeIconProps): React.JSX.Element;
35
+ /**
36
+ * **Accessibility note:** It is best practice to wrap `<Icon.Toggle />` in a button. The button must include `aria-label` and `aria-pressed` in order for a screen reader to properly communicate the icon's state. See example below.
37
+ *
38
+ * @link https://www.w3.org/TR/wai-aria-practices-1.1/#button
39
+ * @example
40
+ * const [toggleState, setToggleState] = useState(false);
41
+ * <Button // Wrap Icon.Toggle with Button
42
+ * appearance='pill'
43
+ * aria-label='like' // required for accessibility
44
+ * aria-pressed={toggleState} // required for accessibility
45
+ * onClick={() => setToggleState(!toggleState)}
46
+ * >
47
+ * <Icon.Toggle
48
+ * activeName="heart-solid"
49
+ * inactiveName="heart-outline"
50
+ * isActive={toggleState}
51
+ * />
52
+ * </Button>
53
+ */
54
+ Toggle: {
55
+ ({ activeName, inactiveName, isActive, size, fixedWidth, ariaLabel, ...rest }: TypeToggleProps): React.JSX.Element;
56
+ displayName: string;
57
+ };
58
+ };
59
+
60
+ declare const Container: styled_components.StyledComponent<"span", any, {
61
+ className: "Icon";
62
+ } & {
63
+ iconSize: TypeIconSize;
64
+ fixedWidth: boolean;
65
+ }, "className">;
66
+
67
+ export { Icon, Container as IconContainer, type TypeIconName, type TypeIconProps, type TypeIconSize, type TypeToggleProps, Icon as default };
package/dist/index.js ADDED
@@ -0,0 +1,221 @@
1
+ "use strict";
2
+ var __create = Object.create;
3
+ var __defProp = Object.defineProperty;
4
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
5
+ var __getOwnPropNames = Object.getOwnPropertyNames;
6
+ var __getProtoOf = Object.getPrototypeOf;
7
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
8
+ var __export = (target, all) => {
9
+ for (var name in all)
10
+ __defProp(target, name, { get: all[name], enumerable: true });
11
+ };
12
+ var __copyProps = (to, from, except, desc) => {
13
+ if (from && typeof from === "object" || typeof from === "function") {
14
+ for (let key of __getOwnPropNames(from))
15
+ if (!__hasOwnProp.call(to, key) && key !== except)
16
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
17
+ }
18
+ return to;
19
+ };
20
+ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
21
+ // If the importer is in node compatibility mode or this is not an ESM
22
+ // file that has been converted to a CommonJS file using a Babel-
23
+ // compatible transform (i.e. "__esModule" has not been set), then set
24
+ // "default" to the CommonJS "module.exports" for node compatibility.
25
+ isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
26
+ mod
27
+ ));
28
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
29
+
30
+ // src/index.ts
31
+ var src_exports = {};
32
+ __export(src_exports, {
33
+ Icon: () => Icon_default,
34
+ IconContainer: () => styles_default,
35
+ default: () => src_default
36
+ });
37
+ module.exports = __toCommonJS(src_exports);
38
+
39
+ // src/Icon.tsx
40
+ var React = __toESM(require("react"));
41
+ var import_styled_components2 = __toESM(require("styled-components"));
42
+ var import_seeds_react_box = __toESM(require("@sproutsocial/seeds-react-box"));
43
+ var import_seeds_react_partner_logo = __toESM(require("@sproutsocial/seeds-react-partner-logo"));
44
+ var import_seeds_react_utilities = require("@sproutsocial/seeds-react-utilities");
45
+ var import_seeds_partner_logos = require("@sproutsocial/seeds-partner-logos");
46
+
47
+ // src/styles.ts
48
+ var import_styled_components = __toESM(require("styled-components"));
49
+ var import_styled_system = require("styled-system");
50
+ var import_seeds_react_system_props = require("@sproutsocial/seeds-react-system-props");
51
+ var sizes = {
52
+ mini: "12px",
53
+ /** TODO: deprecate default in favor of small in future release */
54
+ default: "16px",
55
+ small: "16px",
56
+ medium: "24px",
57
+ large: "32px",
58
+ jumbo: "64px"
59
+ };
60
+ var stylesForSize = (iconActualSize, fixedWidth) => import_styled_components.css`
61
+ line-height: ${iconActualSize};
62
+
63
+ &,
64
+ .Icon-svg {
65
+ height: ${iconActualSize};
66
+ fill: currentColor;
67
+ }
68
+
69
+ ${fixedWidth && `
70
+ &,
71
+ & .Icon-svg {
72
+ width: ${iconActualSize}
73
+ }
74
+ `}
75
+ `;
76
+ var Container = import_styled_components.default.span.attrs({
77
+ className: "Icon"
78
+ })`
79
+ display: inline-block;
80
+ color: inherit;
81
+ vertical-align: middle;
82
+
83
+ ${(props) => stylesForSize(sizes[props.iconSize], props.fixedWidth)}
84
+
85
+ ${import_seeds_react_system_props.COMMON}
86
+ ${import_styled_system.verticalAlign}
87
+ `;
88
+ var styles_default = Container;
89
+
90
+ // src/Icon.tsx
91
+ var import_seeds_icons = require("@sproutsocial/seeds-icons");
92
+ var AllViewboxes = {
93
+ ...import_seeds_icons.ExternalViewBoxes,
94
+ ...import_seeds_icons.GeneralViewBoxes,
95
+ ...import_seeds_icons.SproutViewBoxes
96
+ };
97
+ var Icon = ({
98
+ name,
99
+ size = "small",
100
+ fixedWidth = false,
101
+ ariaLabel,
102
+ color,
103
+ svgProps,
104
+ ...rest
105
+ }) => {
106
+ if ((0, import_seeds_react_utilities.includes)(import_seeds_partner_logos.LogoNamesWithoutVariants, name)) {
107
+ const logoSize = size === "default" ? "small" : size;
108
+ const logoProps = {
109
+ partnerName: name,
110
+ size: logoSize,
111
+ logoType: "symbol",
112
+ svgProps
113
+ };
114
+ return /* @__PURE__ */ React.createElement(
115
+ import_seeds_react_partner_logo.default,
116
+ {
117
+ "aria-label": ariaLabel,
118
+ ...rest,
119
+ ...logoProps
120
+ }
121
+ );
122
+ }
123
+ const defaultVariant = size === "mini" ? "solid" : "outline";
124
+ const iconName = (
125
+ // if not external and has no variant
126
+ !name?.endsWith("-outline") && !name?.endsWith("-solid") && !(0, import_seeds_react_utilities.includes)(import_seeds_icons.ExternalIconNames, name) ? (
127
+ // then add default variant
128
+ `${name}-${defaultVariant}`
129
+ ) : (
130
+ // else use name as is
131
+ name
132
+ )
133
+ );
134
+ const iconViewBox = AllViewboxes[iconName];
135
+ return /* @__PURE__ */ React.createElement(
136
+ styles_default,
137
+ {
138
+ iconSize: size,
139
+ fixedWidth: !!fixedWidth,
140
+ key: iconName,
141
+ role: "img",
142
+ "aria-label": ariaLabel,
143
+ "data-qa-icon": iconName,
144
+ color,
145
+ ...rest
146
+ },
147
+ /* @__PURE__ */ React.createElement(
148
+ "svg",
149
+ {
150
+ className: "Icon-svg",
151
+ viewBox: iconViewBox,
152
+ focusable: false,
153
+ "data-qa-icon-svg": `${iconName}-svg`,
154
+ ...svgProps
155
+ },
156
+ /* @__PURE__ */ React.createElement(
157
+ "use",
158
+ {
159
+ xmlnsXlink: "http://www.w3.org/1999/xlink",
160
+ xlinkHref: `#seeds-svgs_${iconName}`
161
+ }
162
+ )
163
+ )
164
+ );
165
+ };
166
+ var ToggleableIcon = (0, import_styled_components2.default)(Icon)`
167
+ transition: all ${(p) => p.theme.duration.fast} linear;
168
+
169
+ ${(p) => p.active && import_styled_components2.css`
170
+ opacity: 1;
171
+ transform: scale(1);
172
+ `}
173
+
174
+ ${(p) => !p.active && import_styled_components2.css`
175
+ position: absolute;
176
+ opacity: 0;
177
+ transform: scale(0);
178
+ `}
179
+ `;
180
+ var IconToggle = ({
181
+ activeName,
182
+ inactiveName,
183
+ isActive,
184
+ size = "small",
185
+ fixedWidth = false,
186
+ ariaLabel,
187
+ ...rest
188
+ }) => {
189
+ return /* @__PURE__ */ React.createElement(import_seeds_react_box.default, { as: "span", position: "relative", display: "inline-flex", ...rest }, /* @__PURE__ */ React.createElement(
190
+ ToggleableIcon,
191
+ {
192
+ active: isActive,
193
+ name: activeName,
194
+ size,
195
+ fixedWidth,
196
+ "aria-label": ariaLabel,
197
+ "aria-hidden": !isActive
198
+ }
199
+ ), /* @__PURE__ */ React.createElement(
200
+ ToggleableIcon,
201
+ {
202
+ active: !isActive,
203
+ name: inactiveName,
204
+ size,
205
+ fixedWidth,
206
+ "aria-label": ariaLabel,
207
+ "aria-hidden": isActive
208
+ }
209
+ ));
210
+ };
211
+ IconToggle.displayName = "Icon.Toggle";
212
+ Icon.Toggle = IconToggle;
213
+ var Icon_default = Icon;
214
+
215
+ // src/index.ts
216
+ var src_default = Icon_default;
217
+ // Annotate the CommonJS export names for ESM import in node:
218
+ 0 && (module.exports = {
219
+ Icon,
220
+ IconContainer
221
+ });
package/dist/index.mjs ADDED
@@ -0,0 +1,188 @@
1
+ // src/Icon.tsx
2
+ import * as React from "react";
3
+ import styled2, { css as css2 } from "styled-components";
4
+ import Box from "@sproutsocial/seeds-react-box";
5
+ import PartnerLogo from "@sproutsocial/seeds-react-partner-logo";
6
+ import { includes } from "@sproutsocial/seeds-react-utilities";
7
+ import { LogoNamesWithoutVariants as PartnerLogoNames } from "@sproutsocial/seeds-partner-logos";
8
+
9
+ // src/styles.ts
10
+ import styled, { css } from "styled-components";
11
+ import { verticalAlign } from "styled-system";
12
+ import { COMMON } from "@sproutsocial/seeds-react-system-props";
13
+ var sizes = {
14
+ mini: "12px",
15
+ /** TODO: deprecate default in favor of small in future release */
16
+ default: "16px",
17
+ small: "16px",
18
+ medium: "24px",
19
+ large: "32px",
20
+ jumbo: "64px"
21
+ };
22
+ var stylesForSize = (iconActualSize, fixedWidth) => css`
23
+ line-height: ${iconActualSize};
24
+
25
+ &,
26
+ .Icon-svg {
27
+ height: ${iconActualSize};
28
+ fill: currentColor;
29
+ }
30
+
31
+ ${fixedWidth && `
32
+ &,
33
+ & .Icon-svg {
34
+ width: ${iconActualSize}
35
+ }
36
+ `}
37
+ `;
38
+ var Container = styled.span.attrs({
39
+ className: "Icon"
40
+ })`
41
+ display: inline-block;
42
+ color: inherit;
43
+ vertical-align: middle;
44
+
45
+ ${(props) => stylesForSize(sizes[props.iconSize], props.fixedWidth)}
46
+
47
+ ${COMMON}
48
+ ${verticalAlign}
49
+ `;
50
+ var styles_default = Container;
51
+
52
+ // src/Icon.tsx
53
+ import {
54
+ ExternalViewBoxes,
55
+ GeneralViewBoxes,
56
+ SproutViewBoxes,
57
+ ExternalIconNames
58
+ } from "@sproutsocial/seeds-icons";
59
+ var AllViewboxes = {
60
+ ...ExternalViewBoxes,
61
+ ...GeneralViewBoxes,
62
+ ...SproutViewBoxes
63
+ };
64
+ var Icon = ({
65
+ name,
66
+ size = "small",
67
+ fixedWidth = false,
68
+ ariaLabel,
69
+ color,
70
+ svgProps,
71
+ ...rest
72
+ }) => {
73
+ if (includes(PartnerLogoNames, name)) {
74
+ const logoSize = size === "default" ? "small" : size;
75
+ const logoProps = {
76
+ partnerName: name,
77
+ size: logoSize,
78
+ logoType: "symbol",
79
+ svgProps
80
+ };
81
+ return /* @__PURE__ */ React.createElement(
82
+ PartnerLogo,
83
+ {
84
+ "aria-label": ariaLabel,
85
+ ...rest,
86
+ ...logoProps
87
+ }
88
+ );
89
+ }
90
+ const defaultVariant = size === "mini" ? "solid" : "outline";
91
+ const iconName = (
92
+ // if not external and has no variant
93
+ !name?.endsWith("-outline") && !name?.endsWith("-solid") && !includes(ExternalIconNames, name) ? (
94
+ // then add default variant
95
+ `${name}-${defaultVariant}`
96
+ ) : (
97
+ // else use name as is
98
+ name
99
+ )
100
+ );
101
+ const iconViewBox = AllViewboxes[iconName];
102
+ return /* @__PURE__ */ React.createElement(
103
+ styles_default,
104
+ {
105
+ iconSize: size,
106
+ fixedWidth: !!fixedWidth,
107
+ key: iconName,
108
+ role: "img",
109
+ "aria-label": ariaLabel,
110
+ "data-qa-icon": iconName,
111
+ color,
112
+ ...rest
113
+ },
114
+ /* @__PURE__ */ React.createElement(
115
+ "svg",
116
+ {
117
+ className: "Icon-svg",
118
+ viewBox: iconViewBox,
119
+ focusable: false,
120
+ "data-qa-icon-svg": `${iconName}-svg`,
121
+ ...svgProps
122
+ },
123
+ /* @__PURE__ */ React.createElement(
124
+ "use",
125
+ {
126
+ xmlnsXlink: "http://www.w3.org/1999/xlink",
127
+ xlinkHref: `#seeds-svgs_${iconName}`
128
+ }
129
+ )
130
+ )
131
+ );
132
+ };
133
+ var ToggleableIcon = styled2(Icon)`
134
+ transition: all ${(p) => p.theme.duration.fast} linear;
135
+
136
+ ${(p) => p.active && css2`
137
+ opacity: 1;
138
+ transform: scale(1);
139
+ `}
140
+
141
+ ${(p) => !p.active && css2`
142
+ position: absolute;
143
+ opacity: 0;
144
+ transform: scale(0);
145
+ `}
146
+ `;
147
+ var IconToggle = ({
148
+ activeName,
149
+ inactiveName,
150
+ isActive,
151
+ size = "small",
152
+ fixedWidth = false,
153
+ ariaLabel,
154
+ ...rest
155
+ }) => {
156
+ return /* @__PURE__ */ React.createElement(Box, { as: "span", position: "relative", display: "inline-flex", ...rest }, /* @__PURE__ */ React.createElement(
157
+ ToggleableIcon,
158
+ {
159
+ active: isActive,
160
+ name: activeName,
161
+ size,
162
+ fixedWidth,
163
+ "aria-label": ariaLabel,
164
+ "aria-hidden": !isActive
165
+ }
166
+ ), /* @__PURE__ */ React.createElement(
167
+ ToggleableIcon,
168
+ {
169
+ active: !isActive,
170
+ name: inactiveName,
171
+ size,
172
+ fixedWidth,
173
+ "aria-label": ariaLabel,
174
+ "aria-hidden": isActive
175
+ }
176
+ ));
177
+ };
178
+ IconToggle.displayName = "Icon.Toggle";
179
+ Icon.Toggle = IconToggle;
180
+ var Icon_default = Icon;
181
+
182
+ // src/index.ts
183
+ var src_default = Icon_default;
184
+ export {
185
+ Icon_default as Icon,
186
+ styles_default as IconContainer,
187
+ src_default as default
188
+ };
package/package.json ADDED
@@ -0,0 +1,40 @@
1
+ {
2
+ "name": "@sproutsocial/seeds-react-icon",
3
+ "version": "1.0.0",
4
+ "description": "Seeds React Icon component",
5
+ "main": "dist/index.js",
6
+ "types": "dist/index.d.ts",
7
+ "author": "Sprout Social, Inc.",
8
+ "license": "MIT",
9
+ "files": [
10
+ "dist"
11
+ ],
12
+ "scripts": {
13
+ "build": "tsup"
14
+ },
15
+ "dependencies": {
16
+ "@sproutsocial/seeds-react-box": "^1.0.1",
17
+ "@sproutsocial/seeds-react-partner-logo": "^1.0.0",
18
+ "@sproutsocial/seeds-react-system-props": "^2.1.0",
19
+ "@sproutsocial/seeds-react-theme": "^1.0.0",
20
+ "@sproutsocial/seeds-react-utilities": "^2.0.0",
21
+ "styled-system": "^5.1.5"
22
+ },
23
+ "devDependencies": {
24
+ "@sproutsocial/eslint-config-seeds": "*",
25
+ "@sproutsocial/seeds-icons": "^1.8.0",
26
+ "@sproutsocial/seeds-partner-logos": "^1.5.0",
27
+ "styled-components": "^5.2.3",
28
+ "tsx": "3.13.0",
29
+ "typescript": "^5.1.6",
30
+ "tsup": "^8.0.2"
31
+ },
32
+ "peerDependencies": {
33
+ "@sproutsocial/seeds-icons": ">=1.8.0",
34
+ "@sproutsocial/seeds-partner-logos": ">=1.5.0",
35
+ "styled-components": "^5.2.3"
36
+ },
37
+ "engines": {
38
+ "node": ">=18"
39
+ }
40
+ }