@commercetools-frontend/ui-kit 15.14.0 → 15.14.2

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.
@@ -80,7 +80,7 @@ var text__default = /*#__PURE__*/_interopDefault(text);
80
80
  var viewSwitcher__default = /*#__PURE__*/_interopDefault(viewSwitcher);
81
81
 
82
82
  // NOTE: This string will be replaced on build time with the package version.
83
- var version = "15.14.0";
83
+ var version = "15.14.2";
84
84
 
85
85
  exports.i18n = i18n__namespace;
86
86
  Object.defineProperty(exports, 'AccessibleHidden', {
@@ -80,7 +80,7 @@ var text__default = /*#__PURE__*/_interopDefault(text);
80
80
  var viewSwitcher__default = /*#__PURE__*/_interopDefault(viewSwitcher);
81
81
 
82
82
  // NOTE: This string will be replaced on build time with the package version.
83
- var version = "15.14.0";
83
+ var version = "15.14.2";
84
84
 
85
85
  exports.i18n = i18n__namespace;
86
86
  Object.defineProperty(exports, 'AccessibleHidden', {
@@ -33,6 +33,6 @@ export { useDataTableSortingState, usePaginationState, useRowSelection, useSorti
33
33
  export { customProperties, designTokens } from '@commercetools-uikit/design-system';
34
34
 
35
35
  // NOTE: This string will be replaced on build time with the package version.
36
- var version = "15.14.0";
36
+ var version = "15.14.2";
37
37
 
38
38
  export { version };
@@ -220,12 +220,6 @@ choiceGroupsByTheme:
220
220
  break-point-jumbodesktop: 1920px
221
221
 
222
222
  test:
223
- colors:
224
- label: Colors
225
- prefix: color
226
- description: Dark theme colors overwrite
227
- choices:
228
- color-primary: '#00b39e'
229
223
  fontFamilies:
230
224
  label: Font families
231
225
  prefix: font-family
@@ -1891,9 +1885,9 @@ decisionGroupsByTheme:
1891
1885
  padding-for-collapsible-panel-header-as-condensed:
1892
1886
  choice: 'var(--spacing-20) 0'
1893
1887
  padding-for-collapsible-panel-section-wrapper:
1894
- choice: 'var(--spacing-50) 0 var(--spacing-70) calc(var(--spacing-30) + var(--spacing-10))'
1888
+ choice: 'var(--spacing-50) 0 0 calc(var(--spacing-30) + var(--spacing-10))'
1895
1889
  padding-for-collapsible-panel-section-wrapper-as-condensed:
1896
- choice: 'var(--spacing-40) 0 var(--spacing-70) calc(var(--spacing-30) + var(--spacing-10))'
1890
+ choice: 'var(--spacing-40) 0 0 calc(var(--spacing-30) + var(--spacing-10))'
1897
1891
  padding-for-collapsible-panel-section-description:
1898
1892
  choice: '0 0 var(--spacing-40)'
1899
1893
  padding-for-collapsible-panel-section-description-as-condensed:
@@ -0,0 +1,82 @@
1
+ import styled from '@emotion/styled';
2
+
3
+ const BasicSample = styled.div``;
4
+
5
+ const BorderRadiusSample = styled.div`
6
+ width: calc(${(props) => props.value} + 2 * ${(props) => props.value});
7
+ min-width: 20px;
8
+ height: calc(${(props) => props.value} + 2 * ${(props) => props.value});
9
+ min-height: 20px;
10
+ background-color: pink;
11
+ border-radius: ${(props) => props.value};
12
+ display: inline-block;
13
+ margin: 0 10px;
14
+ `;
15
+
16
+ const ColorSample = styled.div`
17
+ width: 30px;
18
+ height: 30px;
19
+ background-color: ${(props) => props.value};
20
+ box-shadow: inset 0 0 5px 0 rgba(0, 0, 0, 0.1);
21
+ display: inline-block;
22
+ `;
23
+
24
+ const FontColorSampleStyle = styled.div`
25
+ color: ${(props) => props.value};
26
+ font-size: 24pt;
27
+ font-weight: bolder;
28
+ display: inline-block;
29
+ `;
30
+ const FontColorSample = (props) => (
31
+ <FontColorSampleStyle {...props}>Aa</FontColorSampleStyle>
32
+ );
33
+
34
+ const FontSizeSampleStyle = styled.div`
35
+ font-size: ${(props) => props.value};
36
+ font-weight: bolder;
37
+ display: inline-block;
38
+ `;
39
+ const FontSizeSample = (props) => (
40
+ <FontSizeSampleStyle {...props}>Aa</FontSizeSampleStyle>
41
+ );
42
+
43
+ const FontWeightSampleStyle = styled.div`
44
+ font-weight: ${(props) => props.value};
45
+ font-size: 2rem;
46
+ display: inline-block;
47
+ `;
48
+ const FontWeightSample = (props) => (
49
+ <FontWeightSampleStyle {...props}>Aa</FontWeightSampleStyle>
50
+ );
51
+
52
+ const ShadowSample = styled.div`
53
+ width: 50px;
54
+ height: 50px;
55
+ box-shadow: ${(props) => props.value};
56
+ display: inline-block;
57
+ margin: 0 10px;
58
+ `;
59
+
60
+ const SpacingSample = styled.div`
61
+ width: ${(props) => props.value};
62
+ height: ${(props) => props.value};
63
+ background-color: lightblue;
64
+ display: inline-block;
65
+ margin: 0 10px;
66
+ `;
67
+
68
+ const samplersMap = {
69
+ 'background-color': ColorSample,
70
+ 'border-color': ColorSample,
71
+ 'border-radius': BorderRadiusSample,
72
+ color: ColorSample,
73
+ 'font-color': FontColorSample,
74
+ 'font-size': FontSizeSample,
75
+ 'font-weight': FontWeightSample,
76
+ 'icon-color': ColorSample,
77
+ shadow: ShadowSample,
78
+ spacing: SpacingSample,
79
+ };
80
+
81
+ export const getSampleComponent = (cssRuleName) =>
82
+ samplersMap[cssRuleName] || BasicSample;
@@ -0,0 +1,270 @@
1
+ /* eslint-disable jsx-a11y/anchor-is-valid */
2
+ /* eslint-disable jsx-a11y/anchor-has-content */
3
+ import styled from '@emotion/styled';
4
+ import PropTypes from 'prop-types';
5
+ import upperFirst from 'lodash/upperFirst';
6
+ import deprecatedTokens from '../deprecated-tokens';
7
+
8
+ const getIsDeprecated = (token) => deprecatedTokens.includes(token);
9
+
10
+ const filterGroupItemsValues = (groupItems, searchText) =>
11
+ Object.entries(groupItems).filter(
12
+ ([key, value]) =>
13
+ key.toLowerCase().includes(searchText.toLowerCase()) ||
14
+ value?.toLowerCase?.().includes(searchText.toLowerCase()) ||
15
+ value?.description?.toLowerCase().includes(searchText.toLowerCase())
16
+ );
17
+
18
+ const Table = styled.table`
19
+ border: 1px solid #ccc;
20
+ border-collapse: collapse;
21
+ & tr td {
22
+ border: 1px solid #ccc;
23
+ padding: 15px;
24
+ text-align: left;
25
+ }
26
+ & thead td {
27
+ background-color: gray;
28
+ color: white;
29
+ font-weight: bold;
30
+ }
31
+ `;
32
+
33
+ const GroupStyle = styled.div`
34
+ padding: 10px;
35
+ display: ${(props) => (props.isVisible ? 'block' : 'none')};
36
+ `;
37
+
38
+ export const Token = styled.p`
39
+ font-family: monospace;
40
+ `;
41
+
42
+ const DeprecationBadge = () => <b style={{ color: 'orange' }}>DEPRECATED</b>;
43
+ DeprecationBadge.displayName = 'DeprecationBadge';
44
+
45
+ export const TokenBodyCell = (props) => (
46
+ <>
47
+ <Token>{props.tokenName}</Token>
48
+ {getIsDeprecated(props.tokenName) && <DeprecationBadge />}
49
+ </>
50
+ );
51
+ TokenBodyCell.propTypes = {
52
+ tokenName: PropTypes.string.isRequired,
53
+ };
54
+
55
+ export const TokenGroupLinks = (props) => {
56
+ return (
57
+ <>
58
+ <a
59
+ href={`#${props.id}`}
60
+ onClick={(event) => {
61
+ event.preventDefault();
62
+ window.scrollTo({
63
+ top: document.getElementById(props.id).offsetTop,
64
+ behavior: 'smooth',
65
+ });
66
+ }}
67
+ >
68
+ {props.children}
69
+ </a>
70
+ {Boolean(props.config) && (
71
+ <ul>
72
+ {Object.entries(props.config).map(
73
+ ([key, configGroup]) =>
74
+ filterGroupItemsValues(
75
+ configGroup.choices || configGroup.decisions,
76
+ props.filterText
77
+ ).length > 0 && (
78
+ <li key={key}>
79
+ <a
80
+ href={`#${props.id}-${configGroup.prefix}`}
81
+ onClick={(event) => {
82
+ event.preventDefault();
83
+ window.scrollTo({
84
+ top: document.getElementById(
85
+ `${props.id}-${configGroup.prefix}`
86
+ ).offsetTop,
87
+ behavior: 'smooth',
88
+ });
89
+ }}
90
+ >
91
+ {configGroup.label}
92
+ </a>
93
+ </li>
94
+ )
95
+ )}
96
+ </ul>
97
+ )}
98
+ </>
99
+ );
100
+ };
101
+ TokenGroupLinks.propTypes = {
102
+ id: PropTypes.string.isRequired,
103
+ config: PropTypes.object,
104
+ filterText: PropTypes.string,
105
+ children: PropTypes.node.isRequired,
106
+ };
107
+
108
+ const TableBody = (props) => {
109
+ return (
110
+ <tbody>
111
+ {props.groupItems.map(([tokenName, tokenData]) => {
112
+ return (
113
+ <tr key={`${props.groupItemsPrefix}-${tokenName}-body-row-key`}>
114
+ {props.columnsConfig.map((columnConfig) => (
115
+ <td
116
+ key={`${props.groupItemsPrefix}-${tokenName}-${columnConfig.key}-body-cell-key`}
117
+ >
118
+ {props.cellRenderer({
119
+ columnKey: columnConfig.key,
120
+ groupItemsPrefix: props.groupItemsPrefix,
121
+ tokenName,
122
+ tokenData,
123
+ themeName: props.themeName,
124
+ })}
125
+ </td>
126
+ ))}
127
+ </tr>
128
+ );
129
+ })}
130
+ </tbody>
131
+ );
132
+ };
133
+ TableBody.propTypes = {
134
+ groupItems: PropTypes.array.isRequired,
135
+ groupItemsPrefix: PropTypes.string,
136
+ themeName: PropTypes.string.isRequired,
137
+ columnsConfig: PropTypes.arrayOf(
138
+ PropTypes.shape({
139
+ key: PropTypes.string.isRequired,
140
+ label: PropTypes.string,
141
+ })
142
+ ).isRequired,
143
+ cellRenderer: PropTypes.func.isRequired,
144
+ };
145
+
146
+ const TokensDetailsTable = (props) => (
147
+ <Table>
148
+ <thead>
149
+ <tr>
150
+ {props.columnsConfig.map((columnsConfig, index) => (
151
+ <td
152
+ key={columnsConfig.key}
153
+ style={{
154
+ minWidth: index === 0 ? 400 : 'auto',
155
+ }}
156
+ >
157
+ {columnsConfig.label || upperFirst(columnsConfig.key)}
158
+ </td>
159
+ ))}
160
+ </tr>
161
+ </thead>
162
+ <TableBody
163
+ groupItems={props.tokensGroupData}
164
+ groupItemsPrefix={props.tokensGroupPrefix}
165
+ themeName={props.themeName}
166
+ columnsConfig={props.columnsConfig}
167
+ cellRenderer={props.cellRenderer}
168
+ />
169
+ </Table>
170
+ );
171
+ TokensDetailsTable.propTypes = {
172
+ columnsConfig: PropTypes.arrayOf(
173
+ PropTypes.shape({
174
+ key: PropTypes.string.isRequired,
175
+ label: PropTypes.string,
176
+ })
177
+ ).isRequired,
178
+ cellRenderer: PropTypes.func.isRequired,
179
+ themeName: PropTypes.string.isRequired,
180
+ tokensGroupPrefix: PropTypes.string,
181
+ tokensGroupData: PropTypes.array.isRequired,
182
+ };
183
+
184
+ export function SingleTokensGroupDetails(props) {
185
+ const filteredGroupItems = filterGroupItemsValues(
186
+ props.groupItems,
187
+ props.filterText
188
+ );
189
+
190
+ return (
191
+ <section>
192
+ <h2 id={props.id}>{props.title || upperFirst(props.id)}</h2>
193
+ {props.subtitle && <p>{props.subtitle}</p>}
194
+ <GroupStyle isVisible={filteredGroupItems.length > 0}>
195
+ <TokensDetailsTable
196
+ columnsConfig={props.columnsConfig}
197
+ cellRenderer={props.cellRenderer}
198
+ themeName={props.themeName}
199
+ tokensGroupPrefix=""
200
+ tokensGroupData={filteredGroupItems}
201
+ />
202
+ </GroupStyle>
203
+ </section>
204
+ );
205
+ }
206
+ SingleTokensGroupDetails.propTypes = {
207
+ id: PropTypes.string.isRequired,
208
+ title: PropTypes.string,
209
+ subtitle: PropTypes.string,
210
+ filterText: PropTypes.string.isRequired,
211
+ groupItems: PropTypes.object.isRequired,
212
+ columnsConfig: PropTypes.arrayOf(
213
+ PropTypes.shape({
214
+ key: PropTypes.string.isRequired,
215
+ label: PropTypes.string,
216
+ })
217
+ ).isRequired,
218
+ cellRenderer: PropTypes.func.isRequired,
219
+ themeName: PropTypes.string.isRequired,
220
+ };
221
+
222
+ export const MultiTokensGroupDetails = (props) => (
223
+ <section>
224
+ <h2 id={props.id}>{props.title || upperFirst(props.id)}</h2>
225
+ {props.subtitle && <p>{props.subtitle}</p>}
226
+ {Object.entries(props.tokensGroupData).map(
227
+ ([tokenGroupKey, tokenGroupConfig]) => {
228
+ const filteredTokensGroups = filterGroupItemsValues(
229
+ tokenGroupConfig[props.id],
230
+ props.filterText
231
+ );
232
+
233
+ return (
234
+ <GroupStyle
235
+ key={`tokens-group_${tokenGroupKey}`}
236
+ isVisible={filteredTokensGroups.length > 0}
237
+ >
238
+ <a id={`${props.id}-${tokenGroupConfig.prefix}`} />
239
+ <h3>{tokenGroupConfig.label}</h3>
240
+ {Boolean(tokenGroupConfig.description) && (
241
+ <p>{tokenGroupConfig.description}</p>
242
+ )}
243
+ <TokensDetailsTable
244
+ columnsConfig={props.columnsConfig}
245
+ cellRenderer={props.cellRenderer}
246
+ themeName={props.themeName}
247
+ tokensGroupPrefix={tokenGroupConfig.prefix}
248
+ tokensGroupData={filteredTokensGroups}
249
+ />
250
+ </GroupStyle>
251
+ );
252
+ }
253
+ )}
254
+ </section>
255
+ );
256
+ MultiTokensGroupDetails.propTypes = {
257
+ id: PropTypes.string.isRequired,
258
+ title: PropTypes.string,
259
+ subtitle: PropTypes.string,
260
+ filterText: PropTypes.string.isRequired,
261
+ tokensGroupData: PropTypes.object.isRequired,
262
+ columnsConfig: PropTypes.arrayOf(
263
+ PropTypes.shape({
264
+ key: PropTypes.string.isRequired,
265
+ label: PropTypes.string,
266
+ })
267
+ ).isRequired,
268
+ cellRenderer: PropTypes.func.isRequired,
269
+ themeName: PropTypes.string.isRequired,
270
+ };
@@ -1,36 +1,26 @@
1
- import { Component } from 'react';
2
- import PropTypes from 'prop-types';
1
+ /* eslint-disable default-case */
2
+ import { useCallback, useMemo, useState } from 'react';
3
3
  import { storiesOf } from '@storybook/react';
4
4
  import styled from '@emotion/styled';
5
- import TextInput from '@commercetools-uikit/text-input';
6
5
  import merge from 'lodash/merge';
7
- import { designTokens } from '@commercetools-uikit/design-system';
6
+ import TextInput from '@commercetools-uikit/text-input';
7
+ import { designTokens, useTheme } from '@commercetools-uikit/design-system';
8
8
  import Readme from './TOKENS.md';
9
9
  import definition from './definition.yaml';
10
- import deprecatedTokens from './deprecated-tokens';
11
-
12
- const choiceGroupsByTheme =
13
- process.env.NODE_ENV !== 'production'
14
- ? definition.choiceGroupsByTheme
15
- : { default: definition.choiceGroupsByTheme.default };
16
- const allThemesNames = Object.keys(choiceGroupsByTheme);
17
-
18
- const getIsDeprecated = (token) => deprecatedTokens.includes(token);
19
-
20
- const Table = styled.table`
21
- border: 1px solid #ccc;
22
- border-collapse: collapse;
23
- & tr td {
24
- border: 1px solid #ccc;
25
- padding: 15px;
26
- text-align: left;
27
- }
28
- & thead td {
29
- background-color: gray;
30
- color: white;
31
- font-weight: bold;
32
- }
33
- `;
10
+ import {
11
+ MultiTokensGroupDetails,
12
+ Token,
13
+ TokenBodyCell,
14
+ TokenGroupLinks,
15
+ SingleTokensGroupDetails,
16
+ } from './story/shared-components';
17
+ import { getSampleComponent } from './story/samplers';
18
+
19
+ const findChoiceValue = (theme, choiceName) => {
20
+ return Object.values(theme)
21
+ .map((choiceGroup) => choiceGroup.choices)
22
+ .find((choices) => choices[choiceName])?.[choiceName];
23
+ };
34
24
 
35
25
  const Background = styled.div`
36
26
  background-color: rgba(0, 0, 0, 0.01);
@@ -42,668 +32,181 @@ const Background = styled.div`
42
32
  }
43
33
  `;
44
34
 
45
- const GroupStyle = styled.div`
46
- padding: 10px;
47
- display: ${(props) => (props.isVisible ? 'block' : 'none')};
48
- `;
49
-
50
- const Token = styled.p`
51
- font-family: monospace;
52
- `;
53
-
54
- const TokenRow = styled.td`
55
- min-width: 400px;
56
- `;
57
-
58
- const Description = styled.p`
59
- font-size: 10pt;
60
- margin: 10px 0;
35
+ const DetailsGroupsContainer = styled.main`
36
+ display: flex;
37
+ flex-direction: column;
38
+ gap: 40px;
61
39
  `;
62
40
 
63
- const DeprecationBadge = () => <b style={{ color: 'orange' }}>DEPRECATED</b>;
64
- DeprecationBadge.displayName = 'DeprecationBadge';
65
-
66
- const getThemeChoiceByName = (theme, choiceName) =>
67
- Object.values(theme)
68
- .map((choiceGroup) => choiceGroup.choices)
69
- .find((choices) => choices[choiceName]);
70
-
71
- const getChoiceValue = (choiceName, theme) => {
72
- const defaultChoice = getThemeChoiceByName(
73
- choiceGroupsByTheme.default,
74
- choiceName
75
- );
76
-
77
- const themeChoice = getThemeChoiceByName(
78
- choiceGroupsByTheme[theme],
79
- choiceName
80
- );
81
-
82
- return defaultChoice
83
- ? themeChoice?.[choiceName] ?? defaultChoice[choiceName]
84
- : undefined;
41
+ const BasicCellRenderer = (cellData) => {
42
+ if (cellData.columnKey !== 'description') {
43
+ return <TokenBodyCell tokenName={cellData.tokenName} />;
44
+ } else {
45
+ return cellData.tokenData.description;
46
+ }
85
47
  };
86
48
 
87
- const filterChoiceGroupValues = (choices, searchText) =>
88
- Object.entries(choices).filter(
89
- ([key, value]) =>
90
- key.toLowerCase().includes(searchText.toLowerCase()) ||
91
- value.toLowerCase().includes(searchText.toLowerCase())
92
- );
93
-
94
- const filterDecisionGroupValues = (decisions, searchText) =>
95
- Object.entries(decisions).filter(
96
- ([key, decision]) =>
97
- key.toLowerCase().includes(searchText.toLowerCase()) ||
98
- decision.choice.toLowerCase().includes(searchText.toLowerCase()) ||
99
- getChoiceValue(decision.choice)
100
- .toLowerCase()
101
- .includes(searchText.toLowerCase())
102
- );
103
-
104
- const filterStatesGroupValues = (states, searchText) =>
105
- Object.entries(states).filter(
106
- ([key, state]) =>
107
- key.toLowerCase().includes(searchText.toLowerCase()) ||
108
- (state.description &&
109
- state.description.toLowerCase().includes(searchText.toLowerCase()))
110
- );
111
-
112
- const filterComponentGroupsGroupValues = (componentGroups, searchText) =>
113
- Object.entries(componentGroups).filter(
114
- ([key, state]) =>
115
- key.toLowerCase().includes(searchText.toLowerCase()) ||
116
- (state.description &&
117
- state.description.toLowerCase().includes(searchText.toLowerCase()))
118
- );
119
-
120
- const filterVariantsGroupValues = (variants, searchText) =>
121
- Object.entries(variants).filter(
122
- ([key, state]) =>
123
- key.toLowerCase().includes(searchText.toLowerCase()) ||
124
- (state.description &&
125
- state.description.toLowerCase().includes(searchText.toLowerCase()))
126
- );
127
-
128
- const getDefaultThemeChoiceGroupProperty = (choiceGroup, property) =>
129
- choiceGroupsByTheme.default[choiceGroup][property];
130
-
131
- const ChoiceGroup = (props) => {
132
- const choices = Object.entries(choiceGroupsByTheme).reduce(
133
- (acc, [theme, themeChoices]) => {
134
- // default theme is used as a blueprint
135
- const themeChoicesBasedOnDefaultTheme = merge(
49
+ function Story() {
50
+ const [filterText, setFilterText] = useState('');
51
+ const { theme } = useTheme();
52
+ const currentThemeChoices = useMemo(() => {
53
+ return merge(
54
+ {},
55
+ definition.choiceGroupsByTheme.default,
56
+ definition.choiceGroupsByTheme[theme]
57
+ );
58
+ }, [theme]);
59
+ const currentThemeDecisions = useMemo(
60
+ () =>
61
+ merge(
136
62
  {},
137
- choiceGroupsByTheme.default,
138
- themeChoices
139
- );
140
- const filteredThemeChoices = Object.fromEntries(
141
- filterChoiceGroupValues(
142
- themeChoicesBasedOnDefaultTheme[props.choiceGroup].choices,
143
- props.searchText
144
- )
145
- );
146
- const filteredThemeChoicesNames = Object.keys(filteredThemeChoices);
147
-
148
- return merge(
149
- acc,
150
- ...filteredThemeChoicesNames.map((name) => ({
151
- [name]: { [theme]: filteredThemeChoices[name] },
152
- }))
153
- );
154
- },
155
- {}
63
+ definition.decisionGroupsByTheme.default,
64
+ definition.decisionGroupsByTheme[theme]
65
+ ),
66
+ [theme]
156
67
  );
157
68
 
158
- return (
159
- <GroupStyle isVisible={Object.values(choices).length > 0}>
160
- <a
161
- id={`choice-${getDefaultThemeChoiceGroupProperty(
162
- props.choiceGroup,
163
- 'prefix'
164
- )}`}
165
- />
166
- <h3>{getDefaultThemeChoiceGroupProperty(props.choiceGroup, 'label')}</h3>
167
- {getDefaultThemeChoiceGroupProperty(props.choiceGroup, 'description') && (
168
- <p>
169
- {getDefaultThemeChoiceGroupProperty(props.choiceGroup, 'description')}
170
- </p>
171
- )}
172
- <Table>
173
- <thead>
174
- <tr>
175
- <TokenRow>Token</TokenRow>
176
- {allThemesNames.map((theme) => {
177
- return <td key={theme}>{theme}</td>;
178
- })}
179
- </tr>
180
- </thead>
181
- <tbody>
182
- {Object.entries(choices).map(([name, values]) => (
183
- <tr key={name}>
184
- <td>
185
- <>
186
- <Token>{name}</Token>
187
- {getIsDeprecated(name) && <DeprecationBadge />}
188
- </>
189
- </td>
190
- {Object.entries(values).map(([theme, value]) => (
191
- <td key={theme}>{props.renderSample(value)}</td>
192
- ))}
193
- </tr>
194
- ))}
195
- </tbody>
196
- </Table>
197
- </GroupStyle>
198
- );
199
- };
200
- ChoiceGroup.displayName = 'ChoiceGroup';
201
- ChoiceGroup.propTypes = {
202
- searchText: PropTypes.string.isRequired,
203
- choiceGroup: PropTypes.shape({
204
- label: PropTypes.string.isRequired,
205
- prefix: PropTypes.string.isRequired,
206
- description: PropTypes.string,
207
- choices: PropTypes.objectOf(PropTypes.string),
208
- }).isRequired,
209
- renderSample: PropTypes.func.isRequired,
210
- };
211
- ChoiceGroup.defaultProps = {
212
- renderSample: (value) => value,
213
- };
214
-
215
- const DecisionGroup = (props) => {
216
- const decisions = filterDecisionGroupValues(
217
- props.decisionGroup.decisions,
218
- props.searchText
219
- );
220
- return (
221
- <GroupStyle isVisible={decisions.length > 0}>
222
- <a id={`decision-${props.decisionGroup.prefix}`} />
223
- <h3>{props.decisionGroup.label}</h3>
224
- <Table>
225
- <thead>
226
- <tr>
227
- <TokenRow>Token</TokenRow>
228
- <td>Choice</td>
229
- {allThemesNames.map((theme) => {
230
- return <td key={theme}>{theme}</td>;
231
- })}
232
- </tr>
233
- </thead>
234
- <tbody>
235
- {decisions.map(([name, decision]) => (
236
- <tr key={name}>
237
- <td>
238
- <Token>{name}</Token>
239
- <Description>{decision.description}</Description>
240
- {decision.deprecated && <DeprecationBadge />}
241
- </td>
242
- <td>
243
- <Token>{decision.choice}</Token>
244
- </td>
245
- {allThemesNames.map((theme) => {
246
- return (
247
- <td key={theme}>
248
- {props.renderSample(
249
- getChoiceValue(decision.choice, theme),
250
- name
251
- )}
252
- </td>
253
- );
254
- })}
255
- </tr>
256
- ))}
257
- </tbody>
258
- </Table>
259
- </GroupStyle>
260
- );
261
- };
262
- DecisionGroup.displayName = 'DecisionGroup';
263
- DecisionGroup.propTypes = {
264
- searchText: PropTypes.string.isRequired,
265
- decisionGroup: PropTypes.shape({
266
- label: PropTypes.string.isRequired,
267
- prefix: PropTypes.string.isRequired,
268
- decisions: PropTypes.shape({
269
- choice: PropTypes.string.isRequired,
270
- description: PropTypes.string,
271
- }),
272
- }).isRequired,
273
- renderSample: PropTypes.func.isRequired,
274
- };
275
- DecisionGroup.defaultProps = {
276
- renderSample: (value) => value,
277
- };
278
-
279
- const StatesGroup = (props) => {
280
- const states = filterStatesGroupValues(props.states, props.searchText);
281
- return (
282
- <GroupStyle isVisible={states.length > 0}>
283
- <Table>
284
- <thead>
285
- <tr>
286
- <TokenRow>State</TokenRow>
287
- <td>Description</td>
288
- </tr>
289
- </thead>
290
- <tbody>
291
- {states.map(([name, state]) => (
292
- <tr key={name}>
293
- <td>
294
- <Token>{name}</Token>
295
- {state.deprecated && <DeprecationBadge />}
296
- </td>
297
- <td>{state.description}</td>
298
- </tr>
299
- ))}
300
- </tbody>
301
- </Table>
302
- </GroupStyle>
303
- );
304
- };
305
- StatesGroup.displayName = 'StatesGroup';
306
- StatesGroup.propTypes = {
307
- searchText: PropTypes.string.isRequired,
308
- states: PropTypes.shape({
309
- decisions: PropTypes.objectOf(PropTypes.string),
310
- description: PropTypes.string,
311
- }).isRequired,
312
- };
313
-
314
- const ComponentGroupsGroup = (props) => {
315
- const componentGroups = filterComponentGroupsGroupValues(
316
- props.states,
317
- props.searchText
318
- );
319
- return (
320
- <GroupStyle isVisible={componentGroups.length > 0}>
321
- <Table>
322
- <thead>
323
- <tr>
324
- <TokenRow>State</TokenRow>
325
- <td>Description</td>
326
- </tr>
327
- </thead>
328
- <tbody>
329
- {componentGroups.map(([name, componentGroup]) => (
330
- <tr key={name}>
331
- <td>
332
- <Token>{name}</Token>
333
- {componentGroup.deprecated && <DeprecationBadge />}
334
- </td>
335
- <td>{componentGroup.description}</td>
336
- </tr>
337
- ))}
338
- </tbody>
339
- </Table>
340
- </GroupStyle>
341
- );
342
- };
343
- ComponentGroupsGroup.displayName = 'ComponentGroupsGroup';
344
- ComponentGroupsGroup.propTypes = {
345
- searchText: PropTypes.string.isRequired,
346
- states: PropTypes.shape({
347
- decisions: PropTypes.objectOf(PropTypes.string),
348
- }).isRequired,
349
- };
69
+ const searchTextChangeHandler = useCallback((event) => {
70
+ setFilterText(event.target.value);
71
+ }, []);
350
72
 
351
- const VariantsGroup = (props) => {
352
- const variants = filterVariantsGroupValues(props.states, props.searchText);
353
73
  return (
354
- <GroupStyle isVisible={variants.length > 0}>
355
- <Table>
356
- <thead>
357
- <tr>
358
- <TokenRow>State</TokenRow>
359
- <td>Description</td>
360
- </tr>
361
- </thead>
362
- <tbody>
363
- {variants.map(([name, variant]) => (
364
- <tr key={name}>
365
- <td>
366
- <Token>{name}</Token>
367
- {variant.deprecated && <DeprecationBadge />}
368
- </td>
369
- <td>{variant.description}</td>
370
- </tr>
371
- ))}
372
- </tbody>
373
- </Table>
374
- </GroupStyle>
375
- );
376
- };
377
- VariantsGroup.displayName = 'VariantsGroup';
378
- VariantsGroup.propTypes = {
379
- searchText: PropTypes.string.isRequired,
380
- states: PropTypes.shape({
381
- decisions: PropTypes.objectOf(PropTypes.string),
382
- description: PropTypes.string,
383
- }).isRequired,
384
- };
385
-
386
- const ColorSample = styled.div`
387
- width: 30px;
388
- height: 30px;
389
- background-color: ${(props) => props.color};
390
- box-shadow: inset 0 0 5px 0 rgba(0, 0, 0, 0.1);
391
- display: inline-block;
392
- `;
393
-
394
- const FontColorSampleStyle = styled.div`
395
- color: ${(props) => props.color};
396
- font-size: 24pt;
397
- font-weight: bolder;
398
- display: inline-block;
399
- `;
400
-
401
- const FontColorSample = (props) => (
402
- <FontColorSampleStyle {...props}>Aa</FontColorSampleStyle>
403
- );
404
- FontColorSample.displayName = 'FontColorSample';
405
-
406
- const BorderRadiusSample = styled.div`
407
- width: calc(
408
- ${(props) => props.borderRadius} + 2 * ${(props) => props.borderRadius}
409
- );
410
- min-width: 20px;
411
- height: calc(
412
- ${(props) => props.borderRadius} + 2 * ${(props) => props.borderRadius}
413
- );
414
- min-height: 20px;
415
- background-color: pink;
416
- border-radius: ${(props) => props.borderRadius};
417
- display: inline-block;
418
- margin: 0 10px;
419
- `;
420
-
421
- const ShadowSample = styled.div`
422
- width: 50px;
423
- height: 50px;
424
- box-shadow: ${(props) => props.shadow};
425
- display: inline-block;
426
- margin: 0 10px;
427
- `;
428
-
429
- const SpacingSample = styled.div`
430
- width: ${(props) => props.spacing};
431
- height: ${(props) => props.spacing};
432
- background-color: lightblue;
433
- display: inline-block;
434
- margin: 0 10px;
435
- `;
436
-
437
- class Story extends Component {
438
- static displayName = 'Story';
439
-
440
- state = {
441
- searchText: '',
442
- };
443
-
444
- render() {
445
- return (
446
- <Background>
74
+ <Background>
75
+ <header>
447
76
  <TextInput
448
- value={this.state.searchText}
449
- onChange={(event) => {
450
- this.setState({ searchText: event.target.value });
451
- }}
452
- horizontalConstraint="m"
77
+ value={filterText}
78
+ onChange={searchTextChangeHandler}
79
+ horizontalConstraint={13}
453
80
  />
454
81
  <h2>Table of Contents</h2>
455
82
  <ul>
456
83
  <li>
457
- <a
458
- href="#choices"
459
- onClick={(event) => {
460
- event.preventDefault();
461
- window.scrollTo(
462
- 0,
463
- document.getElementById('choices').offsetTop
464
- );
465
- }}
84
+ <TokenGroupLinks
85
+ id="choices"
86
+ config={currentThemeChoices}
87
+ filterText={filterText}
466
88
  >
467
89
  Choices
468
- </a>
469
- <ul>
470
- {Object.entries(choiceGroupsByTheme.default).map(
471
- ([key, choiceGroup]) =>
472
- filterChoiceGroupValues(
473
- choiceGroup.choices,
474
- this.state.searchText
475
- ).length > 0 && (
476
- <li key={key}>
477
- <a
478
- href={`#${choiceGroup.prefix}`}
479
- onClick={(event) => {
480
- event.preventDefault();
481
- window.scrollTo(
482
- 0,
483
- document.getElementById(
484
- `choice-${choiceGroup.prefix}`
485
- ).offsetTop
486
- );
487
- }}
488
- >
489
- {choiceGroup.label}
490
- </a>
491
- </li>
492
- )
493
- )}
494
- </ul>
90
+ </TokenGroupLinks>
495
91
  </li>
496
92
  <li>
497
- <a
498
- href="#states"
499
- onClick={(event) => {
500
- event.preventDefault();
501
- window.scrollTo(0, document.getElementById('states').offsetTop);
502
- }}
503
- >
504
- States
505
- </a>
93
+ <TokenGroupLinks id="states">States</TokenGroupLinks>
506
94
  </li>
507
95
  <li>
508
- <a
509
- href="#component-groups"
510
- onClick={(event) => {
511
- event.preventDefault();
512
- window.scrollTo(
513
- 0,
514
- document.getElementById('component-groups').offsetTop
515
- );
516
- }}
517
- >
96
+ <TokenGroupLinks id="component-groups">
518
97
  Component Groups
519
- </a>
98
+ </TokenGroupLinks>
520
99
  </li>
521
100
  <li>
522
- <a
523
- href="#variants"
524
- onClick={(event) => {
525
- event.preventDefault();
526
- window.scrollTo(
527
- 0,
528
- document.getElementById('variants').offsetTop
529
- );
530
- }}
531
- >
532
- Variants
533
- </a>
101
+ <TokenGroupLinks id="variants">Variants</TokenGroupLinks>
534
102
  </li>
535
103
  <li>
536
- {' '}
537
- <a
538
- href="#decisions"
539
- onClick={(event) => {
540
- event.preventDefault();
541
- window.scrollTo(
542
- 0,
543
- document.getElementById('decisions').offsetTop
544
- );
545
- }}
104
+ <TokenGroupLinks
105
+ id="decisions"
106
+ config={currentThemeDecisions}
107
+ filterText={filterText}
546
108
  >
547
109
  Decisions
548
- </a>{' '}
549
- <ul>
550
- {Object.entries(definition.decisionGroupsByTheme.default).map(
551
- ([key, decisionGroup]) =>
552
- filterDecisionGroupValues(
553
- decisionGroup.decisions,
554
- this.state.searchText
555
- ).length > 0 && (
556
- <li key={key}>
557
- <a
558
- href={`#${decisionGroup.prefix}`}
559
- onClick={(event) => {
560
- event.preventDefault();
561
- window.scrollTo(
562
- 0,
563
- document.getElementById(
564
- `decision-${decisionGroup.prefix}`
565
- ).offsetTop
566
- );
567
- }}
568
- >
569
- {decisionGroup.label}
570
- </a>
571
- </li>
572
- )
573
- )}
574
- </ul>
110
+ </TokenGroupLinks>
575
111
  </li>
576
112
  </ul>
577
-
578
- <h2 id="choices">Choices</h2>
579
- <p>
580
- This is the palette of values you may chose from when creating design
581
- tokens.
582
- </p>
583
- <ChoiceGroup
584
- choiceGroup="colors"
585
- searchText={this.state.searchText}
586
- renderSample={(value) => (
587
- <>
588
- <ColorSample color={value} /> {value}
589
- </>
590
- )}
591
- />
592
- <ChoiceGroup
593
- choiceGroup="borderRadiuses"
594
- searchText={this.state.searchText}
595
- renderSample={(value) => (
596
- <>
597
- <BorderRadiusSample borderRadius={value} /> {value}
598
- </>
599
- )}
600
- />
601
- <ChoiceGroup
602
- choiceGroup="shadows"
603
- searchText={this.state.searchText}
604
- renderSample={(value) => (
605
- <>
606
- <ShadowSample shadow={value} /> {value}
607
- </>
608
- )}
609
- />
610
- <ChoiceGroup
611
- choiceGroup="constraints"
612
- searchText={this.state.searchText}
613
- />
614
- <ChoiceGroup
615
- choiceGroup="spacings"
616
- searchText={this.state.searchText}
617
- renderSample={(value) => (
618
- <>
619
- <SpacingSample spacing={value} /> {value}
620
- </>
621
- )}
622
- />
623
- <ChoiceGroup
624
- choiceGroup="transitions"
625
- searchText={this.state.searchText}
626
- />
627
- <ChoiceGroup
628
- choiceGroup="breakpoints"
629
- searchText={this.state.searchText}
630
- />
631
-
632
- <h2 id="states">States</h2>
633
- <StatesGroup
634
- states={definition.states}
635
- searchText={this.state.searchText}
636
- />
637
-
638
- <h2 id="component-groups">Component Groups</h2>
639
- <ComponentGroupsGroup
640
- states={definition.componentGroups}
641
- searchText={this.state.searchText}
642
- />
643
-
644
- <h2 id="variants">Variants</h2>
645
- <VariantsGroup
646
- states={definition.variants}
647
- searchText={this.state.searchText}
648
- />
649
-
650
- <h2 id="decisions">Decisions</h2>
651
- <p>
652
- These are specific decisions where a choice gets applied to an element
653
- (optionally in a certain state).
654
- </p>
655
- <DecisionGroup
656
- decisionGroup={
657
- definition.decisionGroupsByTheme.default.backgroundColors
658
- }
659
- searchText={this.state.searchText}
660
- renderSample={(value) => (
661
- <>
662
- <ColorSample color={value} /> {value}
663
- </>
664
- )}
665
- />
666
- <DecisionGroup
667
- decisionGroup={definition.decisionGroupsByTheme.default.borderColors}
668
- searchText={this.state.searchText}
669
- renderSample={(value) => (
670
- <>
671
- <ColorSample color={value} /> {value}
672
- </>
673
- )}
674
- />
675
- <DecisionGroup
676
- decisionGroup={
677
- definition.decisionGroupsByTheme.default.borderRadiuses
678
- }
679
- searchText={this.state.searchText}
680
- renderSample={(value) => (
681
- <>
682
- <BorderRadiusSample borderRadius={value} /> {value}
683
- </>
684
- )}
685
- />
686
- <DecisionGroup
687
- decisionGroup={definition.decisionGroupsByTheme.default.fontColors}
688
- searchText={this.state.searchText}
689
- renderSample={(value) => (
690
- <>
691
- <FontColorSample color={value} /> {value}
692
- </>
693
- )}
694
- />
695
- <DecisionGroup
696
- decisionGroup={definition.decisionGroupsByTheme.default.shadows}
697
- searchText={this.state.searchText}
698
- renderSample={(value) => (
699
- <>
700
- <ShadowSample shadow={value} /> {value}
701
- </>
702
- )}
113
+ </header>
114
+
115
+ <DetailsGroupsContainer>
116
+ <MultiTokensGroupDetails
117
+ id="choices"
118
+ subtitle="This is the palette of values you may chose from when creating design tokens."
119
+ themeName={theme}
120
+ filterText={filterText}
121
+ columnsConfig={[{ key: 'token' }, { key: 'value' }]}
122
+ cellRenderer={(data) => {
123
+ if (data.columnKey === 'token') {
124
+ return <Token>{data.tokenName}</Token>;
125
+ } else {
126
+ const ChoiceSample = getSampleComponent(data.groupItemsPrefix);
127
+ return (
128
+ <>
129
+ <ChoiceSample value={data.tokenData} />
130
+ &nbsp;{data.tokenData}
131
+ </>
132
+ );
133
+ }
134
+ }}
135
+ tokensGroupData={currentThemeChoices}
136
+ />
137
+
138
+ <SingleTokensGroupDetails
139
+ id="states"
140
+ columnsConfig={[{ key: 'state' }, { key: 'description' }]}
141
+ cellRenderer={BasicCellRenderer}
142
+ groupItems={definition.states}
143
+ themeName={theme}
144
+ filterText={filterText}
145
+ />
146
+
147
+ <SingleTokensGroupDetails
148
+ id="component-groups"
149
+ title="Component Groups"
150
+ columnsConfig={[
151
+ { key: 'component-group', label: 'Component Group' },
152
+ { key: 'description' },
153
+ ]}
154
+ cellRenderer={BasicCellRenderer}
155
+ groupItems={definition.componentGroups}
156
+ themeName={theme}
157
+ filterText={filterText}
158
+ />
159
+
160
+ <SingleTokensGroupDetails
161
+ id="variants"
162
+ columnsConfig={[{ key: 'variant' }, { key: 'description' }]}
163
+ cellRenderer={BasicCellRenderer}
164
+ groupItems={definition.variants}
165
+ themeName={theme}
166
+ filterText={filterText}
167
+ />
168
+
169
+ <MultiTokensGroupDetails
170
+ id="decisions"
171
+ subtitle="These are specific decisions where a choice gets applied to an element (optionally in a certain state)."
172
+ themeName={theme}
173
+ filterText={filterText}
174
+ columnsConfig={[
175
+ { key: 'token' },
176
+ { key: 'choice' },
177
+ { key: 'value' },
178
+ ]}
179
+ cellRenderer={(data) => {
180
+ switch (data.columnKey) {
181
+ case 'token':
182
+ return <Token>{data.tokenName}</Token>;
183
+ case 'choice':
184
+ return <Token>{data.tokenData.choice}</Token>;
185
+ case 'value':
186
+ const ChoiceSample = getSampleComponent(data.groupItemsPrefix);
187
+ const choiceValue = findChoiceValue(
188
+ currentThemeChoices,
189
+ data.tokenData.choice
190
+ );
191
+ if (choiceValue) {
192
+ return (
193
+ <>
194
+ <ChoiceSample value={choiceValue} />
195
+ &nbsp;{choiceValue}
196
+ </>
197
+ );
198
+ } else {
199
+ return <Token>---</Token>;
200
+ }
201
+ default:
202
+ return null;
203
+ }
204
+ }}
205
+ tokensGroupData={currentThemeDecisions}
703
206
  />
704
- </Background>
705
- );
706
- }
207
+ </DetailsGroupsContainer>
208
+ </Background>
209
+ );
707
210
  }
708
211
 
709
212
  storiesOf('Basics|Tokens', module)
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@commercetools-frontend/ui-kit",
3
3
  "description": "A preset of all the UI-Kit components.",
4
- "version": "15.14.0",
4
+ "version": "15.14.2",
5
5
  "bugs": "https://github.com/commercetools/ui-kit/issues",
6
6
  "repository": {
7
7
  "type": "git",
@@ -24,44 +24,44 @@
24
24
  "dependencies": {
25
25
  "@babel/runtime": "^7.20.13",
26
26
  "@babel/runtime-corejs3": "^7.20.13",
27
- "@commercetools-uikit/accessible-hidden": "15.14.0",
28
- "@commercetools-uikit/avatar": "15.14.0",
29
- "@commercetools-uikit/buttons": "15.14.0",
30
- "@commercetools-uikit/card": "15.14.0",
31
- "@commercetools-uikit/collapsible": "15.14.0",
32
- "@commercetools-uikit/collapsible-motion": "15.14.0",
33
- "@commercetools-uikit/collapsible-panel": "15.14.0",
34
- "@commercetools-uikit/constraints": "15.14.0",
35
- "@commercetools-uikit/data-table": "15.14.0",
36
- "@commercetools-uikit/data-table-manager": "15.14.0",
37
- "@commercetools-uikit/design-system": "15.14.0",
38
- "@commercetools-uikit/field-errors": "15.14.0",
39
- "@commercetools-uikit/field-label": "15.14.0",
40
- "@commercetools-uikit/fields": "15.14.0",
41
- "@commercetools-uikit/grid": "15.14.0",
42
- "@commercetools-uikit/hooks": "15.14.0",
43
- "@commercetools-uikit/i18n": "15.14.0",
44
- "@commercetools-uikit/icons": "15.14.0",
45
- "@commercetools-uikit/inputs": "15.14.0",
46
- "@commercetools-uikit/label": "15.14.0",
47
- "@commercetools-uikit/link": "15.14.0",
48
- "@commercetools-uikit/loading-spinner": "15.14.0",
49
- "@commercetools-uikit/messages": "15.14.0",
50
- "@commercetools-uikit/notifications": "15.14.0",
51
- "@commercetools-uikit/pagination": "15.14.0",
52
- "@commercetools-uikit/primary-action-dropdown": "15.14.0",
53
- "@commercetools-uikit/selectable-search-input": "15.14.0",
54
- "@commercetools-uikit/spacings": "15.14.0",
55
- "@commercetools-uikit/stamp": "15.14.0",
56
- "@commercetools-uikit/tag": "15.14.0",
57
- "@commercetools-uikit/text": "15.14.0",
58
- "@commercetools-uikit/tooltip": "15.14.0",
59
- "@commercetools-uikit/utils": "15.14.0",
60
- "@commercetools-uikit/view-switcher": "15.14.0"
27
+ "@commercetools-uikit/accessible-hidden": "15.14.2",
28
+ "@commercetools-uikit/avatar": "15.14.2",
29
+ "@commercetools-uikit/buttons": "15.14.2",
30
+ "@commercetools-uikit/card": "15.14.2",
31
+ "@commercetools-uikit/collapsible": "15.14.2",
32
+ "@commercetools-uikit/collapsible-motion": "15.14.2",
33
+ "@commercetools-uikit/collapsible-panel": "15.14.2",
34
+ "@commercetools-uikit/constraints": "15.14.2",
35
+ "@commercetools-uikit/data-table": "15.14.2",
36
+ "@commercetools-uikit/data-table-manager": "15.14.2",
37
+ "@commercetools-uikit/design-system": "15.14.2",
38
+ "@commercetools-uikit/field-errors": "15.14.2",
39
+ "@commercetools-uikit/field-label": "15.14.2",
40
+ "@commercetools-uikit/fields": "15.14.2",
41
+ "@commercetools-uikit/grid": "15.14.2",
42
+ "@commercetools-uikit/hooks": "15.14.2",
43
+ "@commercetools-uikit/i18n": "15.14.2",
44
+ "@commercetools-uikit/icons": "15.14.2",
45
+ "@commercetools-uikit/inputs": "15.14.2",
46
+ "@commercetools-uikit/label": "15.14.2",
47
+ "@commercetools-uikit/link": "15.14.2",
48
+ "@commercetools-uikit/loading-spinner": "15.14.2",
49
+ "@commercetools-uikit/messages": "15.14.2",
50
+ "@commercetools-uikit/notifications": "15.14.2",
51
+ "@commercetools-uikit/pagination": "15.14.2",
52
+ "@commercetools-uikit/primary-action-dropdown": "15.14.2",
53
+ "@commercetools-uikit/selectable-search-input": "15.14.2",
54
+ "@commercetools-uikit/spacings": "15.14.2",
55
+ "@commercetools-uikit/stamp": "15.14.2",
56
+ "@commercetools-uikit/tag": "15.14.2",
57
+ "@commercetools-uikit/text": "15.14.2",
58
+ "@commercetools-uikit/tooltip": "15.14.2",
59
+ "@commercetools-uikit/utils": "15.14.2",
60
+ "@commercetools-uikit/view-switcher": "15.14.2"
61
61
  },
62
62
  "devDependencies": {
63
63
  "moment": "2.29.4",
64
- "moment-timezone": "0.5.40",
64
+ "moment-timezone": "0.5.41",
65
65
  "react": "17.0.2",
66
66
  "react-intl": "^5.25.1",
67
67
  "react-router-dom": "5.3.4"