@discourser/design-system 0.15.1 → 0.17.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.
Files changed (179) hide show
  1. package/dist/{chunk-UNWXE6UB.cjs → chunk-2P7Z5PVP.cjs} +817 -16
  2. package/dist/chunk-2P7Z5PVP.cjs.map +1 -0
  3. package/dist/{chunk-ABC7N32K.cjs → chunk-PFWU7QSM.cjs} +464 -8
  4. package/dist/chunk-PFWU7QSM.cjs.map +1 -0
  5. package/dist/{chunk-GD6Q2FUE.js → chunk-QC7LGFM3.js} +808 -18
  6. package/dist/chunk-QC7LGFM3.js.map +1 -0
  7. package/dist/{chunk-SBKRSXSZ.js → chunk-SNUJBT5R.js} +464 -8
  8. package/dist/chunk-SNUJBT5R.js.map +1 -0
  9. package/dist/components/Accordion.figma.d.ts +2 -0
  10. package/dist/components/Accordion.figma.d.ts.map +1 -0
  11. package/dist/components/Breadcrumb.d.ts +2 -0
  12. package/dist/components/Breadcrumb.d.ts.map +1 -1
  13. package/dist/components/Breadcrumb.figma.d.ts +2 -0
  14. package/dist/components/Breadcrumb.figma.d.ts.map +1 -0
  15. package/dist/components/ContentCard/ContentCard.d.ts +13 -0
  16. package/dist/components/ContentCard/ContentCard.d.ts.map +1 -0
  17. package/dist/components/ContentCard/ContentCard.figma.d.ts +2 -0
  18. package/dist/components/ContentCard/ContentCard.figma.d.ts.map +1 -0
  19. package/dist/components/ContentCard/index.d.ts +2 -0
  20. package/dist/components/ContentCard/index.d.ts.map +1 -0
  21. package/dist/components/{Heading.d.ts → Header.d.ts} +3 -3
  22. package/dist/components/Header.d.ts.map +1 -0
  23. package/dist/components/Header.figma.d.ts +2 -0
  24. package/dist/components/Header.figma.d.ts.map +1 -0
  25. package/dist/components/Icons/AccountIcon.d.ts +6 -0
  26. package/dist/components/Icons/AccountIcon.d.ts.map +1 -0
  27. package/dist/components/Icons/ChevronUpIcon.d.ts +6 -0
  28. package/dist/components/Icons/ChevronUpIcon.d.ts.map +1 -0
  29. package/dist/components/Icons/ClockIcon.d.ts.map +1 -1
  30. package/dist/components/Icons/DashboardIcon.d.ts +6 -0
  31. package/dist/components/Icons/DashboardIcon.d.ts.map +1 -0
  32. package/dist/components/Icons/DiscourserLogo.d.ts +6 -0
  33. package/dist/components/Icons/DiscourserLogo.d.ts.map +1 -0
  34. package/dist/components/Icons/DiscourserLogo.figma.d.ts +2 -0
  35. package/dist/components/Icons/DiscourserLogo.figma.d.ts.map +1 -0
  36. package/dist/components/Icons/GripDotsVerticalIcon.d.ts.map +1 -1
  37. package/dist/components/Icons/HelpIcon.d.ts +6 -0
  38. package/dist/components/Icons/HelpIcon.d.ts.map +1 -0
  39. package/dist/components/Icons/NotebookIcon.d.ts +6 -0
  40. package/dist/components/Icons/NotebookIcon.d.ts.map +1 -0
  41. package/dist/components/Icons/RightArrowIcon.d.ts +6 -0
  42. package/dist/components/Icons/RightArrowIcon.d.ts.map +1 -0
  43. package/dist/components/Icons/ScenarioIcon.d.ts +6 -0
  44. package/dist/components/Icons/ScenarioIcon.d.ts.map +1 -0
  45. package/dist/components/Icons/index.d.ts +9 -1
  46. package/dist/components/Icons/index.d.ts.map +1 -1
  47. package/dist/components/NavigationMenu/NavigationMenu.d.ts +3 -0
  48. package/dist/components/NavigationMenu/NavigationMenu.d.ts.map +1 -0
  49. package/dist/components/NavigationMenu/NavigationMenu.figma.d.ts +2 -0
  50. package/dist/components/NavigationMenu/NavigationMenu.figma.d.ts.map +1 -0
  51. package/dist/components/NavigationMenu/index.d.ts +3 -0
  52. package/dist/components/NavigationMenu/index.d.ts.map +1 -0
  53. package/dist/components/NavigationMenu/types.d.ts +25 -0
  54. package/dist/components/NavigationMenu/types.d.ts.map +1 -0
  55. package/dist/components/QuickStartPage/QuickStartPage.d.ts +21 -0
  56. package/dist/components/QuickStartPage/QuickStartPage.d.ts.map +1 -0
  57. package/dist/components/QuickStartPage/index.d.ts +3 -0
  58. package/dist/components/QuickStartPage/index.d.ts.map +1 -0
  59. package/dist/components/ScenarioQueue/ScenarioQueue.figma.d.ts +2 -0
  60. package/dist/components/ScenarioQueue/ScenarioQueue.figma.d.ts.map +1 -0
  61. package/dist/components/ScenarioSettings/ScenarioSettings.d.ts +3 -0
  62. package/dist/components/ScenarioSettings/ScenarioSettings.d.ts.map +1 -0
  63. package/dist/components/ScenarioSettings/ScenarioSettings.figma.d.ts +2 -0
  64. package/dist/components/ScenarioSettings/ScenarioSettings.figma.d.ts.map +1 -0
  65. package/dist/components/ScenarioSettings/index.d.ts +3 -0
  66. package/dist/components/ScenarioSettings/index.d.ts.map +1 -0
  67. package/dist/components/ScenarioSettings/types.d.ts +54 -0
  68. package/dist/components/ScenarioSettings/types.d.ts.map +1 -0
  69. package/dist/components/index.cjs +86 -42
  70. package/dist/components/index.d.ts +14 -3
  71. package/dist/components/index.d.ts.map +1 -1
  72. package/dist/components/index.js +1 -1
  73. package/dist/figma-codex/config.d.ts +8 -0
  74. package/dist/figma-codex/config.d.ts.map +1 -0
  75. package/dist/figma-codex/fixtures/CompoundComponent/CompoundComponent.d.ts +6 -0
  76. package/dist/figma-codex/fixtures/CompoundComponent/CompoundComponent.d.ts.map +1 -0
  77. package/dist/figma-codex/fixtures/CompoundComponent/index.d.ts +2 -0
  78. package/dist/figma-codex/fixtures/CompoundComponent/index.d.ts.map +1 -0
  79. package/dist/figma-codex/fixtures/CompoundComponent.figma.d.ts +2 -0
  80. package/dist/figma-codex/fixtures/CompoundComponent.figma.d.ts.map +1 -0
  81. package/dist/figma-codex/fixtures/SimpleComponent.d.ts +8 -0
  82. package/dist/figma-codex/fixtures/SimpleComponent.d.ts.map +1 -0
  83. package/dist/figma-codex/fixtures/SimpleComponent.figma.d.ts +2 -0
  84. package/dist/figma-codex/fixtures/SimpleComponent.figma.d.ts.map +1 -0
  85. package/dist/figma-codex/generate.d.ts +6 -0
  86. package/dist/figma-codex/generate.d.ts.map +1 -0
  87. package/dist/figma-codex/parser.d.ts +18 -0
  88. package/dist/figma-codex/parser.d.ts.map +1 -0
  89. package/dist/figma-codex/resolver.d.ts +5 -0
  90. package/dist/figma-codex/resolver.d.ts.map +1 -0
  91. package/dist/figma-codex/schema.d.ts +60 -0
  92. package/dist/figma-codex/schema.d.ts.map +1 -0
  93. package/dist/figma-codex/writer.d.ts +8 -0
  94. package/dist/figma-codex/writer.d.ts.map +1 -0
  95. package/dist/figma-codex.json +373 -0
  96. package/dist/index.cjs +90 -46
  97. package/dist/index.js +2 -2
  98. package/dist/preset/index.cjs +2 -2
  99. package/dist/preset/index.d.ts.map +1 -1
  100. package/dist/preset/index.js +1 -1
  101. package/dist/preset/recipes/accordion.d.ts.map +1 -1
  102. package/dist/preset/recipes/breadcrumb.d.ts.map +1 -1
  103. package/dist/preset/recipes/content-card.d.ts +2 -0
  104. package/dist/preset/recipes/content-card.d.ts.map +1 -0
  105. package/dist/preset/recipes/index.d.ts +4 -0
  106. package/dist/preset/recipes/index.d.ts.map +1 -1
  107. package/dist/preset/recipes/navigation-menu.d.ts +2 -0
  108. package/dist/preset/recipes/navigation-menu.d.ts.map +1 -0
  109. package/dist/preset/recipes/scenario-settings.d.ts +2 -0
  110. package/dist/preset/recipes/scenario-settings.d.ts.map +1 -0
  111. package/package.json +26 -2
  112. package/src/components/Accordion.figma.tsx +20 -0
  113. package/src/components/Breadcrumb.figma.tsx +18 -0
  114. package/src/components/Breadcrumb.tsx +33 -15
  115. package/src/components/ContentCard/ContentCard.figma.tsx +21 -0
  116. package/src/components/ContentCard/ContentCard.test.tsx +197 -0
  117. package/src/components/ContentCard/ContentCard.tsx +19 -0
  118. package/src/components/ContentCard/index.ts +13 -0
  119. package/src/components/Header.figma.tsx +25 -0
  120. package/src/components/{Heading.tsx → Header.tsx} +2 -2
  121. package/src/components/Icons/AccountIcon.tsx +26 -0
  122. package/src/components/Icons/ChevronUpIcon.tsx +24 -0
  123. package/src/components/Icons/ClockIcon.tsx +6 -6
  124. package/src/components/Icons/DashboardIcon.tsx +47 -0
  125. package/src/components/Icons/Discourser-Logo.svg +14 -0
  126. package/src/components/Icons/DiscourserLogo.figma.tsx +10 -0
  127. package/src/components/Icons/DiscourserLogo.tsx +72 -0
  128. package/src/components/Icons/GripDotsVerticalIcon.tsx +6 -6
  129. package/src/components/Icons/HelpIcon.tsx +26 -0
  130. package/src/components/Icons/NotebookIcon.tsx +26 -0
  131. package/src/components/Icons/RightArrowIcon.tsx +23 -0
  132. package/src/components/Icons/ScenarioIcon.tsx +26 -0
  133. package/src/components/Icons/index.ts +13 -2
  134. package/src/components/NavigationMenu/NavigationMenu.figma.tsx +26 -0
  135. package/src/components/NavigationMenu/NavigationMenu.test.tsx +524 -0
  136. package/src/components/NavigationMenu/NavigationMenu.tsx +102 -0
  137. package/src/components/NavigationMenu/index.ts +2 -0
  138. package/src/components/NavigationMenu/types.ts +27 -0
  139. package/src/components/QuickStartPage/QuickStartPage.tsx +627 -0
  140. package/src/components/QuickStartPage/index.ts +2 -0
  141. package/src/components/ScenarioQueue/ScenarioQueue.figma.tsx +37 -0
  142. package/src/components/ScenarioSettings/ScenarioSettings.figma.tsx +12 -0
  143. package/src/components/ScenarioSettings/ScenarioSettings.test.tsx +406 -0
  144. package/src/components/ScenarioSettings/ScenarioSettings.tsx +386 -0
  145. package/src/components/ScenarioSettings/index.ts +11 -0
  146. package/src/components/ScenarioSettings/types.ts +70 -0
  147. package/src/components/__tests__/Breadcrumb.test.tsx +94 -0
  148. package/src/components/index.ts +38 -4
  149. package/src/figma-codex/README.md +186 -0
  150. package/src/figma-codex/__tests__/config.test.ts +63 -0
  151. package/src/figma-codex/__tests__/generate.test.ts +78 -0
  152. package/src/figma-codex/__tests__/parser.test.ts +138 -0
  153. package/src/figma-codex/__tests__/resolver.test.ts +196 -0
  154. package/src/figma-codex/__tests__/writer.test.ts +111 -0
  155. package/src/figma-codex/config.ts +42 -0
  156. package/src/figma-codex/fixtures/CompoundComponent/CompoundComponent.tsx +17 -0
  157. package/src/figma-codex/fixtures/CompoundComponent/index.ts +1 -0
  158. package/src/figma-codex/fixtures/CompoundComponent.figma.tsx +14 -0
  159. package/src/figma-codex/fixtures/SimpleComponent.figma.tsx +10 -0
  160. package/src/figma-codex/fixtures/SimpleComponent.tsx +10 -0
  161. package/src/figma-codex/fixtures/expected-output.json +78 -0
  162. package/src/figma-codex/generate.ts +106 -0
  163. package/src/figma-codex/parser.ts +138 -0
  164. package/src/figma-codex/resolver.ts +280 -0
  165. package/src/figma-codex/schema.ts +79 -0
  166. package/src/figma-codex/writer.ts +54 -0
  167. package/src/preset/index.ts +6 -0
  168. package/src/preset/recipes/accordion.ts +8 -5
  169. package/src/preset/recipes/breadcrumb.ts +34 -2
  170. package/src/preset/recipes/content-card.ts +124 -0
  171. package/src/preset/recipes/index.ts +4 -0
  172. package/src/preset/recipes/navigation-menu.ts +97 -0
  173. package/src/preset/recipes/scenario-settings.ts +182 -0
  174. package/src/test/setup.ts +12 -9
  175. package/dist/chunk-ABC7N32K.cjs.map +0 -1
  176. package/dist/chunk-GD6Q2FUE.js.map +0 -1
  177. package/dist/chunk-SBKRSXSZ.js.map +0 -1
  178. package/dist/chunk-UNWXE6UB.cjs.map +0 -1
  179. package/dist/components/Heading.d.ts.map +0 -1
