uivisor 0.1.0 → 0.1.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/README.md CHANGED
@@ -80,22 +80,47 @@ export default defineConfig({
80
80
  })
81
81
  ```
82
82
 
83
- ### Next.js
83
+ ### Next.js (App Router, Next 13–16)
84
84
 
85
+ **1. Wrap your config.** Works with `next.config.ts` / `.mjs` (ESM) or `.js` (CJS):
86
+
87
+ ```ts
88
+ // next.config.ts
89
+ import { withUivisor } from 'uivisor/next'
90
+
91
+ const nextConfig = { reactStrictMode: true }
92
+
93
+ export default withUivisor(nextConfig)
94
+ ```
85
95
  ```js
86
- // next.config.js
96
+ // next.config.js (CommonJS)
87
97
  const { withUivisor } = require('uivisor/next')
98
+ module.exports = withUivisor({ reactStrictMode: true })
99
+ ```
88
100
 
89
- /** @type {import('next').NextConfig} */
90
- const nextConfig = { reactStrictMode: true }
101
+ **2. Mount the overlay** once in your root layout (works under both bundlers):
91
102
 
92
- module.exports = withUivisor(nextConfig)
103
+ ```tsx
104
+ // app/layout.tsx
105
+ import { UivisorOverlay } from 'uivisor/next/overlay'
106
+
107
+ export default function RootLayout({ children }) {
108
+ return <html><body>{children}<UivisorOverlay /></body></html>
109
+ }
93
110
  ```
94
111
 
95
- > Use plain `next dev` (webpack). Turbopack (`--turbo`) ignores `webpack()` config, so source locations
96
- > won't be injected under it yet.
112
+ **3. Run it.** Then press **`Alt`+`U`** (or click **◎**).
113
+
114
+ | Command | Overlay | Exact `file:line` |
115
+ |---|---|---|
116
+ | `next dev --webpack` | ✅ | ✅ (recommended) |
117
+ | `next dev` (**Turbopack**, default in Next 15/16) | ✅ | ⚠️ off — falls back to component + selector + text |
97
118
 
98
- Then `npm run dev` and press **`Alt`+`U`** (or click the **◎** button bottom-right).
119
+ > **Turbopack ignores `webpack()` config**, so `data-uiv-src` source attributes aren't injected under plain
120
+ > `next dev`. uivisor detects this and prints a clear console hint. For exact `file:line`, either run
121
+ > `next dev --webpack` (add a `"dev:uivisor": "next dev --webpack"` script), or opt into the **experimental**
122
+ > Turbopack loader: `withUivisor(config, { turbopack: true })`. Everything is **dev-only** — nothing reaches
123
+ > production builds.
99
124
 
100
125
  #### Keeping it updated while we iterate
101
126
 
@@ -5,6 +5,9 @@ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
5
5
  var __getOwnPropNames = Object.getOwnPropertyNames;
6
6
  var __getProtoOf = Object.getPrototypeOf;
7
7
  var __hasOwnProp = Object.prototype.hasOwnProperty;
8
+ var __commonJS = (cb, mod) => function __require() {
9
+ return mod || (0, cb[__getOwnPropNames(cb)[0]])((mod = { exports: {} }).exports, mod), mod.exports;
10
+ };
8
11
  var __export = (target, all) => {
9
12
  for (var name in all)
10
13
  __defProp(target, name, { get: all[name], enumerable: true });
@@ -27,6 +30,349 @@ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__ge
27
30
  ));
28
31
  var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
29
32
 
33
+ // node_modules/next/package.json
34
+ var require_package = __commonJS({
35
+ "node_modules/next/package.json"(exports2, module2) {
36
+ module2.exports = {
37
+ name: "next",
38
+ version: "14.2.15",
39
+ description: "The React Framework",
40
+ main: "./dist/server/next.js",
41
+ license: "MIT",
42
+ repository: "vercel/next.js",
43
+ bugs: "https://github.com/vercel/next.js/issues",
44
+ homepage: "https://nextjs.org",
45
+ types: "index.d.ts",
46
+ files: [
47
+ "dist",
48
+ "app.js",
49
+ "app.d.ts",
50
+ "babel.js",
51
+ "babel.d.ts",
52
+ "client.js",
53
+ "client.d.ts",
54
+ "compat",
55
+ "cache.js",
56
+ "cache.d.ts",
57
+ "config.js",
58
+ "config.d.ts",
59
+ "constants.js",
60
+ "constants.d.ts",
61
+ "document.js",
62
+ "document.d.ts",
63
+ "dynamic.js",
64
+ "dynamic.d.ts",
65
+ "error.js",
66
+ "error.d.ts",
67
+ "future",
68
+ "legacy",
69
+ "script.js",
70
+ "script.d.ts",
71
+ "server.js",
72
+ "server.d.ts",
73
+ "head.js",
74
+ "head.d.ts",
75
+ "image.js",
76
+ "image.d.ts",
77
+ "link.js",
78
+ "link.d.ts",
79
+ "router.js",
80
+ "router.d.ts",
81
+ "jest.js",
82
+ "jest.d.ts",
83
+ "amp.js",
84
+ "amp.d.ts",
85
+ "og.js",
86
+ "og.d.ts",
87
+ "index.d.ts",
88
+ "types/index.d.ts",
89
+ "types/global.d.ts",
90
+ "types/compiled.d.ts",
91
+ "image-types/global.d.ts",
92
+ "navigation-types/navigation.d.ts",
93
+ "navigation-types/compat/navigation.d.ts",
94
+ "font",
95
+ "navigation.js",
96
+ "navigation.d.ts",
97
+ "headers.js",
98
+ "headers.d.ts",
99
+ "navigation-types",
100
+ "web-vitals.js",
101
+ "web-vitals.d.ts",
102
+ "experimental/testmode/playwright.js",
103
+ "experimental/testmode/playwright.d.ts",
104
+ "experimental/testmode/playwright/msw.js",
105
+ "experimental/testmode/playwright/msw.d.ts",
106
+ "experimental/testmode/proxy.js",
107
+ "experimental/testmode/proxy.d.ts"
108
+ ],
109
+ bin: {
110
+ next: "./dist/bin/next"
111
+ },
112
+ scripts: {
113
+ dev: "taskr",
114
+ release: "taskr release",
115
+ build: "pnpm release",
116
+ prepublishOnly: "cd ../../ && turbo run build",
117
+ types: "tsc --declaration --emitDeclarationOnly --stripInternal --declarationDir dist",
118
+ typescript: "tsec --noEmit",
119
+ "ncc-compiled": "ncc cache clean && taskr ncc"
120
+ },
121
+ taskr: {
122
+ requires: [
123
+ "./taskfile-webpack.js",
124
+ "./taskfile-ncc.js",
125
+ "./taskfile-swc.js",
126
+ "./taskfile-watch.js"
127
+ ]
128
+ },
129
+ dependencies: {
130
+ "@next/env": "14.2.15",
131
+ "@swc/helpers": "0.5.5",
132
+ busboy: "1.6.0",
133
+ "caniuse-lite": "^1.0.30001579",
134
+ "graceful-fs": "^4.2.11",
135
+ postcss: "8.4.31",
136
+ "styled-jsx": "5.1.1"
137
+ },
138
+ peerDependencies: {
139
+ "@opentelemetry/api": "^1.1.0",
140
+ "@playwright/test": "^1.41.2",
141
+ react: "^18.2.0",
142
+ "react-dom": "^18.2.0",
143
+ sass: "^1.3.0"
144
+ },
145
+ peerDependenciesMeta: {
146
+ sass: {
147
+ optional: true
148
+ },
149
+ "@opentelemetry/api": {
150
+ optional: true
151
+ },
152
+ "@playwright/test": {
153
+ optional: true
154
+ }
155
+ },
156
+ devDependencies: {
157
+ "@ampproject/toolbox-optimizer": "2.8.3",
158
+ "@babel/code-frame": "7.22.5",
159
+ "@babel/core": "7.22.5",
160
+ "@babel/eslint-parser": "7.22.5",
161
+ "@babel/generator": "7.22.5",
162
+ "@babel/plugin-proposal-class-properties": "7.18.6",
163
+ "@babel/plugin-proposal-export-namespace-from": "7.18.9",
164
+ "@babel/plugin-proposal-numeric-separator": "7.18.6",
165
+ "@babel/plugin-proposal-object-rest-spread": "7.20.7",
166
+ "@babel/plugin-syntax-bigint": "7.8.3",
167
+ "@babel/plugin-syntax-dynamic-import": "7.8.3",
168
+ "@babel/plugin-syntax-import-assertions": "7.22.5",
169
+ "@babel/plugin-syntax-jsx": "7.22.5",
170
+ "@babel/plugin-transform-modules-commonjs": "7.22.5",
171
+ "@babel/plugin-transform-runtime": "7.22.5",
172
+ "@babel/preset-env": "7.22.5",
173
+ "@babel/preset-react": "7.22.5",
174
+ "@babel/preset-typescript": "7.22.5",
175
+ "@babel/runtime": "7.22.5",
176
+ "@babel/traverse": "7.22.5",
177
+ "@babel/types": "7.22.5",
178
+ "@capsizecss/metrics": "2.2.0",
179
+ "@edge-runtime/cookies": "5.0.0",
180
+ "@edge-runtime/ponyfill": "3.0.0",
181
+ "@edge-runtime/primitives": "5.0.0",
182
+ "@hapi/accept": "5.0.2",
183
+ "@jest/transform": "29.5.0",
184
+ "@jest/types": "29.5.0",
185
+ "@mswjs/interceptors": "0.23.0",
186
+ "@napi-rs/triples": "1.2.0",
187
+ "@next/polyfill-module": "14.2.15",
188
+ "@next/polyfill-nomodule": "14.2.15",
189
+ "@next/react-refresh-utils": "14.2.15",
190
+ "@next/swc": "14.2.15",
191
+ "@opentelemetry/api": "1.6.0",
192
+ "@playwright/test": "1.41.2",
193
+ "@taskr/clear": "1.1.0",
194
+ "@taskr/esnext": "1.1.0",
195
+ "@types/amphtml-validator": "1.0.0",
196
+ "@types/babel__code-frame": "7.0.2",
197
+ "@types/babel__core": "7.1.12",
198
+ "@types/babel__generator": "7.6.2",
199
+ "@types/babel__template": "7.4.0",
200
+ "@types/babel__traverse": "7.11.0",
201
+ "@types/bytes": "3.1.1",
202
+ "@types/ci-info": "2.0.0",
203
+ "@types/compression": "0.0.36",
204
+ "@types/content-disposition": "0.5.4",
205
+ "@types/content-type": "1.1.3",
206
+ "@types/cookie": "0.3.3",
207
+ "@types/cross-spawn": "6.0.0",
208
+ "@types/debug": "4.1.5",
209
+ "@types/express-serve-static-core": "4.17.33",
210
+ "@types/fresh": "0.5.0",
211
+ "@types/glob": "7.1.1",
212
+ "@types/graceful-fs": "4.1.9",
213
+ "@types/jsonwebtoken": "9.0.0",
214
+ "@types/lodash": "4.14.198",
215
+ "@types/lodash.curry": "4.1.6",
216
+ "@types/lru-cache": "5.1.0",
217
+ "@types/path-to-regexp": "1.7.0",
218
+ "@types/picomatch": "2.3.3",
219
+ "@types/platform": "1.3.4",
220
+ "@types/react": "18.2.37",
221
+ "@types/react-dom": "18.2.15",
222
+ "@types/react-is": "17.0.3",
223
+ "@types/semver": "7.3.1",
224
+ "@types/send": "0.14.4",
225
+ "@types/shell-quote": "1.7.1",
226
+ "@types/tar": "6.1.5",
227
+ "@types/text-table": "0.2.1",
228
+ "@types/ua-parser-js": "0.7.36",
229
+ "@types/uuid": "8.3.1",
230
+ "@types/webpack-sources1": "npm:@types/webpack-sources@0.1.5",
231
+ "@types/ws": "8.2.0",
232
+ "@vercel/ncc": "0.34.0",
233
+ "@vercel/nft": "0.26.4",
234
+ "@vercel/turbopack-ecmascript-runtime": "https://gitpkg-fork.vercel.sh/vercel/turbo/crates/turbopack-ecmascript-runtime/js?turbopack-240417.2",
235
+ acorn: "8.11.3",
236
+ "amphtml-validator": "1.0.35",
237
+ anser: "1.4.9",
238
+ arg: "4.1.0",
239
+ assert: "2.0.0",
240
+ "async-retry": "1.2.3",
241
+ "async-sema": "3.0.0",
242
+ "babel-plugin-transform-define": "2.0.0",
243
+ "babel-plugin-transform-react-remove-prop-types": "0.4.24",
244
+ "browserify-zlib": "0.2.0",
245
+ browserslist: "4.22.2",
246
+ buffer: "5.6.0",
247
+ bytes: "3.1.1",
248
+ "ci-info": "watson/ci-info#f43f6a1cefff47fb361c88cf4b943fdbcaafe540",
249
+ "cli-select": "1.1.2",
250
+ "client-only": "0.0.1",
251
+ commander: "12.0.0",
252
+ "comment-json": "3.0.3",
253
+ compression: "1.7.4",
254
+ conf: "5.0.0",
255
+ "constants-browserify": "1.0.0",
256
+ "content-disposition": "0.5.3",
257
+ "content-type": "1.0.4",
258
+ cookie: "0.4.1",
259
+ "cross-spawn": "7.0.3",
260
+ "crypto-browserify": "3.12.0",
261
+ "css.escape": "1.5.1",
262
+ "cssnano-preset-default": "5.2.14",
263
+ "data-uri-to-buffer": "3.0.1",
264
+ debug: "4.1.1",
265
+ devalue: "2.0.1",
266
+ "domain-browser": "4.19.0",
267
+ "edge-runtime": "3.0.0",
268
+ events: "3.3.0",
269
+ "find-up": "4.1.0",
270
+ fresh: "0.5.2",
271
+ "get-orientation": "1.1.2",
272
+ glob: "7.1.7",
273
+ "gzip-size": "5.1.1",
274
+ "http-proxy": "1.18.1",
275
+ "http-proxy-agent": "5.0.0",
276
+ "https-browserify": "1.0.0",
277
+ "https-proxy-agent": "5.0.1",
278
+ "icss-utils": "5.1.0",
279
+ "ignore-loader": "0.1.2",
280
+ "image-size": "1.0.0",
281
+ "is-docker": "2.0.0",
282
+ "is-wsl": "2.2.0",
283
+ "jest-worker": "27.5.1",
284
+ json5: "2.2.3",
285
+ jsonwebtoken: "9.0.0",
286
+ "loader-runner": "4.3.0",
287
+ "loader-utils2": "npm:loader-utils@2.0.0",
288
+ "loader-utils3": "npm:loader-utils@3.1.3",
289
+ "lodash.curry": "4.1.1",
290
+ "lru-cache": "5.1.1",
291
+ "mini-css-extract-plugin": "2.4.4",
292
+ msw: "1.3.0",
293
+ nanoid: "3.1.32",
294
+ "native-url": "0.3.4",
295
+ "neo-async": "2.6.1",
296
+ "node-html-parser": "5.3.3",
297
+ ora: "4.0.4",
298
+ "os-browserify": "0.3.0",
299
+ "p-limit": "3.1.0",
300
+ "path-browserify": "1.0.1",
301
+ "path-to-regexp": "6.1.0",
302
+ picomatch: "4.0.1",
303
+ platform: "1.3.6",
304
+ "postcss-flexbugs-fixes": "5.0.2",
305
+ "postcss-modules-extract-imports": "3.0.0",
306
+ "postcss-modules-local-by-default": "4.0.4",
307
+ "postcss-modules-scope": "3.0.0",
308
+ "postcss-modules-values": "4.0.0",
309
+ "postcss-preset-env": "7.4.3",
310
+ "postcss-safe-parser": "6.0.0",
311
+ "postcss-scss": "4.0.3",
312
+ "postcss-value-parser": "4.2.0",
313
+ process: "0.11.10",
314
+ punycode: "2.1.1",
315
+ "querystring-es3": "0.2.1",
316
+ "raw-body": "2.4.1",
317
+ "react-is": "18.2.0",
318
+ "react-refresh": "0.12.0",
319
+ "regenerator-runtime": "0.13.4",
320
+ "sass-loader": "12.4.0",
321
+ "schema-utils2": "npm:schema-utils@2.7.1",
322
+ "schema-utils3": "npm:schema-utils@3.0.0",
323
+ semver: "7.3.2",
324
+ send: "0.17.1",
325
+ "server-only": "0.0.1",
326
+ setimmediate: "1.0.5",
327
+ "shell-quote": "1.7.3",
328
+ "source-map": "0.6.1",
329
+ "source-map08": "npm:source-map@0.8.0-beta.0",
330
+ "stacktrace-parser": "0.1.10",
331
+ "stream-browserify": "3.0.0",
332
+ "stream-http": "3.1.1",
333
+ "strict-event-emitter": "0.5.0",
334
+ "string-hash": "1.1.3",
335
+ string_decoder: "1.3.0",
336
+ "strip-ansi": "6.0.0",
337
+ superstruct: "1.0.3",
338
+ tar: "6.1.15",
339
+ taskr: "1.1.0",
340
+ terser: "5.27.0",
341
+ "terser-webpack-plugin": "5.3.9",
342
+ "text-table": "0.2.0",
343
+ "timers-browserify": "2.0.12",
344
+ "tty-browserify": "0.0.1",
345
+ "ua-parser-js": "1.0.35",
346
+ unistore: "3.4.1",
347
+ util: "0.12.4",
348
+ uuid: "8.3.2",
349
+ "vm-browserify": "1.1.2",
350
+ watchpack: "2.4.0",
351
+ "web-vitals": "3.0.0",
352
+ webpack: "5.90.0",
353
+ "webpack-sources1": "npm:webpack-sources@1.4.3",
354
+ "webpack-sources3": "npm:webpack-sources@3.2.3",
355
+ ws: "8.2.3",
356
+ zod: "3.22.3"
357
+ },
358
+ engines: {
359
+ node: ">=18.17.0"
360
+ },
361
+ optionalDependencies: {
362
+ "@next/swc-darwin-arm64": "14.2.15",
363
+ "@next/swc-darwin-x64": "14.2.15",
364
+ "@next/swc-linux-arm64-gnu": "14.2.15",
365
+ "@next/swc-linux-arm64-musl": "14.2.15",
366
+ "@next/swc-linux-x64-gnu": "14.2.15",
367
+ "@next/swc-linux-x64-musl": "14.2.15",
368
+ "@next/swc-win32-arm64-msvc": "14.2.15",
369
+ "@next/swc-win32-ia32-msvc": "14.2.15",
370
+ "@next/swc-win32-x64-msvc": "14.2.15"
371
+ }
372
+ };
373
+ }
374
+ });
375
+
30
376
  // src/next/index.ts
31
377
  var next_exports = {};
32
378
  __export(next_exports, {
@@ -35,13 +381,32 @@ __export(next_exports, {
35
381
  });
36
382
  module.exports = __toCommonJS(next_exports);
37
383
  var path = __toESM(require("path"), 1);
384
+ var isProd = () => process.env.NODE_ENV === "production";
385
+ var isTurbopack = () => !!process.env.TURBOPACK || !!process.env.TURBOPACK_DEV;
386
+ function nextMajor() {
387
+ try {
388
+ return parseInt(require_package().version, 10) || 0;
389
+ } catch {
390
+ return 0;
391
+ }
392
+ }
393
+ var hintShown = false;
394
+ function turbopackHint(canSourceMap) {
395
+ if (hintShown || !isTurbopack() || isProd()) return;
396
+ hintShown = true;
397
+ console.log(
398
+ '\n[uivisor] Turbopack detected.\n \u2022 Overlay: render <UivisorOverlay/> from "uivisor/next/overlay" in your root layout.\n' + (canSourceMap ? " \u2022 Source locations: ON via turbopack.rules.\n" : " \u2022 Exact file:line: use `next dev --webpack` (or remove `{ turbopack: false }`).\n")
399
+ );
400
+ }
38
401
  function withUivisor(nextConfig = {}, options = {}) {
39
402
  const attr = options.attr || "data-uiv-src";
40
403
  const loaderPath = path.join(__dirname, "loader.cjs");
41
404
  const overlayPath = path.join(__dirname, "..", "overlay", "index.js");
42
- return {
43
- ...nextConfig,
44
- webpack(config, ctx) {
405
+ const useTurbopack = options.turbopack !== false && isTurbopack() && !isProd();
406
+ turbopackHint(useTurbopack);
407
+ const out = { ...nextConfig };
408
+ if (!isTurbopack()) {
409
+ out.webpack = (config, ctx) => {
45
410
  if (typeof nextConfig.webpack === "function") {
46
411
  config = nextConfig.webpack(config, ctx);
47
412
  }
@@ -71,8 +436,29 @@ function withUivisor(nextConfig = {}, options = {}) {
71
436
  };
72
437
  }
73
438
  return config;
439
+ };
440
+ }
441
+ if (useTurbopack) {
442
+ const ld = [{ loader: "uivisor/next/loader", options: { attr } }];
443
+ const rules = {
444
+ "*.tsx": { loaders: ld, as: "*.tsx" },
445
+ "*.jsx": { loaders: ld, as: "*.jsx" }
446
+ };
447
+ const major = nextMajor();
448
+ if (major === 0 || major >= 15) {
449
+ out.turbopack = {
450
+ ...nextConfig.turbopack,
451
+ rules: { ...nextConfig.turbopack?.rules ?? {}, ...rules }
452
+ };
453
+ } else {
454
+ const exp = nextConfig.experimental ?? {};
455
+ out.experimental = {
456
+ ...exp,
457
+ turbo: { ...exp.turbo ?? {}, rules: { ...exp.turbo?.rules ?? {}, ...rules } }
458
+ };
74
459
  }
75
- };
460
+ }
461
+ return out;
76
462
  }
77
463
  var next_default = withUivisor;
78
464
  // Annotate the CommonJS export names for ESM import in node:
@@ -0,0 +1,41 @@
1
+ interface WebpackContext {
2
+ dev: boolean;
3
+ isServer: boolean;
4
+ }
5
+ type NextConfig = {
6
+ webpack?: (config: any, ctx: WebpackContext) => any;
7
+ turbopack?: any;
8
+ [key: string]: unknown;
9
+ };
10
+ interface UivisorNextOptions {
11
+ /** data attribute name for source locations. Default: "data-uiv-src" */
12
+ attr?: string;
13
+ /**
14
+ * Register the source-location loader for Turbopack (`turbopack.rules`) so
15
+ * `data-uiv-src` is injected under plain `next dev` too. Default: true.
16
+ * Set false to disable if it ever conflicts with your setup (the overlay still
17
+ * works via <UivisorOverlay/>; use `next dev --webpack` for source attrs then).
18
+ */
19
+ turbopack?: boolean;
20
+ }
21
+ /**
22
+ * Wrap your Next.js config to enable uivisor in dev.
23
+ *
24
+ * // next.config.ts / .mjs
25
+ * import { withUivisor } from 'uivisor/next'
26
+ * export default withUivisor({ ...yourConfig })
27
+ *
28
+ * // next.config.js (CommonJS)
29
+ * const { withUivisor } = require('uivisor/next')
30
+ * module.exports = withUivisor({ ...yourConfig })
31
+ *
32
+ * Then render <UivisorOverlay/> (from "uivisor/next/overlay") in your root layout.
33
+ *
34
+ * - webpack (`next dev --webpack`): injects `data-uiv-src` + the overlay automatically.
35
+ * - Turbopack (`next dev`): the overlay works via <UivisorOverlay/>; source locations
36
+ * need either `--webpack` or `{ turbopack: true }` (experimental).
37
+ * Dev-only — nothing is added to production builds.
38
+ */
39
+ declare function withUivisor(nextConfig?: NextConfig, options?: UivisorNextOptions): NextConfig;
40
+
41
+ export { type UivisorNextOptions, withUivisor as default, withUivisor };
@@ -0,0 +1,41 @@
1
+ interface WebpackContext {
2
+ dev: boolean;
3
+ isServer: boolean;
4
+ }
5
+ type NextConfig = {
6
+ webpack?: (config: any, ctx: WebpackContext) => any;
7
+ turbopack?: any;
8
+ [key: string]: unknown;
9
+ };
10
+ interface UivisorNextOptions {
11
+ /** data attribute name for source locations. Default: "data-uiv-src" */
12
+ attr?: string;
13
+ /**
14
+ * Register the source-location loader for Turbopack (`turbopack.rules`) so
15
+ * `data-uiv-src` is injected under plain `next dev` too. Default: true.
16
+ * Set false to disable if it ever conflicts with your setup (the overlay still
17
+ * works via <UivisorOverlay/>; use `next dev --webpack` for source attrs then).
18
+ */
19
+ turbopack?: boolean;
20
+ }
21
+ /**
22
+ * Wrap your Next.js config to enable uivisor in dev.
23
+ *
24
+ * // next.config.ts / .mjs
25
+ * import { withUivisor } from 'uivisor/next'
26
+ * export default withUivisor({ ...yourConfig })
27
+ *
28
+ * // next.config.js (CommonJS)
29
+ * const { withUivisor } = require('uivisor/next')
30
+ * module.exports = withUivisor({ ...yourConfig })
31
+ *
32
+ * Then render <UivisorOverlay/> (from "uivisor/next/overlay") in your root layout.
33
+ *
34
+ * - webpack (`next dev --webpack`): injects `data-uiv-src` + the overlay automatically.
35
+ * - Turbopack (`next dev`): the overlay works via <UivisorOverlay/>; source locations
36
+ * need either `--webpack` or `{ turbopack: true }` (experimental).
37
+ * Dev-only — nothing is added to production builds.
38
+ */
39
+ declare function withUivisor(nextConfig?: NextConfig, options?: UivisorNextOptions): NextConfig;
40
+
41
+ export { type UivisorNextOptions, withUivisor as default, withUivisor };
@@ -0,0 +1,441 @@
1
+ var __getOwnPropNames = Object.getOwnPropertyNames;
2
+ var __commonJS = (cb, mod) => function __require() {
3
+ return mod || (0, cb[__getOwnPropNames(cb)[0]])((mod = { exports: {} }).exports, mod), mod.exports;
4
+ };
5
+
6
+ // node_modules/next/package.json
7
+ var require_package = __commonJS({
8
+ "node_modules/next/package.json"(exports, module) {
9
+ module.exports = {
10
+ name: "next",
11
+ version: "14.2.15",
12
+ description: "The React Framework",
13
+ main: "./dist/server/next.js",
14
+ license: "MIT",
15
+ repository: "vercel/next.js",
16
+ bugs: "https://github.com/vercel/next.js/issues",
17
+ homepage: "https://nextjs.org",
18
+ types: "index.d.ts",
19
+ files: [
20
+ "dist",
21
+ "app.js",
22
+ "app.d.ts",
23
+ "babel.js",
24
+ "babel.d.ts",
25
+ "client.js",
26
+ "client.d.ts",
27
+ "compat",
28
+ "cache.js",
29
+ "cache.d.ts",
30
+ "config.js",
31
+ "config.d.ts",
32
+ "constants.js",
33
+ "constants.d.ts",
34
+ "document.js",
35
+ "document.d.ts",
36
+ "dynamic.js",
37
+ "dynamic.d.ts",
38
+ "error.js",
39
+ "error.d.ts",
40
+ "future",
41
+ "legacy",
42
+ "script.js",
43
+ "script.d.ts",
44
+ "server.js",
45
+ "server.d.ts",
46
+ "head.js",
47
+ "head.d.ts",
48
+ "image.js",
49
+ "image.d.ts",
50
+ "link.js",
51
+ "link.d.ts",
52
+ "router.js",
53
+ "router.d.ts",
54
+ "jest.js",
55
+ "jest.d.ts",
56
+ "amp.js",
57
+ "amp.d.ts",
58
+ "og.js",
59
+ "og.d.ts",
60
+ "index.d.ts",
61
+ "types/index.d.ts",
62
+ "types/global.d.ts",
63
+ "types/compiled.d.ts",
64
+ "image-types/global.d.ts",
65
+ "navigation-types/navigation.d.ts",
66
+ "navigation-types/compat/navigation.d.ts",
67
+ "font",
68
+ "navigation.js",
69
+ "navigation.d.ts",
70
+ "headers.js",
71
+ "headers.d.ts",
72
+ "navigation-types",
73
+ "web-vitals.js",
74
+ "web-vitals.d.ts",
75
+ "experimental/testmode/playwright.js",
76
+ "experimental/testmode/playwright.d.ts",
77
+ "experimental/testmode/playwright/msw.js",
78
+ "experimental/testmode/playwright/msw.d.ts",
79
+ "experimental/testmode/proxy.js",
80
+ "experimental/testmode/proxy.d.ts"
81
+ ],
82
+ bin: {
83
+ next: "./dist/bin/next"
84
+ },
85
+ scripts: {
86
+ dev: "taskr",
87
+ release: "taskr release",
88
+ build: "pnpm release",
89
+ prepublishOnly: "cd ../../ && turbo run build",
90
+ types: "tsc --declaration --emitDeclarationOnly --stripInternal --declarationDir dist",
91
+ typescript: "tsec --noEmit",
92
+ "ncc-compiled": "ncc cache clean && taskr ncc"
93
+ },
94
+ taskr: {
95
+ requires: [
96
+ "./taskfile-webpack.js",
97
+ "./taskfile-ncc.js",
98
+ "./taskfile-swc.js",
99
+ "./taskfile-watch.js"
100
+ ]
101
+ },
102
+ dependencies: {
103
+ "@next/env": "14.2.15",
104
+ "@swc/helpers": "0.5.5",
105
+ busboy: "1.6.0",
106
+ "caniuse-lite": "^1.0.30001579",
107
+ "graceful-fs": "^4.2.11",
108
+ postcss: "8.4.31",
109
+ "styled-jsx": "5.1.1"
110
+ },
111
+ peerDependencies: {
112
+ "@opentelemetry/api": "^1.1.0",
113
+ "@playwright/test": "^1.41.2",
114
+ react: "^18.2.0",
115
+ "react-dom": "^18.2.0",
116
+ sass: "^1.3.0"
117
+ },
118
+ peerDependenciesMeta: {
119
+ sass: {
120
+ optional: true
121
+ },
122
+ "@opentelemetry/api": {
123
+ optional: true
124
+ },
125
+ "@playwright/test": {
126
+ optional: true
127
+ }
128
+ },
129
+ devDependencies: {
130
+ "@ampproject/toolbox-optimizer": "2.8.3",
131
+ "@babel/code-frame": "7.22.5",
132
+ "@babel/core": "7.22.5",
133
+ "@babel/eslint-parser": "7.22.5",
134
+ "@babel/generator": "7.22.5",
135
+ "@babel/plugin-proposal-class-properties": "7.18.6",
136
+ "@babel/plugin-proposal-export-namespace-from": "7.18.9",
137
+ "@babel/plugin-proposal-numeric-separator": "7.18.6",
138
+ "@babel/plugin-proposal-object-rest-spread": "7.20.7",
139
+ "@babel/plugin-syntax-bigint": "7.8.3",
140
+ "@babel/plugin-syntax-dynamic-import": "7.8.3",
141
+ "@babel/plugin-syntax-import-assertions": "7.22.5",
142
+ "@babel/plugin-syntax-jsx": "7.22.5",
143
+ "@babel/plugin-transform-modules-commonjs": "7.22.5",
144
+ "@babel/plugin-transform-runtime": "7.22.5",
145
+ "@babel/preset-env": "7.22.5",
146
+ "@babel/preset-react": "7.22.5",
147
+ "@babel/preset-typescript": "7.22.5",
148
+ "@babel/runtime": "7.22.5",
149
+ "@babel/traverse": "7.22.5",
150
+ "@babel/types": "7.22.5",
151
+ "@capsizecss/metrics": "2.2.0",
152
+ "@edge-runtime/cookies": "5.0.0",
153
+ "@edge-runtime/ponyfill": "3.0.0",
154
+ "@edge-runtime/primitives": "5.0.0",
155
+ "@hapi/accept": "5.0.2",
156
+ "@jest/transform": "29.5.0",
157
+ "@jest/types": "29.5.0",
158
+ "@mswjs/interceptors": "0.23.0",
159
+ "@napi-rs/triples": "1.2.0",
160
+ "@next/polyfill-module": "14.2.15",
161
+ "@next/polyfill-nomodule": "14.2.15",
162
+ "@next/react-refresh-utils": "14.2.15",
163
+ "@next/swc": "14.2.15",
164
+ "@opentelemetry/api": "1.6.0",
165
+ "@playwright/test": "1.41.2",
166
+ "@taskr/clear": "1.1.0",
167
+ "@taskr/esnext": "1.1.0",
168
+ "@types/amphtml-validator": "1.0.0",
169
+ "@types/babel__code-frame": "7.0.2",
170
+ "@types/babel__core": "7.1.12",
171
+ "@types/babel__generator": "7.6.2",
172
+ "@types/babel__template": "7.4.0",
173
+ "@types/babel__traverse": "7.11.0",
174
+ "@types/bytes": "3.1.1",
175
+ "@types/ci-info": "2.0.0",
176
+ "@types/compression": "0.0.36",
177
+ "@types/content-disposition": "0.5.4",
178
+ "@types/content-type": "1.1.3",
179
+ "@types/cookie": "0.3.3",
180
+ "@types/cross-spawn": "6.0.0",
181
+ "@types/debug": "4.1.5",
182
+ "@types/express-serve-static-core": "4.17.33",
183
+ "@types/fresh": "0.5.0",
184
+ "@types/glob": "7.1.1",
185
+ "@types/graceful-fs": "4.1.9",
186
+ "@types/jsonwebtoken": "9.0.0",
187
+ "@types/lodash": "4.14.198",
188
+ "@types/lodash.curry": "4.1.6",
189
+ "@types/lru-cache": "5.1.0",
190
+ "@types/path-to-regexp": "1.7.0",
191
+ "@types/picomatch": "2.3.3",
192
+ "@types/platform": "1.3.4",
193
+ "@types/react": "18.2.37",
194
+ "@types/react-dom": "18.2.15",
195
+ "@types/react-is": "17.0.3",
196
+ "@types/semver": "7.3.1",
197
+ "@types/send": "0.14.4",
198
+ "@types/shell-quote": "1.7.1",
199
+ "@types/tar": "6.1.5",
200
+ "@types/text-table": "0.2.1",
201
+ "@types/ua-parser-js": "0.7.36",
202
+ "@types/uuid": "8.3.1",
203
+ "@types/webpack-sources1": "npm:@types/webpack-sources@0.1.5",
204
+ "@types/ws": "8.2.0",
205
+ "@vercel/ncc": "0.34.0",
206
+ "@vercel/nft": "0.26.4",
207
+ "@vercel/turbopack-ecmascript-runtime": "https://gitpkg-fork.vercel.sh/vercel/turbo/crates/turbopack-ecmascript-runtime/js?turbopack-240417.2",
208
+ acorn: "8.11.3",
209
+ "amphtml-validator": "1.0.35",
210
+ anser: "1.4.9",
211
+ arg: "4.1.0",
212
+ assert: "2.0.0",
213
+ "async-retry": "1.2.3",
214
+ "async-sema": "3.0.0",
215
+ "babel-plugin-transform-define": "2.0.0",
216
+ "babel-plugin-transform-react-remove-prop-types": "0.4.24",
217
+ "browserify-zlib": "0.2.0",
218
+ browserslist: "4.22.2",
219
+ buffer: "5.6.0",
220
+ bytes: "3.1.1",
221
+ "ci-info": "watson/ci-info#f43f6a1cefff47fb361c88cf4b943fdbcaafe540",
222
+ "cli-select": "1.1.2",
223
+ "client-only": "0.0.1",
224
+ commander: "12.0.0",
225
+ "comment-json": "3.0.3",
226
+ compression: "1.7.4",
227
+ conf: "5.0.0",
228
+ "constants-browserify": "1.0.0",
229
+ "content-disposition": "0.5.3",
230
+ "content-type": "1.0.4",
231
+ cookie: "0.4.1",
232
+ "cross-spawn": "7.0.3",
233
+ "crypto-browserify": "3.12.0",
234
+ "css.escape": "1.5.1",
235
+ "cssnano-preset-default": "5.2.14",
236
+ "data-uri-to-buffer": "3.0.1",
237
+ debug: "4.1.1",
238
+ devalue: "2.0.1",
239
+ "domain-browser": "4.19.0",
240
+ "edge-runtime": "3.0.0",
241
+ events: "3.3.0",
242
+ "find-up": "4.1.0",
243
+ fresh: "0.5.2",
244
+ "get-orientation": "1.1.2",
245
+ glob: "7.1.7",
246
+ "gzip-size": "5.1.1",
247
+ "http-proxy": "1.18.1",
248
+ "http-proxy-agent": "5.0.0",
249
+ "https-browserify": "1.0.0",
250
+ "https-proxy-agent": "5.0.1",
251
+ "icss-utils": "5.1.0",
252
+ "ignore-loader": "0.1.2",
253
+ "image-size": "1.0.0",
254
+ "is-docker": "2.0.0",
255
+ "is-wsl": "2.2.0",
256
+ "jest-worker": "27.5.1",
257
+ json5: "2.2.3",
258
+ jsonwebtoken: "9.0.0",
259
+ "loader-runner": "4.3.0",
260
+ "loader-utils2": "npm:loader-utils@2.0.0",
261
+ "loader-utils3": "npm:loader-utils@3.1.3",
262
+ "lodash.curry": "4.1.1",
263
+ "lru-cache": "5.1.1",
264
+ "mini-css-extract-plugin": "2.4.4",
265
+ msw: "1.3.0",
266
+ nanoid: "3.1.32",
267
+ "native-url": "0.3.4",
268
+ "neo-async": "2.6.1",
269
+ "node-html-parser": "5.3.3",
270
+ ora: "4.0.4",
271
+ "os-browserify": "0.3.0",
272
+ "p-limit": "3.1.0",
273
+ "path-browserify": "1.0.1",
274
+ "path-to-regexp": "6.1.0",
275
+ picomatch: "4.0.1",
276
+ platform: "1.3.6",
277
+ "postcss-flexbugs-fixes": "5.0.2",
278
+ "postcss-modules-extract-imports": "3.0.0",
279
+ "postcss-modules-local-by-default": "4.0.4",
280
+ "postcss-modules-scope": "3.0.0",
281
+ "postcss-modules-values": "4.0.0",
282
+ "postcss-preset-env": "7.4.3",
283
+ "postcss-safe-parser": "6.0.0",
284
+ "postcss-scss": "4.0.3",
285
+ "postcss-value-parser": "4.2.0",
286
+ process: "0.11.10",
287
+ punycode: "2.1.1",
288
+ "querystring-es3": "0.2.1",
289
+ "raw-body": "2.4.1",
290
+ "react-is": "18.2.0",
291
+ "react-refresh": "0.12.0",
292
+ "regenerator-runtime": "0.13.4",
293
+ "sass-loader": "12.4.0",
294
+ "schema-utils2": "npm:schema-utils@2.7.1",
295
+ "schema-utils3": "npm:schema-utils@3.0.0",
296
+ semver: "7.3.2",
297
+ send: "0.17.1",
298
+ "server-only": "0.0.1",
299
+ setimmediate: "1.0.5",
300
+ "shell-quote": "1.7.3",
301
+ "source-map": "0.6.1",
302
+ "source-map08": "npm:source-map@0.8.0-beta.0",
303
+ "stacktrace-parser": "0.1.10",
304
+ "stream-browserify": "3.0.0",
305
+ "stream-http": "3.1.1",
306
+ "strict-event-emitter": "0.5.0",
307
+ "string-hash": "1.1.3",
308
+ string_decoder: "1.3.0",
309
+ "strip-ansi": "6.0.0",
310
+ superstruct: "1.0.3",
311
+ tar: "6.1.15",
312
+ taskr: "1.1.0",
313
+ terser: "5.27.0",
314
+ "terser-webpack-plugin": "5.3.9",
315
+ "text-table": "0.2.0",
316
+ "timers-browserify": "2.0.12",
317
+ "tty-browserify": "0.0.1",
318
+ "ua-parser-js": "1.0.35",
319
+ unistore: "3.4.1",
320
+ util: "0.12.4",
321
+ uuid: "8.3.2",
322
+ "vm-browserify": "1.1.2",
323
+ watchpack: "2.4.0",
324
+ "web-vitals": "3.0.0",
325
+ webpack: "5.90.0",
326
+ "webpack-sources1": "npm:webpack-sources@1.4.3",
327
+ "webpack-sources3": "npm:webpack-sources@3.2.3",
328
+ ws: "8.2.3",
329
+ zod: "3.22.3"
330
+ },
331
+ engines: {
332
+ node: ">=18.17.0"
333
+ },
334
+ optionalDependencies: {
335
+ "@next/swc-darwin-arm64": "14.2.15",
336
+ "@next/swc-darwin-x64": "14.2.15",
337
+ "@next/swc-linux-arm64-gnu": "14.2.15",
338
+ "@next/swc-linux-arm64-musl": "14.2.15",
339
+ "@next/swc-linux-x64-gnu": "14.2.15",
340
+ "@next/swc-linux-x64-musl": "14.2.15",
341
+ "@next/swc-win32-arm64-msvc": "14.2.15",
342
+ "@next/swc-win32-ia32-msvc": "14.2.15",
343
+ "@next/swc-win32-x64-msvc": "14.2.15"
344
+ }
345
+ };
346
+ }
347
+ });
348
+
349
+ // node_modules/tsup/assets/esm_shims.js
350
+ import path from "path";
351
+ import { fileURLToPath } from "url";
352
+ var getFilename = () => fileURLToPath(import.meta.url);
353
+ var getDirname = () => path.dirname(getFilename());
354
+ var __dirname = /* @__PURE__ */ getDirname();
355
+
356
+ // src/next/index.ts
357
+ import * as path2 from "path";
358
+ var isProd = () => process.env.NODE_ENV === "production";
359
+ var isTurbopack = () => !!process.env.TURBOPACK || !!process.env.TURBOPACK_DEV;
360
+ function nextMajor() {
361
+ try {
362
+ return parseInt(require_package().version, 10) || 0;
363
+ } catch {
364
+ return 0;
365
+ }
366
+ }
367
+ var hintShown = false;
368
+ function turbopackHint(canSourceMap) {
369
+ if (hintShown || !isTurbopack() || isProd()) return;
370
+ hintShown = true;
371
+ console.log(
372
+ '\n[uivisor] Turbopack detected.\n \u2022 Overlay: render <UivisorOverlay/> from "uivisor/next/overlay" in your root layout.\n' + (canSourceMap ? " \u2022 Source locations: ON via turbopack.rules.\n" : " \u2022 Exact file:line: use `next dev --webpack` (or remove `{ turbopack: false }`).\n")
373
+ );
374
+ }
375
+ function withUivisor(nextConfig = {}, options = {}) {
376
+ const attr = options.attr || "data-uiv-src";
377
+ const loaderPath = path2.join(__dirname, "loader.cjs");
378
+ const overlayPath = path2.join(__dirname, "..", "overlay", "index.js");
379
+ const useTurbopack = options.turbopack !== false && isTurbopack() && !isProd();
380
+ turbopackHint(useTurbopack);
381
+ const out = { ...nextConfig };
382
+ if (!isTurbopack()) {
383
+ out.webpack = (config, ctx) => {
384
+ if (typeof nextConfig.webpack === "function") {
385
+ config = nextConfig.webpack(config, ctx);
386
+ }
387
+ if (!ctx.dev) return config;
388
+ config.module = config.module || {};
389
+ config.module.rules = config.module.rules || [];
390
+ config.module.rules.push({
391
+ test: /\.(jsx|tsx)$/,
392
+ exclude: /node_modules/,
393
+ enforce: "pre",
394
+ use: [{ loader: loaderPath, options: { attr } }]
395
+ });
396
+ if (!ctx.isServer) {
397
+ const prevEntry = config.entry;
398
+ config.entry = async () => {
399
+ const entries = typeof prevEntry === "function" ? await prevEntry() : prevEntry;
400
+ for (const key of ["main-app", "main.js", "main"]) {
401
+ const e = entries[key];
402
+ if (!e) continue;
403
+ if (Array.isArray(e)) {
404
+ if (!e.includes(overlayPath)) e.unshift(overlayPath);
405
+ } else if (e && Array.isArray(e.import)) {
406
+ if (!e.import.includes(overlayPath)) e.import.unshift(overlayPath);
407
+ }
408
+ }
409
+ return entries;
410
+ };
411
+ }
412
+ return config;
413
+ };
414
+ }
415
+ if (useTurbopack) {
416
+ const ld = [{ loader: "uivisor/next/loader", options: { attr } }];
417
+ const rules = {
418
+ "*.tsx": { loaders: ld, as: "*.tsx" },
419
+ "*.jsx": { loaders: ld, as: "*.jsx" }
420
+ };
421
+ const major = nextMajor();
422
+ if (major === 0 || major >= 15) {
423
+ out.turbopack = {
424
+ ...nextConfig.turbopack,
425
+ rules: { ...nextConfig.turbopack?.rules ?? {}, ...rules }
426
+ };
427
+ } else {
428
+ const exp = nextConfig.experimental ?? {};
429
+ out.experimental = {
430
+ ...exp,
431
+ turbo: { ...exp.turbo ?? {}, rules: { ...exp.turbo?.rules ?? {}, ...rules } }
432
+ };
433
+ }
434
+ }
435
+ return out;
436
+ }
437
+ var next_default = withUivisor;
438
+ export {
439
+ next_default as default,
440
+ withUivisor
441
+ };
@@ -0,0 +1,13 @@
1
+ /**
2
+ * Dev-only overlay mount for Next.js. Render once near the end of your root
3
+ * layout's <body>. Works under BOTH Turbopack and webpack (no bundler magic) —
4
+ * it just dynamically imports the overlay on the client in development.
5
+ *
6
+ * // app/layout.tsx
7
+ * import { UivisorOverlay } from 'uivisor/next/overlay'
8
+ * ...
9
+ * <body>{children}<UivisorOverlay /></body>
10
+ */
11
+ declare function UivisorOverlay(): null;
12
+
13
+ export { UivisorOverlay, UivisorOverlay as default };
@@ -0,0 +1,17 @@
1
+ "use client";
2
+
3
+ // src/next/overlay.ts
4
+ import { useEffect } from "react";
5
+ function UivisorOverlay() {
6
+ useEffect(() => {
7
+ if (process.env.NODE_ENV !== "production") {
8
+ void import("uivisor/overlay");
9
+ }
10
+ }, []);
11
+ return null;
12
+ }
13
+ var overlay_default = UivisorOverlay;
14
+ export {
15
+ UivisorOverlay,
16
+ overlay_default as default
17
+ };
@@ -894,6 +894,16 @@ var CSS = (
894
894
  .uiv-newclass:focus { border-style: solid; border-color: #6366f1; color: #fff; }
895
895
  .uiv-newclass.on { border-style: solid; border-color: #22d3ee; color: #fff; }
896
896
 
897
+ /* ---- current-styles readout ---- */
898
+ .uiv-readout { display: flex; flex-direction: column; gap: 3px; }
899
+ .uiv-rrow { display: grid; grid-template-columns: 70px 1fr; gap: 8px; align-items: center;
900
+ font-size: 11px; font-family: ui-monospace, monospace; }
901
+ .uiv-rk { color: #71717a; }
902
+ .uiv-rv { color: #fff; word-break: break-all; display: flex; align-items: center; gap: 6px; }
903
+ .uiv-rv.changed { color: #4ade80; } /* edited in uivisor \u2192 green */
904
+ .uiv-sw { display: inline-block; width: 11px; height: 11px; border-radius: 3px;
905
+ border: 1px solid rgba(255,255,255,0.2); flex: 0 0 auto; }
906
+
897
907
  /* ---- Figma-like sectioned controls ---- */
898
908
  .uiv-sectitle { margin: 0 0 8px; font-size: 10px; text-transform: uppercase;
899
909
  letter-spacing: .5px; color: #8b8b94; font-weight: 600; }
@@ -908,7 +918,9 @@ var CSS = (
908
918
  /* numeric field with a scrub handle on the left */
909
919
  .uiv-num { display: flex; align-items: stretch; background: #27272a;
910
920
  border: 1px solid #3f3f46; border-radius: 7px; overflow: hidden; }
911
- .uiv-num.changed { border-color: #22d3ee; }
921
+ .uiv-num.changed { border-color: #4ade80; }
922
+ .uiv-num.changed input { color: #4ade80; } /* uivisor-edited value \u2192 green */
923
+ .uiv-sel.changed, .uiv-color.changed { border-color: #4ade80; }
912
924
  .uiv-num:focus-within { border-color: #6366f1; }
913
925
  .uiv-scrub { display: flex; align-items: center; justify-content: center;
914
926
  width: 24px; color: #8b8b94; cursor: ew-resize; user-select: none;
@@ -948,7 +960,7 @@ var CSS = (
948
960
  .uiv-ctl input.uiv-text { width: 100%; background: #27272a; border: 1px solid #3f3f46;
949
961
  color: #fff; border-radius: 7px; padding: 6px 7px; font-size: 12px; outline: none; }
950
962
  .uiv-ctl input.uiv-text:focus { border-color: #6366f1; }
951
- .uiv-ctl input.uiv-text.changed { border-color: #22d3ee; }
963
+ .uiv-ctl input.uiv-text.changed { border-color: #4ade80; color: #4ade80; }
952
964
 
953
965
  .uiv-journal { display: flex; flex-direction: column; gap: 8px; }
954
966
  .uiv-jitem { background: #1f1f23; border: 1px solid #27272a; border-radius: 8px; padding: 8px; }
@@ -1109,6 +1121,25 @@ var Uivisor = class {
1109
1121
  window.addEventListener("resize", this.onResize, true);
1110
1122
  this.renderBody();
1111
1123
  this.updateBp();
1124
+ window.setTimeout(() => this.reportStatus(), 1500);
1125
+ }
1126
+ /** Tell the dev, in the console, whether uivisor is alive and source-mapped. */
1127
+ reportStatus() {
1128
+ try {
1129
+ const n = document.querySelectorAll("[data-uiv-src]").length;
1130
+ if (n > 0) {
1131
+ console.info(
1132
+ `%cuivisor%c active \u2014 Alt+U (or \u25CE) \xB7 ${n} source-mapped elements`,
1133
+ "color:#818cf8;font-weight:700",
1134
+ "color:inherit"
1135
+ );
1136
+ } else {
1137
+ console.warn(
1138
+ "[uivisor] active, but NO source attributes were found \u2014 exact file:line is OFF.\n\u2022 Next + Turbopack: run `next dev --webpack`, or enable the uivisor Turbopack loader.\n\u2022 Vite: make sure uivisor() is listed BEFORE react() in your plugins.\nTweaking still works (it falls back to component name + selector + text)."
1139
+ );
1140
+ }
1141
+ } catch {
1142
+ }
1112
1143
  }
1113
1144
  q(sel) {
1114
1145
  return this.root.querySelector(sel);
@@ -1476,6 +1507,7 @@ var Uivisor = class {
1476
1507
  <div class="uiv-src">${escapeHtml(src)}</div>
1477
1508
  <span class="uiv-mech">${st.record.styling.primaryMechanism}</span>
1478
1509
  </div>
1510
+ ${this.currentStylesHtml()}
1479
1511
  ${this.breakpointBarHtml()}
1480
1512
  ${this.targetHtml(st)}
1481
1513
  ${this.controlsHtml(this.context(this.selected))}
@@ -1483,20 +1515,93 @@ var Uivisor = class {
1483
1515
  `;
