@teo-garcia/react-shared 1.2.0 → 1.2.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.
@@ -1,30 +1,27 @@
1
1
  import { type ReactNode } from 'react';
2
2
  export interface DevPanelProps {
3
3
  /**
4
- * Tailwind breakpoint map. Defaults to standard Tailwind v3/v4 breakpoints.
4
+ * Tailwind breakpoint map. Defaults to standard Tailwind v4 breakpoints.
5
5
  * Pass your own if you've customized the theme.
6
6
  */
7
7
  breakpoints?: Record<string, number>;
8
8
  /** Additional debug content rendered inside the panel. */
9
9
  children?: ReactNode;
10
- /** Corner to anchor the panel to. Defaults to `'bottom-left'`. */
11
- position?: 'top-left' | 'top-right' | 'bottom-left' | 'bottom-right';
12
10
  /**
13
11
  * Keyboard shortcut to toggle the panel.
14
12
  * Format: modifier keys joined by `+`, then the key. Defaults to `'shift+d'`.
15
- * Examples: `'shift+d'`, `'ctrl+shift+d'`, `'alt+d'`.
16
13
  */
17
14
  shortcut?: string;
18
15
  }
19
16
  /**
20
- * Fixed overlay showing the current Tailwind breakpoint, viewport dimensions,
21
- * and color scheme. Dev-only — renders nothing in production.
17
+ * Fixed bottom-center overlay showing the current Tailwind breakpoint, viewport
18
+ * dimensions, and color scheme. Dev-only — renders nothing in production.
22
19
  *
23
- * Much better than raw px shows the named breakpoint (`lg`) so you immediately
24
- * know which Tailwind classes are active, not just "1124px".
20
+ * Positioned at bottom-center to avoid clashing with Next.js (top-left) and
21
+ * TanStack devtools (bottom-right). Collapses to a compact pill on close.
25
22
  *
26
- * Pass children to add custom debug rows (route, user, feature flags, etc.).
27
- * Toggle visibility with the keyboard shortcut (default: Shift+D).
23
+ * Pass `children` to add custom debug rows (route, user ID, feature flags).
24
+ * Toggle with the keyboard shortcut (default: Shift+D).
28
25
  */
29
26
  export declare function DevPanel(props: DevPanelProps): import("react/jsx-runtime").JSX.Element | null;
30
27
  //# sourceMappingURL=dev-panel.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"dev-panel.d.ts","sourceRoot":"","sources":["../../../src/components/dev-panel/dev-panel.tsx"],"names":[],"mappings":"AAEA,OAAO,EAAuB,KAAK,SAAS,EAAsB,MAAM,OAAO,CAAA;AAwC/E,MAAM,WAAW,aAAa;IAC5B;;;OAGG;IACH,WAAW,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;IACpC,0DAA0D;IAC1D,QAAQ,CAAC,EAAE,SAAS,CAAA;IACpB,kEAAkE;IAClE,QAAQ,CAAC,EAAE,UAAU,GAAG,WAAW,GAAG,aAAa,GAAG,cAAc,CAAA;IACpE;;;;OAIG;IACH,QAAQ,CAAC,EAAE,MAAM,CAAA;CAClB;AA0LD;;;;;;;;;GASG;AACH,wBAAgB,QAAQ,CAAC,KAAK,EAAE,aAAa,kDAG5C"}
1
+ {"version":3,"file":"dev-panel.d.ts","sourceRoot":"","sources":["../../../src/components/dev-panel/dev-panel.tsx"],"names":[],"mappings":"AAEA,OAAO,EAAuB,KAAK,SAAS,EAAsB,MAAM,OAAO,CAAA;AAiC/E,MAAM,WAAW,aAAa;IAC5B;;;OAGG;IACH,WAAW,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;IACpC,0DAA0D;IAC1D,QAAQ,CAAC,EAAE,SAAS,CAAA;IACpB;;;OAGG;IACH,QAAQ,CAAC,EAAE,MAAM,CAAA;CAClB;AA8MD;;;;;;;;;GASG;AACH,wBAAgB,QAAQ,CAAC,KAAK,EAAE,aAAa,kDAG5C"}
@@ -1,5 +1,5 @@
1
1
  'use client';
