angular-grab 0.1.1 → 0.1.3

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.
Files changed (138) hide show
  1. package/.claude/settings.local.json +10 -0
  2. package/.playwright-mcp/console-2026-03-07T02-49-38-061Z.log +37 -0
  3. package/.playwright-mcp/console-2026-03-07T02-51-03-493Z.log +26 -0
  4. package/.playwright-mcp/console-2026-03-07T02-51-25-431Z.log +15 -0
  5. package/.playwright-mcp/console-2026-03-07T02-52-02-980Z.log +199 -0
  6. package/.playwright-mcp/page-2026-03-07T02-52-09-791Z.png +0 -0
  7. package/README.md +215 -0
  8. package/examples/angular-19-app/.editorconfig +17 -0
  9. package/examples/angular-19-app/.vscode/extensions.json +4 -0
  10. package/examples/angular-19-app/.vscode/launch.json +20 -0
  11. package/examples/angular-19-app/.vscode/mcp.json +9 -0
  12. package/examples/angular-19-app/.vscode/tasks.json +42 -0
  13. package/examples/angular-19-app/README.md +59 -0
  14. package/examples/angular-19-app/angular.json +79 -0
  15. package/examples/angular-19-app/package.json +42 -0
  16. package/examples/angular-19-app/public/favicon.ico +0 -0
  17. package/examples/angular-19-app/src/app/app.config.ts +13 -0
  18. package/examples/angular-19-app/src/app/app.css +37 -0
  19. package/examples/angular-19-app/src/app/app.html +25 -0
  20. package/examples/angular-19-app/src/app/app.routes.ts +3 -0
  21. package/examples/angular-19-app/src/app/app.spec.ts +23 -0
  22. package/examples/angular-19-app/src/app/app.ts +12 -0
  23. package/examples/angular-19-app/src/app/button/button.component.ts +25 -0
  24. package/examples/angular-19-app/src/app/card/card.component.ts +33 -0
  25. package/examples/angular-19-app/src/app/header/header.component.ts +31 -0
  26. package/examples/angular-19-app/src/app/popover/popover.component.ts +133 -0
  27. package/examples/angular-19-app/src/index.html +13 -0
  28. package/examples/angular-19-app/src/main.ts +6 -0
  29. package/examples/angular-19-app/src/styles.css +1 -0
  30. package/examples/angular-19-app/tsconfig.app.json +15 -0
  31. package/examples/angular-19-app/tsconfig.json +33 -0
  32. package/examples/angular-19-app/tsconfig.spec.json +15 -0
  33. package/package.json +14 -111
  34. package/packages/angular-grab/package.json +96 -0
  35. package/packages/angular-grab/src/angular/__tests__/context-builder.test.ts +216 -0
  36. package/packages/angular-grab/src/angular/angular-grab.service.ts +62 -0
  37. package/packages/angular-grab/src/angular/index.ts +13 -0
  38. package/packages/angular-grab/src/angular/provide-angular-grab.ts +22 -0
  39. package/packages/angular-grab/src/angular/resolvers/component-resolver.ts +71 -0
  40. package/packages/angular-grab/src/angular/resolvers/context-builder.ts +86 -0
  41. package/packages/angular-grab/src/angular/resolvers/ng-utils.ts +14 -0
  42. package/packages/angular-grab/src/angular/resolvers/source-resolver.ts +61 -0
  43. package/packages/angular-grab/src/builder/__tests__/builder.test.ts +72 -0
  44. package/packages/angular-grab/src/builder/builders/application/index.ts +13 -0
  45. package/packages/angular-grab/src/builder/builders/dev-server/index.ts +9 -0
  46. package/packages/angular-grab/src/builder/index.ts +3 -0
  47. package/packages/angular-grab/src/cli/__tests__/cli.test.ts +239 -0
  48. package/packages/angular-grab/src/cli/commands/init.ts +106 -0
  49. package/packages/angular-grab/src/cli/index.ts +15 -0
  50. package/packages/angular-grab/src/cli/utils/detect-project.ts +78 -0
  51. package/packages/angular-grab/src/cli/utils/modify-angular-json.ts +42 -0
  52. package/packages/angular-grab/src/cli/utils/modify-app-config.ts +42 -0
  53. package/packages/angular-grab/src/core/__tests__/generate-snippet.test.ts +149 -0
  54. package/packages/angular-grab/src/core/__tests__/plugin-registry.test.ts +286 -0
  55. package/packages/angular-grab/src/core/__tests__/store.test.ts +118 -0
  56. package/packages/angular-grab/src/core/__tests__/utils.test.ts +85 -0
  57. package/packages/angular-grab/src/core/clipboard/copy.ts +104 -0
  58. package/packages/angular-grab/src/core/clipboard/generate-snippet.ts +38 -0
  59. package/packages/angular-grab/src/core/constants.ts +10 -0
  60. package/packages/angular-grab/src/core/grab.ts +596 -0
  61. package/packages/angular-grab/src/core/index.global.ts +13 -0
  62. package/packages/angular-grab/src/core/index.ts +19 -0
  63. package/packages/angular-grab/src/core/keyboard/keyboard-handler.ts +163 -0
  64. package/packages/angular-grab/src/core/overlay/crosshair.ts +107 -0
  65. package/packages/angular-grab/src/core/overlay/freeze-overlay.ts +239 -0
  66. package/packages/angular-grab/src/core/overlay/overlay-renderer.ts +180 -0
  67. package/packages/angular-grab/src/core/overlay/select-feedback.ts +108 -0
  68. package/packages/angular-grab/src/core/overlay/toast.ts +175 -0
  69. package/packages/angular-grab/src/core/picker/element-picker.ts +114 -0
  70. package/packages/angular-grab/src/core/plugins/plugin-registry.ts +83 -0
  71. package/packages/angular-grab/src/core/store.ts +52 -0
  72. package/packages/angular-grab/src/core/toolbar/actions-menu.ts +178 -0
  73. package/packages/angular-grab/src/core/toolbar/comment-popover.ts +235 -0
  74. package/packages/angular-grab/src/core/toolbar/copy-actions.ts +98 -0
  75. package/packages/angular-grab/src/core/toolbar/history-popover.ts +245 -0
  76. package/packages/angular-grab/src/core/toolbar/theme-manager.ts +188 -0
  77. package/packages/angular-grab/src/core/toolbar/toolbar-icons.ts +29 -0
  78. package/packages/angular-grab/src/core/toolbar/toolbar-renderer.ts +239 -0
  79. package/packages/angular-grab/src/core/types.ts +139 -0
  80. package/packages/angular-grab/src/core/utils.ts +16 -0
  81. package/packages/angular-grab/src/esbuild-plugin/__tests__/transform.test.ts +174 -0
  82. package/packages/angular-grab/src/esbuild-plugin/index.ts +3 -0
  83. package/packages/angular-grab/src/esbuild-plugin/plugin.ts +29 -0
  84. package/packages/angular-grab/src/esbuild-plugin/scan.ts +105 -0
  85. package/packages/angular-grab/src/esbuild-plugin/transform.ts +152 -0
  86. package/packages/angular-grab/src/vite-plugin/__tests__/plugin.test.ts +84 -0
  87. package/packages/angular-grab/src/vite-plugin/index.ts +19 -0
  88. package/packages/angular-grab/src/webpack-plugin/__tests__/plugin.test.ts +72 -0
  89. package/packages/angular-grab/src/webpack-plugin/index.ts +2 -0
  90. package/packages/angular-grab/src/webpack-plugin/loader.ts +15 -0
  91. package/packages/angular-grab/src/webpack-plugin/plugin.ts +20 -0
  92. package/packages/angular-grab/tsconfig.json +15 -0
  93. package/packages/angular-grab/tsup.config.ts +119 -0
  94. package/pnpm-workspace.yaml +3 -0
  95. package/turbo.json +21 -0
  96. package/dist/angular/index.d.ts +0 -151
  97. package/dist/angular/index.js +0 -2811
  98. package/dist/angular/index.js.map +0 -1
  99. package/dist/builder/builders/application/index.js +0 -143
  100. package/dist/builder/builders/application/index.js.map +0 -1
  101. package/dist/builder/builders/dev-server/index.js +0 -139
  102. package/dist/builder/builders/dev-server/index.js.map +0 -1
  103. package/dist/builder/index.js +0 -2
  104. package/dist/builder/index.js.map +0 -1
  105. package/dist/builder/package.json +0 -1
  106. package/dist/cli/index.js +0 -223
  107. package/dist/cli/index.js.map +0 -1
  108. package/dist/core/index.cjs +0 -2589
  109. package/dist/core/index.cjs.map +0 -1
  110. package/dist/core/index.d.cts +0 -139
  111. package/dist/core/index.d.ts +0 -139
  112. package/dist/core/index.global.js +0 -542
  113. package/dist/core/index.js +0 -2560
  114. package/dist/core/index.js.map +0 -1
  115. package/dist/esbuild-plugin/index.cjs +0 -239
  116. package/dist/esbuild-plugin/index.cjs.map +0 -1
  117. package/dist/esbuild-plugin/index.d.cts +0 -26
  118. package/dist/esbuild-plugin/index.d.ts +0 -26
  119. package/dist/esbuild-plugin/index.js +0 -200
  120. package/dist/esbuild-plugin/index.js.map +0 -1
  121. package/dist/vite-plugin/index.d.ts +0 -7
  122. package/dist/vite-plugin/index.js +0 -128
  123. package/dist/vite-plugin/index.js.map +0 -1
  124. package/dist/webpack-plugin/index.cjs +0 -54
  125. package/dist/webpack-plugin/index.cjs.map +0 -1
  126. package/dist/webpack-plugin/index.d.cts +0 -5
  127. package/dist/webpack-plugin/index.d.ts +0 -5
  128. package/dist/webpack-plugin/index.js +0 -23
  129. package/dist/webpack-plugin/index.js.map +0 -1
  130. package/dist/webpack-plugin/loader.cjs +0 -155
  131. package/dist/webpack-plugin/loader.cjs.map +0 -1
  132. package/dist/webpack-plugin/loader.d.cts +0 -3
  133. package/dist/webpack-plugin/loader.d.ts +0 -3
  134. package/dist/webpack-plugin/loader.js +0 -122
  135. package/dist/webpack-plugin/loader.js.map +0 -1
  136. /package/{builders.json → packages/angular-grab/builders.json} +0 -0
  137. /package/{dist → packages/angular-grab/src}/builder/builders/application/schema.json +0 -0
  138. /package/{dist → packages/angular-grab/src}/builder/builders/dev-server/schema.json +0 -0
