tinywidgets 1.6.0 → 1.6.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.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "tinywidgets",
3
- "version": "1.6.0",
3
+ "version": "1.6.1",
4
4
  "author": "jamesgpearce",
5
5
  "repository": "github:tinyplex/tinywidgets",
6
6
  "license": "MIT",
@@ -19,30 +19,30 @@
19
19
  "prePublishPackage": "prettier --check . && eslint . && cspell --quiet . && tsc && cp ../README.md ./README.md"
20
20
  },
21
21
  "devDependencies": {
22
- "@eslint/js": "^9.30.1",
23
- "@types/react": "^19.2.14",
22
+ "@eslint/js": "^10.0.1",
23
+ "@types/react": "^19.2.17",
24
24
  "@types/react-dom": "^19.2.3",
25
- "cspell": "^10.0.0",
26
- "eslint": "^9.30.1",
25
+ "cspell": "^10.0.1",
26
+ "eslint": "^10.6.0",
27
27
  "eslint-plugin-import": "^2.32.0",
28
28
  "eslint-plugin-react": "^7.37.5",
29
- "eslint-plugin-react-hooks": "^5.2.0",
30
- "globals": "^17.5.0",
31
- "prettier": "^3.8.3",
29
+ "eslint-plugin-react-hooks": "^7.1.1",
30
+ "globals": "^17.7.0",
31
+ "prettier": "^3.9.4",
32
32
  "prettier-plugin-organize-imports": "^4.3.0",
33
- "react": "^19.2.5",
34
- "react-dom": "^19.2.5",
33
+ "react": "^19.2.7",
34
+ "react-dom": "^19.2.7",
35
35
  "typescript": "^6.0.3",
36
- "typescript-eslint": "^8.58.2"
36
+ "typescript-eslint": "^8.62.1"
37
37
  },
38
38
  "exports": {
39
39
  ".": "./src/index.ts",
40
40
  "./css": "./src/index.css.ts"
41
41
  },
42
42
  "dependencies": {
43
- "@vanilla-extract/css": "^1.20.1",
44
- "lucide-react": "^1.8.0",
45
- "tinybase": "^8.2.0"
43
+ "@vanilla-extract/css": "^1.21.1",
44
+ "lucide-react": "^1.23.0",
45
+ "tinybase": "^9.0.0"
46
46
  },