2
- import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
3
3
  import { useEffect, useState } from 'react';
4
4
  const DEFAULT_BREAKPOINTS = {
5
5
  sm: 640,
@@ -8,12 +8,6 @@ const DEFAULT_BREAKPOINTS = {
8
8
  xl: 1280,
9
9
  '2xl': 1536,
10
10
  };
11
- const POSITION_STYLES = {
12
- 'top-left': { top: '0.75rem', left: '0.75rem' },
13
- 'top-right': { top: '0.75rem', right: '0.75rem' },
14
- 'bottom-left': { bottom: '0.75rem', left: '0.75rem' },
15
- 'bottom-right': { bottom: '0.75rem', right: '0.75rem' },
16
- };
17
11
  function resolveBreakpoint(width, breakpoints) {
18
12
  const sorted = Object.entries(breakpoints).sort(([, a], [, b]) => b - a);
19
13
  for (const [name, min] of sorted) {
@@ -31,7 +25,31 @@ function matchShortcut(e, shortcut) {
31
25
  e.ctrlKey === parts.includes('ctrl') &&
32
26
  e.altKey === parts.includes('alt'));
33
27
  }
34
- function DevPanelInner({ breakpoints = DEFAULT_BREAKPOINTS, children, position = 'bottom-left', shortcut = 'shift+d', }) {
28
+ const PILL_BASE = {
29
+ position: 'fixed',
30
+ bottom: '1rem',
31
+ left: '50%',
32
+ transform: 'translateX(-50%)',
33
+ zIndex: 9999,
34
+ fontFamily: 'ui-monospace, "Cascadia Code", "Fira Mono", monospace',
35
+ fontSize: '0.7rem',
36
+ lineHeight: 1,
37
+ background: 'rgba(9, 9, 11, 0.88)',
38
+ border: '1px solid rgba(255, 255, 255, 0.08)',
39
+ borderRadius: '9999px',
40
+ backdropFilter: 'blur(12px)',
41
+ WebkitBackdropFilter: 'blur(12px)',
42
+ boxShadow: '0 4px 24px rgba(0,0,0,0.45), inset 0 1px 0 rgba(255,255,255,0.04)',
43
+ userSelect: 'none',
44
+ whiteSpace: 'nowrap',
45
+ };
46
+ const DIVIDER = {
47
+ width: '1px',
48
+ height: '0.7rem',
49
+ background: 'rgba(255,255,255,0.1)',
50
+ flexShrink: 0,
51
+ };
52
+ function DevPanelInner({ breakpoints = DEFAULT_BREAKPOINTS, children, shortcut = 'shift+d', }) {
35
53
  const [open, setOpen] = useState(true);
36
54
  const [viewport, setViewport] = useState({ w: 0, h: 0 });
37
55
  const [dark, setDark] = useState(false);
@@ -43,7 +61,6 @@ function DevPanelInner({ breakpoints = DEFAULT_BREAKPOINTS, children, position =
43
61
  }
44
62
  update();
45
63
  window.addEventListener('resize', update);
46
- // Watch for class changes on <html> (Tailwind dark mode toggle)
47
64
  const observer = new MutationObserver(update);
48
65
  observer.observe(document.documentElement, {
49
66
  attributes: true,
@@ -67,86 +84,55 @@ function DevPanelInner({ breakpoints = DEFAULT_BREAKPOINTS, children, position =
67
84
  ...Object.entries(breakpoints).sort(([, a], [, b]) => a - b),
68
85
  ];
69
86
  const current = resolveBreakpoint(viewport.w, breakpoints);
70
- const base = {
71
- position: 'fixed',
72
- ...POSITION_STYLES[position],
73
- zIndex: 9999,
74
- fontFamily: 'ui-monospace, monospace',
75
- fontSize: '0.72rem',
76
- backdropFilter: 'blur(10px)',
77
- WebkitBackdropFilter: 'blur(10px)',
78
- };
79
87
  if (!open) {
80
- return (_jsx("button", { onClick: () => setOpen(true), title: `Dev Panel (${shortcut})`, style: {
81
- ...base,
82
- background: 'rgba(15,15,15,0.88)',
83
- color: '#06b6d4',
84
- border: '1px solid rgba(255,255,255,0.08)',
85
- borderRadius: '6px',
86
- padding: '0.2rem 0.5rem',
88
+ return (_jsxs("button", { onClick: () => setOpen(true), title: `Dev Panel (${shortcut})`, style: {
89
+ ...PILL_BASE,
90
+ display: 'flex',
91
+ alignItems: 'center',
92
+ gap: '0.3rem',
93
+ padding: '0.35rem 0.6rem',
87
94
  cursor: 'pointer',
88
- lineHeight: 1.5,
89
- }, children: current }));
95
+ color: 'rgba(255,255,255,0.45)',
96
+ }, children: [_jsx("span", { "aria-hidden": true, style: { color: '#38bdf8', fontSize: '0.45rem', lineHeight: 1 }, children: "\u25CF" }), _jsx("span", { style: {
97
+ color: '#e2e8f0',
98
+ fontWeight: 600,
99
+ letterSpacing: '0.05em',
100
+ }, children: current })] }));
90
101
  }
91
102
  return (_jsxs("div", { style: {
92
- ...base,
93
- background: 'rgba(12,12,12,0.93)',
94
- color: '#cbd5e1',
95
- border: '1px solid rgba(255,255,255,0.07)',
96
- borderRadius: '10px',
97
- padding: '0.6rem 0.75rem',
98
- lineHeight: 1.7,
99
- minWidth: '13rem',
100
- boxShadow: '0 8px 32px rgba(0,0,0,0.5)',
101
- userSelect: 'none',
102
- }, children: [_jsx("button", { onClick: () => setOpen(false), title: 'Close', style: {
103
- position: 'absolute',
104
- top: '0.3rem',
105
- right: '0.45rem',
103
+ ...PILL_BASE,
104
+ display: 'flex',
105
+ alignItems: 'center',
106
+ gap: '0.55rem',
107
+ padding: '0.4rem 0.65rem 0.4rem 0.7rem',
108
+ }, children: [_jsx("span", { "aria-hidden": true, style: { color: '#38bdf8', fontSize: '0.45rem', lineHeight: 1 }, children: "\u25CF" }), _jsx("div", { style: { display: 'flex', alignItems: 'baseline', gap: '0.3rem' }, children: allBreakpoints.map(([name]) => (_jsx("span", { style: {
109
+ color: name === current ? '#e2e8f0' : 'rgba(255,255,255,0.18)',
110
+ fontWeight: name === current ? 600 : 400,
111
+ fontSize: name === current ? '0.72rem' : '0.67rem',
112
+ letterSpacing: name === current ? '0.05em' : '0.02em',
113
+ }, children: name }, name))) }), _jsx("div", { style: DIVIDER }), _jsxs("span", { style: { color: 'rgba(255,255,255,0.3)', letterSpacing: '0.02em' }, children: [viewport.w, _jsx("span", { style: { color: 'rgba(255,255,255,0.12)', margin: '0 0.15rem' }, children: "\u00D7" }), viewport.h] }), _jsx("div", { style: DIVIDER }), _jsx("span", { title: dark ? 'dark mode' : 'light mode', style: { color: 'rgba(255,255,255,0.3)', fontSize: '0.65rem' }, children: dark ? '◑' : '◯' }), children && (_jsxs(_Fragment, { children: [_jsx("div", { style: DIVIDER }), _jsx("div", { style: {
114
+ color: 'rgba(255,255,255,0.28)',
115
+ fontSize: '0.68rem',
116
+ }, children: children })] })), _jsx("div", { style: DIVIDER }), _jsxs("span", { style: { color: 'rgba(255,255,255,0.15)', fontSize: '0.65rem' }, children: [shortcut, " to toggle"] }), _jsx("button", { onClick: () => setOpen(false), title: 'Close', style: {
106
117
  background: 'none',
107
118
  border: 'none',
108
- color: '#475569',
119
+ color: 'rgba(255,255,255,0.2)',
109
120
  cursor: 'pointer',
110
- fontSize: '0.65rem',
121
+ fontSize: '0.58rem',
111
122
  lineHeight: 1,
112
- padding: 0,
113
- }, children: "\u2715" }), _jsx("div", { style: {
114
- display: 'flex',
115
- gap: '0.4rem',
116
- alignItems: 'baseline',
117
- marginBottom: '0.1rem',
118
- }, children: allBreakpoints.map(([name]) => (_jsx("span", { style: {
119
- color: name === current ? '#06b6d4' : '#334155',
120
- fontWeight: name === current ? 700 : 400,
121
- fontSize: name === current ? '0.78rem' : '0.68rem',
122
- letterSpacing: name === current ? '0.02em' : undefined,
123
- }, children: name }, name))) }), _jsxs("div", { style: {
124
- display: 'flex',
125
- gap: '0.75rem',
126
- color: '#475569',
127
- fontSize: '0.68rem',
128
- }, children: [_jsxs("span", { children: [viewport.w, " \u00D7 ", viewport.h] }), _jsx("span", { children: dark ? '☾ dark' : '☀ light' })] }), children && (_jsx("div", { style: {
129
- marginTop: '0.4rem',
130
- paddingTop: '0.4rem',
131
- borderTop: '1px solid rgba(255,255,255,0.05)',
132
- color: '#64748b',
133
- fontSize: '0.68rem',
134
- lineHeight: 1.6,
135
- }, children: children })), _jsxs("div", { style: {
136
- marginTop: '0.3rem',
137
- color: '#1e293b',
138
- fontSize: '0.6rem',
139
- }, children: [shortcut, " to toggle"] })] }));
123
+ padding: '0 0 0 0.1rem',
124
+ marginLeft: '0.05rem',
125
+ }, children: "\u2715" })] }));
140
126
  }
141
127
  /**
142
- * Fixed overlay showing the current Tailwind breakpoint, viewport dimensions,
143
- * and color scheme. Dev-only — renders nothing in production.
128
+ * Fixed bottom-center overlay showing the current Tailwind breakpoint, viewport
129
+ * dimensions, and color scheme. Dev-only — renders nothing in production.
144
130
  *
145
- * Much better than raw px shows the named breakpoint (`lg`) so you immediately
146
- * know which Tailwind classes are active, not just "1124px".
131
+ * Positioned at bottom-center to avoid clashing with Next.js (top-left) and
132
+ * TanStack devtools (bottom-right). Collapses to a compact pill on close.
147
133
  *
148
- * Pass children to add custom debug rows (route, user, feature flags, etc.).
149
- * Toggle visibility with the keyboard shortcut (default: Shift+D).
134
+ * Pass `children` to add custom debug rows (route, user ID, feature flags).
135
+ * Toggle with the keyboard shortcut (default: Shift+D).
150
136
  */
151
137
  export function DevPanel(props) {
152
138
  if (process.env.NODE_ENV === 'production')
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@teo-garcia/react-shared",
3
- "version": "1.2.0",
3
+ "version": "1.2.1",
4
4
  "description": "Shared React hooks, utilities, and test helpers for the teo-garcia template portfolio",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",
@@ -8,142 +8,177 @@
8
8
  "exports": {
9
9
  ".": {
10
10
  "import": "./dist/index.js",
11
+ "default": "./dist/index.js",
11
12
  "types": "./dist/index.d.ts"
12
13
  },
13
14
  "./components": {
14
15
  "import": "./dist/components/index.js",
16
+ "default": "./dist/components/index.js",
15
17
  "types": "./dist/components/index.d.ts"
16
18
  },
17
19
  "./components/error-boundary": {
18
20
  "import": "./dist/components/error-boundary/index.js",
21
+ "default": "./dist/components/error-boundary/index.js",
19
22
  "types": "./dist/components/error-boundary/index.d.ts"
20
23
  },
21
24
  "./components/focus-trap": {
22
25
  "import": "./dist/components/focus-trap/index.js",
26
+ "default": "./dist/components/focus-trap/index.js",
23
27
  "types": "./dist/components/focus-trap/index.d.ts"
24
28
  },
25
29
  "./components/portal": {
26
30
  "import": "./dist/components/portal/index.js",
31
+ "default": "./dist/components/portal/index.js",
27
32
  "types": "./dist/components/portal/index.d.ts"
28
33
  },
29
34
  "./components/skeleton": {
30
35
  "import": "./dist/components/skeleton/index.js",
36
+ "default": "./dist/components/skeleton/index.js",
31
37
  "types": "./dist/components/skeleton/index.d.ts"
32
38
  },
33
39
  "./components/visually-hidden": {
34
40
  "import": "./dist/components/visually-hidden/index.js",
41
+ "default": "./dist/components/visually-hidden/index.js",
35
42
  "types": "./dist/components/visually-hidden/index.d.ts"
36
43
  },
37
44
  "./components/aspect-ratio": {
38
45
  "import": "./dist/components/aspect-ratio/index.js",
46
+ "default": "./dist/components/aspect-ratio/index.js",
39
47
  "types": "./dist/components/aspect-ratio/index.d.ts"
40
48
  },
41
49
  "./components/debug-json": {
42
50
  "import": "./dist/components/debug-json/index.js",
51
+ "default": "./dist/components/debug-json/index.js",
43
52
  "types": "./dist/components/debug-json/index.d.ts"
44
53
  },
45
54
  "./components/dev-panel": {
46
55
  "import": "./dist/components/dev-panel/index.js",
56
+ "default": "./dist/components/dev-panel/index.js",
47
57
  "types": "./dist/components/dev-panel/index.d.ts"
48
58
  },
49
59
  "./components/separator": {
50
60
  "import": "./dist/components/separator/index.js",
61
+ "default": "./dist/components/separator/index.js",
51
62
  "types": "./dist/components/separator/index.d.ts"
52
63
  },
53
64
  "./components/skip-link": {
54
65
  "import": "./dist/components/skip-link/index.js",
66
+ "default": "./dist/components/skip-link/index.js",
55
67
  "types": "./dist/components/skip-link/index.d.ts"
56
68
  },
57
69
  "./hooks": {
58
70
  "import": "./dist/hooks/index.js",
71
+ "default": "./dist/hooks/index.js",
59
72
  "types": "./dist/hooks/index.d.ts"
60
73
  },
61
74
  "./hooks/use-debounce": {
62
75
  "import": "./dist/hooks/use-debounce.js",
76
+ "default": "./dist/hooks/use-debounce.js",
63
77
  "types": "./dist/hooks/use-debounce.d.ts"
64
78
  },
65
79
  "./hooks/use-isomorphic-layout-effect": {
66
80
  "import": "./dist/hooks/use-isomorphic-layout-effect.js",
81
+ "default": "./dist/hooks/use-isomorphic-layout-effect.js",
67
82
  "types": "./dist/hooks/use-isomorphic-layout-effect.d.ts"
68
83
  },
69
84
  "./hooks/use-local-storage": {
70
85
  "import": "./dist/hooks/use-local-storage.js",
86
+ "default": "./dist/hooks/use-local-storage.js",
71
87
  "types": "./dist/hooks/use-local-storage.d.ts"
72
88
  },
73
89
  "./hooks/use-media-query": {
74
90
  "import": "./dist/hooks/use-media-query.js",
91
+ "default": "./dist/hooks/use-media-query.js",
75
92
  "types": "./dist/hooks/use-media-query.d.ts"
76
93
  },
77
94
  "./hooks/use-on-click-outside": {
78
95
  "import": "./dist/hooks/use-on-click-outside.js",
96
+ "default": "./dist/hooks/use-on-click-outside.js",
79
97
  "types": "./dist/hooks/use-on-click-outside.d.ts"
80
98
  },
81
99
  "./hooks/use-previous": {
82
100
  "import": "./dist/hooks/use-previous.js",
101
+ "default": "./dist/hooks/use-previous.js",
83
102
  "types": "./dist/hooks/use-previous.d.ts"
84
103
  },
85
104
  "./hooks/use-copy-to-clipboard": {
86
105
  "import": "./dist/hooks/use-copy-to-clipboard.js",
106
+ "default": "./dist/hooks/use-copy-to-clipboard.js",
87
107
  "types": "./dist/hooks/use-copy-to-clipboard.d.ts"
88
108
  },
89
109
  "./hooks/use-event-listener": {
90
110
  "import": "./dist/hooks/use-event-listener.js",
111
+ "default": "./dist/hooks/use-event-listener.js",
91
112
  "types": "./dist/hooks/use-event-listener.d.ts"
92
113
  },
93
114
  "./hooks/use-idle": {
94
115
  "import": "./dist/hooks/use-idle.js",
116
+ "default": "./dist/hooks/use-idle.js",
95
117
  "types": "./dist/hooks/use-idle.d.ts"
96
118
  },
97
119
  "./hooks/use-intersection-observer": {
98
120
  "import": "./dist/hooks/use-intersection-observer.js",
121
+ "default": "./dist/hooks/use-intersection-observer.js",
99
122
  "types": "./dist/hooks/use-intersection-observer.d.ts"
100
123
  },
101
124
  "./hooks/use-latest": {
102
125
  "import": "./dist/hooks/use-latest.js",
126
+ "default": "./dist/hooks/use-latest.js",
103
127
  "types": "./dist/hooks/use-latest.d.ts"
104
128
  },
105
129
  "./hooks/use-network-status": {
106
130
  "import": "./dist/hooks/use-network-status.js",
131
+ "default": "./dist/hooks/use-network-status.js",
107
132
  "types": "./dist/hooks/use-network-status.d.ts"
108
133
  },
109
134
  "./hooks/use-render-count": {
110
135
  "import": "./dist/hooks/use-render-count.js",
136
+ "default": "./dist/hooks/use-render-count.js",
111
137
  "types": "./dist/hooks/use-render-count.d.ts"
112
138
  },
113
139
  "./hooks/use-toggle": {
114
140
  "import": "./dist/hooks/use-toggle.js",
141
+ "default": "./dist/hooks/use-toggle.js",
115
142
  "types": "./dist/hooks/use-toggle.d.ts"
116
143
  },
117
144
  "./hooks/use-why-did-you-render": {
118
145
  "import": "./dist/hooks/use-why-did-you-render.js",
146
+ "default": "./dist/hooks/use-why-did-you-render.js",
119
147
  "types": "./dist/hooks/use-why-did-you-render.d.ts"
120
148
  },
121
149
  "./utils": {
122
150
  "import": "./dist/utils/index.js",
151
+ "default": "./dist/utils/index.js",
123
152
  "types": "./dist/utils/index.d.ts"
124
153
  },
125
154
  "./utils/cn": {
126
155
  "import": "./dist/utils/cn.js",
156
+ "default": "./dist/utils/cn.js",
127
157
  "types": "./dist/utils/cn.d.ts"
128
158
  },
129
159
  "./utils/format-date": {
130
160
  "import": "./dist/utils/format-date.js",
161
+ "default": "./dist/utils/format-date.js",
131
162
  "types": "./dist/utils/format-date.d.ts"
132
163
  },
133
164
  "./utils/format-number": {
134
165
  "import": "./dist/utils/format-number.js",
166
+ "default": "./dist/utils/format-number.js",
135
167
  "types": "./dist/utils/format-number.d.ts"
136
168
  },
137
169
  "./utils/truncate": {
138
170
  "import": "./dist/utils/truncate.js",
171
+ "default": "./dist/utils/truncate.js",
139
172
  "types": "./dist/utils/truncate.d.ts"
140
173
  },
141
174
  "./test-utils": {
142
175
  "import": "./dist/test-utils/index.js",
176
+ "default": "./dist/test-utils/index.js",
143
177
  "types": "./dist/test-utils/index.d.ts"
144
178
  },
145
179
  "./types": {
146
180
  "import": "./dist/types.js",
181
+ "default": "./dist/types.js",
147
182
  "types": "./dist/types.d.ts"
148
183
  }
149
184
  },