uidex 0.3.0 → 0.4.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/dist/cli/cli.cjs +122 -41
- package/dist/cli/cli.cjs.map +1 -1
- package/dist/cloud/index.cjs +22 -2
- package/dist/cloud/index.cjs.map +1 -1
- package/dist/cloud/index.js +22 -2
- package/dist/cloud/index.js.map +1 -1
- package/dist/headless/index.cjs +909 -346
- package/dist/headless/index.cjs.map +1 -1
- package/dist/headless/index.d.cts +6 -0
- package/dist/headless/index.d.ts +6 -0
- package/dist/headless/index.js +914 -346
- package/dist/headless/index.js.map +1 -1
- package/dist/index.cjs +2887 -1167
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +83 -16
- package/dist/index.d.ts +83 -16
- package/dist/index.js +2919 -1175
- package/dist/index.js.map +1 -1
- package/dist/react/index.cjs +2850 -1155
- package/dist/react/index.cjs.map +1 -1
- package/dist/react/index.d.cts +55 -8
- package/dist/react/index.d.ts +55 -8
- package/dist/react/index.js +2879 -1159
- package/dist/react/index.js.map +1 -1
- package/dist/scan/index.cjs +121 -42
- package/dist/scan/index.cjs.map +1 -1
- package/dist/scan/index.d.cts +5 -0
- package/dist/scan/index.d.ts +5 -0
- package/dist/scan/index.js +121 -42
- package/dist/scan/index.js.map +1 -1
- package/package.json +18 -17
- package/templates/claude/audit.md +8 -2
- package/templates/claude/rules.md +15 -0
- package/dist/cloud/index.d.cts +0 -108
- package/dist/cloud/index.d.ts +0 -108
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "uidex",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.4.0",
|
|
4
4
|
"description": "Convention-driven UI element registry and devtools surface for React apps.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/index.js",
|
|
@@ -57,6 +57,18 @@
|
|
|
57
57
|
"publishConfig": {
|
|
58
58
|
"access": "public"
|
|
59
59
|
},
|
|
60
|
+
"scripts": {
|
|
61
|
+
"dev": "tsup --watch",
|
|
62
|
+
"build": "pnpm run build:css && tsup && pnpm run check:bundles",
|
|
63
|
+
"build:css": "tailwindcss --input src/styles/tailwind.css --output src/styles/tailwind.built.css",
|
|
64
|
+
"check:bundles": "node scripts/check-bundles.mjs",
|
|
65
|
+
"test": "vitest run",
|
|
66
|
+
"test:watch": "vitest",
|
|
67
|
+
"lint": "eslint src/",
|
|
68
|
+
"typecheck": "tsc --noEmit",
|
|
69
|
+
"views-map": "tsx scripts/extract-views-map.ts",
|
|
70
|
+
"views-map:check": "tsx scripts/extract-views-map.ts --check"
|
|
71
|
+
},
|
|
60
72
|
"peerDependencies": {
|
|
61
73
|
"@playwright/test": ">=1.40",
|
|
62
74
|
"react": ">=18",
|
|
@@ -83,6 +95,7 @@
|
|
|
83
95
|
"clsx": "^2.1.1",
|
|
84
96
|
"lucide": "^1.8.0",
|
|
85
97
|
"lucide-react": "^1.7.0",
|
|
98
|
+
"modern-screenshot": "^4.7.0",
|
|
86
99
|
"tailwind-merge": "^3.5.0",
|
|
87
100
|
"xstate": "^5.30.0",
|
|
88
101
|
"zod": "^4.3.6",
|
|
@@ -96,6 +109,8 @@
|
|
|
96
109
|
"@types/node": "^22.10.5",
|
|
97
110
|
"@types/react": "^19.2.14",
|
|
98
111
|
"@types/react-dom": "^19.2.3",
|
|
112
|
+
"@uidex/eslint-config": "workspace:*",
|
|
113
|
+
"@uidex/tsconfig": "workspace:*",
|
|
99
114
|
"@vitejs/plugin-react": "^4.3.4",
|
|
100
115
|
"eslint": "^9.18.0",
|
|
101
116
|
"jsdom": "^26.0.0",
|
|
@@ -105,9 +120,7 @@
|
|
|
105
120
|
"tsup": "^8.3.5",
|
|
106
121
|
"tsx": "^4.7.0",
|
|
107
122
|
"typescript": "^5.9.3",
|
|
108
|
-
"vitest": "^2.1.8"
|
|
109
|
-
"@uidex/eslint-config": "0.0.0",
|
|
110
|
-
"@uidex/tsconfig": "0.0.0"
|
|
123
|
+
"vitest": "^2.1.8"
|
|
111
124
|
},
|
|
112
125
|
"keywords": [
|
|
113
126
|
"uidex",
|
|
@@ -122,17 +135,5 @@
|
|
|
122
135
|
"repository": {
|
|
123
136
|
"type": "git",
|
|
124
137
|
"url": "https://github.com/soel/uidex"
|
|
125
|
-
},
|
|
126
|
-
"scripts": {
|
|
127
|
-
"dev": "tsup --watch",
|
|
128
|
-
"build": "pnpm run build:css && tsup && pnpm run check:bundles",
|
|
129
|
-
"build:css": "tailwindcss --input src/styles/tailwind.css --output src/styles/tailwind.built.css",
|
|
130
|
-
"check:bundles": "node scripts/check-bundles.mjs",
|
|
131
|
-
"test": "vitest run",
|
|
132
|
-
"test:watch": "vitest",
|
|
133
|
-
"lint": "eslint src/",
|
|
134
|
-
"typecheck": "tsc --noEmit",
|
|
135
|
-
"views-map": "tsx scripts/extract-views-map.ts",
|
|
136
|
-
"views-map:check": "tsx scripts/extract-views-map.ts --check"
|
|
137
138
|
}
|
|
138
|
-
}
|
|
139
|
+
}
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
Run `npx uidex scan --audit` and fix all reported diagnostics.
|
|
2
2
|
|
|
3
3
|
1. **`marker-md-ignored`** — legacy `UIDEX_PAGE.md` / `UIDEX_FEATURE.md` files from v1. Migrate their content:
|
|
4
|
-
-
|
|
5
|
-
- Each `- [ ]` checkbox becomes one
|
|
4
|
+
- Create a `uidex.page.ts` (in the route directory) or `uidex.feature.ts` (in the feature directory) and add an `export const uidex` block carrying the `page`/`feature` id, the description, and the acceptance list.
|
|
5
|
+
- Each `- [ ]` checkbox becomes one entry in the `acceptance` array.
|
|
6
6
|
- Delete the `UIDEX_PAGE.md` / `UIDEX_FEATURE.md` file.
|
|
7
7
|
|
|
8
8
|
2. **`acceptance-uncovered`** — a declared `@acceptance` criterion has no flow exercising it.
|
|
@@ -24,6 +24,12 @@ Run `npx uidex scan --audit` and fix all reported diagnostics.
|
|
|
24
24
|
6. **`acceptance-orphan`** — an `@acceptance` tag appears on a JSDoc that doesn't declare `@uidex page|feature|widget`.
|
|
25
25
|
- Move the acceptance tags into the correct JSDoc block, or remove them.
|
|
26
26
|
|
|
27
|
+
7. **`prefer-well-known-file`** (INFO) — a page or feature's `export const uidex` lives on an arbitrary file instead of the well-known file (`uidex.page.ts` for pages, `uidex.feature.ts` for features). Migrate:
|
|
28
|
+
- Create `uidex.page.ts` (in the route directory) or `uidex.feature.ts` (in the feature directory).
|
|
29
|
+
- Move the `export const uidex` block from the current file into the new well-known file.
|
|
30
|
+
- Remove the export (and any now-unused `Uidex` type import) from the original file.
|
|
31
|
+
- Run `npx uidex scan` to regenerate the gen file — `loc.file` updates but the entity itself is unchanged.
|
|
32
|
+
|
|
27
33
|
After fixing, run `npx uidex scan` to regenerate the gen file before re-running the audit.
|
|
28
34
|
|
|
29
35
|
## Decision rules for primitives
|
|
@@ -2,6 +2,21 @@
|
|
|
2
2
|
|
|
3
3
|
This project uses [uidex](https://github.com/soel/uidex) for UI element tracking and feedback ingestion.
|
|
4
4
|
|
|
5
|
+
## AI behavior
|
|
6
|
+
|
|
7
|
+
Before editing any file inside a feature directory (`src/features/<name>/`) or a Next.js route directory, read the entity's well-known metadata file first:
|
|
8
|
+
|
|
9
|
+
- Feature directories: `uidex.feature.ts` — the feature's `export const uidex` block lives here.
|
|
10
|
+
- Route directories: `uidex.page.ts` — the page's `export const uidex` block lives here.
|
|
11
|
+
|
|
12
|
+
These files declare `acceptance` criteria and a `description`. Treat them as **context steering**, not test assertions:
|
|
13
|
+
|
|
14
|
+
- Acceptance criteria capture what matters about the page or feature so changes preserve the right behaviors. They are NOT the testing source of truth — Playwright flows under `e2e/**` are.
|
|
15
|
+
- Before making a change, check whether it would violate a declared acceptance criterion. If it would, flag the conflict to the user before proceeding.
|
|
16
|
+
- If a change adds or removes user-visible behavior, update the acceptance list in the well-known file alongside the code change.
|
|
17
|
+
|
|
18
|
+
If a feature or page directory has no `uidex.feature.ts` / `uidex.page.ts`, the metadata may live on an arbitrary file in the directory (legacy convention) — `uidex scan --audit` will surface a `prefer-well-known-file` diagnostic with the current location.
|
|
19
|
+
|
|
5
20
|
## Entity model
|
|
6
21
|
|
|
7
22
|
Eight entity kinds make up the registry. Most are discovered by convention; annotations only override.
|
package/dist/cloud/index.d.cts
DELETED
|
@@ -1,108 +0,0 @@
|
|
|
1
|
-
interface ConsoleLogEntry {
|
|
2
|
-
level: "log" | "warn" | "error" | "info";
|
|
3
|
-
message: string;
|
|
4
|
-
timestamp: string;
|
|
5
|
-
}
|
|
6
|
-
interface NetworkErrorEntry {
|
|
7
|
-
url: string;
|
|
8
|
-
method: string;
|
|
9
|
-
status: number | null;
|
|
10
|
-
statusText: string | null;
|
|
11
|
-
timestamp: string;
|
|
12
|
-
}
|
|
13
|
-
interface Viewport {
|
|
14
|
-
width: number;
|
|
15
|
-
height: number;
|
|
16
|
-
}
|
|
17
|
-
interface SourceRef {
|
|
18
|
-
filePath: string;
|
|
19
|
-
line: number;
|
|
20
|
-
}
|
|
21
|
-
interface FeedbackSuggestedTarget {
|
|
22
|
-
integrationId: string;
|
|
23
|
-
targetConfig: Record<string, unknown>;
|
|
24
|
-
}
|
|
25
|
-
interface FeedbackPayload {
|
|
26
|
-
type: "bug" | "feature" | "improvement" | "question";
|
|
27
|
-
severity: "low" | "medium" | "high" | "critical";
|
|
28
|
-
title?: string;
|
|
29
|
-
description: string;
|
|
30
|
-
componentId: string;
|
|
31
|
-
element?: string | null;
|
|
32
|
-
sources?: SourceRef[];
|
|
33
|
-
url: string;
|
|
34
|
-
path: string;
|
|
35
|
-
route?: string | null;
|
|
36
|
-
pageTitle?: string;
|
|
37
|
-
sessionId?: string;
|
|
38
|
-
reporterEmail?: string;
|
|
39
|
-
reporterName?: string;
|
|
40
|
-
timestamp: string;
|
|
41
|
-
viewport: Viewport;
|
|
42
|
-
screen: Viewport;
|
|
43
|
-
userAgent: string;
|
|
44
|
-
locale?: string;
|
|
45
|
-
environment?: string;
|
|
46
|
-
appVersion?: string;
|
|
47
|
-
consoleLogs?: ConsoleLogEntry[];
|
|
48
|
-
networkErrors?: NetworkErrorEntry[];
|
|
49
|
-
metadata?: Record<string, string>;
|
|
50
|
-
screenshot?: string;
|
|
51
|
-
suggestedTarget?: FeedbackSuggestedTarget;
|
|
52
|
-
}
|
|
53
|
-
interface FeedbackExternalLink {
|
|
54
|
-
ok: boolean;
|
|
55
|
-
url?: string;
|
|
56
|
-
key?: string;
|
|
57
|
-
error?: string;
|
|
58
|
-
}
|
|
59
|
-
interface FeedbackResult {
|
|
60
|
-
id: string;
|
|
61
|
-
sequenceNumber: number;
|
|
62
|
-
externalLink?: FeedbackExternalLink;
|
|
63
|
-
}
|
|
64
|
-
interface IngestConfigEpic {
|
|
65
|
-
key: string;
|
|
66
|
-
summary: string;
|
|
67
|
-
status: string;
|
|
68
|
-
}
|
|
69
|
-
interface IngestConfig {
|
|
70
|
-
hasJira: boolean;
|
|
71
|
-
integrationId?: string;
|
|
72
|
-
epics?: IngestConfigEpic[];
|
|
73
|
-
}
|
|
74
|
-
/**
|
|
75
|
-
* Generic so third-party adapters (e.g. `uidex-cloud`) can plug in their own
|
|
76
|
-
* payload/result/integration shapes. SDK-bundled `cloud()` returns the
|
|
77
|
-
* defaulted form. `ViewContext.cloud` uses the fully-open variant; consumers
|
|
78
|
-
* that need the SDK shape narrow with `as CloudAdapter`.
|
|
79
|
-
*/
|
|
80
|
-
interface CloudAdapter<TPayload = FeedbackPayload, TResult = FeedbackResult, TIntegrations = {
|
|
81
|
-
getConfig(): Promise<IngestConfig>;
|
|
82
|
-
}> {
|
|
83
|
-
readonly feedback: {
|
|
84
|
-
submit(payload: TPayload): Promise<TResult>;
|
|
85
|
-
};
|
|
86
|
-
readonly integrations: TIntegrations;
|
|
87
|
-
}
|
|
88
|
-
|
|
89
|
-
declare const DEFAULT_CLOUD_ENDPOINT = "https://app.uidex.dev";
|
|
90
|
-
interface CloudOptions {
|
|
91
|
-
projectKey: string;
|
|
92
|
-
endpoint?: string;
|
|
93
|
-
fetch?: typeof fetch;
|
|
94
|
-
}
|
|
95
|
-
declare class CloudError extends Error {
|
|
96
|
-
readonly status: number;
|
|
97
|
-
readonly retryAfter?: number;
|
|
98
|
-
readonly details?: unknown;
|
|
99
|
-
constructor(message: string, options: {
|
|
100
|
-
status: number;
|
|
101
|
-
retryAfter?: number;
|
|
102
|
-
details?: unknown;
|
|
103
|
-
});
|
|
104
|
-
}
|
|
105
|
-
|
|
106
|
-
declare function cloud(options: CloudOptions): CloudAdapter;
|
|
107
|
-
|
|
108
|
-
export { type CloudAdapter, CloudError, type CloudOptions, DEFAULT_CLOUD_ENDPOINT, type FeedbackExternalLink, type FeedbackPayload, type FeedbackResult, type FeedbackSuggestedTarget, type IngestConfig, type IngestConfigEpic, type SourceRef, cloud };
|
package/dist/cloud/index.d.ts
DELETED
|
@@ -1,108 +0,0 @@
|
|
|
1
|
-
interface ConsoleLogEntry {
|
|
2
|
-
level: "log" | "warn" | "error" | "info";
|
|
3
|
-
message: string;
|
|
4
|
-
timestamp: string;
|
|
5
|
-
}
|
|
6
|
-
interface NetworkErrorEntry {
|
|
7
|
-
url: string;
|
|
8
|
-
method: string;
|
|
9
|
-
status: number | null;
|
|
10
|
-
statusText: string | null;
|
|
11
|
-
timestamp: string;
|
|
12
|
-
}
|
|
13
|
-
interface Viewport {
|
|
14
|
-
width: number;
|
|
15
|
-
height: number;
|
|
16
|
-
}
|
|
17
|
-
interface SourceRef {
|
|
18
|
-
filePath: string;
|
|
19
|
-
line: number;
|
|
20
|
-
}
|
|
21
|
-
interface FeedbackSuggestedTarget {
|
|
22
|
-
integrationId: string;
|
|
23
|
-
targetConfig: Record<string, unknown>;
|
|
24
|
-
}
|
|
25
|
-
interface FeedbackPayload {
|
|
26
|
-
type: "bug" | "feature" | "improvement" | "question";
|
|
27
|
-
severity: "low" | "medium" | "high" | "critical";
|
|
28
|
-
title?: string;
|
|
29
|
-
description: string;
|
|
30
|
-
componentId: string;
|
|
31
|
-
element?: string | null;
|
|
32
|
-
sources?: SourceRef[];
|
|
33
|
-
url: string;
|
|
34
|
-
path: string;
|
|
35
|
-
route?: string | null;
|
|
36
|
-
pageTitle?: string;
|
|
37
|
-
sessionId?: string;
|
|
38
|
-
reporterEmail?: string;
|
|
39
|
-
reporterName?: string;
|
|
40
|
-
timestamp: string;
|
|
41
|
-
viewport: Viewport;
|
|
42
|
-
screen: Viewport;
|
|
43
|
-
userAgent: string;
|
|
44
|
-
locale?: string;
|
|
45
|
-
environment?: string;
|
|
46
|
-
appVersion?: string;
|
|
47
|
-
consoleLogs?: ConsoleLogEntry[];
|
|
48
|
-
networkErrors?: NetworkErrorEntry[];
|
|
49
|
-
metadata?: Record<string, string>;
|
|
50
|
-
screenshot?: string;
|
|
51
|
-
suggestedTarget?: FeedbackSuggestedTarget;
|
|
52
|
-
}
|
|
53
|
-
interface FeedbackExternalLink {
|
|
54
|
-
ok: boolean;
|
|
55
|
-
url?: string;
|
|
56
|
-
key?: string;
|
|
57
|
-
error?: string;
|
|
58
|
-
}
|
|
59
|
-
interface FeedbackResult {
|
|
60
|
-
id: string;
|
|
61
|
-
sequenceNumber: number;
|
|
62
|
-
externalLink?: FeedbackExternalLink;
|
|
63
|
-
}
|
|
64
|
-
interface IngestConfigEpic {
|
|
65
|
-
key: string;
|
|
66
|
-
summary: string;
|
|
67
|
-
status: string;
|
|
68
|
-
}
|
|
69
|
-
interface IngestConfig {
|
|
70
|
-
hasJira: boolean;
|
|
71
|
-
integrationId?: string;
|
|
72
|
-
epics?: IngestConfigEpic[];
|
|
73
|
-
}
|
|
74
|
-
/**
|
|
75
|
-
* Generic so third-party adapters (e.g. `uidex-cloud`) can plug in their own
|
|
76
|
-
* payload/result/integration shapes. SDK-bundled `cloud()` returns the
|
|
77
|
-
* defaulted form. `ViewContext.cloud` uses the fully-open variant; consumers
|
|
78
|
-
* that need the SDK shape narrow with `as CloudAdapter`.
|
|
79
|
-
*/
|
|
80
|
-
interface CloudAdapter<TPayload = FeedbackPayload, TResult = FeedbackResult, TIntegrations = {
|
|
81
|
-
getConfig(): Promise<IngestConfig>;
|
|
82
|
-
}> {
|
|
83
|
-
readonly feedback: {
|
|
84
|
-
submit(payload: TPayload): Promise<TResult>;
|
|
85
|
-
};
|
|
86
|
-
readonly integrations: TIntegrations;
|
|
87
|
-
}
|
|
88
|
-
|
|
89
|
-
declare const DEFAULT_CLOUD_ENDPOINT = "https://app.uidex.dev";
|
|
90
|
-
interface CloudOptions {
|
|
91
|
-
projectKey: string;
|
|
92
|
-
endpoint?: string;
|
|
93
|
-
fetch?: typeof fetch;
|
|
94
|
-
}
|
|
95
|
-
declare class CloudError extends Error {
|
|
96
|
-
readonly status: number;
|
|
97
|
-
readonly retryAfter?: number;
|
|
98
|
-
readonly details?: unknown;
|
|
99
|
-
constructor(message: string, options: {
|
|
100
|
-
status: number;
|
|
101
|
-
retryAfter?: number;
|
|
102
|
-
details?: unknown;
|
|
103
|
-
});
|
|
104
|
-
}
|
|
105
|
-
|
|
106
|
-
declare function cloud(options: CloudOptions): CloudAdapter;
|
|
107
|
-
|
|
108
|
-
export { type CloudAdapter, CloudError, type CloudOptions, DEFAULT_CLOUD_ENDPOINT, type FeedbackExternalLink, type FeedbackPayload, type FeedbackResult, type FeedbackSuggestedTarget, type IngestConfig, type IngestConfigEpic, type SourceRef, cloud };
|