@plumeria/turbopack-loader 18.4.0 → 18.4.2

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 (2) hide show
  1. package/dist/index.js +139 -180
  2. package/package.json +3 -3
package/dist/index.js CHANGED
@@ -105,87 +105,37 @@ const componentFunctionOf = (node) => {
105
105
  }
106
106
  return undefined;
107
107
  };
108
+ const unwrapPatternDefault = (pattern) => pattern?.type === 'AssignmentPattern' ? pattern.left : pattern;
109
+ const destructuredPropAliases = (fn) => {
110
+ const aliases = new Map();
111
+ const first = fn.params[0];
112
+ const pattern = unwrapPatternDefault(first?.pat ?? first);
113
+ if (pattern?.type !== 'ObjectPattern')
114
+ return aliases;
115
+ for (const item of pattern.properties ?? []) {
116
+ if (item.type !== 'KeyValuePatternProperty')
117
+ continue;
118
+ const local = unwrapPatternDefault(item.value);
119
+ const key = item.key;
120
+ if (!utils_1.t.isIdentifier(local))
121
+ continue;
122
+ if (!utils_1.t.isIdentifier(key) && !utils_1.t.isStringLiteral(key))
123
+ continue;
124
+ const name = String(key.value);
125
+ if (name !== local.value)
126
+ aliases.set(local.value, name);
127
+ }
128
+ return aliases;
129
+ };
108
130
  const isStaticArgValue = (node) => node.type === 'StringLiteral' ||
109
131
  node.type === 'NumericLiteral' ||
110
132
  node.type === 'BooleanLiteral' ||
111
133
  (node.type === 'TemplateLiteral' && node.expressions.length === 0) ||
112
134
  utils_1.t.isIdentifier(node) ||
113
135
  utils_1.t.isMemberExpression(node);
114
- const namedParamsOf = (params, defaults) => {
115
- if (params.length !== 1)
116
- return undefined;
117
- const first = params[0];
118
- const pattern = (first?.pat ?? first);
119
- if (pattern?.type !== 'ObjectPattern')
120
- return undefined;
121
- const named = [];
122
- for (const prop of pattern.properties ?? []) {
123
- if (prop.type === 'AssignmentPatternProperty' && utils_1.t.isIdentifier(prop.key)) {
124
- named.push({ key: prop.key.value, local: prop.key.value });
125
- if (prop.value)
126
- defaults[prop.key.value] = prop.value;
127
- }
128
- else if (prop.type === 'KeyValuePatternProperty' &&
129
- utils_1.t.isIdentifier(prop.key) &&
130
- utils_1.t.isIdentifier(prop.value)) {
131
- named.push({ key: prop.key.value, local: prop.value.value });
132
- }
133
- else if (prop.type === 'KeyValuePatternProperty' &&
134
- utils_1.t.isIdentifier(prop.key) &&
135
- prop.value?.type === 'AssignmentPattern' &&
136
- utils_1.t.isIdentifier(prop.value.left)) {
137
- const pattern = prop.value;
138
- named.push({ key: String(prop.key.value), local: pattern.left.value });
139
- defaults[pattern.left.value] = pattern.right;
140
- }
141
- else {
142
- return undefined;
143
- }
144
- }
145
- return named.length > 0 ? named : undefined;
146
- };
147
- const styleFunctionsOf = (objExpr) => {
148
- const styleFunctions = {};
149
- objExpr.properties.forEach((prop) => {
150
- if (prop.type !== 'KeyValueProperty' || prop.key.type !== 'Identifier')
151
- return;
152
- const func = prop.value;
153
- if (func.type !== 'ArrowFunctionExpression' &&
154
- func.type !== 'FunctionExpression')
155
- return;
156
- const defaults = {};
157
- const params = func.params.map((p) => {
158
- const pattern = typeof p === 'object' && p !== null && 'pat' in p ? p.pat : p;
159
- if (utils_1.t.isIdentifier(pattern))
160
- return pattern.value;
161
- if (pattern?.type === 'AssignmentPattern' &&
162
- utils_1.t.isIdentifier(pattern.left)) {
163
- defaults[pattern.left.value] = pattern.right;
164
- return pattern.left.value;
165
- }
166
- return 'arg';
167
- });
168
- let actualBody = func.body;
169
- if (actualBody?.type === 'ParenthesisExpression')
170
- actualBody = actualBody.expression;
171
- if (actualBody?.type === 'BlockStatement') {
172
- const first = actualBody.stmts?.[0];
173
- if (first?.type === 'ReturnStatement')
174
- actualBody = first.argument;
175
- if (actualBody?.type === 'ParenthesisExpression')
176
- actualBody = actualBody.expression;
177
- }
178
- if (actualBody && actualBody.type === 'ObjectExpression') {
179
- styleFunctions[prop.key.value] = {
180
- params,
181
- named: namedParamsOf(func.params, defaults),
182
- defaults,
183
- body: actualBody,
184
- };
185
- }
186
- });
187
- return styleFunctions;
188
- };
136
+ const isNoOpStyle = (node) => utils_1.t.isNullLiteral(node) ||
137
+ (utils_1.t.isBooleanLiteral(node) && node.value === false) ||
138
+ (utils_1.t.isIdentifier(node) && node.value === 'undefined');
189
139
  const foldDynamicVars = (vars) => {
190
140
  const grouped = new Map();
191
141
  [...vars]
@@ -207,59 +157,6 @@ const foldDynamicVars = (vars) => {
207
157
  return `"${cssVar}": ${value}`;
208
158
  });
