@khanacademy/wonder-blocks-card 0.0.0-PR2816-20251007223425 → 0.0.0-PR2816-20251008182823

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/CHANGELOG.md CHANGED
@@ -1,6 +1,6 @@
1
1
  # @khanacademy/wonder-blocks-card
2
2
 
3
- ## 0.0.0-PR2816-20251007223425
3
+ ## 0.0.0-PR2816-20251008182823
4
4
 
5
5
  ### Minor Changes
6
6
 
package/dist/es/index.js CHANGED
@@ -2,13 +2,13 @@ import { jsx, jsxs } from 'react/jsx-runtime';
2
2
  import * as React from 'react';
3
3
  import { StyleSheet } from 'aphrodite';
4
4
  import { View } from '@khanacademy/wonder-blocks-core';
5
- import { sizing, semanticColor, border, boxShadow } from '@khanacademy/wonder-blocks-tokens';
5
+ import { sizing, semanticColor, border, boxShadow, font } from '@khanacademy/wonder-blocks-tokens';
6
6
  import xIcon from '@phosphor-icons/core/bold/x-bold.svg';
7
7
  import IconButton from '@khanacademy/wonder-blocks-icon-button';
8
8
  import { focusStyles } from '@khanacademy/wonder-blocks-styles';
9
9
 
10
10
  const DismissButton=props=>{const{onClick,style,testId}=props;return jsx(IconButton,{icon:xIcon,"aria-label":props["aria-label"]||"Close",onClick:onClick,kind:"tertiary",actionType:"neutral",style:[componentStyles.root,style],testId:testId})};const componentStyles=StyleSheet.create({root:{position:"absolute",insetInlineEnd:sizing.size_080,top:sizing.size_080,zIndex:1,":focus":focusStyles.focus[":focus-visible"]}});
11
11
 
12
- const Card=React.forwardRef(function Card(props,ref){const{styles,labels,tag,testId,background="base-default",borderRadius="small",paddingSize="small",elevation="none",children,onDismiss,inert}=props;const componentStyles=getComponentStyles({background,borderRadius,paddingSize,elevation});return jsxs(View,{"aria-label":labels?.cardAriaLabel,style:[componentStyles.root,styles?.root],ref:ref,tag:tag,testId:testId,inert:inert?"":undefined,children:[onDismiss?jsx(DismissButton,{"aria-label":labels?.dismissButtonAriaLabel||"Close",onClick:e=>onDismiss?.(e)}):null,children]})});const styleMap={backgroundColor:{"base-subtle":semanticColor.core.background.base.subtle,"base-default":semanticColor.core.background.base.default},borderRadius:{small:border.radius.radius_080,medium:border.radius.radius_120},padding:{none:sizing.size_0,small:sizing.size_160,medium:sizing.size_240},elevation:{none:"none",low:boxShadow.low}};const dynamicStyles={};const getStyleKey=({background,borderRadius,paddingSize,elevation})=>{return `${background||"default"}-${borderRadius||"small"}-${paddingSize||"small"}-${elevation||"none"}`};const getComponentStyles=props=>{const styleKey=getStyleKey(props);if(dynamicStyles[styleKey]){return dynamicStyles[styleKey]}const{background,borderRadius,paddingSize,elevation}=props;const isBackgroundColorStyle=background==="base-subtle"||background==="base-default";const newStyles=StyleSheet.create({root:{...isBackgroundColorStyle&&{backgroundColor:styleMap.backgroundColor[background]},...!isBackgroundColorStyle&&background&&{background:`url(${background})`,backgroundSize:"cover"},borderColor:semanticColor.core.border.neutral.subtle,borderStyle:"solid",borderWidth:border.width.thin,minInlineSize:sizing.size_280,position:"relative",borderRadius:borderRadius&&styleMap.borderRadius[borderRadius],boxShadow:elevation&&styleMap.elevation[elevation],padding:paddingSize&&styleMap.padding[paddingSize]}});dynamicStyles[styleKey]=newStyles;return newStyles};
12
+ const Card=React.forwardRef(function Card(props,ref){const{styles,labels,tag,testId,background="base-default",borderRadius="small",paddingSize="small",elevation="none",children,onDismiss,inert}=props;const componentStyles=getComponentStyles({background,borderRadius,paddingSize,elevation});return jsxs(View,{"aria-label":labels?.cardAriaLabel,style:[componentStyles.root,styles?.root],ref:ref,tag:tag,testId:testId,inert:inert?"":undefined,children:[onDismiss?jsx(DismissButton,{"aria-label":labels?.dismissButtonAriaLabel||"Close",onClick:e=>onDismiss?.(e)}):null,children]})});const styleMap={backgroundColor:{"base-subtle":semanticColor.core.background.base.subtle,"base-default":semanticColor.core.background.base.default},borderRadius:{small:border.radius.radius_080,medium:border.radius.radius_120},padding:{none:sizing.size_0,small:sizing.size_160,medium:sizing.size_240},elevation:{none:"none",low:boxShadow.low}};const getComponentStyles=({background="base-default",borderRadius="small",paddingSize="small",elevation="none"})=>{const isBackgroundColorStyle=background==="base-subtle"||background==="base-default";return StyleSheet.create({root:{...isBackgroundColorStyle&&{backgroundColor:styleMap.backgroundColor[background]},...!isBackgroundColorStyle&&background&&{background:`url(${background})`,backgroundSize:"cover"},borderColor:semanticColor.core.border.neutral.subtle,borderStyle:"solid",borderWidth:border.width.thin,fontFamily:font.family.sans,minInlineSize:sizing.size_280,position:"relative",borderRadius:styleMap.borderRadius[borderRadius],boxShadow:styleMap.elevation[elevation],padding:styleMap.padding[paddingSize]}})};
13
13
 
