@weapp-vite/web 1.0.1 → 1.1.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.
package/dist/index.mjs CHANGED
@@ -361,6 +361,25 @@ function parseEventAttribute(name) {
361
361
  }
362
362
  return { prefix: name.slice(0, name.length - match[1].length), rawEvent: match[1] };
363
363
  }
364
+ function resolveComponentTagName(name, componentTags) {
365
+ if (!componentTags) {
366
+ return void 0;
367
+ }
368
+ return componentTags[name] ?? componentTags[name.toLowerCase()];
369
+ }
370
+ var PROPERTY_BIND_EXCLUSIONS = /* @__PURE__ */ new Set(["class", "style", "id", "slot"]);
371
+ function shouldBindAsProperty(name) {
372
+ if (PROPERTY_BIND_EXCLUSIONS.has(name)) {
373
+ return false;
374
+ }
375
+ if (name.startsWith("data-") || name.startsWith("aria-")) {
376
+ return false;
377
+ }
378
+ return true;
379
+ }
380
+ function normalizePropertyName(name) {
381
+ return name.replace(/-([a-z])/g, (_, char) => char.toUpperCase());
382
+ }
364
383
  function renderAttributes(attribs, scopeVar, wxsVar, options) {
365
384
  let buffer = "";
366
385
  for (const [rawName, rawValue] of Object.entries(attribs)) {
@@ -379,24 +398,31 @@ function renderAttributes(attribs, scopeVar, wxsVar, options) {
379
398
  buffer += ` @${domEvent}=\${ctx.event(${JSON.stringify(event)}, ${handlerExpr}, ${scopeVar}, ${wxsVar}, ${JSON.stringify(flags)})}`;
380
399
  continue;
381
400
  }
382
- const name = normalizeAttributeName(rawName);
401
+ const useProperty = options?.preferProperty && shouldBindAsProperty(rawName);
402
+ const name = useProperty ? normalizePropertyName(rawName) : normalizeAttributeName(rawName);
383
403
  const expr = buildExpression(parseInterpolations(rawValue ?? ""), scopeVar, wxsVar);
384
- buffer += ` ${name}=\${${expr}}`;
404
+ buffer += ` ${useProperty ? "." : ""}${name}=\${${expr}}`;
385
405
  }
386
406
  return buffer;
387
407
  }
