@common-origin/design-system 1.16.0 → 2.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.
package/README.md CHANGED
@@ -1,10 +1,49 @@
1
1
  # Common Origin Design System
2
2
 
3
- A production-ready design system built with atomic design principles, design tokens, and WCAG 2.2 AA accessibility compliance. This package provides reusable React components and design tokens for building consistent user interfaces.
3
+ A production-ready, **framework-agnostic** design system built with atomic design principles, design tokens, and WCAG 2.2 AA accessibility compliance. This package provides reusable React components and design tokens for building consistent user interfaces.
4
+
5
+ ## ⚠️ Version 2.0 Breaking Changes
6
+
7
+ **Version 2.0.0** removes Next.js dependencies, making the design system work in **any React application** (Next.js, Create React App, Vite, etc.).
8
+
9
+ If you're upgrading from v1.x, see **[MIGRATION-V2.md](./MIGRATION-V2.md)** for the complete migration guide.
10
+
11
+ **Quick summary:** Components like `Button`, `Breadcrumbs`, and `CardSmall` now accept an optional `linkComponent` prop. Pass your framework's Link component (e.g., Next.js Link, React Router Link) for client-side navigation, or omit it to use standard HTML links.
4
12
 
5
13
  ## 🚀 Getting Started
6
14
 
15
+ ### Installation
16
+
17
+ ```bash
18
+ npm install @common-origin/design-system styled-components
19
+ ```
20
+
21
+ ### Usage
22
+
23
+ ```tsx
24
+ import { Button, Typography, Stack } from '@common-origin/design-system'
25
+
26
+ // For Next.js apps, pass Link component for client-side routing
27
+ import Link from 'next/link'
28
+
29
+ function App() {
30
+ return (
31
+ <Stack direction="column" gap="md">
32
+ <Typography variant="h1">Welcome</Typography>
33
+ <Button
34
+ purpose="link"
35
+ url="/about"
36
+ linkComponent={Link}
37
+ >
38
+ Learn More
39
+ </Button>
40
+ </Stack>
41
+ )
42
+ }
43
+ ```
44
+
7
45
  ### Development
