@stevederico/skateboard-ui 4.3.0 → 4.6.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/CHANGELOG.md +16 -0
- package/README.md +3 -1
- package/dist/components/ThemeToggle.js +2 -2
- package/dist/components/core/Utilities.d.ts +2 -1
- package/dist/components/core/Utilities.js +2 -5
- package/dist/components/views/SettingsView.js +2 -5
- package/dist/ui/slot.d.ts +4 -0
- package/dist/ui/slot.js +19 -1
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,21 @@
|
|
|
1
1
|
# CHANGELOG
|
|
2
2
|
|
|
3
|
+
4.6.0
|
|
4
|
+
|
|
5
|
+
SettingsView uses ThemeToggle
|
|
6
|
+
|
|
7
|
+
4.5.0
|
|
8
|
+
|
|
9
|
+
Toggle uses resolvedTheme
|
|
10
|
+
ThemeProvider owns dark
|
|
11
|
+
Drop dark-mode stripping
|
|
12
|
+
Slot render child fallback
|
|
13
|
+
|
|
14
|
+
4.4.0
|
|
15
|
+
|
|
16
|
+
Document a11y releases
|
|
17
|
+
Fix peer-dep naming
|
|
18
|
+
|
|
3
19
|
4.3.0
|
|
4
20
|
|
|
5
21
|
Submenu aria-controls wiring
|
package/README.md
CHANGED
|
@@ -6,6 +6,8 @@ React component library for rapid application development. Built with TypeScript
|
|
|
6
6
|
|
|
7
7
|
**Self-contained components (v4.0).** Every component is now hand-written with no primitive framework underneath — the previously-vendored `@base-ui/react` bundle (~31k lines) is gone. Floating positioning, focus trapping, dismiss layers, and animations are small in-house hooks; modals use the native `<dialog>` element. The legacy `shadcn/ui/*` import paths still work — they re-export the new `ui/*` components — so existing apps need no changes.
|
|
8
8
|
|
|
9
|
+
**Accessibility-hardened (v4.1–4.3).** The self-contained tier was put through three rounds of a11y work: menu/select typeahead, correct keyboard focus management and tab-stops (menus, tabs, radios, popovers, navigation menu), ARIA wiring (`aria-controls`, labelled-by, indeterminate checkbox mixed state, named popover/slider dialogs), scroll-lock and exit-animation fixes, plus matching DOMException error names. Each release adds to a Playwright a11y regression suite that runs `workers: 1`.
|
|
10
|
+
|
|
9
11
|
**TypeScript with full type declarations.** Source is TypeScript, compiled to plain JavaScript + `.d.ts` in `dist/` (`npm run build`). JavaScript apps consume the compiled JS exactly as before — import paths are unchanged — and TypeScript apps get real types for every export (`SkateboardConstants`, `User`, component props, `VariantProps`, typed icons).
|
|
10
12
|
|
|
11
13
|
**Node.js 24+** is required in the app repo for build tooling and backend (see `engines` in `package.json`). The UI package itself runs in the browser.
|
|
@@ -1309,7 +1311,7 @@ All components support dark mode automatically and accept a `className` prop for
|
|
|
1309
1311
|
### Required peer dependencies
|
|
1310
1312
|
- React 19.1+
|
|
1311
1313
|
- react-dom 19.1+
|
|
1312
|
-
- react-router
|
|
1314
|
+
- react-router 7.0+
|
|
1313
1315
|
|
|
1314
1316
|
### Hard dependencies
|
|
1315
1317
|
|
|
@@ -5,14 +5,14 @@ import { Sun, Moon } from '../icons/index.js';
|
|
|
5
5
|
import { Button } from '../shadcn/ui/button.js';
|
|
6
6
|
import { cn } from '../shadcn/lib/utils.js';
|
|
7
7
|
export default function ThemeToggle({ className = "", iconSize = 16, variant = "settings", ...props }) {
|
|
8
|
-
const {
|
|
8
|
+
const { resolvedTheme, setTheme } = useTheme();
|
|
9
9
|
const [mounted, setMounted] = React.useState(false);
|
|
10
10
|
React.useEffect(() => {
|
|
11
11
|
setMounted(true);
|
|
12
12
|
}, []);
|
|
13
13
|
if (!mounted)
|
|
14
14
|
return null;
|
|
15
|
-
const isDarkMode =
|
|
15
|
+
const isDarkMode = resolvedTheme === 'dark';
|
|
16
16
|
const toggleTheme = () => setTheme(isDarkMode ? 'light' : 'dark');
|
|
17
17
|
return (_jsx(Button, { variant: variant === "landing" ? "outline" : "ghost", size: "icon", onClick: toggleTheme, className: cn(className), "aria-label": "Toggle dark mode", ...props, children: isDarkMode
|
|
18
18
|
? _jsx(Sun, { size: iconSize })
|
|
@@ -321,7 +321,8 @@ export declare function showUpgradeSheet(upgradeSheetRef: RefObject<{
|
|
|
321
321
|
*/
|
|
322
322
|
export declare function timestampToString(input: number | Date, format?: string): string | number | Date;
|
|
323
323
|
/**
|
|
324
|
-
* Hook that sets the document title
|
|
324
|
+
* Hook that sets the document title on navigation.
|
|
325
|
+
* Dark mode is owned by ThemeProvider — never touch the class here.
|
|
325
326
|
*
|
|
326
327
|
* @param {Object} location - react-router location object
|
|
327
328
|
*/
|
|
@@ -657,17 +657,14 @@ export function timestampToString(input, format = "DOB") {
|
|
|
657
657
|
}
|
|
658
658
|
}
|
|
659
659
|
/**
|
|
660
|
-
* Hook that sets the document title
|
|
660
|
+
* Hook that sets the document title on navigation.
|
|
661
|
+
* Dark mode is owned by ThemeProvider — never touch the class here.
|
|
661
662
|
*
|
|
662
663
|
* @param {Object} location - react-router location object
|
|
663
664
|
*/
|
|
664
665
|
export function useAppSetup(location) {
|
|
665
666
|
useEffect(() => {
|
|
666
667
|
document.title = getConstants().appName;
|
|
667
|
-
if (!location.pathname.toLowerCase().includes('app')) {
|
|
668
|
-
document.documentElement.classList.remove('dark');
|
|
669
|
-
document.body.classList.remove('dark');
|
|
670
|
-
}
|
|
671
668
|
}, [location.pathname]);
|
|
672
669
|
}
|
|
673
670
|
// ===== API REQUEST UTILITIES =====
|
|
@@ -2,8 +2,7 @@ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
|
2
2
|
import React from 'react';
|
|
3
3
|
import { useNavigate } from 'react-router';
|
|
4
4
|
import { getState } from '../core/Context.js';
|
|
5
|
-
import
|
|
6
|
-
import { Sun, Moon } from '../../icons/index.js';
|
|
5
|
+
import ThemeToggle from '../ThemeToggle.js';
|
|
7
6
|
import Header from '../layout/Header.js';
|
|
8
7
|
import { Avatar, AvatarFallback } from '../../shadcn/ui/avatar.js';
|
|
9
8
|
import { Badge } from '../../shadcn/ui/badge.js';
|
|
@@ -29,8 +28,6 @@ export default function SettingsView() {
|
|
|
29
28
|
const { state, dispatch } = getState();
|
|
30
29
|
const constants = state.constants;
|
|
31
30
|
const navigate = useNavigate();
|
|
32
|
-
const { theme, setTheme } = useTheme();
|
|
33
|
-
const isDarkMode = theme === 'dark';
|
|
34
31
|
const user = state.user;
|
|
35
32
|
const subscription = user?.subscription;
|
|
36
33
|
const showAuth = (constants.noLogin === false || typeof constants.noLogin === 'undefined') && user;
|
|
@@ -49,7 +46,7 @@ export default function SettingsView() {
|
|
|
49
46
|
return `Ends ${new Date(subscription.expires * 1000).toLocaleDateString('en-US')}`;
|
|
50
47
|
return `Plan ${status}`;
|
|
51
48
|
}
|
|
52
|
-
return (_jsxs("div", { className: "flex-1", children: [_jsx(Header, { title: "Settings", children: _jsx(
|
|
49
|
+
return (_jsxs("div", { className: "flex-1", children: [_jsx(Header, { title: "Settings", children: _jsx(ThemeToggle, { iconSize: 20 }) }), _jsxs("div", { className: "flex flex-col items-center p-4 gap-4", children: [!user && constants.noLogin !== true && (_jsx(Card, { className: "w-full max-w-lg", children: _jsxs(CardHeader, { children: [_jsx(CardTitle, { children: "Account" }), _jsx(CardDescription, { children: "Sign in to access your account settings." }), _jsx(CardAction, { children: _jsx(Button, { variant: "outline", size: "sm", onClick: () => {
|
|
53
50
|
if (isAuthOverlayEnabled()) {
|
|
54
51
|
dispatch({ type: 'SHOW_AUTH_OVERLAY' });
|
|
55
52
|
}
|
package/dist/ui/slot.d.ts
CHANGED
|
@@ -19,6 +19,10 @@ declare function Slot({ children, className, style, ref, ...props }: SlotProps):
|
|
|
19
19
|
* element to `render` to control the rendered element; here that maps onto the
|
|
20
20
|
* `asChild` + Slot mechanism. Returns whether to use the Slot and what child to
|
|
21
21
|
* render through it, so `render={<Button/>}` keeps working on the new components.
|
|
22
|
+
* Matching Base UI's render-prop semantics, the component's children become the
|
|
23
|
+
* render element's children when the element has none of its own — so
|
|
24
|
+
* `<Trigger render={<Button/>}>Columns</Trigger>` renders the label, while
|
|
25
|
+
* `render={<Button>Sign Out</Button>}` keeps the element's own children.
|
|
22
26
|
*/
|
|
23
27
|
declare function resolveRender(asChild: boolean | undefined, render: React.ReactElement | undefined, children: React.ReactNode): {
|
|
24
28
|
useSlot: boolean;
|
package/dist/ui/slot.js
CHANGED
|
@@ -53,10 +53,28 @@ function Slot({ children, className, style, ref, ...props }) {
|
|
|
53
53
|
* element to `render` to control the rendered element; here that maps onto the
|
|
54
54
|
* `asChild` + Slot mechanism. Returns whether to use the Slot and what child to
|
|
55
55
|
* render through it, so `render={<Button/>}` keeps working on the new components.
|
|
56
|
+
* Matching Base UI's render-prop semantics, the component's children become the
|
|
57
|
+
* render element's children when the element has none of its own — so
|
|
58
|
+
* `<Trigger render={<Button/>}>Columns</Trigger>` renders the label, while
|
|
59
|
+
* `render={<Button>Sign Out</Button>}` keeps the element's own children.
|
|
56
60
|
*/
|
|
57
61
|
function resolveRender(asChild, render, children) {
|
|
58
|
-
if (React.isValidElement(render))
|
|
62
|
+
if (React.isValidElement(render)) {
|
|
63
|
+
const renderProps = render.props;
|
|
64
|
+
const ownChildren = typeof renderProps === "object" &&
|
|
65
|
+
renderProps !== null &&
|
|
66
|
+
"children" in renderProps
|
|
67
|
+
? renderProps.children
|
|
68
|
+
: undefined;
|
|
69
|
+
// != null, not truthiness: 0 and "" are renderable children to keep.
|
|
70
|
+
if (ownChildren == null && children != null) {
|
|
71
|
+
return {
|
|
72
|
+
useSlot: true,
|
|
73
|
+
slotChild: React.cloneElement(render, undefined, children),
|
|
74
|
+
};
|
|
75
|
+
}
|
|
59
76
|
return { useSlot: true, slotChild: render };
|
|
77
|
+
}
|
|
60
78
|
return { useSlot: !!asChild, slotChild: children };
|
|
61
79
|
}
|
|
62
80
|
export { Slot, mergeRefs, resolveRender };
|