@@ -0,0 +1,97 @@
1
+ import { defineSlotRecipe } from '@pandacss/dev';
2
+
3
+ export const navigationMenu = defineSlotRecipe({
4
+ className: 'navigation-menu',
5
+ slots: [
6
+ 'root',
7
+ 'section',
8
+ 'sectionTrigger',
9
+ 'sectionIcon',
10
+ 'sectionTitle',
11
+ 'sectionIndicator',
12
+ 'sectionContent',
13
+ 'itemList',
14
+ 'item',
15
+ 'itemLink',
16
+ ],
17
+ base: {
18
+ // ── Token mappings verified against Figma MCP output (node 38:4046) ──
19
+ // Figma file: GaHmFfmvO4loUzuZS4TgEz
20
+ root: {
21
+ bg: 'surface.dim', // Figma: #f5f1eb warm sage sidebar bg
22
+ width: 'full',
23
+ py: '2',
24
+ },
25
+ section: {
26
+ borderBottom: 'none',
27
+ },
28
+ sectionTrigger: {
29
+ // Layout-only props — no conflicts with accordion recipe here
30
+ display: 'flex',
31
+ alignItems: 'center',
32
+ justifyContent: 'space-between',
33
+ width: 'full',
34
+ cursor: 'pointer',
35
+ // NOTE: fontSize, fontWeight, borderRadius, p, bg, color are applied via
36
+ // css={{}} on Accordion.ItemTrigger in the component (utilities layer > recipes layer).
37
+ // See ScenarioCard.tsx for the same pattern.
38
+ _hover: {
39
+ bg: 'surface.container.high',
40
+ },
41
+ },
42
+ sectionIcon: {
43
+ flexShrink: 0,
44
+ display: 'flex',
45
+ alignItems: 'center',
46
+ justifyContent: 'center',
47
+ width: '6', // 24px container
48
+ height: '6',
49
+ color: 'primary.50', // olive green icons — Figma: #518500
50
+ fontSize: '20px', // icon SVGs use width/height: 1em → sets 20×20px
51
+ },
52
+ sectionTitle: {
53
+ flex: 1,
54
+ textAlign: 'start',
55
+ // Font styles inherited from trigger's css={{}} utility overrides
56
+ },
57
+ sectionIndicator: {
58
+ // color set via css={{}} on Accordion.ItemIndicator (utilities > recipes)
59
+ _open: {
60
+ rotate: '180deg',
61
+ },
62
+ },
63
+ sectionContent: {
64
+ overflow: 'hidden',
65
+ borderRadius: '0', // override accordion's default border-radius
66
+ },
67
+ itemList: {
68
+ display: 'flex',
69
+ flexDirection: 'column',
70
+ gap: '0.5',
71
+ pt: '1',
72
+ pb: '2',
73
+ },
74
+ item: {},
75
+ itemLink: {
76
+ display: 'block',
77
+ py: '2', // Figma: 5px top/bottom
78
+ pl: '8', // Figma: 30px left indent → spacing.8 = 32px
79
+ pr: '2', // Figma: 5px right padding
80
+ borderRadius: 'l3', // Figma: 8px
81
+ textDecoration: 'none',
82
+ fontSize: 'md', // Figma: 16px
83
+ fontWeight: 'norma', // Figma: Inter Medium 500
84
+ lineHeight: '1',
85
+ color: 'onSurface', // Figma: #363636
86
+ cursor: 'pointer',
87
+ _hover: {
88
+ bg: 'surface.container.high', // Figma: #ebe7e1
89
+ },
90
+ // Figma active state: surface.container.low (NOT primary.container)
91
+ '&[data-active="true"]': {
92
+ bg: 'surface.container.low', // Figma: #f3f4e9 → surfaceContainerLow
93
+ color: 'onSurface',
94
+ },
95
+ },
96
+ },
97
+ });
@@ -0,0 +1,182 @@
1
+ import { defineSlotRecipe } from '@pandacss/dev';
2
+
3
+ export const scenarioSettings = defineSlotRecipe({
4
+ className: 'scenario-settings',
5
+ // ── Token mappings verified against Figma MCP output (node 38:4186) ──
6
+ // Figma file: GaHmFfmvO4loUzuZS4TgEz — "Discourser Queue Right Accordion"
7
+ slots: [
8
+ 'root',
9
+ 'section',
10
+ 'sectionTrigger',
11
+ 'triggerLabel',
12
+ 'sectionIndicator',
13
+ 'sectionContent',
14
+ // Info panels (sections 1-4): surfacevariant bg, explanation card, adjustments
15
+ 'infoPanel',
16
+ 'explanationCard',
17
+ 'explanationTitle',
18
+ 'explanationList',
19
+ 'explanationItem',
20
+ 'levelLabel',
21
+ 'adjustmentsRow',
22
+ // Radio panels (sections 5-6): neutral.1 bg, radio group, badge
23
+ 'radioPanel',
24
+ 'radioPanelTitle',
25
+ 'radioCurrentRow',
26
+ 'radioCurrentLabel',
27
+ 'currentlyBadge',
28
+ ],
29
+ base: {
30
+ root: {
31
+ display: 'flex',
32
+ flexDirection: 'column',
33
+ width: 'full',
34
+ cursor: 'default',
35
+ },
36
+ section: {
37
+ // Remove the accordion's default borderBottom
38
+ borderBottom: 'none',
39
+ width: 'full',
40
+ },
41
+ sectionTrigger: {
42
+ // Layout — non-conflicting props only.
43
+ // fontSize, fontWeight, borderRadius, bg, color, py applied via css={{}} in component.
44
+ display: 'flex',
45
+ alignItems: 'center',
46
+ justifyContent: 'space-between',
47
+ gap: '4',
48
+ width: 'full',
49
+ px: '5', // 20px — Figma spec
50
+ cursor: 'pointer',
51
+ },
52
+ triggerLabel: {
53
+ flex: 1,
54
+ textAlign: 'start',
55
+ overflow: 'hidden',
56
+ textOverflow: 'ellipsis',
57
+ whiteSpace: 'nowrap',
58
+ },
59
+ sectionIndicator: {
60
+ // color applied via css={{}} on ItemIndicator
61
+ flexShrink: 0,
62
+ _open: {
63
+ rotate: '180deg',
64
+ },
65
+ },
66
+ sectionContent: {
67
+ overflow: 'hidden',
68
+ borderRadius: '0',
69
+ width: 'full',
70
+ },
71
+
72
+ // ── Info Panel (sections 1-4) ─────────────────────────────────────────────
73
+ // Figma: bg = surfacevariant (#E1E4D5) — closest token: surface.container.highest (#E2E3D8)
74
+ infoPanel: {
75
+ display: 'flex',
76
+ flexDirection: 'column',
77
+ gap: '5', // 20px — Figma spec
78
+ p: '5', // 20px — Figma spec
79
+ bg: 'surface.container.highest',
80
+ width: 'full',
81
+ },
82
+
83
+ // Figma: bg = neutral/99 (#FDFCF5), border = surfacevariant, rounded-8, p-20
84
+ explanationCard: {
85
+ display: 'flex',
86
+ flexDirection: 'column',
87
+ gap: '4', // 16px
88
+ p: '5', // 20px
89
+ bg: 'neutral.1', // neutral[99] = #FDFCF5 ✓
90
+ borderWidth: '1px',
91
+ borderStyle: 'solid',
92
+ borderColor: 'surface.container.highest',
93
+ borderRadius: 'l3', // 8px
94
+ },
95
+
96
+ // Figma: Inter Medium 20px, --dark-surfacecontainerhigh (#282b24 ≈ onSurface)
97
+ explanationTitle: {
98
+ fontSize: 'lg',
99
+ fontWeight: 'semibold',
100
+ color: 'onSurface',
101
+ lineHeight: '1',
102
+ },
103
+
104
+ explanationList: {
105
+ display: 'flex',
106
+ flexDirection: 'column',
107
+ gap: '3', // 12px between items
108
+ listStyleType: 'disc',
109
+ pl: '5', // indent for disc markers
110
+ },
111
+
112
+ explanationItem: {
113
+ fontSize: 'sm', // 16px — Figma spec
114
+ lineHeight: '1.4',
115
+ color: 'fg.default',
116
+ },
117
+
118
+ // Figma: Inter Bold — the "Beginner:", "Intermediate:", "Advanced:" labels
119
+ levelLabel: {
120
+ fontWeight: 'bold',
121
+ color: 'fg.default',
122
+ },
123
+
124
+ adjustmentsRow: {
125
+ display: 'flex',
126
+ alignItems: 'center',
127
+ justifyContent: 'center',
128
+ width: 'full',
129
+ },
130
+
131
+ // ── Radio Panel (sections 5-6) ────────────────────────────────────────────
132
+ // Figma: bg = neutral/99 (#FDFCF5)
133
+ radioPanel: {
134
+ display: 'flex',
135
+ flexDirection: 'column',
136
+ gap: '6', // 24px
137
+ p: '5', // 20px
138
+ bg: 'neutral.1', // neutral[99] = #FDFCF5 ✓
139
+ width: 'full',
140
+ },
141
+
142
+ // Figma: Inter Medium 20px, #363636 ≈ onSurface
143
+ radioPanelTitle: {
144
+ fontSize: 'lg',
145
+ fontWeight: 'semibold',
146
+ color: 'onSurface',
147
+ lineHeight: '1',
148
+ },
149
+
150
+ radioCurrentRow: {
151
+ display: 'flex',
152
+ alignItems: 'center',
153
+ gap: '2.5', // 10px — Figma spec
154
+ mt: '2.5', // space below panel title
155
+ },
156
+
157
+ // Figma: Inter SemiBold 18px, #363636
158
+ radioCurrentLabel: {
159
+ fontSize: 'md',
160
+ fontWeight: 'semibold',
161
+ color: 'onSurface',
162
+ whiteSpace: 'nowrap',
163
+ },
164
+
165
+ // Figma: bg = dark-primary (#B1D18A) = inversePrimary, fully rounded pill
166
+ // px-16, py-6, font: Geist/12px, color: #2c2a27 ≈ fg.default
167
+ currentlyBadge: {
168
+ display: 'inline-flex',
169
+ alignItems: 'center',
170
+ gap: '1.5',
171
+ px: '4', // 16px
172
+ py: '1.5', // 6px
173
+ bg: 'inversePrimary', // #B1D18A light mode ✓
174
+ color: 'fg.default',
175
+ borderRadius: 'full',
176
+ fontSize: 'xs', // 12px
177
+ fontWeight: 'normal',
178
+ lineHeight: '1',
179
+ whiteSpace: 'nowrap',
180
+ },
181
+ },
182
+ });
package/src/test/setup.ts CHANGED
@@ -8,15 +8,18 @@ expect.extend(toHaveNoViolations);
8
8
 
9
9
  // Mock ResizeObserver — JSDOM does not implement it, but @zag-js/tabs requires
10
10
  // it to sync the active tab indicator rectangle position.
11
- Object.defineProperty(window, 'ResizeObserver', {
12
- writable: true,
13
- configurable: true,
14
- value: class ResizeObserver {
15
- observe() {}
16
- unobserve() {}
17
- disconnect() {}
18
- },
19
- });
11
+ // Guard for Node.js environment (e.g. figma-codex tests with @vitest-environment node)
12
+ if (typeof window !== 'undefined') {
13
+ Object.defineProperty(window, 'ResizeObserver', {
14
+ writable: true,
15
+ configurable: true,
16
+ value: class ResizeObserver {
17
+ observe() {}
18
+ unobserve() {}
19
+ disconnect() {}
20
+ },
21
+ });
22
+ }
20
23
 
21
24
  // Cleanup after each test
22
25
  afterEach(() => {