From ce924d4b6d7c5844dbac9df3de6cd575c69b5639 Mon Sep 17 00:00:00 2001 From: Sakti Kumar Chourasia Date: Thu, 23 Apr 2026 23:13:20 -0700 Subject: [PATCH] fix: updated import method and updated demo website to reflect that --- README.md | 64 ++++++++++++++++++ demo/src/components/islands/InstallTabs.tsx | 73 ++++++++++++++++----- package.json | 44 +++++++++++-- src/DraggableSheet.tsx | 2 + src/FlickDeck.tsx | 2 + src/InspectorBubble.tsx | 2 + src/MovableLauncher.tsx | 2 + src/ResizableSplitPane.tsx | 2 + src/SnapDock.tsx | 2 + src/ZoomLens.tsx | 2 + vite.config.js | 16 ++++- 11 files changed, 188 insertions(+), 23 deletions(-) diff --git a/README.md b/README.md index 88c0d03..bd8a528 100644 --- a/README.md +++ b/README.md @@ -32,6 +32,7 @@ Building a chat widget, floating toolbar, debug panel, or side dock? You want th | [``](#resizablesplitter) | An N-pane resizable split layout with draggable handles, min/max constraints, and localStorage-persisted ratios. | | [``](#inspectorbubble) | A Chrome-DevTools-style element picker overlay for design QA — hover to see tag, selector, dimensions, font, colors + WCAG contrast, box model, ARIA role, and accessible name. | | [``](#zoomlens) | A draggable magnifier circle that zooms into whatever it hovers — free-drag over the whole page or scope it to one element (product-image-zoom style). Wheel to zoom, hotkey or Escape to dismiss. | +| [``](#flickdeck) | A stack of cards where each back card peeks from one edge. Click the peek to flick that card to the front, or optionally swipe the front card off to dismiss it. | ## Installation @@ -56,6 +57,21 @@ bun add react-driftkit +## Importing + +Every component is available two ways — both tree-shake to the same code. + +```tsx +// 1. Barrel import — grab multiple components at once +import { MovableLauncher, SnapDock, InspectorBubble } from 'react-driftkit'; + +// 2. Per-component subpath — named or default, pick the style you prefer +import { SnapDock } from 'react-driftkit/SnapDock'; +import SnapDock from 'react-driftkit/SnapDock'; +``` + +Subpath imports are handy when you only need one component and want the import line to be explicit about bundle cost (your bundler will tree-shake the barrel import down to the same output either way, as long as `sideEffects` is respected — which it is here). + ## Quick Start ```tsx @@ -67,6 +83,7 @@ import { ResizableSplitPane, InspectorBubble, ZoomLens, + FlickDeck, } from 'react-driftkit'; function App() { @@ -104,6 +121,13 @@ function App() { {/* Magnifier scoped to one element — hover to zoom. */} Product + + {/* Stack of cards — click a peeking card to flick it to the front. */} + +
Overview
+
Details
+
Stats
+
); } @@ -125,6 +149,8 @@ A draggable floating wrapper that lets users pick up any widget and drop it anyw - **Click vs. drag threshold** (5 px) so nested buttons still fire ```tsx +import MovableLauncher from 'react-driftkit/MovableLauncher'; + @@ -143,6 +169,8 @@ An edge-pinned dock that slides along any side of the viewport. Drop it anywhere - **Unstyled** — `data-edge` and `data-orientation` attributes let you drive CSS without re-rendering ```tsx +import SnapDock from 'react-driftkit/SnapDock'; + @@ -164,6 +192,8 @@ A pull-up / pull-down sheet pinned to an edge, with snap points like `peek`, `ha - **Drag handle selector** — confine drag to a nested handle so inner content stays scrollable ```tsx +import DraggableSheet from 'react-driftkit/DraggableSheet'; +
Details, filters, cart...
@@ -184,6 +214,8 @@ An N-pane resizable split layout. Drag the handles between panes to redistribute - **Double-click reset** to `defaultSizes` ```tsx +import ResizableSplitPane from 'react-driftkit/ResizableSplitPane'; + @@ -204,6 +236,8 @@ A Chrome-DevTools-style element picker overlay for design QA. Turn it on, hover - **Hotkey toggle**, ignore rules, and self-skipping overlay chrome ```tsx +import InspectorBubble from 'react-driftkit/InspectorBubble'; + + Overview + Details + Stats + +``` + +**Full API, more examples, and live demo →** + +--- + ## Use Cases - **Chat widgets** — floating support buttons that stay accessible @@ -254,6 +314,8 @@ A draggable magnifier circle that zooms into whatever it hovers. Great for desig - **In-house devtools** — a built-in element picker for style audits, a11y audits, or click-to-log workflows - **Product image zoom** — magnifier scoped to a single image, follows the cursor, hides on leave - **Data table inspection** — drag a magnifier over dense tables, charts, or heatmaps to read small values without re-flowing the page +- **Tip / onboarding stacks** — a deck of coachmark cards the user can flick through and swipe off one by one +- **Comparison decks** — toggle between product plans, chart variants, or before/after states with a single click on the peek ## How it works @@ -267,6 +329,8 @@ Under the hood all components use the [Pointer Events API](https://developer.moz `ZoomLens` live-clones either `document.body` (free mode) or a target element (target mode) into a portalled host, then applies a `translate()` + `scale()` transform so the point under the lens center maps to target-local — or document — coords. A `MutationObserver` rebuilds the clone when the real DOM changes, debounced to 150 ms and skipped during drag. In target mode, pointer tracking attaches directly to the target, and the lens overlay is `pointer-events: none` so hover state keeps passing through to the real element underneath. +`FlickDeck` lays every card in a single CSS grid cell so the container auto-sizes to the largest card, then offsets back cards with pure `transform` — `translate` along the peek axis, plus `scale` (top/bottom peek) or `rotate` around the attached edge (left/right peek). Depth fade uses `opacity`. The front card's `key` is its id; a click or keyboard activation on a peek swaps ids with a CSS transition. Swipe-to-dismiss tracks pointer movement on the front card and fires `on.dismiss(id)` once the drag crosses `dismissThreshold` in the direction opposite the peek, leaving the consumer to remove that child. + ## Contributing Contributions are welcome. Open an issue or send a pull request. diff --git a/demo/src/components/islands/InstallTabs.tsx b/demo/src/components/islands/InstallTabs.tsx index 537d703..32aaae7 100644 --- a/demo/src/components/islands/InstallTabs.tsx +++ b/demo/src/components/islands/InstallTabs.tsx @@ -7,27 +7,68 @@ const installCommands = [ { pm: 'pnpm', cmd: 'pnpm add react-driftkit' }, ]; +const importStyles = [ + { + key: 'barrel', + label: 'Barrel', + code: `import { SnapDock, InspectorBubble } from 'react-driftkit';`, + }, + { + key: 'subpath-named', + label: 'Per-component (named)', + code: `import { SnapDock } from 'react-driftkit/SnapDock';`, + }, + { + key: 'subpath-default', + label: 'Per-component (default)', + code: `import SnapDock from 'react-driftkit/SnapDock';`, + }, +]; + export default function InstallTabs() { const [activePm, setActivePm] = useState('npm'); + const [activeImport, setActiveImport] = useState('barrel'); const active = installCommands.find((c) => c.pm === activePm) ?? installCommands[0]; + const activeImp = importStyles.find((i) => i.key === activeImport) ?? importStyles[0]; return ( -
-
- {installCommands.map(({ pm }) => ( - - ))} + <> +
+
+ {installCommands.map(({ pm }) => ( + + ))} +
+
+ {active.cmd} + +
-
- {active.cmd} - + +
+
+ {importStyles.map(({ key, label }) => ( + + ))} +
+
+ {activeImp.code} + +
-
+ ); } diff --git a/package.json b/package.json index bf8f6e3..625703d 100644 --- a/package.json +++ b/package.json @@ -3,14 +3,50 @@ "version": "0.7.0", "description": "Small React primitives for floating UI: draggable launchers and edge-pinned docks", "type": "module", - "main": "dist/react-driftkit.cjs", - "module": "dist/react-driftkit.js", + "sideEffects": false, + "main": "dist/index.cjs", + "module": "dist/index.js", "types": "dist/index.d.ts", "exports": { ".": { "types": "./dist/index.d.ts", - "import": "./dist/react-driftkit.js", - "require": "./dist/react-driftkit.cjs" + "import": "./dist/index.js", + "require": "./dist/index.cjs" + }, + "./MovableLauncher": { + "types": "./dist/MovableLauncher.d.ts", + "import": "./dist/MovableLauncher.js", + "require": "./dist/MovableLauncher.cjs" + }, + "./SnapDock": { + "types": "./dist/SnapDock.d.ts", + "import": "./dist/SnapDock.js", + "require": "./dist/SnapDock.cjs" + }, + "./DraggableSheet": { + "types": "./dist/DraggableSheet.d.ts", + "import": "./dist/DraggableSheet.js", + "require": "./dist/DraggableSheet.cjs" + }, + "./ResizableSplitPane": { + "types": "./dist/ResizableSplitPane.d.ts", + "import": "./dist/ResizableSplitPane.js", + "require": "./dist/ResizableSplitPane.cjs" + }, + "./InspectorBubble": { + "types": "./dist/InspectorBubble.d.ts", + "import": "./dist/InspectorBubble.js", + "require": "./dist/InspectorBubble.cjs" + }, + "./ZoomLens": { + "types": "./dist/ZoomLens.d.ts", + "import": "./dist/ZoomLens.js", + "require": "./dist/ZoomLens.cjs" + }, + "./FlickDeck": { + "types": "./dist/FlickDeck.d.ts", + "import": "./dist/FlickDeck.js", + "require": "./dist/FlickDeck.cjs" } }, "files": [ diff --git a/src/DraggableSheet.tsx b/src/DraggableSheet.tsx index 7086843..1d14259 100644 --- a/src/DraggableSheet.tsx +++ b/src/DraggableSheet.tsx @@ -380,3 +380,5 @@ export function DraggableSheet({
); } + +export default DraggableSheet; diff --git a/src/FlickDeck.tsx b/src/FlickDeck.tsx index 249ba42..2ef5dbb 100644 --- a/src/FlickDeck.tsx +++ b/src/FlickDeck.tsx @@ -378,3 +378,5 @@ export function FlickDeck({
); } + +export default FlickDeck; diff --git a/src/InspectorBubble.tsx b/src/InspectorBubble.tsx index 29195b7..b270f57 100644 --- a/src/InspectorBubble.tsx +++ b/src/InspectorBubble.tsx @@ -930,3 +930,5 @@ function BubbleAnchor({
); } + +export default InspectorBubble; diff --git a/src/MovableLauncher.tsx b/src/MovableLauncher.tsx index 362fa0a..8c47c7c 100644 --- a/src/MovableLauncher.tsx +++ b/src/MovableLauncher.tsx @@ -266,3 +266,5 @@ export function MovableLauncher({ ); } + +export default MovableLauncher; diff --git a/src/ResizableSplitPane.tsx b/src/ResizableSplitPane.tsx index 1dfd5cd..15ec73c 100644 --- a/src/ResizableSplitPane.tsx +++ b/src/ResizableSplitPane.tsx @@ -392,3 +392,5 @@ export function ResizableSplitPane({ ); } + +export default ResizableSplitPane; diff --git a/src/SnapDock.tsx b/src/SnapDock.tsx index e7c7e2e..7e05b02 100644 --- a/src/SnapDock.tsx +++ b/src/SnapDock.tsx @@ -408,3 +408,5 @@ export function SnapDock({ ); } + +export default SnapDock; diff --git a/src/ZoomLens.tsx b/src/ZoomLens.tsx index e16bb35..7ea013d 100644 --- a/src/ZoomLens.tsx +++ b/src/ZoomLens.tsx @@ -680,3 +680,5 @@ export function ZoomLens({ return createPortal(overlay, document.body); } + +export default ZoomLens; diff --git a/vite.config.js b/vite.config.js index d0bb8e0..3d3acdf 100644 --- a/vite.config.js +++ b/vite.config.js @@ -8,13 +8,23 @@ export default defineConfig({ plugins: [react()], build: { lib: { - entry: resolve(__dirname, 'src/index.ts'), - name: 'ReactDriftKit', + entry: { + index: resolve(__dirname, 'src/index.ts'), + MovableLauncher: resolve(__dirname, 'src/MovableLauncher.tsx'), + SnapDock: resolve(__dirname, 'src/SnapDock.tsx'), + DraggableSheet: resolve(__dirname, 'src/DraggableSheet.tsx'), + ResizableSplitPane: resolve(__dirname, 'src/ResizableSplitPane.tsx'), + InspectorBubble: resolve(__dirname, 'src/InspectorBubble.tsx'), + ZoomLens: resolve(__dirname, 'src/ZoomLens.tsx'), + FlickDeck: resolve(__dirname, 'src/FlickDeck.tsx'), + }, formats: ['es', 'cjs'], - fileName: 'react-driftkit', }, rollupOptions: { external: ['react', 'react-dom', 'react/jsx-runtime'], + output: { + exports: 'named', + }, }, }, });