@studiocubics/components 0.0.1

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.
Files changed (140) hide show
  1. package/CHANGELOG.md +11 -0
  2. package/README.md +71 -0
  3. package/eslint.config.js +21 -0
  4. package/package.json +66 -0
  5. package/rollup.config.js +34 -0
  6. package/src/Cards/Card/Card.module.css +27 -0
  7. package/src/Cards/Card/Card.tsx +105 -0
  8. package/src/Cards/CollectionItemCard/CollectionItemCard.module.css +84 -0
  9. package/src/Cards/CollectionItemCard/CollectionItemCard.tsx +170 -0
  10. package/src/Cards/CollectionItemCard/CollectionItemCardActions.tsx +85 -0
  11. package/src/Cards/CollectionItemCard/_index.ts +2 -0
  12. package/src/Cards/GlassCard/GlassCard.module.css +71 -0
  13. package/src/Cards/GlassCard/GlassCard.tsx +80 -0
  14. package/src/Cards/_index.ts +3 -0
  15. package/src/Display/Accordion/Accordion.module.css +69 -0
  16. package/src/Display/Accordion/Accordion.tsx +61 -0
  17. package/src/Display/Accordion/AccordionItem.tsx +135 -0
  18. package/src/Display/Accordion/_index.ts +2 -0
  19. package/src/Display/Chip/Chip.module.css +64 -0
  20. package/src/Display/Chip/Chip.tsx +105 -0
  21. package/src/Display/IdentityDisplay/IdentityDisplay.module.css +95 -0
  22. package/src/Display/IdentityDisplay/IdentityDisplay.tsx +119 -0
  23. package/src/Display/InputErrors/InputErrors.module.css +6 -0
  24. package/src/Display/InputErrors/InputErrors.tsx +52 -0
  25. package/src/Display/Kbd/Kbd.module.css +29 -0
  26. package/src/Display/Kbd/Kbd.tsx +39 -0
  27. package/src/Display/Kbd/_index.ts +2 -0
  28. package/src/Display/Kbd/buttonList.tsx +246 -0
  29. package/src/Display/LabeledValue/LabeledValue.module.css +32 -0
  30. package/src/Display/LabeledValue/LabeledValue.tsx +20 -0
  31. package/src/Display/List/List.module.css +143 -0
  32. package/src/Display/List/List.tsx +298 -0
  33. package/src/Display/PasswordStrength/PasswordStrength.module.css +45 -0
  34. package/src/Display/PasswordStrength/PasswordStrength.tsx +41 -0
  35. package/src/Display/PasswordStrength/usePasswordStrength.tsx +77 -0
  36. package/src/Display/Skeleton/Skeleton.module.css +54 -0
  37. package/src/Display/Skeleton/Skeleton.tsx +28 -0
  38. package/src/Display/Toast/Toaster.tsx +58 -0
  39. package/src/Display/Toast/_index.ts +2 -0
  40. package/src/Display/Toast/toast.ts +44 -0
  41. package/src/Display/Tooltip/Tooltip.module.css +128 -0
  42. package/src/Display/Tooltip/Tooltip.tsx +93 -0
  43. package/src/Display/Tooltip/getArrowDirection.ts +55 -0
  44. package/src/Display/Tooltip/useTooltip.tsx +63 -0
  45. package/src/Display/_index.ts +12 -0
  46. package/src/Forms/ConfirmationForm/ConfirmationForm.module.css +23 -0
  47. package/src/Forms/ConfirmationForm/ConfirmationForm.tsx +60 -0
  48. package/src/Forms/_index.ts +1 -0
  49. package/src/Inputs/Button/Button.module.css +131 -0
  50. package/src/Inputs/Button/Button.tsx +178 -0
  51. package/src/Inputs/Checkbox/Checkbox.module.css +77 -0
  52. package/src/Inputs/Checkbox/Checkbox.tsx +191 -0
  53. package/src/Inputs/Checkbox/CheckboxGroup/CheckboxGroup.module.css +10 -0
  54. package/src/Inputs/Checkbox/CheckboxGroup/CheckboxGroup.tsx +83 -0
  55. package/src/Inputs/Checkbox/CheckboxSelectAll.tsx +34 -0
  56. package/src/Inputs/Checkbox/_index.ts +3 -0
  57. package/src/Inputs/PasswordInput/PasswordInput.module.css +111 -0
  58. package/src/Inputs/PasswordInput/PasswordInput.tsx +229 -0
  59. package/src/Inputs/Select/Select.module.css +138 -0
  60. package/src/Inputs/Select/Select.tsx +136 -0
  61. package/src/Inputs/Switch/Switch.module.css +119 -0
  62. package/src/Inputs/Switch/Switch.tsx +195 -0
  63. package/src/Inputs/TextAreaInput/TextAreaInput.module.css +65 -0
  64. package/src/Inputs/TextAreaInput/TextAreaInput.tsx +97 -0
  65. package/src/Inputs/TextInput/TextInput.module.css +112 -0
  66. package/src/Inputs/TextInput/TextInput.tsx +142 -0
  67. package/src/Inputs/ThemeToggle/ThemeToggleListItem.tsx +80 -0
  68. package/src/Inputs/ThemeToggle/_index.ts +1 -0
  69. package/src/Inputs/_index.ts +8 -0
  70. package/src/Layout/Dialog/Dialog.module.css +15 -0
  71. package/src/Layout/Dialog/Dialog.tsx +115 -0
  72. package/src/Layout/PageLayout/PageLayout.module.css +20 -0
  73. package/src/Layout/PageLayout/PageLayout.tsx +79 -0
  74. package/src/Layout/PageLayoutPagination/PageLayoutPagination.module.css +5 -0
  75. package/src/Layout/PageLayoutPagination/PageLayoutPagination.tsx +40 -0
  76. package/src/Layout/PageLayoutTabs/PageLayoutTabs.module.css +3 -0
  77. package/src/Layout/PageLayoutTabs/PageLayoutTabs.tsx +62 -0
  78. package/src/Layout/Popover/Popover.module.css +9 -0
  79. package/src/Layout/Popover/Popover.tsx +145 -0
  80. package/src/Layout/SectionWrapper/SectionWrapper.module.css +31 -0
  81. package/src/Layout/SectionWrapper/SectionWrapper.tsx +62 -0
  82. package/src/Layout/Sidebar/Sidebar.module.css +17 -0
  83. package/src/Layout/Sidebar/Sidebar.tsx +39 -0
  84. package/src/Layout/Sidebar/SidebarBody/SidebarBody.module.css +31 -0
  85. package/src/Layout/Sidebar/SidebarBody/SidebarBody.tsx +18 -0
  86. package/src/Layout/Sidebar/SidebarDrawer/SidebarDrawer.module.css +20 -0
  87. package/src/Layout/Sidebar/SidebarDrawer/SidebarDrawer.tsx +19 -0
  88. package/src/Layout/Sidebar/SidebarFooter/SidebarFooter.module.css +35 -0
  89. package/src/Layout/Sidebar/SidebarFooter/SidebarFooter.tsx +19 -0
  90. package/src/Layout/Sidebar/SidebarHeader/SidebarHeader.tsx +14 -0
  91. package/src/Layout/Sidebar/SidebarViewport/SidebarViewport.module.css +12 -0
  92. package/src/Layout/Sidebar/SidebarViewport/SidebarViewport.tsx +11 -0
  93. package/src/Layout/Sidebar/_index.ts +6 -0
  94. package/src/Layout/Table/Table.module.css +46 -0
  95. package/src/Layout/Table/Table.tsx +222 -0
  96. package/src/Layout/Table/TableFooter.tsx +4 -0
  97. package/src/Layout/Table/TableHeader.tsx +4 -0
  98. package/src/Layout/Table/_index.ts +5 -0
  99. package/src/Layout/Table/tableUtils.ts +142 -0
  100. package/src/Layout/Table/types.ts +48 -0
  101. package/src/Layout/_index.ts +8 -0
  102. package/src/Misc/Cursor/Cursor.module.css +31 -0
  103. package/src/Misc/Cursor/Cursor.tsx +77 -0
  104. package/src/Misc/Logos.tsx +230 -0
  105. package/src/Misc/PoweredByBanner/PoweredByBanner.module.css +20 -0
  106. package/src/Misc/PoweredByBanner/PoweredByBanner.tsx +17 -0
  107. package/src/Misc/Ripple/Ripple.module.css +25 -0
  108. package/src/Misc/Ripple/Ripple.tsx +126 -0
  109. package/src/Misc/Spinner/Spinner.module.css +38 -0
  110. package/src/Misc/Spinner/Spinner.tsx +36 -0
  111. package/src/Misc/TransitionAnimation/TransitionAnimation.module.css +131 -0
  112. package/src/Misc/TransitionAnimation/TransitionAnimation.tsx +166 -0
  113. package/src/Misc/_index.ts +6 -0
  114. package/src/Navigation/Breadcrumbs/Breadcrumbs.module.css +22 -0
  115. package/src/Navigation/Breadcrumbs/Breadcrumbs.tsx +127 -0
  116. package/src/Navigation/Breadcrumbs/BreadcrumbsItem.tsx +31 -0
  117. package/src/Navigation/Breadcrumbs/_index.ts +3 -0
  118. package/src/Navigation/Breadcrumbs/useBreadcrumbs.tsx +74 -0
  119. package/src/Navigation/Pagination/Pagination.module.css +41 -0
  120. package/src/Navigation/Pagination/Pagination.tsx +187 -0
  121. package/src/Navigation/Pagination/PaginationItem.tsx +28 -0
  122. package/src/Navigation/Pagination/_index.ts +3 -0
  123. package/src/Navigation/Pagination/usePagination.tsx +65 -0
  124. package/src/Navigation/Tabs/Tab/Tab.module.css +43 -0
  125. package/src/Navigation/Tabs/Tab/Tab.tsx +155 -0
  126. package/src/Navigation/Tabs/Tabs.tsx +37 -0
  127. package/src/Navigation/Tabs/TabsBar/TabsBar.module.css +47 -0
  128. package/src/Navigation/Tabs/TabsBar/TabsBar.tsx +92 -0
  129. package/src/Navigation/Tabs/_index.ts +3 -0
  130. package/src/Navigation/_index.ts +3 -0
  131. package/src/Typography/ClampedText/ClampedText.module.css +5 -0
  132. package/src/Typography/ClampedText/ClampedText.tsx +77 -0
  133. package/src/Typography/CopyableText/CopyableText.module.css +21 -0
  134. package/src/Typography/CopyableText/CopyableText.tsx +120 -0
  135. package/src/Typography/PageTitle/PageTitle.module.css +47 -0
  136. package/src/Typography/PageTitle/PageTitle.tsx +35 -0
  137. package/src/Typography/_index.ts +3 -0
  138. package/src/declaration.d.ts +4 -0
  139. package/src/index.ts +8 -0
  140. package/tsconfig.json +32 -0