209
159
  };
210
- const isUnitlessProp = (prop) => zss_engine_1.exceptionCamelCase.includes(prop) || prop.startsWith('--');
211
- const collectVarProps = (style, cssVar, props) => {
212
- const reference = `var(${cssVar})`;
213
- for (const [prop, value] of Object.entries(style)) {
214
- if (typeof value === 'string' && value.includes(reference))
215
- props.push(prop);
216
- else if (value !== null && typeof value === 'object')
217
- collectVarProps(value, cssVar, props);
218
- }
219
- };
220
- const retargetVar = (style, cssVar, next, unitless) => {
221
- const reference = `var(${cssVar})`;
222
- for (const [prop, value] of Object.entries(style)) {
223
- if (typeof value === 'string' && value.includes(reference)) {
224
- if (isUnitlessProp(prop) === unitless)
225
- style[prop] = value
226
- .split(reference)
227
- .join(`var(${next})`);
228
- }
229
- else if (value !== null && typeof value === 'object') {
230
- retargetVar(value, cssVar, next, unitless);
231
- }
232
- }
233
- };
234
- const splitVarByUnit = (style, cssVar) => {
235
- const props = [];
236
- collectVarProps(style, cssVar, props);
237
- if (props.length === 0)
238
- return [];
239
- const lead = props[0];
240
- const split = props.find((prop) => isUnitlessProp(prop) !== isUnitlessProp(lead));
241
- if (!split)
242
- return [{ cssVar, prop: lead }];
243
- const splitVar = `${cssVar}-${(0, zss_engine_1.camelToKebabCase)(split).replace(/^-+/, '')}`;
244
- retargetVar(style, cssVar, splitVar, isUnitlessProp(split));
245
- return [
246
- { cssVar, prop: lead },
247
- { cssVar: splitVar, prop: split },
248
- ];
249
- };
250
- const applyVarFallback = (style, cssVar, literal) => {
251
- const reference = `var(${cssVar})`;
252
- for (const [prop, value] of Object.entries(style)) {
253
- if (typeof value === 'string' && value.includes(reference)) {
254
- style[prop] = value
255
- .split(reference)
256
- .join(`var(${cssVar}, ${(0, zss_engine_1.applyCssValue)(literal, (0, zss_engine_1.camelToKebabCase)(prop))})`);
257
- }
258
- else if (value !== null && typeof value === 'object') {
259
- applyVarFallback(value, cssVar, literal);
260
- }
261
- }
262
- };
263
160
  async function loader(source) {
264
161
  const callback = this.async();
265
162
  const loaderOptions = this.getOptions?.() ??
@@ -365,18 +262,22 @@ async function loader(source) {
365
262
  }
366
263
  }
367
264
  const components = [];
