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
@@ -0,0 +1,267 @@
1
+ import { findChildByName, getFrameHash, setFrameHash, hashString, hashDef } from '../cache';
2
+ import { enforceFixedBoxSizingAfterLayout, applyRingIfPossible, getRingNode, markRingNode } from '../layout';
3
+ import { splitClassName } from '../tailwind';
4
+ import { RENDER_ENGINE_VERSION } from '../render-engine-version';
5
+ import { tagGeneratedNode } from './generated-node';
6
+ import { getThemeContext } from './theme-context';
7
+ import {
8
+ ENABLE_SYMBOL_MASTERS,
9
+ toFigmaVariantPropertyName,
10
+ toFigmaVariantPropertyValue,
11
+ ensureThemeComponentLibrary,
12
+ } from './master-shared';
13
+ import { isTruthyStateProp } from './state-utils';
14
+ import { createStateStoryFrame } from './story-frames';
15
+ import type { StoryBuilderContext } from './story-builder-context';
16
+
17
+ /**
18
+ * State-master logic: creating Figma component sets that represent the
19
+ * default / hover / disabled / error / checked variants of state-typed
20
+ * components (Input, Checkbox, Switch, …).
21
+ */
22
+
23
+ export { isTruthyStateProp };
24
+
25
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
26
+ export function shouldCreateStateMaster(def: any): boolean {
27
+ if (!def || def.type !== 'state') return false;
28
+ if (def.symbolCandidate === false) return false;
29
+ const states = def && def.states ? def.states : {};
30
+ const stateNames = Object.keys(states);
31
+ return stateNames.length > 0;
32
+ }
33
+
34
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
35
+ export function buildStateComponentSetHash(def: any, theme: string): string {
36
+ const themeContext = getThemeContext(theme);
37
+ return hashString(
38
+ hashDef(def)
39
+ + ':'
40
+ + theme
41
+ + ':state-component-set-v3:'
42
+ + RENDER_ENGINE_VERSION
43
+ + ':'
44
+ + JSON.stringify({
45
+ colorGroup: themeContext.colorGroup,
46
+ radiusGroup: themeContext.radiusGroup,
47
+ })
48
+ );
49
+ }
50
+
51
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
52
+ export function getStateVariantNames(def: any): string[] {
53
+ const out: string[] = ['default'];
54
+ const states = def && def.states ? def.states : {};
55
+ const names = Object.keys(states);
56
+ for (let i = 0; i < names.length; i++) {
57
+ const name = String(names[i] || '').trim();
58
+ if (!name || name === 'default') continue;
59
+ if (out.indexOf(name) !== -1) continue;
60
+ out.push(name);
61
+ }
62
+ return out;
63
+ }
64
+
65
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
66
+ export function hasCheckedStateVariant(def: any): boolean {
67
+ const names = getStateVariantNames(def);
68
+ for (let i = 0; i < names.length; i++) {
69
+ if (names[i].toLowerCase() === 'checked') return true;
70
+ }
71
+ return false;
72
+ }
73
+
74
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
75
+ export function getVisualStateVariantNames(def: any): string[] {
76
+ const all = getStateVariantNames(def);
77
+ const out: string[] = [];
78
+ for (let i = 0; i < all.length; i++) {
79
+ const name = all[i];
80
+ if (name.toLowerCase() === 'checked') continue;
81
+ out.push(name);
82
+ }
83
+ if (out.length === 0) out.push('default');
84
+ return out;
85
+ }
86
+
87
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
88
+ export function resolveStateVariantName(def: any, requested: unknown, includeChecked: boolean = true): string {
89
+ const requestedName = String(requested == null ? '' : requested).trim().toLowerCase();
90
+ const available = includeChecked ? getStateVariantNames(def) : getVisualStateVariantNames(def);
91
+ for (let i = 0; i < available.length; i++) {
92
+ if (available[i].toLowerCase() === requestedName) return available[i];
93
+ }
94
+ return 'default';
95
+ }
96
+
97
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
98
+ export function isCheckedInstance(instance: any): boolean {
99
+ const props = instance && instance.props ? instance.props : {};
100
+ return isTruthyStateProp(props.checked)
101
+ || isTruthyStateProp(props.defaultChecked)
102
+ || isTruthyStateProp(props['aria-checked']);
103
+ }
104
+
105
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
106
+ export function getStateVariantForInstance(def: any, instance: any): string {
107
+ const props = instance && instance.props ? instance.props : {};
108
+ const explicitState = props['data-state'] != null ? props['data-state'] : props.state;
109
+ if (explicitState != null && String(explicitState).trim() !== '') {
110
+ return resolveStateVariantName(def, explicitState, false);
111
+ }
112
+ if (isTruthyStateProp(props.disabled) || isTruthyStateProp(props['aria-disabled'])) {
113
+ return resolveStateVariantName(def, 'disabled', false);
114
+ }
115
+ if (isTruthyStateProp(props['aria-invalid'])) {
116
+ return resolveStateVariantName(def, 'error', false);
117
+ }
118
+ return 'default';
119
+ }
120
+
121
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
122
+ export function buildStateVariantProps(def: any, stateName: string, checked: boolean): Record<string, any> {
123
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
124
+ const props: Record<string, any> = {};
125
+ const normalized = resolveStateVariantName(def, stateName, false);
126
+ const stateInfo = def && def.states && def.states[normalized] ? def.states[normalized] : null;
127
+ const stateClasses = stateInfo && Array.isArray(stateInfo.classes) ? stateInfo.classes : [];
128
+ const checkedState = def && def.states && def.states.checked ? def.states.checked : null;
129
+ const checkedClasses = checkedState && Array.isArray(checkedState.classes) ? checkedState.classes : [];
130
+ const mergedClasses = checked ? stateClasses.concat(checkedClasses) : stateClasses;
131
+ if (mergedClasses.length > 0) {
132
+ props.className = mergedClasses.join(' ');
133
+ }
134
+ if (checked) {
135
+ props.checked = 'true';
136
+ }
137
+ if (normalized === 'disabled') {
138
+ props.disabled = 'true';
139
+ } else if (normalized === 'error') {
140
+ props['aria-invalid'] = 'true';
141
+ } else if (normalized === 'open') {
142
+ props['data-state'] = 'open';
143
+ }
144
+ return props;
145
+ }
146
+
147
+ export function ensureStateComponentSet(
148
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
149
+ def: any,
150
+ theme: string,
151
+ ctx: StoryBuilderContext
152
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
153
+ ): any | null {
154
+ if (!ENABLE_SYMBOL_MASTERS) return null;
155
+ if (!shouldCreateStateMaster(def)) return null;
156
+
157
+ const stateNames = getVisualStateVariantNames(def);
158
+ if (stateNames.length === 0) return null;
159
+ const includeChecked = hasCheckedStateVariant(def);
160
+
161
+ const themeLibrary = ensureThemeComponentLibrary(theme);
162
+ if (!themeLibrary) return null;
163
+
164
+ const setName = def.name + ' [' + theme + ']';
165
+ const masterHash = buildStateComponentSetHash(def, theme);
166
+ const existing = findChildByName(themeLibrary, setName);
167
+ if (existing && existing.type === 'COMPONENT_SET' && getFrameHash(existing) === masterHash) {
168
+ return existing;
169
+ }
170
+ if (existing) {
171
+ existing.remove();
172
+ }
173
+
174
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
175
+ const components: any[] = [];
176
+ const checkedValues = includeChecked ? [false, true] : [false];
177
+ for (let i = 0; i < stateNames.length; i++) {
178
+ const stateName = stateNames[i];
179
+ for (let ci = 0; ci < checkedValues.length; ci++) {
180
+ const checked = checkedValues[ci];
181
+ const stateVariantProps = buildStateVariantProps(def, stateName, checked);
182
+ const sourceNode = createStateStoryFrame(
183
+ def,
184
+ { props: stateVariantProps },
185
+ theme,
186
+ ctx
187
+ );
188
+ themeLibrary.appendChild(sourceNode);
189
+
190
+ // `createStateStoryFrame` → `applyTailwindStylesToFrame` calls
191
+ // `markRingNode(sourceNode, ringInfo)` for ring classes. We must
192
+ // capture that ring info BEFORE `createComponentFromNode` — it
193
+ // creates a NEW node identity, so the `RING_NODES` WeakMap entry
194
+ // keyed on `sourceNode` is unreachable from the resulting component.
195
+ // Without this transfer the focus / error variants of state masters
196
+ // (Input, Textarea) render with no ring overlay — only the host's
197
+ // 1px border shows. Confirmed 2026-05-17 from a side-by-side
198
+ // Storybook (correct: 1px border + 3px halo) vs Figma (broken: 1px
199
+ // border alone) comparison.
200
+ const ringInfo = getRingNode(sourceNode);
201
+
202
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
203
+ let component: any = null;
204
+ try {
205
+ component = figma.createComponentFromNode(sourceNode);
206
+ } catch (_error) {
207
+ try {
208
+ sourceNode.remove();
209
+ } catch (_cleanupError) {
210
+ // ignore cleanup errors
211
+ }
212
+ continue;
213
+ }
214
+ if (!component) continue;
215
+ // Transfer the captured ring mark onto the new component identity.
216
+ if (ringInfo) {
217
+ markRingNode(component, ringInfo);
218
+ }
219
+ enforceFixedBoxSizingAfterLayout(
220
+ component,
221
+ splitClassName(stateVariantProps && stateVariantProps.className ? String(stateVariantProps.className) : '')
222
+ );
223
+ // Now that the component's dimensions are finalised by
224
+ // `enforceFixedBoxSizingAfterLayout`, build the ring overlay against
225
+ // those final dimensions. Idempotent: if the comp already has an
226
+ // `__inkbridge-ring__` child from an earlier pass, it's removed and
227
+ // recreated at the correct size.
228
+ applyRingIfPossible(component as unknown as FrameNode, themeLibrary);
229
+
230
+ const nameParts = [
231
+ toFigmaVariantPropertyName('state') + '=' + toFigmaVariantPropertyValue(stateName),
232
+ ];
233
+ if (includeChecked) {
234
+ nameParts.push(toFigmaVariantPropertyName('checked') + '=' + toFigmaVariantPropertyValue(String(checked)));
235
+ }
236
+ component.name = nameParts.join(', ');
237
+ component.visible = false;
238
+ if (component.parent !== themeLibrary) {
239
+ themeLibrary.appendChild(component);
240
+ }
241
+ components.push(component);
242
+ }
243
+ }
244
+
245
+ if (components.length === 0) return null;
246
+
247
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
248
+ let componentSet: any = null;
249
+ try {
250
+ componentSet = figma.combineAsVariants(components, themeLibrary);
251
+ } catch (_error) {
252
+ for (let i = 0; i < components.length; i++) {
253
+ try {
254
+ components[i].remove();
255
+ } catch (_cleanupError) {
256
+ // ignore cleanup errors
257
+ }
258
+ }
259
+ return null;
260
+ }
261
+
262
+ componentSet.name = setName;
263
+ componentSet.visible = false;
264
+ setFrameHash(componentSet, masterHash);
265
+ tagGeneratedNode(componentSet, 'state-component-set:' + def.name + ':' + theme);
266
+ return componentSet;
267
+ }
@@ -0,0 +1,15 @@
1
+ /**
2
+ * Predicate for "is this prop value truthy by HTML/JSX conventions?"
3
+ *
4
+ * Originally lived as two near-duplicates: `isTruthyStateProp` (in
5
+ * state-master) and `isTruthyBoolProp` (in ui-builder). They differed only
6
+ * in whether they trimmed whitespace; the trimming version is correct
7
+ * because attributes can carry leading/trailing whitespace through JSX.
8
+ * Both call sites now use this one function.
9
+ */
10
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
11
+ export function isTruthyStateProp(value: any): boolean {
12
+ if (value == null) return false;
13
+ const normalized = String(value).trim().toLowerCase();
14
+ return normalized !== '' && normalized !== 'false' && normalized !== '0' && normalized !== 'off';
15
+ }
@@ -0,0 +1,40 @@
1
+ import type { RGB } from '../tokens';
2
+ import type { JsxNode } from '../tailwind';
3
+ import type { ComponentDef } from '../components/scanner-types';
4
+
5
+ export type StoryRenderContext = {
6
+ maxWidth?: number;
7
+ /** Story-level viewport width for responsive breakpoint resolution. */
8
+ viewportWidth?: number;
9
+ textAlign?: 'LEFT' | 'CENTER' | 'RIGHT';
10
+ parentLayout?: 'HORIZONTAL' | 'VERTICAL';
11
+ textColor?: string | RGB | null;
12
+ textColorToken?: string;
13
+ parentCompoundDef?: unknown;
14
+ };
15
+
16
+ export type StoryBuilderContext = {
17
+ getComponentDefByName: (name: string) => ComponentDef | null;
18
+ normalizeComponentDef: (raw: ComponentDef) => ComponentDef;
19
+ applyClipBehavior: (frame: FrameNode, classes: string[] | undefined) => void;
20
+ applyLayoutClasses: (
21
+ frame: FrameNode,
22
+ classes: string[] | undefined,
23
+ colorGroup: Record<string, string>,
24
+ radiusGroup: Record<string, string> | null,
25
+ theme: string
26
+ ) => void;
27
+ hasExplicitHeight: (classes: string[] | undefined) => boolean;
28
+ renderJsxTree: (
29
+ node: JsxNode,
30
+ colorGroup: Record<string, string>,
31
+ radiusGroup: Record<string, string> | null,
32
+ theme: string,
33
+ depth?: number,
34
+ context?: StoryRenderContext
35
+ ) => SceneNode | null;
36
+ applyAbsoluteIfAllowed: (child: SceneNode, parent: FrameNode, allowAbsolute: boolean) => void;
37
+ applyGridColumnsWithReflow: (frame: FrameNode, widthOverride?: number, colsOverride?: number) => void;
38
+ hasWidthHintInClasses: (classes: string[]) => boolean;
39
+ propsContainWidthHint: (props: Record<string, unknown> | undefined) => boolean;
40
+ };