@@ -0,0 +1,15 @@
1
+ {
2
+ "compilerOptions": {
3
+ "target": "ES2022",
4
+ "module": "ESNext",
5
+ "moduleResolution": "bundler",
6
+ "declaration": true,
7
+ "strict": true,
8
+ "esModuleInterop": true,
9
+ "skipLibCheck": true,
10
+ "outDir": "dist",
11
+ "rootDir": "src",
12
+ "lib": ["ES2022", "DOM", "DOM.Iterable"]
13
+ },
14
+ "include": ["src"]
15
+ }
@@ -0,0 +1,119 @@
1
+ import { defineConfig } from 'tsup';
2
+ import { copyFileSync, mkdirSync, writeFileSync } from 'fs';
3
+ import { resolve } from 'path';
4
+
5
+ export default defineConfig([
6
+ // 1. Core: ESM + CJS + types
7
+ {
8
+ entry: { 'core/index': 'src/core/index.ts' },
9
+ format: ['esm', 'cjs'],
10
+ dts: true,
11
+ clean: true,
12
+ sourcemap: true,
13
+ outDir: 'dist',
14
+ },
15
+ // 2. Core IIFE: browser global
16
+ {
17
+ entry: { 'core/index': 'src/core/index.global.ts' },
18
+ format: ['iife'],
19
+ globalName: 'AngularGrab',
20
+ outDir: 'dist',
21
+ clean: false,
22
+ minify: true,
23
+ },
24
+ // 3. Angular: ESM + types
25
+ {
26
+ entry: { 'angular/index': 'src/angular/index.ts' },
27
+ format: ['esm'],
28
+ dts: true,
29
+ clean: false,
30
+ sourcemap: true,
31
+ outDir: 'dist',
32
+ external: ['@angular/core'],
33
+ },
34
+ // 4. Esbuild plugin: ESM + CJS + types
35
+ {
36
+ entry: { 'esbuild-plugin/index': 'src/esbuild-plugin/index.ts' },
37
+ format: ['esm', 'cjs'],
38
+ dts: true,
39
+ clean: false,
40
+ sourcemap: true,
41
+ outDir: 'dist',
42
+ external: ['esbuild', 'typescript'],
43
+ },
44
+ // 5. Vite plugin: ESM + types
45
+ {
46
+ entry: { 'vite-plugin/index': 'src/vite-plugin/index.ts' },
47
+ format: ['esm'],
48
+ dts: true,
49
+ clean: false,
50
+ sourcemap: true,
51
+ outDir: 'dist',
52
+ external: ['vite'],
53
+ },
54
+ // 6. Webpack plugin + loader: ESM + CJS + types
55
+ {
56
+ entry: {
57
+ 'webpack-plugin/index': 'src/webpack-plugin/index.ts',
58
+ 'webpack-plugin/loader': 'src/webpack-plugin/loader.ts',
59
+ },
60
+ format: ['esm', 'cjs'],
61
+ dts: true,
62
+ clean: false,
63
+ sourcemap: true,
64
+ outDir: 'dist',
65
+ shims: true,
66
+ external: ['webpack'],
67
+ },
68
+ // 7. Builder: CJS only (Angular CLI requirement)
69
+ // Angular CLI uses require() to load builders. Since the root package is
70
+ // "type": "module", we force .js output and write a nested package.json
71
+ // with "type": "commonjs" so Node treats these .js files as CJS.
72
+ {
73
+ entry: {
74
+ 'builder/index': 'src/builder/index.ts',
75
+ 'builder/builders/application/index': 'src/builder/builders/application/index.ts',
76
+ 'builder/builders/dev-server/index': 'src/builder/builders/dev-server/index.ts',
77
+ },
78
+ format: ['cjs'],
79
+ dts: false,
80
+ clean: false,
81
+ sourcemap: true,
82
+ outDir: 'dist',
83
+ outExtension: () => ({ js: '.js' }),
84
+ external: ['@angular/build', '@angular-devkit/architect'],
85
+ onSuccess: async () => {
86
+ const distBuilder = resolve('dist', 'builder');
87
+ mkdirSync(distBuilder, { recursive: true });
88
+
89
+ // Mark dist/builder/ as CommonJS so .js files are loaded via require()
90
+ writeFileSync(
91
+ resolve(distBuilder, 'package.json'),
92
+ JSON.stringify({ type: 'commonjs' }) + '\n',
93
+ );
94
+
95
+ // Copy schema.json files to dist
96
+ const distApp = resolve(distBuilder, 'builders', 'application');
97
+ const distDev = resolve(distBuilder, 'builders', 'dev-server');
98
+ mkdirSync(distApp, { recursive: true });
99
+ mkdirSync(distDev, { recursive: true });
100
+ copyFileSync(
101
+ resolve('src', 'builder', 'builders', 'application', 'schema.json'),
102
+ resolve(distApp, 'schema.json'),
103
+ );
104
+ copyFileSync(
105
+ resolve('src', 'builder', 'builders', 'dev-server', 'schema.json'),
106
+ resolve(distDev, 'schema.json'),
107
+ );
108
+ },
109
+ },
110
+ // 8. CLI: ESM with shebang
111
+ {
112
+ entry: { 'cli/index': 'src/cli/index.ts' },
113
+ format: ['esm'],
114
+ clean: false,
115
+ sourcemap: true,
116
+ outDir: 'dist',
117
+ banner: { js: '#!/usr/bin/env node' },
118
+ },
119
+ ]);
@@ -0,0 +1,3 @@
1
+ packages:
2
+ - "packages/*"
3
+ - "examples/*"
package/turbo.json ADDED
@@ -0,0 +1,21 @@
1
+ {
2
+ "$schema": "https://turbo.build/schema.json",
3
+ "tasks": {
4
+ "build": {
5
+ "dependsOn": ["^build"],
6
+ "outputs": ["dist/**"]
7
+ },
8
+ "dev": {
9
+ "dependsOn": ["^build"],
10
+ "cache": false,
11
+ "persistent": true
12
+ },
13
+ "test": {
14
+ "dependsOn": ["build"]
15
+ },
16
+ "lint": {},
17
+ "clean": {
18
+ "cache": false
19
+ }
20
+ }
21
+ }
@@ -1,151 +0,0 @@
1
- import { InjectionToken, EnvironmentProviders } from '@angular/core';
2
-
3
- declare function resolveComponent(element: Element): {
4
- name: string | null;
5
- hostElement: Element | null;
6
- stack: Array<{
7
- name: string;
8
- hostElement: Element | null;
9
- }>;
10
- };
11
-
12
- declare function resolveSource(element: Element): {
13
- filePath: string | null;
14
- line: number | null;
15
- column: number | null;
16
- };
17
-
18
- type ThemeMode = 'dark' | 'light' | 'system';
19
- /** Serializable subset of ElementContext — no live DOM reference. */
20
- interface HistoryContext {
21
- html: string;
22
- componentName: string | null;
23
- filePath: string | null;
24
- line: number | null;
25
- column: number | null;
26
- componentStack: ComponentStackEntry[];
27
- selector: string;
28
- cssClasses: string[];
29
- }
30
- interface HistoryEntry {
31
- id: string;
32
- context: HistoryContext;
33
- snippet: string;
34
- timestamp: number;
35
- }
36
- interface AngularGrabOptions {
37
- /** Keyboard shortcut to activate. Default: "Meta+C" (Mac) / "Ctrl+C" (Win) */
38
- activationKey: string;
39
- /** Whether activation requires hold or toggle. Default: 'hold' */
40
- activationMode: 'hold' | 'toggle';
41
- /** Milliseconds to hold before activating in hold mode. Default: 0 */
42
- keyHoldDuration: number;
43
- /** Max lines of HTML to include in copied context. Default: 20 */
44
- maxContextLines: number;
45
- /** Master on/off switch. Default: true */
46
- enabled: boolean;
47
- /** Allow activation while focused in input/textarea. Default: false */
48
- enableInInputs: boolean;
49
- /** Only activate in dev mode. Default: true */
50
- devOnly: boolean;
51
- /** Show the floating mini toolbar. Default: true */
52
- showToolbar: boolean;
53
- /** Theme mode for all UI. Default: 'dark' */
54
- themeMode: ThemeMode;
55
- }
56
- interface ComponentStackEntry {
57
- name: string;
58
- filePath: string | null;
59
- line: number | null;
60
- column: number | null;
61
- }
62
- interface ElementContext {
63
- element: Element;
64
- html: string;
65
- componentName: string | null;
66
- filePath: string | null;
67
- line: number | null;
68
- column: number | null;
69
- componentStack: ComponentStackEntry[];
70
- selector: string;
71
- cssClasses: string[];
72
- }
73
- interface PluginHooks {
74
- onActivate?: () => void;
75
- onDeactivate?: () => void;
76
- onElementHover?: (element: Element) => void;
77
- onElementSelect?: (context: ElementContext) => void;
78
- onBeforeCopy?: (context: ElementContext) => void;
79
- onCopySuccess?: (text: string, context: ElementContext, prompt?: string) => void;
80
- onCopyError?: (error: Error) => void;
81
- transformCopyContent?: (text: string, context: ElementContext) => string;
82
- }
83
- interface Theme {
84
- overlayBorderColor: string;
85
- overlayBgColor: string;
86
- labelBgColor: string;
87
- labelTextColor: string;
88
- toastBgColor: string;
89
- toastTextColor: string;
90
- toolbarBgColor: string;
91
- toolbarTextColor: string;
92
- toolbarAccentColor: string;
93
- popoverBgColor: string;
94
- popoverTextColor: string;
95
- popoverBorderColor: string;
96
- }
97
- interface Plugin {
98
- name: string;
99
- hooks?: PluginHooks;
100
- theme?: Partial<Theme>;
101
- options?: Partial<AngularGrabOptions>;
102
- setup?: (api: AngularGrabAPI) => PluginCleanup | void;
103
- }
104
- type PluginCleanup = () => void;
105
- type ComponentResolver = (element: Element) => {
106
- name: string | null;
107
- hostElement: Element | null;
108
- stack?: Array<{
109
- name: string;
110
- hostElement: Element | null;
111
- }>;
112
- } | null;
113
- type SourceResolver = (element: Element) => {
114
- filePath: string | null;
115
- line: number | null;
116
- column: number | null;
117
- } | null;
118
- interface AngularGrabAPI {
119
- activate(): void;
120
- deactivate(): void;
121
- toggle(): void;
122
- isActive(): boolean;
123
- setOptions(opts: Partial<AngularGrabOptions>): void;
124
- registerPlugin(plugin: Plugin): void;
125
- unregisterPlugin(name: string): void;
126
- setComponentResolver(resolver: ComponentResolver): void;
127
- setSourceResolver(resolver: SourceResolver): void;
128
- showToolbar(): void;
129
- hideToolbar(): void;
130
- setThemeMode(mode: ThemeMode): void;
131
- getHistory(): HistoryEntry[];
132
- clearHistory(): void;
133
- dispose(): void;
134
- }
135
-
136
- declare function buildContext(element: Element): ElementContext;
137
-
138
- /**
139
- * Initialize angular-grab. Registers Angular-specific component and source
140
- * resolvers, then returns the API handle. Idempotent — subsequent calls
141
- * return the same instance.
142
- */
143
- declare function initAngularGrab(options?: Partial<AngularGrabOptions>): AngularGrabAPI;
144
- declare function getAngularGrabApi(): AngularGrabAPI | null;
145
- declare function registerAngularGrabPlugin(plugin: Plugin): void;
146
- declare function disposeAngularGrab(): void;
147
-
148
- declare const ANGULAR_GRAB_API: InjectionToken<AngularGrabAPI>;
149
- declare function provideAngularGrab(options?: Partial<AngularGrabOptions>): EnvironmentProviders;
150
-
151
- export { ANGULAR_GRAB_API, buildContext, disposeAngularGrab, getAngularGrabApi, initAngularGrab, provideAngularGrab, registerAngularGrabPlugin, resolveComponent, resolveSource };