@weapp-vite/web 1.0.0 → 1.0.1

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.
@@ -1,12 +1,743 @@
1
+ // src/runtime/style.ts
2
+ var injected = /* @__PURE__ */ new Map();
3
+ function createStyleId(css) {
4
+ let hash = 2166136261;
5
+ for (let i = 0; i < css.length; i++) {
6
+ hash ^= css.charCodeAt(i);
7
+ hash += (hash << 1) + (hash << 4) + (hash << 7) + (hash << 8) + (hash << 24);
8
+ }
9
+ return `weapp-web-style-${(hash >>> 0).toString(36)}`;
10
+ }
11
+ function removeStyle(id) {
12
+ if (typeof document === "undefined") {
13
+ return;
14
+ }
15
+ const style = injected.get(id);
16
+ if (style) {
17
+ style.remove();
18
+ injected.delete(id);
19
+ }
20
+ }
21
+ function injectStyle(css, id) {
22
+ if (typeof document === "undefined") {
23
+ return () => {
24
+ };
25
+ }
26
+ const styleId = id ?? createStyleId(css);
27
+ const existing = injected.get(styleId);
28
+ if (existing) {
29
+ existing.textContent = css;
30
+ return () => removeStyle(styleId);
31
+ }
32
+ const style = document.createElement("style");
33
+ style.id = styleId;
34
+ style.textContent = css;
35
+ document.head.append(style);
36
+ injected.set(styleId, style);
37
+ return () => removeStyle(styleId);
38
+ }
39
+
40
+ // src/runtime/button.ts
41
+ var DEFAULT_FORM_CONFIG = {
42
+ preventDefault: true
43
+ };
44
+ var DEFAULT_HOVER_CLASS = "button-hover";
45
+ var DEFAULT_HOVER_START = 20;
46
+ var DEFAULT_HOVER_STAY = 70;
47
+ var BUTTON_STYLE_ID = "weapp-web-button-style";
48
+ var NAV_BUTTON_TAG = "weapp-button";
49
+ var BaseElement = globalThis.HTMLElement ?? class {
50
+ };
51
+ var formConfig = { ...DEFAULT_FORM_CONFIG };
52
+ var styleInjected = false;
53
+ var BUTTON_STYLE = `
54
+ weapp-button {
55
+ display: block;
56
+ width: 100%;
57
+ box-sizing: border-box;
58
+ }
59
+
60
+ weapp-button.weapp-btn--mini {
61
+ display: inline-block;
62
+ width: auto;
63
+ }
64
+
65
+ weapp-button .weapp-btn {
66
+ appearance: none;
67
+ -webkit-appearance: none;
68
+ box-sizing: border-box;
69
+ width: 100%;
70
+ border-radius: 6px;
71
+ border: 1px solid #d7d7d7;
72
+ padding: 0 16px;
73
+ height: 44px;
74
+ line-height: 44px;
75
+ font-size: 17px;
76
+ font-weight: 400;
77
+ background-color: #f8f8f8;
78
+ color: #000000;
79
+ cursor: pointer;
80
+ outline: none;
81
+ user-select: none;
82
+ -webkit-tap-highlight-color: transparent;
83
+ }
84
+
85
+ weapp-button.weapp-btn--primary .weapp-btn {
86
+ background-color: #07c160;
87
+ border-color: #07c160;
88
+ color: #ffffff;
89
+ }
90
+
91
+ weapp-button.weapp-btn--warn .weapp-btn {
92
+ background-color: #e64340;
93
+ border-color: #e64340;
94
+ color: #ffffff;
95
+ }
96
+
97
+ weapp-button.weapp-btn--plain .weapp-btn {
98
+ background-color: transparent;
99
+ }
100
+
101
+ weapp-button.weapp-btn--plain.weapp-btn--default .weapp-btn {
102
+ border-color: #353535;
103
+ color: #353535;
104
+ }
105
+
106
+ weapp-button.weapp-btn--plain.weapp-btn--primary .weapp-btn {
107
+ border-color: #07c160;
108
+ color: #07c160;
109
+ }
110
+
111
+ weapp-button.weapp-btn--plain.weapp-btn--warn .weapp-btn {
112
+ border-color: #e64340;
113
+ color: #e64340;
114
+ }
115
+
116
+ weapp-button.weapp-btn--loading .weapp-btn,
117
+ weapp-button.weapp-btn--disabled .weapp-btn {
118
+ opacity: 0.6;
119
+ cursor: not-allowed;
120
+ }
121
+
122
+ weapp-button.button-hover .weapp-btn {
123
+ opacity: 0.7;
124
+ }
125
+
126
+ weapp-button.button-hover.weapp-btn--plain .weapp-btn {
127
+ background-color: rgba(0, 0, 0, 0.1);
128
+ }
129
+
130
+ weapp-button.weapp-btn--mini .weapp-btn {
131
+ height: 28px;
132
+ line-height: 28px;
133
+ font-size: 13px;
134
+ padding: 0 12px;
135
+ border-radius: 4px;
136
+ }
137
+
138
+ weapp-button .weapp-btn__content {
139
+ display: inline-flex;
140
+ align-items: center;
141
+ justify-content: center;
142
+ gap: 6px;
143
+ width: 100%;
144
+ }
145
+
146
+ weapp-button .weapp-btn__loading {
147
+ width: 14px;
148
+ height: 14px;
149
+ border-radius: 50%;
150
+ border: 2px solid currentColor;
151
+ border-top-color: transparent;
152
+ animation: weapp-btn-spin 0.8s linear infinite;
153
+ }
154
+
155
+ weapp-button .weapp-btn__loading[hidden] {
156
+ display: none;
157
+ }
158
+
159
+ @keyframes weapp-btn-spin {
160
+ from { transform: rotate(0deg); }
161
+ to { transform: rotate(360deg); }
162
+ }
163
+ `;
164
+ function ensureButtonStyle() {
165
+ if (styleInjected) {
166
+ return;
167
+ }
168
+ injectStyle(BUTTON_STYLE, BUTTON_STYLE_ID);
169
+ styleInjected = true;
170
+ }
171
+ function toBoolean(value) {
172
+ if (value === null) {
173
+ return false;
174
+ }
175
+ const normalized = value.trim().toLowerCase();
176
+ if (normalized === "" || normalized === "true") {
177
+ return true;
178
+ }
179
+ return normalized !== "false" && normalized !== "0";
180
+ }
181
+ function parseNumber(value, fallback) {
182
+ if (value === null || value === "") {
183
+ return fallback;
184
+ }
185
+ const numeric = Number(value);
186
+ return Number.isFinite(numeric) ? numeric : fallback;
187
+ }
188
+ function isDisabled(element) {
189
+ return toBoolean(element.getAttribute("disabled")) || toBoolean(element.getAttribute("loading"));
190
+ }
191
+ function normalizeType(value) {
192
+ if (!value) {
193
+ return "default";
194
+ }
195
+ const normalized = value.toLowerCase();
196
+ if (normalized === "primary" || normalized === "warn") {
197
+ return normalized;
198
+ }
199
+ return "default";
200
+ }
201
+ function getHoverClass(element) {
202
+ const hoverClass = element.getAttribute("hover-class");
203
+ if (!hoverClass) {
204
+ return DEFAULT_HOVER_CLASS;
205
+ }
206
+ if (hoverClass === "none") {
207
+ return "";
208
+ }
209
+ return hoverClass;
210
+ }
211
+ function isInternalNode(node) {
212
+ return node instanceof HTMLElement && node.dataset?.weappInternal === "true";
213
+ }
214
+ function collectFormValues(form) {
215
+ const values = {};
216
+ const appendValue = (name, value, multiple = false) => {
217
+ if (multiple) {
218
+ if (!Array.isArray(values[name])) {
219
+ values[name] = values[name] === void 0 ? [] : [values[name]];
220
+ }
221
+ values[name].push(value);
222
+ return;
223
+ }
224
+ values[name] = value;
225
+ };
226
+ const formElements = Array.from(form.elements ?? []);
227
+ for (const element of formElements) {
228
+ if (!(element instanceof HTMLElement)) {
229
+ continue;
230
+ }
231
+ const name = element.getAttribute("name")?.trim();
232
+ if (!name) {
233
+ continue;
234
+ }
235
+ const disabled = "disabled" in element ? element.disabled : toBoolean(element.getAttribute("disabled"));
236
+ if (disabled) {
237
+ continue;
238
+ }
239
+ if (element instanceof HTMLInputElement) {
240
+ const type = element.type?.toLowerCase();
241
+ if (type === "checkbox") {
242
+ if (element.checked) {
243
+ appendValue(name, element.value, true);
244
+ }
245
+ continue;
246
+ }
247
+ if (type === "radio") {
248
+ if (element.checked) {
249
+ appendValue(name, element.value);
250
+ }
251
+ continue;
252
+ }
253
+ appendValue(name, element.value);
254
+ continue;
255
+ }
256
+ if (element instanceof HTMLTextAreaElement || element instanceof HTMLSelectElement) {
257
+ appendValue(name, element.value);
258
+ continue;
259
+ }
260
+ }
261
+ const customControls = form.querySelectorAll("switch, checkbox, radio, picker, slider, weapp-switch, weapp-checkbox, weapp-radio, weapp-picker, weapp-slider");
262
+ for (const element of Array.from(customControls)) {
263
+ const name = element.getAttribute("name")?.trim();
264
+ if (!name) {
265
+ continue;
266
+ }
267
+ const disabled = toBoolean(element.getAttribute("disabled"));
268
+ if (disabled) {
269
+ continue;
270
+ }
271
+ const tag = element.tagName.toLowerCase();
272
+ const rawValue = element.value ?? element.getAttribute("value");
273
+ if (tag.includes("checkbox")) {
274
+ const checked = element.checked ?? toBoolean(element.getAttribute("checked"));
275
+ if (checked) {
276
+ appendValue(name, rawValue ?? true, true);
277
+ }
278
+ continue;
279
+ }
280
+ if (tag.includes("radio")) {
281
+ const checked = element.checked ?? toBoolean(element.getAttribute("checked"));
282
+ if (checked) {
283
+ appendValue(name, rawValue ?? true);
284
+ }
285
+ continue;
286
+ }
287
+ if (tag.includes("switch")) {
288
+ const checked = element.checked ?? toBoolean(element.getAttribute("checked"));
289
+ appendValue(name, checked);
290
+ continue;
291
+ }
292
+ appendValue(name, rawValue ?? "");
293
+ }
294
+ return values;
295
+ }
296
+ var WeappButton = class extends BaseElement {
297
+ static get observedAttributes() {
298
+ return [
299
+ "type",
300
+ "plain",
301
+ "size",
302
+ "loading",
303
+ "disabled",
304
+ "hover-class",
305
+ "hover-start-time",
306
+ "hover-stay-time",
307
+ "form-type",
308
+ "open-type"
309
+ ];
310
+ }
311
+ #button;
312
+ #content;
313
+ #text;
314
+ #loading;
315
+ #hoverTimer;
316
+ #hoverRemoveTimer;
317
+ #lastTouchTime = 0;
318
+ #observer;
319
+ connectedCallback() {
320
+ ensureButtonStyle();
321
+ this.#ensureStructure();
322
+ this.#applyState();
323
+ this.#bindEvents();
324
+ }
325
+ disconnectedCallback() {
326
+ this.#clearHoverTimers();
327
+ this.#observer?.disconnect();
328
+ this.#observer = void 0;
329
+ }
330
+ attributeChangedCallback() {
331
+ this.#applyState();
332
+ }
333
+ #ensureStructure() {
334
+ if (this.#button) {
335
+ return;
336
+ }
337
+ const button = document.createElement("button");
338
+ button.type = "button";
339
+ button.className = "weapp-btn";
340
+ button.dataset.weappInternal = "true";
341
+ const content = document.createElement("span");
342
+ content.className = "weapp-btn__content";
343
+ content.dataset.weappInternal = "true";
344
+ const loading = document.createElement("span");
345
+ loading.className = "weapp-btn__loading";
346
+ loading.dataset.weappInternal = "true";
347
+ loading.setAttribute("hidden", "");
348
+ const text = document.createElement("span");
349
+ text.className = "weapp-btn__text";
350
+ text.dataset.weappInternal = "true";
351
+ content.append(loading, text);
352
+ button.append(content);
353
+ const existing = Array.from(this.childNodes).filter((node) => !isInternalNode(node));
354
+ for (const node of existing) {
355
+ text.appendChild(node);
356
+ }
357
+ this.appendChild(button);
358
+ this.#button = button;
359
+ this.#content = content;
360
+ this.#text = text;
361
+ this.#loading = loading;
362
+ if (typeof MutationObserver !== "undefined") {
363
+ this.#observer = new MutationObserver((records) => {
364
+ if (!this.#text) {
365
+ return;
366
+ }
367
+ for (const record of records) {
368
+ for (const node of Array.from(record.addedNodes)) {
369
+ if (isInternalNode(node)) {
370
+ continue;
371
+ }
372
+ if (node === this.#button) {
373
+ continue;
374
+ }
375
+ this.#text.appendChild(node);
376
+ }
377
+ }
378
+ });
379
+ this.#observer.observe(this, { childList: true });
380
+ }
381
+ }
382
+ #applyState() {
383
+ if (!this.#button || !this.#loading) {
384
+ return;
385
+ }
386
+ const type = normalizeType(this.getAttribute("type"));
387
+ const plain = toBoolean(this.getAttribute("plain"));
388
+ const size = (this.getAttribute("size") ?? "default").toLowerCase();
389
+ const loading = toBoolean(this.getAttribute("loading"));
390
+ const disabled = toBoolean(this.getAttribute("disabled"));
391
+ const openType = this.getAttribute("open-type");
392
+ this.classList.toggle("weapp-btn--primary", type === "primary");
393
+ this.classList.toggle("weapp-btn--warn", type === "warn");
394
+ this.classList.toggle("weapp-btn--default", type === "default");
395
+ this.classList.toggle("weapp-btn--plain", plain);
396
+ this.classList.toggle("weapp-btn--mini", size === "mini");
397
+ this.classList.toggle("weapp-btn--loading", loading);
398
+ this.classList.toggle("weapp-btn--disabled", disabled);
399
+ if (openType) {
400
+ const openTypeClass = `weapp-btn--open-type-${openType}`;
401
+ for (const className of Array.from(this.classList)) {
402
+ if (className.startsWith("weapp-btn--open-type-") && className !== openTypeClass) {
403
+ this.classList.remove(className);
404
+ }
405
+ }
406
+ this.classList.add(openTypeClass);
407
+ } else {
408
+ for (const className of Array.from(this.classList)) {
409
+ if (className.startsWith("weapp-btn--open-type-")) {
410
+ this.classList.remove(className);
411
+ }
412
+ }
413
+ }
414
+ const locked = disabled || loading;
415
+ this.#button.disabled = locked;
416
+ if (locked) {
417
+ this.#button.setAttribute("aria-disabled", "true");
418
+ } else {
419
+ this.#button.removeAttribute("aria-disabled");
420
+ }
421
+ this.#loading.toggleAttribute("hidden", !loading);
422
+ }
423
+ #bindEvents() {
424
+ if (this.__weappButtonBound) {
425
+ return;
426
+ }
427
+ ;
428
+ this.__weappButtonBound = true;
429
+ this.addEventListener("click", this.#handleClickCapture, true);
430
+ this.addEventListener("click", this.#handleClick);
431
+ this.addEventListener("touchstart", this.#handlePressStart, { passive: true });
432
+ this.addEventListener("mousedown", this.#handlePressStart);
433
+ this.addEventListener("touchend", this.#handlePressEnd);
434
+ this.addEventListener("touchcancel", this.#handlePressEnd);
435
+ this.addEventListener("mouseup", this.#handlePressEnd);
436
+ this.addEventListener("mouseleave", this.#handlePressEnd);
437
+ }
438
+ #handleClickCapture = (event) => {
439
+ if (isDisabled(this)) {
440
+ event.preventDefault();
441
+ event.stopImmediatePropagation();
442
+ }
443
+ };
444
+ #handleClick = (event) => {
445
+ if (isDisabled(this)) {
446
+ return;
447
+ }
448
+ const formType = this.getAttribute("form-type");
449
+ if (!formType) {
450
+ return;
451
+ }
452
+ const form = this.closest("form");
453
+ if (!form) {
454
+ return;
455
+ }
456
+ if (formType === "submit") {
457
+ const detail = { value: collectFormValues(form) };
458
+ const submitEvent = new CustomEvent("submit", {
459
+ detail,
460
+ bubbles: true,
461
+ cancelable: true
462
+ });
463
+ const shouldSubmit = form.dispatchEvent(submitEvent);
464
+ if (shouldSubmit && !formConfig.preventDefault) {
465
+ form.submit();
466
+ }
467
+ event.preventDefault();
468
+ return;
469
+ }
470
+ if (formType === "reset") {
471
+ form.reset();
472
+ event.preventDefault();
473
+ }
474
+ };
475
+ #handlePressStart = (event) => {
476
+ if (isDisabled(this)) {
477
+ return;
478
+ }
479
+ const hoverClass = getHoverClass(this);
480
+ if (!hoverClass) {
481
+ return;
482
+ }
483
+ if (event.type === "touchstart") {
484
+ this.#lastTouchTime = Date.now();
485
+ }
486
+ if (event.type === "mousedown" && Date.now() - this.#lastTouchTime < 400) {
487
+ return;
488
+ }
489
+ const startTime = parseNumber(this.getAttribute("hover-start-time"), DEFAULT_HOVER_START);
490
+ this.#clearHoverTimers();
491
+ this.#hoverTimer = globalThis.setTimeout(() => {
492
+ this.classList.add(hoverClass);
493
+ }, startTime);
494
+ };
495
+ #handlePressEnd = (event) => {
496
+ const hoverClass = getHoverClass(this);
497
+ if (!hoverClass) {
498
+ return;
499
+ }
500
+ if (event.type === "mouseup" && Date.now() - this.#lastTouchTime < 400) {
501
+ return;
502
+ }
503
+ const stayTime = parseNumber(this.getAttribute("hover-stay-time"), DEFAULT_HOVER_STAY);
504
+ if (this.#hoverTimer) {
505
+ clearTimeout(this.#hoverTimer);
506
+ this.#hoverTimer = void 0;
507
+ }
508
+ if (this.classList.contains(hoverClass)) {
509
+ this.#hoverRemoveTimer = globalThis.setTimeout(() => {
510
+ this.classList.remove(hoverClass);
511
+ }, stayTime);
512
+ }
513
+ };
514
+ #clearHoverTimers() {
515
+ if (this.#hoverTimer) {
516
+ clearTimeout(this.#hoverTimer);
517
+ this.#hoverTimer = void 0;
518
+ }
519
+ if (this.#hoverRemoveTimer) {
520
+ clearTimeout(this.#hoverRemoveTimer);
521
+ this.#hoverRemoveTimer = void 0;
522
+ }
523
+ }
524
+ };
525
+ function ensureButtonDefined() {
526
+ if (typeof customElements === "undefined") {
527
+ return;
528
+ }
529
+ if (!customElements.get(NAV_BUTTON_TAG)) {
530
+ customElements.define(NAV_BUTTON_TAG, WeappButton);
531
+ }
532
+ }
533
+ function setButtonFormConfig(next) {
534
+ formConfig = {
535
+ ...formConfig,
536
+ ...next
537
+ };
538
+ }
539
+
540
+ // src/runtime/component.ts
541
+ import { html, LitElement } from "lit";
542
+ import { unsafeHTML } from "lit/directives/unsafe-html.js";
543
+
544
+ // src/runtime/renderContext.ts
545
+ var expressionCache = /* @__PURE__ */ new Map();
546
+ function createScope(initial) {
547
+ return Object.assign(/* @__PURE__ */ Object.create(null), initial ?? {});
548
+ }
549
+ function createChildScope(parent, locals) {
550
+ return Object.assign(Object.create(parent), locals ?? {});
551
+ }
552
+ function evaluateExpression(expression, scope) {
553
+ if (!expression) {
554
+ return void 0;
555
+ }
556
+ const trimmed = expression.trim();
557
+ if (!trimmed) {
558
+ return void 0;
559
+ }
560
+ let evaluator = expressionCache.get(trimmed);
561
+ if (!evaluator) {
562
+ try {
563
+ evaluator = new Function("scope", `with(scope){ return (${trimmed}); }`);
564
+ } catch (error) {
565
+ const reason = error instanceof Error ? error.message : String(error);
566
+ throw new SyntaxError(`[@weapp-vite/web] \u65E0\u6CD5\u89E3\u6790\u8868\u8FBE\u5F0F "${trimmed}": ${reason}`);
567
+ }
568
+ expressionCache.set(trimmed, evaluator);
569
+ }
570
+ try {
571
+ return evaluator(scope);
572
+ } catch {
573
+ return void 0;
574
+ }
575
+ }
576
+ function normalizeList(value) {
577
+ if (Array.isArray(value)) {
578
+ return value;
579
+ }
580
+ if (value == null) {
581
+ return [];
582
+ }
583
+ if (typeof value === "number" && Number.isFinite(value)) {
584
+ const length = Math.max(0, Math.floor(value));
585
+ return Array.from({ length }, (_, index) => index);
586
+ }
587
+ if (typeof value === "object") {
588
+ return Object.values(value);
589
+ }
590
+ return [];
591
+ }
592
+ function normalizeKey(rawKey, item, index, scope) {
593
+ const key = rawKey?.trim();
594
+ if (!key) {
595
+ if (item != null && (typeof item === "string" || typeof item === "number" || typeof item === "boolean")) {
596
+ return item;
597
+ }
598
+ return index;
599
+ }
600
+ if (key === "*this") {
601
+ return item;
602
+ }
603
+ if (key.includes("{{") && key.includes("}}")) {
604
+ const expr = key.replace(/^\{\{\s*/, "").replace(/\s*\}\}$/, "");
605
+ return evaluateExpression(expr, scope);
606
+ }
607
+ if (!/[\.\[\(\)]/.test(key) && item && typeof item === "object" && key in item) {
608
+ return item[key];
609
+ }
610
+ return evaluateExpression(key, scope);
611
+ }
612
+ function createEventHandler(instance, methods, eventName, handlerRef, flags) {
613
+ const handler = typeof handlerRef === "function" ? handlerRef : methods[handlerRef] ?? instance[handlerRef];
614
+ if (typeof handler !== "function") {
615
+ return () => {
616
+ };
617
+ }
618
+ return (nativeEvent) => {
619
+ if (flags?.catch) {
620
+ nativeEvent.stopPropagation();
621
+ }
622
+ const target = nativeEvent.target;
623
+ const currentTarget = nativeEvent.currentTarget;
624
+ const dataset = currentTarget?.dataset ?? {};
625
+ const syntheticEvent = {
626
+ type: eventName,
627
+ timeStamp: nativeEvent.timeStamp,
628
+ detail: nativeEvent.detail ?? nativeEvent.data ?? void 0,
629
+ target: {
630
+ dataset: target?.dataset ?? dataset
631
+ },
632
+ currentTarget: {
633
+ dataset
634
+ },
635
+ originalEvent: nativeEvent
636
+ };
637
+ handler.call(instance, syntheticEvent);
638
+ };
639
+ }
640
+ function createWxsModule(code, id, requireMap) {
641
+ const module = { exports: {} };
642
+ const exports = module.exports;
643
+ const getRegExp = (pattern, flags) => new RegExp(pattern, flags);
644
+ const getDate = (value) => value == null ? /* @__PURE__ */ new Date() : new Date(value);
645
+ const require2 = (request) => requireMap?.[request];
646
+ try {
647
+ const runner = new Function("module", "exports", "require", "getRegExp", "getDate", code);
648
+ runner(module, exports, require2, getRegExp, getDate);
649
+ } catch (error) {
650
+ const reason = error instanceof Error ? error.message : String(error);
651
+ throw new Error(`[@weapp-vite/web] WXS \u6267\u884C\u5931\u8D25: ${id} ${reason}`);
652
+ }
653
+ return module.exports;
654
+ }
655
+ function createRenderContext(instance, methods) {
656
+ return {
657
+ instance,
658
+ eval: (expression, scope, wxs) => {
659
+ const baseScope = scope ?? createScope();
660
+ const renderScope = wxs ? createChildScope(baseScope, wxs) : baseScope;
661
+ return evaluateExpression(expression, renderScope);
662
+ },
663
+ createScope: (parent, locals) => createChildScope(parent, locals),
664
+ mergeScope: (parent, data) => {
665
+ const baseScope = parent ?? createScope();
666
+ if (!data || typeof data !== "object") {
667
+ return baseScope;
668
+ }
669
+ return createChildScope(baseScope, data);
670
+ },
671
+ normalizeList,
672
+ key: (rawKey, item, index, scope, wxs) => {
673
+ const baseScope = scope ?? createScope();
674
+ const renderScope = wxs ? createChildScope(baseScope, wxs) : baseScope;
675
+ return normalizeKey(rawKey, item, index, renderScope);
676
+ },
677
+ renderTemplate: (templates, name, scope, ctx) => {
678
+ if (!name) {
679
+ return "";
680
+ }
681
+ const template = templates?.[name];
682
+ if (typeof template !== "function") {
683
+ return "";
684
+ }
685
+ return template(scope, ctx);
686
+ },
687
+ event: (eventName, handlerName, _scope, _wxs, flags) => {
688
+ if (typeof handlerName === "function") {
689
+ return createEventHandler(instance, methods, eventName, handlerName, flags);
690
+ }
691
+ const resolvedHandler = String(handlerName ?? "");
692
+ return createEventHandler(instance, methods, eventName, resolvedHandler, flags);
693
+ },
694
+ createWxsModule
695
+ };
696
+ }
697
+
1
698
  // src/runtime/component.ts
2
- var EVENT_TO_DOM = {
3
- tap: "click",
4
- input: "input",
5
- change: "change",
6
- submit: "submit",
7
- blur: "blur",
8
- focus: "focus"
699
+ var supportsLit = typeof document !== "undefined" && typeof document.createComment === "function" && typeof document.createTreeWalker === "function";
700
+ var FallbackElement = class {
9
701
  };
702
+ function bindRuntimeEvents(root, methods, instance) {
703
+ if (typeof document === "undefined") {
704
+ return;
705
+ }
706
+ const walker = document.createTreeWalker(root, NodeFilter.SHOW_ELEMENT);
707
+ while (walker.nextNode()) {
708
+ const element = walker.currentNode;
709
+ for (const attribute of element.getAttributeNames()) {
710
+ if (!attribute.startsWith("data-wx-on-")) {
711
+ continue;
712
+ }
713
+ const handlerName = element.getAttribute(attribute);
714
+ if (!handlerName) {
715
+ continue;
716
+ }
717
+ const handler = methods[handlerName];
718
+ if (!handler) {
719
+ continue;
720
+ }
721
+ const eventName = attribute.slice("data-wx-on-".length);
722
+ element.addEventListener(eventName, (nativeEvent) => {
723
+ const dataset = { ...element.dataset };
724
+ const syntheticEvent = {
725
+ type: eventName,
726
+ timeStamp: nativeEvent.timeStamp,
727
+ detail: nativeEvent.detail ?? nativeEvent.data ?? void 0,
728
+ target: {
729
+ dataset
730
+ },
731
+ currentTarget: {
732
+ dataset
733
+ },
734
+ originalEvent: nativeEvent
735
+ };
736
+ handler.call(instance, syntheticEvent);
737
+ });
738
+ }
739
+ }
740
+ }
10
741
  function hyphenate(name) {
11
742
  return name.replace(/([A-Z])/g, (_, char) => `-${char.toLowerCase()}`);
12
743
  }
@@ -57,60 +788,26 @@ function coerceValue(value, type) {
57
788
  }
58
789
  return value;
59
790
  }
60
- function bindRuntimeEvents(root, methods, instance) {
61
- if (typeof document === "undefined") {
62
- return;
63
- }
64
- const walker = document.createTreeWalker(root, NodeFilter.SHOW_ELEMENT);
65
- while (walker.nextNode()) {
66
- const element = walker.currentNode;
67
- for (const attribute of element.getAttributeNames()) {
68
- if (!attribute.startsWith("data-wx-on-")) {
69
- continue;
70
- }
71
- const handlerName = element.getAttribute(attribute);
72
- if (!handlerName) {
73
- continue;
74
- }
75
- const eventName = attribute.slice("data-wx-on-".length);
76
- const handler = methods[handlerName];
77
- if (!handler) {
78
- continue;
79
- }
80
- const domEvent = EVENT_TO_DOM[eventName] ?? eventName;
81
- element.addEventListener(domEvent, (nativeEvent) => {
82
- const dataset = { ...element.dataset };
83
- const syntheticEvent = {
84
- type: eventName,
85
- timeStamp: nativeEvent.timeStamp,
86
- detail: nativeEvent.detail ?? nativeEvent.data ?? void 0,
87
- target: {
88
- dataset
89
- },
90
- currentTarget: {
91
- dataset
92
- },
93
- originalEvent: nativeEvent
94
- };
95
- handler.call(instance, syntheticEvent);
96
- });
97
- }
98
- }
99
- }
100
791
  function defineComponent(tagName, options) {
101
792
  if (!options || typeof options !== "object") {
102
793
  throw new TypeError("[@weapp-vite/web] defineComponent \u9700\u8981\u63D0\u4F9B\u914D\u7F6E\u5BF9\u8C61\u3002");
103
794
  }
104
- if (customElements.get(tagName)) {
105
- return customElements.get(tagName);
795
+ const existing = customElements.get(tagName);
796
+ if (existing) {
797
+ existing.__weappUpdate?.(options);
798
+ return existing;
106
799
  }
800
+ const BaseElement3 = supportsLit ? LitElement : globalThis.HTMLElement ?? FallbackElement;
107
801
  const { template, style = "", component = {} } = options;
108
802
  if (!template) {
109
803
  throw new Error("[@weapp-vite/web] defineComponent \u9700\u8981\u63D0\u4F9B\u6A21\u677F\u6E32\u67D3\u51FD\u6570\u3002");
110
804
  }
111
- const propertyEntries = Object.entries(component.properties ?? {});
112
- const observedAttributes = propertyEntries.map(([name]) => hyphenate(name));
113
- const defaultPropertyValues = propertyEntries.reduce((acc, [name, prop]) => {
805
+ let templateRef = template;
806
+ let styleRef = style;
807
+ let componentRef = component;
808
+ let propertyEntries = Object.entries(componentRef.properties ?? {});
809
+ let observedAttributes = propertyEntries.map(([name]) => hyphenate(name));
810
+ let defaultPropertyValues = propertyEntries.reduce((acc, [name, prop]) => {
114
811
  if (Object.prototype.hasOwnProperty.call(prop, "value")) {
115
812
  acc[name] = cloneValue(prop.value);
116
813
  } else {
@@ -118,38 +815,26 @@ function defineComponent(tagName, options) {
118
815
  }
119
816
  return acc;
120
817
  }, {});
121
- const lifetimes = component.lifetimes ?? {};
122
- class WeappWebComponent extends HTMLElement {
818
+ let lifetimes = componentRef.lifetimes ?? {};
819
+ const instances = /* @__PURE__ */ new Set();
820
+ class WeappWebComponent extends BaseElement3 {
123
821
  static get observedAttributes() {
124
822
  return observedAttributes;
125
823
  }
126
824
  #state;
127
825
  #properties;
128
826
  #methods;
129
- #shadow;
130
- #contentRoot;
131
- #styleElement;
132
827
  #isMounted = false;
828
+ #renderContext = createRenderContext(this, {});
829
+ #usesLegacyTemplate = false;
830
+ #readyFired = false;
133
831
  constructor() {
134
832
  super();
135
- const dataOption = typeof component.data === "function" ? component.data() : component.data ?? {};
833
+ const dataOption = typeof componentRef.data === "function" ? componentRef.data() : componentRef.data ?? {};
136
834
  this.#properties = { ...defaultPropertyValues };
137
835
  this.#state = { ...cloneValue(this.#properties), ...cloneValue(dataOption) };
138
- this.#shadow = this.attachShadow({ mode: "open" });
139
- if (style) {
140
- this.#styleElement = document.createElement("style");
141
- this.#styleElement.textContent = style;
142
- this.#shadow.append(this.#styleElement);
143
- }
144
- this.#contentRoot = document.createElement("div");
145
- this.#contentRoot.setAttribute("part", "content");
146
- this.#shadow.append(this.#contentRoot);
147
836
  this.#methods = {};
148
- for (const [name, fn] of Object.entries(component.methods ?? {})) {
149
- if (typeof fn === "function") {
150
- this.#methods[name] = fn.bind(this);
151
- }
152
- }
837
+ this.#syncMethods(componentRef.methods ?? {});
153
838
  for (const [propName] of propertyEntries) {
154
839
  Object.defineProperty(this, propName, {
155
840
  configurable: true,
@@ -160,6 +845,15 @@ function defineComponent(tagName, options) {
160
845
  }
161
846
  });
162
847
  }
848
+ if (!supportsLit) {
849
+ const host = this;
850
+ if (!host.shadowRoot && typeof host.attachShadow === "function") {
851
+ host.attachShadow({ mode: "open" });
852
+ }
853
+ ;
854
+ this.renderRoot = host.shadowRoot ?? host;
855
+ }
856
+ instances.add(this);
163
857
  lifetimes.created?.call(this);
164
858
  }
165
859
  get data() {
@@ -179,26 +873,76 @@ function defineComponent(tagName, options) {
179
873
  }));
180
874
  }
181
875
  connectedCallback() {
876
+ const superConnected = BaseElement3.prototype.connectedCallback;
877
+ if (supportsLit && typeof superConnected === "function") {
878
+ superConnected.call(this);
879
+ }
182
880
  this.#applyAttributes();
183
- this.#render();
184
881
  lifetimes.attached?.call(this);
185
882
  this.#isMounted = true;
186
- lifetimes.ready?.call(this);
883
+ if (!supportsLit) {
884
+ this.#renderLegacy();
885
+ }
187
886
  }
188
887
  disconnectedCallback() {
888
+ const superDisconnected = BaseElement3.prototype.disconnectedCallback;
889
+ if (supportsLit && typeof superDisconnected === "function") {
890
+ superDisconnected.call(this);
891
+ }
189
892
  this.#isMounted = false;
893
+ instances.delete(this);
190
894
  lifetimes.detached?.call(this);
191
895
  }
192
- attributeChangedCallback(attrName, _oldValue, newValue) {
896
+ attributeChangedCallback(attrName, oldValue, newValue) {
897
+ const superAttributeChanged = BaseElement3.prototype.attributeChangedCallback;
898
+ if (supportsLit && typeof superAttributeChanged === "function") {
899
+ superAttributeChanged.call(this, attrName, oldValue, newValue);
900
+ }
193
901
  const propName = toCamelCase(attrName);
194
902
  if (!Object.prototype.hasOwnProperty.call(this.#properties, propName)) {
195
903
  return;
196
904
  }
197
- const propOption = component.properties?.[propName];
905
+ const propOption = componentRef.properties?.[propName];
198
906
  const coerced = coerceValue(newValue, propOption?.type);
199
907
  this.#setProperty(propName, coerced);
200
908
  }
909
+ firstUpdated() {
910
+ lifetimes.ready?.call(this);
911
+ this.#readyFired = true;
912
+ }
913
+ updated() {
914
+ if (this.#usesLegacyTemplate) {
915
+ const renderRoot = this.renderRoot ?? this.shadowRoot ?? this;
916
+ bindRuntimeEvents(renderRoot, this.#methods, this);
917
+ }
918
+ }
919
+ render() {
920
+ const result = templateRef(this.#state, this.#renderContext);
921
+ const styleMarkup = styleRef ? html`<style>${styleRef}</style>` : null;
922
+ if (typeof result === "string") {
923
+ this.#usesLegacyTemplate = true;
924
+ return html`${styleMarkup}${unsafeHTML(result)}`;
925
+ }
926
+ this.#usesLegacyTemplate = false;
927
+ if (styleMarkup) {
928
+ return html`${styleMarkup}${result}`;
929
+ }
930
+ return result;
931
+ }
932
+ requestUpdate(name, oldValue, options2) {
933
+ const superRequestUpdate = BaseElement3.prototype.requestUpdate;
934
+ if (supportsLit && typeof superRequestUpdate === "function") {
935
+ return superRequestUpdate.call(this, name, oldValue, options2);
936
+ }
937
+ if (this.#isMounted) {
938
+ this.#renderLegacy();
939
+ }
940
+ return void 0;
941
+ }
201
942
  #applyAttributes() {
943
+ if (!this.attributes || typeof this.attributes[Symbol.iterator] !== "function") {
944
+ return;
945
+ }
202
946
  for (const attr of this.attributes) {
203
947
  this.attributeChangedCallback(attr.name, null, attr.value);
204
948
  }
@@ -214,17 +958,17 @@ function defineComponent(tagName, options) {
214
958
  this.#state[key] = value;
215
959
  if (Object.prototype.hasOwnProperty.call(this.#properties, key)) {
216
960
  this.#properties[key] = value;
217
- component.properties?.[key]?.observer?.call(this, value, oldValue);
961
+ componentRef.properties?.[key]?.observer?.call(this, value, oldValue);
218
962
  }
219
963
  changed = true;
220
964
  }
221
965
  }
222
966
  if (changed) {
223
- this.#render();
967
+ this.requestUpdate();
224
968
  }
225
969
  }
226
970
  #setProperty(name, value) {
227
- const propOption = component.properties?.[name];
971
+ const propOption = componentRef.properties?.[name];
228
972
  const coerced = coerceValue(value, propOption?.type);
229
973
  const oldValue = this.#properties[name];
230
974
  if (oldValue === coerced) {
@@ -233,24 +977,380 @@ function defineComponent(tagName, options) {
233
977
  this.#properties[name] = coerced;
234
978
  this.#state[name] = coerced;
235
979
  if (this.#isMounted) {
236
- this.#render();
980
+ this.requestUpdate();
237
981
  }
238
982
  propOption?.observer?.call(this, coerced, oldValue);
239
983
  }
240
- #render() {
241
- const html = template(this.#state);
242
- if (!this.#contentRoot) {
243
- return;
984
+ #syncMethods(nextMethods) {
985
+ const resolved = nextMethods ?? {};
986
+ const bound = {};
987
+ for (const [name, fn] of Object.entries(resolved)) {
988
+ if (typeof fn === "function") {
989
+ bound[name] = fn.bind(this);
990
+ }
991
+ }
992
+ for (const key of Object.keys(this.#methods)) {
993
+ if (!(key in bound)) {
994
+ delete this.#methods[key];
995
+ }
996
+ }
997
+ for (const [key, fn] of Object.entries(bound)) {
998
+ this.#methods[key] = fn;
999
+ }
1000
+ this.#renderContext = createRenderContext(this, this.#methods);
1001
+ }
1002
+ __weappSync(nextMethods) {
1003
+ this.#syncMethods(nextMethods);
1004
+ this.requestUpdate();
1005
+ }
1006
+ #renderLegacy() {
1007
+ const result = templateRef(this.#state, this.#renderContext);
1008
+ const root = this.renderRoot ?? this.shadowRoot ?? this;
1009
+ const styleMarkup = styleRef ? `<style>${styleRef}</style>` : "";
1010
+ if (typeof result === "string") {
1011
+ root.innerHTML = `${styleMarkup}${result}`;
1012
+ bindRuntimeEvents(root, this.#methods, this);
1013
+ } else if (result == null) {
1014
+ root.innerHTML = styleMarkup;
1015
+ } else {
1016
+ root.innerHTML = `${styleMarkup}${String(result)}`;
1017
+ }
1018
+ if (!this.#readyFired) {
1019
+ lifetimes.ready?.call(this);
1020
+ this.#readyFired = true;
244
1021
  }
245
- this.#contentRoot.innerHTML = html;
246
- bindRuntimeEvents(this.#contentRoot, this.#methods, this);
247
1022
  }
248
1023
  }
1024
+ const updateComponent = (nextOptions) => {
1025
+ if (!nextOptions?.template) {
1026
+ return;
1027
+ }
1028
+ templateRef = nextOptions.template;
1029
+ styleRef = nextOptions.style ?? "";
1030
+ componentRef = nextOptions.component ?? {};
1031
+ lifetimes = componentRef.lifetimes ?? {};
1032
+ propertyEntries = Object.entries(componentRef.properties ?? {});
1033
+ observedAttributes = propertyEntries.map(([name]) => hyphenate(name));
1034
+ defaultPropertyValues = propertyEntries.reduce((acc, [name, prop]) => {
1035
+ if (Object.prototype.hasOwnProperty.call(prop, "value")) {
1036
+ acc[name] = cloneValue(prop.value);
1037
+ } else {
1038
+ acc[name] = void 0;
1039
+ }
1040
+ return acc;
1041
+ }, {});
1042
+ const nextMethods = componentRef.methods ?? {};
1043
+ for (const instance of instances) {
1044
+ instance.__weappSync(nextMethods);
1045
+ }
1046
+ };
1047
+ WeappWebComponent.__weappUpdate = updateComponent;
249
1048
  customElements.define(tagName, WeappWebComponent);
250
1049
  return WeappWebComponent;
251
1050
  }
252
1051
 
1052
+ // src/runtime/navigationBar.ts
1053
+ var NAVIGATION_BAR_TAG = "weapp-navigation-bar";
1054
+ var BaseElement2 = globalThis.HTMLElement ?? class {
1055
+ };
1056
+ var navigationBarInstances = /* @__PURE__ */ new Set();
1057
+ var navigationBarMetrics = {};
1058
+ var NAVBAR_STYLE = `
1059
+ :host {
1060
+ --weapp-status-bar-height: 20px;
1061
+ --weapp-nav-content-height: 44px;
1062
+ --weapp-nav-height: calc(var(--weapp-status-bar-height) + var(--weapp-nav-content-height));
1063
+ --weapp-nav-bg: #ffffff;
1064
+ --weapp-nav-color: #000000;
1065
+ --weapp-nav-transition-duration: 0ms;
1066
+ --weapp-nav-transition-easing: ease;
1067
+ display: block;
1068
+ position: relative;
1069
+ z-index: 999;
1070
+ font-family: -apple-system, BlinkMacSystemFont, 'Helvetica Neue', Arial, sans-serif;
1071
+ }
1072
+
1073
+ .weapp-nav__spacer {
1074
+ height: var(--weapp-nav-height);
1075
+ }
1076
+
1077
+ .weapp-nav {
1078
+ position: fixed;
1079
+ top: 0;
1080
+ left: 0;
1081
+ right: 0;
1082
+ height: var(--weapp-nav-height);
1083
+ display: flex;
1084
+ flex-direction: column;
1085
+ background: var(--weapp-nav-bg);
1086
+ color: var(--weapp-nav-color);
1087
+ box-shadow: 0 0.5px 0 rgba(0, 0, 0, 0.1);
1088
+ transition:
1089
+ background-color var(--weapp-nav-transition-duration) var(--weapp-nav-transition-easing),
1090
+ color var(--weapp-nav-transition-duration) var(--weapp-nav-transition-easing);
1091
+ }
1092
+
1093
+ .weapp-nav--transparent {
1094
+ box-shadow: none;
1095
+ }
1096
+
1097
+ .weapp-nav__status {
1098
+ height: var(--weapp-status-bar-height);
1099
+ }
1100
+
1101
+ .weapp-nav__content {
1102
+ height: var(--weapp-nav-content-height);
1103
+ display: flex;
1104
+ align-items: center;
1105
+ justify-content: center;
1106
+ position: relative;
1107
+ padding: 0 12px;
1108
+ box-sizing: border-box;
1109
+ font-size: 17px;
1110
+ font-weight: 500;
1111
+ line-height: 1;
1112
+ }
1113
+
1114
+ .weapp-nav__left,
1115
+ .weapp-nav__right {
1116
+ position: absolute;
1117
+ top: 0;
1118
+ bottom: 0;
1119
+ width: 88px;
1120
+ display: flex;
1121
+ align-items: center;
1122
+ }
1123
+
1124
+ .weapp-nav__left {
1125
+ left: 12px;
1126
+ }
1127
+
1128
+ .weapp-nav__right {
1129
+ right: 12px;
1130
+ justify-content: flex-end;
1131
+ }
1132
+
1133
+ .weapp-nav__title {
1134
+ display: inline-flex;
1135
+ align-items: center;
1136
+ gap: 6px;
1137
+ max-width: 70%;
1138
+ overflow: hidden;
1139
+ text-overflow: ellipsis;
1140
+ white-space: nowrap;
1141
+ }
1142
+
1143
+ .weapp-nav__loading {
1144
+ width: 12px;
1145
+ height: 12px;
1146
+ border-radius: 50%;
1147
+ border: 2px solid currentColor;
1148
+ border-top-color: transparent;
1149
+ animation: weapp-nav-spin 0.8s linear infinite;
1150
+ }
1151
+
1152
+ .weapp-nav__loading[hidden] {
1153
+ display: none;
1154
+ }
1155
+
1156
+ @keyframes weapp-nav-spin {
1157
+ from { transform: rotate(0deg); }
1158
+ to { transform: rotate(360deg); }
1159
+ }
1160
+ `;
1161
+ function isIOS() {
1162
+ if (typeof navigator === "undefined") {
1163
+ return false;
1164
+ }
1165
+ return /iphone|ipad|ipod/i.test(navigator.userAgent);
1166
+ }
1167
+ function getDefaultHeights() {
1168
+ if (isIOS()) {
1169
+ return { statusBarHeight: 20, navContentHeight: 44 };
1170
+ }
1171
+ return { statusBarHeight: 24, navContentHeight: 48 };
1172
+ }
1173
+ function readSafeAreaTop() {
1174
+ if (typeof document === "undefined" || !document.body) {
1175
+ return 0;
1176
+ }
1177
+ const probe = document.createElement("div");
1178
+ probe.style.cssText = [
1179
+ "position: absolute",
1180
+ "top: 0",
1181
+ "height: env(safe-area-inset-top)",
1182
+ "height: constant(safe-area-inset-top)",
1183
+ "pointer-events: none",
1184
+ "visibility: hidden"
1185
+ ].join(";");
1186
+ document.body.appendChild(probe);
1187
+ const height = Math.max(0, probe.getBoundingClientRect().height);
1188
+ probe.remove();
1189
+ return height;
1190
+ }
1191
+ function resolveNavigationBarMetrics() {
1192
+ const defaults = getDefaultHeights();
1193
+ const safeAreaTop = navigationBarMetrics.safeAreaTop !== void 0 ? navigationBarMetrics.safeAreaTop : readSafeAreaTop();
1194
+ const statusBarHeight = navigationBarMetrics.statusBarHeight !== void 0 ? navigationBarMetrics.statusBarHeight : safeAreaTop > 0 ? safeAreaTop : defaults.statusBarHeight;
1195
+ const navContentHeight = navigationBarMetrics.navContentHeight !== void 0 ? navigationBarMetrics.navContentHeight : defaults.navContentHeight;
1196
+ return {
1197
+ safeAreaTop,
1198
+ statusBarHeight,
1199
+ navContentHeight,
1200
+ navHeight: statusBarHeight + navContentHeight
1201
+ };
1202
+ }
1203
+ function isTransparentColor(value) {
1204
+ if (!value) {
1205
+ return false;
1206
+ }
1207
+ const normalized = value.trim().toLowerCase();
1208
+ return normalized === "transparent" || normalized === "rgba(0,0,0,0)" || normalized === "rgba(0, 0, 0, 0)" || normalized === "hsla(0,0%,0%,0)";
1209
+ }
1210
+ function setNavigationBarMetrics(next) {
1211
+ navigationBarMetrics = { ...navigationBarMetrics, ...next };
1212
+ for (const instance of navigationBarInstances) {
1213
+ instance.applyMetrics();
1214
+ }
1215
+ }
1216
+ var WeappNavigationBar = class extends BaseElement2 {
1217
+ static get observedAttributes() {
1218
+ return ["title", "background-color", "text-style", "front-color", "loading"];
1219
+ }
1220
+ #nav;
1221
+ #title;
1222
+ #loading;
1223
+ #resizeHandler;
1224
+ connectedCallback() {
1225
+ if (!this.shadowRoot) {
1226
+ this.attachShadow({ mode: "open" });
1227
+ }
1228
+ if (this.shadowRoot && !this.shadowRoot.hasChildNodes()) {
1229
+ this.#renderShell();
1230
+ }
1231
+ navigationBarInstances.add(this);
1232
+ this.applyMetrics();
1233
+ this.applyAppearance();
1234
+ this.#bindResize();
1235
+ }
1236
+ disconnectedCallback() {
1237
+ navigationBarInstances.delete(this);
1238
+ if (this.#resizeHandler) {
1239
+ const target = typeof window !== "undefined" ? window.visualViewport ?? window : void 0;
1240
+ target?.removeEventListener("resize", this.#resizeHandler);
1241
+ this.#resizeHandler = void 0;
1242
+ }
1243
+ }
1244
+ attributeChangedCallback() {
1245
+ this.applyAppearance();
1246
+ }
1247
+ applyMetrics() {
1248
+ const metrics = resolveNavigationBarMetrics();
1249
+ this.style.setProperty("--weapp-status-bar-height", `${metrics.statusBarHeight}px`);
1250
+ this.style.setProperty("--weapp-nav-content-height", `${metrics.navContentHeight}px`);
1251
+ this.style.setProperty("--weapp-nav-height", `${metrics.navHeight}px`);
1252
+ }
1253
+ applyAppearance() {
1254
+ if (!this.#nav || !this.#title || !this.#loading) {
1255
+ return;
1256
+ }
1257
+ const title = this.getAttribute("title") ?? "";
1258
+ this.#title.textContent = title;
1259
+ const background = this.getAttribute("background-color") ?? "#ffffff";
1260
+ const frontColor = this.getAttribute("front-color");
1261
+ const textStyle = (this.getAttribute("text-style") ?? "").toLowerCase();
1262
+ const color = frontColor || (textStyle === "white" ? "#ffffff" : "#000000");
1263
+ const loadingAttr = this.getAttribute("loading");
1264
+ const loading = loadingAttr !== null && loadingAttr !== "false" && loadingAttr !== "0";
1265
+ this.style.setProperty("--weapp-nav-bg", background);
1266
+ this.style.setProperty("--weapp-nav-color", color);
1267
+ this.#loading.toggleAttribute("hidden", !loading);
1268
+ this.#nav.classList.toggle("weapp-nav--transparent", isTransparentColor(background));
1269
+ }
1270
+ #bindResize() {
1271
+ if (this.#resizeHandler || typeof window === "undefined") {
1272
+ return;
1273
+ }
1274
+ const target = window.visualViewport ?? window;
1275
+ this.#resizeHandler = () => {
1276
+ this.applyMetrics();
1277
+ };
1278
+ target.addEventListener("resize", this.#resizeHandler);
1279
+ }
1280
+ #renderShell() {
1281
+ const root = this.shadowRoot;
1282
+ root.innerHTML = "";
1283
+ const style = document.createElement("style");
1284
+ style.textContent = NAVBAR_STYLE;
1285
+ const spacer = document.createElement("div");
1286
+ spacer.className = "weapp-nav__spacer";
1287
+ const nav = document.createElement("div");
1288
+ nav.className = "weapp-nav";
1289
+ const status = document.createElement("div");
1290
+ status.className = "weapp-nav__status";
1291
+ const content = document.createElement("div");
1292
+ content.className = "weapp-nav__content";
1293
+ const left = document.createElement("div");
1294
+ left.className = "weapp-nav__left";
1295
+ const right = document.createElement("div");
1296
+ right.className = "weapp-nav__right";
1297
+ const title = document.createElement("span");
1298
+ title.className = "weapp-nav__title";
1299
+ const loading = document.createElement("span");
1300
+ loading.className = "weapp-nav__loading";
1301
+ loading.setAttribute("hidden", "");
1302
+ const titleText = document.createElement("span");
1303
+ titleText.className = "weapp-nav__title-text";
1304
+ title.append(loading, titleText);
1305
+ content.append(left, title, right);
1306
+ nav.append(status, content);
1307
+ root.append(style, spacer, nav);
1308
+ this.#nav = nav;
1309
+ this.#title = titleText;
1310
+ this.#loading = loading;
1311
+ }
1312
+ };
1313
+ function ensureNavigationBarDefined() {
1314
+ if (typeof customElements === "undefined") {
1315
+ return;
1316
+ }
1317
+ if (!customElements.get(NAVIGATION_BAR_TAG)) {
1318
+ customElements.define(NAVIGATION_BAR_TAG, WeappNavigationBar);
1319
+ }
1320
+ }
1321
+
1322
+ // src/runtime/rpx.ts
1323
+ var DEFAULT_DESIGN_WIDTH = 750;
1324
+ var DEFAULT_VAR_NAME = "--rpx";
1325
+ var initialized = false;
1326
+ function computeRpx(designWidth) {
1327
+ if (typeof window === "undefined") {
1328
+ return 0;
1329
+ }
1330
+ const width = document.documentElement?.clientWidth ?? window.innerWidth;
1331
+ return width / designWidth;
1332
+ }
1333
+ function setupRpx(config) {
1334
+ if (typeof document === "undefined") {
1335
+ return;
1336
+ }
1337
+ const designWidth = config?.designWidth ?? DEFAULT_DESIGN_WIDTH;
1338
+ const varName = config?.varName ?? DEFAULT_VAR_NAME;
1339
+ const root = document.documentElement;
1340
+ const apply = () => {
1341
+ const value = computeRpx(designWidth);
1342
+ root.style.setProperty(varName, `${value}px`);
1343
+ };
1344
+ apply();
1345
+ if (!initialized) {
1346
+ initialized = true;
1347
+ window.addEventListener("resize", apply);
1348
+ }
1349
+ }
1350
+
253
1351
  // src/runtime/polyfill.ts
1352
+ var ROUTE_META_SYMBOL = /* @__PURE__ */ Symbol("@weapp-vite/web:route-meta");
1353
+ var PAGE_STATE_SYMBOL = /* @__PURE__ */ Symbol("@weapp-vite/web:page-state");
254
1354
  var pageRegistry = /* @__PURE__ */ new Map();
255
1355
  var componentRegistry = /* @__PURE__ */ new Map();
256
1356
  var navigationHistory = [];
@@ -258,8 +1358,6 @@ var pageOrder = [];
258
1358
  var activeEntry;
259
1359
  var appInstance;
260
1360
  var appLaunched = false;
261
- var ROUTE_META_SYMBOL = /* @__PURE__ */ Symbol("@weapp-vite/web:route-meta");
262
- var PAGE_STATE_SYMBOL = /* @__PURE__ */ Symbol("@weapp-vite/web:page-state");
263
1361
  var PAGE_LIFECYCLE_KEYS = /* @__PURE__ */ new Set(["onLoad", "onReady", "onShow", "onHide", "onUnload"]);
264
1362
  var RESERVED_PAGE_METHOD_KEYS = /* @__PURE__ */ new Set([
265
1363
  "data",
@@ -520,19 +1618,41 @@ function augmentPageComponentOptions(component, record) {
520
1618
  };
521
1619
  return enhanced;
522
1620
  }
523
- function initializePageRoutes(ids) {
1621
+ function initializePageRoutes(ids, options) {
524
1622
  pageOrder = Array.from(new Set(ids));
525
1623
  if (!pageOrder.length) {
526
1624
  return;
527
1625
  }
1626
+ if (options?.rpx) {
1627
+ setupRpx(options.rpx);
1628
+ }
1629
+ if (options?.navigationBar) {
1630
+ setNavigationBarMetrics(options.navigationBar);
1631
+ }
1632
+ if (options?.form) {
1633
+ setButtonFormConfig(options.form);
1634
+ }
528
1635
  if (!navigationHistory.length) {
529
1636
  pushEntry(pageOrder[0], {});
530
1637
  }
531
1638
  }
532
1639
  function registerPage(options, meta) {
1640
+ ensureButtonDefined();
1641
+ ensureNavigationBarDefined();
533
1642
  const tag = slugify(meta.id, "wv-page");
534
1643
  const template = meta.template ?? (() => "");
535
1644
  const normalized = normalizePageOptions(options);
1645
+ const existing = pageRegistry.get(meta.id);
1646
+ if (existing) {
1647
+ existing.hooks = normalized.hooks;
1648
+ const component2 = augmentPageComponentOptions(normalized.component, existing);
1649
+ defineComponent(tag, {
1650
+ template,
1651
+ style: meta.style,
1652
+ component: component2
1653
+ });
1654
+ return options;
1655
+ }
536
1656
  const record = {
537
1657
  tag,
538
1658
  hooks: normalized.hooks,
@@ -548,9 +1668,18 @@ function registerPage(options, meta) {
548
1668
  return options;
549
1669
  }
550
1670
  function registerComponent(options, meta) {
1671
+ ensureButtonDefined();
551
1672
  const tag = slugify(meta.id, "wv-component");
552
1673
  const template = meta.template ?? (() => "");
553
1674
  const component = normalizeComponentOptions(options);
1675
+ if (componentRegistry.has(meta.id)) {
1676
+ defineComponent(tag, {
1677
+ template,
1678
+ style: meta.style,
1679
+ component
1680
+ });
1681
+ return options;
1682
+ }
554
1683
  defineComponent(tag, {
555
1684
  template,
556
1685
  style: meta.style,
@@ -561,6 +1690,16 @@ function registerComponent(options, meta) {
561
1690
  }
562
1691
  function registerApp(options, _meta) {
563
1692
  const resolved = options ?? {};
1693
+ if (appInstance) {
1694
+ const currentGlobal = appInstance.globalData;
1695
+ Object.assign(appInstance, resolved);
1696
+ if (isRecord(currentGlobal)) {
1697
+ appInstance.globalData = currentGlobal;
1698
+ } else if (!isRecord(appInstance.globalData)) {
1699
+ appInstance.globalData = {};
1700
+ }
1701
+ return options;
1702
+ }
564
1703
  appInstance = resolved;
565
1704
  appLaunched = false;
566
1705
  if (!isRecord(appInstance.globalData)) {
@@ -612,6 +1751,82 @@ function getCurrentPagesInternal() {
612
1751
  function getAppInstance() {
613
1752
  return appInstance;
614
1753
  }
1754
+ function getActiveNavigationBar() {
1755
+ const pages = getCurrentPagesInternal();
1756
+ const current = pages[pages.length - 1];
1757
+ if (!current) {
1758
+ return void 0;
1759
+ }
1760
+ const renderRoot = current.renderRoot ?? current.shadowRoot ?? current;
1761
+ if (!renderRoot || typeof renderRoot.querySelector !== "function") {
1762
+ return void 0;
1763
+ }
1764
+ return renderRoot.querySelector("weapp-navigation-bar");
1765
+ }
1766
+ var warnedNavigationBarMissing = false;
1767
+ function warnNavigationBarMissing(action) {
1768
+ if (warnedNavigationBarMissing) {
1769
+ return;
1770
+ }
1771
+ warnedNavigationBarMissing = true;
1772
+ const logger = globalThis.console;
1773
+ if (logger?.warn) {
1774
+ logger.warn(`[@weapp-vite/web] ${action} \u9700\u8981\u9ED8\u8BA4\u5BFC\u822A\u680F\u652F\u6301\uFF0C\u4F46\u5F53\u524D\u9875\u9762\u672A\u6E32\u67D3 weapp-navigation-bar\u3002`);
1775
+ }
1776
+ }
1777
+ function setNavigationBarTitle(options) {
1778
+ const bar = getActiveNavigationBar();
1779
+ if (!bar) {
1780
+ warnNavigationBarMissing("wx.setNavigationBarTitle");
1781
+ return Promise.resolve();
1782
+ }
1783
+ if (options?.title !== void 0) {
1784
+ bar.setAttribute("title", options.title);
1785
+ }
1786
+ return Promise.resolve();
1787
+ }
1788
+ function setNavigationBarColor(options) {
1789
+ const bar = getActiveNavigationBar();
1790
+ if (!bar) {
1791
+ warnNavigationBarMissing("wx.setNavigationBarColor");
1792
+ return Promise.resolve();
1793
+ }
1794
+ if (options?.frontColor) {
1795
+ bar.setAttribute("front-color", options.frontColor);
1796
+ }
1797
+ if (options?.backgroundColor) {
1798
+ bar.setAttribute("background-color", options.backgroundColor);
1799
+ }
1800
+ if (options?.animation) {
1801
+ const duration = typeof options.animation.duration === "number" ? `${options.animation.duration}ms` : void 0;
1802
+ const easing = options.animation.timingFunction;
1803
+ if (duration) {
1804
+ bar.style.setProperty("--weapp-nav-transition-duration", duration);
1805
+ }
1806
+ if (easing) {
1807
+ bar.style.setProperty("--weapp-nav-transition-easing", easing);
1808
+ }
1809
+ }
1810
+ return Promise.resolve();
1811
+ }
1812
+ function showNavigationBarLoading() {
1813
+ const bar = getActiveNavigationBar();
1814
+ if (!bar) {
1815
+ warnNavigationBarMissing("wx.showNavigationBarLoading");
1816
+ return Promise.resolve();
1817
+ }
1818
+ bar.setAttribute("loading", "true");
1819
+ return Promise.resolve();
1820
+ }
1821
+ function hideNavigationBarLoading() {
1822
+ const bar = getActiveNavigationBar();
1823
+ if (!bar) {
1824
+ warnNavigationBarMissing("wx.hideNavigationBarLoading");
1825
+ return Promise.resolve();
1826
+ }
1827
+ bar.removeAttribute("loading");
1828
+ return Promise.resolve();
1829
+ }
615
1830
  var globalTarget = typeof globalThis !== "undefined" ? globalThis : {};
616
1831
  if (globalTarget) {
617
1832
  const wxBridge = globalTarget.wx ?? {};
@@ -620,7 +1835,11 @@ if (globalTarget) {
620
1835
  navigateBack,
621
1836
  redirectTo,
622
1837
  switchTab,
623
- reLaunch
1838
+ reLaunch,
1839
+ setNavigationBarTitle,
1840
+ setNavigationBarColor,
1841
+ showNavigationBarLoading,
1842
+ hideNavigationBarLoading
624
1843
  });
625
1844
  globalTarget.wx = wxBridge;
626
1845
  if (typeof globalTarget.getApp !== "function") {
@@ -631,46 +1850,7 @@ if (globalTarget) {
631
1850
  }
632
1851
  }
633
1852
 
634
- // src/runtime/style.ts
635
- var injected = /* @__PURE__ */ new Map();
636
- function createStyleId(css) {
637
- let hash = 2166136261;
638
- for (let i = 0; i < css.length; i++) {
639
- hash ^= css.charCodeAt(i);
640
- hash += (hash << 1) + (hash << 4) + (hash << 7) + (hash << 8) + (hash << 24);
641
- }
642
- return `weapp-web-style-${(hash >>> 0).toString(36)}`;
643
- }
644
- function removeStyle(id) {
645
- if (typeof document === "undefined") {
646
- return;
647
- }
648
- const style = injected.get(id);
649
- if (style) {
650
- style.remove();
651
- injected.delete(id);
652
- }
653
- }
654
- function injectStyle(css, id) {
655
- if (typeof document === "undefined") {
656
- return () => {
657
- };
658
- }
659
- const styleId = id ?? createStyleId(css);
660
- const existing = injected.get(styleId);
661
- if (existing) {
662
- existing.textContent = css;
663
- return () => removeStyle(styleId);
664
- }
665
- const style = document.createElement("style");
666
- style.id = styleId;
667
- style.textContent = css;
668
- document.head.append(style);
669
- injected.set(styleId, style);
670
- return () => removeStyle(styleId);
671
- }
672
-
673
- // src/runtime/template.ts
1853
+ // src/runtime/legacyTemplate.ts
674
1854
  import { parseDocument } from "htmlparser2";
675
1855
  var CONTROL_ATTRS = /* @__PURE__ */ new Set([
676
1856
  "wx:if",
@@ -703,7 +1883,7 @@ var SELF_CLOSING_TAGS = /* @__PURE__ */ new Set([
703
1883
  "wbr"
704
1884
  ]);
705
1885
  var templateCache = /* @__PURE__ */ new Map();
706
- var expressionCache = /* @__PURE__ */ new Map();
1886
+ var expressionCache2 = /* @__PURE__ */ new Map();
707
1887
  function filterRenderableNode(node) {
708
1888
  if (node.type === "directive" || node.type === "comment") {
709
1889
  return false;
@@ -727,13 +1907,13 @@ function getOrParseTemplate(source) {
727
1907
  }
728
1908
  return cached;
729
1909
  }
730
- function createScope(initial) {
1910
+ function createScope2(initial) {
731
1911
  return Object.assign(/* @__PURE__ */ Object.create(null), initial ?? {});
732
1912
  }
733
- function createChildScope(parent) {
1913
+ function createChildScope2(parent) {
734
1914
  return Object.assign(Object.create(parent), {});
735
1915
  }
736
- function normalizeList(value) {
1916
+ function normalizeList2(value) {
737
1917
  if (Array.isArray(value)) {
738
1918
  return value;
739
1919
  }
@@ -767,7 +1947,7 @@ function normalizeTagName(name) {
767
1947
  case "image":
768
1948
  return "img";
769
1949
  case "button":
770
- return "button";
1950
+ return "weapp-button";
771
1951
  case "input":
772
1952
  return "input";
773
1953
  case "textarea":
@@ -838,7 +2018,7 @@ function unwrapExpression(expression) {
838
2018
  }
839
2019
  return trimmed;
840
2020
  }
841
- function evaluateExpression(expression, scope) {
2021
+ function evaluateExpression2(expression, scope) {
842
2022
  if (!expression) {
843
2023
  return void 0;
844
2024
  }
@@ -846,7 +2026,7 @@ function evaluateExpression(expression, scope) {
846
2026
  if (!trimmed) {
847
2027
  return void 0;
848
2028
  }
849
- let evaluator = expressionCache.get(trimmed);
2029
+ let evaluator = expressionCache2.get(trimmed);
850
2030
  if (!evaluator) {
851
2031
  try {
852
2032
  evaluator = new Function("scope", `with(scope){ return (${trimmed}); }`);
@@ -854,7 +2034,7 @@ function evaluateExpression(expression, scope) {
854
2034
  const reason = error instanceof Error ? error.message : String(error);
855
2035
  throw new SyntaxError(`[@weapp-vite/web] \u65E0\u6CD5\u89E3\u6790\u8868\u8FBE\u5F0F "${trimmed}": ${reason}`);
856
2036
  }
857
- expressionCache.set(trimmed, evaluator);
2037
+ expressionCache2.set(trimmed, evaluator);
858
2038
  }
859
2039
  try {
860
2040
  return evaluator(scope);
@@ -881,7 +2061,7 @@ function interpolateText(source, scope, escapeResult) {
881
2061
  break;
882
2062
  }
883
2063
  const expression = source.slice(start + 2, end).trim();
884
- const evaluated = toDisplayString(evaluateExpression(expression, scope));
2064
+ const evaluated = toDisplayString(evaluateExpression2(expression, scope));
885
2065
  buffer += evaluated;
886
2066
  cursor = end + 2;
887
2067
  }
@@ -999,7 +2179,7 @@ function renderConditionalSequence(nodes, startIndex, scope, renderChildren) {
999
2179
  if (!conditionExpr) {
1000
2180
  continue;
1001
2181
  }
1002
- const condition = evaluateExpression(conditionExpr, scope);
2182
+ const condition = evaluateExpression2(conditionExpr, scope);
1003
2183
  if (condition) {
1004
2184
  return {
1005
2185
  rendered: renderElement(
@@ -1022,14 +2202,14 @@ function renderElement(node, scope, renderChildren, options = {}) {
1022
2202
  if (!options.skipFor) {
1023
2203
  const forExtract = extractFor(attribs);
1024
2204
  if (forExtract.expr) {
1025
- const list = normalizeList(evaluateExpression(forExtract.expr, scope));
2205
+ const list = normalizeList2(evaluateExpression2(forExtract.expr, scope));
1026
2206
  if (!list.length) {
1027
2207
  return "";
1028
2208
  }
1029
2209
  let buffer = "";
1030
2210
  for (let idx = 0; idx < list.length; idx++) {
1031
2211
  const item = list[idx];
1032
- const childScope = createChildScope(scope);
2212
+ const childScope = createChildScope2(scope);
1033
2213
  childScope[forExtract.itemName] = item;
1034
2214
  childScope[forExtract.indexName] = idx;
1035
2215
  buffer += renderElement(node, childScope, renderChildren, {
@@ -1090,7 +2270,7 @@ function renderTree(input, scope) {
1090
2270
  return "";
1091
2271
  }
1092
2272
  function renderTemplate(nodes, scope) {
1093
- const renderScope = createScope(scope);
2273
+ const renderScope = createScope2(scope);
1094
2274
  return renderTree(nodes, renderScope);
1095
2275
  }
1096
2276
  function createTemplate(source) {
@@ -1098,8 +2278,11 @@ function createTemplate(source) {
1098
2278
  return (scope) => renderTemplate(nodes, scope);
1099
2279
  }
1100
2280
  export {
2281
+ createRenderContext,
1101
2282
  createTemplate,
1102
2283
  defineComponent,
2284
+ ensureButtonDefined,
2285
+ hideNavigationBarLoading,
1103
2286
  initializePageRoutes,
1104
2287
  injectStyle,
1105
2288
  navigateBack,
@@ -1111,5 +2294,11 @@ export {
1111
2294
  registerPage,
1112
2295
  removeStyle,
1113
2296
  renderTemplate,
2297
+ setButtonFormConfig,
2298
+ setNavigationBarColor,
2299
+ setNavigationBarMetrics,
2300
+ setNavigationBarTitle,
2301
+ setupRpx,
2302
+ showNavigationBarLoading,
1114
2303
  switchTab
1115
2304
  };