1484
1516
  this.bindControls();
1485
1517
  }
1518
+ /** Read-only readout of the element's actual current styles — so you don't guess. */
1519
+ currentStylesHtml() {
1520
+ const el = this.selected;
1521
+ if (!el) return "";
1522
+ let cs;
1523
+ try {
1524
+ cs = getComputedStyle(el);
1525
+ } catch {
1526
+ return "";
1527
+ }
1528
+ const g = (p) => cs.getPropertyValue(p).trim();
1529
+ const hex = (v) => rgbToHex(v) || v;
1530
+ const swatch = (v) => {
1531
+ const h = hex(v);
1532
+ return /^#|rgb/.test(h) ? `<span class="uiv-sw" style="background:${h}"></span>${h}` : h;
1533
+ };
1534
+ const box = (prefix) => {
1535
+ const t = g(`${prefix}-top`);
1536
+ const r = g(`${prefix}-right`);
1537
+ const b = g(`${prefix}-bottom`);
1538
+ const l = g(`${prefix}-left`);
1539
+ if (t === r && r === b && b === l) return t;
1540
+ if (t === b && r === l) return `${t} ${r}`;
1541
+ return `${t} ${r} ${b} ${l}`;
1542
+ };
1543
+ const changedSet = new Set(this.st()?.record.changes.map((c) => c.property) ?? []);
1544
+ const changed = (props) => props.some((p) => changedSet.has(p));
1545
+ const px4 = (pre) => [`${pre}-top`, `${pre}-right`, `${pre}-bottom`, `${pre}-left`];
1546
+ const rows = [];
1547
+ const add = (k, v, props = []) => {
1548
+ if (v) rows.push({ k, v, edited: changed(props) });
1549
+ };
1550
+ add("display", g("display"));
1551
+ add("size", `${Math.round(parseFloat(g("width")) || 0)} \xD7 ${Math.round(parseFloat(g("height")) || 0)}`);
1552
+ const pad = box("padding");
1553
+ if (pad && pad !== "0px") add("padding", pad, px4("padding"));
1554
+ const mar = box("margin");
1555
+ if (mar && mar !== "0px") add("margin", mar, px4("margin"));
1556
+ if (/flex|grid/.test(g("display"))) {
1557
+ const gap = g("gap");
1558
+ if (gap && gap !== "normal" && gap !== "0px") add("gap", gap, ["gap"]);
1559
+ }
1560
+ add("font", `${g("font-size")} \xB7 ${g("font-weight")} \xB7 lh ${g("line-height")}`, [
1561
+ "font-size",
1562
+ "font-weight",
1563
+ "line-height"
1564
+ ]);
1565
+ const ls = g("letter-spacing");
1566
+ if (ls && ls !== "normal") add("tracking", ls, ["letter-spacing"]);
1567
+ add("color", swatch(g("color")), ["color"]);
1568
+ const bg = g("background-color");
1569
+ if (bg && bg !== "rgba(0, 0, 0, 0)" && bg !== "transparent")
1570
+ add("background", swatch(bg), ["background-color"]);
1571
+ const bw = g("border-top-width");
1572
+ if (bw && parseFloat(bw) > 0)
1573
+ add("border", `${bw} ${g("border-top-style")} ${hex(g("border-top-color"))}`, px4("border").map((p) => `${p}-width`));
1574
+ const br = g("border-radius");
1575
+ if (br && br !== "0px")
1576
+ add("radius", br, [
1577
+ "border-radius",
1578
+ "border-top-left-radius",
1579
+ "border-top-right-radius",
1580
+ "border-bottom-right-radius",
1581
+ "border-bottom-left-radius"
1582
+ ]);
1583
+ if (g("box-shadow") !== "none" && g("box-shadow")) add("shadow", "yes");
1584
+ const op = g("opacity");
1585
+ if (op && parseFloat(op) < 1) add("opacity", op);
1586
+ const items = rows.map((r) => `<div class="uiv-rrow"><span class="uiv-rk">${r.k}</span><span class="uiv-rv${r.edited ? " changed" : ""}">${r.v}</span></div>`).join("");
1587
+ return `<div class="uiv-sec"><div class="uiv-sectitle">Current styles</div><div class="uiv-readout">${items}</div></div>`;
1588
+ }
1486
1589
  /** Breakpoint scope switcher: shows the PROJECT's breakpoints + the live window one. */
