tinywidgets 1.1.5 → 1.2.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/eslint.config.js CHANGED
@@ -138,47 +138,6 @@ export default tsLint.config(
138
138
  },
139
139
  },
140
140
 
141
- {
142
- files: ['src/@types/**/*.js'],
143
- settings: {jsdoc: {mode: 'typescript', contexts: ['any']}},
144
- rules: {
145
- 'jsdoc/check-tag-names': [
146
- 2,
147
- {definedTags: ['category', 'packageDocumentation']},
148
- ],
149
- 'jsdoc/no-restricted-syntax': [
150
- 2,
151
- {
152
- contexts: [
153
- {
154
- comment:
155
- // eslint-disable-next-line max-len
156
- 'JsdocBlock:not(:has(JsdocTag[tag=/category|packageDocumentation/]))',
157
- message: 'Every non-module block requires a @category tag',
158
- },
159
- {
160
- comment: 'JsdocBlock:not(:has(JsdocTag[tag=since]))',
161
- message: 'Every block requires a @since tag',
162
- },
163
- {
164
- comment:
165
- 'JsdocBlock:has(JsdocTag[tag=since] ~ JsdocTag[tag=since])',
166
- message: 'Every block must have only one @since tag',
167
- },
168
- ],
169
- },
170
- ],
171
- 'jsdoc/require-jsdoc': 2,
172
- 'jsdoc/require-description': 2,
173
- 'jsdoc/require-description-complete-sentence': 2,
174
- 'jsdoc/require-returns-description': 2,
175
- 'jsdoc/no-blank-blocks': 2,
176
- 'jsdoc/require-param-type': 0,
177
- 'jsdoc/require-returns-type': 0,
178
- 'jsdoc/check-param-names': 0,
179
- },
180
- },
181
-
182
141
  {
183
142
  files: ['eslint.config.js'],
184
143
  extends: [tsLint.configs.disableTypeChecked],
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "tinywidgets",
3
- "version": "1.1.5",
3
+ "version": "1.2.0",
4
4
  "author": "jamesgpearce",
5
5
  "repository": "github:tinyplex/tinywidgets",
6
6
  "license": "MIT",
@@ -19,28 +19,28 @@
19
19
  "prePublishPackage": "prettier --check . && eslint . && cspell --quiet . && tsc && cp ../README.md ./README.md"
20
20
  },
21
21
  "devDependencies": {
22
- "@types/react": "^19.0.12",
23
- "cspell": "^8.18.1",
24
- "eslint": "^9.23.0",
25
- "eslint-plugin-react": "^7.37.4",
22
+ "@eslint/js": "^9.25.1",
23
+ "@types/react": "^19.1.2",
24
+ "cspell": "^8.19.3",
25
+ "eslint": "^9.25.1",
26
+ "eslint-plugin-import": "^2.31.0",
27
+ "eslint-plugin-react": "^7.37.5",
26
28
  "eslint-plugin-react-hooks": "^5.2.0",
29
+ "globals": "^16.0.0",
27
30
  "prettier": "^3.5.3",
28
31
  "prettier-plugin-organize-imports": "^4.1.0",
29
- "typescript": "^5.8.2"
32
+ "typescript": "^5.8.3",
33
+ "typescript-eslint": "^8.31.0"
30
34
  },
31
35
  "exports": {
32
36
  ".": "./src/index.ts",
33
37
  "./css": "./src/index.css.ts"
34
38
  },
35
39
  "dependencies": {
36
- "@eslint/js": "^9.23.0",
37
40
  "@vanilla-extract/css": "^1.17.1",
38
- "eslint-plugin-import": "^2.31.0",
39
- "globals": "^16.0.0",
40
- "lucide-react": "^0.485.0",
41
+ "lucide-react": "^0.503.0",
41
42
  "react": "^19.1.0",
42
43
  "react-dom": "^19.1.0",
43
- "tinybase": "^6.0.0",
44
- "typescript-eslint": "^8.28.0"
44
+ "tinybase": "^6.0.4"
45
45
  }