388
408
  var Renderer = class {
389
- renderNodes(nodes, scopeVar, wxsVar) {
409
+ renderNodes(nodes, scopeVar, wxsVar, componentTags) {
390
410
  const parts = [];
391
411
  for (let index = 0; index < nodes.length; index += 1) {
392
412
  const node = nodes[index];
393
413
  if (isConditionalElement(node)) {
394
- const { rendered, endIndex } = this.renderConditionalSequence(nodes, index, scopeVar, wxsVar);
414
+ const { rendered, endIndex } = this.renderConditionalSequence(
415
+ nodes,
416
+ index,
417
+ scopeVar,
418
+ wxsVar,
419
+ componentTags
420
+ );
395
421
  parts.push(rendered);
396
422
  index = endIndex;
397
423
  continue;
398
424
  }
399
- parts.push(this.renderNode(node, scopeVar, wxsVar));
425
+ parts.push(this.renderNode(node, scopeVar, wxsVar, componentTags));
400
426
  }
401
427
  if (parts.length === 0) {
402
428
  return '""';
@@ -406,7 +432,7 @@ var Renderer = class {
406
432
  }
407
433
  return `[${parts.join(", ")}]`;
408
434
  }
409
- renderConditionalSequence(nodes, startIndex, scopeVar, wxsVar) {
435
+ renderConditionalSequence(nodes, startIndex, scopeVar, wxsVar, componentTags) {
410
436
  const branches = [];
411
437
  let cursor = startIndex;
412
438
  while (cursor < nodes.length) {
@@ -432,44 +458,44 @@ var Renderer = class {
432
458
  if (!node) {
433
459
  return { rendered: '""', endIndex: startIndex };
434
460
  }
435
- return { rendered: this.renderNode(node, scopeVar, wxsVar), endIndex: startIndex };
461
+ return { rendered: this.renderNode(node, scopeVar, wxsVar, componentTags), endIndex: startIndex };
436
462
  }
437
463
  let expr = '""';
438
464
  for (let index = branches.length - 1; index >= 0; index -= 1) {
439
465
  const { node, attribs } = branches[index];
440
466
  const cleanedAttribs = stripControlAttributes(attribs);
441
467
  if ("wx:else" in attribs) {
442
- expr = this.renderElement(node, scopeVar, wxsVar, { overrideAttribs: cleanedAttribs });
468
+ expr = this.renderElement(node, scopeVar, wxsVar, componentTags, { overrideAttribs: cleanedAttribs });
443
469
  continue;
444
470
  }
445
471
  const conditionExpr = attribs["wx:if"] ?? attribs["wx:elif"] ?? "";
446
- const rendered = this.renderElement(node, scopeVar, wxsVar, { overrideAttribs: cleanedAttribs });
472
+ const rendered = this.renderElement(node, scopeVar, wxsVar, componentTags, { overrideAttribs: cleanedAttribs });
447
473
  const condition = buildExpression(parseInterpolations(conditionExpr), scopeVar, wxsVar);
448
474
  expr = `(${condition} ? ${rendered} : ${expr})`;
449
475
  }
450
476
  return { rendered: expr, endIndex: startIndex + branches.length - 1 };
451
477
  }
452
- renderNode(node, scopeVar, wxsVar) {
478
+ renderNode(node, scopeVar, wxsVar, componentTags) {
453
479
  if (node.type === "text") {
454
480
  const parts = parseInterpolations(node.data ?? "");
455
481
  return buildExpression(parts, scopeVar, wxsVar);
456
482
  }
457
483
  if (node.type === "element") {
458
484
  if (node.name === "template" && node.attribs?.is) {
459
- return this.renderTemplateInvoke(node, scopeVar, wxsVar);
485
+ return this.renderTemplateInvoke(node, scopeVar, wxsVar, componentTags);
460
486
  }
461
- return this.renderElement(node, scopeVar, wxsVar);
487
+ return this.renderElement(node, scopeVar, wxsVar, componentTags);
462
488
  }
463
489
  return '""';
464
490
  }
465
- renderTemplateInvoke(node, scopeVar, wxsVar) {
491
+ renderTemplateInvoke(node, scopeVar, wxsVar, _componentTags) {
466
492
  const attribs = node.attribs ?? {};
467
493
  const isExpr = buildExpression(parseInterpolations(attribs.is ?? ""), scopeVar, wxsVar);
468
494
  const dataExpr = attribs.data ? buildExpression(parseInterpolations(attribs.data), scopeVar, wxsVar) : void 0;
469
495
  const scopeExpr = dataExpr ? `ctx.mergeScope(${scopeVar}, ${dataExpr})` : scopeVar;
470
496
  return `ctx.renderTemplate(__templates, ${isExpr}, ${scopeExpr}, ctx)`;
471
497
  }
472
- renderElement(node, scopeVar, wxsVar, options = {}) {
498
+ renderElement(node, scopeVar, wxsVar, componentTags, options = {}) {
473
499
  const attribs = options.overrideAttribs ?? node.attribs ?? {};
474
500
  if (!options.skipFor) {
475
501
  const forInfo = extractFor(node.attribs ?? {});
@@ -483,19 +509,24 @@ var Renderer = class {
483
509
  node,
484
510
  "__scope",
485
511
  wxsVar,
512
+ componentTags,
486
513
  { skipFor: true, overrideAttribs: forInfo.restAttribs }
487
514
  );
488
515
  const keyExpr = `ctx.key(${JSON.stringify(forInfo.key ?? "")}, ${itemVar}, ${indexVar}, ${scopeExpr}, ${wxsVar})`;
489
516
  return `repeat(${listExpr}, (${itemVar}, ${indexVar}) => ${keyExpr}, (${itemVar}, ${indexVar}) => { const __scope = ${scopeExpr}; return ${itemRender}; })`;
490
517
  }
491
518
  }
492
- const tagName = normalizeTagName(node.name ?? "");
519
+ const customTag = resolveComponentTagName(node.name ?? "", componentTags);
520
+ const tagName = customTag ?? normalizeTagName(node.name ?? "");
493
521
  if (tagName === "#fragment") {
494
- return this.renderNodes(node.children ?? [], scopeVar, wxsVar);
522
+ return this.renderNodes(node.children ?? [], scopeVar, wxsVar, componentTags);
495
523
  }
496
- const attrs = renderAttributes(attribs, scopeVar, wxsVar, { skipControl: true });
524
+ const attrs = renderAttributes(attribs, scopeVar, wxsVar, {
525
+ skipControl: true,
526
+ preferProperty: Boolean(customTag)
527
+ });
497
528
  const childNodes = node.children ?? [];
498
- const children = childNodes.map((child) => `\${${this.renderNode(child, scopeVar, wxsVar)}}`).join("");
529
+ const children = childNodes.map((child) => `\${${this.renderNode(child, scopeVar, wxsVar, componentTags)}}`).join("");
499
530
  if (SELF_CLOSING_TAGS.has(tagName) && childNodes.length === 0) {
500
531
  return `html\`<${tagName}${attrs} />\``;
501
532
  }
@@ -640,7 +671,7 @@ function compileWxml(options) {
640
671
  templatePairs.push(`...${entry.importName}`);
641
672
  }
642
673
  for (const template of templates) {
643
- const rendered = renderer.renderNodes(template.nodes, "scope", "__wxs_modules");
674
+ const rendered = renderer.renderNodes(template.nodes, "scope", "__wxs_modules", options.componentTags);
644
675
  templatePairs.push(`${JSON.stringify(template.name)}: (scope, ctx) => ${rendered}`);
645
676
  }
646
677
  bodyLines.push(`const __templates = { ${templatePairs.join(", ")} }`);
@@ -677,7 +708,7 @@ function compileWxml(options) {
677
708
  bodyLines.push(`const __wxs_modules = {}`);
678
709
  }
679
710
  const includesRender = includes.map((entry) => `${entry.importName}(scope, ctx)`);
680
- const renderContent = renderer.renderNodes(renderNodesList, "scope", "__wxs_modules");
711
+ const renderContent = renderer.renderNodes(renderNodesList, "scope", "__wxs_modules", options.componentTags);
681
712
  const contentExpr = includesRender.length > 0 ? `[${[...includesRender, renderContent].join(", ")}]` : renderContent;
682
713
  bodyLines.push(`export function render(scope, ctx) {`);
683
714
  if (wxs.length > 0) {
@@ -741,6 +772,12 @@ function transformWxsToEsm(code, id, options) {
741
772
  return { code: body, dependencies };
742
773
  }
743
774
 
775
+ // src/shared/slugify.ts
776
+ function slugify(id, prefix) {
777
+ const normalized = id.replace(/[^a-z0-9]+/gi, "-").replace(/^-+|-+$/g, "").toLowerCase();
778
+ return `${prefix}-${normalized || "index"}`;
779
+ }
780
+
744
781
  // src/plugin.ts
745
782
  var traverseCandidate = (() => {
746
783
  const mod = _babelTraverse;
@@ -779,7 +816,11 @@ function weappWebPlugin(options = {}) {
779
816
  let enableHmr = false;
780
817
  const moduleMeta = /* @__PURE__ */ new Map();
781
818
  const pageNavigationMap = /* @__PURE__ */ new Map();
819
+ const templateComponentMap = /* @__PURE__ */ new Map();
820
+ const componentTagMap = /* @__PURE__ */ new Map();
821
+ const componentIdMap = /* @__PURE__ */ new Map();
782
822
  let appNavigationDefaults = {};
823
+ let appComponentTags = {};
783
824
  let scanResult = {
784
825
  app: void 0,
785
826
  pages: [],
@@ -795,10 +836,10 @@ function weappWebPlugin(options = {}) {
795
836
  root = config.root;
796
837
  srcRoot = resolve(root, options.srcDir ?? "src");
797
838
  enableHmr = config.command === "serve";
798
- await scanProject();
839
+ await scanProject(this.warn?.bind(this));
799
840
  },
800
841
  async buildStart() {
801
- await scanProject();
842
+ await scanProject(this.warn?.bind(this));
802
843
  },
803
844
  resolveId(id) {
804
845
  if (id === "/@weapp-vite/web/entry" || id === "@weapp-vite/web/entry") {
@@ -815,19 +856,22 @@ function weappWebPlugin(options = {}) {
815
856
  async handleHotUpdate(ctx) {
816
857
  const clean = cleanUrl(ctx.file);
817
858
  if (clean.endsWith(".json") || isTemplateFile(clean) || isWxsFile(clean) || clean.endsWith(".wxss") || SCRIPT_EXTS.includes(extname(clean))) {
818
- await scanProject();
859
+ await scanProject(this.warn?.bind(this));
819
860
  }
820
861
  },
821
862
  transform(code, id) {
822
863
  const clean = cleanUrl(id);
823
864
  if (isTemplateFile(clean)) {
824
- const navigationConfig = pageNavigationMap.get(normalizePath2(clean));
865
+ const normalizedId = normalizePath2(clean);
866
+ const navigationConfig = pageNavigationMap.get(normalizedId);
867
+ const componentTags = templateComponentMap.get(normalizedId);
825
868
  const { code: compiled, dependencies, warnings } = compileWxml({
826
869
  id: clean,
827
870
  source: code,
828
871
  resolveTemplatePath,
829
872
  resolveWxsPath,
830
- navigationBar: navigationConfig ? { config: navigationConfig } : void 0
873
+ navigationBar: navigationConfig ? { config: navigationConfig } : void 0,
874
+ componentTags
831
875
  });
832
876
  if (dependencies.length > 0 && "addWatchFile" in this) {
833
877
  for (const dep of dependencies) {
@@ -981,12 +1025,23 @@ if (import.meta.hot) { import.meta.hot.accept() }
981
1025
  };
982
1026
  }
983
1027
  };
984
- async function scanProject() {
1028
+ async function scanProject(warn) {
985
1029
  moduleMeta.clear();
986
1030
  pageNavigationMap.clear();
1031
+ templateComponentMap.clear();
1032
+ componentTagMap.clear();
1033
+ componentIdMap.clear();
987
1034
  appNavigationDefaults = {};
1035
+ appComponentTags = {};
988
1036
  const pages = /* @__PURE__ */ new Map();
989
1037
  const components = /* @__PURE__ */ new Map();
1038
+ const reportWarning = (message) => {
1039
+ if (warn) {
1040
+ warn(message);
1041
+ return;
1042
+ }
1043
+ console.warn(message);
1044
+ };
990
1045
  const appScript = await resolveScriptFile(join(srcRoot, "app"));
991
1046
  if (appScript) {
992
1047
  moduleMeta.set(
@@ -1002,6 +1057,11 @@ if (import.meta.hot) { import.meta.hot.accept() }
1002
1057
  const appJsonPath = join(srcRoot, "app.json");
1003
1058
  if (await fs.pathExists(appJsonPath)) {
1004
1059
  const appJson = await readJsonFile(appJsonPath);
1060
+ if (appJson) {
1061
+ appComponentTags = await collectComponentTagsFromConfig(appJson, srcRoot, appJsonPath, reportWarning, (tags) => {
1062
+ appComponentTags = tags;
1063
+ });
1064
+ }
1005
1065
  if (appJson?.pages && Array.isArray(appJson.pages)) {
1006
1066
  for (const page of appJson.pages) {
1007
1067
  if (typeof page === "string") {
@@ -1059,17 +1119,22 @@ if (import.meta.hot) { import.meta.hot.accept() }
1059
1119
  script,
1060
1120
  id: toPosixId(pageId)
1061
1121
  });
1122
+ const pageComponentTags = pageJson ? await collectComponentTagsFromConfig(pageJson, dirname2(script), pageJsonPath, reportWarning) : await collectComponentTagsFromJson(pageJsonPath, dirname2(script), reportWarning);
1123
+ if (template) {
1124
+ const mergedTags = mergeComponentTags(appComponentTags, pageComponentTags);
1125
+ if (Object.keys(mergedTags).length > 0) {
1126
+ templateComponentMap.set(normalizePath2(template), mergedTags);
1127
+ } else {
1128
+ templateComponentMap.delete(normalizePath2(template));
1129
+ }
1130
+ }
1062
1131
  if (pageJson) {
1063
- await collectComponentsFromConfig(pageJson, dirname2(script));
1064
1132
  if (template) {
1065
1133
  const config = mergeNavigationConfig(appNavigationDefaults, pickNavigationConfig(pageJson));
1066
1134
  pageNavigationMap.set(normalizePath2(template), config);
1067
1135
  }
1068
- } else {
1069
- await collectComponentsFromJson(pageJsonPath, dirname2(script));
1070
- if (template) {
1071
- pageNavigationMap.set(normalizePath2(template), { ...appNavigationDefaults });
1072
- }
1136
+ } else if (template) {
1137
+ pageNavigationMap.set(normalizePath2(template), { ...appNavigationDefaults });
1073
1138
  }
1074
1139
  }
1075
1140
  async function collectComponent(componentId, importerDir) {
@@ -1099,26 +1164,94 @@ if (import.meta.hot) { import.meta.hot.accept() }
1099
1164
  script,
1100
1165
  id: componentIdPosix
1101
1166
  });
1102
- await collectComponentsFromJson(`${script.replace(new RegExp(`${extname(script)}$`), "")}.json`, dirname2(script));
1167
+ const componentJsonPath = `${script.replace(new RegExp(`${extname(script)}$`), "")}.json`;
1168
+ const componentTags = await collectComponentTagsFromJson(componentJsonPath, dirname2(script), reportWarning);
1169
+ if (template) {
1170
+ const mergedTags = mergeComponentTags(appComponentTags, componentTags);
1171
+ if (Object.keys(mergedTags).length > 0) {
1172
+ templateComponentMap.set(normalizePath2(template), mergedTags);
1173
+ } else {
1174
+ templateComponentMap.delete(normalizePath2(template));
1175
+ }
1176
+ }
1103
1177
  }
1104
- async function collectComponentsFromConfig(json, importerDir) {
1178
+ async function collectComponentTagsFromConfig(json, importerDir, jsonPath, warn2, onResolved) {
1105
1179
  const usingComponents = json.usingComponents;
1106
1180
  if (!usingComponents || typeof usingComponents !== "object") {
1107
- return;
1181
+ return {};
1108
1182
  }
1109
- for (const value of Object.values(usingComponents)) {
1110
- if (typeof value !== "string") {
1183
+ const tags = {};
1184
+ const resolved = [];
1185
+ for (const [rawKey, rawValue] of Object.entries(usingComponents)) {
1186
+ if (typeof rawValue !== "string") {
1187
+ continue;
1188
+ }
1189
+ const key = normalizeComponentKey(rawKey);
1190
+ if (!key) {
1191
+ continue;
1192
+ }
1193
+ const script = await resolveComponentScript(rawValue, importerDir);
1194
+ if (!script) {
1195
+ warn2(`[@weapp-vite/web] usingComponents entry "${rawKey}" not found: ${rawValue} (${jsonPath})`);
1111
1196
  continue;
1112
1197
  }
1113
- await collectComponent(value, importerDir);
1198
+ const tag = getComponentTag(script);
1199
+ if (tag) {
1200
+ tags[key] = tag;
1201
+ resolved.push({ rawValue });
1202
+ }
1203
+ }
1204
+ onResolved?.(tags);
1205
+ for (const entry of resolved) {
1206
+ await collectComponent(entry.rawValue, importerDir);
1114
1207
  }
1208
+ return tags;
1115
1209
  }
1116
- async function collectComponentsFromJson(jsonPath, importerDir) {
1210
+ async function collectComponentTagsFromJson(jsonPath, importerDir, warn2) {
1117
1211
  const json = await readJsonFile(jsonPath);
1118
1212
  if (!json) {
1119
- return;
1213
+ return {};
1214
+ }
1215
+ return collectComponentTagsFromConfig(json, importerDir, jsonPath, warn2);
1216
+ }
1217
+ function mergeComponentTags(base, overrides) {
1218
+ if (!Object.keys(base).length && !Object.keys(overrides).length) {
1219
+ return {};
1220
+ }
1221
+ return {
1222
+ ...base,
1223
+ ...overrides
1224
+ };
1225
+ }
1226
+ function normalizeComponentKey(raw) {
1227
+ return raw.trim().toLowerCase();
1228
+ }
1229
+ function getComponentId(script) {
1230
+ const cached = componentIdMap.get(script);
1231
+ if (cached) {
1232
+ return cached;
1233
+ }
1234
+ const idRelative = relative2(srcRoot, script).replace(new RegExp(`${extname(script)}$`), "");
1235
+ const componentIdPosix = toPosixId(idRelative);
1236
+ componentIdMap.set(script, componentIdPosix);
1237
+ return componentIdPosix;
1238
+ }
1239
+ function getComponentTag(script) {
1240
+ const cached = componentTagMap.get(script);
1241
+ if (cached) {
1242
+ return cached;
1243
+ }
1244
+ const id = getComponentId(script);
1245
+ const tag = slugify(id, "wv-component");
1246
+ componentTagMap.set(script, tag);
1247
+ return tag;
1248
+ }
1249
+ async function resolveComponentScript(raw, importerDir) {
1250
+ const base = resolveComponentBase(raw, importerDir);
1251
+ if (!base) {
1252
+ return void 0;
1120
1253
  }
1121
- await collectComponentsFromConfig(json, importerDir);
1254
+ return resolveScriptFile(base);
1122
1255
  }
1123
1256
  function resolveComponentBase(raw, importerDir) {
1124
1257
  if (!raw) {
@@ -1397,7 +1530,23 @@ var NAV_BUTTON_TAG = "weapp-button";
1397
1530
  var BaseElement = globalThis.HTMLElement ?? class {
1398
1531
  };
1399
1532
  var formConfig = { ...DEFAULT_FORM_CONFIG };
1400
- var styleInjected = false;
1533
+ var styleTargets = /* @__PURE__ */ new WeakSet();
1534
+ var sharedSheet;
1535
+ function resolveAdoptedStyleSheets(root) {
1536
+ const doc = root.ownerDocument ?? document;
1537
+ if (!doc || typeof doc.createElement !== "function") {
1538
+ return void 0;
1539
+ }
1540
+ if (!("adoptedStyleSheets" in doc)) {
1541
+ return void 0;
1542
+ }
1543
+ if (!sharedSheet && "replaceSync" in CSSStyleSheet.prototype) {
1544
+ const sheet = new CSSStyleSheet();
1545
+ sheet.replaceSync(BUTTON_STYLE);
1546
+ sharedSheet = sheet;
1547
+ }
1548
+ return sharedSheet;
1549
+ }
1401
1550
  var BUTTON_STYLE = `
1402
1551
  weapp-button {
1403
1552
  display: block;
@@ -1415,8 +1564,8 @@ weapp-button .weapp-btn {
1415
1564
  -webkit-appearance: none;
1416
1565
  box-sizing: border-box;
1417
1566
  width: 100%;
1418
- border-radius: 6px;
1419
- border: 1px solid #d7d7d7;
1567
+ border-radius: 5px;
1568
+ border: 1px solid #d9d9d9;
1420
1569
  padding: 0 16px;
1421
1570
  height: 44px;
1422
1571
  line-height: 44px;
@@ -1447,7 +1596,7 @@ weapp-button.weapp-btn--plain .weapp-btn {
1447
1596
  }
1448
1597
 
1449
1598
  weapp-button.weapp-btn--plain.weapp-btn--default .weapp-btn {
1450
- border-color: #353535;
1599
+ border-color: #b2b2b2;
1451
1600
  color: #353535;
1452
1601
  }
1453
1602
 
@@ -1463,21 +1612,34 @@ weapp-button.weapp-btn--plain.weapp-btn--warn .weapp-btn {
1463
1612
 
1464
1613
  weapp-button.weapp-btn--loading .weapp-btn,
1465
1614
  weapp-button.weapp-btn--disabled .weapp-btn {
1466
- opacity: 0.6;
1615
+ background-color: #f7f7f7;
1616
+ border-color: #d9d9d9;
1617
+ color: #9b9b9b;
1467
1618
  cursor: not-allowed;
1468
1619
  }
1469
1620
 
1470
1621
  weapp-button.button-hover .weapp-btn {
1471
- opacity: 0.7;
1622
+ background-color: #ededed;
1623
+ border-color: #d2d2d2;
1624
+ }
1625
+
1626
+ weapp-button.button-hover.weapp-btn--primary .weapp-btn {
1627
+ background-color: #06ad56;
1628
+ border-color: #06ad56;
1629
+ }
1630
+
1631
+ weapp-button.button-hover.weapp-btn--warn .weapp-btn {
1632
+ background-color: #d93c37;
1633
+ border-color: #d93c37;
1472
1634
  }
1473
1635
 
1474
1636
  weapp-button.button-hover.weapp-btn--plain .weapp-btn {
1475
- background-color: rgba(0, 0, 0, 0.1);
1637
+ background-color: rgba(0, 0, 0, 0.06);
1476
1638
  }
1477
1639
 
1478
1640
  weapp-button.weapp-btn--mini .weapp-btn {
1479
- height: 28px;
1480
- line-height: 28px;
1641
+ height: 32px;
1642
+ line-height: 32px;
1481
1643
  font-size: 13px;
1482
1644
  padding: 0 12px;
1483
1645
  border-radius: 4px;
@@ -1509,12 +1671,36 @@ weapp-button .weapp-btn__loading[hidden] {
1509
1671
  to { transform: rotate(360deg); }
1510
1672
  }
1511
1673
  `;
1512
- function ensureButtonStyle() {
1513
- if (styleInjected) {
1674
+ function ensureButtonStyle(root) {
1675
+ if (typeof document === "undefined") {
1676
+ return;
1677
+ }
1678
+ if (root && styleTargets.has(root)) {
1514
1679
  return;
1515
1680
  }
1516
- injectStyle(BUTTON_STYLE, BUTTON_STYLE_ID);
1517
- styleInjected = true;
1681
+ if (!root) {
1682
+ const target = document.head;
1683
+ if (!target || styleTargets.has(target)) {
1684
+ return;
1685
+ }
1686
+ injectStyle(BUTTON_STYLE, BUTTON_STYLE_ID);
1687
+ styleTargets.add(target);
1688
+ return;
1689
+ }
1690
+ const sheet = resolveAdoptedStyleSheets(root);
1691
+ if (sheet) {
1692
+ const existing = root.adoptedStyleSheets ?? [];
1693
+ if (!existing.includes(sheet)) {
1694
+ root.adoptedStyleSheets = [...existing, sheet];
1695
+ }
1696
+ styleTargets.add(root);
1697
+ return;
1698
+ }
1699
+ const style = document.createElement("style");
1700
+ style.id = BUTTON_STYLE_ID;
1701
+ style.textContent = BUTTON_STYLE;
1702
+ root.appendChild(style);
1703
+ styleTargets.add(root);
1518
1704
  }
1519
1705
  function toBoolean(value) {
1520
1706
  if (value === null) {
@@ -1665,7 +1851,12 @@ var WeappButton = class extends BaseElement {
1665
1851
  #lastTouchTime = 0;
1666
1852
  #observer;
1667
1853
  connectedCallback() {
1668
- ensureButtonStyle();
1854
+ const root = this.getRootNode();
1855
+ if (root instanceof ShadowRoot) {
1856
+ ensureButtonStyle(root);
1857
+ } else {
1858
+ ensureButtonStyle();
1859
+ }
1669
1860
  this.#ensureStructure();
1670
1861
  this.#applyState();
1671
1862
  this.#bindEvents();
@@ -2728,10 +2919,6 @@ var RESERVED_COMPONENT_METHOD_KEYS = /* @__PURE__ */ new Set([
2728
2919
  "observers",
2729
2920
  "mixins"
2730
2921
  ]);
2731
- function slugify(id, prefix) {
2732
- const normalized = id.replace(/[^a-z0-9]+/gi, "-").replace(/^-+|-+$/g, "").toLowerCase();
2733
- return `${prefix}-${normalized || "index"}`;
2734
- }
2735
2922
  function ensureDocumentReady(callback) {
2736
2923
  if (typeof document === "undefined") {
2737
2924
  return;
package/dist/plugin.mjs CHANGED
@@ -339,6 +339,25 @@ function parseEventAttribute(name) {
339
339
  }
340
340
  return { prefix: name.slice(0, name.length - match[1].length), rawEvent: match[1] };
341
341
  }
342
+ function resolveComponentTagName(name, componentTags) {
343
+ if (!componentTags) {
344
+ return void 0;
345
+ }
346
+ return componentTags[name] ?? componentTags[name.toLowerCase()];
347
+ }
348
+ var PROPERTY_BIND_EXCLUSIONS = /* @__PURE__ */ new Set(["class", "style", "id", "slot"]);
349
+ function shouldBindAsProperty(name) {
350
+ if (PROPERTY_BIND_EXCLUSIONS.has(name)) {
351
+ return false;
352
+ }
353
+ if (name.startsWith("data-") || name.startsWith("aria-")) {
354
+ return false;
355
+ }
356
+ return true;
357
+ }
358
+ function normalizePropertyName(name) {
359
+ return name.replace(/-([a-z])/g, (_, char) => char.toUpperCase());
360
+ }
342
361
  function renderAttributes(attribs, scopeVar, wxsVar, options) {
343
362
  let buffer = "";
344
363
  for (const [rawName, rawValue] of Object.entries(attribs)) {
@@ -357,24 +376,31 @@ function renderAttributes(attribs, scopeVar, wxsVar, options) {
357
376
  buffer += ` @${domEvent}=\${ctx.event(${JSON.stringify(event)}, ${handlerExpr}, ${scopeVar}, ${wxsVar}, ${JSON.stringify(flags)})}`;
358
377
  continue;
359
378
  }
360
- const name = normalizeAttributeName(rawName);
379
+ const useProperty = options?.preferProperty && shouldBindAsProperty(rawName);
380
+ const name = useProperty ? normalizePropertyName(rawName) : normalizeAttributeName(rawName);
361
381
  const expr = buildExpression(parseInterpolations(rawValue ?? ""), scopeVar, wxsVar);
362
- buffer += ` ${name}=\${${expr}}`;
382
+ buffer += ` ${useProperty ? "." : ""}${name}=\${${expr}}`;
363
383
  }
364
384
  return buffer;
365
385
  }
366
386
  var Renderer = class {
367
- renderNodes(nodes, scopeVar, wxsVar) {
387
+ renderNodes(nodes, scopeVar, wxsVar, componentTags) {
368
388
  const parts = [];
369
389
  for (let index = 0; index < nodes.length; index += 1) {
370
390
  const node = nodes[index];
371
391
  if (isConditionalElement(node)) {
372
- const { rendered, endIndex } = this.renderConditionalSequence(nodes, index, scopeVar, wxsVar);
392
+ const { rendered, endIndex } = this.renderConditionalSequence(
393
+ nodes,
394
+ index,
395
+ scopeVar,
396
+ wxsVar,
397
+ componentTags
398
+ );
373
399
  parts.push(rendered);
374
400
  index = endIndex;
375
401
  continue;
376
402
  }
377
- parts.push(this.renderNode(node, scopeVar, wxsVar));
403
+ parts.push(this.renderNode(node, scopeVar, wxsVar, componentTags));
378
404
  }
379
405
  if (parts.length === 0) {
380
406
  return '""';
@@ -384,7 +410,7 @@ var Renderer = class {
384
410
  }
385
411
  return `[${parts.join(", ")}]`;
386
412
  }
387
- renderConditionalSequence(nodes, startIndex, scopeVar, wxsVar) {
413
+ renderConditionalSequence(nodes, startIndex, scopeVar, wxsVar, componentTags) {
388
414
  const branches = [];
389
415
  let cursor = startIndex;
390
416
  while (cursor < nodes.length) {
@@ -410,44 +436,44 @@ var Renderer = class {
410
436
  if (!node) {
411
437
  return { rendered: '""', endIndex: startIndex };
412
438
  }
413
- return { rendered: this.renderNode(node, scopeVar, wxsVar), endIndex: startIndex };
439
+ return { rendered: this.renderNode(node, scopeVar, wxsVar, componentTags), endIndex: startIndex };
414
440
  }
415
441
  let expr = '""';
416
442
  for (let index = branches.length - 1; index >= 0; index -= 1) {
417
443
  const { node, attribs } = branches[index];
418
444
  const cleanedAttribs = stripControlAttributes(attribs);
419
445
  if ("wx:else" in attribs) {
420
- expr = this.renderElement(node, scopeVar, wxsVar, { overrideAttribs: cleanedAttribs });
446
+ expr = this.renderElement(node, scopeVar, wxsVar, componentTags, { overrideAttribs: cleanedAttribs });
421
447
  continue;
422
448
  }
423
449
  const conditionExpr = attribs["wx:if"] ?? attribs["wx:elif"] ?? "";
424
- const rendered = this.renderElement(node, scopeVar, wxsVar, { overrideAttribs: cleanedAttribs });
450
+ const rendered = this.renderElement(node, scopeVar, wxsVar, componentTags, { overrideAttribs: cleanedAttribs });
425
451
  const condition = buildExpression(parseInterpolations(conditionExpr), scopeVar, wxsVar);
426
452
  expr = `(${condition} ? ${rendered} : ${expr})`;
427
453
  }
428
454
  return { rendered: expr, endIndex: startIndex + branches.length - 1 };
429
455
  }
430
- renderNode(node, scopeVar, wxsVar) {
456
+ renderNode(node, scopeVar, wxsVar, componentTags) {
431
457
  if (node.type === "text") {
432
458
  const parts = parseInterpolations(node.data ?? "");
433
459
  return buildExpression(parts, scopeVar, wxsVar);
434
460
  }
435
461
  if (node.type === "element") {
436
462
  if (node.name === "template" && node.attribs?.is) {
437
- return this.renderTemplateInvoke(node, scopeVar, wxsVar);
463
+ return this.renderTemplateInvoke(node, scopeVar, wxsVar, componentTags);
438
464
  }
439
- return this.renderElement(node, scopeVar, wxsVar);
465
+ return this.renderElement(node, scopeVar, wxsVar, componentTags);
440
466
  }
441
467
  return '""';
442
468
  }
443
- renderTemplateInvoke(node, scopeVar, wxsVar) {
469
+ renderTemplateInvoke(node, scopeVar, wxsVar, _componentTags) {
444
470
  const attribs = node.attribs ?? {};
445
471
  const isExpr = buildExpression(parseInterpolations(attribs.is ?? ""), scopeVar, wxsVar);
446
472
  const dataExpr = attribs.data ? buildExpression(parseInterpolations(attribs.data), scopeVar, wxsVar) : void 0;
447
473
  const scopeExpr = dataExpr ? `ctx.mergeScope(${scopeVar}, ${dataExpr})` : scopeVar;
448
474
  return `ctx.renderTemplate(__templates, ${isExpr}, ${scopeExpr}, ctx)`;
449
475
  }
450
- renderElement(node, scopeVar, wxsVar, options = {}) {
476
+ renderElement(node, scopeVar, wxsVar, componentTags, options = {}) {
451
477
  const attribs = options.overrideAttribs ?? node.attribs ?? {};
452
478
  if (!options.skipFor) {
453
479
  const forInfo = extractFor(node.attribs ?? {});
@@ -461,19 +487,24 @@ var Renderer = class {
461
487
  node,
462
488
  "__scope",
463
489
  wxsVar,
490
+ componentTags,
464
491
  { skipFor: true, overrideAttribs: forInfo.restAttribs }
465
492
  );
466
493
  const keyExpr = `ctx.key(${JSON.stringify(forInfo.key ?? "")}, ${itemVar}, ${indexVar}, ${scopeExpr}, ${wxsVar})`;
467
494
  return `repeat(${listExpr}, (${itemVar}, ${indexVar}) => ${keyExpr}, (${itemVar}, ${indexVar}) => { const __scope = ${scopeExpr}; return ${itemRender}; })`;
468
495
  }
469
496
  }
470
- const tagName = normalizeTagName(node.name ?? "");
497
+ const customTag = resolveComponentTagName(node.name ?? "", componentTags);
498
+ const tagName = customTag ?? normalizeTagName(node.name ?? "");
471
499
  if (tagName === "#fragment") {
472
- return this.renderNodes(node.children ?? [], scopeVar, wxsVar);
500
+ return this.renderNodes(node.children ?? [], scopeVar, wxsVar, componentTags);
473
501
  }
474
- const attrs = renderAttributes(attribs, scopeVar, wxsVar, { skipControl: true });
502
+ const attrs = renderAttributes(attribs, scopeVar, wxsVar, {
503
+ skipControl: true,
504
+ preferProperty: Boolean(customTag)
505
+ });
475
506
  const childNodes = node.children ?? [];
476
- const children = childNodes.map((child) => `\${${this.renderNode(child, scopeVar, wxsVar)}}`).join("");
507
+ const children = childNodes.map((child) => `\${${this.renderNode(child, scopeVar, wxsVar, componentTags)}}`).join("");
477
508
  if (SELF_CLOSING_TAGS.has(tagName) && childNodes.length === 0) {
478
509
  return `html\`<${tagName}${attrs} />\``;
479
510
  }
@@ -618,7 +649,7 @@ function compileWxml(options) {
618
649
  templatePairs.push(`...${entry.importName}`);
619
650
  }
620
651
  for (const template of templates) {
621
- const rendered = renderer.renderNodes(template.nodes, "scope", "__wxs_modules");
652
+ const rendered = renderer.renderNodes(template.nodes, "scope", "__wxs_modules", options.componentTags);
622
653
  templatePairs.push(`${JSON.stringify(template.name)}: (scope, ctx) => ${rendered}`);
623
654
  }
624
655
  bodyLines.push(`const __templates = { ${templatePairs.join(", ")} }`);
@@ -655,7 +686,7 @@ function compileWxml(options) {
655
686
  bodyLines.push(`const __wxs_modules = {}`);
656
687
  }
657
688
  const includesRender = includes.map((entry) => `${entry.importName}(scope, ctx)`);
658
- const renderContent = renderer.renderNodes(renderNodesList, "scope", "__wxs_modules");
689
+ const renderContent = renderer.renderNodes(renderNodesList, "scope", "__wxs_modules", options.componentTags);
659
690
  const contentExpr = includesRender.length > 0 ? `[${[...includesRender, renderContent].join(", ")}]` : renderContent;
660
691
  bodyLines.push(`export function render(scope, ctx) {`);
661
692
  if (wxs.length > 0) {
@@ -741,6 +772,12 @@ function transformWxssToCss(source, options) {
741
772
  };
742
773
  }
743
774
 
775
+ // src/shared/slugify.ts
776
+ function slugify(id, prefix) {
777
+ const normalized = id.replace(/[^a-z0-9]+/gi, "-").replace(/^-+|-+$/g, "").toLowerCase();
778
+ return `${prefix}-${normalized || "index"}`;
779
+ }
780
+
744
781
  // src/plugin.ts
745
782
  var traverseCandidate = (() => {
746
783
  const mod = _babelTraverse;
@@ -779,7 +816,11 @@ function weappWebPlugin(options = {}) {
779
816
  let enableHmr = false;
780
817
  const moduleMeta = /* @__PURE__ */ new Map();
781
818
  const pageNavigationMap = /* @__PURE__ */ new Map();
819
+ const templateComponentMap = /* @__PURE__ */ new Map();
820
+ const componentTagMap = /* @__PURE__ */ new Map();
821
+ const componentIdMap = /* @__PURE__ */ new Map();
782
822
  let appNavigationDefaults = {};
823
+ let appComponentTags = {};
783
824
  let scanResult = {
784
825
  app: void 0,
785
826
  pages: [],
@@ -795,10 +836,10 @@ function weappWebPlugin(options = {}) {
795
836
  root = config.root;
796
837
  srcRoot = resolve(root, options.srcDir ?? "src");
797
838
  enableHmr = config.command === "serve";
798
- await scanProject();
839
+ await scanProject(this.warn?.bind(this));
799
840
  },
800
841
  async buildStart() {
801
- await scanProject();
842
+ await scanProject(this.warn?.bind(this));
802
843
  },
803
844
  resolveId(id) {
804
845
  if (id === "/@weapp-vite/web/entry" || id === "@weapp-vite/web/entry") {
@@ -815,19 +856,22 @@ function weappWebPlugin(options = {}) {
815
856
  async handleHotUpdate(ctx) {
816
857
  const clean = cleanUrl(ctx.file);
817
858
  if (clean.endsWith(".json") || isTemplateFile(clean) || isWxsFile(clean) || clean.endsWith(".wxss") || SCRIPT_EXTS.includes(extname(clean))) {
818
- await scanProject();
859
+ await scanProject(this.warn?.bind(this));
819
860
  }
820
861
  },
821
862
  transform(code, id) {
822
863
  const clean = cleanUrl(id);
823
864
  if (isTemplateFile(clean)) {
824
- const navigationConfig = pageNavigationMap.get(normalizePath2(clean));
865
+ const normalizedId = normalizePath2(clean);
866
+ const navigationConfig = pageNavigationMap.get(normalizedId);
867
+ const componentTags = templateComponentMap.get(normalizedId);
825
868
  const { code: compiled, dependencies, warnings } = compileWxml({
826
869
  id: clean,
827
870
  source: code,
828
871
  resolveTemplatePath,
829
872
  resolveWxsPath,
830
- navigationBar: navigationConfig ? { config: navigationConfig } : void 0
873
+ navigationBar: navigationConfig ? { config: navigationConfig } : void 0,
874
+ componentTags
831
875
  });
832
876
  if (dependencies.length > 0 && "addWatchFile" in this) {
833
877
  for (const dep of dependencies) {
@@ -981,12 +1025,23 @@ if (import.meta.hot) { import.meta.hot.accept() }
981
1025
  };
982
1026
  }
983
1027
  };
984
- async function scanProject() {
1028
+ async function scanProject(warn) {
985
1029
  moduleMeta.clear();
986
1030
  pageNavigationMap.clear();
1031
+ templateComponentMap.clear();
1032
+ componentTagMap.clear();
1033
+ componentIdMap.clear();
987
1034
  appNavigationDefaults = {};
1035
+ appComponentTags = {};
988
1036
  const pages = /* @__PURE__ */ new Map();
989
1037
  const components = /* @__PURE__ */ new Map();
1038
+ const reportWarning = (message) => {
1039
+ if (warn) {
1040
+ warn(message);
1041
+ return;
1042
+ }
1043
+ console.warn(message);
1044
+ };
990
1045
  const appScript = await resolveScriptFile(join(srcRoot, "app"));
991
1046
  if (appScript) {
992
1047
  moduleMeta.set(
@@ -1002,6 +1057,11 @@ if (import.meta.hot) { import.meta.hot.accept() }
1002
1057
  const appJsonPath = join(srcRoot, "app.json");
1003
1058
  if (await fs.pathExists(appJsonPath)) {
1004
1059
  const appJson = await readJsonFile(appJsonPath);
1060
+ if (appJson) {
1061
+ appComponentTags = await collectComponentTagsFromConfig(appJson, srcRoot, appJsonPath, reportWarning, (tags) => {
1062
+ appComponentTags = tags;
1063
+ });
1064
+ }
1005
1065
  if (appJson?.pages && Array.isArray(appJson.pages)) {
1006
1066
  for (const page of appJson.pages) {
1007
1067
  if (typeof page === "string") {
@@ -1059,17 +1119,22 @@ if (import.meta.hot) { import.meta.hot.accept() }
1059
1119
  script,
1060
1120
  id: toPosixId(pageId)
1061
1121
  });
1122
+ const pageComponentTags = pageJson ? await collectComponentTagsFromConfig(pageJson, dirname2(script), pageJsonPath, reportWarning) : await collectComponentTagsFromJson(pageJsonPath, dirname2(script), reportWarning);
1123
+ if (template) {
1124
+ const mergedTags = mergeComponentTags(appComponentTags, pageComponentTags);
1125
+ if (Object.keys(mergedTags).length > 0) {
1126
+ templateComponentMap.set(normalizePath2(template), mergedTags);
1127
+ } else {
1128
+ templateComponentMap.delete(normalizePath2(template));
1129
+ }
1130
+ }
1062
1131
  if (pageJson) {
1063
- await collectComponentsFromConfig(pageJson, dirname2(script));
1064
1132
  if (template) {
1065
1133
  const config = mergeNavigationConfig(appNavigationDefaults, pickNavigationConfig(pageJson));
1066
1134
  pageNavigationMap.set(normalizePath2(template), config);
1067
1135
  }
1068
- } else {
1069
- await collectComponentsFromJson(pageJsonPath, dirname2(script));
1070
- if (template) {
1071
- pageNavigationMap.set(normalizePath2(template), { ...appNavigationDefaults });
1072
- }
1136
+ } else if (template) {
1137
+ pageNavigationMap.set(normalizePath2(template), { ...appNavigationDefaults });
1073
1138
  }
1074
1139
  }
1075
1140
  async function collectComponent(componentId, importerDir) {
@@ -1099,26 +1164,94 @@ if (import.meta.hot) { import.meta.hot.accept() }
1099
1164
  script,
1100
1165
  id: componentIdPosix
1101
1166
  });
1102
- await collectComponentsFromJson(`${script.replace(new RegExp(`${extname(script)}$`), "")}.json`, dirname2(script));
1167
+ const componentJsonPath = `${script.replace(new RegExp(`${extname(script)}$`), "")}.json`;
1168
+ const componentTags = await collectComponentTagsFromJson(componentJsonPath, dirname2(script), reportWarning);
1169
+ if (template) {
1170
+ const mergedTags = mergeComponentTags(appComponentTags, componentTags);
1171
+ if (Object.keys(mergedTags).length > 0) {
1172
+ templateComponentMap.set(normalizePath2(template), mergedTags);
1173
+ } else {
1174
+ templateComponentMap.delete(normalizePath2(template));
1175
+ }
1176
+ }
1103
1177
  }
1104
- async function collectComponentsFromConfig(json, importerDir) {
1178
+ async function collectComponentTagsFromConfig(json, importerDir, jsonPath, warn2, onResolved) {
1105
1179
  const usingComponents = json.usingComponents;
1106
1180
  if (!usingComponents || typeof usingComponents !== "object") {
1107
- return;
1181
+ return {};
1108
1182
  }
1109
- for (const value of Object.values(usingComponents)) {
1110
- if (typeof value !== "string") {
1183
+ const tags = {};
1184
+ const resolved = [];
1185
+ for (const [rawKey, rawValue] of Object.entries(usingComponents)) {
1186
+ if (typeof rawValue !== "string") {
1111
1187
  continue;
1112
1188
  }
1113
- await collectComponent(value, importerDir);
1189
+ const key = normalizeComponentKey(rawKey);
1190
+ if (!key) {
1191
+ continue;
1192
+ }
1193
+ const script = await resolveComponentScript(rawValue, importerDir);
1194
+ if (!script) {
1195
+ warn2(`[@weapp-vite/web] usingComponents entry "${rawKey}" not found: ${rawValue} (${jsonPath})`);
1196
+ continue;
1197
+ }
1198
+ const tag = getComponentTag(script);
1199
+ if (tag) {
1200
+ tags[key] = tag;
1201
+ resolved.push({ rawValue });
1202
+ }
1203
+ }
1204
+ onResolved?.(tags);
1205
+ for (const entry of resolved) {
1206
+ await collectComponent(entry.rawValue, importerDir);
1114
1207
  }
1208
+ return tags;
1115
1209
  }
1116
- async function collectComponentsFromJson(jsonPath, importerDir) {
1210
+ async function collectComponentTagsFromJson(jsonPath, importerDir, warn2) {
1117
1211
  const json = await readJsonFile(jsonPath);
1118
1212
  if (!json) {
1119
- return;
1213
+ return {};
1214
+ }
1215
+ return collectComponentTagsFromConfig(json, importerDir, jsonPath, warn2);
1216
+ }
1217
+ function mergeComponentTags(base, overrides) {
1218
+ if (!Object.keys(base).length && !Object.keys(overrides).length) {
1219
+ return {};
1220
+ }
1221
+ return {
1222
+ ...base,
1223
+ ...overrides
1224
+ };
1225
+ }
1226
+ function normalizeComponentKey(raw) {
1227
+ return raw.trim().toLowerCase();
1228
+ }
1229
+ function getComponentId(script) {
1230
+ const cached = componentIdMap.get(script);
1231
+ if (cached) {
1232
+ return cached;
1233
+ }
1234
+ const idRelative = relative2(srcRoot, script).replace(new RegExp(`${extname(script)}$`), "");
1235
+ const componentIdPosix = toPosixId(idRelative);
1236
+ componentIdMap.set(script, componentIdPosix);
1237
+ return componentIdPosix;
1238
+ }
1239
+ function getComponentTag(script) {
1240
+ const cached = componentTagMap.get(script);
1241
+ if (cached) {
1242
+ return cached;
1243
+ }
1244
+ const id = getComponentId(script);
1245
+ const tag = slugify(id, "wv-component");
1246
+ componentTagMap.set(script, tag);
1247
+ return tag;
1248
+ }
1249
+ async function resolveComponentScript(raw, importerDir) {
1250
+ const base = resolveComponentBase(raw, importerDir);
1251
+ if (!base) {
1252
+ return void 0;
1120
1253
  }
1121
- await collectComponentsFromConfig(json, importerDir);
1254
+ return resolveScriptFile(base);
1122
1255
  }
1123
1256
  function resolveComponentBase(raw, importerDir) {
1124
1257
  if (!raw) {
@@ -49,7 +49,23 @@ var NAV_BUTTON_TAG = "weapp-button";
49
49
  var BaseElement = globalThis.HTMLElement ?? class {
50
50
  };
51
51
  var formConfig = { ...DEFAULT_FORM_CONFIG };
52
- var styleInjected = false;
52
+ var styleTargets = /* @__PURE__ */ new WeakSet();
53
+ var sharedSheet;
54
+ function resolveAdoptedStyleSheets(root) {
55
+ const doc = root.ownerDocument ?? document;
56
+ if (!doc || typeof doc.createElement !== "function") {
57
+ return void 0;
58
+ }
59
+ if (!("adoptedStyleSheets" in doc)) {
60
+ return void 0;
61
+ }
62
+ if (!sharedSheet && "replaceSync" in CSSStyleSheet.prototype) {
63
+ const sheet = new CSSStyleSheet();
64
+ sheet.replaceSync(BUTTON_STYLE);
65
+ sharedSheet = sheet;
66
+ }
67
+ return sharedSheet;
68
+ }
53
69
  var BUTTON_STYLE = `
54
70
  weapp-button {
55
71
  display: block;
@@ -67,8 +83,8 @@ weapp-button .weapp-btn {
67
83
  -webkit-appearance: none;
68
84
  box-sizing: border-box;
69
85
  width: 100%;
70
- border-radius: 6px;
71
- border: 1px solid #d7d7d7;
86
+ border-radius: 5px;
87
+ border: 1px solid #d9d9d9;
72
88
  padding: 0 16px;
73
89
  height: 44px;
74
90
  line-height: 44px;
@@ -99,7 +115,7 @@ weapp-button.weapp-btn--plain .weapp-btn {
99
115
  }
100
116
 
101
117
  weapp-button.weapp-btn--plain.weapp-btn--default .weapp-btn {
102
- border-color: #353535;
118
+ border-color: #b2b2b2;
103
119
  color: #353535;
104
120
  }
105
121
 
@@ -115,21 +131,34 @@ weapp-button.weapp-btn--plain.weapp-btn--warn .weapp-btn {
115
131
 
116
132
  weapp-button.weapp-btn--loading .weapp-btn,
117
133
  weapp-button.weapp-btn--disabled .weapp-btn {
118
- opacity: 0.6;
134
+ background-color: #f7f7f7;
135
+ border-color: #d9d9d9;
136
+ color: #9b9b9b;
119
137
  cursor: not-allowed;
120
138
  }
121
139
 
122
140
  weapp-button.button-hover .weapp-btn {
123
- opacity: 0.7;
141
+ background-color: #ededed;
142
+ border-color: #d2d2d2;
143
+ }
144
+
145
+ weapp-button.button-hover.weapp-btn--primary .weapp-btn {
146
+ background-color: #06ad56;
147
+ border-color: #06ad56;
148
+ }
149
+
150
+ weapp-button.button-hover.weapp-btn--warn .weapp-btn {
151
+ background-color: #d93c37;
152
+ border-color: #d93c37;
124
153
  }
125
154
 
126
155
  weapp-button.button-hover.weapp-btn--plain .weapp-btn {
127
- background-color: rgba(0, 0, 0, 0.1);
156
+ background-color: rgba(0, 0, 0, 0.06);
128
157
  }
129
158
 
130
159
  weapp-button.weapp-btn--mini .weapp-btn {
131
- height: 28px;
132
- line-height: 28px;
160
+ height: 32px;
161
+ line-height: 32px;
133
162
  font-size: 13px;
134
163
  padding: 0 12px;
135
164
  border-radius: 4px;
@@ -161,12 +190,36 @@ weapp-button .weapp-btn__loading[hidden] {
161
190
  to { transform: rotate(360deg); }
162
191
  }
163
192
  `;
164
- function ensureButtonStyle() {
165
- if (styleInjected) {
193
+ function ensureButtonStyle(root) {
194
+ if (typeof document === "undefined") {
195
+ return;
196
+ }
197
+ if (root && styleTargets.has(root)) {
198
+ return;
199
+ }
200
+ if (!root) {
201
+ const target = document.head;
202
+ if (!target || styleTargets.has(target)) {
203
+ return;
204
+ }
205
+ injectStyle(BUTTON_STYLE, BUTTON_STYLE_ID);
206
+ styleTargets.add(target);
207
+ return;
208
+ }
209
+ const sheet = resolveAdoptedStyleSheets(root);
210
+ if (sheet) {
211
+ const existing = root.adoptedStyleSheets ?? [];
212
+ if (!existing.includes(sheet)) {
213
+ root.adoptedStyleSheets = [...existing, sheet];
214
+ }
215
+ styleTargets.add(root);
166
216
  return;
167
217
  }
168
- injectStyle(BUTTON_STYLE, BUTTON_STYLE_ID);
169
- styleInjected = true;
218
+ const style = document.createElement("style");
219
+ style.id = BUTTON_STYLE_ID;
220
+ style.textContent = BUTTON_STYLE;
221
+ root.appendChild(style);
222
+ styleTargets.add(root);
170
223
  }
171
224
  function toBoolean(value) {
172
225
  if (value === null) {
@@ -317,7 +370,12 @@ var WeappButton = class extends BaseElement {
317
370
  #lastTouchTime = 0;
318
371
  #observer;
319
372
  connectedCallback() {
320
- ensureButtonStyle();
373
+ const root = this.getRootNode();
374
+ if (root instanceof ShadowRoot) {
375
+ ensureButtonStyle(root);
376
+ } else {
377
+ ensureButtonStyle();
378
+ }
321
379
  this.#ensureStructure();
322
380
  this.#applyState();
323
381
  this.#bindEvents();
@@ -1319,6 +1377,12 @@ function ensureNavigationBarDefined() {
1319
1377
  }
1320
1378
  }
1321
1379
 
1380
+ // src/shared/slugify.ts
1381
+ function slugify(id, prefix) {
1382
+ const normalized = id.replace(/[^a-z0-9]+/gi, "-").replace(/^-+|-+$/g, "").toLowerCase();
1383
+ return `${prefix}-${normalized || "index"}`;
1384
+ }
1385
+
1322
1386
  // src/runtime/rpx.ts
1323
1387
  var DEFAULT_DESIGN_WIDTH = 750;
1324
1388
  var DEFAULT_VAR_NAME = "--rpx";
@@ -1380,10 +1444,6 @@ var RESERVED_COMPONENT_METHOD_KEYS = /* @__PURE__ */ new Set([
1380
1444
  "observers",
1381
1445
  "mixins"
1382
1446
  ]);
1383
- function slugify(id, prefix) {
1384
- const normalized = id.replace(/[^a-z0-9]+/gi, "-").replace(/^-+|-+$/g, "").toLowerCase();
1385
- return `${prefix}-${normalized || "index"}`;
1386
- }
1387
1447
  function ensureDocumentReady(callback) {
1388
1448
  if (typeof document === "undefined") {
1389
1449
  return;
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@weapp-vite/web",
3
3
  "type": "module",
4
- "version": "1.0.1",
4
+ "version": "1.1.0",
5
5
  "description": "Experimental web runtime for weapp-vite templates",
6
6
  "author": "ice breaker <1324318532@qq.com>",
7
7
  "license": "MIT",