1487
1590
  breakpointBarHtml() {
1488
1591
  const sys = this.bpSystem();
1489
1592
  const bps = sys.breakpoints;
1490
1593
  const names = ["base", ...bps.map((b) => b.name)];
1491
1594
  const frameBp = this.responsive ? activeBreakpoint(this.frameWidth, sys).name : null;
1492
- const liveChip = `<button class="uiv-chip${!this.responsive ? " on" : ""}" data-bp="live" title="Your real browser window">Live</button>`;
1595
+ const winBp = currentBreakpoint(sys).name;
1596
+ const liveW = typeof window !== "undefined" ? window.innerWidth : 0;
1597
+ const liveChip = `<button class="uiv-chip${!this.responsive ? " on" : ""}" data-bp="live" title="Follow your real browser window">Live</button>`;
1493
1598
  const chips = names.map((n) => {
1494
- const active = this.responsive && n === frameBp;
1599
+ const active = this.responsive ? n === frameBp : n === winBp;
1495
1600
  const px2 = n === "base" ? 0 : bps.find((b) => b.name === n).minWidth;
1496
1601
  return `<button class="uiv-chip${active ? " on" : ""}" data-bp="${n}" title="Preview at \u2265${px2}px">${n}</button>`;
1497
1602
  }).join("");
1498
1603
  const detected = sys.name === "detected" ? "" : " (defaults)";
1499
- const hint = this.responsive ? `Virtual screen at <b>${this.frameWidth}px</b> (${frameBp}). Edits scoped to <b>${frameBp}:</b>. Drag the frame edge to fine-tune.` : `Click a size to shrink the screen to it & design for that breakpoint. Live = your real window.`;
1604
+ const hint = this.responsive ? `Virtual screen at <b>${this.frameWidth}px</b> (${frameBp}). Edits scoped to <b>${frameBp}:</b>. Drag the frame edge to fine-tune.` : `Live \u2014 your window is <b>${liveW}px</b> = <b>${winBp}</b> range, edits scoped to <b>${winBp}:</b>. Click another size to shrink the screen to it.`;
1500
1605
  return `<div class="uiv-sec"><div class="uiv-sectitle">Screen / breakpoint${detected}</div><div class="uiv-chips">${liveChip}${chips}</div><div class="uiv-bphint">${hint}</div></div>`;
1501
1606
  }
