weifuwu 0.70.0 → 0.72.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/README.md +66 -55
- package/dist/components/Accordion/Accordion.d.ts +1 -1
- package/dist/components/Affix/Affix.d.ts +1 -1
- package/dist/components/AiChat/AiChat.d.ts +2 -2
- package/dist/components/Alert/Alert.d.ts +1 -1
- package/dist/components/AlertGroup/AlertGroup.d.ts +1 -1
- package/dist/components/Anchor/Anchor.d.ts +1 -1
- package/dist/components/ApprovalCard/ApprovalCard.d.ts +3 -1
- package/dist/components/AspectRatio/AspectRatio.d.ts +1 -1
- package/dist/components/AutoComplete/AutoComplete.d.ts +1 -1
- package/dist/components/Avatar/Avatar.d.ts +1 -1
- package/dist/components/AvatarGroup/AvatarGroup.d.ts +1 -1
- package/dist/components/BackTop/BackTop.d.ts +1 -1
- package/dist/components/Badge/Badge.d.ts +7 -1
- package/dist/components/Breadcrumb/Breadcrumb.d.ts +1 -1
- package/dist/components/Button/Button.d.ts +1 -1
- package/dist/components/Calendar/Calendar.d.ts +1 -1
- package/dist/components/Card/Card.d.ts +1 -1
- package/dist/components/Carousel/Carousel.d.ts +1 -1
- package/dist/components/Cascader/Cascader.d.ts +7 -3
- package/dist/components/Chart/Chart.d.ts +1 -1
- package/dist/components/Checkbox/Checkbox.d.ts +1 -1
- package/dist/components/CheckboxGroup/CheckboxGroup.d.ts +1 -1
- package/dist/components/CodeBlock/CodeBlock.d.ts +1 -1
- package/dist/components/Collapse/Collapse.d.ts +1 -1
- package/dist/components/ColorPicker/ColorPicker.d.ts +1 -1
- package/dist/components/Command/Command.d.ts +1 -1
- package/dist/components/Confirm/Confirm.d.ts +2 -2
- package/dist/components/ContextMenu/ContextMenu.d.ts +1 -1
- package/dist/components/CopyButton/CopyButton.d.ts +1 -1
- package/dist/components/DatePicker/DatePicker.d.ts +1 -1
- package/dist/components/Descriptions/Descriptions.d.ts +1 -1
- package/dist/components/DiffView/DiffView.d.ts +1 -1
- package/dist/components/Divider/Divider.d.ts +1 -1
- package/dist/components/Drawer/Drawer.d.ts +1 -1
- package/dist/components/Dropdown/Dropdown.d.ts +1 -1
- package/dist/components/Editor/Editor.d.ts +1 -1
- package/dist/components/Editor/tools/toolbar.d.ts +1 -1
- package/dist/components/EmptyState/EmptyState.d.ts +3 -2
- package/dist/components/Field/Field.d.ts +1 -1
- package/dist/components/FileUpload/FileUpload.d.ts +1 -1
- package/dist/components/FloatButton/FloatButton.d.ts +1 -1
- package/dist/components/Form/Form.d.ts +1 -1
- package/dist/components/Grid/Grid.d.ts +1 -1
- package/dist/components/Highlight/Highlight.d.ts +1 -1
- package/dist/components/HoverCard/HoverCard.d.ts +2 -2
- package/dist/components/Icon/Icon.d.ts +1 -1
- package/dist/components/Img/Img.d.ts +1 -1
- package/dist/components/InView/InView.d.ts +1 -1
- package/dist/components/InfiniteScroll/InfiniteScroll.d.ts +1 -1
- package/dist/components/Input/Input.d.ts +1 -1
- package/dist/components/InputNumber/InputNumber.d.ts +3 -3
- package/dist/components/JSONViewer/JSONViewer.d.ts +1 -1
- package/dist/components/Kanban/Kanban.d.ts +1 -1
- package/dist/components/Label/Label.d.ts +1 -1
- package/dist/components/Layout/Layout.d.ts +3 -1
- package/dist/components/Link/Link.d.ts +1 -1
- package/dist/components/List/List.d.ts +1 -1
- package/dist/components/Loading/Loading.d.ts +1 -1
- package/dist/components/LogViewer/LogViewer.d.ts +1 -1
- package/dist/components/Markdown/Markdown.d.ts +1 -1
- package/dist/components/Markdown/parser.d.ts +11 -5
- package/dist/components/Mentions/Mentions.d.ts +1 -1
- package/dist/components/Menu/Menu.d.ts +2 -2
- package/dist/components/Menubar/Menubar.d.ts +1 -1
- package/dist/components/MessageBubble/MessageBubble.d.ts +1 -1
- package/dist/components/Modal/Modal.d.ts +1 -1
- package/dist/components/NavMenu/NavMenu.d.ts +1 -1
- package/dist/components/Notification/Notification.d.ts +2 -2
- package/dist/components/PageHeader/PageHeader.d.ts +1 -1
- package/dist/components/Pagination/Pagination.d.ts +1 -1
- package/dist/components/PasswordInput/PasswordInput.d.ts +1 -1
- package/dist/components/PinInput/PinInput.d.ts +1 -1
- package/dist/components/Pipeline/Pipeline.d.ts +1 -1
- package/dist/components/Popconfirm/Popconfirm.d.ts +2 -2
- package/dist/components/Popover/Popover.d.ts +2 -2
- package/dist/components/ProgressBar/ProgressBar.d.ts +6 -1
- package/dist/components/QRCode/QRCode.d.ts +1 -1
- package/dist/components/RadioGroup/RadioGroup.d.ts +1 -1
- package/dist/components/Rate/Rate.d.ts +3 -1
- package/dist/components/Resizable/Resizable.d.ts +1 -1
- package/dist/components/Result/Result.d.ts +1 -1
- package/dist/components/Scrollbar/Scrollbar.d.ts +1 -1
- package/dist/components/SearchInput/SearchInput.d.ts +1 -1
- package/dist/components/SegmentedControl/SegmentedControl.d.ts +1 -1
- package/dist/components/Select/Select.d.ts +1 -1
- package/dist/components/Skeleton/Skeleton.d.ts +1 -1
- package/dist/components/Slider/Slider.d.ts +1 -1
- package/dist/components/Space/Space.d.ts +1 -1
- package/dist/components/Sparkline/Sparkline.d.ts +3 -1
- package/dist/components/StatCard/StatCard.d.ts +5 -3
- package/dist/components/Steps/Steps.d.ts +1 -1
- package/dist/components/Switch/Switch.d.ts +1 -1
- package/dist/components/Table/Table.d.ts +1 -1
- package/dist/components/Tabs/Tabs.d.ts +1 -1
- package/dist/components/Tag/Tag.d.ts +1 -1
- package/dist/components/TagsInput/TagsInput.d.ts +1 -1
- package/dist/components/Textarea/Textarea.d.ts +1 -1
- package/dist/components/ThemeSwitch/ThemeSwitch.d.ts +1 -1
- package/dist/components/Timeline/Timeline.d.ts +6 -5
- package/dist/components/Toast/Toast.d.ts +2 -2
- package/dist/components/ToggleGroup/ToggleGroup.d.ts +1 -1
- package/dist/components/ToolCallCard/ToolCallCard.d.ts +1 -1
- package/dist/components/Tooltip/Tooltip.d.ts +2 -2
- package/dist/components/Tour/Tour.d.ts +1 -1
- package/dist/components/Transfer/Transfer.d.ts +7 -3
- package/dist/components/Tree/Tree.d.ts +4 -2
- package/dist/components/TreeSelect/TreeSelect.d.ts +1 -1
- package/dist/components/Typography/Typography.d.ts +1 -1
- package/dist/components/VirtualList/VirtualList.d.ts +1 -1
- package/dist/components/VirtualTable/VirtualTable.d.ts +10 -2
- package/dist/components/Watermark/Watermark.d.ts +1 -1
- package/dist/components/index.d.ts +1 -1
- package/dist/components/index.js +13 -13
- package/dist/components/style.css +803 -320
- package/dist/dev/index.js +1 -1
- package/dist/index.js +12 -5
- package/dist/layout/weifuwu-layout.css +133 -15
- package/dist/ui/index.d.ts +1 -1
- package/dist/ui/ssr-page.d.ts +1 -1
- package/dist/ui/ssr.d.ts +1 -1
- package/dist/ui-dom/Confirm.d.ts +44 -0
- package/dist/ui-dom/Notification.d.ts +70 -0
- package/dist/ui-dom/Toast.d.ts +43 -0
- package/dist/{client → ui-dom}/diff.d.ts +7 -6
- package/dist/ui-dom/index.d.ts +33 -0
- package/dist/ui-dom/index.js +18 -0
- package/dist/ui-dom/jsx-runtime.d.ts +4 -0
- package/dist/ui-dom/jsx-runtime.js +1 -0
- package/dist/ui-dom/popup-tracker.d.ts +36 -0
- package/dist/ui-dom/registry.d.ts +39 -0
- package/dist/{client → ui-dom}/render.d.ts +14 -6
- package/dist/ui-dom/router.d.ts +66 -0
- package/dist/ui-dom/serve.d.ts +28 -0
- package/dist/ui-dom/ssr.d.ts +56 -0
- package/dist/{client → ui-dom}/types.d.ts +63 -18
- package/dist/{client → ui-dom}/ui.d.ts +9 -1
- package/dist/{client → ui-dom}/vnode.d.ts +24 -16
- package/docs/components.md +2 -2
- package/docs/custom-components.md +2 -0
- package/docs/frontend-middleware.md +3 -1
- package/docs/frontend-ui-dom.md +110 -0
- package/docs/frontend.md +3 -1
- package/docs/layout.md +37 -9
- package/docs/realtime.md +2 -0
- package/docs/saas.md +2 -0
- package/package.json +7 -7
- package/dist/client/app.d.ts +0 -26
- package/dist/client/error-boundary.d.ts +0 -23
- package/dist/client/index.d.ts +0 -54
- package/dist/client/index.js +0 -6
- package/dist/client/registry.d.ts +0 -34
- package/dist/client/router.d.ts +0 -26
- package/dist/client/type-flow.test.d.ts +0 -7
- /package/dist/{client → ui-dom}/ai.d.ts +0 -0
- /package/dist/{client → ui-dom}/browser.d.ts +0 -0
- /package/dist/{client → ui-dom}/focus-trap.d.ts +0 -0
- /package/dist/{client → ui-dom}/hydration.d.ts +0 -0
- /package/dist/{client → ui-dom}/i18n.d.ts +0 -0
- /package/dist/{client → ui-dom}/locale/en_US.d.ts +0 -0
- /package/dist/{client → ui-dom}/locale/zh_CN.d.ts +0 -0
- /package/dist/{client → ui-dom}/middleware/api.d.ts +0 -0
- /package/dist/{client → ui-dom}/middleware/auth.d.ts +0 -0
- /package/dist/{client → ui-dom}/middleware/ws.d.ts +0 -0
- /package/dist/{client → ui-dom}/motion.d.ts +0 -0
- /package/dist/{client → ui-dom}/popup.d.ts +0 -0
- /package/dist/{client → ui-dom}/reactive.d.ts +0 -0
- /package/dist/{client → ui-dom}/route-match.d.ts +0 -0
- /package/dist/{client → ui-dom}/scroll-lock.d.ts +0 -0
- /package/dist/{client → ui-dom}/use-chat.d.ts +0 -0
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* weifuwu/ui-dom — 前端路由(UIRouter 纯路由 + uiServe 渲染运行时)
|
|
3
|
+
*
|
|
4
|
+
* 定稿架构(design/ui-architecture.md + ui-dom-client-align.md):
|
|
5
|
+
* req = window.location,res = VNode,uiServe = VDOM(落地)
|
|
6
|
+
* handler = 异步组件:async (location, ctx) => vnode($ 有效)
|
|
7
|
+
* middleware = 两阶段 async(layout 与 SSR 都是中间件)
|
|
8
|
+
*
|
|
9
|
+
* 渲染运行时复制自 client(registry/createUi/render/diff/popup-tracker 局部实例),
|
|
10
|
+
* VNode 契约共享(components 直接复用)。
|
|
11
|
+
*/
|
|
12
|
+
export { UIRouter } from './router.ts';
|
|
13
|
+
export type { UIRouterOptions, RouteMatch } from './router.ts';
|
|
14
|
+
export { uiServe } from './serve.ts';
|
|
15
|
+
export type { UIServeOptions, UIServeHandle } from './serve.ts';
|
|
16
|
+
export { h, jsx, jsxs, jsxDEV, Fragment, Portal, createPortal } from './vnode.ts';
|
|
17
|
+
export type { VNode, VNodeChild, VNodeType, Component } from './vnode.ts';
|
|
18
|
+
export { createReactiveState } from './reactive.ts';
|
|
19
|
+
export { createClientBrowser } from './browser.ts';
|
|
20
|
+
export { mountVNode } from './render.ts';
|
|
21
|
+
export { callRefCleanup } from './render.ts';
|
|
22
|
+
export { animateOut } from './motion.ts';
|
|
23
|
+
export { patchValue } from './diff.ts';
|
|
24
|
+
export { hydrateVNode } from './hydration.ts';
|
|
25
|
+
export { isAsyncComponent, asyncComponent } from './vnode.ts';
|
|
26
|
+
export { api } from './middleware/api.ts';
|
|
27
|
+
export type { ApiClient, ApiOptions, ApiRequestOptions, ApiInjected } from './middleware/api.ts';
|
|
28
|
+
export { auth } from './middleware/auth.ts';
|
|
29
|
+
export type { AuthClient, AuthInjected } from './middleware/auth.ts';
|
|
30
|
+
export { ws } from './middleware/ws.ts';
|
|
31
|
+
export type { WsClient, WsInjected } from './middleware/ws.ts';
|
|
32
|
+
export { ssrPage, serializeData, ssrToString } from './ssr.ts';
|
|
33
|
+
export type { UIRequest, UIResponse, UIHandler, UIMiddleware, UIRouteDef, WfuiContext, } from './types.ts';
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
function wn(e){let n=[],t=(e||"/").replace(/:(\w+)/g,(o,i)=>(n.push(i),"([^/]+)")).replace(/\*/g,".*");return{re:new RegExp(`^${t}$`),keys:n}}var Ce=class{_routes=[];_middlewares=[];_injections=[];_injected=!1;_mode;_notFound;constructor(n={}){this._mode=n.mode??"history"}get mode(){return this._mode}use(n,t){if(typeof n=="string"&&t){let o=this,i=n,u=async(r,d,a)=>{let l=d.__routePath??o.getPath(),f=null;return l===i?f="/":(i==="/"?l!=="/"&&l.startsWith("/"):l.startsWith(i+"/"))&&(f=l.slice(i.length)),f===null?a:async(g,w)=>t._handle(f,g,w)};return this._middlewares.push(u),this}return n.length<=1?(this._injections.push(n),this):(this._middlewares.push(n),this)}async _ensureInjected(n){if(!this._injected){this._injected=!0;for(let t of this._injections){let o=await t(n);o&&o!==n&&Object.assign(n,o)}}}get(n,t,o){return this._routes.push({path:n,handler:t,title:o?.title}),this}notFound(n){return this._notFound=n,this}getPath(){return this._getPath(void 0)}_getPath(n){let t=n?.location??(typeof window<"u"?window.location:null);return this._mode==="hash"?(t?.hash??"").replace(/^#/,"")||"/":t?.pathname??"/"}match(n){let t=null;for(let o of this._routes){let{re:i,keys:u}=wn(o.path),r=n.match(i);if(!r)continue;let d={};for(let a=0;a<u.length;a++)d[u[a]]=decodeURIComponent(r[a+1]);t={handler:o.handler,params:d,title:o.title};break}return t||(t={handler:this._notFound??(()=>null),params:{}}),t}async _handle(n,t,o){await this._ensureInjected(o);let i=this.match(n);i.title&&typeof document<"u"&&(document.title=i.title),o.params=i.params;let r=i.handler,d=o.__routePath;o.__routePath=n;try{for(let a=this._middlewares.length-1;a>=0;a--){let l=this._middlewares[a],f=r;r=await l(t,o,f)??f}return await r(t,o)}finally{o.__routePath=d}}async execute(n,t,o){await this._ensureInjected(t);let i=this.match(o);i.title&&typeof document<"u"&&(document.title=i.title),t.params=i.params;let r=i.handler;for(let d=this._middlewares.length-1;d>=0;d--){let a=this._middlewares[d],l=r;r=await a(n,t,l)??l}return await r(n,t)}};function ee(){return{idCounter:0,idRegistry:new Map,unmountHooks:[],asyncFactoryCache:new WeakMap}}function O(e){return e?.__registry??ee()}function ae(e){return`_wf_${e.idCounter++}`}function ue(e,n){return e.unmountHooks.push(n),()=>{let t=e.unmountHooks.indexOf(n);t>=0&&e.unmountHooks.splice(t,1)}}function Te(e,n,t){let o=e.asyncFactoryCache.get(n);if(o)return o;let i={promise:null};return i.promise=Promise.resolve().then(()=>n(t)).then(u=>{if(typeof u!="function")throw new Error(`asyncComponent factory <${n.name||"anonymous"}> must return a Component (initProps, ctx) => (props) => VNode.`);return i.resolved=u,u}),e.asyncFactoryCache.set(n,i),i}async function We(e,n,t){return Te(e,n,t).promise}function De(e,n){return e.asyncFactoryCache.get(n)?.resolved}function xe(e,n,t,o){try{e(n)}catch(i){console.error(`[weifuwu] ref ${t} error in <${o??"anonymous"}>`,i)}}function bn(e,n){let t=e._child;if(t!=null)if(Array.isArray(t))for(let o of t)o&&typeof o=="object"&&U(o,n);else typeof t=="object"&&U(t,n)}function U(e,n){if(e==null||typeof e!="object")return;let t=e;if(t._id){if(t._customId&&n.idRegistry.delete(t._customId),n.idRegistry.delete(t._id),n.unmountHooks.length>0){let o=[...n.unmountHooks];for(let i of o)i(t._id);if(t._customId)for(let i of o)i(t._customId)}t._id=void 0,t._customId=void 0,t._render=void 0,t._parentNode=void 0,t._refNode=void 0}if(t._child!=null){if(Array.isArray(t._child))for(let o of t._child)o&&typeof o=="object"&&U(o,n);else U(t._child,n);t._child=void 0}if(t.props?.children&&typeof t.type=="string"){let o=Array.isArray(t.props.children)?t.props.children:[t.props.children];for(let i of o)i&&typeof i=="object"&&U(i,n)}typeof t.props?.ref=="function"&&xe(t.props.ref,null,"cleanup"),t._remoteEl&&(bn(t,n),t._remoteEl.remove(),t._remoteEl=void 0)}function je(e,n="bottom",t=6,o=!0){switch(n){case"bottom":return{top:e.bottom+t,left:o?e.left+e.width/2:e.left};case"top":return{top:e.top-t,left:o?e.left+e.width/2:e.left};case"left":return{top:o?e.top+e.height/2:e.top,left:e.left-t};case"right":return{top:o?e.top+e.height/2:e.top,left:e.right+t}}}function de(e,n,t=8){if(!n)return e;let o=n.getBoundingClientRect();if(o.width===0&&o.height===0)return e;let i=Number.parseFloat(n.style.top)||o.top,u=Number.parseFloat(n.style.left)||o.left,r=e.top-i,d=e.left-u,a={top:o.top+r,bottom:o.bottom+r,left:o.left+d,right:o.right+d},l=window.innerWidth,f=window.innerHeight,g=e.top,w=e.left;return a.bottom>f-t&&(g=Math.max(t,g-(a.bottom-(f-t)))),a.top<t&&(g=Math.max(t,g+(t-a.top))),a.right>l-t&&(w=Math.max(t,w-(a.right-(l-t)))),a.left<t&&(w=Math.max(t,w+(t-a.left))),{top:g,left:w,width:e.width}}function qe(e){let n=new Map,t=new Map,o=!1,i=0;function u(){i||(i=requestAnimationFrame(()=>{i=0;let f=[];for(let[g,w]of n){if(!w.isOpen())continue;let T=w.getEl();if(!T)continue;let m=T.getBoundingClientRect();if(m.width===0&&m.height===0)continue;let h=w.compute(m);Object.assign(w.pos,de(h,w.panel?.(),w.margin)),f.push(g)}for(let[g,w]of t){let T=w.getScroller(),m=T instanceof Window?document.scrollingElement?.scrollTop??T.scrollY??0:T.scrollTop??0;m!==w.handle.y&&(w.handle.y=m,f.push(g))}f.length>0&&e(f)}))}function r(){o||(o=!0,window.addEventListener("scroll",u,{capture:!0,passive:!0}),window.addEventListener("resize",u))}function d(){o&&(window.removeEventListener("scroll",u,{capture:!0}),window.removeEventListener("resize",u),o=!1)}function a(f){for(let g of[...n.keys()])(g.startsWith(`popup:${f}:`)||g===`popup:${f}`)&&n.delete(g);t.delete(f)}function l(){d(),i&&(cancelAnimationFrame(i),i=0),n.clear(),t.clear()}return{popupTrackers:n,scrollTrackers:t,schedulePopupRecompute:u,ensurePopupListeners:r,destroyPopupListeners:d,cleanupTrackers:a,destroy:l}}var ne=0,$e="",Fe="",Ke="",Be="",ce=0;function Ge(){return typeof window<"u"&&typeof document<"u"}function Ye(){if(ne++,ne>1||!Ge())return;ce=window.scrollY;let e=document.body;$e=e.style.overflow,Fe=e.style.position,Ke=e.style.top,Be=e.style.width,e.style.overflow="hidden",(/iPhone|iPad|iPod/.test(navigator.platform)||/Mac/.test(navigator.platform)&&"ontouchend"in document)&&(e.style.position="fixed",e.style.top=`-${ce}px`,e.style.width="100%")}function ze(){if(ne===0||(ne--,ne>0)||!Ge())return;let e=document.body;e.style.overflow=$e,e.style.position=Fe,e.style.top=Ke,e.style.width=Be,ce>0&&window.scrollTo(0,ce)}var Cn='a[href], button:not([disabled]), input:not([disabled]), textarea:not([disabled]), select:not([disabled]), [tabindex]:not([tabindex="-1"])';function Ee(e){let n=e.querySelectorAll(Cn);if(n.length===0)return()=>{};let t=n[0],o=n[n.length-1],i=r=>{r.key==="Tab"&&(r.shiftKey&&document.activeElement===t?(r.preventDefault(),o.focus()):!r.shiftKey&&document.activeElement===o&&(r.preventDefault(),t.focus()))},u=document.activeElement;return queueMicrotask(()=>{t.focus()}),e.addEventListener("keydown",i),()=>{e.removeEventListener("keydown",i),u?.focus()}}function G(e){let n=new WeakMap,t=new Set,o=u=>{if(u===null||typeof u!="object")return u;if(u instanceof Set||u instanceof Map){if(n.has(u))return n.get(u);let d=u instanceof Set?new Set(["add","delete","clear"]):new Set(["set","delete","clear"]),a=new Proxy(u,{get(l,f){let g=Reflect.get(l,f);return typeof g=="function"?d.has(String(f))?(...w)=>{let T=g.apply(l,w);e();for(let m of t)m();return T}:g.bind(l):g},set(l,f,g){Reflect.set(l,f,g),e();for(let w of t)w();return!0}});return n.set(u,a),a}if(u instanceof Date||u instanceof RegExp)return u;if(n.has(u))return n.get(u);let r=new Proxy(u,{set(d,a,l){if(Reflect.get(d,a)===l)return!0;Reflect.set(d,a,l),e();for(let g of t)g();return!0},get(d,a){let l=Reflect.get(d,a);return typeof l=="object"&&l!==null?o(l):l},deleteProperty(d,a){if(Reflect.has(d,a)){Reflect.deleteProperty(d,a),e();for(let l of t)l()}return!0}});return n.set(u,r),r},i=o({});return Object.defineProperty(i,"__watch",{value:u=>(t.add(u),()=>{t.delete(u)}),writable:!1,enumerable:!1}),i}function Je(e,n,t){let o=new AbortController,i=t?.signal;i&&(i.aborted?o.abort():i.addEventListener("abort",()=>o.abort(),{once:!0}));let u=t?.traceId??_n(),r=t?.record!==!1,d=[],a=(async()=>{let l;try{l=await fetch(e,{method:"POST",headers:{"Content-Type":"application/json","X-Trace-Id":u,Accept:"text/event-stream",...t?.headers},body:JSON.stringify(n),signal:o.signal})}catch(f){if(o.signal.aborted)return;t?.onError?.({code:"provider_error",message:f instanceof Error?f.message:String(f)});return}if(!l.ok){t?.onError?.({code:Pn(l.status),message:`HTTP ${l.status} ${l.statusText}`});return}try{for await(let{name:f,data:g}of xn(l.body)){if(o.signal.aborted)return;En(d,{name:f,data:g},r),Tn(f,g,t??{})}}catch(f){if(o.signal.aborted)return;t?.onError?.({code:"provider_error",message:f instanceof Error?f.message:String(f)})}})();return{abort:()=>o.abort(),done:a,traceId:u,events:d}}function Tn(e,n,t){switch(e){case"wf:token":return t.onToken?.(n.text);case"wf:tool_call":return t.onToolCall?.(n);case"wf:tool_result":return t.onToolResult?.(n);case"wf:tool_progress":return t.onToolProgress?.(n);case"wf:step":return t.onStep?.(n);case"wf:approval_request":return t.onApproval?.(n);case"wf:usage":return t.onUsage?.(n);case"wf:done":return t.onDone?.(n);case"wf:error":return t.onError?.(n);default:return t.onEvent?.(e,n)}}async function*xn(e){let n=e.getReader(),t=new TextDecoder,o="";try{for(;;){let{done:i,value:u}=await n.read();if(i)break;o+=t.decode(u,{stream:!0});let r=o.split(`
|
|
2
|
+
|
|
3
|
+
`);o=r.pop()??"";for(let d of r){let a="message",l="";for(let f of d.split(`
|
|
4
|
+
`))f.startsWith("event: ")?a=f.slice(7):f.startsWith("data: ")&&(l+=f.slice(6));if(l)try{yield{name:a,data:JSON.parse(l)}}catch{}}}}finally{n.releaseLock()}}function En(e,n,t){t&&(e.length>=1e3&&e.shift(),e.push(n))}function Pn(e){return e===401||e===403?"auth_failed":e===429?"rate_limited":e>=500?"provider_error":"invalid_request"}function _n(){return typeof crypto<"u"&&typeof crypto.randomUUID=="function"?crypto.randomUUID():`trace-${Date.now()}-${Math.random().toString(36).slice(2,10)}`}function kn(e){return e.map(n=>({role:n.role,content:n.content}))}function Pe(){return typeof crypto<"u"&&typeof crypto.randomUUID=="function"?crypto.randomUUID():`msg-${Date.now()}-${Math.random().toString(36).slice(2,10)}`}function Xe(e,n,t){t.initialMessages?e.messages=structuredClone(t.initialMessages):e.messages===void 0&&(e.messages=[]),e.input===void 0&&(e.input=""),e.streaming===void 0&&(e.streaming=!1),e.error===void 0&&(e.error=null),e.usage===void 0&&(e.usage=null),e.step===void 0&&(e.step=null);let o=null;function i(){if(!e.streaming)return;let T=e.messages[e.messages.length-1];return T&&T.role==="assistant"&&T.status==="streaming"?T:void 0}function u(T,m,h){let b=i();switch(T){case"wf:token":b&&(b.content+=m.text);break;case"wf:tool_call":{b&&(b.toolCalls||(b.toolCalls=[]),b.toolCalls.push({call:m,status:"running"}));break}case"wf:tool_progress":{let N=m,s=b?.toolCalls?.find(c=>c.call.id===N.toolCallId);s&&(s.progress=N);break}case"wf:tool_result":{let N=m,s=b?.toolCalls?.find(c=>c.call.id===N.id);s&&(s.result=N,s.status=N.ok?"ok":"error");break}case"wf:approval_request":b&&(b.approval=m);break;case"wf:usage":b&&(b.usage=m);break;case"wf:step":e.step=m;break;case"wf:done":b&&(b.status="done",b.approval=void 0),e.streaming=!1,e.step=null;break;case"wf:error":b&&(b.status="error",b.error=m,b.approval=void 0),e.error=m,e.streaming=!1,e.step=null;break;default:h?.(T,m);break}}function r(){let T=t.body?t.body(e.messages):{messages:kn(e.messages)};o=n(t.url,T,{onToken:h=>u("wf:token",{text:h}),onToolCall:h=>u("wf:tool_call",h),onToolProgress:h=>u("wf:tool_progress",h),onToolResult:h=>u("wf:tool_result",h),onApproval:h=>u("wf:approval_request",h),onUsage:h=>u("wf:usage",h),onStep:h=>u("wf:step",h),onDone:h=>u("wf:done",h),onError:h=>u("wf:error",h),onEvent:(h,b)=>u(h,b,t.onEvent)},{signal:t.signal,headers:t.headers}),e.streaming=!0;let m=i();m&&o?.traceId&&(m.id=o.traceId)}function d(){if(e.streaming)return;let T=String(e.input??"").trim();T&&(e.input="",e.error=null,e.usage=null,e.step=null,e.messages.push({id:Pe(),role:"user",content:T,status:"done"},{id:Pe(),role:"assistant",content:"",status:"streaming",toolCalls:[]}),r())}function a(){o?.abort(),e.streaming=!1,e.step=null;let T=e.messages[e.messages.length-1];T&&T.role==="assistant"&&T.status==="streaming"&&(!T.content&&(!T.toolCalls||T.toolCalls.length===0)?e.messages.pop():T.status="done")}function l(){if(e.streaming)return;let T=-1;for(let m=e.messages.length-1;m>=0;m--)if(e.messages[m].role==="user"){T=m;break}T!==-1&&(e.messages.splice(T+1),e.error=null,e.usage=null,e.step=null,e.messages.push({id:Pe(),role:"assistant",content:"",status:"streaming",toolCalls:[]}),r())}function f(){o?.abort(),e.messages=[],e.input="",e.streaming=!1,e.error=null,e.usage=null,e.step=null}async function g(T,m){let h=e.messages[e.messages.length-1],b=h?.role==="assistant"?h.approval:void 0;if(b&&(h.approval=void 0,!!t.approveUrl))try{await fetch(t.approveUrl,{method:"POST",headers:{"Content-Type":"application/json",...t.headers},body:JSON.stringify({id:b.id,decision:T,note:m}),signal:t.signal})}catch(N){if(t.signal?.aborted)return;e.error={code:"provider_error",message:N instanceof Error?N.message:String(N)}}}function w(){o?.abort(),o=null}return{send:d,stop:a,retry:l,clear:f,approve:g,dispose:w}}var Qe="__wfAsyncComponent";function Nn(e){let n=e;return n[Qe]=!0,n}function z(e){return typeof e=="function"&&e?.[Qe]===!0}var $=Symbol("Fragment"),j=Symbol("Portal");function _e(e,n,t){return{type:e,props:Ze(n),key:t??void 0}}var Rn=_e;function Sn(e,n,t){return _e(e,n,t)}function Mn(e,n,...t){let o=Ze(n??{});return t.length>0&&(o.children=t.length===1?t[0]:t),{type:e,props:o,key:n?.key??void 0}}function Ze(e){if(!e)return{};let n={};for(let t of Object.keys(e))t!=="key"&&(n[t]=e[t]);return n}function ke(e,n){return{type:j,props:{children:e,portalKey:n},key:n??void 0,_placement:"remote"}}var fe=new Set,te=new Map,pe=new Map,oe=new Map;function en(e){let{ctx:n,renderByIds:t,getSelfId:o,dirtyBatch:i,dirtySet:u,mediaRegistry:r,popupTrackers:d,scrollTrackers:a,schedulePopupRecompute:l,ensurePopupListeners:f,isRendering:g,isMounting:w,setMounting:T,endMounting:m}=e,h=e.registry??O(n),b=s=>ue(h,s);return{_selfId:"_wf_root",_ctxVersion:0,_dirtySet:u,setMounting:T,endMounting:m,bumpCtxVersion:function(){this._ctxVersion++},render:function(s){if(g()){if(w())return;this._pendingRender||(this._pendingRender=!0,queueMicrotask(()=>{this._pendingRender=!1,this.render(s)}));return}if(!s||s.length===0){let c=o(this);if(c)s=[c];else return}t(s)},dirty:function(s){if(!w()){if(g()){this._pendingDirty||(this._pendingDirty=!0,queueMicrotask(()=>{this._pendingDirty=!1,this.dirty(s)}));return}if(!s||s.length===0){let c=o(this);if(c)s=[c];else return}for(let c of s)c&&(i.add(c),u.add(c));this._dirtyScheduled||(this._dirtyScheduled=!0,queueMicrotask(()=>{this._dirtyScheduled=!1;let c=[...i];i.clear(),c.length>0&&t(c)}))}},$:function(){let s=this;if(!Object.prototype.hasOwnProperty.call(s,"_$cache")){let c=G(()=>{let p=s._selfVNode?._id??o(s);p&&n.ui.dirty([p])});s._$cache=c}return s._$cache},useChat:function(s){let c=this.$(),p=Xe(c,Je,s);Object.assign(c,{send:p.send,stop:p.stop,retry:p.retry,clear:p.clear,approve:p.approve,dispose:p.dispose});let y=o(this);if(y){let v=b(C=>{C===y&&(p.dispose(),v())})}return c},useMedia:function(s,c){let y=`media:${o(this)}:${s}`;if(!r.has(y)){let v=window.matchMedia(s);c(v.matches);let C=P=>c(P.matches);v.addEventListener("change",C),r.set(y,{mql:v,handler:C})}},useBreakpoint:function(s,c){let p=typeof s=="function"?{mobile:"(max-width: 639px)",tablet:"(min-width: 640px) and (max-width: 1023px)",desktop:"(min-width: 1024px)"}:s,y=typeof s=="function"?s:c,C=`bp:${o(this)}`;function P(){for(let[x,M]of Object.entries(p))if(window.matchMedia(M).matches)return x;return Object.keys(p)[0]??""}if(!r.has(C)){y(P());let x=[];for(let M of Object.values(p)){let V=window.matchMedia(M),L=()=>y(P());V.addEventListener("change",L),x.push({mql:V,handler:L})}r.set(C,{mqls:x})}},usePopupPosition:function(s){let c=o(this),p={top:0,left:0,refresh:()=>{}};if(!c)return p;let y={pos:p,getEl:s.el,isOpen:s.isOpen,compute:s.compute,panel:s.panel,margin:s.margin??8};return d.set(c,y),f(),p.refresh=()=>{let v=y.getEl();if(!v)return;let C=v.getBoundingClientRect();if(C.width===0&&C.height===0)return;let P=y.compute(C);Object.assign(p,de(P,y.panel?.(),y.margin))},p},useHoverCapable:function(){return typeof window<"u"&&!!window.matchMedia?.("(hover: hover)").matches},useStableRef:function(s,c){return y=>{y?s(y):c?.()}},useVisualViewport:function(){let s=o(this),c={height:window.innerHeight,offsetTop:0,keyboardOpen:!1},p=()=>{n.ui&&n.ui.dirty(s?[s]:void 0)},y=()=>{let C=window.visualViewport;c.height=C?.height??window.innerHeight,c.offsetTop=C?.offsetTop??0,c.keyboardOpen=c.height<window.innerHeight*.9,p()},v=window.visualViewport;if(v?.addEventListener?(v.addEventListener("resize",y),v.addEventListener("scroll",y)):window.addEventListener("resize",y),s){let C=b(P=>{P===s&&(v?.removeEventListener?(v.removeEventListener("resize",y),v.removeEventListener("scroll",y)):window.removeEventListener("resize",y),C())})}return c},usePopup:function(s){let c=o(this),p=this.useHoverCapable(),y=()=>typeof s.trigger=="function"?s.trigger():s.trigger,v=s.open!==void 0,C=()=>!!s.disabled?.(),P=()=>v?typeof s.open=="function"?!!s.open():!!s.open:s.isOpen(),x=_=>{C()||(v?s.onOpenChange?.(_):s.setOpen(_))},M=()=>{let _=s.placement;return typeof _=="function"?_():_??"bottom"},V=null,L=!1,E=n.ui.usePopupPosition({el:s.el,isOpen:()=>P(),compute:_=>{if(s.position){let A=s.position();return{top:A.y,left:A.x}}return je(_,M(),s.gap??6,s.center!==!1)},panel:()=>V,margin:s.margin??8}),S=_=>{if(s.closeOnOutside===!1||!P())return;let A=_.target;if(!(A instanceof Node))return;let q=s.el();q&&q.contains(A)||V&&V.contains(A)||x(!1)},k=_=>{s.closeOnEscape!==!1&&(_.key!=="Escape"||!P()||x(!1))};if(document.addEventListener("mousedown",S),document.addEventListener("keydown",k),c){let _=b(A=>{A===c&&(document.removeEventListener("mousedown",S),document.removeEventListener("keydown",k),_())})}let R={},I=_=>typeof _=="function"?_():_??0,H=()=>I(s.openDelay),He=()=>I(s.closeDelay),F,K,cn=()=>{clearTimeout(F),clearTimeout(K),F=void 0,K=void 0},fn=_=>{if(C())return;let A=_.currentTarget,q=_.relatedTarget;A.contains(q)||(clearTimeout(K),K=void 0,F=setTimeout(()=>{F=void 0,x(!0)},H()))},pn=_=>{if(C())return;let A=_.currentTarget,q=_.relatedTarget;A.contains(q)||(clearTimeout(F),F=void 0,K=setTimeout(()=>{K=void 0,x(!1)},He()))},mn=()=>{C()||(clearTimeout(K),K=void 0,F=setTimeout(()=>{F=void 0,x(!0)},H()))},yn=()=>{C()||(clearTimeout(F),F=void 0,K=setTimeout(()=>{K=void 0,x(!1)},He()))},Z=()=>y()==="hover";if(R.onMouseOver=_=>{Z()&&fn(_)},R.onMouseOut=_=>{Z()&&pn(_)},R.onClick=()=>{Z()?p||x(!P()):y()==="click"&&x(!0)},R.onFocus=()=>{Z()&&mn()},R.onBlur=()=>{Z()&&yn()},y()==="longpress"){let _,A=0,q=0,B=()=>{clearTimeout(_),_=void 0};R.onPointerDown=W=>{C()||(A=W.clientX??0,q=W.clientY??0,B(),_=setTimeout(()=>{_=void 0,s.onTrigger?.({clientX:A,clientY:q}),x(!0)},s.longPressDuration??500))},R.onPointerUp=B,R.onPointerLeave=B,R.onPointerMove=W=>{let we=Math.abs((W.clientX??0)-A),be=Math.abs((W.clientY??0)-q);(we>10||be>10)&&B()},R.onContextMenu=W=>{W.preventDefault(),s.onTrigger?.({clientX:W.clientX??0,clientY:W.clientY??0}),x(!0)}}if(R.onKeyDown=_=>{_.key==="Escape"&&s.closeOnEscape!==!1&&x(!1)},c){let _=b(A=>{A===c&&(cn(),_())})}let gn=_=>{if(_){V=_;let A=()=>E.refresh();_.addEventListener("animationend",A,{once:!0})}else V=null},he=null,ve=null,hn=_=>{gn(_),ve&&ve(_)};return{get open(){return P()},setOpen:x,wrapProps:R,portal:(_,A="popover")=>{if(C())return null;if(!P())return L=!1,he=null,null;let B=s.el();(!L||B!==he)&&(B?E.refresh():queueMicrotask(()=>{P()&&E.refresh()}),L=!0,he=B);let W=_.props??{};ve=W.ref??null;let we=["wf-popup",W.class].filter(Boolean).join(" "),be={...W.style??{},position:"fixed",top:`${E.top}px`,left:`${E.left}px`,maxWidth:s.width!==void 0?`min(${s.width}px, calc(100vw - 32px))`:"calc(100vw - 32px)"},vn={..._,props:{...W,class:we,style:be,ref:hn}};return ke(vn,A)},refresh:()=>E.refresh()}},useLongPress:function(s){let{onLongPress:c,duration:p=500}=s,y,v=0,C=0,P=null,x=()=>{clearTimeout(y),y=void 0};return{onPointerDown:M=>{v=M.clientX??0,C=M.clientY??0,P=M,x(),y=setTimeout(()=>{y=void 0,P&&c(P)},p)},onPointerUp:x,onPointerLeave:x,onPointerMove:M=>{let V=Math.abs((M.clientX??0)-v),L=Math.abs((M.clientY??0)-C);(V>10||L>10)&&x()},onContextMenu:M=>{M.preventDefault(),c(M)}}},useInView:function(s){let c=o(this),p={isIn:!1,ready:!1,observe:x,refresh:M,disconnect:V},y=null,v=null,C=()=>{n.ui&&n.ui.dirty(c?[c]:void 0)};function P(){if(v?.disconnect(),v=null,!y)return;let L=typeof s.rootMargin=="function"?s.rootMargin():s.rootMargin,E=typeof s.threshold=="function"?s.threshold():s.threshold;v=new IntersectionObserver(S=>{let k=S[S.length-1];if(!k)return;let R=k.isIntersecting,I=R!==p.isIn,H=!p.ready;p.isIn=R,p.ready=!0,s.onChange?.(k,R),(I||H)&&C()},{root:s.root?s.root():null,rootMargin:L??"0px",threshold:E??0}),v.observe(y)}function x(L){y=L,L?P():(v?.disconnect(),v=null,p.isIn=!1)}function M(){P()}function V(){v?.disconnect(),v=null}return p},useScrollPosition:function(s){let c=o(this),p={y:0,refresh(){let v=y.getScroller();p.y=v instanceof Window?document.scrollingElement?.scrollTop??v.scrollY??0:v.scrollTop??0}},y={handle:p,getScroller:s.getScroller??(()=>window)};return c?(a.set(c,y),f(),p.refresh(),p):(p.refresh(),p)},useAsync:function(s){let c=o(this),p=G(()=>{n.ui&&n.ui.dirty(c?[c]:void 0)});p.loading=!0;let y=0,v=()=>{let C=++y;p.loading=!0,p.error=null,Promise.resolve().then(()=>s()).then(P=>{y===C&&(p.data=P,p.loading=!1)}).catch(P=>{y===C&&(p.error=P,p.loading=!1)})};return v(),p.reload=v,p},useControlled:function(s){let c=o(this),p=s.value!==void 0;if(p&&!s.onChange&&s.name&&(fe.has(s.name)||(fe.add(s.name),console.warn(`[weifuwu/${s.name}] \u53D7\u63A7\u6A21\u5F0F\uFF08value \u5DF2\u4F20\uFF09\u4F46\u672A\u63D0\u4F9B onChange\uFF0C\u4EA4\u4E92\u65E0\u6CD5\u751F\u6548\u3002
|
|
5
|
+
\u975E\u53D7\u63A7\uFF1A\u53BB\u6389 value\uFF1B\u53D7\u63A7\uFF1A\u4F20\u5165 onChange={(v) => setValue(v)}`))),!p&&c&&!te.has(c)){te.set(c,s.value);let v=b(C=>{C===c&&(te.delete(c),v())})}let y=v=>{if(p){s.onChange?.(v);return}c&&te.set(c,v),n.ui&&(c?n.ui.dirty([c]):n.ui.render())};return{value:p?s.value:c?te.get(c):s.value,setValue:y,controlled:p}},useControlledInput:function(s){let c=o(this),p=this.useControlled({value:s.value,onChange:s.onChange,name:s.name});if(c&&!pe.has(c)){pe.set(c,{keyword:"",selectedLabel:""});let C=b(P=>{P===c&&(pe.delete(c),C())})}let y=c?pe.get(c):{keyword:"",selectedLabel:""},v=()=>{c?n.ui?.dirty([c]):n.ui?.render()};return{...p,get keyword(){return y.keyword},setKeyword(C){y.keyword=C,v()},get selectedLabel(){return y.selectedLabel},setSelectedLabel(C){y.selectedLabel=C,v()}}},useOpen:function(s){let c=o(this);if(c&&!oe.has(c)){oe.set(c,!1);let P=b(x=>{x===c&&(oe.delete(c),P())})}let p=s.open!==void 0;p&&!s.onOpenChange&&s.name&&!fe.has(s.name)&&(fe.add(s.name),console.warn(`[weifuwu/${s.name}] \u53D7\u63A7\u6A21\u5F0F\uFF08open \u5DF2\u4F20\uFF09\u4F46\u672A\u63D0\u4F9B onOpenChange\uFF0C\u4EA4\u4E92\u65E0\u6CD5\u751F\u6548\u3002
|
|
6
|
+
\u975E\u53D7\u63A7\uFF1A\u53BB\u6389 open\uFF1B\u53D7\u63A7\uFF1A\u4F20\u5165 onOpenChange={(o) => setOpen(o)}`));let y=()=>p?!!s.open:c?oe.get(c)??!1:!1,v=()=>{c?n.ui?.dirty([c]):n.ui?.render()},C=P=>{if(p){s.onOpenChange?.(P);return}c&&oe.set(c,P),v()};return{get open(){return y()},setOpen:C,triggerProps:{onClick:()=>C(!0),onFocus:()=>{s.openOnFocus&&C(!0)}}}},usePresence:function(s){let c=o(this),p="closed",y,v=()=>{p="closed",n.ui&&(c?n.ui.dirty([c]):n.ui.render())};return{get phase(){return p},ref:P=>{P?y||(y=()=>{p==="exit"&&v()},P.addEventListener("animationend",y)):y=void 0},sync:P=>(P?p="open":p==="open"&&(p="exit"),p)}},useDialog:function(s){let c=o(this),p,y=null,v=this.usePresence(s);return{get phase(){return v.phase},rootRef:x=>{x?(Ye(),y&&(p=Ee(y)),v.ref(x)):(ze(),p?.(),v.ref(null))},panelRef:x=>{y=x,x&&!p&&(p=Ee(x))},sync:x=>v.sync(x)}},useGlobalKey:function(s){let c=o(this);if(typeof window>"u")return()=>{};if(window.addEventListener("keydown",s),c){let p=b(y=>{y===c&&(window.removeEventListener("keydown",s),p())})}return()=>window.removeEventListener("keydown",s)},useDrag:function(s){let c=0,p=0,y=!1,v=x=>{y&&s.onMove(x,{x:x.clientX-c,y:x.clientY-p})},C=x=>{y&&(y=!1,window.removeEventListener("pointermove",v),window.removeEventListener("pointerup",C),s.onEnd?.(x))};return{onPointerDown:x=>{y||(x.preventDefault(),y=!0,c=x.clientX,p=x.clientY,window.addEventListener("pointermove",v),window.addEventListener("pointerup",C),s.onStart?.(x))}}},useDragDrop:function(s){let c={};s.onDrop&&(c.onDrop=y=>{y.preventDefault(),s.onDrop(y)}),s.onDragOver&&(c.onDragOver=y=>{y.preventDefault(),s.onDragOver(y)}),s.onDragLeave&&(c.onDragLeave=y=>s.onDragLeave(y));let p={draggable:!0};if(s.onDragStart){let y=s.onDragStart;p.onDragStart=v=>{typeof document<"u"&&document.body.classList.add("wf-dragging"),y(v)}}if(s.onDragEnd){let y=s.onDragEnd;p.onDragEnd=v=>{typeof document<"u"&&document.body.classList.remove("wf-dragging"),y(v)}}return{dropProps:c,dragProps:p}},useReducedMotion:function(){return typeof window<"u"&&!!window.matchMedia?.("(prefers-reduced-motion: reduce)").matches},useAnimationEnd:function(s,c){let p=null,y=()=>{s(),c?.once&&p&&p.removeEventListener("animationend",y)};return C=>{C?(p=C,C.addEventListener("animationend",y)):p&&(p.removeEventListener("animationend",y),p=null)}},useTween:function(s,c){let p=o(this),y=this.useReducedMotion(),v=c?.duration??400,C=c?.ease==="linear"?E=>E:E=>1-Math.pow(1-E,3),P,x=s,M={value:y?s:0,reset:()=>{}},V=()=>{n.ui&&(p?n.ui.dirty([p]):n.ui.render())},L=E=>{if(x=E,y){M.value=E,V();return}if(E===M.value)return;P&&cancelAnimationFrame(P);let S=M.value,k=performance.now(),R=I=>{let H=Math.min(1,(I-k)/v);M.value=Math.round(S+(E-S)*C(H)),H<1?(P=requestAnimationFrame(R),V()):(P=void 0,V())};P=requestAnimationFrame(R)};return M.reset=E=>{E===x&&P||L(E)},queueMicrotask(()=>L(s)),M},selfId:function(s){if(typeof s!="string"||!s)throw new Error(`[weifuwu] selfId requires a non-empty string, got ${typeof s}`);if(h.idRegistry.has(s))throw new Error(`[weifuwu] Duplicate component ID: "${s}". Each component must have a unique custom ID.`);let c=this._selfVNode;c&&(c._customId=s,h.idRegistry.set(s,c))}}}var nn=new WeakMap;function An(e){let n=nn.get(e)??{count:0,warned:!1};n.count++,n.count>=3&&!n.warned&&(n.warned=!0,console.warn("[weifuwu] ref \u51FD\u6570\u6BCF\u6B21\u6E32\u67D3\u90FD\u53D8\u5316\uFF08\u5185\u8054 ref\uFF09\u2014\u2014ref \u56DE\u8C03\u5728\u6BCF\u6B21\u6E32\u67D3\u540E\u91CD\u65B0\u6267\u884C\uFF08\u6027\u80FD\u635F\u8017\uFF09\u3002\u628A ref \u5B9A\u4E49\u5230 mount \u4F5C\u7528\u57DF\uFF08\u7A33\u5B9A\u5F15\u7528\uFF09\uFF1Aconst listRef = (el) => {...}; return h('div', { ref: listRef })")),nn.set(e,n)}function Y(e,n,t,o,i){if(t==null){if(o==null)return null;let l=D(o,i);return l==null?null:(n&&n.parentNode?n.parentNode.insertBefore(l,n):e.appendChild(l),l)}if(o==null)return n?(U(t,O(i)),n.remove()):U(t,O(i)),null;let u=on(t),r=on(o);if(u!==r){U(t,O(i));let l=D(o,i);return l==null?null:(n?.parentNode&&n.parentNode.replaceChild(l,n),l)}if(r==="text")return n&&n.textContent!==String(o)&&(n.textContent=String(o)),n;let d=o,a=t;if(typeof d.type=="function"){let l=d.type;a._render&&a.type===d.type&&(d._render=a._render,d._id=a._id,d._id&&O(i).idRegistry.set(d._id,d)),d._parentNode=e,d._refNode=n;let f=Object.create(i);f.ui=Object.create(i.ui);let g=f.ui;if(g._selfId=d._id,g._selfVNode=d,d._ctxVersion=a._ctxVersion??g._ctxVersion??0,a._render&&a.type===d.type&&Ln(a.props,d.props)&&!g._dirtySet?.has(a._id)&&d._ctxVersion===g._ctxVersion)return d._child=a._child,n;g._dirtySet?.delete(a._id);let w;try{typeof d._render=="function"?w=d._render(d.props):w=Se(l,d.props,d,f)}catch(h){let b=i.ui?._errorHandler;b?(b(h),w=null):(console.error(`[weifuwu] Component render error in <${l?.name||"anonymous"}> (id: ${a._id??"?"}, phase: update)`,h),w=null)}let T=a._child;d._child=w;let m=Y(e,n,T,w,f);return m||(d._refNode=null),m}if(d.type===$){let l=a._childNodes,f=sn(e,a,d,i,l);return d._childNodes=f,n}if(typeof d.type=="string"){if(n&&n.nodeType===1){let l=a.props?.ref,f=d.props?.ref;l!==f&&(typeof f=="function"&&f(n),typeof l=="function"&&typeof f=="function"&&An(n)),Re(n,a.props,d.props),sn(n,a,d,i)}else if(n){U(t,O(i));let l=D(o,i);return l==null?null:(n.parentNode?.replaceChild(l,n),l)}return n}if(d.type===j)return se(a,d,i),null;if(Array.isArray(o)){let l=Array.isArray(t)?t:[];me(l,o);let f=Array.from(e.childNodes),g=n?f.indexOf(n):-1,w=g>=0?re(f.slice(g),l):re(f,l);return ye(e,l,o,i,w,n),n}return n}var tn=new Map;function In(e){let n=tn.get(e);return n||(n=`fn:${e.name||"anon"}`,tn.set(e,n)),n}function on(e){if(e==null||typeof e=="boolean")return"null";if(typeof e=="string"||typeof e=="number")return"text";if(Array.isArray(e))return"array";let n=e;return typeof n.type=="function"?In(n.type):n.type===$?"fragment":n.type===j?"portal":typeof n.type=="string"?"tag:"+n.type:"unknown"}function Re(e,n,t){let o=n?Object.keys(n).filter(r=>r!=="children"&&r!=="key"&&r!=="innerHTML"):[],i=t?Object.keys(t).filter(r=>r!=="children"&&r!=="key"&&r!=="innerHTML"):[],u=new Set(i);for(let r of o){if(!n)break;if(!u.has(r)){if(r==="ref")continue;r.startsWith("on")&&typeof n[r]=="function"?e.removeEventListener(r.slice(2).toLowerCase(),n[r]):r==="value"&&(e instanceof HTMLInputElement||e instanceof HTMLTextAreaElement||e instanceof HTMLSelectElement)?e.value="":e.removeAttribute(r==="className"?"class":r)}}for(let r of i){if(r==="ref")continue;let d=n?.[r],a=t?.[r];if(r==="innerHTML")a!==d&&(e.innerHTML=String(a??""));else if(a!==d)if(r==="class"||r==="className")e instanceof SVGElement?e.setAttribute("class",rn(a)):e.className=rn(a);else if(r==="style"&&typeof a=="object"&&a!==null){let l=e.style,f=a;for(let g of Object.keys(f)){let w=f[g];w==null?g.startsWith("--")?l.removeProperty(g):l[g]="":g.startsWith("--")?l.setProperty(g,String(w)):l[g]=typeof w=="number"?w+"px":String(w)}}else if(r.startsWith("on")&&typeof a=="function"){let l=r.slice(2).toLowerCase();typeof d=="function"&&e.removeEventListener(l,d),e.addEventListener(l,a)}else r==="draggable"?e.setAttribute("draggable",a?"true":"false"):r==="value"&&(e instanceof HTMLInputElement||e instanceof HTMLTextAreaElement||e instanceof HTMLSelectElement)?e.value=String(a??""):a===!0?e.setAttribute(r,""):a!=null&&a!==!1?e.setAttribute(r,String(a)):r==="value"&&(e instanceof HTMLInputElement||e instanceof HTMLTextAreaElement||e instanceof HTMLSelectElement)?e.value="":e.removeAttribute(r)}}function rn(e){return typeof e=="string"?e:Array.isArray(e)?e.filter(Boolean).join(" "):e&&typeof e=="object"?Object.entries(e).filter(([,n])=>n).map(([n])=>n).join(" "):""}function Ne(e){if(!(e==null||typeof e!="object"))return Array.isArray(e)?void 0:e.key}function me(e,n){if(!n.some(o=>o&&typeof o=="object"&&!Array.isArray(o)&&o.key!==void 0)){for(let o=0;o<n.length;o++){let i=n[o];i&&typeof i=="object"&&!Array.isArray(i)&&(i.key=String(o))}for(let o=0;o<e.length;o++){let i=e[o];i&&typeof i=="object"&&!Array.isArray(i)&&(i.key=String(o))}}}function re(e,n){let t=[],o=0;for(let i of n){if(i==null||typeof i=="boolean"){t.push(null);continue}let u=i;if(u.type===j){t.push(null);continue}if(u.type===$){let r=u._childNodes;Array.isArray(r)&&r.length>0?(t.push(r.slice()),o+=r.length):(t.push(e[o]?[e[o]]:null),o+=1)}else if(typeof u.type=="function")if(u._render){let r=u._childNodes??u._refNode;r==null?t.push(null):Array.isArray(r)?(t.push(r.slice()),o+=r.length):(t.push([r]),o+=1)}else t.push(e[o]?[e[o]]:null),o+=1;else typeof process<"u"&&process.env.DBG&&console.error("[map] idx=",o,"type=",u.type,"sourceLen=",e.length,"hit=",!!e[o]),t.push(e[o]?[e[o]]:null),o+=1}return t}function sn(e,n,t,o,i){let u=ie(n.props?.children),r=ie(t.props?.children);me(u,r);let d=i??Array.from(e.childNodes),a=re(d,u),l=ye(e,u,r,o,a,i?.[0]??null),f=[];for(let g of l)g&&g.length>0&&f.push(...g);return f}function ie(e){if(e==null)return[];if(!Array.isArray(e))return[e];let n=[];for(let t of e)Array.isArray(t)?n.push(...t):n.push(t);return n}function ln(e){return e==null?[]:e instanceof DocumentFragment?Array.from(e.childNodes):[e]}function ye(e,n,t,o,i=[],u=null){if(!t.some(m=>m&&typeof m=="object"&&!Array.isArray(m)&&m.key!==void 0&&m._placement!=="remote")){let m=Math.max(n.length,t.length);for(let h=0;h<m;h++){let b=h<n.length?n[h]:null,N=h<t.length?t[h]:null;if(N==null){if(b!=null){U(b,O(o));for(let s of i[h]??[])s.remove()}}else if(b==null){let s=D(N,o);if(s!=null){let c=null;for(let p=h+1;p<i.length;p++){let y=i[p]?.[0];if(y&&y.parentNode===e){c=y;break}}c?e.insertBefore(s,c):e.appendChild(s)}}else{let s=i[h]?.[0]??null;Y(e,s,b,N,o)}}return[]}for(let m=0;m<n.length;m++){let h=n[m];if(!(h==null||typeof h=="boolean")&&Ne(h)===void 0)for(let b of i[m]??[])b.remove()}let d=new Map,a=0;for(let m=0;m<n.length;m++){let h=Ne(n[m]);h!==void 0&&d.set(h,{vnode:n[m],nodes:i[m]??[],index:a++})}let l=t.map(m=>Ne(m)),f=new Set(l);for(let m of[...d.keys()])if(!f.has(m)){let h=d.get(m);U(h.vnode,O(o));for(let b of h.nodes)b?.remove();d.delete(m)}let g=new Array(t.length).fill(null),w=-1,T=u&&u.parentNode===e?u:e.firstChild;for(let m=0;m<t.length;m++){let h=l[m],b=t[m],N=h!==void 0?d.get(h):void 0,s=b&&typeof b=="object"&&b._placement==="remote";if(N)if(N.nodes.length>0){if(N.index<w)for(let p of N.nodes)e.insertBefore(p,T);w=Math.max(w,N.index),Y(e,N.nodes[0],N.vnode,b,o),g[m]=b._childNodes??N.nodes.filter(p=>p.parentNode===e),T=g[m][g[m].length-1]?.nextSibling??null}else if(s)se(N.vnode,b,o),g[m]=[];else{let c=Y(e,null,N.vnode,b,o);g[m]=ln(c);for(let y of g[m])e.insertBefore(y,T);T=g[m][g[m].length-1]?.nextSibling??null}else if(s)X(b,o),g[m]=[];else{let c=D(b,o);g[m]=ln(c);for(let y of g[m])e.insertBefore(y,T);T=g[m][g[m].length-1]?.nextSibling??null}}return g}function Vn(e,n){if(e===n)return!0;if(Array.isArray(e)&&Array.isArray(n)){if(e.length!==n.length)return!1;for(let t=0;t<e.length;t++)if(e[t]!==n[t])return!1;return!0}return e===n}function Ln(e,n){if(e===n)return!0;if(!e||!n)return!1;let t=new Set([...Object.keys(e),...Object.keys(n)]);for(let o of t)if(o!=="key"){if(o==="children"){if(!Vn(e[o],n[o]))return!1}else if(e[o]!==n[o])return!1}return!0}var Me="http://www.w3.org/2000/svg",Ae=new Set(["svg","path","circle","line","rect","text","g","polyline","polygon","ellipse","defs","use","clipPath","mask","linearGradient","radialGradient","stop","tspan"]);function D(e,n){if(e==null||typeof e=="boolean")return null;if(typeof e=="string"||typeof e=="number")return document.createTextNode(String(e));if(Array.isArray(e))return Hn(e,n);let t=e;if(t.type===j)return X(t,n),null;if(t.type===$){let r=document.createDocumentFragment(),d=t.props?.children==null?[]:Array.isArray(t.props.children)?t.props.children:[t.props.children];for(let a of d){let l=D(a,n);l!=null&&r.appendChild(l)}return t._childNodes=Array.from(r.childNodes),r}if(typeof t.type=="function")return On(t.type,t.props,t,n);let o=t.type,i=Ae.has(o)?document.createElementNS(Me,o):document.createElement(o);t.el=i;let u;for(let[r,d]of Object.entries(t.props??{}))r==="children"||r==="key"||r==="value"||r==="innerHTML"||an(i,r,d);if("value"in(t.props??{})&&i instanceof HTMLSelectElement?u=t.props.value:"value"in(t.props??{})&&an(i,"value",t.props.value),"innerHTML"in(t.props??{}))i.innerHTML=String(t.props.innerHTML??"");else{let r=Ie(t.props?.children);for(let d of r){let a=D(d,n);if(a!=null&&(i.appendChild(a),d&&typeof d=="object"&&typeof d.type=="function")){let l=d;l._parentNode||(l._parentNode=i,l._refNode=a)}}}return u!==void 0&&(i.value=String(u)),typeof t.props?.ref=="function"&&xe(t.props.ref,i,"mount",o),i}function Un(e){let n=e.ui;n&&typeof n.render=="function"&&n.render(["_wf_root"])}function Se(e,n,t,o){let i;if(z(e)){if(i=De(O(o),e),!i)return Te(O(o),e,o).promise.then(()=>Un(o),()=>{}),null}else i=e;o.ui?.setMounting?.(!0);let u;try{u=i(n,o)}finally{o.ui?.endMounting?.()}if(typeof u!="function")throw new Error(`Component ${e.name||"anonymous"} must return a render function. Use (init_props, ctx) => (props) => VNode pattern.`);return t._render=u,u(n)}function On(e,n,t,o){if(!t._id){let a=O(o);t._id=ae(a),a.idRegistry.set(t._id,t)}let i=Object.create(o);i.ui=Object.create(o.ui);let u=i.ui;u._selfId=t._id,u._selfVNode=t,t._ctxVersion=u._ctxVersion??0;let r;try{r=Se(e,n,t,i)}catch(a){let l=o.ui?._errorHandler;l?(l(a),r=null):(console.error(`[weifuwu] Component render error in <${e.name||"anonymous"}> (id: ${t._id??"?"}, phase: mount)`,a),r=null)}if(r==null){if(t._child=null,i.ui?._errorHandler){let l=document.createComment("wf-empty");return t._refNode=l,l}return null}t._child=r;let d=D(r,i);return t._refNode||(t._refNode=d),d}function Hn(e,n){let t=document.createDocumentFragment();for(let o of e){let i=D(o,n);i!=null&&t.appendChild(i)}return t}function Wn(){let e=document.getElementById("__wf_portal");return e||(e=document.createElement("div"),e.id="__wf_portal",e.style.cssText="position:fixed;inset:0;pointer-events:none;z-index:9999",document.body.appendChild(e)),e}function X(e,n){let t=Wn(),o=document.createElement("div");o.style.pointerEvents="auto",t.appendChild(o),e._remoteEl=o;let i=ie(e.props?.children);e._child=i;for(let u of i){let r=D(u,n);r!=null&&o.appendChild(r)}}function se(e,n,t){let o=e?._remoteEl;if(n._remoteEl=o,!o){X(n,t);return}let i=ie(n.props?.children),u=e._child||[];n._child=i,me(u,i);let r=re(Array.from(o.childNodes),u);ye(o,u,i,t,r,r[0]?.[0]??null)}function Ie(e){if(e==null)return[];if(!Array.isArray(e))return[e];let n=[];for(let t of e)Array.isArray(t)?n.push(...t):n.push(t);return n}function an(e,n,t){if(n!=="ref")if(n==="class"||n==="className")e instanceof SVGElement?e.setAttribute("class",String(t??"")):e.className=String(t??"");else if(n==="style"&&typeof t=="object"&&t!==null){let o=e.style;for(let i of Object.keys(t)){let u=t[i];u!=null&&(i.startsWith("--")?o.setProperty(i,String(u)):o[i]=typeof u=="number"?u+"px":String(u))}}else n.startsWith("on")&&typeof t=="function"?e.addEventListener(n.slice(2).toLowerCase(),t):n==="draggable"?e.setAttribute("draggable",t?"true":"false"):n==="value"&&(e instanceof HTMLInputElement||e instanceof HTMLTextAreaElement||e instanceof HTMLSelectElement)?e.value=String(t??""):t===!0?e.setAttribute(n,""):t!=null&&t!==!1&&e.setAttribute(n,String(t))}function Dn(e,n,t){e.innerHTML="";let o=D(n,t);o instanceof Node&&e.appendChild(o)}function jn(e){U(e,ee())}function Ve(e){e.node=e.node?e.node.nextSibling:null}function qn(e,n){e.node&&e.node.parentNode?e.node.parentNode.insertBefore(n,e.node):e.parent.appendChild(n)}function $n(e,n){e.node&&e.node.parentNode?(e.node.parentNode.replaceChild(n,e.node),Ve(e)):e.parent.appendChild(n)}async function le(e,n,t){if(e==null||typeof e=="boolean")return null;if(typeof e=="string"||typeof e=="number"){let d=String(e);if(t.node&&t.node.nodeType===3)return t.node.textContent!==d&&(t.node.textContent=d),Ve(t),t.node;let a=document.createTextNode(d);return qn(t,a),a}if(Array.isArray(e)){let d=null;for(let a of e){let l=await le(a,n,t);l!=null&&!d&&(d=l)}return d}let o=e;if(o.type===j||o.type===$){let d=o.props?.children,a=d==null?[]:Array.isArray(d)?d:[d],l=null;for(let f of a){let g=await le(f,n,t);g!=null&&!l&&(l=g)}return l}if(typeof o.type=="function")return Fn(o,n,t);let i=o.type,u=o.props??{},r;if(t.node&&t.node.nodeType===1&&t.node.tagName.toLowerCase()===i.toLowerCase()?(r=t.node,Ve(t)):(r=Ae.has(i)?document.createElementNS(Me,i):document.createElement(i),$n(t,r)),o.el=r,Re(r,null,u),!("innerHTML"in u)){let d={parent:r,node:r.firstChild},a=Ie(u.children);for(let l of a){let f=await le(l,n,d);if(f!=null&&f.parentNode!==r&&r.appendChild(f),l&&typeof l=="object"&&typeof l.type=="function"){let g=l;g._parentNode||(g._parentNode=r,g._refNode=f)}}for(;d.node;){let l=d.node;d.node=l.nextSibling,l.parentNode?.removeChild(l)}}return"value"in u&&r instanceof HTMLSelectElement&&(r.value=String(u.value??"")),typeof u.ref=="function"&&u.ref(r),r}async function Fn(e,n,t){if(!e._id){let a=O(n);e._id=ae(a),a.idRegistry.set(e._id,e)}let o=Object.create(n);o.ui=Object.create(n.ui);let i=o.ui;i._selfId=e._id,i._selfVNode=e,e._ctxVersion=i._ctxVersion??0;let u=e.type,r;try{let a;z(u)?a=await We(O(n),u,o):a=u;let l=a(e.props??{},o);if(typeof l!="function")throw new Error(`Component ${u.name||"anonymous"} must return a render function. Use (init_props, ctx) => (props) => VNode pattern.`);e._render=l,r=l(e.props??{})}catch(a){let l=n.ui?._errorHandler;l?(l(a),r=null):(console.error(`[weifuwu] Component hydration error in <${u.name||"anonymous"}> (id: ${e._id??"?"})`,a),r=null)}if(r==null)return e._child=null,null;e._child=r;let d=await le(r,o,t);return e._refNode||(e._refNode=d),d}async function Le(e,n,t){let o={parent:e,node:e.firstChild};for(await le(n,t,o);o.node;){let i=o.node;o.node=i.nextSibling,i.parentNode?.removeChild(i)}}function Ue(){return{activeElement:()=>typeof document<"u"?document.activeElement:null,byId:e=>typeof document<"u"?document.getElementById(e):null,query:e=>typeof document<"u"?document.querySelector(e):null,createElement:e=>typeof document<"u"?document.createElement(e):null,bodyAppend:e=>{typeof document<"u"&&document.body.appendChild(e)},bodyRemove:e=>{typeof document<"u"&&e.parentNode&&document.body.removeChild(e)},copyText:async e=>{let n=typeof window<"u"?window:null;if(n?.navigator?.clipboard?.writeText)try{return await n.navigator.clipboard.writeText(e),!0}catch{}try{if(typeof document>"u")return!1;let t=document.createElement("textarea");t.value=e,t.style.position="fixed",t.style.opacity="0",document.body.appendChild(t),t.select();let o=document.execCommand("copy");return document.body.removeChild(t),o}catch{return!1}},execCommand:(e,n)=>typeof document<"u"?document.execCommand(e,!1,n):!1,queryCommandState:e=>typeof document<"u"?document.queryCommandState(e):!1,queryCommandValue:e=>typeof document<"u"?document.queryCommandValue(e):"",selectionText:()=>typeof window<"u"?window.getSelection?.()?.toString()??null:null,getSelection:()=>typeof window<"u"?window.getSelection():null,viewportHeight:()=>typeof window<"u"?window.innerHeight:0,scrollTop:()=>{let e=typeof document<"u"?document:null,n=typeof window<"u"?window:null;return e?.scrollingElement?.scrollTop??n?.scrollY??0},hash:()=>typeof window<"u"?window.location?.hash??"":"",setHash:e=>{typeof window<"u"&&(window.location.hash=e)},timeout:(e,n)=>typeof window<"u"?window.setTimeout(e,n):0,rootElement:()=>typeof document<"u"?document.documentElement:null,storageGet:e=>{try{return typeof window<"u"?window.localStorage?.getItem(e)??null:null}catch{return null}},storageSet:(e,n)=>{try{typeof window<"u"&&window.localStorage?.setItem(e,n)}catch{}}}}function Kn(e,n){let t=typeof n.root=="string"?document.querySelector(n.root):n.root;if(!t)throw new Error(`uiServe: root not found: ${n.root}`);let o=t,i=!!n.hydrate;i||(o.innerHTML="");let u=ee(),r=new Set,d=new Set,a=new Map,l=!1,f=!1,g=[];function w(E){g.push(f),f=E}function T(){f=g.pop()??!1}let m={params:{},query:{}},h=new Map,b=globalThis.__DATA__??window.__DATA__;if(b&&typeof b=="object")for(let[E,S]of Object.entries(b))h.set(E,{value:S});m.data={async get(E,S){let k=h.get(E);if(k&&"value"in k)return k.value;if(k?.promise)return k.promise;if(!S)return;let R=Promise.resolve().then(()=>S()).then(I=>(h.set(E,{value:I}),I));return h.set(E,{promise:R}),R},set(E,S){h.set(E,{value:S})},has(E){return h.has(E)}};let N=!1;function s(){r.size>0&&!N&&(N=!0,queueMicrotask(()=>{N=!1;let E=[...r];r.clear(),E.length>0&&c(E)}))}function c(E){if(!l){l=!0;for(let S of E){let k=u.idRegistry.get(S);if(!k||!k._render)continue;m.ui._dirtySet?.delete(S);let R=k._child,I=k._render(k.props);if(k._child=I,R&&R._placement==="remote"||I&&I._placement==="remote"){R&&I?se(R,I,m):I?X(I,m):R&&U(R,u);continue}if(!k._parentNode&&k._refNode){let H=k._refNode.parentNode;H&&(k._parentNode=H)}if(k._parentNode){let H=Y(k._parentNode,k._refNode??null,R,I,m);H&&H!==k._refNode?k._refNode=H:H||(k._refNode=null)}}l=!1,s()}}let p=null;function y(){return p||(p=qe(E=>m.ui.render(E))),p}m.browser=Ue(),m.__registry=u,m.ui=en({ctx:m,renderByIds:c,getSelfId:E=>E?._selfId??m.ui?._selfId,dirtyBatch:r,dirtySet:d,mediaRegistry:a,popupTrackers:y().popupTrackers,scrollTrackers:y().scrollTrackers,schedulePopupRecompute:y().schedulePopupRecompute,ensurePopupListeners:y().ensurePopupListeners,destroyPopupListeners:y().destroyPopupListeners,isRendering:()=>l,isMounting:()=>f,setMounting:w,endMounting:T,registry:u}),ue(u,E=>{for(let S of[...a.keys()])if(S.startsWith(`media:${E}:`)||S===`bp:${E}`){let k=a.get(S);k?.mql&&k.handler&&k.mql.removeEventListener("change",k.handler),k?.mqls?.forEach(({mql:R,handler:I})=>R.removeEventListener("change",I)),a.delete(S)}y().cleanupTrackers(E)}),m.__rerender=()=>x(),m.app={navigate:E=>{e.mode==="hash"?window.location.hash="#"+E:window.history.pushState({},"",E),x()}};let v=null,C=!1,P=!1;function x(){P||(P=!0,queueMicrotask(()=>{P=!1,M()}))}async function M(){if(!C){C=!0;try{let E=e.getPath();if(m.route={path:E,params:m.params,query:m.query},!m.__state){let k=G(()=>{C||x()});m.__state=k;let R=m.ui.$;m.ui.$=function(){return this&&this._selfVNode?R.call(this):k}}let S=await e.execute(window.location,m,E);if(v==null){if(S){let k=i&&o.firstElementChild?(Le(o,S,m),o.firstChild):D(S,m);k&&k.parentNode!==o&&o.appendChild(k)}}else Y(o,o.firstChild,v,S,m);v=S}catch(E){if(console.error("[ui-dom] render error:",E),v==null){let S=document.createElement("div");S.className="ui-dom-error",S.textContent=`\u6E32\u67D3\u9519\u8BEF: ${E?.message??String(E)}`,o.appendChild(S)}}finally{C=!1}}}let V=()=>x();window.addEventListener("popstate",V);let L=()=>x();return e.mode==="hash"&&window.addEventListener("hashchange",L),x(),{get ctx(){return m},close(){window.removeEventListener("popstate",V),e.mode==="hash"&&window.removeEventListener("hashchange",L),v&&U(v,u),y().destroy(),u.idRegistry.clear(),o.innerHTML="",v=null}}}function Bn(e,n,t=400){let o=!1,i=()=>{o||(o=!0,e.removeEventListener("animationend",i),clearTimeout(u),n())};e.addEventListener("animationend",i);let u=setTimeout(i,t)}function Q(e,n){return Object.assign(Object.create(e),n)}function Gn(e){let n={baseURL:e?.baseURL??"",headers:{"Content-Type":"application/json",...e?.headers}},t=e?.onRequest,o=e?.onResponse,i=e?.timeout??0;async function u(r,d,a,l){let f=n.baseURL+d,g={method:r,headers:{...n.headers,...l?.headers}},w=e?.token?.();w&&!g.headers.Authorization&&(g.headers.Authorization=`Bearer ${w}`);let T=i>0,m=!!l?.signal,h=null,b=null;(T||m)&&(h=new AbortController,g.signal=h.signal,T&&(b=setTimeout(()=>h.abort(new Error("Request timed out")),i)),m&&l.signal.addEventListener("abort",()=>h.abort())),a!==void 0&&r!=="GET"&&r!=="HEAD"&&(g.body=JSON.stringify(a));let N={url:f,init:g};t&&(N=t(N));try{let s=await fetch(N.url,N.init);if(o)return o(s);if(!s.ok){let y=await s.text().catch(()=>"");throw new Oe(s.status,y||s.statusText)}let c=s.headers.get("content-length");if(s.status===204||c==="0")return;let p=(s.headers.get("content-type")||"").toLowerCase();return p.includes("application/json")||p.includes("json")?s.json():s.text()}finally{b&&clearTimeout(b)}}return r=>Q(r,{api:{get:(a,l)=>u("GET",a,void 0,l),post:(a,l,f)=>u("POST",a,l,f),put:(a,l,f)=>u("PUT",a,l,f),patch:(a,l,f)=>u("PATCH",a,l,f),delete:(a,l)=>u("DELETE",a,void 0,l)}})}var Oe=class extends Error{status;body;constructor(n,t){super(`API Error ${n}: ${t}`),this.name="ApiError",this.status=n,this.body=t}};function Yn(e){try{let n=e.split(".");if(n.length!==3)return null;let t=n[1].replace(/-/g,"+").replace(/_/g,"/");return JSON.parse(atob(t))}catch{return null}}function zn(e){let n=Yn(e);return n?.exp?n.exp*1e3-3e4<Date.now():!0}function Jn(e){let n=e?.storage??localStorage,t=e?.tokenKey??"weifuwu_token",o=e?.userKey??"weifuwu_user",i=e?.refreshTokenKey??"weifuwu_refresh",u=e?.refreshEndpoint??"/api/auth/refresh";return r=>{let d=n.getItem(t),a=n.getItem(o),l={token:d,user:a?JSON.parse(a):null,get isLoggedIn(){return this.token!==null},login(f,g,w){l.token=f,l.user=g,n.setItem(t,f),n.setItem(o,JSON.stringify(g)),w&&n.setItem(i,w)},logout(){l.token=null,l.user=null,n.removeItem(t),n.removeItem(o),n.removeItem(i)},setUser(f){l.user=f,n.setItem(o,JSON.stringify(f))},async refresh(){let f=n.getItem(i);if(!f)return!1;try{let g=await fetch(u,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({refreshToken:f})});if(!g.ok)return l.logout(),!1;let w=await g.json();return l.token=w.token,n.setItem(t,w.token),w.refreshToken&&n.setItem(i,w.refreshToken),!0}catch{return!1}}};return d&&zn(d)&&l.refresh().catch(()=>{}),Q(r,{auth:l})}}function Xn(e={}){let n=e.url??"/ws",t=e.reconnectInterval??3e3,o=e.maxReconnect??10,i=e.pingInterval??3e4,u=e.pingTimeout??1e4;return r=>{let d=new Set,a=null,l=0,f=null,g=null,w=null,T=!1,m={isConnected:!1,onMessage:c=>(d.add(c),()=>{d.delete(c)}),send:c=>{a?.readyState===WebSocket.OPEN&&a.send(JSON.stringify(c))},_connect:h,close:()=>{T=!0,s(),a?.close(),a=null,m.isConnected=!1}};async function h(){if(!T)try{a=new WebSocket(n),a.onopen=()=>{m.isConnected=!0,l=0,b()},a.onmessage=c=>{try{let p=JSON.parse(c.data);for(let y of d)y(p)}catch{}N()},a.onclose=()=>{m.isConnected=!1,s(),!T&&l<o&&(l++,f=setTimeout(h,t*Math.min(l,5)))},a.onerror=()=>{a?.close()}}catch{T||(f=setTimeout(h,t))}}function b(){i<=0||(g=setInterval(()=>{a?.readyState===WebSocket.OPEN&&a.send(JSON.stringify({type:"ping"})),w=setTimeout(()=>{a?.close()},u)},i))}function N(){clearTimeout(w)}function s(){clearInterval(g),clearTimeout(w),clearTimeout(f)}return h(),Q(r,{ws:m})}}function ge(e){return e.replace(/&/g,"&").replace(/</g,"<").replace(/>/g,">").replace(/"/g,""")}var Qn=new Set(["area","base","br","col","embed","hr","img","input","link","meta","param","source","track","wbr"]);function Zn(e){return typeof e=="string"?e:Array.isArray(e)?e.filter(Boolean).join(" "):e&&typeof e=="object"?Object.entries(e).filter(([,n])=>n).map(([n])=>n).join(" "):""}function et(e){return typeof e=="string"?e:e&&typeof e=="object"?Object.entries(e).filter(([,n])=>n!=null).map(([n,t])=>`${n}:${typeof t=="number"?t+"px":String(t)}`).join(";"):""}function un(e,n){let t=new Set,o={$:()=>G(()=>{}),dirty:()=>{},render:()=>{},selfId:r=>{if(t.has(r))throw new Error(`[weifuwu] Duplicate component ID: "${r}"`);t.add(r)},useMedia:()=>{},useBreakpoint:()=>{},usePopupPosition:()=>({top:0,left:0,refresh:()=>{}}),useHoverCapable:()=>!1,useVisualViewport:()=>({height:0,offsetTop:0,keyboardOpen:!1}),useLongPress:()=>({}),useInView:()=>({isIn:!1,ready:!1,observe:()=>{},refresh:()=>{},disconnect:()=>{}}),useScrollPosition:()=>({y:0,refresh:()=>{}}),useStableRef:r=>d=>{d&&r?.(d)},useGlobalKey:()=>()=>{},useReducedMotion:()=>!1,useAnimationEnd:()=>()=>{},useTween:r=>{let d={value:r,reset:a=>{d.value=a}};return d},useDrag:()=>({onPointerDown:()=>{}}),useDragDrop:()=>({dropProps:{},dragProps:{}}),useControlled:r=>({value:r.value,setValue:d=>{r.onChange?.(d)},controlled:r.value!==void 0}),useControlledInput:r=>({value:r.value,setValue:d=>{r.onChange?.(d)},controlled:r.value!==void 0,keyword:"",setKeyword:()=>{},selectedLabel:"",setSelectedLabel:()=>{}}),useOpen:r=>({get open(){return!!r.open},setOpen:d=>{r.onOpenChange?.(d)},triggerProps:{}}),useAsync:()=>({data:void 0,loading:!0,error:void 0,reload:()=>{}}),usePopup:()=>({open:!1,setOpen:()=>{},wrapProps:{},portal:()=>null,refresh:()=>{}}),usePresence:()=>({phase:"closed",ref:()=>{},sync:r=>r?"open":"closed"}),useDialog:()=>({phase:"closed",rootRef:()=>{},panelRef:()=>{},sync:r=>r?"open":"closed"}),useChat:()=>({messages:[],input:"",streaming:!1,error:null,usage:null,step:null,send:()=>{},stop:()=>{},retry:()=>{},clear:()=>{},approve:async()=>{},dispose:()=>{}})},i={activeElement:()=>null,byId:()=>null,query:()=>null,createElement:()=>null,bodyAppend:()=>{},bodyRemove:()=>{},copyText:async()=>!1,execCommand:()=>!1,selectionText:()=>null,getSelection:()=>null,queryCommandState:()=>!1,queryCommandValue:()=>"",viewportHeight:()=>0,scrollTop:()=>0,hash:()=>"",setHash:()=>{},timeout:()=>0,rootElement:()=>null,storageGet:()=>null,storageSet:()=>{}},u=Object.create(e??{});return u.ui=o,u.browser=i,u.data={async get(r,d){if(n.has(r))return n.get(r);if(!d)return;let a=await d();return n.set(r,a),a},set(r,d){n.set(r,d)},has(r){return n.has(r)}},u}async function J(e,n){if(e==null||typeof e=="boolean")return"";if(typeof e=="string"||typeof e=="number")return ge(String(e));if(Array.isArray(e)){let l="";for(let f of e)l+=await J(f,n);return l}let t=e;if(t.type===j||t.type===$)return J(t.props?.children,n);if(typeof t.type=="function"){let l;if(z(t.type)){if(l=await t.type(n),typeof l!="function")throw new Error(`asyncComponent factory <${t.type.name||"anonymous"}> must return a Component (initProps, ctx) => (props) => VNode.`)}else l=t.type;let f=Object.create(n),g=l(t.props??{},f);if(typeof g!="function")throw new Error(`Component ${t.type.name||"anonymous"} must return a render function. Use (init_props, ctx) => (props) => VNode pattern.`);return J(g(t.props??{}),f)}let o=t.type,i=t.props??{},u=[],r;for(let[l,f]of Object.entries(i))if(!(l==="children"||l==="key")&&l!=="ref"&&!(l.startsWith("on")&&typeof f=="function")){if(l==="innerHTML"){r=String(f??"");continue}if(l==="class"||l==="className"){let g=Zn(f);g&&u.push(` class="${ge(g)}"`);continue}if(l==="style"&&f&&typeof f=="object"){u.push(` style="${ge(et(f))}"`);continue}if(f===!0){u.push(` ${l}`);continue}f===!1||f==null||u.push(` ${l}="${ge(String(f))}"`)}let d=u.join("");if(Qn.has(o))return`<${o}${d}>`;if(r!==void 0)return`<${o}${d}>${r}</${o}>`;let a=await J(i.children,n);return`<${o}${d}>${a}</${o}>`}async function nt(e,n,t,o={}){let i=o.data??new Map,u=un(t,i);return await J({type:e,props:n??{},key:void 0},u)}function dn(e){return`<script>window.__DATA__=${JSON.stringify(Object.fromEntries(e)).replace(/</g,"\\u003c")};<\/script>`}async function tt(e,n){let t=new Map,i=un({params:{},query:{}},t),u=n.url.split("?")[0].split("#")[0],r=e.match(u);i.params=r.params,i.query=Object.fromEntries(new URLSearchParams(n.url.split("?")[1]??""));let d=new URL(n.url.startsWith("http")?n.url:`http://localhost${n.url.startsWith("/")?n.url:"/"+n.url}`),a=await e.execute(d,i,u),l=await J(a,i),f=dn(t),g=r.title??n.title??"",w=n.rootId??"root",T=`<!DOCTYPE html>
|
|
7
|
+
<html lang="${n.lang??"zh-CN"}">
|
|
8
|
+
<head>
|
|
9
|
+
<meta charset="UTF-8">
|
|
10
|
+
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
11
|
+
${g?`<title>${g}</title>`:""}
|
|
12
|
+
</head>
|
|
13
|
+
<body>
|
|
14
|
+
<div id="${w}">${l}</div>
|
|
15
|
+
${f}
|
|
16
|
+
<script src="/app.js"><\/script>
|
|
17
|
+
</body>
|
|
18
|
+
</html>`;return{html:l,dataScript:f,page:T}}export{$ as Fragment,j as Portal,Ce as UIRouter,Bn as animateOut,Gn as api,Nn as asyncComponent,Jn as auth,jn as callRefCleanup,Ue as createClientBrowser,ke as createPortal,G as createReactiveState,Mn as h,Le as hydrateVNode,z as isAsyncComponent,_e as jsx,Sn as jsxDEV,Rn as jsxs,Dn as mountVNode,Y as patchValue,dn as serializeData,tt as ssrPage,nt as ssrToString,Kn as uiServe,Xn as ws};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
var r=Symbol("Fragment");function o(e,t,n){return{type:e,props:i(t),key:n??void 0}}var s=o;function p(e,t,n){return o(e,t,n)}function i(e){if(!e)return{};let t={};for(let n of Object.keys(e))n!=="key"&&(t[n]=e[n]);return t}export{r as Fragment,o as jsx,p as jsxDEV,s as jsxs};
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* weifuwu/ui-dom 弹层/滚动位置跟踪系统(实例化——serve 每实例一个)
|
|
3
|
+
*
|
|
4
|
+
* 复制自 client/app.ts 闭包逻辑(createUi 依赖):scroll/resize 时重算弹层
|
|
5
|
+
* fixed 坐标(rAF 节流)+ 滚动位置跟踪。createApp 与 uiServe 各自持有实例。
|
|
6
|
+
*/
|
|
7
|
+
import type { PopupPosition } from './types.ts';
|
|
8
|
+
export interface PopupTrackerEntry {
|
|
9
|
+
pos: PopupPosition;
|
|
10
|
+
getEl: () => HTMLElement | null;
|
|
11
|
+
isOpen: () => boolean;
|
|
12
|
+
compute: (rect: DOMRect) => {
|
|
13
|
+
top: number;
|
|
14
|
+
left: number;
|
|
15
|
+
width?: number;
|
|
16
|
+
};
|
|
17
|
+
panel?: () => HTMLElement | null;
|
|
18
|
+
margin: number;
|
|
19
|
+
}
|
|
20
|
+
export interface ScrollTrackerEntry {
|
|
21
|
+
handle: {
|
|
22
|
+
y: number;
|
|
23
|
+
};
|
|
24
|
+
getScroller: () => HTMLElement | Window;
|
|
25
|
+
}
|
|
26
|
+
export interface PopupTrackerSystem {
|
|
27
|
+
popupTrackers: Map<string, PopupTrackerEntry>;
|
|
28
|
+
scrollTrackers: Map<string, ScrollTrackerEntry>;
|
|
29
|
+
schedulePopupRecompute: () => void;
|
|
30
|
+
ensurePopupListeners: () => void;
|
|
31
|
+
destroyPopupListeners: () => void;
|
|
32
|
+
cleanupTrackers: (id: string) => void;
|
|
33
|
+
destroy: () => void;
|
|
34
|
+
}
|
|
35
|
+
/** 创建跟踪系统实例(renderByIds 用于滚动/resize 后精准刷新目标组件) */
|
|
36
|
+
export declare function createPopupTrackerSystem(renderByIds: (ids: string[]) => void): PopupTrackerSystem;
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* weifuwu/ui-dom 注册表 — 工厂版(serve 创建局部实例,隔离于 createApp 的模块级状态)
|
|
3
|
+
*
|
|
4
|
+
* 复制自 client/registry.ts(算法相同),但**无模块级单例**——uiServe 创建实例
|
|
5
|
+
* 注入 ctx.__registry,render/diff/ui 经 getRegistry(ctx) 读取,与 createApp 零交叉。
|
|
6
|
+
*/
|
|
7
|
+
import type { VNode, Component, AsyncComponent } from './vnode.ts';
|
|
8
|
+
import type { WfuiContext } from './types.ts';
|
|
9
|
+
type UnmountHook = (id: string) => void;
|
|
10
|
+
interface FactoryEntry {
|
|
11
|
+
promise: Promise<Component<any, any>>;
|
|
12
|
+
resolved?: Component<any, any>;
|
|
13
|
+
}
|
|
14
|
+
/** 注册表实例状态 */
|
|
15
|
+
export interface Registry {
|
|
16
|
+
idCounter: number;
|
|
17
|
+
idRegistry: Map<string, VNode>;
|
|
18
|
+
unmountHooks: UnmountHook[];
|
|
19
|
+
asyncFactoryCache: WeakMap<AsyncComponent<any, any>, FactoryEntry>;
|
|
20
|
+
}
|
|
21
|
+
/** 创建局部注册表(uiServe 每实例一个——组件 id/dirty/卸载钩子与 createApp 隔离) */
|
|
22
|
+
export declare function createRegistry(): Registry;
|
|
23
|
+
/** 从 ctx 取注入的注册表(render/diff/ui 统一入口;serve 注入 __registry) */
|
|
24
|
+
export declare function getRegistry(ctx: any): Registry;
|
|
25
|
+
/** 指定实例生成组件 ID */
|
|
26
|
+
export declare function nextComponentIdFor(reg: Registry): string;
|
|
27
|
+
/** 指定实例注册卸载钩子(组件从 idRegistry 注销时触发) */
|
|
28
|
+
export declare function onComponentUnmountFor(reg: Registry, hook: UnmountHook): () => void;
|
|
29
|
+
/** 启动 async 工厂(幂等,缓存) */
|
|
30
|
+
export declare function startAsyncFactory(reg: Registry, Comp: AsyncComponent, ctx: WfuiContext): FactoryEntry;
|
|
31
|
+
/** async 模式:await 工厂定义 */
|
|
32
|
+
export declare function resolveAsyncFactory(reg: Registry, Comp: AsyncComponent, ctx: WfuiContext): Promise<Component>;
|
|
33
|
+
/** sync 模式:工厂已解析 → 定义;未解析 → undefined */
|
|
34
|
+
export declare function resolveAsyncFactorySync(reg: Registry, Comp: AsyncComponent): Component | undefined;
|
|
35
|
+
/** 包裹 ref 回调调用——用户 ref 逻辑抛错时不中断渲染/卸载管线 */
|
|
36
|
+
export declare function safeCallRef(ref: Function, arg: any, phase: 'mount' | 'cleanup', name?: string): void;
|
|
37
|
+
/** 通知 ref 清理 + Portal 子容器清理(指定实例) */
|
|
38
|
+
export declare function callRefCleanupFor(input: any, reg: Registry): void;
|
|
39
|
+
export {};
|
|
@@ -10,25 +10,33 @@
|
|
|
10
10
|
*
|
|
11
11
|
* 状态管理:组件使用闭包变量 + ctx.ui.render() 手动触发重渲染。
|
|
12
12
|
*/
|
|
13
|
-
import type { VNode, Component, AsyncComponent } from './vnode.ts';
|
|
13
|
+
import type { VNode, VNodeChild, Component, AsyncComponent } from './vnode.ts';
|
|
14
14
|
import type { WfuiContext } from './types.ts';
|
|
15
15
|
export declare const SVG_NS = "http://www.w3.org/2000/svg";
|
|
16
16
|
export declare const SVG_TAGS: Set<string>;
|
|
17
|
-
export declare function render(input:
|
|
18
|
-
export declare function renderValue(v:
|
|
17
|
+
export declare function render(input: VNodeChild, ctx: WfuiContext): Node | null;
|
|
18
|
+
export declare function renderValue(v: VNodeChild, ctx: WfuiContext): Node | null;
|
|
19
|
+
/**
|
|
20
|
+
* 异步组件工厂缓存:同一工厂只执行一次,多实例/多渲染共享。
|
|
21
|
+
* resolved 记录已解析的定义(同步快速路径用)。
|
|
22
|
+
* (缓存本体在 registry.ts,本文件仅保留依赖 render 的调度函数)
|
|
23
|
+
*/
|
|
24
|
+
/** 占位完成后整树重渲染(async 工厂已解析,diff 收敛到目标位置) */
|
|
25
|
+
export declare function scheduleFullReRender(ctx: WfuiContext): void;
|
|
19
26
|
/**
|
|
20
27
|
* 同步 mount 组件(async 工厂占位策略):
|
|
21
28
|
* - 同步组件 → def(props, ctx) → render fn → 输出 VNode
|
|
22
29
|
* - async 工厂已解析 → 同同步组件
|
|
23
30
|
* - async 工厂未解析 → 占位(返回 null)+ 启动工厂 + 完成后整树重渲染
|
|
24
31
|
*/
|
|
25
|
-
export declare function mountComponent(Comp: Component | AsyncComponent, props:
|
|
32
|
+
export declare function mountComponent(Comp: Component | AsyncComponent, props: VNode['props'], vnode: VNode, ctx: WfuiContext): VNode | null;
|
|
26
33
|
/** 首次渲染 Portal:创建远程容器、渲染子节点(不返回占位节点) */
|
|
27
34
|
export declare function renderPortal(vnode: VNode, ctx: WfuiContext): void;
|
|
28
35
|
/** 更新 Portal:复用远程容器,patch 子节点(不操作父 DOM) */
|
|
29
36
|
export declare function patchPortal(oldV: VNode | null, newV: VNode, ctx: WfuiContext): void;
|
|
30
37
|
/** 展平嵌套数组 */
|
|
31
|
-
export declare function flattenChildren(children:
|
|
38
|
+
export declare function flattenChildren(children: VNodeChild): VNodeChild[];
|
|
32
39
|
export declare function mountVNode(container: Element, vnode: VNode, ctx: WfuiContext): void;
|
|
33
|
-
export { callRefCleanup, idRegistry, clearAsyncComponentCache, nextComponentId } from './registry.ts';
|
|
34
40
|
export { patchValue } from './diff.ts';
|
|
41
|
+
/** 模块级兼容(无 ctx 场景——独立清理,不影响活跃 registry) */
|
|
42
|
+
export declare function callRefCleanup(input: any): void;
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* weifuwu/ui-dom UIRouter — 纯路由(无渲染状态)
|
|
3
|
+
*
|
|
4
|
+
* 定稿架构职责划分:
|
|
5
|
+
* UIRouter = 路由表 + 匹配 + 中间件链(产 VNode)——不碰 DOM/渲染/状态
|
|
6
|
+
* serveUI = 渲染运行时(VDOM 落地:registry/createUi/renderValue/patchValue)
|
|
7
|
+
*
|
|
8
|
+
* req = window.location,res = VNode,params/query 在 ctx(serve 组装 ctx 时注入)
|
|
9
|
+
* handler = 异步组件:async (location, ctx) => vnode($ 有效)
|
|
10
|
+
* middleware = 两阶段 async:(location, ctx, children) => async (location, ctx) => vnode
|
|
11
|
+
* layout 与 SSR 都是中间件
|
|
12
|
+
*/
|
|
13
|
+
import type { UIHandler, UIMiddleware } from './types.ts';
|
|
14
|
+
import type { VNode, UIContext, AppMiddleware } from './types.ts';
|
|
15
|
+
/** UIRouter 选项 */
|
|
16
|
+
export interface UIRouterOptions {
|
|
17
|
+
mode?: 'hash' | 'history';
|
|
18
|
+
}
|
|
19
|
+
/** 匹配结果(serve 用它执行中间件链 + handler) */
|
|
20
|
+
export interface RouteMatch {
|
|
21
|
+
handler: UIHandler;
|
|
22
|
+
params: Record<string, string>;
|
|
23
|
+
title?: string;
|
|
24
|
+
}
|
|
25
|
+
/**
|
|
26
|
+
* 前端路由应用 — new UIRouter()(纯路由)
|
|
27
|
+
*/
|
|
28
|
+
export declare class UIRouter<C extends object = {}> {
|
|
29
|
+
private _routes;
|
|
30
|
+
private _middlewares;
|
|
31
|
+
/** ctx 注入中间件链(toast/confirm/notification 等——对齐后端 app.use 注入 ctx.xxx) */
|
|
32
|
+
private _injections;
|
|
33
|
+
/** 注入已完成标记(应用级 ctx——首次渲染时执行一次) */
|
|
34
|
+
private _injected;
|
|
35
|
+
private _mode;
|
|
36
|
+
private _notFound?;
|
|
37
|
+
constructor(options?: UIRouterOptions);
|
|
38
|
+
get mode(): 'hash' | 'history';
|
|
39
|
+
/** ctx 注入中间件(toast/confirm 等——(ctx) => ctx,对齐后端 app.use 注入 ctx.xxx) */
|
|
40
|
+
use<O extends object>(mw: AppMiddleware<any, O>): UIRouter<C & O>;
|
|
41
|
+
/** 渲染中间件(layout/SSR 等)——包装 children 产 vnode */
|
|
42
|
+
use<I extends object, O extends object>(mw: UIMiddleware<I, O>): UIRouter<C & O>;
|
|
43
|
+
/** 子路由挂载(= 后端 mount(path, subRouter))——独立路由树:sub 的中间件/notFound/嵌套均生效 */
|
|
44
|
+
use(prefix: string, sub: UIRouter): this;
|
|
45
|
+
/** 执行 ctx 注入链(首次渲染时一次——应用级 ctx,对齐 createApp.use 链) */
|
|
46
|
+
private _ensureInjected;
|
|
47
|
+
/** 页面路由(对齐后端 get(path, handler))——handler = 异步组件 */
|
|
48
|
+
get(path: string, handler: UIHandler<C>, opts?: {
|
|
49
|
+
title?: string;
|
|
50
|
+
}): this;
|
|
51
|
+
/** 404 */
|
|
52
|
+
notFound(handler: UIHandler): this;
|
|
53
|
+
/** 当前 URL 路径(serve 调用——mode 由 UIRouter 决定) */
|
|
54
|
+
getPath(): string;
|
|
55
|
+
private _getPath;
|
|
56
|
+
/** 匹配 URL → { handler, params, title }(serve 执行渲染) */
|
|
57
|
+
match(path: string): RouteMatch;
|
|
58
|
+
/**
|
|
59
|
+
* 子路由树处理(供 use(prefix, sub) 调用):
|
|
60
|
+
* 相对路径匹配 + sub 的中间件链 + sub 的 notFound——支持任意嵌套。
|
|
61
|
+
* 返回 VNode(无渲染——serve 落地)。
|
|
62
|
+
*/
|
|
63
|
+
_handle(relPath: string, location: Location, ctx: UIContext): Promise<VNode | null>;
|
|
64
|
+
/** 顶层执行:中间件链 + handler → VNode(serve 调用,URL 变化时) */
|
|
65
|
+
execute(location: Location, ctx: UIContext, path: string): Promise<VNode | null>;
|
|
66
|
+
}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* weifuwu/ui-dom serve — 渲染运行时(VDOM 落地机制)
|
|
3
|
+
*
|
|
4
|
+
* 定稿架构:serveUI = VDOM(落地,对齐后端 serve(router) = HTTP 传输)。
|
|
5
|
+
*
|
|
6
|
+
* uiServe(router, { root }) 调用时路由已全部注册——serve 负责:
|
|
7
|
+
* 1. 创建渲染运行时:局部 registry + createUi(19 原语)+ popup-tracker + ctx.data/browser
|
|
8
|
+
* 2. 监听 popstate/hashchange → router.match(params 注入)→ 中间件链 → handler → vnode
|
|
9
|
+
* 3. renderValue / patchValue diff/patch DOM;组件 $ dirty → renderByIds(局部 registry)
|
|
10
|
+
*
|
|
11
|
+
* 与 createApp 隔离:registry/popup-tracker/dirty 集合全部局部实例(client 零改动)。
|
|
12
|
+
*/
|
|
13
|
+
import type { UIRouter } from './router.ts';
|
|
14
|
+
import type { WfuiContext } from './types.ts';
|
|
15
|
+
/** uiServe 选项 */
|
|
16
|
+
export interface UIServeOptions {
|
|
17
|
+
root: string | Element;
|
|
18
|
+
hydrate?: boolean;
|
|
19
|
+
}
|
|
20
|
+
/** serve 句柄 */
|
|
21
|
+
export interface UIServeHandle<C extends object = {}> {
|
|
22
|
+
/** 释放全部资源(监听/渲染状态/注册表) */
|
|
23
|
+
close(): void;
|
|
24
|
+
/** 当前 ctx(调试/测试用)——含 UIRouter ctx 注入的类型扩展 */
|
|
25
|
+
ctx: WfuiContext & C;
|
|
26
|
+
}
|
|
27
|
+
/** uiServe — 绑定唯一根节点 + URL 驱动渲染(= VDOM 落地,对齐 serve(router)) */
|
|
28
|
+
export declare function uiServe<RC extends object = {}>(router: UIRouter<RC>, options: UIServeOptions): UIServeHandle<RC>;
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 服务端 SSR 字符串遍历器 — async 工厂组件(形态 C)的 HTML 序列化
|
|
3
|
+
*
|
|
4
|
+
* 支持:
|
|
5
|
+
* - 同步组件(mount → render → VNode → HTML)
|
|
6
|
+
* - async 工厂组件(await 工厂 → 数据进 HTML;服务端不缓存定义,数据 per-request)
|
|
7
|
+
* - Fragment / Portal(内联子节点)
|
|
8
|
+
* - innerHTML prop(原样输出)、class/style 对象序列化
|
|
9
|
+
* - 事件处理器 / ref 剥离、文本自动转义(XSS)
|
|
10
|
+
* - 服务端 ctx shim($ no-op dirty、ctx.data 预取、selfId 隔离)
|
|
11
|
+
*
|
|
12
|
+
* 产物为 HtmlSafe 标记的安全 HTML 片段,可直接内联进 ctx.ui.html 模板。
|
|
13
|
+
*/
|
|
14
|
+
import type { Component, AsyncComponent } from './vnode.ts';
|
|
15
|
+
export interface SsrOptions {
|
|
16
|
+
/** 服务端数据存储:ctx.data 预取结果写入此处,调用方序列化进 __DATA__ */
|
|
17
|
+
data?: Map<string, unknown>;
|
|
18
|
+
}
|
|
19
|
+
/**
|
|
20
|
+
* SSR 渲染组件 → HTML 片段(HtmlSafe 标记,可直接内联进 ctx.ui.html 模板,不二次转义)。
|
|
21
|
+
*
|
|
22
|
+
* ```ts
|
|
23
|
+
* const data = new Map()
|
|
24
|
+
* const html = await ctx.ui.ssr(BlogPage, { slug }, { data })
|
|
25
|
+
* return ctx.ui.html`
|
|
26
|
+
* <div id="root">${html}</div>
|
|
27
|
+
* ${ctx.ui.ssrData(data)}
|
|
28
|
+
* `
|
|
29
|
+
* ```
|
|
30
|
+
*/
|
|
31
|
+
export declare function ssrToString(Comp: Component | AsyncComponent, props: Record<string, any>, serverCtx: any, opts?: SsrOptions): Promise<string>;
|
|
32
|
+
/** 序列化数据存储 → window.__DATA__ 脚本(防 XSS:转义 <) */
|
|
33
|
+
export declare function serializeData(data: Map<string, unknown>): string;
|
|
34
|
+
import type { UIRouter } from './router.ts';
|
|
35
|
+
export interface SsrPageResult {
|
|
36
|
+
html: string;
|
|
37
|
+
/** __DATA__ 脚本(hydration 种子) */
|
|
38
|
+
dataScript: string;
|
|
39
|
+
/** 完整 HTML(含 dataScript) */
|
|
40
|
+
page: string;
|
|
41
|
+
}
|
|
42
|
+
/**
|
|
43
|
+
* SSR 渲染路由页面 → 完整 HTML(Node 无 DOM)。
|
|
44
|
+
* 执行 router 匹配 → 中间件链 → handler(async 组件)→ vnode → renderSsr。
|
|
45
|
+
*
|
|
46
|
+
* ```ts
|
|
47
|
+
* const { page } = await ssrPage(router, { url: '/users/42' })
|
|
48
|
+
* // 客户端 uiServe(router, { root, hydrate: true }) 收养
|
|
49
|
+
* ```
|
|
50
|
+
*/
|
|
51
|
+
export declare function ssrPage(router: UIRouter, opts: {
|
|
52
|
+
url: string;
|
|
53
|
+
title?: string;
|
|
54
|
+
lang?: string;
|
|
55
|
+
rootId?: string;
|
|
56
|
+
}): Promise<SsrPageResult>;
|
|
@@ -3,6 +3,7 @@
|
|
|
3
3
|
*/
|
|
4
4
|
import type { UseChatHandle, UseChatOptions } from './use-chat.ts';
|
|
5
5
|
import type { VNode } from './vnode.ts';
|
|
6
|
+
export type { VNode } from './vnode.ts';
|
|
6
7
|
import type { Placement } from './popup.ts';
|
|
7
8
|
/** 弹层位置跟踪配置 — 供 ctx.ui.usePopupPosition 使用 */
|
|
8
9
|
export interface PopupPositionOptions {
|
|
@@ -108,16 +109,16 @@ export interface UseLongPressOptions {
|
|
|
108
109
|
/** 长按时长(ms,默认 500) */
|
|
109
110
|
duration?: number;
|
|
110
111
|
/** 长按触发回调(接收触发事件,含 clientX/clientY) */
|
|
111
|
-
onLongPress: (e
|
|
112
|
+
onLongPress: (e: PointerEvent | MouseEvent) => void;
|
|
112
113
|
}
|
|
113
114
|
/** 长按返回的触发 props — spread 到目标元素 */
|
|
114
115
|
export interface UseLongPressHandle {
|
|
115
|
-
onPointerDown: (e:
|
|
116
|
-
onPointerUp: (e:
|
|
117
|
-
onPointerLeave: (e:
|
|
118
|
-
onPointerMove: (e:
|
|
116
|
+
onPointerDown: (e: PointerEvent) => void;
|
|
117
|
+
onPointerUp: (e: PointerEvent) => void;
|
|
118
|
+
onPointerLeave: (e: PointerEvent) => void;
|
|
119
|
+
onPointerMove: (e: PointerEvent) => void;
|
|
119
120
|
/** 桌面右键兼容(移动端浏览器 contextmenu 也会触发) */
|
|
120
|
-
onContextMenu: (e:
|
|
121
|
+
onContextMenu: (e: MouseEvent) => void;
|
|
121
122
|
}
|
|
122
123
|
/** 可视视口(visualViewport)状态 — useVisualViewport 返回值 */
|
|
123
124
|
export interface VisualViewportHandle {
|
|
@@ -271,7 +272,7 @@ export interface WfuiContext {
|
|
|
271
272
|
* return () => h('div', { ref: listRef })
|
|
272
273
|
* ```
|
|
273
274
|
*/
|
|
274
|
-
useStableRef: (init: (el: HTMLElement | null) => void, cleanup?: () => void) => (el:
|
|
275
|
+
useStableRef: (init: (el: HTMLElement | null) => void, cleanup?: () => void) => (el: HTMLElement | null) => void;
|
|
275
276
|
/**
|
|
276
277
|
* 全局键盘监听(window keydown):mount 注册、组件卸载自动清理;返回退订函数。
|
|
277
278
|
* 覆盖 Command 全局快捷键 / Img preview Escape 等 document/window 级键盘场景。
|
|
@@ -436,7 +437,7 @@ export interface WfuiContext {
|
|
|
436
437
|
}) => {
|
|
437
438
|
phase: 'closed' | 'open' | 'exit';
|
|
438
439
|
/** 挂到根元素(animationend 监听:exit 结束才真正卸载) */
|
|
439
|
-
ref: (el:
|
|
440
|
+
ref: (el: HTMLElement | null) => void;
|
|
440
441
|
/** render 阶段同步 open → 返回当前 phase */
|
|
441
442
|
sync: (open: boolean) => 'closed' | 'open' | 'exit';
|
|
442
443
|
};
|
|
@@ -445,9 +446,9 @@ export interface WfuiContext {
|
|
|
445
446
|
}) => {
|
|
446
447
|
phase: 'closed' | 'open' | 'exit';
|
|
447
448
|
/** 挂到 portal 根(lockScroll + animationend 退场监听) */
|
|
448
|
-
rootRef: (el:
|
|
449
|
+
rootRef: (el: HTMLElement | null) => void;
|
|
449
450
|
/** 挂到焦点 trap 目标(对话框面板) */
|
|
450
|
-
panelRef: (el:
|
|
451
|
+
panelRef: (el: HTMLElement | null) => void;
|
|
451
452
|
/** render 阶段同步 open → 返回当前 phase */
|
|
452
453
|
sync: (open: boolean) => 'closed' | 'open' | 'exit';
|
|
453
454
|
};
|
|
@@ -465,7 +466,7 @@ export interface WfuiContext {
|
|
|
465
466
|
*/
|
|
466
467
|
useAnimationEnd: (cb: () => void, opts?: {
|
|
467
468
|
once?: boolean;
|
|
468
|
-
}) => (el:
|
|
469
|
+
}) => (el: HTMLElement | null) => void;
|
|
469
470
|
/** 数值补间(rAF + ease + reduced-motion 直落终值):count-up / 进度 / 指示器。
|
|
470
471
|
* 目标值变化自动补间;返回 `{ value }`(当前值,render 读)。 */
|
|
471
472
|
useTween: (target: number, opts?: {
|
|
@@ -481,7 +482,7 @@ export interface WfuiContext {
|
|
|
481
482
|
/** 当前组件实例 ID(仅供内部使用,通过 ctx 扩展注入) */
|
|
482
483
|
_selfId?: string;
|
|
483
484
|
/** 当前组件 VNode 引用(仅供内部使用,通过 ctx 扩展注入) */
|
|
484
|
-
_selfVNode?:
|
|
485
|
+
_selfVNode?: VNode;
|
|
485
486
|
};
|
|
486
487
|
/** 路由(由 router 中间件注入) */
|
|
487
488
|
route?: {
|
|
@@ -502,13 +503,28 @@ export interface WfuiContext {
|
|
|
502
503
|
isConnected: boolean;
|
|
503
504
|
[key: string]: any;
|
|
504
505
|
};
|
|
505
|
-
/** API 客户端(由 api
|
|
506
|
+
/** API 客户端(由 api 中间件注入);options 为 ApiRequestOptions 形状(headers/signal) */
|
|
506
507
|
api?: {
|
|
507
|
-
get: <T =
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
|
|
508
|
+
get: <T = unknown>(url: string, options?: {
|
|
509
|
+
headers?: Record<string, string>;
|
|
510
|
+
signal?: AbortSignal;
|
|
511
|
+
}) => Promise<T>;
|
|
512
|
+
post: <T = unknown>(url: string, body?: unknown, options?: {
|
|
513
|
+
headers?: Record<string, string>;
|
|
514
|
+
signal?: AbortSignal;
|
|
515
|
+
}) => Promise<T>;
|
|
516
|
+
put: <T = unknown>(url: string, body?: unknown, options?: {
|
|
517
|
+
headers?: Record<string, string>;
|
|
518
|
+
signal?: AbortSignal;
|
|
519
|
+
}) => Promise<T>;
|
|
520
|
+
patch: <T = unknown>(url: string, body?: unknown, options?: {
|
|
521
|
+
headers?: Record<string, string>;
|
|
522
|
+
signal?: AbortSignal;
|
|
523
|
+
}) => Promise<T>;
|
|
524
|
+
delete: <T = unknown>(url: string, options?: {
|
|
525
|
+
headers?: Record<string, string>;
|
|
526
|
+
signal?: AbortSignal;
|
|
527
|
+
}) => Promise<T>;
|
|
512
528
|
[key: string]: any;
|
|
513
529
|
};
|
|
514
530
|
/** 数据管道(由 createApp 注入):ctx.data.get(key, fetcher) */
|
|
@@ -564,3 +580,32 @@ export interface RouteDef {
|
|
|
564
580
|
}
|
|
565
581
|
/** 扩展 ctx — 创建新对象,原 ctx 的 getter 通过原型链继承 */
|
|
566
582
|
export declare function extendCtx<T extends Record<string, unknown>>(ctx: WfuiContext, fields: T): WfuiContext & T;
|
|
583
|
+
/** SSR 数据种子(ssr.ts 序列化进 window.__DATA__ 脚本,hydration 时客户端读取) */
|
|
584
|
+
declare global {
|
|
585
|
+
interface Window {
|
|
586
|
+
__DATA__?: Record<string, unknown>;
|
|
587
|
+
}
|
|
588
|
+
var __DATA__: Record<string, unknown> | undefined;
|
|
589
|
+
}
|
|
590
|
+
export {};
|
|
591
|
+
/** ui-dom ctx:client WfuiContext + 顶层 params/query/data(定稿——对齐后端 ctx.params/ctx.query) */
|
|
592
|
+
export type UIContext<C extends object = {}> = WfuiContext & C & {
|
|
593
|
+
params: Record<string, string>;
|
|
594
|
+
query: Record<string, string>;
|
|
595
|
+
data: NonNullable<WfuiContext['data']>;
|
|
596
|
+
[key: string]: any;
|
|
597
|
+
};
|
|
598
|
+
/** req = window.location(浏览器原生 Location,不包装) */
|
|
599
|
+
export type UIRequest = Location;
|
|
600
|
+
/** res = VNode(数据结构);uiServe = VDOM(落地) */
|
|
601
|
+
export type UIResponse = VNode | null;
|
|
602
|
+
/** handler = 异步组件:async (location, ctx) => vnode($ 有效) */
|
|
603
|
+
export type UIHandler<C extends object = {}> = (location: Location, ctx: UIContext<C>) => Promise<UIResponse> | UIResponse;
|
|
604
|
+
/** middleware = 两阶段 async:(location, ctx, children) => async (location, ctx) => vnode */
|
|
605
|
+
export type UIMiddleware<I extends object = {}, O extends object = {}> = (location: Location, ctx: UIContext<I>, children: UIHandler<any>) => Promise<UIHandler<O>> | UIHandler<O>;
|
|
606
|
+
/** 路由定义(UIRouter.get 内部存储) */
|
|
607
|
+
export interface UIRouteDef {
|
|
608
|
+
path: string;
|
|
609
|
+
handler: UIHandler;
|
|
610
|
+
title?: string;
|
|
611
|
+
}
|