uilint-react 0.1.39 → 0.1.40

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.
@@ -133,16 +133,21 @@ function updateElementRects(elements) {
133
133
  rect: el.element.getBoundingClientRect()
134
134
  }));
135
135
  }
136
- function buildEditorUrl(source, editor = "cursor") {
136
+ function buildEditorUrl(source, editor = "cursor", workspaceRoot) {
137
137
  const { fileName, lineNumber, columnNumber } = source;
138
138
  const column = columnNumber ?? 1;
139
+ let absolutePath = fileName;
140
+ if (workspaceRoot && !fileName.startsWith("/")) {
141
+ const root = workspaceRoot.endsWith("/") ? workspaceRoot.slice(0, -1) : workspaceRoot;
142
+ absolutePath = `${root}/${fileName}`;
143
+ }
139
144
  if (editor === "cursor") {
140
145
  return `cursor://file/${encodeURIComponent(
141
- fileName
146
+ absolutePath
142
147
  )}:${lineNumber}:${column}`;
143
148
  }
144
149
  return `vscode://file/${encodeURIComponent(
145
- fileName
150
+ absolutePath
146
151
  )}:${lineNumber}:${column}`;
147
152
  }
148
153
 
@@ -447,6 +452,9 @@ var useUILintStore = create()((set, get) => ({
447
452
  wsProgressPhase: /* @__PURE__ */ new Map(),
448
453
  wsLastActivity: null,
449
454
  wsRecentResults: [],
455
+ workspaceRoot: null,
456
+ appRoot: null,
457
+ serverCwd: null,
450
458
  connectWebSocket: (url) => {
451
459
  const targetUrl = url || get().wsUrl;
452
460
  const existing = get().wsConnection;
@@ -682,6 +690,16 @@ var useUILintStore = create()((set, get) => ({
682
690
  }
683
691
  break;
684
692
  }
693
+ case "workspace:info": {
694
+ const { appRoot, workspaceRoot, serverCwd } = data;
695
+ console.log("[UILint] Received workspace info:", {
696
+ appRoot,
697
+ workspaceRoot,
698
+ serverCwd
699
+ });
700
+ set({ appRoot, workspaceRoot, serverCwd });
701
+ break;
702
+ }
685
703
  }
686
704
  },
687
705
  _reconnectWebSocket: () => {
@@ -879,7 +897,7 @@ function UILintProvider({
879
897
  );
880
898
  const handleMouseMove = useCallback2(
881
899
  (e) => {
882
- if (!altKeyHeld && !inspectedElement) return;
900
+ if (!altKeyHeld) return;
883
901
  const elementAtPoint = document.elementFromPoint(e.clientX, e.clientY);
884
902
  if (!elementAtPoint) {
885
903
  setLocatorTarget(null);
@@ -896,16 +914,11 @@ function UILintProvider({
896
914
  }
897
915
  setLocatorTarget(null);
898
916
  },
899
- [
900
- altKeyHeld,
901
- inspectedElement,
902
- getLocatorTargetFromElement,
903
- setLocatorTarget
904
- ]
917
+ [altKeyHeld, getLocatorTargetFromElement, setLocatorTarget]
905
918
  );
906
919
  const handleLocatorClick = useCallback2(
907
920
  (e) => {
908
- if (!altKeyHeld && !inspectedElement || !locatorTarget) return;
921
+ if (!altKeyHeld || !locatorTarget) return;
909
922
  const targetEl = e.target;
910
923
  if (targetEl?.closest?.("[data-ui-lint]")) return;
911
924
  e.preventDefault();
@@ -917,13 +930,7 @@ function UILintProvider({
917
930
  });
918
931
  setLocatorTarget(null);
919
932
  },
920
- [
921
- altKeyHeld,
922
- locatorTarget,
923
- inspectedElement,
924
- setInspectedElement,
925
- setLocatorTarget
926
- ]
933
+ [altKeyHeld, locatorTarget, setInspectedElement, setLocatorTarget]
927
934
  );
928
935
  useEffect2(() => {
929
936
  if (!isBrowser() || !enabled) return;
@@ -953,20 +960,14 @@ function UILintProvider({
953
960
  }, [enabled, setAltKeyHeld, setLocatorTarget]);
954
961
  useEffect2(() => {
955
962
  if (!isBrowser() || !enabled) return;
956
- if (!altKeyHeld && !inspectedElement) return;
963
+ if (!altKeyHeld) return;
957
964
  window.addEventListener("mousemove", handleMouseMove);
958
965
  window.addEventListener("click", handleLocatorClick, true);
959
966
  return () => {
960
967
  window.removeEventListener("mousemove", handleMouseMove);
961
968
  window.removeEventListener("click", handleLocatorClick, true);
962
969
  };
963
- }, [
964
- enabled,
965
- altKeyHeld,
966
- inspectedElement,
967
- handleMouseMove,
968
- handleLocatorClick
969
- ]);
970
+ }, [enabled, altKeyHeld, handleMouseMove, handleLocatorClick]);
970
971
  useEffect2(() => {
971
972
  if (!isBrowser() || !enabled) return;
972
973
  const handleKeyDown = (e) => {
@@ -1030,10 +1031,10 @@ function UILintUI() {
1030
1031
  const [components, setComponents] = useState(null);
1031
1032
  useEffect2(() => {
1032
1033
  Promise.all([
1033
- import("./UILintToolbar-4SH33QJU.js"),
1034
- import("./InspectionPanel-VAHZBVVL.js"),
1035
- import("./LocatorOverlay-BEJYHU6S.js"),
1036
- import("./ElementBadges-3AFD2W4Z.js")
1034
+ import("./UILintToolbar-MJH7RUZK.js"),
1035
+ import("./InspectionPanel-4LOWGHW7.js"),
1036
+ import("./LocatorOverlay-ERRFPXKK.js"),
1037
+ import("./ElementBadges-2I25HN6W.js")
1037
1038
  ]).then(([toolbar, panel, locator, badges]) => {
1038
1039
  setComponents({
1039
1040
  Toolbar: toolbar.UILintToolbar,
@@ -1,7 +1,7 @@
1
1
  "use client";
2
2
  import {
3
3
  useUILintContext
4
- } from "./chunk-ILK73X6L.js";
4
+ } from "./chunk-LAL3JTAA.js";
5
5
 
6
6
  // src/components/ui-lint/LocatorOverlay.tsx
7
7
  import { useState, useEffect, useMemo } from "react";
package/dist/index.d.ts CHANGED
@@ -169,32 +169,31 @@ declare function useUILintContext(): UILintContextValue;
169
169
  declare function UILintProvider({ children, enabled, }: UILintProviderProps): react_jsx_runtime.JSX.Element;
170
170
 
171
171
  /**
172
- * UILint Toolbar - Three-segment pill for live scanning
172
+ * UILint Toolbar - Improved UX Version
173
173
  *
174
- * Design:
175
- * ┌────────────────────────────────────────┐
176
- * │ [👁 Toggle] │ [Issues] │ [...] │
177
- * └────────────────────────────────────────┘
178
- * ⌥+Click to inspect
179
- *
180
- * Segments:
181
- * 1. Toggle: Enable/disable live scanning mode
182
- * 2. Issues: Show issue count, opens results panel
183
- * 3. Settings: Ellipsis for settings popover
174
+ * Key improvements:
175
+ * - Clear visual hierarchy: Primary (toggle) → Secondary (issues) → Tertiary (settings)
176
+ * - Contextual hints that only show when relevant
177
+ * - CSS-based hover/focus states (no inline handlers)
178
+ * - Full keyboard navigation with visible focus rings
179
+ * - Smooth animations for all state changes
180
+ * - Better disabled state communication
181
+ * - Expanded panel that doesn't conflict with settings
182
+ * - Touch-friendly targets (min 44px)
183
+ * - ARIA labels and semantic markup
184
184
  */
185
185
 
186
- /**
187
- * Main Toolbar Component - Three-segment pill
188
- */
189
186
  declare function UILintToolbar(): React$1.ReactPortal | null;
190
187
 
191
188
  /**
192
- * Inspection Panel - Slide-out sidebar showing element details, source preview,
193
- * and LLM analysis with clipboard-ready fix prompts
189
+ * Inspection Panel - Lightweight floating popover showing element issues
190
+ * with inline code previews and "Open in Cursor" actions
191
+ *
192
+ * Positions near the clicked badge, avoiding overlap with the element itself.
194
193
  */
195
194
 
196
195
  /**
197
- * Main Inspection Panel Component
196
+ * Main Inspection Panel Component - Floating Popover
198
197
  */
199
198
  declare function InspectionPanel(): React$1.ReactPortal | null;
200
199
 
@@ -253,8 +252,11 @@ declare function getElementById(id: string): Element | null;
253
252
  declare function updateElementRects(elements: ScannedElement[]): ScannedElement[];
254
253
  /**
255
254
  * Build an "Open in Editor" URL
255
+ * @param source - The source location (fileName may be relative or absolute)
256
+ * @param editor - The editor to open in (cursor or vscode)
257
+ * @param workspaceRoot - Optional workspace root to prepend for relative paths
256
258
  */
257
- declare function buildEditorUrl(source: SourceLocation, editor?: "cursor" | "vscode"): string;
259
+ declare function buildEditorUrl(source: SourceLocation, editor?: "cursor" | "vscode", workspaceRoot?: string | null): string;
258
260
 
259
261
  /**
260
262
  * Client for fetching source code from the dev API
package/dist/index.js CHANGED
@@ -1,7 +1,7 @@
1
1
  "use client";
2
2
  import {
3
3
  UILintToolbar
4
- } from "./chunk-4TLFW7LD.js";
4
+ } from "./chunk-C6NUU5MF.js";
5
5
  import {
6
6
  InspectionPanel,
7
7
  clearSourceCache,
@@ -9,10 +9,10 @@ import {
9
9
  fetchSourceWithContext,
10
10
  getCachedSource,
11
11
  prefetchSources
12
- } from "./chunk-NCNRCF5A.js";
12
+ } from "./chunk-2VRWAMW7.js";
13
13
  import {
14
14
  LocatorOverlay
15
- } from "./chunk-7434TUMX.js";
15
+ } from "./chunk-UD6HPLEZ.js";
16
16
  import {
17
17
  DATA_UILINT_ID,
18
18
  DEFAULT_SETTINGS,
@@ -28,7 +28,7 @@ import {
28
28
  scanDOMForSources,
29
29
  updateElementRects,
30
30
  useUILintContext
31
- } from "./chunk-ILK73X6L.js";
31
+ } from "./chunk-LAL3JTAA.js";
32
32
 
33
33
  // src/consistency/snapshot.ts
34
34
  var DATA_ELEMENTS_ATTR = "data-elements";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "uilint-react",
3
- "version": "0.1.39",
3
+ "version": "0.1.40",
4
4
  "description": "React component for AI-powered UI consistency checking",
5
5
  "author": "Peter Suggate",
6
6
  "repository": {
@@ -34,7 +34,7 @@
34
34
  "node": ">=20.0.0"
35
35
  },
36
36
  "dependencies": {
37
- "uilint-core": "^0.1.39",
37
+ "uilint-core": "^0.1.40",
38
38
  "zustand": "^5.0.5"
39
39
  },
40
40
  "peerDependencies": {