1502
1607
  /** "Apply changes to": this element, an existing shared class, or a NEW class. */
@@ -1641,10 +1746,10 @@ var Uivisor = class {
1641
1746
  if (c.kind === "select") {
1642
1747
  const cur = this.selectCurrent(c.css);
1643
1748
  const opts = c.options.map((o) => `<option value="${o}"${o === cur ? " selected" : ""}>${o}</option>`).join("");
1644
- return `<div class="uiv-ctl"><span class="clabel">${c.label}</span><div class="cfield"><select class="uiv-sel" data-css="${c.css}">${opts}</select></div><span></span></div>`;
1749
+ return `<div class="uiv-ctl"><span class="clabel">${c.label}</span><div class="cfield"><select class="uiv-sel${this.isChanged([c.css]) ? " changed" : ""}" data-css="${c.css}">${opts}</select></div><span></span></div>`;
1645
1750
  }
1646
1751
  const val = toHexInput(this.liveVal(c.css));
1647
- return `<div class="uiv-ctl"><span class="clabel">${c.label}</span><div class="cfield"><input type="color" class="uiv-color" data-css="${c.css}" value="${val}"></div><span></span></div>`;
1752
+ return `<div class="uiv-ctl"><span class="clabel">${c.label}</span><div class="cfield"><input type="color" class="uiv-color${this.isChanged([c.css]) ? " changed" : ""}" data-css="${c.css}" value="${val}"></div><span></span></div>`;
1648
1753
  }