46
- }
46
+ }
@@ -78,3 +78,24 @@ export const mainHasSideNav = style(
78
78
  paddingLeft: `calc(${dimensions.sideNavWidth} + ${dimensions.padding})`,
79
79
  }),
80
80
  );
81
+
82
+ export const mainHasFooter = style({
83
+ paddingBottom: `calc(${dimensions.footerHeight} + ${dimensions.padding})`,
84
+ });
85
+
86
+ export const footer = style({
87
+ display: 'flex',
88
+ justifyContent: 'right',
89
+ alignItems: 'center',
90
+ gap: dimensions.padding,
91
+ padding: dimensions.padding,
92
+ position: 'fixed',
93
+ bottom: 0,
94
+ left: 0,
95
+ right: 0,
96
+ height: dimensions.footerHeight,
97
+ backgroundColor: colors.backgroundHaze,
98
+ borderTop: colors.border,
99
+ boxShadow: colors.shadow,
100
+ backdropFilter: 'blur(8px)',
101
+ });
@@ -23,8 +23,10 @@ import {Button} from '../Button/index.tsx';
23
23
  import {
24
24
  app,
25
25
  appLayout,
26
+ footer,
26
27
  header,
27
28
  main,
29
+ mainHasFooter,
28
30
  mainHasSideNav,
29
31
  sideNav,
30
32
  sideNavButton,
@@ -83,6 +85,11 @@ export const App = (props: {
83
85
  * the application.
84
86
  */
85
87
  readonly main?: ComponentType | ReactNode;
88
+ /**
89
+ * An optional component, element, or string which renders the footer of
90
+ * the application.
91
+ */
92
+ readonly footer?: ComponentType | ReactNode;
86
93
  /**
87
94
  * An extra CSS class name for the component.
88
95
  */
@@ -104,6 +111,7 @@ const Layout = ({
104
111
  topNavRight: topNavRightComponentOrNode,
105
112
  sideNav: sideNavComponentOrNode,
106
113
  main: mainComponentOrNode,
114
+ footer: footerComponentOrNode,
107
115
  className,
108
116
  }: Parameters<typeof App>[0]) => {
109
117
  const sessionStoreIsReady = useSessionStoreIsReady();
@@ -124,8 +132,10 @@ const Layout = ({
124
132
  topNavRightComponentOrNode,
125
133
  sideNavComponentOrNode,
126
134
  mainComponentOrNode,
135
+ footerComponentOrNode,
127
136
  ].some((componentOrNode) => componentOrNode);
128
137
  const hasSideNav = sideNavComponentOrNode != null;
138
+ const hasFooter = footerComponentOrNode != null;
129
139
 
130
140
  return sessionStoreIsReady && routeStoreIsReady && localStoreIsReady ? (
131
141
  <div
@@ -169,9 +179,20 @@ const Layout = ({
169
179
  </nav>
170
180
  ) : null}
171
181
  </header>
172
- <main className={classNames(main, hasSideNav && mainHasSideNav)}>
182
+ <main
183
+ className={classNames(
184
+ main,
185
+ hasSideNav && mainHasSideNav,
186
+ hasFooter && mainHasFooter,
187
+ )}
188
+ >
173
189
  {renderComponentOrNode(mainComponentOrNode)}
174
190
  </main>
191
+ {hasFooter ? (
192
+ <footer className={footer}>
193
+ {renderComponentOrNode(footerComponentOrNode)}
194
+ </footer>
195
+ ) : null}
175
196
  </>
176
197
  ) : null}
177
198
  </div>
@@ -1,5 +1,5 @@
1
- import type {ComponentType, ReactNode, Ref} from 'react';
2
- import {forwardRef, useCallback} from 'react';
1
+ import type {ComponentType, ReactNode} from 'react';
2
+ import {useCallback} from 'react';
3
3
  import {classNames, renderComponentOrNode} from '../../common/functions.tsx';
4
4
  import {iconSize} from '../../css/dimensions.css.ts';
5
5
  import {
@@ -103,104 +103,101 @@ import {
103
103
  * 'current'.
104
104
  * @icon Lucide.RectangleHorizontal
105
105
  */
106
- export const Button = forwardRef(
107
- (
108
- {
109
- icon: Icon,
110
- title: titleComponentOrNode,
111
- titleRight: titleRightComponentOrNode,
112
- iconRight: IconRight,
113
- onClick,
114
- variant = 'default',
115
- current,
116
- href,
117
- alt,
118
- className,
119
- }: {
120
- /**
121
- * An optional component which renders an icon for the button, and which
122
- * must accept a className prop.
123
- */
124
- readonly icon?: ComponentType<{className?: string}>;
125
- /**
126
- * An optional component, element, or string which renders the title of
127
- * the button.
128
- */
129
- readonly title?: ComponentType | ReactNode;
130
- /**
131
- * An optional component, element, or string which renders a second title
132
- * on the right side of the button.
133
- */
134
- readonly titleRight?: ComponentType | ReactNode;
135
- /**
136
- * An optional component which renders a second icon for the button, and
137
- * which must accept a className prop.
138
- */
139
- readonly iconRight?: ComponentType<{className?: string}>;
140
- /**
141
- * A handler called when the user clicks on the button.
142
- */
143
- readonly onClick?: () => void;
144
- /**
145
- * A variant of the button, one of:
146
- * - `default`
147
- * - `icon`
148
- * - `accent`
149
- * - `ghost`
150
- * - `item`
151
- */
152
- readonly variant?: keyof typeof buttonVariants;
153
- /**
154
- * A flag that indicates that an `item` button is 'current' and therefore
155
- * highlighted.
156
- */
157
- readonly current?: boolean;
158
- /**
159
- * A URL that can be used instead of an `onClick` to launch a new web
160
- * page, much like a link.
161
- */
162
- readonly href?: string;
163
- /**
164
- * Alternative text shown when the user hovers over the button.
165
- */
166
- readonly alt?: string;
167
- /**
168
- * An extra CSS class name for the component.
169
- */
170
- readonly className?: string;
171
- },
172
- ref: Ref<HTMLButtonElement>,
173
- ) => {
174
- const hrefClick = useCallback(
175
- () => (href ? open(href, '_blank', 'noreferrer') : null),
176
- [href],
177
- );
106
+ export const Button = ({
107
+ icon: Icon,
108
+ title: titleComponentOrNode,
109
+ titleRight: titleRightComponentOrNode,
110
+ iconRight: IconRight,
111
+ onClick,
112
+ variant = 'default',
113
+ current,
114
+ href,
115
+ alt,
116
+ className,
117
+ ref,
118
+ }: {
119
+ /**
120
+ * An optional component which renders an icon for the button, and which
121
+ * must accept a className prop.
122
+ */
123
+ readonly icon?: ComponentType<{className?: string}>;
124
+ /**
125
+ * An optional component, element, or string which renders the title of
126
+ * the button.
127
+ */
128
+ readonly title?: ComponentType | ReactNode;
129
+ /**
130
+ * An optional component, element, or string which renders a second title
131
+ * on the right side of the button.
132
+ */
133
+ readonly titleRight?: ComponentType | ReactNode;
134
+ /**
135
+ * An optional component which renders a second icon for the button, and
136
+ * which must accept a className prop.
137
+ */
138
+ readonly iconRight?: ComponentType<{className?: string}>;
139
+ /**
140
+ * A handler called when the user clicks on the button.
141
+ */
142
+ readonly onClick?: () => void;
143
+ /**
144
+ * A variant of the button, one of:
145
+ * - `default`
146
+ * - `icon`
147
+ * - `accent`
148
+ * - `ghost`
149
+ * - `item`
150
+ */
151
+ readonly variant?: keyof typeof buttonVariants;
152
+ /**
153
+ * A flag that indicates that an `item` button is 'current' and therefore
154
+ * highlighted.
155
+ */
156
+ readonly current?: boolean;
157
+ /**
158
+ * A URL that can be used instead of an `onClick` to launch a new web
159
+ * page, much like a link.
160
+ */
161
+ readonly href?: string;
162
+ /**
163
+ * Alternative text shown when the user hovers over the button.
164
+ */
165
+ readonly alt?: string;
166
+ /**
167
+ * An extra CSS class name for the component.
168
+ */
169
+ readonly className?: string;
170
+ ref?: React.RefObject<HTMLButtonElement>;
171
+ }) => {
172
+ const hrefClick = useCallback(
173
+ () => (href ? open(href, '_blank', 'noreferrer') : null),
174
+ [href],
175
+ );
178
176
 
179
- return (
180
- <button
181
- className={classNames(
182
- button,
183
- buttonVariants[variant],
184
- current && currentStyle,
185
- className,
186
- )}
187
- onClick={onClick ?? hrefClick}
188
- title={alt}
189
- ref={ref}
190
- >
191
- {Icon ? <Icon className={iconSize} /> : null}
192
- {titleComponentOrNode ? (
193
- <span className={titleStyle}>
194
- {renderComponentOrNode(titleComponentOrNode)}
195
- </span>
196
- ) : null}
197
- {titleRightComponentOrNode ? (
198
- <span className={titleStyleRight}>
199
- {renderComponentOrNode(titleRightComponentOrNode)}
200
- </span>
201
- ) : null}
202
- {IconRight ? <IconRight className={iconSize} /> : null}
203
- </button>
204
- );
205
- },
206
- );
177
+ return (
178
+ <button
179
+ className={classNames(
180
+ button,
181
+ buttonVariants[variant],
182
+ current && currentStyle,
183
+ className,
184
+ )}
185
+ onClick={onClick ?? hrefClick}
186
+ title={alt}
187
+ ref={ref}
188
+ >
189
+ {Icon ? <Icon className={iconSize} /> : null}
190
+ {titleComponentOrNode ? (
191
+ <span className={titleStyle}>
192
+ {renderComponentOrNode(titleComponentOrNode)}
193
+ </span>
194
+ ) : null}
195
+ {titleRightComponentOrNode ? (
196
+ <span className={titleStyleRight}>
197
+ {renderComponentOrNode(titleRightComponentOrNode)}
198
+ </span>
199
+ ) : null}
200
+ {IconRight ? <IconRight className={iconSize} /> : null}
201
+ </button>
202
+ );
203
+ };
@@ -8,6 +8,7 @@ const classAndObject = createTheme({
8
8
  radius: fallbackVar('var(--tinyWidgets-radius)', '0.5rem'),
9
9
  sideNavWidth: fallbackVar('var(--tinyWidgets-sideNavWidth)', '20rem'),
10
10
  topNavHeight: fallbackVar('var(--tinyWidgets-topNavHeight)', '4rem'),
11
+ footerHeight: fallbackVar('var(--tinyWidgets-footerHeight)', '2rem'),
11
12
  });
12
13
  export const dimensionsClass = classAndObject[0];
13
14
 
@@ -24,6 +25,7 @@ export const dimensionsClass = classAndObject[0];
24
25
  * - `radius`
25
26
  * - `sideNavWidth`
26
27
  * - `topNavHeight`
28
+ * - `footerHeight`
27
29
  *
28
30
  * You can use these variables directly in React components that take style
29
31
  * attributes, like this:
package/src/index.ts CHANGED
@@ -10,13 +10,7 @@ export {Metric} from './components/Metric/index.tsx';
10
10
  export {Row} from './components/Row/index.tsx';
11
11
  export {Summary} from './components/Summary/index.tsx';
12
12
  export {Tag} from './components/Tag/index.tsx';
13
- export {
14
- TasksProvider,
15
- useScheduleTask,
16
- } from './components/TasksProvider/index.tsx';
17
13
 
18
14
  export {classNames} from './common/functions.tsx';
19
15
  export {useDark} from './stores/LocalStore.tsx';
20
16
  export {useRoute, useSetRouteCallback} from './stores/RouteStore.tsx';
21
-
22
- export type {ScheduleTask} from './components/TasksProvider/index.tsx';
package/.prettierignore DELETED
@@ -1 +0,0 @@
1
- package.json
package/bun.lockb DELETED
Binary file