@mandujs/core 0.18.9 → 0.18.11

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@mandujs/core",
3
- "version": "0.18.9",
3
+ "version": "0.18.11",
4
4
  "description": "Mandu Framework Core - Spec, Generator, Guard, Runtime",
5
5
  "type": "module",
6
6
  "main": "./src/index.ts",
@@ -778,7 +778,8 @@ if (typeof window !== 'undefined') {
778
778
  minify: false, // dev only
779
779
  sourcemap: options.sourcemap ? "external" : "none",
780
780
  target: "browser",
781
- external: ["react", "react-dom", "react-dom/client"],
781
+ // React를 인라인 번들링 (import map 없이도 독립 동작)
782
+ // DevTools는 Shadow DOM 격리 → 앱 React와 충돌 없음
782
783
  define: {
783
784
  "process.env.NODE_ENV": JSON.stringify("development"),
784
785
  ...options.define,
@@ -1251,6 +1252,15 @@ export async function buildClientBundles(
1251
1252
  // Hydration 라우트가 없어도 빈 매니페스트를 저장해야 함
1252
1253
  // (이전 빌드의 stale 매니페스트 참조 방지)
1253
1254
  if (hydratedRoutes.length === 0) {
1255
+ // Dev 모드에서는 DevTools 번들 빌드 (island 없어도 동작해야 함)
1256
+ const isDev = env === "development";
1257
+ if (isDev) {
1258
+ const devtoolsResult = await buildDevtoolsBundle(outDir, options);
1259
+ if (!devtoolsResult.success) {
1260
+ console.warn("[Mandu] DevTools bundle build failed:", devtoolsResult.errors.join(", "));
1261
+ }
1262
+ }
1263
+
1254
1264
  const emptyManifest = createEmptyManifest(env);
1255
1265
  await fs.writeFile(
1256
1266
  path.join(rootDir, ".mandu/manifest.json"),
@@ -202,29 +202,38 @@ export function ManduBadge({
202
202
  }: ManduBadgeProps): React.ReactElement {
203
203
  const character = MANDU_CHARACTERS[state];
204
204
  const stateColor = stateColors[state];
205
+ const [isHovered, setIsHovered] = React.useState(false);
205
206
 
206
207
  const badgeStyle: React.CSSProperties = {
207
208
  display: 'flex',
208
209
  alignItems: 'center',
209
210
  justifyContent: 'center',
210
- gap: '6px',
211
- padding: '8px 12px',
211
+ gap: '8px',
212
+ padding: count > 0 ? '10px 16px' : '0',
213
+ width: count > 0 ? 'auto' : '48px',
214
+ height: '48px',
212
215
  borderRadius: '9999px',
213
216
  backgroundColor: colors.background.dark,
214
- border: `2px solid ${stateColor}`,
217
+ border: `2px solid ${isHovered ? colors.brand.accent : stateColor}`,
215
218
  cursor: 'pointer',
216
- transition: `all ${animation.duration.fast} ${animation.easing.easeOut}`,
217
- boxShadow: colors.background.overlay,
218
- fontSize: '16px',
219
+ transition: `all ${animation.duration.normal} ${animation.easing.spring}`,
220
+ boxShadow: isHovered
221
+ ? `0 8px 24px rgba(0, 0, 0, 0.4), 0 0 0 4px ${stateColor}33`
222
+ : `0 4px 12px rgba(0, 0, 0, 0.3)`,
223
+ fontSize: '22px',
219
224
  userSelect: 'none',
225
+ transform: isHovered ? 'scale(1.08)' : 'scale(1)',
226
+ outline: 'none',
227
+ lineHeight: 1,
220
228
  };
221
229
 
222
230
  const countStyle: React.CSSProperties = {
223
- fontSize: '12px',
224
- fontWeight: 600,
231
+ fontSize: '13px',
232
+ fontWeight: 700,
225
233
  color: stateColor,
226
234
  minWidth: '18px',
227
235
  textAlign: 'center',
236
+ lineHeight: 1,
228
237
  };
229
238
 
230
239
  return (
@@ -232,9 +241,13 @@ export function ManduBadge({
232
241
  data-testid={testIds.badge}
233
242
  style={badgeStyle}
234
243
  onClick={onClick}
244
+ onMouseEnter={() => setIsHovered(true)}
245
+ onMouseLeave={() => setIsHovered(false)}
246
+ onFocus={() => setIsHovered(true)}
247
+ onBlur={() => setIsHovered(false)}
235
248
  aria-label={`Mandu Kitchen: ${character.message}${count > 0 ? `, ${count} issues` : ''}`}
236
249
  >
237
- <span aria-hidden="true">{character.emoji}</span>
250
+ <span aria-hidden="true">🥟</span>
238
251
  {count > 0 && <span style={countStyle}>{count}</span>}
239
252
  </button>
240
253
  );