14
14
  export { Card };
package/dist/index.js CHANGED
@@ -37,6 +37,6 @@ var IconButton__default = /*#__PURE__*/_interopDefaultLegacy(IconButton);
37
37
 
38
38
  const DismissButton=props=>{const{onClick,style,testId}=props;return jsxRuntime.jsx(IconButton__default["default"],{icon:xIcon__default["default"],"aria-label":props["aria-label"]||"Close",onClick:onClick,kind:"tertiary",actionType:"neutral",style:[componentStyles.root,style],testId:testId})};const componentStyles=aphrodite.StyleSheet.create({root:{position:"absolute",insetInlineEnd:wonderBlocksTokens.sizing.size_080,top:wonderBlocksTokens.sizing.size_080,zIndex:1,":focus":wonderBlocksStyles.focusStyles.focus[":focus-visible"]}});
39
39
 
40
- const Card=React__namespace.forwardRef(function Card(props,ref){const{styles,labels,tag,testId,background="base-default",borderRadius="small",paddingSize="small",elevation="none",children,onDismiss,inert}=props;const componentStyles=getComponentStyles({background,borderRadius,paddingSize,elevation});return jsxRuntime.jsxs(wonderBlocksCore.View,{"aria-label":labels?.cardAriaLabel,style:[componentStyles.root,styles?.root],ref:ref,tag:tag,testId:testId,inert:inert?"":undefined,children:[onDismiss?jsxRuntime.jsx(DismissButton,{"aria-label":labels?.dismissButtonAriaLabel||"Close",onClick:e=>onDismiss?.(e)}):null,children]})});const styleMap={backgroundColor:{"base-subtle":wonderBlocksTokens.semanticColor.core.background.base.subtle,"base-default":wonderBlocksTokens.semanticColor.core.background.base.default},borderRadius:{small:wonderBlocksTokens.border.radius.radius_080,medium:wonderBlocksTokens.border.radius.radius_120},padding:{none:wonderBlocksTokens.sizing.size_0,small:wonderBlocksTokens.sizing.size_160,medium:wonderBlocksTokens.sizing.size_240},elevation:{none:"none",low:wonderBlocksTokens.boxShadow.low}};const dynamicStyles={};const getStyleKey=({background,borderRadius,paddingSize,elevation})=>{return `${background||"default"}-${borderRadius||"small"}-${paddingSize||"small"}-${elevation||"none"}`};const getComponentStyles=props=>{const styleKey=getStyleKey(props);if(dynamicStyles[styleKey]){return dynamicStyles[styleKey]}const{background,borderRadius,paddingSize,elevation}=props;const isBackgroundColorStyle=background==="base-subtle"||background==="base-default";const newStyles=aphrodite.StyleSheet.create({root:{...isBackgroundColorStyle&&{backgroundColor:styleMap.backgroundColor[background]},...!isBackgroundColorStyle&&background&&{background:`url(${background})`,backgroundSize:"cover"},borderColor:wonderBlocksTokens.semanticColor.core.border.neutral.subtle,borderStyle:"solid",borderWidth:wonderBlocksTokens.border.width.thin,minInlineSize:wonderBlocksTokens.sizing.size_280,position:"relative",borderRadius:borderRadius&&styleMap.borderRadius[borderRadius],boxShadow:elevation&&styleMap.elevation[elevation],padding:paddingSize&&styleMap.padding[paddingSize]}});dynamicStyles[styleKey]=newStyles;return newStyles};
40
+ const Card=React__namespace.forwardRef(function Card(props,ref){const{styles,labels,tag,testId,background="base-default",borderRadius="small",paddingSize="small",elevation="none",children,onDismiss,inert}=props;const componentStyles=getComponentStyles({background,borderRadius,paddingSize,elevation});return jsxRuntime.jsxs(wonderBlocksCore.View,{"aria-label":labels?.cardAriaLabel,style:[componentStyles.root,styles?.root],ref:ref,tag:tag,testId:testId,inert:inert?"":undefined,children:[onDismiss?jsxRuntime.jsx(DismissButton,{"aria-label":labels?.dismissButtonAriaLabel||"Close",onClick:e=>onDismiss?.(e)}):null,children]})});const styleMap={backgroundColor:{"base-subtle":wonderBlocksTokens.semanticColor.core.background.base.subtle,"base-default":wonderBlocksTokens.semanticColor.core.background.base.default},borderRadius:{small:wonderBlocksTokens.border.radius.radius_080,medium:wonderBlocksTokens.border.radius.radius_120},padding:{none:wonderBlocksTokens.sizing.size_0,small:wonderBlocksTokens.sizing.size_160,medium:wonderBlocksTokens.sizing.size_240},elevation:{none:"none",low:wonderBlocksTokens.boxShadow.low}};const getComponentStyles=({background="base-default",borderRadius="small",paddingSize="small",elevation="none"})=>{const isBackgroundColorStyle=background==="base-subtle"||background==="base-default";return aphrodite.StyleSheet.create({root:{...isBackgroundColorStyle&&{backgroundColor:styleMap.backgroundColor[background]},...!isBackgroundColorStyle&&background&&{background:`url(${background})`,backgroundSize:"cover"},borderColor:wonderBlocksTokens.semanticColor.core.border.neutral.subtle,borderStyle:"solid",borderWidth:wonderBlocksTokens.border.width.thin,fontFamily:wonderBlocksTokens.font.family.sans,minInlineSize:wonderBlocksTokens.sizing.size_280,position:"relative",borderRadius:styleMap.borderRadius[borderRadius],boxShadow:styleMap.elevation[elevation],padding:styleMap.padding[paddingSize]}})};
41
41
 
