inkbridge 0.1.0-beta.2 → 0.1.0-beta.21

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 (178) hide show
  1. package/README.md +108 -25
  2. package/bin/inkbridge.mjs +354 -83
  3. package/code.js +40 -11802
  4. package/manifest.json +1 -0
  5. package/package.json +74 -23
  6. package/scanner/adapter-utils-regression.ts +159 -0
  7. package/scanner/aspect-percent-position-regression.ts +237 -0
  8. package/scanner/aspect-ratio-regression.ts +90 -0
  9. package/scanner/blob-placement-regression.ts +2 -2
  10. package/scanner/block-cache-regression.ts +195 -0
  11. package/scanner/bundle-size-regression.ts +50 -0
  12. package/scanner/child-sizing-matrix-regression.ts +303 -0
  13. package/scanner/cli.ts +342 -13
  14. package/scanner/component-scanner.ts +2108 -174
  15. package/scanner/component-sections-regression.ts +198 -0
  16. package/scanner/compound-classes-lookup-regression.ts +163 -0
  17. package/scanner/css-token-reader-regression.ts +7 -6
  18. package/scanner/css-token-reader.ts +152 -31
  19. package/scanner/cva-jsx-child-fallback-regression.ts +98 -0
  20. package/scanner/cva-master-icon-regression.ts +315 -0
  21. package/scanner/data-attr-prop-alias-regression.ts +129 -0
  22. package/scanner/explicit-size-root-regression.ts +102 -0
  23. package/scanner/font-family-extract-regression.ts +113 -0
  24. package/scanner/font-style-resolver-regression.ts +1 -1
  25. package/scanner/framework-adapter-shadcn-regression.ts +480 -0
  26. package/scanner/full-width-matrix-regression.ts +338 -0
  27. package/scanner/grid-cols-extraction-regression.ts +110 -0
  28. package/scanner/image-src-collector-regression.ts +204 -0
  29. package/scanner/inline-flex-regression.ts +235 -0
  30. package/scanner/input-range-regression.ts +217 -0
  31. package/scanner/instance-rendering-regression.ts +224 -0
  32. package/scanner/jsx-prop-unresolved-regression.ts +178 -0
  33. package/scanner/jsx-text-regression.ts +178 -0
  34. package/scanner/layout-alignment-regression.ts +108 -0
  35. package/scanner/layout-flex-regression.ts +90 -0
  36. package/scanner/layout-mode-regression.ts +71 -0
  37. package/scanner/layout-sizing-regression.ts +227 -0
  38. package/scanner/layout-spacing-regression.ts +135 -0
  39. package/scanner/local-const-className-regression.ts +331 -0
  40. package/scanner/percent-position-regression.ts +105 -0
  41. package/scanner/provider-cascade-regression.ts +224 -0
  42. package/scanner/provider-flatten-regression.ts +235 -0
  43. package/scanner/radial-gradient-regression.ts +1 -1
  44. package/scanner/render-prop-parser-regression.ts +161 -0
  45. package/scanner/ring-utility-regression.ts +153 -0
  46. package/scanner/sandbox-spread-regression.ts +125 -0
  47. package/scanner/selection-pressed-regression.ts +241 -0
  48. package/scanner/size-full-normalization-regression.ts +127 -0
  49. package/scanner/state-classification-regression.ts +175 -0
  50. package/scanner/story-diagnostics-regression.ts +216 -0
  51. package/scanner/story-dimensioning-regression.ts +298 -0
  52. package/scanner/story-render-strategy-regression.ts +205 -0
  53. package/scanner/stretch-to-parent-width-regression.ts +147 -0
  54. package/scanner/svg-fill-parent-regression.ts +98 -0
  55. package/scanner/svg-group-inheritance-regression.ts +166 -0
  56. package/scanner/svg-marker-inline-regression.ts +211 -0
  57. package/scanner/svg-marker-regression.ts +116 -0
  58. package/scanner/tailwind-parser.ts +46 -4
  59. package/scanner/text-resize-matrix-regression.ts +173 -0
  60. package/scanner/transform-math-regression.ts +1 -1
  61. package/scanner/types.ts +26 -2
  62. package/src/cache/frame-cache.ts +150 -0
  63. package/src/cache/index.ts +2 -0
  64. package/src/{component-defs.ts → components/component-defs.ts} +25 -10
  65. package/src/{component-gen.ts → components/component-gen.ts} +43 -116
  66. package/src/components/component-instance.ts +386 -0
  67. package/src/components/component-library.ts +44 -0
  68. package/src/components/component-lookup.ts +161 -0
  69. package/src/components/index.ts +7 -0
  70. package/src/components/scanner-types.ts +39 -0
  71. package/src/components/symbol-instance-policy.ts +312 -0
  72. package/src/design-system/block-cache.ts +130 -0
  73. package/src/design-system/component-sections.ts +107 -0
  74. package/src/design-system/cva-inference.ts +187 -0
  75. package/src/design-system/cva-master.ts +427 -0
  76. package/src/design-system/cva-utils.ts +29 -0
  77. package/src/design-system/design-system.ts +334 -0
  78. package/src/design-system/frame-stabilizers.ts +191 -0
  79. package/src/design-system/frame-utils.ts +46 -0
  80. package/src/design-system/generated-node.ts +84 -0
  81. package/src/design-system/icon-rendering.ts +229 -0
  82. package/src/design-system/index.ts +13 -0
  83. package/src/design-system/instance-rendering.ts +307 -0
  84. package/src/design-system/master-shared.ts +133 -0
  85. package/src/design-system/node-helpers.ts +237 -0
  86. package/src/design-system/node-variants.ts +196 -0
  87. package/src/design-system/non-cva-master.ts +104 -0
  88. package/src/design-system/portal-handling.ts +138 -0
  89. package/src/design-system/preview-builder.ts +738 -0
  90. package/src/{render-context.ts → design-system/render-context.ts} +32 -6
  91. package/src/design-system/render-prop-parser.ts +50 -0
  92. package/src/design-system/responsive-resolver.ts +180 -0
  93. package/src/design-system/selectable-state.ts +157 -0
  94. package/src/design-system/state-master.ts +267 -0
  95. package/src/design-system/state-utils.ts +15 -0
  96. package/src/design-system/story-builder-context.ts +40 -0
  97. package/src/design-system/story-builder.ts +1322 -0
  98. package/src/design-system/story-diagnostics.ts +80 -0
  99. package/src/design-system/story-dimensioning.ts +272 -0
  100. package/src/design-system/story-frames.ts +400 -0
  101. package/src/design-system/story-instance.ts +333 -0
  102. package/src/{story-layout.ts → design-system/story-layout.ts} +2 -2
  103. package/src/design-system/story-render-strategy.ts +150 -0
  104. package/src/design-system/story-tree-search.ts +110 -0
  105. package/src/design-system/symbol-fallback.ts +89 -0
  106. package/src/design-system/symbol-source.ts +172 -0
  107. package/src/design-system/table-helpers.ts +56 -0
  108. package/src/design-system/tag-predicates.ts +99 -0
  109. package/src/design-system/theme-context.ts +52 -0
  110. package/src/design-system/typography.ts +100 -0
  111. package/src/design-system/ui-builder.ts +2676 -0
  112. package/src/{clip-path-decorative.ts → effects/clip-path-decorative.ts} +11 -11
  113. package/src/effects/icon-builder.ts +1074 -0
  114. package/src/effects/index.ts +5 -0
  115. package/src/effects/portal-panel.ts +369 -0
  116. package/src/{radial-gradient.ts → effects/radial-gradient.ts} +1 -1
  117. package/src/framework-adapters/index.ts +47 -0
  118. package/src/framework-adapters/shadcn.ts +541 -0
  119. package/src/{github.ts → github/github.ts} +46 -21
  120. package/src/github/index.ts +1 -0
  121. package/src/layout/deferred-layout.ts +1556 -0
  122. package/src/layout/index.ts +24 -0
  123. package/src/layout/layout-parser.ts +375 -0
  124. package/src/{layout-utils.ts → layout/layout-utils.ts} +23 -17
  125. package/src/layout/parser/alignment.ts +54 -0
  126. package/src/layout/parser/flex.ts +59 -0
  127. package/src/layout/parser/index.ts +65 -0
  128. package/src/layout/parser/ir.ts +80 -0
  129. package/src/layout/parser/layout-mode.ts +57 -0
  130. package/src/layout/parser/sizing.ts +241 -0
  131. package/src/layout/parser/spacing-scale.ts +78 -0
  132. package/src/layout/parser/spacing.ts +134 -0
  133. package/src/layout/ring-utils.ts +120 -0
  134. package/src/layout/size-utils.ts +143 -0
  135. package/src/layout/text-resize-decision.ts +51 -0
  136. package/src/{width-solver.ts → layout/width-solver.ts} +168 -37
  137. package/src/main.ts +444 -162
  138. package/src/{config.ts → plugin/config.ts} +12 -12
  139. package/src/{dev-server.ts → plugin/dev-server.ts} +3 -3
  140. package/src/plugin/image-src-collector.ts +52 -0
  141. package/src/plugin/index.ts +3 -0
  142. package/src/plugin/packs/index.ts +2 -0
  143. package/src/{pack-provider.ts → plugin/packs/pack-provider.ts} +12 -12
  144. package/src/{packs.ts → plugin/packs/packs.ts} +22 -17
  145. package/src/render-engine-version.ts +2 -0
  146. package/src/tailwind/adapter-utils.ts +137 -0
  147. package/src/{class-utils.ts → tailwind/class-utils.ts} +33 -6
  148. package/src/tailwind/index.ts +8 -0
  149. package/src/tailwind/jsx-utils.ts +319 -0
  150. package/src/{node-ir.ts → tailwind/node-ir.ts} +208 -19
  151. package/src/{responsive-analyzer.ts → tailwind/responsive-analyzer.ts} +32 -2
  152. package/src/{state-analyzer.ts → tailwind/state-analyzer.ts} +71 -5
  153. package/src/{tailwind.ts → tailwind/tailwind.ts} +423 -674
  154. package/src/{utility-resolver.ts → tailwind/utility-resolver.ts} +27 -6
  155. package/src/{font-style-resolver.ts → text/font-style-resolver.ts} +0 -2
  156. package/src/text/index.ts +4 -0
  157. package/src/{inline-text.ts → text/inline-text.ts} +13 -13
  158. package/src/{text-builder.ts → text/text-builder.ts} +24 -7
  159. package/src/{text-line.ts → text/text-line.ts} +2 -2
  160. package/src/{change-detection.ts → tokens/change-detection.ts} +12 -12
  161. package/src/{color-resolver.ts → tokens/color-resolver.ts} +1 -6
  162. package/src/{colors.ts → tokens/colors.ts} +13 -6
  163. package/src/tokens/index.ts +6 -0
  164. package/src/{token-source.ts → tokens/token-source.ts} +4 -1
  165. package/src/{tokens.ts → tokens/tokens.ts} +116 -20
  166. package/src/{variables.ts → tokens/variables.ts} +447 -102
  167. package/templates/patch-tokens-route.ts +25 -6
  168. package/templates/scan-components-route.ts +26 -5
  169. package/ui.html +485 -37
  170. package/src/component-lookup.ts +0 -82
  171. package/src/design-system.ts +0 -59
  172. package/src/icon-builder.ts +0 -607
  173. package/src/layout-parser.ts +0 -667
  174. package/src/story-builder.ts +0 -1706
  175. package/src/ui-builder.ts +0 -1996
  176. /package/src/{image-cache.ts → cache/image-cache.ts} +0 -0
  177. /package/src/{blob-placement.ts → effects/blob-placement.ts} +0 -0
  178. /package/src/{transform-math.ts → tailwind/transform-math.ts} +0 -0