@@ -0,0 +1,77 @@
1
+ "use client";
2
+
3
+ import type {
4
+ PolymorphicComponentProps,
5
+ PolymorphicComponentType,
6
+ } from "@studiocubics/types";
7
+ import { cn } from "@studiocubics/utils";
8
+ import type { ElementType } from "react";
9
+ import styles from "./ClampedText.module.css";
10
+
11
+ /**
12
+ * Props specific to the ClampedText component.
13
+ *
14
+ * These extend the intrinsic element props of whatever element is passed via `as`.
15
+ * @group ClampedText
16
+ * @category inputs
17
+ */
18
+ export interface ClampedTextBaseProps {
19
+ lineCount?: number;
20
+ }
21
+ const defaultElement = "p";
22
+ type DefaultElement = typeof defaultElement;
23
+ /**
24
+ * Polymorphic props for the ClampedText component.
25
+ *
26
+ * `C` defines the element type rendered by the component (e.g. `"ClampedText"`, `"a"`, `"div"`).
27
+ * All intrinsic props for `C` are supported unless overridden by `ClampedTextBaseProps`.
28
+ *
29
+ * @group ClampedText
30
+ * @category inputs
31
+ */
32
+ export type ClampedTextProps<C extends ElementType = DefaultElement> =
33
+ PolymorphicComponentProps<C, ClampedTextBaseProps>;
34
+
35
+ /**
36
+ * Base implementation for the ClampedText component.
37
+ *
38
+ * This is a polymorphic component that defaults to rendering a `<ClampedText>`.
39
+ * Use the `as` prop to change the underlying element.
40
+ *
41
+ * @typeParam C - The intrinsic or custom element type to render.
42
+ *
43
+ * @group ClampedText
44
+ * @category inputs
45
+ */
46
+ function ClampedTextBase<C extends ElementType = DefaultElement>(
47
+ props: ClampedTextProps<C>,
48
+ ) {
49
+ const { as, className, lineCount = 1, style, ...restProps } = props;
50
+ const Component = (as || defaultElement) as ElementType;
51
+
52
+ const componentProps = {
53
+ className: cn(className, styles.root),
54
+ style: { WebkitLineClamp: `${lineCount}`, ...style },
55
+ ...restProps,
56
+ };
57
+
58
+ return <Component {...componentProps} />;
59
+ }
60
+ ClampedTextBase.displayName = "ClampedText";
61
+
62
+ /**
63
+ * A polymorphic ClampedText component.
64
+ *
65
+ * By default it renders a `<ClampedText>`, but any element can be used via the `as` prop:
66
+ *
67
+ * ```tsx
68
+ * <ClampedText as="a" href="/docs">Read docs</ClampedText>
69
+ * ```
70
+ *
71
+ * @group ClampedText
72
+ * @category inputs
73
+ */
74
+ export const ClampedText = ClampedTextBase as PolymorphicComponentType<
75
+ ClampedTextBaseProps,
76
+ DefaultElement
77
+ >;
@@ -0,0 +1,21 @@
1
+ .root {
2
+ display: flex;
3
+ align-items: center;
4
+ gap: var(--spacing-gap);
5
+ & > span {
6
+ background-color: var(--color-surface);
7
+ border-radius: var(--shape-br-sm);
8
+ padding: var(--spacing-gap);
9
+ overflow: auto hidden;
10
+ -ms-overflow-style: none; /* IE and Edge */
11
+ scrollbar-width: none; /* Firefox */
12
+ text-overflow: ellipsis;
13
+ white-space: nowrap;
14
+ font-size: 0.9em;
15
+ flex: 1;
16
+ &::-webkit-scrollbar {
17
+ /* Hide scrollbar for Chrome, Safari, and Opera */
18
+ display: none;
19
+ }
20
+ }
21
+ }
@@ -0,0 +1,120 @@
1
+ "use client";
2
+
3
+ import type {
4
+ PolymorphicComponentProps,
5
+ PolymorphicComponentType,
6
+ } from "@studiocubics/types";
7
+ import { cn } from "@studiocubics/utils";
8
+ import {
9
+ type ComponentProps,
10
+ type MouseEvent,
11
+ useEffect,
12
+ useState,
13
+ type ElementType,
14
+ } from "react";
15
+ import styles from "./CopyableText.module.css";
16
+ import { useDelayedAction } from "@studiocubics/hooks";
17
+ import { Button, type ButtonProps } from "../../Inputs/Button/Button";
18
+
19
+ export interface CopyableTextBaseProps {
20
+ children: string;
21
+ disabled?: boolean;
22
+ slotProps?: {
23
+ button?: ButtonProps;
24
+ };
25
+ }
26
+
27
+ const defaultElement = "div";
28
+ type DefaultElement = typeof defaultElement;
29
+
30
+ export type CopyableTextProps<C extends ElementType = DefaultElement> =
31
+ PolymorphicComponentProps<C, CopyableTextBaseProps>;
32
+
33
+ function CopyableTextBase<C extends ElementType = DefaultElement>(
34
+ props: CopyableTextProps<C>,
35
+ ) {
36
+ const {
37
+ as,
38
+ children,
39
+ className,
40
+ disabled = false,
41
+ slotProps = {},
42
+ ...rest
43
+ } = props as CopyableTextProps<DefaultElement>;
44
+
45
+ const [copied, setCopied] = useState(false);
46
+ const delay = useDelayedAction();
47
+ const Component = (as || defaultElement) as ElementType;
48
+ const componentProps = { ...rest, className: cn(className, styles.root) };
49
+
50
+ async function handleCopy(e: MouseEvent<HTMLButtonElement>) {
51
+ await navigator.clipboard.writeText(children);
52
+ setCopied(true);
53
+ slotProps.button?.onClick?.(e);
54
+ }
55
+ useEffect(() => {
56
+ if (copied) {
57
+ delay(() => setCopied(false), 2000);
58
+ }
59
+ }, [delay, copied]);
60
+ return (
61
+ <Component {...componentProps}>
62
+ <span>{children}</span>
63
+ <Button
64
+ disabled={disabled}
65
+ square
66
+ size="sm"
67
+ {...slotProps.button}
68
+ onClick={handleCopy}
69
+ >
70
+ {copied ? (
71
+ <CheckIcon width={24} height={24} />
72
+ ) : (
73
+ <CopyIcon width={24} height={24} />
74
+ )}
75
+ </Button>
76
+ </Component>
77
+ );
78
+ }
79
+
80
+ CopyableTextBase.displayName = "CopyableText";
81
+
82
+ export const CopyableText = CopyableTextBase as PolymorphicComponentType<
83
+ CopyableTextBaseProps,
84
+ DefaultElement
85
+ >;
86
+
87
+ export function CopyIcon(props: ComponentProps<"svg">) {
88
+ return (
89
+ <svg
90
+ {...props}
91
+ xmlns="http://www.w3.org/2000/svg"
92
+ viewBox="0 0 24 24"
93
+ fill="none"
94
+ stroke="currentColor"
95
+ strokeWidth="2.3"
96
+ strokeLinecap="round"
97
+ strokeLinejoin="round"
98
+ >
99
+ <rect width="14" height="14" x="8" y="8" rx="2" ry="2" />
100
+ <path d="M4 16c-1.1 0-2-.9-2-2V4c0-1.1.9-2 2-2h10c1.1 0 2 .9 2 2" />
101
+ </svg>
102
+ );
103
+ }
104
+ // TODO convert to animated check icon
105
+ function CheckIcon(props: ComponentProps<"svg">) {
106
+ return (
107
+ <svg
108
+ {...props}
109
+ xmlns="http://www.w3.org/2000/svg"
110
+ viewBox="0 0 24 24"
111
+ fill="none"
112
+ stroke="currentColor"
113
+ strokeWidth="2.3"
114
+ strokeLinecap="round"
115
+ strokeLinejoin="round"
116
+ >
117
+ <path d="M4 12 9 17l11 -11" />
118
+ </svg>
119
+ );
120
+ }
@@ -0,0 +1,47 @@
1
+ .root {
2
+ display: flex;
3
+ justify-content: space-between;
4
+ width: 100%;
5
+ padding: var(--spacing-gap-4);
6
+ border-bottom: 1px solid var(--color-outline);
7
+ gap: var(--spacing-gap-3);
8
+ & h1 {
9
+ font-size: var(--fs-h2);
10
+ }
11
+ & h2 {
12
+ font-weight: normal;
13
+ color: var(--color-on-background-faint);
14
+ font-size: var(--fs-body2);
15
+ }
16
+ }
17
+ .noBorder {
18
+ border-bottom: none;
19
+ }
20
+ .size_lg {
21
+ padding: var(--spacing-gap-6);
22
+ & h1 {
23
+ font-size: var(--fs-h1);
24
+ }
25
+ & h2 {
26
+ font-size: var(--fs-body);
27
+ }
28
+ }
29
+ .size_sm {
30
+ padding: var(--spacing-gap-2);
31
+ & h1 {
32
+ font-size: var(--fs-h4);
33
+ }
34
+ }
35
+ .main {
36
+ display: flex;
37
+ flex-direction: column;
38
+ justify-content: flex-end;
39
+ }
40
+ .actions {
41
+ display: flex;
42
+ justify-content: flex-end;
43
+ gap: var(--spacing-gap-2);
44
+ align-items: center;
45
+ flex: 1;
46
+ overflow: hidden;
47
+ }
@@ -0,0 +1,35 @@
1
+ import type { ReactNode } from "react";
2
+ import styles from "./PageTitle.module.css";
3
+ import { cn } from "@studiocubics/utils";
4
+
5
+ export interface PageTitleProps {
6
+ title: ReactNode;
7
+ actions?: ReactNode;
8
+ subtitle?: ReactNode;
9
+ size?: "sm" | "md" | "lg";
10
+ noBorders?: boolean;
11
+ }
12
+
13
+ export function PageTitle({
14
+ title,
15
+ subtitle,
16
+ actions,
17
+ size = "md",
18
+ noBorders = false,
19
+ }: PageTitleProps) {
20
+ return (
21
+ <div
22
+ className={cn(
23
+ styles.root,
24
+ styles[`size_${size}`],
25
+ noBorders ? styles.noBorder : ""
26
+ )}
27
+ >
28
+ <div className={styles.main}>
29
+ <h1>{title}</h1>
30
+ <h2>{subtitle}</h2>
31
+ </div>
32
+ {actions && <div className={styles.actions}>{actions}</div>}
33
+ </div>
34
+ );
35
+ }
@@ -0,0 +1,3 @@
1
+ export * from "./PageTitle/PageTitle";
2
+ export * from "./ClampedText/ClampedText";
3
+ export * from "./CopyableText/CopyableText";
@@ -0,0 +1,4 @@
1
+ declare module "*.module.css" {
2
+ const classes: { [key: string]: string };
3
+ export default classes;
4
+ }
package/src/index.ts ADDED
@@ -0,0 +1,8 @@
1
+ export * from "./Cards/_index";
2
+ export * from "./Display/_index";
3
+ export * from "./Forms/_index";
4
+ export * from "./Inputs/_index";
5
+ export * from "./Layout/_index";
6
+ export * from "./Misc/_index";
7
+ export * from "./Navigation/_index";
8
+ export * from "./Typography/_index";
package/tsconfig.json ADDED
@@ -0,0 +1,32 @@
1
+ {
2
+ "compilerOptions": {
3
+ "tsBuildInfoFile": "./node_modules/.tmp/tsconfig.app.tsbuildinfo",
4
+ "target": "ES2022",
5
+ "useDefineForClassFields": true,
6
+ "lib": ["ES2022", "DOM", "DOM.Iterable"],
7
+ "module": "ESNext",
8
+ "resolveJsonModule": true,
9
+ "allowJs": true,
10
+ "skipLibCheck": true,
11
+
12
+ /* Bundler mode */
13
+ "moduleResolution": "bundler",
14
+ "verbatimModuleSyntax": true,
15
+ "moduleDetection": "force",
16
+ "noEmit": true,
17
+ "jsx": "react-jsx",
18
+ // Output
19
+ "declaration": true,
20
+ "outDir": "./dist",
21
+ "rootDir": "./src",
22
+
23
+ /* Linting */
24
+ "strict": true,
25
+ "noUnusedLocals": true,
26
+ "noUnusedParameters": true,
27
+ "erasableSyntaxOnly": true,
28
+ "noFallthroughCasesInSwitch": true,
29
+ "noUncheckedSideEffectImports": true
30
+ },
31
+ "include": ["./src"]
32
+ }