42
42
  exports.Card = Card;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@khanacademy/wonder-blocks-card",
3
- "version": "0.0.0-PR2816-20251007223425",
3
+ "version": "0.0.0-PR2816-20251008182823",
4
4
  "design": "v1",
5
5
  "description": "Card component for Wonder Blocks.",
6
6
  "main": "dist/index.js",
@@ -14,8 +14,8 @@
14
14
  },
15
15
  "dependencies": {
16
16
  "@khanacademy/wonder-blocks-core": "12.4.0",
17
- "@khanacademy/wonder-blocks-tokens": "14.0.0",
18
- "@khanacademy/wonder-blocks-icon-button": "10.5.2"
17
+ "@khanacademy/wonder-blocks-icon-button": "10.5.2",
18
+ "@khanacademy/wonder-blocks-tokens": "14.0.0"
19
19
  },
20
20
  "peerDependencies": {
21
21
  "aphrodite": "^1.2.5",
@@ -1,12 +1,6 @@
1
1
  import * as React from "react";
2
2
  import {render, screen} from "@testing-library/react";
3
3
  import {userEvent} from "@testing-library/user-event";
4
- import {
5
- boxShadow,
6
- border,
7
- semanticColor,
8
- sizing,
9
- } from "@khanacademy/wonder-blocks-tokens";
10
4
 
11
5
  import Card from "../../components/card";
12
6
 
@@ -197,180 +191,4 @@ describe("Card", () => {
197
191
  expect(secondChild).toBeInTheDocument();
198
192
  });
199
193
  });
