@khanacademy/wonder-blocks-cell 3.4.4 → 3.4.6

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.
@@ -1,356 +0,0 @@
1
- import * as React from "react";
2
- import {StyleSheet} from "aphrodite";
3
-
4
- import type {StyleType} from "@khanacademy/wonder-blocks-core";
5
-
6
- import Clickable from "@khanacademy/wonder-blocks-clickable";
7
- import {View} from "@khanacademy/wonder-blocks-core";
8
- import {Strut} from "@khanacademy/wonder-blocks-layout";
9
- import {color, spacing} from "@khanacademy/wonder-blocks-tokens";
10
-
11
- import {CellMeasurements, getHorizontalRuleStyles} from "./common";
12
-
13
- import type {CellProps} from "../../util/types";
14
-
15
- type LeftAccessoryProps = {
16
- leftAccessory?: CellProps["leftAccessory"];
17
- leftAccessoryStyle?: CellProps["leftAccessoryStyle"];
18
- disabled?: CellProps["disabled"];
19
- };
20
-
21
- /**
22
- * Left Accessories can be defined using WB components such as Icon, IconButton,
23
- * or it can even be used for a custom node/component if needed.
24
- */
25
- const LeftAccessory = ({
26
- leftAccessory,
27
- leftAccessoryStyle,
28
- disabled,
29
- }: LeftAccessoryProps): React.ReactElement => {
30
- if (!leftAccessory) {
31
- // @ts-expect-error [FEI-5019] - TS2322 - Type 'null' is not assignable to type 'ReactElement<any, string | JSXElementConstructor<any>>'.
32
- return null;
33
- }
34
-
35
- return (
36
- <>
37
- <View
38
- style={[
39
- styles.accessory,
40
- disabled && styles.accessoryDisabled,
41
- {...leftAccessoryStyle},
42
- ]}
43
- >
44
- {leftAccessory}
45
- </View>
46
- <Strut size={CellMeasurements.accessoryHorizontalSpacing} />
47
- </>
48
- );
49
- };
50
-
51
- type RightAccessoryProps = {
52
- rightAccessory?: CellProps["rightAccessory"];
53
- rightAccessoryStyle?: CellProps["rightAccessoryStyle"];
54
- active?: CellProps["active"];
55
- disabled?: CellProps["disabled"];
56
- };
57
-
58
- /**
59
- * Right Accessories can be defined using WB components such as Icon,
60
- * IconButton, or it can even be used for a custom node/component if needed.
61
- */
62
- const RightAccessory = ({
63
- rightAccessory,
64
- rightAccessoryStyle,
65
- active,
66
- disabled,
67
- }: RightAccessoryProps): React.ReactElement => {
68
- if (!rightAccessory) {
69
- // @ts-expect-error [FEI-5019] - TS2322 - Type 'null' is not assignable to type 'ReactElement<any, string | JSXElementConstructor<any>>'.
70
- return null;
71
- }
72
-
73
- return (
74
- <>
75
- <Strut size={CellMeasurements.accessoryHorizontalSpacing} />
76
- <View
77
- style={[
78
- styles.accessory,
79
- styles.accessoryRight,
80
- disabled && styles.accessoryDisabled,
81
- {...rightAccessoryStyle},
82
- active && styles.accessoryActive,
83
- ]}
84
- >
85
- {rightAccessory}
86
- </View>
87
- </>
88
- );
89
- };
90
-
91
- /**
92
- * The Cell inner wrapper is the main container for the Cell contents. It
93
- * doesn't include the optional Clickable wrapper, which is added by the Cell
94
- * component.
95
- */
96
- function CellInner(props: CellCoreProps): React.ReactElement {
97
- const {
98
- active,
99
- children,
100
- disabled,
101
- horizontalRule = "inset",
102
- contentStyle = undefined,
103
- leftAccessory = undefined,
104
- leftAccessoryStyle = undefined,
105
- rightAccessory = undefined,
106
- rightAccessoryStyle = undefined,
107
- style,
108
- testId,
109
- innerStyle,
110
- } = props;
111
- const horizontalRuleStyles = getHorizontalRuleStyles(horizontalRule);
112
-
113
- return (
114
- <View
115
- style={[
116
- styles.innerWrapper,
117
- innerStyle,
118
- // custom styles
119
- style,
120
- horizontalRuleStyles,
121
- ]}
122
- >
123
- {/* Left accessory */}
124
- <LeftAccessory
125
- leftAccessory={leftAccessory}
126
- leftAccessoryStyle={leftAccessoryStyle}
127
- disabled={disabled}
128
- />
129
-
130
- {/* Cell contents */}
131
- <View style={[styles.content, contentStyle]} testId={testId}>
132
- {children}
133
- </View>
134
-
135
- {/* Right accessory */}
136
- <RightAccessory
137
- rightAccessory={rightAccessory}
138
- rightAccessoryStyle={rightAccessoryStyle}
139
- active={active}
140
- disabled={disabled}
141
- />
142
- </View>
143
- );
144
- }
145
-
146
- type CellCoreProps = Partial<Omit<CellProps, "title">> & {
147
- /**
148
- * The content of the cell.
149
- */
150
- children: React.ReactNode;
151
- /**
152
- * The optional styles applied to the inner wrapper.
153
- *
154
- * Note: This is not intended to be used externally, only used directly
155
- * within the package scope.
156
- */
157
- innerStyle?: StyleType;
158
- };
159
-
160
- /**
161
- * CellCore is the base cell wrapper. It's used as the skeleton/layout that is
162
- * used by CompactCell and DetailCell (and any other variants).
163
- *
164
- * Both variants share how they render their accessories, and the main
165
- * responsibility of this component is to render the contents that are passed in
166
- * (using the `children` prop).
167
- */
168
- const CellCore = (props: CellCoreProps): React.ReactElement => {
169
- const {
170
- active,
171
- disabled,
172
- href,
173
- onClick,
174
- "aria-label": ariaLabel,
175
- "aria-selected": ariaSelected,
176
- "aria-checked": ariaChecked,
177
- target,
178
- role,
179
- rootStyle,
180
- } = props;
181
-
182
- // Pressable cell.
183
- if (onClick || href) {
184
- return (
185
- // @ts-expect-error - TypeScript doesn't know that `target` can only be defined when `href` is.
186
- <Clickable
187
- disabled={disabled}
188
- onClick={onClick}
189
- href={href}
190
- hideDefaultFocusRing={true}
191
- aria-label={ariaLabel ? ariaLabel : undefined}
192
- aria-selected={ariaSelected ? ariaSelected : undefined}
193
- aria-checked={ariaChecked}
194
- role={role}
195
- target={target}
196
- style={[
197
- styles.wrapper,
198
- styles.clickable,
199
- rootStyle,
200
- active && styles.active,
201
- disabled && styles.disabled,
202
- ]}
203
- aria-current={active ? "true" : undefined}
204
- >
205
- {() => <CellInner {...props} />}
206
- </Clickable>
207
- );
208
- }
209
-
210
- // No click event attached, so just render the cell without a Clickable
211
- // wrapper.
212
- return (
213
- <View
214
- style={[styles.wrapper, rootStyle, active && styles.active]}
215
- aria-current={active ? "true" : undefined}
216
- role={role}
217
- >
218
- <CellInner {...props} />
219
- </View>
220
- );
221
- };
222
-
223
- const styles = StyleSheet.create({
224
- wrapper: {
225
- background: color.white,
226
- color: color.offBlack,
227
- display: "flex",
228
- minHeight: CellMeasurements.cellMinHeight,
229
- textAlign: "left",
230
- width: "100%",
231
- },
232
-
233
- innerWrapper: {
234
- minHeight: CellMeasurements.cellMinHeight,
235
- padding: `${CellMeasurements.cellPadding.paddingVertical}px ${CellMeasurements.cellPadding.paddingHorizontal}px`,
236
- flexDirection: "row",
237
- flex: 1,
238
-
239
- // Reduce the padding of the innerWrapper when the focus ring is
240
- // visible.
241
- ":focus-visible": {
242
- padding: `${CellMeasurements.cellPadding.paddingVertical - 2}px ${
243
- CellMeasurements.cellPadding.paddingHorizontal - 2
244
- }px`,
245
- },
246
- },
247
-
248
- content: {
249
- alignSelf: "center",
250
- // Expand the content to fill the available space.
251
- flex: 1,
252
- overflowWrap: "break-word",
253
- },
254
-
255
- accessory: {
256
- // Use content width by default.
257
- minWidth: "auto",
258
- // Horizontal alignment of the accessory.
259
- alignItems: "center",
260
- // Vertical alignment.
261
- alignSelf: "center",
262
- },
263
-
264
- accessoryRight: {
265
- // The right accessory will have this color by default. Unless the
266
- // accessory element overrides that color internally.
267
- color: color.offBlack64,
268
- },
269
-
270
- /**
271
- * States
272
- */
273
- clickable: {
274
- outline: "none",
275
- /**
276
- * States
277
- */
278
- // disabled
279
- // NOTE: We use `aria-disabled` instead of `disabled` because we want
280
- // to allow the cell to be focusable even when it's disabled.
281
- [":hover[aria-disabled=true]" as any]: {
282
- cursor: "not-allowed",
283
- },
284
-
285
- // focus (only visible when using keyboard navigation)
286
- ":focus-visible": {
287
- borderRadius: spacing.xxxSmall_4,
288
- // To hide the internal corners of the cell.
289
- overflow: "hidden",
290
- // To display the focus ring based on the cell's border.
291
- position: "relative",
292
- },
293
- // NOTE: We use a pseudo element to draw the focus ring because we can't
294
- // use `outline` since it conflicts with different layout contexts (e.g.
295
- // `View` elements add their own z-index).
296
- [":focus-visible:after" as any]: {
297
- content: "''",
298
- // Since we are using a pseudo element, we need to manually
299
- // calculate the width/height and use absolute position to
300
- // prevent other elements from being shifted around.
301
- position: "absolute",
302
- top: 0,
303
- left: 0,
304
- zIndex: 1,
305
- // We remove the border width from the width/height to ensure
306
- // that the focus ring is drawn inside the cell.
307
- width: `calc(100% - ${spacing.xxxSmall_4}px)`,
308
- height: `calc(100% - ${spacing.xxxSmall_4}px)`,
309
- border: `${spacing.xxxxSmall_2}px solid ${color.blue}`,
310
- borderRadius: spacing.xxxSmall_4,
311
- },
312
-
313
- // hover + enabled
314
- [":hover[aria-disabled=false]" as any]: {
315
- background: color.offBlack8,
316
- },
317
-
318
- // pressed + enabled
319
- [":active[aria-disabled=false]" as any]: {
320
- background: color.offBlack16,
321
- },
322
- },
323
-
324
- active: {
325
- background: color.fadedBlue8,
326
- color: color.blue,
327
-
328
- [":hover[aria-disabled=false]" as any]: {
329
- background: color.fadedBlue16,
330
- },
331
-
332
- [":active[aria-disabled=false]" as any]: {
333
- background: color.fadedBlue24,
334
- },
335
- },
336
-
337
- disabled: {
338
- color: color.offBlack32,
339
- ":focus-visible": {
340
- // Prevent the focus ring from being displayed when the cell is
341
- // disabled.
342
- outline: "none",
343
- },
344
- },
345
-
346
- accessoryActive: {
347
- color: color.blue,
348
- },
349
-
350
- accessoryDisabled: {
351
- color: color.offBlack,
352
- opacity: 0.32,
353
- },
354
- });
355
-
356
- export default CellCore;
@@ -1,74 +0,0 @@
1
- import {StyleSheet} from "aphrodite";
2
-
3
- import {color, spacing} from "@khanacademy/wonder-blocks-tokens";
4
-
5
- import type {StyleType} from "@khanacademy/wonder-blocks-core";
6
- import type {HorizontalRuleVariant} from "../../util/types";
7
-
8
- export const CellMeasurements = {
9
- cellMinHeight: spacing.xxLarge_48,
10
-
11
- /**
12
- * The cell wrapper's gap.
13
- */
14
- cellPadding: {
15
- paddingVertical: spacing.small_12,
16
- paddingHorizontal: spacing.medium_16,
17
- },
18
-
19
- /**
20
- * The DetailCell wrapper's gap.
21
- */
22
- detailCellPadding: {
23
- paddingVertical: spacing.medium_16,
24
- paddingHorizontal: spacing.medium_16,
25
- },
26
-
27
- /**
28
- * The horizontal spacing between the left and right accessory.
29
- */
30
- accessoryHorizontalSpacing: spacing.medium_16,
31
- } as const;
32
-
33
- /**
34
- * Gets the horizontalRule style based on the variant.
35
- * @param {HorizontalRuleVariant} horizontalRule The variant of the horizontal
36
- * rule.
37
- * @returns A styled horizontal rule.
38
- */
39
- export const getHorizontalRuleStyles = (
40
- horizontalRule: HorizontalRuleVariant,
41
- ): StyleType => {
42
- switch (horizontalRule) {
43
- case "inset":
44
- return [styles.horizontalRule, styles.horizontalRuleInset];
45
- case "full-width":
46
- return styles.horizontalRule;
47
- case "none":
48
- return {};
49
- }
50
- };
51
-
52
- const styles = StyleSheet.create({
53
- horizontalRule: {
54
- position: "relative",
55
- ":after": {
56
- width: "100%",
57
- content: "''",
58
- position: "absolute",
59
- // align to the bottom of the cell
60
- bottom: 0,
61
- // align border to the right of the cell
62
- right: 0,
63
- height: spacing.xxxxSmall_2,
64
- boxShadow: `inset 0px -1px 0px ${color.offBlack8}`,
65
- },
66
- },
67
-
68
- horizontalRuleInset: {
69
- ":after": {
70
- // Inset doesn't include the left padding of the cell.
71
- width: `calc(100% - ${CellMeasurements.cellPadding.paddingHorizontal}px)`,
72
- },
73
- },
74
- });
package/src/index.ts DELETED
@@ -1,4 +0,0 @@
1
- import CompactCell from "./components/compact-cell";
2
- import DetailCell from "./components/detail-cell";
3
-
4
- export {CompactCell, DetailCell};
package/src/util/types.ts DELETED
@@ -1,156 +0,0 @@
1
- import * as React from "react";
2
-
3
- import type {AriaProps, StyleType} from "@khanacademy/wonder-blocks-core";
4
- import type {Typography} from "@khanacademy/wonder-blocks-typography";
5
- import {ClickableRole} from "@khanacademy/wonder-blocks-clickable";
6
-
7
- /**
8
- * A set of values that can be used to configure the horizontal rule appearance.
9
- */
10
- export type HorizontalRuleVariant = "full-width" | "inset" | "none";
11
-
12
- /**
13
- * An element or component that represents an accessory within a cell.
14
- */
15
- type Accessory = React.ReactNode;
16
-
17
- /**
18
- * A subset of CSS Properties to allow overriding some of the default styles set
19
- * on the accessory wrapper (loosely based on StyleType).
20
- */
21
- export type AccessoryStyle = {
22
- /**
23
- * A subset of valid Spacing values.
24
- */
25
- minWidth?: 16 | 24 | 32 | 48;
26
- /**
27
- * To vertically align the accessory.
28
- */
29
- alignSelf?: "flex-start" | "flex-end" | "center";
30
- /**
31
- * To horizontally align the accessory.
32
- */
33
- alignItems?: "flex-start" | "flex-end" | "center";
34
- };
35
-
36
- /**
37
- * A union that allows using plain text or WB Typography elements.
38
- */
39
- export type TypographyText =
40
- | string
41
- | React.ReactElement<React.ComponentProps<Typography>>;
42
-
43
- /**
44
- * Common properties for all cells.
45
- */
46
- export type CellProps = {
47
- /**
48
- * The title / main content of the cell. You can either provide a string or
49
- * a Typography component. If a string is provided, typography defaults to
50
- * LabelLarge.
51
- */
52
- title: TypographyText;
53
- /**
54
- * Optional custom styles applied to the content wrapper. For
55
- * example, it can be used to set a custom minWidth or a custom
56
- * alignment.
57
- */
58
- contentStyle?: AccessoryStyle;
59
- /**
60
- * If provided, this adds a left accessory to the cell. Left
61
- * Accessories can be defined using WB components such as Icon,
62
- * IconButton, or it can even be used for a custom node/component if
63
- * needed. What ever is passed in will occupy the "LeftAccessory” area
64
- * of the Cell.
65
- */
66
- leftAccessory?: Accessory;
67
- /**
68
- * Optional custom styles applied to the leftAccessory wrapper. For
69
- * example, it can be used to set a custom minWidth or a custom
70
- * alignment.
71
- *
72
- * NOTE: leftAccessoryStyle can only be used if leftAccessory is set.
73
- */
74
- leftAccessoryStyle?: AccessoryStyle;
75
- /**
76
- * If provided, this adds a right accessory to the cell. Right
77
- * Accessories can be defined using WB components such as Icon,
78
- * IconButton, or it can even be used for a custom node/component if
79
- * needed. What ever is passed in will occupy the “RightAccessory”
80
- * area of the Cell.
81
- */
82
- rightAccessory?: Accessory;
83
- /**
84
- * Optional custom styles applied to the rightAccessory wrapper. For
85
- * example, it can be used to set a custom minWidth or a custom
86
- * alignment.
87
- *
88
- * NOTE: rightAccessoryStyle can only be used if rightAccessory is
89
- * set.
90
- */
91
- rightAccessoryStyle?: AccessoryStyle;
92
- /**
93
- * Adds a horizontal rule at the bottom of the cell that can be used to
94
- * separate cells within groups such as lists. Defaults to `inset`.
95
- */
96
- horizontalRule?: HorizontalRuleVariant;
97
-
98
- /**
99
- * A custom role for the cell.
100
- */
101
- role?: ClickableRole;
102
- /**
103
- * Optional custom styles applied to the top node.
104
- *
105
- * _NOTE:_ This is the top node of the cell, not the cell container. If
106
- * possible, try to use this prop carefully and use `style` instead.
107
- */
108
- rootStyle?: StyleType;
109
- /**
110
- * Optional custom styles applied to the cell container.
111
- */
112
- style?: StyleType;
113
- /**
114
- * Optional test ID for e2e testing.
115
- */
116
- testId?: string;
117
- /**
118
- * Called when the cell is clicked.
119
- *
120
- * If not provided, the Cell can’t be hovered and/or pressed (highlighted on
121
- * hover).
122
- */
123
- onClick?: (e: React.SyntheticEvent) => unknown;
124
- /**
125
- * Whether the cell is active (or currently selected).
126
- */
127
- active?: boolean;
128
- /**
129
- * Whether the cell is disabled.
130
- */
131
- disabled?: boolean;
132
- /**
133
- * Used to announce the cell's content to screen readers.
134
- */
135
- "aria-label"?: string;
136
- /**
137
- * Used to indicate the current element is selected.
138
- */
139
- "aria-selected"?: AriaProps["aria-selected"];
140
- /**
141
- * Used to indicate the current item is checked.
142
- */
143
- "aria-checked"?: AriaProps["aria-checked"];
144
- /**
145
- * Optinal href which Cell should direct to, uses client-side routing
146
- * by default if react-router is present.
147
- */
148
- href?: string;
149
- /**
150
- * A target destination window for a link to open in. Should only be used
151
- * when `href` is specified.
152
- *
153
- * TODO(WB-1262): only allow this prop when `href` is also set.t
154
- */
155
- target?: "_blank";
156
- };
@@ -1,16 +0,0 @@
1
- {
2
- "exclude": ["dist"],
3
- "extends": "../tsconfig-shared.json",
4
- "compilerOptions": {
5
- "outDir": "./dist",
6
- "rootDir": "src",
7
- },
8
- "references": [
9
- {"path": "../wonder-blocks-clickable/tsconfig-build.json"},
10
- {"path": "../wonder-blocks-core/tsconfig-build.json"},
11
- {"path": "../wonder-blocks-icon/tsconfig-build.json"},
12
- {"path": "../wonder-blocks-layout/tsconfig-build.json"},
13
- {"path": "../wonder-blocks-tokens/tsconfig-build.json"},
14
- {"path": "../wonder-blocks-typography/tsconfig-build.json"},
15
- ]
16
- }