265
+ const propAliases = new Map();
266
+ const addComponent = (name, fn) => {
267
+ components.push({ name, node: fn });
268
+ const aliases = destructuredPropAliases(fn);
269
+ if (aliases.size > 0)
270
+ propAliases.set(name, aliases);
271
+ };
368
272
  for (const node of ast.body) {
369
273
  const statement = unwrapExport(node);
370
274
  if (isFunctionNode(statement)) {
371
- components.push({
372
- name: statement.identifier?.value ?? 'default',
373
- node: statement,
374
- });
275
+ addComponent(statement.identifier?.value ?? 'default', statement);
375
276
  }
376
277
  else if (statement?.type === 'CallExpression') {
377
278
  const fn = componentFunctionOf(statement);
378
279
  if (fn)
379
- components.push({ name: 'default', node: fn });
280
+ addComponent('default', fn);
380
281
  }
381
282
  else if (utils_1.t.isVariableDeclaration(statement)) {
382
283
  for (const decl of statement.declarations) {
@@ -384,7 +285,7 @@ async function loader(source) {
384
285
  continue;
385
286
  const fn = componentFunctionOf(decl.init);
386
287
  if (fn)
387
- components.push({ name: decl.id.value, node: fn });
288
+ addComponent(decl.id.value, fn);
388
289
  }
389
290
  }
390
291
  }
@@ -484,7 +385,7 @@ async function loader(source) {
484
385
  scannedTables.createHashTable[uniqueKey];
485
386
  }
486
387
  if (scannedTables.createFunctionTable[uniqueKey]) {
487
- createFunctionImportMap[localName] = styleFunctionsOf(scannedTables.createFunctionTable[uniqueKey]);
388
+ createFunctionImportMap[localName] = (0, utils_1.styleFunctionsOf)(scannedTables.createFunctionTable[uniqueKey]);
488
389
  }
489
390
  if (scannedTables.variantsHashTable[uniqueKey]) {
490
391
  variantsImportMap[localName] =
@@ -584,6 +485,16 @@ async function loader(source) {
584
485
  for (const key of Object.keys(createStaticImportMap)) {
585
486
  mergedCreateStaticHashTable[key] = createStaticImportMap[key];
586
487
  }
488
+ const dynamicStyleTables = {
489
+ keyframesHashTable: mergedKeyframesTable,
490
+ viewTransitionHashTable: mergedViewTransitionTable,
491
+ createThemeHashTable: mergedCreateThemeHashTable,
492
+ createThemeObjectTable: scannedTables.createThemeObjectTable,
493
+ createHashTable: mergedCreateTable,
494
+ createStaticHashTable: mergedCreateStaticHashTable,
495
+ createStaticObjectTable: scannedTables.createStaticObjectTable,
496
+ variantsHashTable: mergedVariantsTable,
497
+ };
587
498
  const localCreateStyles = {};
588
499
  const localStyleAliases = {};
589
500
  const checkStyleAliasAssignment = (decl) => {
@@ -644,7 +555,7 @@ async function loader(source) {
644
555
  records.forEach((r) => (atomMap[r.key] = r.hash));
645
556
  hashMap[key] = atomMap;
646
557
  });
647
- const styleFunctions = styleFunctionsOf(init.arguments[0].expression);
558
+ const styleFunctions = (0, utils_1.styleFunctionsOf)(init.arguments[0].expression);
648
559
  if (utils_1.t.isIdentifier(node.id)) {
649
560
  idSpans.add(node.id.span.start);
650
561
  }
@@ -983,7 +894,16 @@ async function loader(source) {
983
894
  }
984
895
  return null;
985
896
  };
986
- const resolveDynamicCall = (expr) => {
897
+ const isStyleFunctionCall = (expr) => {
898
+ if (!utils_1.t.isCallExpression(expr) || !utils_1.t.isMemberExpression(expr.callee))
899
+ return false;
900
+ const callee = expr.callee;
901
+ if (!utils_1.t.isIdentifier(callee.object) || !utils_1.t.isIdentifier(callee.property))
902
+ return false;
903
+ return Boolean(localCreateStyles[callee.object.value]?.functions?.[callee.property.value] ??
904
+ createFunctionImportMap[callee.object.value]?.[callee.property.value]);
905
+ };
906
+ const resolveDynamicCall = (expr, forceRuntime = false) => {
987
907
  if (!utils_1.t.isCallExpression(expr) || !utils_1.t.isMemberExpression(expr.callee))
988
908
  return null;
989
909
  const callee = expr.callee;
@@ -1027,7 +947,9 @@ async function loader(source) {
1027
947
  throwCompilationError(`Plumeria: ${getSource(expr)} leaves "${key}" unset, and a dynamic style function has no value to fall back on.`, expr);
1028
948
  return;
1029
949
  }
1030
- if (isStaticArgValue(source) && argObj[key] !== undefined)
950
+ if (!forceRuntime &&
951
+ isStaticArgValue(source) &&
952
+ argObj[key] !== undefined)
1031
953
  tempStaticTable[local] = argObj[key];
1032
954
  else
1033
955
  runtime.push({ param: local, source });
@@ -1035,6 +957,8 @@ async function loader(source) {
1035
957
  }
1036
958
  else if (callArgs.length === 1 &&
1037
959
  callArgs[0].expression.type === 'ObjectExpression') {
960
+ if (forceRuntime)
961
+ return null;
1038
962
  const argObj = resolveObjectArg(callArgs[0].expression) ?? {};
1039
963
  func.params.forEach((p) => {
1040
964
  if (argObj[p] !== undefined)
@@ -1049,39 +973,10 @@ async function loader(source) {
1049
973
  runtime.push({ param: p, source: callArg.expression });
1050
974
  });
1051
975
  }
1052
- const withDefault = Object.entries(func.defaults ?? {}).filter(([param]) => tempStaticTable[param] === undefined);
1053
- const cssVars = {};
1054
- const varParams = Array.from(new Set([
1055
- ...runtime.map(({ param }) => param),
1056
- ...withDefault.map(([param]) => param),
1057
- ]));
1058
- if (varParams.length > 0) {
1059
- varParams.forEach((param) => (tempStaticTable[param] = param));
1060
- const probe = (0, utils_1.objectExpressionToObject)(func.body, tempStaticTable, mergedKeyframesTable, mergedViewTransitionTable, mergedCreateThemeHashTable, scannedTables.createThemeObjectTable, mergedCreateTable, mergedCreateStaticHashTable, scannedTables.createStaticObjectTable, mergedVariantsTable);
1061
- const hash = (0, zss_engine_1.genBase36Hash)(probe ?? {}, 1, 8);
1062
- varParams.forEach((param) => {
1063
- const cssVar = `--${hash}-${param}`;
1064
- tempStaticTable[param] = `var(${cssVar})`;
1065
- cssVars[param] = cssVar;
1066
- });
1067
- }
1068
- const style = (0, utils_1.objectExpressionToObject)(func.body, tempStaticTable, mergedKeyframesTable, mergedViewTransitionTable, mergedCreateThemeHashTable, scannedTables.createThemeObjectTable, mergedCreateTable, mergedCreateStaticHashTable, scannedTables.createStaticObjectTable, mergedVariantsTable);
1069
- if (!style)
976
+ const resolved = (0, utils_1.resolveDynamicStyle)(func, runtime.map(({ param }) => param), tempStaticTable, dynamicStyleTables);
977
+ if (!resolved)
1070
978
  return null;
1071
- const varGroups = new Map();
1072
- varParams.forEach((param) => {
1073
- const cssVar = cssVars[param];
1074
- if (cssVar)
1075
- varGroups.set(param, splitVarByUnit(style, cssVar));
1076
- });
1077
- withDefault.forEach(([param, expr]) => {
1078
- const literal = expr.type === 'StringLiteral' || expr.type === 'NumericLiteral'
1079
- ? expr.value
1080
- : undefined;
1081
- if (literal === undefined)
1082
- return;
1083
- (varGroups.get(param) ?? []).forEach(({ cssVar }) => applyVarFallback(style, cssVar, literal));
1084
- });
979
+ const { style, varGroups } = resolved;
1085
980
  const vars = [];
1086
981
  runtime.forEach(({ param, source }) => {
1087
982
  const groups = varGroups.get(param);
@@ -1104,7 +999,7 @@ async function loader(source) {
1104
999
  valueExpr = JSON.stringify((0, zss_engine_1.applyCssValue)(argSource.slice(1, -1), kebabProp));
1105
1000
  }
1106
1001
  else {
1107
- valueExpr = isUnitlessProp(prop)
1002
+ valueExpr = (0, utils_1.isUnitlessProp)(prop)
1108
1003
  ? argSource
1109
1004
  : `(typeof (${argSource}) === 'number' ? (${argSource}) + 'px' : (${argSource}))`;
1110
1005
  }
@@ -1122,6 +1017,7 @@ async function loader(source) {
1122
1017
  });
1123
1018
  const conditionals = [];
1124
1019
  const dynamicVars = [];
1020
+ const propVarSpreads = [];
1125
1021
  let groupIdCounter = 0;
1126
1022
  let sourceOrder = 0;
1127
1023
  const baseChunks = [];
@@ -1238,6 +1134,8 @@ async function loader(source) {
1238
1134
  return buildDecision(node, prefix, off, { n: 0 }, scoped);
1239
1135
  };
1240
1136
  const collectConditions = (node, currentTestStrings = [], argOrder) => {
1137
+ if (isNoOpStyle(node))
1138
+ return true;
1241
1139
  let branchStyle = resolveStyleObject(node);
1242
1140
  if (!branchStyle) {
1243
1141
  const dynamic = resolveDynamicCall(node);
@@ -1317,17 +1215,20 @@ async function loader(source) {
1317
1215
  ? expr.value
1318
1216
  : expr.property.value;
1319
1217
  const source = utils_1.t.isIdentifier(expr) ? varName : getSource(expr);
1320
- markStylePropApplied(varName, expr);
1321
1218
  const owner = ownerComponentOf(expr);
1219
+ const propName = (utils_1.t.isIdentifier(expr) && owner
1220
+ ? propAliases.get(owner)?.get(varName)
1221
+ : undefined) ?? varName;
1222
+ markStylePropApplied(propName, expr);
1322
1223
  let possibilities = owner
1323
- ? scannedTables.componentPropsTable?.[`${resourcePath}-${owner}`]?.[varName]
1224
+ ? scannedTables.componentPropsTable?.[`${resourcePath}-${owner}`]?.[propName]
1324
1225
  : undefined;
1325
1226
  if (!possibilities) {
1326
1227
  const candidates = [];
1327
1228
  for (const key of Object.keys(scannedTables.componentPropsTable || {})) {
1328
1229
  if (!key.startsWith(`${resourcePath}-`))
1329
1230
  continue;
1330
- const entries = scannedTables.componentPropsTable?.[key]?.[varName];
1231
+ const entries = scannedTables.componentPropsTable?.[key]?.[propName];
1331
1232
  if (entries)
1332
1233
  candidates.push(...entries);
1333
1234
  }
@@ -1336,9 +1237,23 @@ async function loader(source) {
1336
1237
  }
1337
1238
  if (!possibilities || possibilities.length === 0)
1338
1239
  return false;
1339
- const testLHS = gates.length
1340
- ? `((${gates.join(' && ')}) ? ${source} : "")`
1240
+ const carriesVars = possibilities.some((entry) => entry.hasVars);
1241
+ if (carriesVars && !isStyleProp) {
1242
+ throwCompilationError(`Plumeria: "${varName}" carries a dynamic function key, and css.use() returns only a class name. ` +
1243
+ `Apply it to ${styleProp} on the element instead.`, expr);
1244
+ }
1245
+ const gate = gates.length ? `(${gates.join(' && ')}) && ` : '';
1246
+ if (carriesVars) {
1247
+ const spread = `...(${gate}${source} && ${source}.vars)`;
1248
+ if (!propVarSpreads.includes(spread))
1249
+ propVarSpreads.push(spread);
1250
+ }
1251
+ const token = carriesVars
1252
+ ? `((${source} && ${source}.key) || ${source})`
1341
1253
  : source;
1254
+ const testLHS = gates.length
1255
+ ? `((${gates.join(' && ')}) ? ${token} : "")`
1256
+ : token;
1342
1257
  const currentGroupId = ++groupIdCounter;
1343
1258
  const currentOrder = sourceOrder++;
1344
1259
  const seen = new Set();
@@ -1368,6 +1283,8 @@ async function loader(source) {
1368
1283
  };
1369
1284
  for (const arg of args) {
1370
1285
  const expr = arg.expression;
1286
+ if (isNoOpStyle(expr))
1287
+ continue;
1371
1288
  if (pushPropPossibilities(expr, []))
1372
1289
  continue;
1373
1290
  if (utils_1.t.isCallExpression(expr) && utils_1.t.isIdentifier(expr.callee)) {
@@ -1577,6 +1494,7 @@ async function loader(source) {
1577
1494
  isOptimizable,
1578
1495
  baseStyle,
1579
1496
  dynamicVars,
1497
+ propVarSpreads,
1580
1498
  };
1581
1499
  }
1582
1500
  const stateSources = baseChunks.map(({ order, style }) => ({ order, style: style }));
@@ -1832,7 +1750,13 @@ async function loader(source) {
1832
1750
  classParts.push(`(${JSON.stringify(results)}[${masterKeyExpr || '""'}] || ${baseConflictClass ? JSON.stringify(baseConflictClass) : '""'})`);
1833
1751
  }
1834
1752
  classParts.push(...dynamicClassParts);
1835
- return { classParts, isOptimizable, baseStyle, dynamicVars };
1753
+ return {
1754
+ classParts,
1755
+ isOptimizable,
1756
+ baseStyle,
1757
+ dynamicVars,
1758
+ propVarSpreads,
1759
+ };
1836
1760
  };
1837
1761
  (0, utils_1.traverse)(ast, {
1838
1762
  JSXOpeningElement({ node }) {
@@ -2033,14 +1957,40 @@ async function loader(source) {
2033
1957
  node.value &&
2034
1958
  node.value.type === 'JSXExpressionContainer') {
2035
1959
  const expr = node.value.expression;
1960
+ const carrierFor = (subNode) => {
1961
+ const vars = [];
1962
+ let unresolved = false;
1963
+ (0, utils_1.traverse)(subNode, {
1964
+ CallExpression({ node: call }) {
1965
+ if (!isStyleFunctionCall(call))
1966
+ return;
1967
+ const resolved = resolveDynamicCall(call, true);
1968
+ if (!resolved) {
1969
+ unresolved = true;
1970
+ return;
1971
+ }
1972
+ vars.push(...resolved.vars);
1973
+ },
1974
+ });
1975
+ if (unresolved)
1976
+ return null;
1977
+ return `{ ${foldDynamicVars(vars).join(', ')} }`;
1978
+ };
2036
1979
  const replaceWithKey = (subNode) => {
2037
1980
  const entry = list.find((x) => x.spanStart === subNode.span.start &&
2038
1981
  x.filePath === resourcePath);
2039
1982
  if (entry) {
1983
+ let content = JSON.stringify(entry.key);
1984
+ if (entry.hasVars) {
1985
+ const carrier = carrierFor(subNode);
1986
+ if (!carrier)
1987
+ return false;
1988
+ content = `{ key: ${content}, vars: ${carrier} }`;
1989
+ }
2040
1990
  replacements.push({
2041
1991
  start: subNode.span.start - baseByteOffset,
2042
1992
  end: subNode.span.end - baseByteOffset,
2043
- content: JSON.stringify(entry.key),
1993
+ content,
2044
1994
  });
2045
1995
  processStyleRecords(entry.styleObj);
2046
1996
  return true;
@@ -2058,6 +2008,11 @@ async function loader(source) {
2058
2008
  excludeSubtreeSpans(subNode);
2059
2009
  }
2060
2010
  },
2011
+ CallExpression({ node: subNode }) {
2012
+ if (replaceWithKey(subNode)) {
2013
+ excludeSubtreeSpans(subNode);
2014
+ }
2015
+ },
2061
2016
  });
2062
2017
  }
2063
2018
  }
@@ -2133,10 +2088,11 @@ async function loader(source) {
2133
2088
  }
2134
2089
  }
2135
2090
  }
2136
- const { classParts, isOptimizable, baseStyle, dynamicVars } = buildClassParts(args, dynamicClassParts, existingClassExpr, true);
2091
+ const { classParts, isOptimizable, baseStyle, dynamicVars, propVarSpreads, } = buildClassParts(args, dynamicClassParts, existingClassExpr, true);
2137
2092
  const styleParts = [
2138
2093
  ...existingStyleParts,
2139
2094
  ...foldDynamicVars(dynamicVars),
2095
+ ...propVarSpreads,
2140
2096
  ];
2141
2097
  const styleAttr = styleParts.length > 0 || existingStyleExpr
2142
2098
  ? ` style={{ ${[existingStyleExpr, ...styleParts].filter(Boolean).join(', ')} }}`
@@ -2153,10 +2109,13 @@ async function loader(source) {
2153
2109
  });
2154
2110
  }
2155
2111
  else {
2112
+ const keptClass = existingClassExpr
2113
+ ? `className={${existingClassExpr}}`
2114
+ : '';
2156
2115
  replacements.push({
2157
2116
  start: node.span.start - baseByteOffset,
2158
2117
  end: node.span.end - baseByteOffset,
2159
- content: styleAttr || '',
2118
+ content: `${keptClass}${styleAttr}`,
2160
2119
  });
2161
2120
  }
2162
2121
  },
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@plumeria/turbopack-loader",
3
- "version": "18.4.0",
3
+ "version": "18.4.2",
4
4
  "description": "Plumeria Turbopack-loader",
5
5
  "author": "Refirst 11",
6
6
  "license": "MIT",
@@ -29,8 +29,8 @@
29
29
  "zero-virtual.css"
30
30
  ],
31
31
  "dependencies": {
32
- "@plumeria/compiler": "^18.4.0",
33
- "@plumeria/utils": "^18.4.0"
32
+ "@plumeria/compiler": "^18.4.2",
33
+ "@plumeria/utils": "^18.4.2"
34
34
  },
35
35
  "devDependencies": {
36
36
  "@swc/core": "1.15.47",