200
-
201
- describe("Style application", () => {
202
- it("should apply default styles", () => {
203
- // Arrange
204
- const testId = "test-card";
205
-
206
- // Act
207
- render(<Card testId={testId}>Content</Card>);
208
- const card = screen.getByTestId(testId);
209
-
210
- // Assert
211
- expect(card).toHaveStyle({
212
- position: "relative",
213
- borderStyle: "solid",
214
- });
215
- });
216
-
217
- it("should apply base-subtle background", () => {
218
- // Arrange
219
- const testId = "test-card";
220
-
221
- // Act
222
- render(
223
- <Card testId={testId} background="base-subtle">
224
- Content
225
- </Card>,
226
- );
227
- const card = screen.getByTestId(testId);
228
-
229
- // Assert
230
- expect(card).toHaveStyle({
231
- backgroundColor: semanticColor.core.background.base.subtle,
232
- });
233
- });
234
-
235
- it("should apply medium border radius", () => {
236
- // Arrange
237
- const testId = "test-card";
238
-
239
- // Act
240
- render(
241
- <Card testId={testId} borderRadius="medium">
242
- Content
243
- </Card>,
244
- );
245
- const card = screen.getByTestId(testId);
246
-
247
- // Assert
248
- expect(card).toHaveStyle({
249
- borderRadius: border.radius.radius_120,
250
- });
251
- });
252
-
253
- it("should apply medium padding", () => {
254
- // Arrange
255
- const testId = "test-card";
256
-
257
- // Act
258
- render(
259
- <Card testId={testId} paddingSize="medium">
260
- Content
261
- </Card>,
262
- );
263
- const card = screen.getByTestId(testId);
264
-
265
- // Assert
266
- expect(card).toHaveStyle({
267
- padding: sizing.size_240,
268
- });
269
- });
270
-
271
- it("should apply low elevation", () => {
272
- // Arrange
273
- const testId = "test-card";
274
-
275
- // Act
276
- render(
277
- <Card testId={testId} elevation="low">
278
- Content
279
- </Card>,
280
- );
281
- const card = screen.getByTestId(testId);
282
-
283
- // Assert
284
- expect(card).toHaveStyle({
285
- boxShadow: boxShadow.low,
286
- });
287
- });
288
-
289
- it("should apply image background", () => {
290
- // Arrange
291
- const testId = "test-card";
292
- const testImage = Image;
293
-
294
- // Act
295
- render(
296
- <Card testId={testId} background={testImage}>
297
- Content
298
- </Card>,
299
- );
300
- const card = screen.getByTestId(testId);
301
-
302
- // Assert
303
- expect(card).toHaveStyle({
304
- backgroundSize: "cover",
305
- });
306
- });
307
- });
308
-
309
- describe("Style application", () => {
310
- it("should apply custom margin style", () => {
311
- // Arrange
312
- const testId = "test-card";
313
- const customStyle = {marginTop: "10px"};
314
-
315
- // Act
316
- render(
317
- <Card testId={testId} styles={{root: customStyle}}>
318
- Content
319
- </Card>,
320
- );
321
-
322
- // Assert
323
- expect(screen.getByTestId(testId)).toHaveStyle(customStyle);
324
- });
325
-
326
- it("should apply custom padding style", () => {
327
- // Arrange
328
- const testId = "test-card";
329
- const customStyle = {padding: "20px"};
330
-
331
- // Act
332
- render(
333
- <Card testId={testId} styles={{root: customStyle}}>
334
- Content
335
- </Card>,
336
- );
337
-
338
- // Assert
339
- expect(screen.getByTestId(testId)).toHaveStyle(customStyle);
340
- });
341
-
342
- it("should apply custom background color", () => {
343
- // Arrange
344
- const testId = "test-card";
345
- const customStyle = {backgroundColor: "rgb(255, 0, 0)"};
346
-
347
- // Act
348
- render(
349
- <Card testId={testId} styles={{root: customStyle}}>
350
- Content
351
- </Card>,
352
- );
353
-
354
- // Assert
355
- expect(screen.getByTestId(testId)).toHaveStyle(customStyle);
356
- });
357
-
358
- it("should maintain default styles with custom styles", () => {
359
- // Arrange
360
- const testId = "test-card";
361
- const customStyle = {marginTop: "10px"};
362
-
363
- // Act
364
- render(
365
- <Card testId={testId} styles={{root: customStyle}}>
366
- Content
367
- </Card>,
368
- );
369
-
370
- // Assert
371
- const element = screen.getByTestId(testId);
372
- expect(element).toHaveStyle(customStyle);
373
- expect(element).toHaveStyle({position: "relative"}); // A default style
374
- });
375
- });
376
194
  });