package/README.md CHANGED
@@ -1,12 +1,18 @@
1
+ <img src="https://inkbridge.ink/inkbridge-logo.png" alt="Inkbridge" width="80" />
2
+
1
3
  # Inkbridge
2
4
 
3
- Generates native Figma frames from your Tailwind React components and syncs design tokens back to your codebase via GitHub PRs.
5
+ Generates native Figma frames and reusable Figma component instances from your Tailwind React components, and syncs design tokens back to your codebase via GitHub PRs.
6
+
7
+ <img src="https://inkbridge.ink/docs/mediacards-figma.png" alt="An Inkbridge-generated Figma page showing component variants rendered as native Figma frames" />
8
+
9
+ > Read the methodology behind this — stories as the single source of truth between design and code: [inkbridge.ink/methodology](https://inkbridge.ink/methodology). Browse the full docs at [inkbridge.ink/docs](https://inkbridge.ink/docs).
4
10
 
5
11
  ## What it does
6
12
 
7
13
  | Feature | Description |
8
14
  |---|---|
9
- | **Generate Design System Page** | Scans your Storybook stories and builds a pixel-accurate Figma page from your Tailwind classes |
15
+ | **Generate Design System Page** | Scans your Storybook stories and builds a pixel-accurate Figma page from your Tailwind classes, including reusable component instances for symbol candidates (CVA and non-CVA) |
10
16
  | **Push to Code** | Creates a GitHub PR from Figma token changes. Source can be CSS-first (`auto`/`css`) or DTCG (`dtcg`). |
11
17
  | **Detect & Sync Changes** | Detects class-level changes in Figma frames and proposes them as a GitHub PR |
12
18
  | **Dev Mode codegen** | Shows Tailwind class names for any selected node in Figma Dev Mode |
@@ -17,7 +23,7 @@ Generates native Figma frames from your Tailwind React components and syncs desi
17
23
 
18
24
  - **Figma Desktop** (not the browser — the plugin needs localhost access)
19
25
  - **Node.js 18+** and **pnpm**
20
- - A project with Next.js, Tailwind CSS, and Storybook stories (`.stories.tsx`)
26
+ - A project with Next.js, Tailwind CSS, and Storybook stories (`.stories.tsx` or `.stories.ts`)
21
27
 
22
28
  ---
23
29
 
@@ -30,11 +36,16 @@ pnpm add -D inkbridge
30
36
  pnpm exec inkbridge setup
31
37
  ```
32
38
 
33
- `setup` does three things automatically:
34
- - Creates `inkbridge.config.json` in your project root (auto-detects component paths from `.storybook/main.ts`)
35
- - Creates the scanner API route at `src/app/api/figma/scan-components/route.ts`
36
- - Creates the token patch API route at `src/app/api/figma/patch-tokens/route.ts`
37
- - Adds `figma:dev` and `figma:scan` scripts to your `package.json`
39
+ `pnpm exec inkbridge setup` is the only required step after install. It prints exactly what it will change before writing anything (run with `--dry-run` to preview without applying, or `--force` to refresh route templates and `inkbridge.config.json` after a plugin update):
40
+
41
+ - Creates `inkbridge.config.json` in your project root (auto-detects component paths from `.storybook/main.*`)
42
+ - Creates the scanner API route at `src/app/api/inkbridge/scan-components/route.ts`
43
+ - Creates the token patch API route at `src/app/api/inkbridge/patch-tokens/route.ts`
44
+ - Adds `inkbridge:dev` and `inkbridge:scan` scripts to your `package.json`
45
+ - Adds `headers()` to your `next.config.*` exposing CORS on `/api/inkbridge/:path*` so the Figma plugin iframe can reach those routes (scoped — your other routes are untouched)
46
+ - Appends `.inkbridge/` to your `.gitignore` so the scanner-output JSON doesn't show up in every diff
47
+
48
+ Inkbridge does not modify your ESLint config or any other tooling. The recommended `react/forbid-dom-props` rule for inline styles is suggested in "Recommended lint rules" below, but never written by setup.
38
49
 
39
50
  ### 2. Load the plugin in Figma Desktop
40
51
 
@@ -47,7 +58,7 @@ Figma remembers this path — you only do this once.
47
58
  ### 3. Start your dev server
48
59
 
49
60
  ```bash
50
- pnpm figma:dev
61
+ pnpm inkbridge:dev
51
62
  ```
52
63
 
53
64
  The plugin auto-discovers your server on ports `4000`, `3000`, and `5173`.
@@ -60,24 +71,32 @@ The plugin auto-discovers your server on ports `4000`, `3000`, and `5173`.
60
71
 
61
72
  ### Generate Design System Page
62
73
 
63
- 1. Start dev server: `pnpm figma:dev`
74
+ 1. Start dev server: `pnpm inkbridge:dev`
64
75
  2. Open any Figma file
65
76
  3. **Plugins → Development → Inkbridge → Generate Design System Page**
66
- 4. The plugin scans your Storybook stories and builds a "Design System" page
77
+ 4. The plugin scans your Storybook stories and builds a "Design System" page with token tables, themed columns, grouped component sections, and responsive/state preview blocks where relevant
67
78
 
68
79
  Component data is always scanned live on every run — never stale. Re-run at any time to pick up changes.
69
80
 
81
+ For symbol candidates, the generated page renders real Figma component instances instead of only flattened frames:
82
+
83
+ - CVA components (for example `Button`) render as variant-aware instances.
84
+ - Non-CVA reusable components (for example `Card` compounds) can render as instances too.
85
+ - For compound instances, story text is applied by slot-aware overrides (for example title/description/content) when possible.
86
+
87
+ When a story instance uses non-default style/behavior props (for example `className`, `disabled`, `aria-invalid`, or unknown props), rendering falls back to direct frames for visual correctness.
88
+
70
89
  ### Manual scan
71
90
 
72
91
  ```bash
73
- pnpm figma:scan
92
+ pnpm inkbridge:scan
74
93
  ```
75
94
 
76
95
  Writes `.inkbridge/component-definitions.json`. Useful for debugging scanner output.
77
96
 
78
- ### Push to Code (Pro)
97
+ ### Push to Code
79
98
 
80
- Requires a Pro license and GitHub configuration.
99
+ Sync token edits from Figma back to your codebase as a GitHub PR.
81
100
 
82
101
  1. **Plugins → Development → Inkbridge → Settings**
83
102
  2. Fill in:
@@ -91,7 +110,6 @@ Requires a Pro license and GitHub configuration.
91
110
  - **Allow New Tokens from Figma** — optional; permits creating new token keys on push (off by default)
92
111
  - **New Token Prefixes** — optional comma-separated allowlist (for example `chart-, brand-`)
93
112
  - **GitHub token** — a [fine-grained PAT](https://github.com/settings/tokens?type=beta) with `Contents` and `Pull requests` read & write
94
- - **License key** — from your Inkbridge account
95
113
  3. **Save Settings**
96
114
  4. **Plugins → Development → Inkbridge → Push to Code**
97
115
  5. Enter a commit message and click **Push Tokens to Code** (it auto-detects token changes and opens the PR step)
@@ -115,31 +133,95 @@ Edit `inkbridge.config.json` in your project root:
115
133
  |---|---|---|
116
134
  | `componentPaths` | auto-detected | Directories to scan for components |
117
135
  | `exclude` | `[]` | Directory or file names to skip |
118
- | `onlyWithStories` | `true` | Only include components with a `.stories.tsx` file |
136
+ | `onlyWithStories` | `true` | Only include components with a `.stories.tsx` or `.stories.ts` file |
119
137
 
120
138
  The scanner re-reads this file on every scan — no server restart needed.
121
139
 
122
140
  ---
123
141
 
142
+ ## Supported styling
143
+
144
+ Inkbridge reads styling from **Tailwind class names** (`className="…"`).
145
+ The Figma renderer is built to handle the breadth of Tailwind utilities:
146
+ flex / grid layouts, responsive variants (`sm:`, `md:`, `lg:`, …),
147
+ arbitrary values (`left-[18.33%]`, `aspect-5/3`), color / spacing
148
+ tokens, and SVG attribute inheritance.
149
+
150
+ ### What's not supported yet
151
+
152
+ - **Inline `style={{ … }}` props.** Currently ignored by the renderer.
153
+ If you set `style={{ color: '#0a0', padding: 8 }}` on an element, the
154
+ Figma rendering will use whatever the Tailwind class list says — your
155
+ inline overrides won't be applied. Use Tailwind utilities or arbitrary
156
+ values instead (`text-[#0a0] p-2`). A consumer-side ESLint rule
157
+ (`react/forbid-dom-props` + `react/forbid-component-props`) is
158
+ recommended to catch this — see "Recommended lint rules" below.
159
+
160
+ - **CSS variables in arbitrary classes** (`text-[var(--accent)]`) —
161
+ not yet resolved through the scanner's token map; the literal CSS
162
+ variable name reaches Figma and renders as black. Use a Tailwind
163
+ token alias (`text-accent`) instead.
164
+
165
+ - **`<g transform="…">`** — the transform isn't composed onto child
166
+ positions yet, so paths inside a transformed group render at their
167
+ pre-transform coordinates.
168
+
169
+ - **`clip-path` / `mask` on `<g>`** — clipping is honored at the
170
+ element level (`overflow-hidden`, `clip-path-decorative-*`) but not
171
+ via SVG `<g clip-path="url(…)">`.
172
+
173
+ These are tracked as universality enhancements. File an issue if one
174
+ blocks you and we'll prioritize.
175
+
176
+ ### Recommended lint rules
177
+
178
+ Until inline-style support lands, add these rules to your project's
179
+ ESLint config so you don't accidentally rely on patterns the plugin
180
+ ignores:
181
+
182
+ ```json
183
+ {
184
+ "rules": {
185
+ "react/forbid-dom-props": ["error", {
186
+ "forbid": [{
187
+ "propName": "style",
188
+ "message": "Use Tailwind classes — Inkbridge ignores inline styles."
189
+ }]
190
+ }],
191
+ "react/forbid-component-props": ["error", {
192
+ "forbid": [{
193
+ "propName": "style",
194
+ "message": "Use Tailwind classes — Inkbridge ignores inline styles."
195
+ }]
196
+ }]
197
+ }
198
+ }
199
+ ```
200
+
201
+ Skip this rule on any component where Figma rendering doesn't matter
202
+ (e.g. animation-only effects).
203
+
204
+ ---
205
+
124
206
  ## Troubleshooting
125
207
 
126
208
  ### "Dev server not reachable"
127
209
 
128
210
  The plugin cannot connect to `localhost:4000`, `:3000`, or `:5173`.
129
211
 
130
- - Make sure `pnpm figma:dev` is running
212
+ - Make sure `pnpm inkbridge:dev` is running
131
213
  - Check the terminal for errors in the Next.js server
132
214
  - Make sure you're using **Figma Desktop** — the browser version blocks localhost
133
215
 
134
216
  ### "Create Pull Request" does nothing / no PR opens
135
217
 
136
- - Restart your dev server (`pnpm figma:dev`) so `/api/figma/patch-tokens` is available
218
+ - Restart your dev server (`pnpm inkbridge:dev`) so `/api/inkbridge/patch-tokens` is available
137
219
  - Re-import the plugin from `node_modules/inkbridge/manifest.json` after updating
138
220
  - Re-open the plugin and retry **Push Tokens to Code**
139
221
 
140
222
  ### Theme rename/new theme only commits one changed token
141
223
 
142
- - Ensure your project route `src/app/api/figma/patch-tokens/route.ts` is up to date:
224
+ - Ensure your project route `src/app/api/inkbridge/patch-tokens/route.ts` is up to date:
143
225
 
144
226
  ```bash
145
227
  pnpm exec inkbridge setup
@@ -184,15 +266,16 @@ Component data is always scanned live — you only need to update when a new `in
184
266
 
185
267
  ```
186
268
  Figma plugin (sandboxed)
187
- └── code.js Main logic — cannot make network requests directly
188
- └── ui.html Hidden iframe — relays all network requests to code.js
269
+ └── code.js Main logic — no direct network access
270
+ └── ui.html Hidden iframe — relays I/O for code.js
189
271
 
190
- code.js ui.html localhost:4000/api/figma/scan-components
191
- localhost:4000/api/figma/patch-tokens
192
- https://api.github.com
272
+ code.js ui.html localhost:4000/api/inkbridge/scan-components
273
+ localhost:4000/api/inkbridge/patch-tokens
274
+ https://api.github.com
193
275
  ```
194
276
 
195
- All network I/O is relayed through the UI iframe via `postMessage` due to the Figma sandbox restriction.
277
+ All network I/O is relayed through the UI iframe via `postMessage`
278
+ because the Figma plugin sandbox can't make requests directly.
196
279
 
197
280
  ---
198
281