1649
1754
  bindControls() {
1650
1755
  const root = this.root;
package/package.json CHANGED
@@ -1,10 +1,19 @@
1
1
  {
2
2
  "name": "uivisor",
3
- "version": "0.1.0",
3
+ "version": "0.1.1",
4
4
  "type": "module",
5
5
  "description": "Dev-only visual UI tweaker that turns mouse edits into a precise, breakpoint-aware prompt for your AI coding agent — without touching your source.",
6
6
  "license": "MIT",
7
- "keywords": ["vite-plugin", "react", "devtools", "ai", "visual-editing", "tailwind"],
7
+ "author": "Kazbek Kabdulov",
8
+ "homepage": "https://github.com/kabdulov/uivisor#readme",
9
+ "repository": {
10
+ "type": "git",
11
+ "url": "git+https://github.com/kabdulov/uivisor.git"
12
+ },
13
+ "bugs": {
14
+ "url": "https://github.com/kabdulov/uivisor/issues"
15
+ },
16
+ "keywords": ["vite-plugin", "next", "turbopack", "react", "devtools", "ai", "visual-editing", "tailwind"],
8
17
  "exports": {
9
18
  "./vite": {
10
19
  "types": "./dist/vite/index.d.ts",
@@ -22,15 +31,21 @@
22
31
  "default": "./dist/overlay/index.js"
23
32
  },
24
33
  "./next": {
25
- "types": "./dist/next/index.d.cts",
26
- "import": "./dist/next/index.cjs",
34
+ "types": "./dist/next/index.d.ts",
35
+ "import": "./dist/next/index.js",
27
36
  "require": "./dist/next/index.cjs",
28
37
  "default": "./dist/next/index.cjs"
29
38
  },
39
+ "./next/overlay": {
40
+ "types": "./dist/next/overlay.d.ts",
41
+ "import": "./dist/next/overlay.js",
42
+ "default": "./dist/next/overlay.js"
43
+ },
30
44
  "./next/loader": {
31
45
  "require": "./dist/next/loader.cjs",
32
46
  "default": "./dist/next/loader.cjs"
33
- }
47
+ },
48
+ "./package.json": "./package.json"
34
49
  },
35
50
  "files": ["dist"],
36
51
  "publishConfig": {
@@ -41,7 +56,7 @@
41
56
  },
42
57
  "workspaces": ["demo", "demo-next"],
43
58
  "scripts": {
44
- "build": "tsup",
59
+ "build": "rm -rf dist && tsup",
45
60
  "dev": "tsup --watch",
46
61
  "test": "vitest run",
47
62
  "typecheck": "tsc --noEmit",
@@ -49,10 +64,12 @@
49
64
  "prepublishOnly": "npm run build && vitest run"
50
65
  },
51
66
  "peerDependencies": {
52
- "vite": ">=4"
67
+ "vite": ">=4",
68
+ "react": ">=18"
53
69
  },
54
70
  "peerDependenciesMeta": {
55
- "vite": { "optional": true }
71
+ "vite": { "optional": true },
72
+ "react": { "optional": true }
56
73
  },
57
74
  "dependencies": {
58
75
  "@babel/core": "^7.24.0"
@@ -61,7 +78,9 @@
61
78
  "@babel/types": "^7.24.0",
62
79
  "@types/babel__core": "^7.20.5",
63
80
  "@types/node": "^20.11.0",
81
+ "@types/react": "^18.3.0",
64
82
  "jsdom": "^24.0.0",
83
+ "react": "^18.3.1",
65
84
  "tsup": "^8.0.0",
66
85
  "typescript": "^5.4.0",
67
86
  "vitest": "^1.6.0"