@@ -8,6 +8,7 @@ import {
8
8
  border,
9
9
  semanticColor,
10
10
  sizing,
11
+ font,
11
12
  } from "@khanacademy/wonder-blocks-tokens";
12
13
 
13
14
  import {DismissButton} from "./dismiss-button";
@@ -212,39 +213,19 @@ const styleMap = {
212
213
  },
213
214
  } as const;
214
215
 
215
- // Cache for dynamically generated styles
216
- const dynamicStyles: Record<string, any> = {};
217
-
218
216
  /**
219
- * Generates a unique key for caching styles based on prop combinations
217
+ * Gets the styles for the card based on its props
220
218
  */
221
- const getStyleKey = ({
222
- background,
223
- borderRadius,
224
- paddingSize,
225
- elevation,
226
- }: StyleProps): string => {
227
- return `${background || "default"}-${borderRadius || "small"}-${
228
- paddingSize || "small"
229
- }-${elevation || "none"}`;
230
- };
231
-
232
- /**
233
- * Generates the component styles with caching for better performance
234
- */
235
- const getComponentStyles = (props: StyleProps) => {
236
- const styleKey = getStyleKey(props);
237
- // Return cached styles if they exist
238
- if (dynamicStyles[styleKey]) {
239
- return dynamicStyles[styleKey];
240
- }
241
-
242
- const {background, borderRadius, paddingSize, elevation} = props;
219
+ const getComponentStyles = ({
220
+ background = "base-default",
221
+ borderRadius = "small",
222
+ paddingSize = "small",
223
+ elevation = "none",
224
+ }: StyleProps) => {
243
225
  const isBackgroundColorStyle =
244
226
  background === "base-subtle" || background === "base-default";
245
227
 
246
- // Generate new styles
247
- const newStyles = StyleSheet.create({
228
+ return StyleSheet.create({
248
229
  root: {
249
230
  // Background styles
250
231
  ...(isBackgroundColorStyle && {
@@ -260,18 +241,15 @@ const getComponentStyles = (props: StyleProps) => {
260
241
  borderColor: semanticColor.core.border.neutral.subtle,
261
242
  borderStyle: "solid",
262
243
  borderWidth: border.width.thin,
244
+ fontFamily: font.family.sans,
263
245
  minInlineSize: sizing.size_280,
264
246
  position: "relative",
265
247
  // Optional styles based on props
266
- borderRadius: borderRadius && styleMap.borderRadius[borderRadius],
267
- boxShadow: elevation && styleMap.elevation[elevation],
268
- padding: paddingSize && styleMap.padding[paddingSize],
248
+ borderRadius: styleMap.borderRadius[borderRadius],
249
+ boxShadow: styleMap.elevation[elevation],
250
+ padding: styleMap.padding[paddingSize],
269
251
  },
270
252
  });
271
-
272
- // Cache the styles
273
- dynamicStyles[styleKey] = newStyles;
274
- return newStyles;
275
253
  };
276
254
 
277
255
  export default Card;