46
+
8
47
  ```bash
9
48
  # Install dependencies
10
49
  npm install
@@ -10,6 +10,12 @@ export interface BaseButtonProps {
10
10
  iconName?: IconName;
11
11
  id?: string;
12
12
  'data-testid'?: string;
13
+ /**
14
+ * Custom link component (e.g., Next.js Link, React Router Link)
15
+ * Receives href, children, and other props
16
+ * @example linkComponent={NextLink} or linkComponent={ReactRouterLink}
17
+ */
18
+ linkComponent?: React.ComponentType<any>;
13
19
  }
14
20
  export interface ButtonProps extends BaseButtonProps, Omit<React.ButtonHTMLAttributes<HTMLButtonElement>, keyof BaseButtonProps> {
15
21
  purpose?: 'button';
@@ -6,6 +6,11 @@ interface Breadcrumb {
6
6
  interface BreadcrumbsProps {
7
7
  breadcrumbs: Breadcrumb[];
8
8
  'data-testid'?: string;
9
+ /**
10
+ * Custom link component (e.g., Next.js Link)
11
+ * @example linkComponent={NextLink}
12
+ */
13
+ linkComponent?: React.ComponentType<any>;
9
14
  }
10
15
  export declare const Breadcrumbs: React.FC<BreadcrumbsProps>;
11
16
  export {};
@@ -5,5 +5,10 @@ export type CardSmallProps = {
5
5
  subtitle?: string;
6
6
  meta?: string;
7
7
  href?: string;
8
+ /**
9
+ * Custom link component (e.g., Next.js Link)
10
+ * @example linkComponent={NextLink}
11
+ */
12
+ linkComponent?: React.ComponentType<any>;
8
13
  };
9
14
  export declare const CardSmall: React.FC<CardSmallProps>;
package/dist/index.esm.js CHANGED
@@ -1,6 +1,5 @@
1
1
  import React, { useState, forwardRef, useId, useRef, useEffect, useCallback } from 'react';
2
2
  import styled, { keyframes, css } from 'styled-components';
3
- import Link from 'next/link';
4
3
  import { parseISO, format } from 'date-fns';
5
4
 
6
5
  function _extends() {
@@ -745,7 +744,7 @@ var semantic$a = {
745
744
  h1: "700 3rem/3rem 'Inter', sans-serif",
746
745
  h2: "700 2rem/2.5rem 'Inter', sans-serif",
747
746
  h3: "700 1.75rem/2.25rem 'Inter', sans-serif",
748
- h4: "500 1.5rem/2rem 'Inter', sans-serif",
747
+ h4: "700 1.5rem/2rem 'Inter', sans-serif",
749
748
  h5: "500 1.25rem/1.75rem 'Inter', sans-serif",
750
749
  h6: "500 1.125rem/1.5rem 'Inter', sans-serif",
751
750
  subtitle: "500 1rem/1.5rem 'Inter', sans-serif",
@@ -804,7 +803,7 @@ var AvatarInitials = styled.span.withConfig({
804
803
  },
805
804
  displayName: "Avatar__AvatarInitials",
806
805
  componentId: "sc-ezn4ax-2"
807
- })(templateObject_3$i || (templateObject_3$i = __makeTemplateObject(["\n font-family: ", ";\n font-weight: ", ";\n font-size: ", ";\n color: ", ";\n line-height: 1;\n text-transform: uppercase;\n user-select: none;\n"], ["\n font-family: ", ";\n font-weight: ", ";\n font-size: ", ";\n color: ", ";\n line-height: 1;\n text-transform: uppercase;\n user-select: none;\n"
806
+ })(templateObject_3$h || (templateObject_3$h = __makeTemplateObject(["\n font-family: ", ";\n font-weight: ", ";\n font-size: ", ";\n color: ", ";\n line-height: 1;\n text-transform: uppercase;\n user-select: none;\n"], ["\n font-family: ", ";\n font-weight: ", ";\n font-size: ", ";\n color: ", ";\n line-height: 1;\n text-transform: uppercase;\n user-select: none;\n"
808
807
  // Helper function to get initials from name
809
808
  ])), tokensData.base.fontFamily.body, tokensData.base.fontWeight[3], function (_a) {
810
809
  var $size = _a.$size;
@@ -867,7 +866,7 @@ var Avatar = function Avatar(_a) {
867
866
  "aria-hidden": "true"
868
867
  }, initials));
869
868
  };
870
- var templateObject_1$y, templateObject_2$l, templateObject_3$i;
869
+ var templateObject_1$y, templateObject_2$l, templateObject_3$h;
871
870
 
872
871
  React.createElement;
873
872
  var _a$5 = tokensData.semantic,
@@ -1018,7 +1017,7 @@ var BadgeIndicator = styled.span.withConfig({
1018
1017
  },
1019
1018
  displayName: "Badge__BadgeIndicator",
1020
1019
  componentId: "sc-tjz4pp-1"
1021
- })(templateObject_3$h || (templateObject_3$h = __makeTemplateObject(["\n position: absolute;\n top: 0;\n right: 0;\n transform: translate(50%, -50%);\n display: ", ";\n align-items: center;\n justify-content: center;\n min-width: ", ";\n height: ", ";\n padding: ", ";\n border-radius: ", ";\n line-height: 1;\n white-space: nowrap;\n box-shadow: 0 0 0 2px ", ";\n animation: ", " 0.2s ease-out;\n \n ", "\n"], ["\n position: absolute;\n top: 0;\n right: 0;\n transform: translate(50%, -50%);\n display: ", ";\n align-items: center;\n justify-content: center;\n min-width: ", ";\n height: ", ";\n padding: ", ";\n border-radius: ", ";\n line-height: 1;\n white-space: nowrap;\n box-shadow: 0 0 0 2px ", ";\n animation: ", " 0.2s ease-out;\n \n ", "\n"])), function (props) {
1020
+ })(templateObject_3$g || (templateObject_3$g = __makeTemplateObject(["\n position: absolute;\n top: 0;\n right: 0;\n transform: translate(50%, -50%);\n display: ", ";\n align-items: center;\n justify-content: center;\n min-width: ", ";\n height: ", ";\n padding: ", ";\n border-radius: ", ";\n line-height: 1;\n white-space: nowrap;\n box-shadow: 0 0 0 2px ", ";\n animation: ", " 0.2s ease-out;\n \n ", "\n"], ["\n position: absolute;\n top: 0;\n right: 0;\n transform: translate(50%, -50%);\n display: ", ";\n align-items: center;\n justify-content: center;\n min-width: ", ";\n height: ", ";\n padding: ", ";\n border-radius: ", ";\n line-height: 1;\n white-space: nowrap;\n box-shadow: 0 0 0 2px ", ";\n animation: ", " 0.2s ease-out;\n \n ", "\n"])), function (props) {
1022
1021
  return props.$isVisible ? 'flex' : 'none';
1023
1022
  }, function (props) {
1024
1023
  return props.$isDot ? '8px' : '16px';
@@ -1074,7 +1073,7 @@ var Badge = function Badge(_a) {
1074
1073
  color: "inverse"
1075
1074
  }, displayCount), /*#__PURE__*/React.createElement(ScreenReaderOnly, null, label)));
1076
1075
  };
1077
- var templateObject_1$w, templateObject_2$k, templateObject_3$h, templateObject_4$e;
1076
+ var templateObject_1$w, templateObject_2$k, templateObject_3$g, templateObject_4$e;
1078
1077
 
1079
1078
  React.createElement;
1080
1079
  var StyledBox = styled.div.withConfig({
@@ -1090,7 +1089,7 @@ var StyledBox = styled.div.withConfig({
1090
1089
  }, function (props) {
1091
1090
  return props.$flexDirection && css(templateObject_2$j || (templateObject_2$j = __makeTemplateObject(["flex-direction: ", ";"], ["flex-direction: ", ";"])), props.$flexDirection);
1092
1091
  }, function (props) {
1093
- return props.$justifyContent && css(templateObject_3$g || (templateObject_3$g = __makeTemplateObject(["justify-content: ", ";"], ["justify-content: ", ";"])), props.$justifyContent);
1092
+ return props.$justifyContent && css(templateObject_3$f || (templateObject_3$f = __makeTemplateObject(["justify-content: ", ";"], ["justify-content: ", ";"])), props.$justifyContent);
1094
1093
  }, function (props) {
1095
1094
  return props.$alignItems && css(templateObject_4$d || (templateObject_4$d = __makeTemplateObject(["align-items: ", ";"], ["align-items: ", ";"])), props.$alignItems);
1096
1095
  }, function (props) {
@@ -1276,7 +1275,7 @@ var BoxTransform = function BoxTransform(props) {
1276
1275
  }, rest), children);
1277
1276
  };
1278
1277
  var Box = BoxTransform;
1279
- var templateObject_1$v, templateObject_2$j, templateObject_3$g, templateObject_4$d, templateObject_5$a, templateObject_6$9, templateObject_7$7, templateObject_8$3, templateObject_9$2, templateObject_10$2, templateObject_11$2, templateObject_12$2, templateObject_13$2, templateObject_14$1, templateObject_15$1, templateObject_16$1, templateObject_17$1, templateObject_18$1, templateObject_19$1, templateObject_20$1, templateObject_21$1, templateObject_22$1, templateObject_23$1, templateObject_24$1, templateObject_25$1, templateObject_26$1, templateObject_27$1, templateObject_28$1, templateObject_29$1, templateObject_30$1, templateObject_31$1, templateObject_32$1, templateObject_33$1, templateObject_34$1, templateObject_35$1, templateObject_36, templateObject_37, templateObject_38, templateObject_39, templateObject_40, templateObject_41, templateObject_42, templateObject_43;
1278
+ var templateObject_1$v, templateObject_2$j, templateObject_3$f, templateObject_4$d, templateObject_5$a, templateObject_6$9, templateObject_7$7, templateObject_8$3, templateObject_9$2, templateObject_10$2, templateObject_11$2, templateObject_12$2, templateObject_13$2, templateObject_14$1, templateObject_15$1, templateObject_16$1, templateObject_17$1, templateObject_18$1, templateObject_19$1, templateObject_20$1, templateObject_21$1, templateObject_22$1, templateObject_23$1, templateObject_24$1, templateObject_25$1, templateObject_26$1, templateObject_27$1, templateObject_28$1, templateObject_29$1, templateObject_30$1, templateObject_31$1, templateObject_32$1, templateObject_33$1, templateObject_34$1, templateObject_35$1, templateObject_36, templateObject_37, templateObject_38, templateObject_39, templateObject_40, templateObject_41, templateObject_42, templateObject_43;
1280
1279
 
1281
1280
  var add = {
1282
1281
  path: "M13 11H19V13H13V19H11V13H5V11H11V5H13V11Z",
@@ -1303,7 +1302,7 @@ var arrowRight = {
1303
1302
  name: "arrowRight"
1304
1303
  };
1305
1304
  var bell = {
1306
- path: "M12.0001 2C15.3561 2 18.1753 4.52384 18.546 7.85938L18.7979 10.125C18.8012 10.1546 18.8024 10.1676 18.8038 10.1797C18.9166 11.1628 19.2372 12.1106 19.7432 12.9609C19.7494 12.9714 19.7553 12.9824 19.7706 13.0078L20.3487 13.9707C20.5997 14.3891 20.829 14.7681 20.9795 15.0879C21.1276 15.4024 21.2852 15.8285 21.209 16.3115C21.1337 16.789 20.8882 17.2229 20.5176 17.5332C20.1426 17.8471 19.6956 17.931 19.3497 17.9658C18.998 18.0012 18.5554 18 18.0674 18H5.93268C5.44476 18 5.00211 18.0012 4.65045 17.9658C4.30456 17.931 3.85755 17.8471 3.48248 17.5332C3.1119 17.2229 2.86641 16.789 2.79107 16.3115C2.7149 15.8285 2.87247 15.4024 3.02057 15.0879C3.17116 14.7681 3.40038 14.3891 3.65143 13.9707L4.22955 13.0078C4.24481 12.9824 4.25068 12.9714 4.25689 12.9609C4.76296 12.1106 5.08348 11.1628 5.19635 10.1797C5.19773 10.1676 5.19892 10.1546 5.20221 10.125L5.45416 7.85938C5.82477 4.52384 8.644 2 12.0001 2ZM12.0001 4C9.6631 4 7.69954 5.75741 7.44146 8.08008L7.18951 10.3457C7.18638 10.3739 7.18457 10.3907 7.18268 10.4072C7.03761 11.6714 6.62638 12.8909 5.97564 13.9844C5.96724 13.9985 5.95885 14.013 5.94439 14.0371L5.36627 15C5.09277 15.4558 4.92766 15.7334 4.83014 15.9404C4.82533 15.9506 4.82155 15.9606 4.81744 15.9697C4.82787 15.971 4.83877 15.9744 4.85064 15.9756C5.07838 15.9985 5.40111 16 5.93268 16H18.0674C18.599 16 18.9217 15.9985 19.1495 15.9756C19.161 15.9744 19.1716 15.9709 19.1817 15.9697C19.1776 15.9607 19.1747 15.9505 19.17 15.9404C19.0725 15.7334 18.9074 15.4558 18.6338 15L18.0557 14.0371C18.0413 14.013 18.0329 13.9985 18.0245 13.9844C17.3737 12.8909 16.9625 11.6714 16.8174 10.4072C16.8155 10.3907 16.8137 10.3739 16.8106 10.3457L16.5587 8.08008C16.3006 5.75741 14.337 4 12.0001 4Z M12.0001 22C10.9897 22 10.0894 21.4972 9.419 20.7256C8.75348 19.9595 8.31404 18.9367 8.11822 17.8408C8.0211 17.2971 8.38314 16.7778 8.92682 16.6807C9.47038 16.5837 9.98987 16.9457 10.087 17.4893C10.233 18.3066 10.5467 18.9742 10.9288 19.4141C11.3063 19.8486 11.6896 20 12.0001 20C12.3106 20 12.6938 19.8486 13.0713 19.4141C13.4535 18.9742 13.7671 18.3066 13.9131 17.4893C14.0102 16.9457 14.5297 16.5837 15.0733 16.6807C15.617 16.7778 15.979 17.2971 15.8819 17.8408C15.6861 18.9367 15.2466 19.9595 14.5811 20.7256C13.9108 21.4972 13.0104 22 12.0001 22Z",
1305
+ path: "M12 2C17.5228 2 22 6.47715 22 12C22 17.5228 17.5228 22 12 22C6.47715 22 2 17.5228 2 12C2 6.47715 6.47715 2 12 2ZM12 4C7.58172 4 4 7.58172 4 12C4 16.4183 7.58172 20 12 20C16.4183 20 20 16.4183 20 12C20 7.58172 16.4183 4 12 4ZM15.707 9.70703L13.4141 12L15.707 14.293L14.293 15.707L12 13.4141L9.70703 15.707L8.29297 14.293L10.5859 12L8.29297 9.70703L9.70703 8.29297L12 10.5859L14.293 8.29297L15.707 9.70703Z",
1307
1306
  name: "bell"
1308
1307
  };
1309
1308
  var back = {
@@ -1606,16 +1605,6 @@ var StyledLink = styled.a.withConfig({
1606
1605
  displayName: "Button__StyledLink",
1607
1606
  componentId: "sc-1eiuum9-1"
1608
1607
  })(templateObject_2$i || (templateObject_2$i = __makeTemplateObject(["\n ", "\n border-radius: ", ";\n \n ", "\n ", "\n"], ["\n ", "\n border-radius: ", ";\n \n ", "\n ", "\n"
1609
- // Styled Next.js Link component (modern API without legacyBehavior)
1610
- ])), baseButtonStyles, button.primary.borderRadius, getVariantStyles, getSizeStyles);
1611
- // Styled Next.js Link component (modern API without legacyBehavior)
1612
- var StyledNextLink = styled(Link).withConfig({
1613
- shouldForwardProp: function shouldForwardProp(prop) {
1614
- return !prop.startsWith('$');
1615
- },
1616
- displayName: "Button__StyledNextLink",
1617
- componentId: "sc-1eiuum9-2"
1618
- })(templateObject_3$f || (templateObject_3$f = __makeTemplateObject(["\n ", "\n border-radius: ", ";\n \n ", "\n ", "\n"], ["\n ", "\n border-radius: ", ";\n \n ", "\n ", "\n"
1619
1608
  // Helper function to get icon size based on button size
1620
1609
  ])), baseButtonStyles, button.primary.borderRadius, getVariantStyles, getSizeStyles);
1621
1610
  // Helper function to get icon size based on button size
@@ -1652,18 +1641,21 @@ var Button = function Button(_a) {
1652
1641
  children = _a.children,
1653
1642
  target = _a.target,
1654
1643
  iconName = _a.iconName,
1644
+ LinkComponent = _a.linkComponent,
1655
1645
  dataTestId = _a["data-testid"],
1656
- rest = __rest(_a, ["variant", "size", "url", "purpose", "children", "target", "iconName", 'data-testid']);
1657
- // For internal links, use Next.js Link (modern API without legacyBehavior)
1658
- if (purpose === 'link' && url && !url.startsWith('http') && !target) {
1659
- return /*#__PURE__*/React.createElement(StyledNextLink, {
1660
- href: url,
1646
+ rest = __rest(_a, ["variant", "size", "url", "purpose", "children", "target", "iconName", "linkComponent", 'data-testid']);
1647
+ // For links with custom link component (e.g., Next.js Link, React Router Link)
1648
+ if (purpose === 'link' && url && LinkComponent) {
1649
+ return /*#__PURE__*/React.createElement(LinkComponent, {
1650
+ href: url
1651
+ }, /*#__PURE__*/React.createElement(StyledLink, {
1652
+ as: "span",
1661
1653
  $variant: variant,
1662
1654
  $size: size,
1663
1655
  "data-testid": dataTestId
1664
- }, renderButtonContent(children, iconName, size));
1656
+ }, renderButtonContent(children, iconName, size)));
1665
1657
  }
1666
- // For external links or links with target
1658
+ // For standard links (external or without custom component)
1667
1659
  if (purpose === 'link' && url) {
1668
1660
  var linkProps = rest;
1669
1661
  return /*#__PURE__*/React.createElement(StyledLink, _extends({
@@ -1704,7 +1696,7 @@ var Button = function Button(_a) {
1704
1696
  "data-testid": dataTestId
1705
1697
  }, buttonProps), renderButtonContent(children, iconName, size));
1706
1698
  };
1707
- var templateObject_1$t, templateObject_2$i, templateObject_3$f;
1699
+ var templateObject_1$t, templateObject_2$i;
1708
1700
 
1709
1701
  var chip = tokensData.component.chip;
1710
1702
  // Helper function to get variant styles as objects for CSS custom properties
@@ -2735,7 +2727,8 @@ var isInternalUrl = function isInternalUrl(url) {
2735
2727
  return url.startsWith('/') && !url.startsWith('http');
2736
2728
  };
2737
2729
  var Breadcrumbs = function Breadcrumbs(_a) {
2738
- var breadcrumbs = _a.breadcrumbs;
2730
+ var breadcrumbs = _a.breadcrumbs,
2731
+ LinkComponent = _a.linkComponent;
2739
2732
  return /*#__PURE__*/React.createElement(Container, null, /*#__PURE__*/React.createElement(BreadcrumbNavStyled, {
2740
2733
  "aria-label": "breadcrumb"
2741
2734
  }, /*#__PURE__*/React.createElement("ol", null, breadcrumbs.map(function (breadcrumb, index) {
@@ -2743,15 +2736,16 @@ var Breadcrumbs = function Breadcrumbs(_a) {
2743
2736
  key: index
2744
2737
  }, index === breadcrumbs.length - 1 ? /*#__PURE__*/React.createElement(Typography, {
2745
2738
  variant: "caption"
2746
- }, breadcrumb.label) : isInternalUrl(breadcrumb.url) ? /*#__PURE__*/React.createElement(Link, {
2739
+ }, breadcrumb.label) : LinkComponent && isInternalUrl(breadcrumb.url) ? /*#__PURE__*/React.createElement(LinkComponent, {
2747
2740
  href: breadcrumb.url
2748
2741
  }, /*#__PURE__*/React.createElement(Typography, {
2749
2742
  variant: "caption"
2750
- }, breadcrumb.label)) : /*#__PURE__*/React.createElement("a", {
2751
- href: breadcrumb.url,
2743
+ }, breadcrumb.label)) : /*#__PURE__*/React.createElement("a", _extends({
2744
+ href: breadcrumb.url
2745
+ }, !isInternalUrl(breadcrumb.url) && {
2752
2746
  target: "_blank",
2753
2747
  rel: "noopener noreferrer"
2754
- }, /*#__PURE__*/React.createElement(Typography, {
2748
+ }), /*#__PURE__*/React.createElement(Typography, {
2755
2749
  variant: "caption"
2756
2750
  }, breadcrumb.label)));
2757
2751
  }))));
@@ -2768,14 +2762,12 @@ var CardSmall = function CardSmall(_a) {
2768
2762
  picture = _a.picture,
2769
2763
  subtitle = _a.subtitle,
2770
2764
  meta = _a.meta,
2771
- href = _a.href;
2765
+ href = _a.href,
2766
+ LinkComponent = _a.linkComponent;
2772
2767
  if (!picture || !meta) {
2773
2768
  return null;
2774
2769
  }
2775
- return /*#__PURE__*/React.createElement(CardSmallStyled, null, /*#__PURE__*/React.createElement(Link, {
2776
- href: href || '#',
2777
- "aria-label": title
2778
- }, /*#__PURE__*/React.createElement(Stack, {
2770
+ var content = /*#__PURE__*/React.createElement(Stack, {
2779
2771
  direction: "column",
2780
2772
  gap: "sm"
2781
2773
  }, /*#__PURE__*/React.createElement(Picture, {
@@ -2797,7 +2789,14 @@ var CardSmall = function CardSmall(_a) {
2797
2789
  }, subtitle), meta && /*#__PURE__*/React.createElement(Typography, {
2798
2790
  variant: "label",
2799
2791
  color: "subdued"
2800
- }, meta))))));
2792
+ }, meta))));
2793
+ return /*#__PURE__*/React.createElement(CardSmallStyled, null, LinkComponent && href ? /*#__PURE__*/React.createElement(LinkComponent, {
2794
+ href: href,
2795
+ "aria-label": title
2796
+ }, content) : /*#__PURE__*/React.createElement("a", {
2797
+ href: href || '#',
2798
+ "aria-label": title
2799
+ }, content));
2801
2800
  };
2802
2801
  var templateObject_1$h;
2803
2802