47
47
  "peerDependencies": {
48
48
  "react": "^19.2.4",
@@ -1,6 +1,12 @@
1
- import {style} from '@vanilla-extract/css';
1
+ import {style, styleVariants} from '@vanilla-extract/css';
2
2
  import {colors} from '../../css/colors.css';
3
3
  import {dimensions} from '../../css/dimensions.css';
4
+ import {
5
+ buttonOpen,
6
+ collapsible,
7
+ collapsibleOpen,
8
+ content,
9
+ } from '../Collapsible/index.css';
4
10
 
5
11
  export const card = style({
6
12
  border: colors.border,
@@ -10,3 +16,63 @@ export const card = style({
10
16
  overflow: 'auto',
11
17
  padding: dimensions.padding,
12
18
  });
19
+
20
+ export const titledCard = style([collapsible, collapsibleOpen]);
21
+
22
+ const titleButtonBase = style([
23
+ buttonOpen,
24
+ {
25
+ alignItems: 'center',
26
+ alignSelf: 'center',
27
+ backgroundColor: colors.backgroundHover,
28
+ border: colors.border,
29
+ borderRadius: dimensions.radius,
30
+ borderBottomLeftRadius: 0,
31
+ borderBottomRightRadius: 0,
32
+ boxShadow: 'none',
33
+ color: colors.foregroundBright,
34
+ display: 'inline-flex',
35
+ flexShrink: 0,
36
+ fontFamily: 'inherit',
37
+ fontWeight: 'inherit',
38
+ gap: dimensions.padding,
39
+ justifyContent: 'space-between',
40
+ lineHeight: 'normal',
41
+ margin: '-1px',
42
+ outlineOffset: '-2px',
43
+ overflow: 'hidden',
44
+ padding: '0.5rem 1rem',
45
+ textAlign: 'left',
46
+ transition: 'background-color 0.1s,border-color 0.1s',
47
+ whiteSpace: 'nowrap',
48
+ },
49
+ ]);
50
+
51
+ export const titleButton = styleVariants({
52
+ closable: [
53
+ titleButtonBase,
54
+ {
55
+ cursor: 'pointer',
56
+ selectors: {
57
+ '&:hover': {
58
+ backgroundColor: colors.backgroundHover,
59
+ color: colors.foregroundBright,
60
+ },
61
+ },
62
+ },
63
+ ],
64
+ static: [titleButtonBase],
65
+ });
66
+
67
+ export const title = style({
68
+ flex: '1 1 auto',
69
+ overflow: 'hidden',
70
+ textOverflow: 'ellipsis',
71
+ });
72
+
73
+ export const titleRight = style({
74
+ flex: '0 0 auto',
75
+ overflow: 'hidden',
76
+ });
77
+
78
+ export const titledCardContent = style([content]);
@@ -1,9 +1,20 @@
1
- import type {ReactNode} from 'react';
2
- import {classNames} from '../../common/functions';
3
- import {card} from './index.css';
1
+ import {X} from 'lucide-react';
2
+ import type {ComponentType, ReactNode} from 'react';
3
+ import {classNames, renderComponentOrNode} from '../../common/functions';
4
+ import {iconSize} from '../../css/dimensions.css';
5
+ import {
6
+ card,
7
+ titleButton,
8
+ titledCard,
9
+ titledCardContent,
10
+ title as titleStyle,
11
+ titleRight as titleStyleRight,
12
+ } from './index.css';
4
13
 
5
14
  /**
6
- * The `Card` component displays a simple rectangular container.
15
+ * The `Card` component displays a simple rectangular container. If a `title `
16
+ * prop is provided, it is displayed in the same style as a `Collapsible`
17
+ * component, but without the collapsible behavior.
7
18
  *
8
19
  * @param props The props for the component.
9
20
  * @returns The Card component.
@@ -16,12 +27,55 @@ import {card} from './index.css';
16
27
  * </Card>
17
28
  * ```
18
29
  * This example shows a simple card.
30
+ * @example
31
+ * ```tsx
32
+ * <Card
33
+ * title="TinyWidgets"
34
+ * icon={Lucide.Grid3x3}
35
+ * >
36
+ * <p>Always open</p>
37
+ * </Card>
38
+ * ```
39
+ * This example shows a titled card.
40
+ * @example
41
+ * ```tsx
42
+ * <Card
43
+ * title="TinyWidgets"
44
+ * onClose={() => console.log('Closed')}
45
+ * >
46
+ * <p>Close me</p>
47
+ * </Card>
48
+ * ```
49
+ * This example shows a card with a close button.
19
50
  * @icon Lucide.Square
20
51
  */
21
52
  export const Card = ({
53
+ icon: Icon,
54
+ title,
55
+ titleRight,
56
+ onClose,
22
57
  className,
23
58
  children,
24
59
  }: {
60
+ /**
61
+ * An optional component which renders an icon for the top of the card, and
62
+ * which must accept a className prop.
63
+ */
64
+ readonly icon?: ComponentType<{className?: string}>;
65
+ /**
66
+ * An optional component, element, or string which renders the title of
67
+ * the top of the card.
68
+ */
69
+ readonly title?: ComponentType | ReactNode;
70
+ /**
71
+ * An optional component, element, or string which renders a second title
72
+ * on the right side of the top of the card.
73
+ */
74
+ readonly titleRight?: ComponentType | ReactNode;
75
+ /**
76
+ * A handler called when the user clicks on the close button.
77
+ */
78
+ readonly onClose?: () => void;
25
79
  /**
26
80
  * An extra CSS class name for the component.
27
81
  */
@@ -30,4 +84,31 @@ export const Card = ({
30
84
  * The children of the component that go inside the card.
31
85
  */
32
86
  readonly children: ReactNode;
33
- }) => <div className={classNames(card, className)}>{children}</div>;
87
+ }) => {
88
+ const hasHeader =
89
+ Icon != null || title != null || titleRight != null || onClose != null;
90
+
91
+ return hasHeader ? (
92
+ <div className={classNames(titledCard, className)}>
93
+ <div
94
+ className={titleButton[onClose ? 'closable' : 'static']}
95
+ onClick={onClose}
96
+ {...(onClose ? {title: 'Close'} : {})}
97
+ >
98
+ {Icon ? <Icon className={iconSize} /> : null}
99
+ {title ? (
100
+ <span className={titleStyle}>{renderComponentOrNode(title)}</span>
101
+ ) : null}
102
+ {titleRight ? (
103
+ <span className={titleStyleRight}>
104
+ {renderComponentOrNode(titleRight)}
105
+ </span>
106
+ ) : null}
107
+ {onClose ? <X className={iconSize} /> : null}
108
+ </div>
109
+ <div className={titledCardContent}>{children}</div>
110
+ </div>
111
+ ) : (
112
+ <div className={classNames(card, className)}>{children}</div>
113
+ );
114
+ };