flexium 0.12.13 → 0.12.17
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 +149 -92
- package/dist/canvas.d.cts +14 -13
- package/dist/canvas.d.ts +14 -13
- package/dist/canvas.js +1 -1
- package/dist/canvas.js.map +1 -1
- package/dist/canvas.mjs +1 -1
- package/dist/canvas.mjs.map +1 -1
- package/dist/chunk-3DKZ2J4D.mjs +2 -0
- package/dist/chunk-3DKZ2J4D.mjs.map +1 -0
- package/dist/chunk-5PNH2ARD.mjs +2 -0
- package/dist/chunk-5PNH2ARD.mjs.map +1 -0
- package/dist/{chunk-7BXR4ZFD.js → chunk-6VIRXD2Y.js} +2 -2
- package/dist/chunk-6VIRXD2Y.js.map +1 -0
- package/dist/chunk-6Z33DLMI.js +2 -0
- package/dist/chunk-6Z33DLMI.js.map +1 -0
- package/dist/chunk-E75BJDOQ.mjs +2 -0
- package/dist/chunk-E75BJDOQ.mjs.map +1 -0
- package/dist/chunk-IWFEXW4F.mjs +2 -0
- package/dist/chunk-IWFEXW4F.mjs.map +1 -0
- package/dist/chunk-JY6CE6RN.mjs +2 -0
- package/dist/chunk-JY6CE6RN.mjs.map +1 -0
- package/dist/chunk-LTT43APF.js +2 -0
- package/dist/chunk-LTT43APF.js.map +1 -0
- package/dist/chunk-PSKDIB7J.js +2 -0
- package/dist/chunk-PSKDIB7J.js.map +1 -0
- package/dist/chunk-UWFVCKRU.js +2 -0
- package/dist/chunk-UWFVCKRU.js.map +1 -0
- package/dist/chunk-WGKD63GN.mjs +2 -0
- package/dist/chunk-WGKD63GN.mjs.map +1 -0
- package/dist/chunk-YWTD32NA.js +2 -0
- package/dist/chunk-YWTD32NA.js.map +1 -0
- package/dist/core.d.cts +91 -15
- package/dist/core.d.ts +91 -15
- package/dist/core.js +1 -1
- package/dist/core.js.map +1 -1
- package/dist/core.mjs +1 -1
- package/dist/core.mjs.map +1 -1
- package/dist/dom.d.cts +154 -9
- package/dist/dom.d.ts +154 -9
- package/dist/dom.js +1 -1
- package/dist/dom.js.map +1 -1
- package/dist/dom.mjs +1 -1
- package/dist/dom.mjs.map +1 -1
- package/dist/index.d.cts +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.js +1 -1
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +1 -1
- package/dist/index.mjs.map +1 -1
- package/dist/interactive.d.cts +17 -16
- package/dist/interactive.d.ts +17 -16
- package/dist/interactive.js +1 -1
- package/dist/interactive.js.map +1 -1
- package/dist/interactive.mjs +1 -1
- package/dist/interactive.mjs.map +1 -1
- package/dist/jsx-dev-runtime.d.cts +1 -1
- package/dist/jsx-dev-runtime.d.ts +1 -1
- package/dist/jsx-runtime.d.cts +1 -1
- package/dist/jsx-runtime.d.ts +1 -1
- package/dist/metafile-cjs.json +1 -1
- package/dist/metafile-esm.json +1 -1
- package/dist/render-QZAFAGIM.js +2 -0
- package/dist/render-QZAFAGIM.js.map +1 -0
- package/dist/render-UIWHIMS2.mjs +2 -0
- package/dist/render-UIWHIMS2.mjs.map +1 -0
- package/dist/router.d.cts +1 -1
- package/dist/router.d.ts +1 -1
- package/dist/router.js +1 -1
- package/dist/router.js.map +1 -1
- package/dist/router.mjs +1 -1
- package/dist/router.mjs.map +1 -1
- package/dist/server.d.cts +17 -0
- package/dist/server.d.ts +17 -0
- package/dist/server.js +2 -0
- package/dist/server.js.map +1 -0
- package/dist/server.mjs +2 -0
- package/dist/server.mjs.map +1 -0
- package/dist/types-CxlS2F2j.d.cts +19 -0
- package/dist/types-CxlS2F2j.d.ts +19 -0
- package/dist/types-y2GGaXXk.d.cts +9 -0
- package/dist/types-y2GGaXXk.d.ts +9 -0
- package/package.json +6 -1
- package/dist/chunk-44RZHCII.mjs +0 -2
- package/dist/chunk-44RZHCII.mjs.map +0 -1
- package/dist/chunk-7BXR4ZFD.js.map +0 -1
- package/dist/chunk-APAMPY43.js +0 -2
- package/dist/chunk-APAMPY43.js.map +0 -1
- package/dist/chunk-CPJRQL2C.mjs +0 -2
- package/dist/chunk-CPJRQL2C.mjs.map +0 -1
- package/dist/chunk-ECB5HZOQ.mjs +0 -2
- package/dist/chunk-ECB5HZOQ.mjs.map +0 -1
- package/dist/chunk-ENWGYQNU.js +0 -2
- package/dist/chunk-ENWGYQNU.js.map +0 -1
- package/dist/chunk-IA4FEBFE.js +0 -2
- package/dist/chunk-IA4FEBFE.js.map +0 -1
- package/dist/chunk-LUREDEUB.mjs +0 -2
- package/dist/chunk-LUREDEUB.mjs.map +0 -1
- package/dist/chunk-LUW7DIEW.js +0 -2
- package/dist/chunk-LUW7DIEW.js.map +0 -1
- package/dist/chunk-S6WF3XNF.mjs +0 -2
- package/dist/chunk-S6WF3XNF.mjs.map +0 -1
package/dist/router.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/router/utils.ts","../src/router/router.ts","../src/router/dom/Route.tsx","../src/router/dom/Routes.tsx","../src/router/dom/Outlet.tsx","../src/router/dom/Link.tsx"],"names":["parseQuery","search","params","result","value","key","accumulator","part","isUnsafePath","path","createRoutesFromChildren","children","routes","child","component","subChildren","beforeEnter","route","nestedChildren","matchRoutes","locationPathname","routePath","matchResult","matchPath","locationPath","routeSegments","locationSegments","i","routeSegment","locationSegment","RouterCtx","createContext","RouteDepthCtx","getDefaultLocation","getCurrentLocation","globalLocation","globalNavigate","popstateListenerAttached","location","reactive","updateLocation","newLocation","router","routerContext","context","Route","_props","isFNode","node","Routes","props","currentLocation","navigate","childrenList","routeNodes","otherChildren","routeDefinitions","currentPath","matches","matchedContent","rootMatch","Component","routeKey","jsx","Outlet","depth","state","match","Link","event"],"mappings":"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","file":"router.js","sourcesContent":["import { RouteDefinition, RouteMatch } from './types'\n\n// Simple query parser (native URLSearchParams fallback) - internal use only\nfunction parseQuery(search: string): Record<string, string> {\n if (!search) return {}\n if (typeof URLSearchParams !== 'undefined') {\n const params = new URLSearchParams(search)\n const result: Record<string, string> = {}\n params.forEach((value, key) => result[key] = value)\n return result\n }\n return search\n .substring(1)\n .split('&')\n .reduce((accumulator, part) => {\n const [key, value] = part.split('=')\n if (key) accumulator[decodeURIComponent(key)] = decodeURIComponent(value || '')\n return accumulator\n }, {} as Record<string, string>)\n}\n\nfunction isUnsafePath(path: string): boolean {\n // Prevent prototype pollution or massive strings\n if (path.length > 2048) return true\n if (path.includes('__proto__') || path.includes('constructor')) return true\n // Basic XSS check for javascript: protocol\n if (/^\\s*javascript:/i.test(path)) return true\n return false\n}\n\n// Convert children FNodes to RouteDefinitions - internal use only\nfunction createRoutesFromChildren(children: any[]): RouteDefinition[] {\n const routes: RouteDefinition[] = []\n\n children.forEach(child => {\n if (!child) return\n\n // Assuming child is an FNode-like object (config)\n // In Flexium, Route component returns null, but 'createNode' isn't called here.\n // We are traversing the props passed to Router.\n\n const { path, component, children: subChildren, beforeEnter } = child.props || {}\n\n const route: RouteDefinition = {\n path: path || '/',\n component: component,\n beforeEnter\n }\n\n if (subChildren) {\n // If subChildren is array\n const nestedChildren = Array.isArray(subChildren) ? subChildren : [subChildren]\n // We expect the children of a Route to be other Routes\n // However, the 'children' prop in JSX might be the Route components themselves.\n route.children = createRoutesFromChildren(nestedChildren)\n }\n\n // Also check child.children if props.children is empty (direct FNode structure)\n if (!route.children && child.children && child.children.length > 0) {\n route.children = createRoutesFromChildren(child.children)\n }\n\n routes.push(route)\n })\n return routes\n}\n\n// Simple Matcher - internal use only\nfunction matchRoutes(routes: RouteDefinition[], locationPathname: string): RouteMatch[] | null {\n // We want to find the best matching branch\n\n for (const route of routes) {\n // 1. Match current segment\n // Simple exact match or parameter match logic needed?\n // Let's implement simple param matching: /user/:id\n\n const routePath = route.path\n\n const matchResult = matchPath(routePath, locationPathname)\n if (matchResult) {\n return [{ route, params: matchResult.params, pathname: matchResult.path }]\n }\n }\n return null\n}\n\nfunction matchPath(routePath: string, locationPath: string) {\n // 1. Split into segments\n const routeSegments = routePath.split('/').filter(Boolean)\n const locationSegments = locationPath.split('/').filter(Boolean)\n\n if (routeSegments.length !== locationSegments.length) return null\n\n const params: Record<string, string> = {}\n\n for (let i = 0; i < routeSegments.length; i++) {\n const routeSegment = routeSegments[i]\n const locationSegment = locationSegments[i]\n\n if (routeSegment.startsWith(':')) {\n const key = routeSegment.slice(1)\n params[key] = locationSegment\n } else if (routeSegment !== locationSegment) {\n return null\n }\n }\n\n return { params, path: locationPath }\n}\n\n// Export only what's needed by other router files\nexport { parseQuery, isUnsafePath, createRoutesFromChildren, matchRoutes }\n","import { reactive } from '../core/reactive'\nimport { createContext, context } from '../core/context'\nimport type { Location, RouterContext } from './types'\nimport { parseQuery, isUnsafePath } from './utils'\n\n// Contexts\nexport const RouterCtx = createContext<RouterContext>(null as any)\nexport const RouteDepthCtx = createContext<number>(0)\n\n// Helper functions\nconst getDefaultLocation = (): Location => ({\n pathname: '/',\n search: '',\n hash: '',\n query: {},\n})\n\nconst getCurrentLocation = (): Location => {\n if (typeof window === 'undefined') {\n return getDefaultLocation()\n }\n return {\n pathname: window.location.pathname,\n search: window.location.search,\n hash: window.location.hash,\n query: parseQuery(window.location.search),\n }\n}\n\n// Global singleton location state\nlet globalLocation: Location | null = null\nlet globalNavigate: ((path: string) => void) | null = null\nlet popstateListenerAttached = false\n\n// Create location state and navigation (singleton pattern)\nexport function location(): [Location, (path: string) => void] {\n // Return existing singleton if already created\n if (globalLocation && globalNavigate) {\n return [globalLocation, globalNavigate]\n }\n\n // Create a reactive location object (only once)\n globalLocation = reactive<Location>(getCurrentLocation())\n\n const updateLocation = (newLocation: Location) => {\n if (!globalLocation) return\n globalLocation.pathname = newLocation.pathname\n globalLocation.search = newLocation.search\n globalLocation.hash = newLocation.hash\n globalLocation.query = newLocation.query\n }\n\n globalNavigate = (path: string) => {\n if (typeof window === 'undefined') return\n if (isUnsafePath(path)) {\n console.error('[Flexium Router] Blocked navigation to unsafe path:', path)\n return\n }\n window.history.pushState({}, '', path)\n const newLocation = getCurrentLocation()\n updateLocation(newLocation)\n }\n\n // Listen to popstate (only once)\n if (typeof window !== 'undefined' && !popstateListenerAttached) {\n window.addEventListener('popstate', () => {\n updateLocation(getCurrentLocation())\n })\n popstateListenerAttached = true\n }\n\n return [globalLocation, globalNavigate]\n}\n\n// Router hook\nexport function router(): RouterContext {\n const routerContext = context(RouterCtx)\n if (!routerContext) {\n throw new Error('router() must be called within a <Routes> component')\n }\n return routerContext\n}\n","import type { RouteProps } from '../types'\n\nexport function Route(_props: RouteProps) {\n return null\n}\n","import { jsx as f } from '../../jsx-runtime'\nimport type { FNode, FNodeChild } from '../../dom'\nimport { RouterCtx, RouteDepthCtx, location } from '../router'\nimport { createRoutesFromChildren, matchRoutes } from '../utils'\nimport { Route } from './Route'\n\nfunction isFNode(node: any): node is FNode {\n return node && typeof node === 'object' && ('type' in node || Array.isArray(node))\n}\n\nexport function Routes(props: { children: FNodeChild }) {\n const [currentLocation, navigate] = location()\n\n // Parse children to find <Route> definitions and other content\n let childrenList: any[] = Array.isArray(props.children) ? props.children : [props.children]\n\n // Separate routes from other children (like Nav components)\n const routeNodes = childrenList.filter(child => isFNode(child) && child.type === Route)\n const otherChildren = childrenList.filter(child => !isFNode(child) || child.type !== Route)\n\n // Create route definitions\n const routeDefinitions = createRoutesFromChildren(routeNodes)\n\n // DIRECT access to currentLocation.pathname\n // This should trigger reactive tracking in the component's effect context\n const currentPath = currentLocation.pathname\n const matches = matchRoutes(routeDefinitions, currentPath) || []\n const params = matches.length > 0 ? matches[matches.length - 1].params : {}\n\n const routerContext = {\n location: currentLocation,\n navigate,\n matches: matches,\n params: params\n }\n\n // Render matched component\n let matchedContent: FNodeChild = null\n\n if (matches.length > 0) {\n const rootMatch = matches[0]\n const Component = rootMatch.route.component\n\n // Use pathname as key to force re-mount on route change\n const routeKey = currentPath\n\n // Guard Check\n if (rootMatch.route.beforeEnter) {\n const result = rootMatch.route.beforeEnter(rootMatch.params)\n if (result !== false) {\n matchedContent = f(RouteDepthCtx.Provider, {\n value: 1,\n key: routeKey,\n children: f(Component, { params: rootMatch.params, key: routeKey })\n })\n }\n } else {\n matchedContent = f(RouteDepthCtx.Provider, {\n value: 1,\n key: routeKey,\n children: f(Component, { params: rootMatch.params, key: routeKey })\n })\n }\n }\n\n return f(RouterCtx.Provider, {\n value: routerContext,\n children: [...otherChildren, matchedContent]\n })\n}\n","import { state } from '../../core/state'\nimport { context } from '../../core/context'\nimport { jsx as f } from '../../jsx-runtime'\nimport { RouteDepthCtx, router } from '../router'\n\nexport function Outlet() {\n const routerContext = router()\n const depth = (context(RouteDepthCtx) as number) || 0\n\n const [matches] = state(() => routerContext.matches)\n\n if (depth >= matches.length) return null\n\n const match = matches[depth]\n const Component = match.route.component\n\n // Guard\n if (match.route.beforeEnter) {\n if (match.route.beforeEnter(match.params) === false) return null\n }\n\n // Render next level\n return f(RouteDepthCtx.Provider, {\n value: depth + 1,\n children: f(Component, { params: match.params })\n })\n}\n","import { jsx as f } from '../../jsx-runtime'\nimport type { LinkProps } from '../types'\nimport { router } from '../router'\n\nexport function Link(props: LinkProps) {\n const routerContext = router()\n return f('a', {\n href: props.to,\n class: props.class,\n onclick: (event: Event) => {\n event.preventDefault()\n routerContext.navigate(props.to)\n },\n children: props.children\n })\n}\n"]}
|
|
1
|
+
{"version":3,"sources":["../src/router/utils.ts","../src/router/router.ts","../src/router/dom/Route.tsx","../src/router/dom/Routes.tsx","../src/router/dom/Outlet.tsx","../src/router/dom/Link.tsx"],"names":["parseQuery","search","params","result","value","key","accumulator","part","isUnsafePath","path","createRoutesFromChildren","children","routes","child","component","subChildren","beforeEnter","route","nestedChildren","matchRoutes","locationPathname","routePath","matchResult","matchPath","locationPath","routeSegments","locationSegments","i","routeSegment","locationSegment","RouterCtx","createContext","RouteDepthCtx","getDefaultLocation","getCurrentLocation","globalLocation","globalNavigate","popstateListenerAttached","location","reactive","updateLocation","newLocation","router","routerContext","context","Route","_props","isFNode","node","Routes","props","currentLocation","navigate","childrenList","routeNodes","otherChildren","routeDefinitions","currentPath","matches","matchedContent","rootMatch","Component","routeKey","jsx","Outlet","depth","state","match","Link","event"],"mappings":"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","file":"router.js","sourcesContent":["import { RouteDefinition, RouteMatch } from './types'\n\n// Simple query parser (native URLSearchParams fallback) - internal use only\nfunction parseQuery(search: string): Record<string, string> {\n if (!search) return {}\n if (typeof URLSearchParams !== 'undefined') {\n const params = new URLSearchParams(search)\n const result: Record<string, string> = {}\n params.forEach((value, key) => result[key] = value)\n return result\n }\n return search\n .substring(1)\n .split('&')\n .reduce((accumulator, part) => {\n const [key, value] = part.split('=')\n if (key) accumulator[decodeURIComponent(key)] = decodeURIComponent(value || '')\n return accumulator\n }, {} as Record<string, string>)\n}\n\nfunction isUnsafePath(path: string): boolean {\n // Prevent prototype pollution or massive strings\n if (path.length > 2048) return true\n if (path.includes('__proto__') || path.includes('constructor')) return true\n // Basic XSS check for javascript: protocol\n if (/^\\s*javascript:/i.test(path)) return true\n return false\n}\n\n// Convert children FNodes to RouteDefinitions - internal use only\nfunction createRoutesFromChildren(children: any[]): RouteDefinition[] {\n const routes: RouteDefinition[] = []\n\n children.forEach(child => {\n if (!child) return\n\n // Assuming child is an FNode-like object (config)\n // In Flexium, Route component returns null, but 'createNode' isn't called here.\n // We are traversing the props passed to Router.\n\n const { path, component, children: subChildren, beforeEnter } = child.props || {}\n\n const route: RouteDefinition = {\n path: path || '/',\n component: component,\n beforeEnter\n }\n\n if (subChildren) {\n // If subChildren is array\n const nestedChildren = Array.isArray(subChildren) ? subChildren : [subChildren]\n // We expect the children of a Route to be other Routes\n // However, the 'children' prop in JSX might be the Route components themselves.\n route.children = createRoutesFromChildren(nestedChildren)\n }\n\n // Also check child.children if props.children is empty (direct FNode structure)\n if (!route.children && child.children && child.children.length > 0) {\n route.children = createRoutesFromChildren(child.children)\n }\n\n routes.push(route)\n })\n return routes\n}\n\n// Simple Matcher - internal use only\nfunction matchRoutes(routes: RouteDefinition[], locationPathname: string): RouteMatch[] | null {\n // We want to find the best matching branch\n\n for (const route of routes) {\n // 1. Match current segment\n // Simple exact match or parameter match logic needed?\n // Let's implement simple param matching: /user/:id\n\n const routePath = route.path\n\n const matchResult = matchPath(routePath, locationPathname)\n if (matchResult) {\n return [{ route, params: matchResult.params, pathname: matchResult.path }]\n }\n }\n return null\n}\n\nfunction matchPath(routePath: string, locationPath: string) {\n // 1. Split into segments\n const routeSegments = routePath.split('/').filter(Boolean)\n const locationSegments = locationPath.split('/').filter(Boolean)\n\n if (routeSegments.length !== locationSegments.length) return null\n\n const params: Record<string, string> = {}\n\n for (let i = 0; i < routeSegments.length; i++) {\n const routeSegment = routeSegments[i]\n const locationSegment = locationSegments[i]\n\n if (routeSegment.startsWith(':')) {\n const key = routeSegment.slice(1)\n params[key] = locationSegment\n } else if (routeSegment !== locationSegment) {\n return null\n }\n }\n\n return { params, path: locationPath }\n}\n\n// Export only what's needed by other router files\nexport { parseQuery, isUnsafePath, createRoutesFromChildren, matchRoutes }\n","import { reactive } from '../core/reactive'\nimport { createContext, context } from '../core/context'\nimport type { Location, RouterContext } from './types'\nimport { parseQuery, isUnsafePath } from './utils'\n\n// Contexts\nexport const RouterCtx = createContext<RouterContext>(null as any)\nexport const RouteDepthCtx = createContext<number>(0)\n\n// Helper functions\nconst getDefaultLocation = (): Location => ({\n pathname: '/',\n search: '',\n hash: '',\n query: {},\n})\n\nconst getCurrentLocation = (): Location => {\n if (typeof window === 'undefined') {\n return getDefaultLocation()\n }\n return {\n pathname: window.location.pathname,\n search: window.location.search,\n hash: window.location.hash,\n query: parseQuery(window.location.search),\n }\n}\n\n// Global singleton location state\nlet globalLocation: Location | null = null\nlet globalNavigate: ((path: string) => void) | null = null\nlet popstateListenerAttached = false\n\n// Create location state and navigation (singleton pattern)\nexport function location(): [Location, (path: string) => void] {\n // Return existing singleton if already created\n if (globalLocation && globalNavigate) {\n return [globalLocation, globalNavigate]\n }\n\n // Create a reactive location object (only once)\n globalLocation = reactive<Location>(getCurrentLocation())\n\n const updateLocation = (newLocation: Location) => {\n if (!globalLocation) return\n globalLocation.pathname = newLocation.pathname\n globalLocation.search = newLocation.search\n globalLocation.hash = newLocation.hash\n globalLocation.query = newLocation.query\n }\n\n globalNavigate = (path: string) => {\n if (typeof window === 'undefined') return\n if (isUnsafePath(path)) {\n console.error('[Flexium Router] Blocked navigation to unsafe path:', path)\n return\n }\n window.history.pushState({}, '', path)\n const newLocation = getCurrentLocation()\n updateLocation(newLocation)\n }\n\n // Listen to popstate (only once)\n if (typeof window !== 'undefined' && !popstateListenerAttached) {\n window.addEventListener('popstate', () => {\n updateLocation(getCurrentLocation())\n })\n popstateListenerAttached = true\n }\n\n return [globalLocation, globalNavigate]\n}\n\n// Router hook\nexport function router(): RouterContext {\n const routerContext = context(RouterCtx)\n if (!routerContext) {\n throw new Error('router() must be called within a <Routes> component')\n }\n return routerContext\n}\n","import type { RouteProps } from '../types'\n\nexport function Route(_props: RouteProps) {\n return null\n}\n","import { jsx as f } from '../../jsx-runtime'\nimport type { FNode, FNodeChild } from '../../dom'\nimport { RouterCtx, RouteDepthCtx, location } from '../router'\nimport { createRoutesFromChildren, matchRoutes } from '../utils'\nimport { Route } from './Route'\n\nfunction isFNode(node: any): node is FNode {\n return node && typeof node === 'object' && ('type' in node || Array.isArray(node))\n}\n\nexport function Routes(props: { children: FNodeChild }) {\n const [currentLocation, navigate] = location()\n\n // Parse children to find <Route> definitions and other content\n let childrenList: any[] = Array.isArray(props.children) ? props.children : [props.children]\n\n // Separate routes from other children (like Nav components)\n const routeNodes = childrenList.filter(child => isFNode(child) && child.type === Route)\n const otherChildren = childrenList.filter(child => !isFNode(child) || child.type !== Route)\n\n // Create route definitions\n const routeDefinitions = createRoutesFromChildren(routeNodes)\n\n // DIRECT access to currentLocation.pathname\n // This should trigger reactive tracking in the component's effect context\n const currentPath = currentLocation.pathname\n const matches = matchRoutes(routeDefinitions, currentPath) || []\n const params = matches.length > 0 ? matches[matches.length - 1].params : {}\n\n const routerContext = {\n location: currentLocation,\n navigate,\n matches: matches,\n params: params\n }\n\n // Render matched component\n let matchedContent: FNodeChild = null\n\n if (matches.length > 0) {\n const rootMatch = matches[0]\n const Component = rootMatch.route.component\n\n // Use pathname as key to force re-mount on route change\n const routeKey = currentPath\n\n // Guard Check\n if (rootMatch.route.beforeEnter) {\n const result = rootMatch.route.beforeEnter(rootMatch.params)\n if (result !== false) {\n matchedContent = f(RouteDepthCtx.Provider, {\n value: 1,\n key: routeKey,\n children: f(Component, { params: rootMatch.params, key: routeKey })\n })\n }\n } else {\n matchedContent = f(RouteDepthCtx.Provider, {\n value: 1,\n key: routeKey,\n children: f(Component, { params: rootMatch.params, key: routeKey })\n })\n }\n }\n\n return f(RouterCtx.Provider, {\n value: routerContext,\n children: [...otherChildren, matchedContent]\n })\n}\n","import { state } from '../../core/state'\nimport { context } from '../../core/context'\nimport { jsx as f } from '../../jsx-runtime'\nimport { RouteDepthCtx, router } from '../router'\n\nexport function Outlet() {\n const routerContext = router()\n const depth = (context(RouteDepthCtx) as number) || 0\n\n const [matches] = state(() => routerContext.matches)\n\n if (depth >= matches.length) return null\n\n const match = matches[depth]\n const Component = match.route.component\n\n // Guard\n if (match.route.beforeEnter) {\n if (match.route.beforeEnter(match.params) === false) return null\n }\n\n // Render next level\n return f(RouteDepthCtx.Provider, {\n value: depth + 1,\n children: f(Component, { params: match.params })\n })\n}\n","import { jsx as f } from '../../jsx-runtime'\nimport type { LinkProps } from '../types'\nimport { router } from '../router'\n\nexport function Link(props: LinkProps) {\n const routerContext = router()\n return f('a', {\n href: props.to,\n class: props.class,\n onclick: (event: Event) => {\n event.preventDefault()\n routerContext.navigate(props.to)\n },\n children: props.children\n })\n}\n"]}
|
package/dist/router.mjs
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import {a,b}from'./chunk-
|
|
1
|
+
import {a,b}from'./chunk-3DKZ2J4D.mjs';import {a as a$2}from'./chunk-WGKD63GN.mjs';import {a as a$3}from'./chunk-JY6CE6RN.mjs';import'./chunk-IWFEXW4F.mjs';import'./chunk-5PNH2ARD.mjs';import {a as a$1}from'./chunk-ZCO4NIGC.mjs';function k(t){if(!t)return {};if(typeof URLSearchParams<"u"){let e=new URLSearchParams(t),r={};return e.forEach((o,n)=>r[n]=o),r}return t.substring(1).split("&").reduce((e,r)=>{let[o,n]=r.split("=");return o&&(e[decodeURIComponent(o)]=decodeURIComponent(n||"")),e},{})}function D(t){return !!(t.length>2048||t.includes("__proto__")||t.includes("constructor")||/^\s*javascript:/i.test(t))}function y(t){let e=[];return t.forEach(r=>{if(!r)return;let{path:o,component:n,children:s,beforeEnter:f}=r.props||{},u={path:o||"/",component:n,beforeEnter:f};if(s){let c=Array.isArray(s)?s:[s];u.children=y(c);}!u.children&&r.children&&r.children.length>0&&(u.children=y(r.children)),e.push(u);}),e}function E(t,e){for(let r of t){let o=r.path,n=j(o,e);if(n)return [{route:r,params:n.params,pathname:n.path}]}return null}function j(t,e){let r=t.split("/").filter(Boolean),o=e.split("/").filter(Boolean);if(r.length!==o.length)return null;let n={};for(let s=0;s<r.length;s++){let f=r[s],u=o[s];if(f.startsWith(":")){let c=f.slice(1);n[c]=u;}else if(f!==u)return null}return {params:n,path:e}}var w=a(null),p=a(0),_=()=>({pathname:"/",search:"",hash:"",query:{}}),v=()=>typeof window>"u"?_():{pathname:window.location.pathname,search:window.location.search,hash:window.location.hash,query:k(window.location.search)},l=null,g=null,F=false;function N(){if(l&&g)return [l,g];l=a$3(v());let t=e=>{l&&(l.pathname=e.pathname,l.search=e.search,l.hash=e.hash,l.query=e.query);};return g=e=>{if(typeof window>"u")return;if(D(e)){console.error("[Flexium Router] Blocked navigation to unsafe path:",e);return}window.history.pushState({},"",e);let r=v();t(r);},typeof window<"u"&&!F&&(window.addEventListener("popstate",()=>{t(v());}),F=true),[l,g]}function m(){let t=b(w);if(!t)throw new Error("router() must be called within a <Routes> component");return t}function R(t){return null}function A(t){return t&&typeof t=="object"&&("type"in t||Array.isArray(t))}function q(t){let[e,r]=N(),o=Array.isArray(t.children)?t.children:[t.children],n=o.filter(i=>A(i)&&i.type===R),s=o.filter(i=>!A(i)||i.type!==R),f=y(n),u=e.pathname,c=E(f,u)||[],S=c.length>0?c[c.length-1].params:{},U={location:e,navigate:r,matches:c,params:S},x=null;if(c.length>0){let i=c[0],L=i.route.component,h=u;i.route.beforeEnter?i.route.beforeEnter(i.params)!==false&&(x=a$1(p.Provider,{value:1,key:h,children:a$1(L,{params:i.params,key:h})})):x=a$1(p.Provider,{value:1,key:h,children:a$1(L,{params:i.params,key:h})});}return a$1(w.Provider,{value:U,children:[...s,x]})}function B(){let t=m(),e=b(p)||0,[r]=a$2(()=>t.matches);if(e>=r.length)return null;let o=r[e],n=o.route.component;return o.route.beforeEnter&&o.route.beforeEnter(o.params)===false?null:a$1(p.Provider,{value:e+1,children:a$1(n,{params:o.params})})}function M(t){let e=m();return a$1("a",{href:t.to,class:t.class,onclick:r=>{r.preventDefault(),e.navigate(t.to);},children:t.children})}export{M as Link,B as Outlet,R as Route,q as Routes,m as router};//# sourceMappingURL=router.mjs.map
|
|
2
2
|
//# sourceMappingURL=router.mjs.map
|
package/dist/router.mjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/router/utils.ts","../src/router/router.ts","../src/router/dom/Route.tsx","../src/router/dom/Routes.tsx","../src/router/dom/Outlet.tsx","../src/router/dom/Link.tsx"],"names":["parseQuery","search","params","result","value","key","accumulator","part","isUnsafePath","path","createRoutesFromChildren","children","routes","child","component","subChildren","beforeEnter","route","nestedChildren","matchRoutes","locationPathname","routePath","matchResult","matchPath","locationPath","routeSegments","locationSegments","i","routeSegment","locationSegment","RouterCtx","createContext","RouteDepthCtx","getDefaultLocation","getCurrentLocation","globalLocation","globalNavigate","popstateListenerAttached","location","reactive","updateLocation","newLocation","router","routerContext","context","Route","_props","isFNode","node","Routes","props","currentLocation","navigate","childrenList","routeNodes","otherChildren","routeDefinitions","currentPath","matches","matchedContent","rootMatch","Component","routeKey","jsx","Outlet","depth","state","match","Link","event"],"mappings":"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","file":"router.mjs","sourcesContent":["import { RouteDefinition, RouteMatch } from './types'\n\n// Simple query parser (native URLSearchParams fallback) - internal use only\nfunction parseQuery(search: string): Record<string, string> {\n if (!search) return {}\n if (typeof URLSearchParams !== 'undefined') {\n const params = new URLSearchParams(search)\n const result: Record<string, string> = {}\n params.forEach((value, key) => result[key] = value)\n return result\n }\n return search\n .substring(1)\n .split('&')\n .reduce((accumulator, part) => {\n const [key, value] = part.split('=')\n if (key) accumulator[decodeURIComponent(key)] = decodeURIComponent(value || '')\n return accumulator\n }, {} as Record<string, string>)\n}\n\nfunction isUnsafePath(path: string): boolean {\n // Prevent prototype pollution or massive strings\n if (path.length > 2048) return true\n if (path.includes('__proto__') || path.includes('constructor')) return true\n // Basic XSS check for javascript: protocol\n if (/^\\s*javascript:/i.test(path)) return true\n return false\n}\n\n// Convert children FNodes to RouteDefinitions - internal use only\nfunction createRoutesFromChildren(children: any[]): RouteDefinition[] {\n const routes: RouteDefinition[] = []\n\n children.forEach(child => {\n if (!child) return\n\n // Assuming child is an FNode-like object (config)\n // In Flexium, Route component returns null, but 'createNode' isn't called here.\n // We are traversing the props passed to Router.\n\n const { path, component, children: subChildren, beforeEnter } = child.props || {}\n\n const route: RouteDefinition = {\n path: path || '/',\n component: component,\n beforeEnter\n }\n\n if (subChildren) {\n // If subChildren is array\n const nestedChildren = Array.isArray(subChildren) ? subChildren : [subChildren]\n // We expect the children of a Route to be other Routes\n // However, the 'children' prop in JSX might be the Route components themselves.\n route.children = createRoutesFromChildren(nestedChildren)\n }\n\n // Also check child.children if props.children is empty (direct FNode structure)\n if (!route.children && child.children && child.children.length > 0) {\n route.children = createRoutesFromChildren(child.children)\n }\n\n routes.push(route)\n })\n return routes\n}\n\n// Simple Matcher - internal use only\nfunction matchRoutes(routes: RouteDefinition[], locationPathname: string): RouteMatch[] | null {\n // We want to find the best matching branch\n\n for (const route of routes) {\n // 1. Match current segment\n // Simple exact match or parameter match logic needed?\n // Let's implement simple param matching: /user/:id\n\n const routePath = route.path\n\n const matchResult = matchPath(routePath, locationPathname)\n if (matchResult) {\n return [{ route, params: matchResult.params, pathname: matchResult.path }]\n }\n }\n return null\n}\n\nfunction matchPath(routePath: string, locationPath: string) {\n // 1. Split into segments\n const routeSegments = routePath.split('/').filter(Boolean)\n const locationSegments = locationPath.split('/').filter(Boolean)\n\n if (routeSegments.length !== locationSegments.length) return null\n\n const params: Record<string, string> = {}\n\n for (let i = 0; i < routeSegments.length; i++) {\n const routeSegment = routeSegments[i]\n const locationSegment = locationSegments[i]\n\n if (routeSegment.startsWith(':')) {\n const key = routeSegment.slice(1)\n params[key] = locationSegment\n } else if (routeSegment !== locationSegment) {\n return null\n }\n }\n\n return { params, path: locationPath }\n}\n\n// Export only what's needed by other router files\nexport { parseQuery, isUnsafePath, createRoutesFromChildren, matchRoutes }\n","import { reactive } from '../core/reactive'\nimport { createContext, context } from '../core/context'\nimport type { Location, RouterContext } from './types'\nimport { parseQuery, isUnsafePath } from './utils'\n\n// Contexts\nexport const RouterCtx = createContext<RouterContext>(null as any)\nexport const RouteDepthCtx = createContext<number>(0)\n\n// Helper functions\nconst getDefaultLocation = (): Location => ({\n pathname: '/',\n search: '',\n hash: '',\n query: {},\n})\n\nconst getCurrentLocation = (): Location => {\n if (typeof window === 'undefined') {\n return getDefaultLocation()\n }\n return {\n pathname: window.location.pathname,\n search: window.location.search,\n hash: window.location.hash,\n query: parseQuery(window.location.search),\n }\n}\n\n// Global singleton location state\nlet globalLocation: Location | null = null\nlet globalNavigate: ((path: string) => void) | null = null\nlet popstateListenerAttached = false\n\n// Create location state and navigation (singleton pattern)\nexport function location(): [Location, (path: string) => void] {\n // Return existing singleton if already created\n if (globalLocation && globalNavigate) {\n return [globalLocation, globalNavigate]\n }\n\n // Create a reactive location object (only once)\n globalLocation = reactive<Location>(getCurrentLocation())\n\n const updateLocation = (newLocation: Location) => {\n if (!globalLocation) return\n globalLocation.pathname = newLocation.pathname\n globalLocation.search = newLocation.search\n globalLocation.hash = newLocation.hash\n globalLocation.query = newLocation.query\n }\n\n globalNavigate = (path: string) => {\n if (typeof window === 'undefined') return\n if (isUnsafePath(path)) {\n console.error('[Flexium Router] Blocked navigation to unsafe path:', path)\n return\n }\n window.history.pushState({}, '', path)\n const newLocation = getCurrentLocation()\n updateLocation(newLocation)\n }\n\n // Listen to popstate (only once)\n if (typeof window !== 'undefined' && !popstateListenerAttached) {\n window.addEventListener('popstate', () => {\n updateLocation(getCurrentLocation())\n })\n popstateListenerAttached = true\n }\n\n return [globalLocation, globalNavigate]\n}\n\n// Router hook\nexport function router(): RouterContext {\n const routerContext = context(RouterCtx)\n if (!routerContext) {\n throw new Error('router() must be called within a <Routes> component')\n }\n return routerContext\n}\n","import type { RouteProps } from '../types'\n\nexport function Route(_props: RouteProps) {\n return null\n}\n","import { jsx as f } from '../../jsx-runtime'\nimport type { FNode, FNodeChild } from '../../dom'\nimport { RouterCtx, RouteDepthCtx, location } from '../router'\nimport { createRoutesFromChildren, matchRoutes } from '../utils'\nimport { Route } from './Route'\n\nfunction isFNode(node: any): node is FNode {\n return node && typeof node === 'object' && ('type' in node || Array.isArray(node))\n}\n\nexport function Routes(props: { children: FNodeChild }) {\n const [currentLocation, navigate] = location()\n\n // Parse children to find <Route> definitions and other content\n let childrenList: any[] = Array.isArray(props.children) ? props.children : [props.children]\n\n // Separate routes from other children (like Nav components)\n const routeNodes = childrenList.filter(child => isFNode(child) && child.type === Route)\n const otherChildren = childrenList.filter(child => !isFNode(child) || child.type !== Route)\n\n // Create route definitions\n const routeDefinitions = createRoutesFromChildren(routeNodes)\n\n // DIRECT access to currentLocation.pathname\n // This should trigger reactive tracking in the component's effect context\n const currentPath = currentLocation.pathname\n const matches = matchRoutes(routeDefinitions, currentPath) || []\n const params = matches.length > 0 ? matches[matches.length - 1].params : {}\n\n const routerContext = {\n location: currentLocation,\n navigate,\n matches: matches,\n params: params\n }\n\n // Render matched component\n let matchedContent: FNodeChild = null\n\n if (matches.length > 0) {\n const rootMatch = matches[0]\n const Component = rootMatch.route.component\n\n // Use pathname as key to force re-mount on route change\n const routeKey = currentPath\n\n // Guard Check\n if (rootMatch.route.beforeEnter) {\n const result = rootMatch.route.beforeEnter(rootMatch.params)\n if (result !== false) {\n matchedContent = f(RouteDepthCtx.Provider, {\n value: 1,\n key: routeKey,\n children: f(Component, { params: rootMatch.params, key: routeKey })\n })\n }\n } else {\n matchedContent = f(RouteDepthCtx.Provider, {\n value: 1,\n key: routeKey,\n children: f(Component, { params: rootMatch.params, key: routeKey })\n })\n }\n }\n\n return f(RouterCtx.Provider, {\n value: routerContext,\n children: [...otherChildren, matchedContent]\n })\n}\n","import { state } from '../../core/state'\nimport { context } from '../../core/context'\nimport { jsx as f } from '../../jsx-runtime'\nimport { RouteDepthCtx, router } from '../router'\n\nexport function Outlet() {\n const routerContext = router()\n const depth = (context(RouteDepthCtx) as number) || 0\n\n const [matches] = state(() => routerContext.matches)\n\n if (depth >= matches.length) return null\n\n const match = matches[depth]\n const Component = match.route.component\n\n // Guard\n if (match.route.beforeEnter) {\n if (match.route.beforeEnter(match.params) === false) return null\n }\n\n // Render next level\n return f(RouteDepthCtx.Provider, {\n value: depth + 1,\n children: f(Component, { params: match.params })\n })\n}\n","import { jsx as f } from '../../jsx-runtime'\nimport type { LinkProps } from '../types'\nimport { router } from '../router'\n\nexport function Link(props: LinkProps) {\n const routerContext = router()\n return f('a', {\n href: props.to,\n class: props.class,\n onclick: (event: Event) => {\n event.preventDefault()\n routerContext.navigate(props.to)\n },\n children: props.children\n })\n}\n"]}
|
|
1
|
+
{"version":3,"sources":["../src/router/utils.ts","../src/router/router.ts","../src/router/dom/Route.tsx","../src/router/dom/Routes.tsx","../src/router/dom/Outlet.tsx","../src/router/dom/Link.tsx"],"names":["parseQuery","search","params","result","value","key","accumulator","part","isUnsafePath","path","createRoutesFromChildren","children","routes","child","component","subChildren","beforeEnter","route","nestedChildren","matchRoutes","locationPathname","routePath","matchResult","matchPath","locationPath","routeSegments","locationSegments","i","routeSegment","locationSegment","RouterCtx","createContext","RouteDepthCtx","getDefaultLocation","getCurrentLocation","globalLocation","globalNavigate","popstateListenerAttached","location","reactive","updateLocation","newLocation","router","routerContext","context","Route","_props","isFNode","node","Routes","props","currentLocation","navigate","childrenList","routeNodes","otherChildren","routeDefinitions","currentPath","matches","matchedContent","rootMatch","Component","routeKey","jsx","Outlet","depth","state","match","Link","event"],"mappings":"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","file":"router.mjs","sourcesContent":["import { RouteDefinition, RouteMatch } from './types'\n\n// Simple query parser (native URLSearchParams fallback) - internal use only\nfunction parseQuery(search: string): Record<string, string> {\n if (!search) return {}\n if (typeof URLSearchParams !== 'undefined') {\n const params = new URLSearchParams(search)\n const result: Record<string, string> = {}\n params.forEach((value, key) => result[key] = value)\n return result\n }\n return search\n .substring(1)\n .split('&')\n .reduce((accumulator, part) => {\n const [key, value] = part.split('=')\n if (key) accumulator[decodeURIComponent(key)] = decodeURIComponent(value || '')\n return accumulator\n }, {} as Record<string, string>)\n}\n\nfunction isUnsafePath(path: string): boolean {\n // Prevent prototype pollution or massive strings\n if (path.length > 2048) return true\n if (path.includes('__proto__') || path.includes('constructor')) return true\n // Basic XSS check for javascript: protocol\n if (/^\\s*javascript:/i.test(path)) return true\n return false\n}\n\n// Convert children FNodes to RouteDefinitions - internal use only\nfunction createRoutesFromChildren(children: any[]): RouteDefinition[] {\n const routes: RouteDefinition[] = []\n\n children.forEach(child => {\n if (!child) return\n\n // Assuming child is an FNode-like object (config)\n // In Flexium, Route component returns null, but 'createNode' isn't called here.\n // We are traversing the props passed to Router.\n\n const { path, component, children: subChildren, beforeEnter } = child.props || {}\n\n const route: RouteDefinition = {\n path: path || '/',\n component: component,\n beforeEnter\n }\n\n if (subChildren) {\n // If subChildren is array\n const nestedChildren = Array.isArray(subChildren) ? subChildren : [subChildren]\n // We expect the children of a Route to be other Routes\n // However, the 'children' prop in JSX might be the Route components themselves.\n route.children = createRoutesFromChildren(nestedChildren)\n }\n\n // Also check child.children if props.children is empty (direct FNode structure)\n if (!route.children && child.children && child.children.length > 0) {\n route.children = createRoutesFromChildren(child.children)\n }\n\n routes.push(route)\n })\n return routes\n}\n\n// Simple Matcher - internal use only\nfunction matchRoutes(routes: RouteDefinition[], locationPathname: string): RouteMatch[] | null {\n // We want to find the best matching branch\n\n for (const route of routes) {\n // 1. Match current segment\n // Simple exact match or parameter match logic needed?\n // Let's implement simple param matching: /user/:id\n\n const routePath = route.path\n\n const matchResult = matchPath(routePath, locationPathname)\n if (matchResult) {\n return [{ route, params: matchResult.params, pathname: matchResult.path }]\n }\n }\n return null\n}\n\nfunction matchPath(routePath: string, locationPath: string) {\n // 1. Split into segments\n const routeSegments = routePath.split('/').filter(Boolean)\n const locationSegments = locationPath.split('/').filter(Boolean)\n\n if (routeSegments.length !== locationSegments.length) return null\n\n const params: Record<string, string> = {}\n\n for (let i = 0; i < routeSegments.length; i++) {\n const routeSegment = routeSegments[i]\n const locationSegment = locationSegments[i]\n\n if (routeSegment.startsWith(':')) {\n const key = routeSegment.slice(1)\n params[key] = locationSegment\n } else if (routeSegment !== locationSegment) {\n return null\n }\n }\n\n return { params, path: locationPath }\n}\n\n// Export only what's needed by other router files\nexport { parseQuery, isUnsafePath, createRoutesFromChildren, matchRoutes }\n","import { reactive } from '../core/reactive'\nimport { createContext, context } from '../core/context'\nimport type { Location, RouterContext } from './types'\nimport { parseQuery, isUnsafePath } from './utils'\n\n// Contexts\nexport const RouterCtx = createContext<RouterContext>(null as any)\nexport const RouteDepthCtx = createContext<number>(0)\n\n// Helper functions\nconst getDefaultLocation = (): Location => ({\n pathname: '/',\n search: '',\n hash: '',\n query: {},\n})\n\nconst getCurrentLocation = (): Location => {\n if (typeof window === 'undefined') {\n return getDefaultLocation()\n }\n return {\n pathname: window.location.pathname,\n search: window.location.search,\n hash: window.location.hash,\n query: parseQuery(window.location.search),\n }\n}\n\n// Global singleton location state\nlet globalLocation: Location | null = null\nlet globalNavigate: ((path: string) => void) | null = null\nlet popstateListenerAttached = false\n\n// Create location state and navigation (singleton pattern)\nexport function location(): [Location, (path: string) => void] {\n // Return existing singleton if already created\n if (globalLocation && globalNavigate) {\n return [globalLocation, globalNavigate]\n }\n\n // Create a reactive location object (only once)\n globalLocation = reactive<Location>(getCurrentLocation())\n\n const updateLocation = (newLocation: Location) => {\n if (!globalLocation) return\n globalLocation.pathname = newLocation.pathname\n globalLocation.search = newLocation.search\n globalLocation.hash = newLocation.hash\n globalLocation.query = newLocation.query\n }\n\n globalNavigate = (path: string) => {\n if (typeof window === 'undefined') return\n if (isUnsafePath(path)) {\n console.error('[Flexium Router] Blocked navigation to unsafe path:', path)\n return\n }\n window.history.pushState({}, '', path)\n const newLocation = getCurrentLocation()\n updateLocation(newLocation)\n }\n\n // Listen to popstate (only once)\n if (typeof window !== 'undefined' && !popstateListenerAttached) {\n window.addEventListener('popstate', () => {\n updateLocation(getCurrentLocation())\n })\n popstateListenerAttached = true\n }\n\n return [globalLocation, globalNavigate]\n}\n\n// Router hook\nexport function router(): RouterContext {\n const routerContext = context(RouterCtx)\n if (!routerContext) {\n throw new Error('router() must be called within a <Routes> component')\n }\n return routerContext\n}\n","import type { RouteProps } from '../types'\n\nexport function Route(_props: RouteProps) {\n return null\n}\n","import { jsx as f } from '../../jsx-runtime'\nimport type { FNode, FNodeChild } from '../../dom'\nimport { RouterCtx, RouteDepthCtx, location } from '../router'\nimport { createRoutesFromChildren, matchRoutes } from '../utils'\nimport { Route } from './Route'\n\nfunction isFNode(node: any): node is FNode {\n return node && typeof node === 'object' && ('type' in node || Array.isArray(node))\n}\n\nexport function Routes(props: { children: FNodeChild }) {\n const [currentLocation, navigate] = location()\n\n // Parse children to find <Route> definitions and other content\n let childrenList: any[] = Array.isArray(props.children) ? props.children : [props.children]\n\n // Separate routes from other children (like Nav components)\n const routeNodes = childrenList.filter(child => isFNode(child) && child.type === Route)\n const otherChildren = childrenList.filter(child => !isFNode(child) || child.type !== Route)\n\n // Create route definitions\n const routeDefinitions = createRoutesFromChildren(routeNodes)\n\n // DIRECT access to currentLocation.pathname\n // This should trigger reactive tracking in the component's effect context\n const currentPath = currentLocation.pathname\n const matches = matchRoutes(routeDefinitions, currentPath) || []\n const params = matches.length > 0 ? matches[matches.length - 1].params : {}\n\n const routerContext = {\n location: currentLocation,\n navigate,\n matches: matches,\n params: params\n }\n\n // Render matched component\n let matchedContent: FNodeChild = null\n\n if (matches.length > 0) {\n const rootMatch = matches[0]\n const Component = rootMatch.route.component\n\n // Use pathname as key to force re-mount on route change\n const routeKey = currentPath\n\n // Guard Check\n if (rootMatch.route.beforeEnter) {\n const result = rootMatch.route.beforeEnter(rootMatch.params)\n if (result !== false) {\n matchedContent = f(RouteDepthCtx.Provider, {\n value: 1,\n key: routeKey,\n children: f(Component, { params: rootMatch.params, key: routeKey })\n })\n }\n } else {\n matchedContent = f(RouteDepthCtx.Provider, {\n value: 1,\n key: routeKey,\n children: f(Component, { params: rootMatch.params, key: routeKey })\n })\n }\n }\n\n return f(RouterCtx.Provider, {\n value: routerContext,\n children: [...otherChildren, matchedContent]\n })\n}\n","import { state } from '../../core/state'\nimport { context } from '../../core/context'\nimport { jsx as f } from '../../jsx-runtime'\nimport { RouteDepthCtx, router } from '../router'\n\nexport function Outlet() {\n const routerContext = router()\n const depth = (context(RouteDepthCtx) as number) || 0\n\n const [matches] = state(() => routerContext.matches)\n\n if (depth >= matches.length) return null\n\n const match = matches[depth]\n const Component = match.route.component\n\n // Guard\n if (match.route.beforeEnter) {\n if (match.route.beforeEnter(match.params) === false) return null\n }\n\n // Render next level\n return f(RouteDepthCtx.Provider, {\n value: depth + 1,\n children: f(Component, { params: match.params })\n })\n}\n","import { jsx as f } from '../../jsx-runtime'\nimport type { LinkProps } from '../types'\nimport { router } from '../router'\n\nexport function Link(props: LinkProps) {\n const routerContext = router()\n return f('a', {\n href: props.to,\n class: props.class,\n onclick: (event: Event) => {\n event.preventDefault()\n routerContext.navigate(props.to)\n },\n children: props.children\n })\n}\n"]}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { a as SSROptions, b as SSRResult } from './types-CxlS2F2j.cjs';
|
|
2
|
+
export { S as SerializedState } from './types-CxlS2F2j.cjs';
|
|
3
|
+
import { F as FNodeChild } from './types-y2GGaXXk.cjs';
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Render component tree to HTML string with hydration markers
|
|
7
|
+
*/
|
|
8
|
+
declare function renderToString(app: FNodeChild | (() => FNodeChild), options?: SSROptions): SSRResult;
|
|
9
|
+
/**
|
|
10
|
+
* Render component tree to static HTML (no hydration markers)
|
|
11
|
+
* Use for email templates, static pages, etc.
|
|
12
|
+
*/
|
|
13
|
+
declare function renderToStaticMarkup(app: FNodeChild | (() => FNodeChild)): string;
|
|
14
|
+
|
|
15
|
+
declare function getIsServer(): boolean;
|
|
16
|
+
|
|
17
|
+
export { SSROptions, SSRResult, getIsServer, renderToStaticMarkup, renderToString };
|
package/dist/server.d.ts
ADDED
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { a as SSROptions, b as SSRResult } from './types-CxlS2F2j.js';
|
|
2
|
+
export { S as SerializedState } from './types-CxlS2F2j.js';
|
|
3
|
+
import { F as FNodeChild } from './types-y2GGaXXk.js';
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Render component tree to HTML string with hydration markers
|
|
7
|
+
*/
|
|
8
|
+
declare function renderToString(app: FNodeChild | (() => FNodeChild), options?: SSROptions): SSRResult;
|
|
9
|
+
/**
|
|
10
|
+
* Render component tree to static HTML (no hydration markers)
|
|
11
|
+
* Use for email templates, static pages, etc.
|
|
12
|
+
*/
|
|
13
|
+
declare function renderToStaticMarkup(app: FNodeChild | (() => FNodeChild)): string;
|
|
14
|
+
|
|
15
|
+
declare function getIsServer(): boolean;
|
|
16
|
+
|
|
17
|
+
export { SSROptions, SSRResult, getIsServer, renderToStaticMarkup, renderToString };
|
package/dist/server.js
ADDED
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
'use strict';var chunkPSKDIB7J_js=require('./chunk-PSKDIB7J.js'),chunkUWFVCKRU_js=require('./chunk-UWFVCKRU.js');var $={"&":"&","<":"<",">":">",'"':""","'":"'"},F=/[&<>"']/g;function l(e){return String(e).replace(F,r=>$[r])}function a(e){return l(e)}var f=false,d=null,h=0;function I(){return f}function b(){f=true,d=new Map,h=0;}function S(){f=false;let e=Object.fromEntries(d||new Map);return d=null,{states:e}}function x(){return `fid-${h++}`}var T=new Set(["area","base","br","col","embed","hr","img","input","link","meta","param","source","track","wbr"]),v=new Set(["disabled","checked","readonly","required","hidden","selected","autofocus","autoplay","controls","loop","muted","multiple","open","defer","async","novalidate"]),A={className:"class",htmlFor:"for"};function R(e,r={}){let{hydrate:n=true}=r;b();try{let t;typeof e=="function"&&!N(e)?t={type:e,props:{},children:[],key:void 0}:t=e;let o=p(t,n),i=S();return {html:o,state:i}}catch(t){throw S(),t}}function E(e){let{html:r}=R(e,{hydrate:false});return r}function N(e){return e&&typeof e=="object"&&"type"in e&&"props"in e}function p(e,r){if(e==null||typeof e=="boolean")return "";if(typeof e=="string"||typeof e=="number")return l(String(e));if(Array.isArray(e))return e.map(n=>p(n,r)).join("");if(typeof e=="function")return C({type:e,props:{},children:[]},r);if(typeof e=="object"&&N(e)){if(typeof e.type=="string")return w(e,r);if(typeof e.type=="function")return C(e,r)}return ""}function w(e,r){let n=e.type,t=j(e.props,r);if(e.props?.dangerouslySetInnerHTML){let i=e.props.dangerouslySetInnerHTML.__html||"";return `<${n}${t}>${i}</${n}>`}if(T.has(n))return `<${n}${t}>`;let o=(e.children||[]).map(i=>p(i,r)).join("");return `<${n}${t}>${o}</${n}>`}function j(e,r){if(!e)return "";let n=[];if(r){let t=x();n.push(`data-fid="${t}"`);}for(let[t,o]of Object.entries(e)){if(t.startsWith("on")||t==="ref"||t==="key"||t==="children"||t==="dangerouslySetInnerHTML"||o==null)continue;let i=A[t]||t;if(t==="style"&&typeof o=="object"){let c=Object.entries(o).filter(([,s])=>s!=null).map(([s,u])=>`${k(s)}:${u}`).join(";");c&&n.push(`style="${a(c)}"`);continue}if(v.has(i)){o&&n.push(i);continue}o!==false&&n.push(`${i}="${a(String(o))}"`);}return n.length?" "+n.join(" "):""}function C(e,r){let n=e.type,t={...e.props};e.children&&e.children.length>0&&(t.children=e.children.length===1?e.children[0]:e.children);let o=n._contextId,i=o!==void 0,c;i&&(c=chunkPSKDIB7J_js.c(o,t.value));let s={hooks:[],hookIndex:0};try{let u=chunkUWFVCKRU_js.a(s,()=>n(t));return p(u,r)}finally{i&&chunkPSKDIB7J_js.d(o,c);}}function k(e){return e.replace(/([A-Z])/g,"-$1").toLowerCase()}exports.getIsServer=I;exports.renderToStaticMarkup=E;exports.renderToString=R;//# sourceMappingURL=server.js.map
|
|
2
|
+
//# sourceMappingURL=server.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/server/escape.ts","../src/server/serverState.ts","../src/server/renderToString.ts"],"names":["ESCAPE_MAP","ESCAPE_REGEX","escapeHtml","str","char","escapeAttribute","isServerRendering","serverStateCollector","hydrationIdCounter","getIsServer","enterServerRender","exitServerRender","states","generateHydrationId","VOID_ELEMENTS","BOOLEAN_ATTRS","ATTR_ALIASES","renderToString","app","options","hydrate","fnode","isFNode","html","renderNodeToString","state","error","renderToStaticMarkup","value","includeHydrationMarkers","child","renderComponentToString","renderElementToString","tag","attrs","renderAttributes","innerHTML","childrenHtml","props","parts","fid","key","attrName","styleStr","v","k","kebabCase","Component","contextId","isProvider","prevContextValue","pushContext","instance","result","runWithComponent","popContext"],"mappings":"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","file":"server.js","sourcesContent":["const ESCAPE_MAP: Record<string, string> = {\n '&': '&',\n '<': '<',\n '>': '>',\n '\"': '"',\n \"'\": '''\n}\n\nconst ESCAPE_REGEX = /[&<>\"']/g\n\nexport function escapeHtml(str: string): string {\n return String(str).replace(ESCAPE_REGEX, char => ESCAPE_MAP[char])\n}\n\nexport function escapeAttribute(str: string): string {\n return escapeHtml(str)\n}\n","import type { SerializedState } from './types'\n\nlet isServerRendering = false\nlet serverStateCollector: Map<string, unknown> | null = null\nlet hydrationIdCounter = 0\n\nexport function getIsServer(): boolean {\n return isServerRendering\n}\n\nexport function enterServerRender(): void {\n isServerRendering = true\n serverStateCollector = new Map()\n hydrationIdCounter = 0\n}\n\nexport function exitServerRender(): SerializedState {\n isServerRendering = false\n const states = Object.fromEntries(serverStateCollector || new Map())\n serverStateCollector = null\n\n return { states }\n}\n\nexport function collectServerState(key: string, value: unknown): void {\n if (serverStateCollector) {\n serverStateCollector.set(key, value)\n }\n}\n\nexport function generateHydrationId(): string {\n return `fid-${hydrationIdCounter++}`\n}\n\nexport function resetHydrationIdCounter(): void {\n hydrationIdCounter = 0\n}\n","import type { FNode, FNodeChild } from '../dom/types'\nimport type { SSROptions, SSRResult } from './types'\nimport { escapeHtml, escapeAttribute } from './escape'\nimport {\n enterServerRender,\n exitServerRender,\n generateHydrationId\n} from './serverState'\nimport { runWithComponent, ComponentInstance } from '../core/hook'\nimport { pushContext, popContext } from '../core/context'\n\n// Self-closing HTML tags\nconst VOID_ELEMENTS = new Set([\n 'area', 'base', 'br', 'col', 'embed', 'hr', 'img', 'input',\n 'link', 'meta', 'param', 'source', 'track', 'wbr'\n])\n\n// Attributes that should be rendered as boolean\nconst BOOLEAN_ATTRS = new Set([\n 'disabled', 'checked', 'readonly', 'required', 'hidden',\n 'selected', 'autofocus', 'autoplay', 'controls', 'loop', 'muted',\n 'multiple', 'open', 'defer', 'async', 'novalidate'\n])\n\n// Attributes that need special handling\nconst ATTR_ALIASES: Record<string, string> = {\n className: 'class',\n htmlFor: 'for'\n}\n\n/**\n * Render component tree to HTML string with hydration markers\n */\nexport function renderToString(\n app: FNodeChild | (() => FNodeChild),\n options: SSROptions = {}\n): SSRResult {\n const { hydrate = true } = options\n\n enterServerRender()\n\n try {\n // Normalize input - wrap function in FNode if needed\n let fnode: FNodeChild\n if (typeof app === 'function' && !isFNode(app)) {\n fnode = { type: app, props: {}, children: [], key: undefined }\n } else {\n fnode = app\n }\n\n const html = renderNodeToString(fnode, hydrate)\n const state = exitServerRender()\n\n return { html, state }\n } catch (error) {\n exitServerRender()\n throw error\n }\n}\n\n/**\n * Render component tree to static HTML (no hydration markers)\n * Use for email templates, static pages, etc.\n */\nexport function renderToStaticMarkup(app: FNodeChild | (() => FNodeChild)): string {\n const { html } = renderToString(app, { hydrate: false })\n return html\n}\n\nfunction isFNode(value: any): value is FNode {\n return value && typeof value === 'object' && 'type' in value && 'props' in value\n}\n\nfunction renderNodeToString(fnode: FNodeChild, includeHydrationMarkers: boolean): string {\n // Null/undefined/boolean -> empty string\n if (fnode === null || fnode === undefined || typeof fnode === 'boolean') {\n return ''\n }\n\n // String/number -> escaped text\n if (typeof fnode === 'string' || typeof fnode === 'number') {\n return escapeHtml(String(fnode))\n }\n\n // Array -> concatenate children\n if (Array.isArray(fnode)) {\n return fnode.map(child => renderNodeToString(child, includeHydrationMarkers)).join('')\n }\n\n // Function (standalone) -> wrap in FNode and render\n if (typeof fnode === 'function') {\n const wrappedFnode: FNode = { type: fnode, props: {}, children: [], key: undefined }\n return renderComponentToString(wrappedFnode, includeHydrationMarkers)\n }\n\n // Object (FNode)\n if (typeof fnode === 'object' && isFNode(fnode)) {\n // HTML element\n if (typeof fnode.type === 'string') {\n return renderElementToString(fnode, includeHydrationMarkers)\n }\n\n // Function component\n if (typeof fnode.type === 'function') {\n return renderComponentToString(fnode, includeHydrationMarkers)\n }\n }\n\n return ''\n}\n\nfunction renderElementToString(fnode: FNode, includeHydrationMarkers: boolean): string {\n const tag = fnode.type as string\n const attrs = renderAttributes(fnode.props, includeHydrationMarkers)\n\n // Handle dangerouslySetInnerHTML\n if (fnode.props?.dangerouslySetInnerHTML) {\n const innerHTML = fnode.props.dangerouslySetInnerHTML.__html || ''\n return `<${tag}${attrs}>${innerHTML}</${tag}>`\n }\n\n // Void elements (self-closing)\n if (VOID_ELEMENTS.has(tag)) {\n return `<${tag}${attrs}>`\n }\n\n // Render children\n const childrenHtml = (fnode.children || [])\n .map(child => renderNodeToString(child, includeHydrationMarkers))\n .join('')\n\n return `<${tag}${attrs}>${childrenHtml}</${tag}>`\n}\n\nfunction renderAttributes(props: Record<string, any>, includeHydrationMarkers: boolean): string {\n if (!props) return ''\n\n const parts: string[] = []\n\n // Add hydration ID if needed\n if (includeHydrationMarkers) {\n const fid = generateHydrationId()\n parts.push(`data-fid=\"${fid}\"`)\n }\n\n for (const [key, value] of Object.entries(props)) {\n // Skip event handlers, refs, and internal props\n if (key.startsWith('on') || key === 'ref' || key === 'key' || key === 'children') continue\n if (key === 'dangerouslySetInnerHTML') continue\n\n // Skip undefined/null values\n if (value === undefined || value === null) continue\n\n // Handle aliased attributes\n const attrName = ATTR_ALIASES[key] || key\n\n // Handle style object\n if (key === 'style' && typeof value === 'object') {\n const styleStr = Object.entries(value)\n .filter(([, v]) => v !== null && v !== undefined)\n .map(([k, v]) => `${kebabCase(k)}:${v}`)\n .join(';')\n if (styleStr) {\n parts.push(`style=\"${escapeAttribute(styleStr)}\"`)\n }\n continue\n }\n\n // Handle boolean attributes\n if (BOOLEAN_ATTRS.has(attrName)) {\n if (value) parts.push(attrName)\n continue\n }\n\n // Handle false boolean values - skip entirely\n if (value === false) continue\n\n // Regular attribute\n parts.push(`${attrName}=\"${escapeAttribute(String(value))}\"`)\n }\n\n return parts.length ? ' ' + parts.join(' ') : ''\n}\n\nfunction renderComponentToString(fnode: FNode, includeHydrationMarkers: boolean): string {\n const Component = fnode.type as Function\n\n // Merge props with children\n const props = { ...fnode.props }\n if (fnode.children && fnode.children.length > 0) {\n props.children = fnode.children.length === 1\n ? fnode.children[0]\n : fnode.children\n }\n\n // Check if this is a Context Provider\n const contextId = (Component as any)._contextId\n const isProvider = contextId !== undefined\n let prevContextValue: any\n\n if (isProvider) {\n prevContextValue = pushContext(contextId, props.value)\n }\n\n // Create minimal component instance for server (hooks support)\n const instance: ComponentInstance = {\n hooks: [],\n hookIndex: 0\n }\n\n try {\n // Run component with hook context\n const result = runWithComponent(instance, () => Component(props))\n\n // Render result\n return renderNodeToString(result, includeHydrationMarkers)\n } finally {\n // Restore context if it was a provider\n if (isProvider) {\n popContext(contextId, prevContextValue)\n }\n }\n}\n\nfunction kebabCase(str: string): string {\n return str.replace(/([A-Z])/g, '-$1').toLowerCase()\n}\n"]}
|
package/dist/server.mjs
ADDED
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
import {c,d as d$1}from'./chunk-3DKZ2J4D.mjs';import {a as a$1}from'./chunk-5PNH2ARD.mjs';var $={"&":"&","<":"<",">":">",'"':""","'":"'"},F=/[&<>"']/g;function l(e){return String(e).replace(F,r=>$[r])}function a(e){return l(e)}var f=false,d=null,h=0;function I(){return f}function b(){f=true,d=new Map,h=0;}function S(){f=false;let e=Object.fromEntries(d||new Map);return d=null,{states:e}}function x(){return `fid-${h++}`}var T=new Set(["area","base","br","col","embed","hr","img","input","link","meta","param","source","track","wbr"]),v=new Set(["disabled","checked","readonly","required","hidden","selected","autofocus","autoplay","controls","loop","muted","multiple","open","defer","async","novalidate"]),A={className:"class",htmlFor:"for"};function R(e,r={}){let{hydrate:n=true}=r;b();try{let t;typeof e=="function"&&!N(e)?t={type:e,props:{},children:[],key:void 0}:t=e;let o=p(t,n),i=S();return {html:o,state:i}}catch(t){throw S(),t}}function E(e){let{html:r}=R(e,{hydrate:false});return r}function N(e){return e&&typeof e=="object"&&"type"in e&&"props"in e}function p(e,r){if(e==null||typeof e=="boolean")return "";if(typeof e=="string"||typeof e=="number")return l(String(e));if(Array.isArray(e))return e.map(n=>p(n,r)).join("");if(typeof e=="function")return C({type:e,props:{},children:[]},r);if(typeof e=="object"&&N(e)){if(typeof e.type=="string")return w(e,r);if(typeof e.type=="function")return C(e,r)}return ""}function w(e,r){let n=e.type,t=j(e.props,r);if(e.props?.dangerouslySetInnerHTML){let i=e.props.dangerouslySetInnerHTML.__html||"";return `<${n}${t}>${i}</${n}>`}if(T.has(n))return `<${n}${t}>`;let o=(e.children||[]).map(i=>p(i,r)).join("");return `<${n}${t}>${o}</${n}>`}function j(e,r){if(!e)return "";let n=[];if(r){let t=x();n.push(`data-fid="${t}"`);}for(let[t,o]of Object.entries(e)){if(t.startsWith("on")||t==="ref"||t==="key"||t==="children"||t==="dangerouslySetInnerHTML"||o==null)continue;let i=A[t]||t;if(t==="style"&&typeof o=="object"){let c=Object.entries(o).filter(([,s])=>s!=null).map(([s,u])=>`${k(s)}:${u}`).join(";");c&&n.push(`style="${a(c)}"`);continue}if(v.has(i)){o&&n.push(i);continue}o!==false&&n.push(`${i}="${a(String(o))}"`);}return n.length?" "+n.join(" "):""}function C(e,r){let n=e.type,t={...e.props};e.children&&e.children.length>0&&(t.children=e.children.length===1?e.children[0]:e.children);let o=n._contextId,i=o!==void 0,c$1;i&&(c$1=c(o,t.value));let s={hooks:[],hookIndex:0};try{let u=a$1(s,()=>n(t));return p(u,r)}finally{i&&d$1(o,c$1);}}function k(e){return e.replace(/([A-Z])/g,"-$1").toLowerCase()}export{I as getIsServer,E as renderToStaticMarkup,R as renderToString};//# sourceMappingURL=server.mjs.map
|
|
2
|
+
//# sourceMappingURL=server.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/server/escape.ts","../src/server/serverState.ts","../src/server/renderToString.ts"],"names":["ESCAPE_MAP","ESCAPE_REGEX","escapeHtml","str","char","escapeAttribute","isServerRendering","serverStateCollector","hydrationIdCounter","getIsServer","enterServerRender","exitServerRender","states","generateHydrationId","VOID_ELEMENTS","BOOLEAN_ATTRS","ATTR_ALIASES","renderToString","app","options","hydrate","fnode","isFNode","html","renderNodeToString","state","error","renderToStaticMarkup","value","includeHydrationMarkers","child","renderComponentToString","renderElementToString","tag","attrs","renderAttributes","innerHTML","childrenHtml","props","parts","fid","key","attrName","styleStr","v","k","kebabCase","Component","contextId","isProvider","prevContextValue","pushContext","instance","result","runWithComponent","popContext"],"mappings":"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","file":"server.mjs","sourcesContent":["const ESCAPE_MAP: Record<string, string> = {\n '&': '&',\n '<': '<',\n '>': '>',\n '\"': '"',\n \"'\": '''\n}\n\nconst ESCAPE_REGEX = /[&<>\"']/g\n\nexport function escapeHtml(str: string): string {\n return String(str).replace(ESCAPE_REGEX, char => ESCAPE_MAP[char])\n}\n\nexport function escapeAttribute(str: string): string {\n return escapeHtml(str)\n}\n","import type { SerializedState } from './types'\n\nlet isServerRendering = false\nlet serverStateCollector: Map<string, unknown> | null = null\nlet hydrationIdCounter = 0\n\nexport function getIsServer(): boolean {\n return isServerRendering\n}\n\nexport function enterServerRender(): void {\n isServerRendering = true\n serverStateCollector = new Map()\n hydrationIdCounter = 0\n}\n\nexport function exitServerRender(): SerializedState {\n isServerRendering = false\n const states = Object.fromEntries(serverStateCollector || new Map())\n serverStateCollector = null\n\n return { states }\n}\n\nexport function collectServerState(key: string, value: unknown): void {\n if (serverStateCollector) {\n serverStateCollector.set(key, value)\n }\n}\n\nexport function generateHydrationId(): string {\n return `fid-${hydrationIdCounter++}`\n}\n\nexport function resetHydrationIdCounter(): void {\n hydrationIdCounter = 0\n}\n","import type { FNode, FNodeChild } from '../dom/types'\nimport type { SSROptions, SSRResult } from './types'\nimport { escapeHtml, escapeAttribute } from './escape'\nimport {\n enterServerRender,\n exitServerRender,\n generateHydrationId\n} from './serverState'\nimport { runWithComponent, ComponentInstance } from '../core/hook'\nimport { pushContext, popContext } from '../core/context'\n\n// Self-closing HTML tags\nconst VOID_ELEMENTS = new Set([\n 'area', 'base', 'br', 'col', 'embed', 'hr', 'img', 'input',\n 'link', 'meta', 'param', 'source', 'track', 'wbr'\n])\n\n// Attributes that should be rendered as boolean\nconst BOOLEAN_ATTRS = new Set([\n 'disabled', 'checked', 'readonly', 'required', 'hidden',\n 'selected', 'autofocus', 'autoplay', 'controls', 'loop', 'muted',\n 'multiple', 'open', 'defer', 'async', 'novalidate'\n])\n\n// Attributes that need special handling\nconst ATTR_ALIASES: Record<string, string> = {\n className: 'class',\n htmlFor: 'for'\n}\n\n/**\n * Render component tree to HTML string with hydration markers\n */\nexport function renderToString(\n app: FNodeChild | (() => FNodeChild),\n options: SSROptions = {}\n): SSRResult {\n const { hydrate = true } = options\n\n enterServerRender()\n\n try {\n // Normalize input - wrap function in FNode if needed\n let fnode: FNodeChild\n if (typeof app === 'function' && !isFNode(app)) {\n fnode = { type: app, props: {}, children: [], key: undefined }\n } else {\n fnode = app\n }\n\n const html = renderNodeToString(fnode, hydrate)\n const state = exitServerRender()\n\n return { html, state }\n } catch (error) {\n exitServerRender()\n throw error\n }\n}\n\n/**\n * Render component tree to static HTML (no hydration markers)\n * Use for email templates, static pages, etc.\n */\nexport function renderToStaticMarkup(app: FNodeChild | (() => FNodeChild)): string {\n const { html } = renderToString(app, { hydrate: false })\n return html\n}\n\nfunction isFNode(value: any): value is FNode {\n return value && typeof value === 'object' && 'type' in value && 'props' in value\n}\n\nfunction renderNodeToString(fnode: FNodeChild, includeHydrationMarkers: boolean): string {\n // Null/undefined/boolean -> empty string\n if (fnode === null || fnode === undefined || typeof fnode === 'boolean') {\n return ''\n }\n\n // String/number -> escaped text\n if (typeof fnode === 'string' || typeof fnode === 'number') {\n return escapeHtml(String(fnode))\n }\n\n // Array -> concatenate children\n if (Array.isArray(fnode)) {\n return fnode.map(child => renderNodeToString(child, includeHydrationMarkers)).join('')\n }\n\n // Function (standalone) -> wrap in FNode and render\n if (typeof fnode === 'function') {\n const wrappedFnode: FNode = { type: fnode, props: {}, children: [], key: undefined }\n return renderComponentToString(wrappedFnode, includeHydrationMarkers)\n }\n\n // Object (FNode)\n if (typeof fnode === 'object' && isFNode(fnode)) {\n // HTML element\n if (typeof fnode.type === 'string') {\n return renderElementToString(fnode, includeHydrationMarkers)\n }\n\n // Function component\n if (typeof fnode.type === 'function') {\n return renderComponentToString(fnode, includeHydrationMarkers)\n }\n }\n\n return ''\n}\n\nfunction renderElementToString(fnode: FNode, includeHydrationMarkers: boolean): string {\n const tag = fnode.type as string\n const attrs = renderAttributes(fnode.props, includeHydrationMarkers)\n\n // Handle dangerouslySetInnerHTML\n if (fnode.props?.dangerouslySetInnerHTML) {\n const innerHTML = fnode.props.dangerouslySetInnerHTML.__html || ''\n return `<${tag}${attrs}>${innerHTML}</${tag}>`\n }\n\n // Void elements (self-closing)\n if (VOID_ELEMENTS.has(tag)) {\n return `<${tag}${attrs}>`\n }\n\n // Render children\n const childrenHtml = (fnode.children || [])\n .map(child => renderNodeToString(child, includeHydrationMarkers))\n .join('')\n\n return `<${tag}${attrs}>${childrenHtml}</${tag}>`\n}\n\nfunction renderAttributes(props: Record<string, any>, includeHydrationMarkers: boolean): string {\n if (!props) return ''\n\n const parts: string[] = []\n\n // Add hydration ID if needed\n if (includeHydrationMarkers) {\n const fid = generateHydrationId()\n parts.push(`data-fid=\"${fid}\"`)\n }\n\n for (const [key, value] of Object.entries(props)) {\n // Skip event handlers, refs, and internal props\n if (key.startsWith('on') || key === 'ref' || key === 'key' || key === 'children') continue\n if (key === 'dangerouslySetInnerHTML') continue\n\n // Skip undefined/null values\n if (value === undefined || value === null) continue\n\n // Handle aliased attributes\n const attrName = ATTR_ALIASES[key] || key\n\n // Handle style object\n if (key === 'style' && typeof value === 'object') {\n const styleStr = Object.entries(value)\n .filter(([, v]) => v !== null && v !== undefined)\n .map(([k, v]) => `${kebabCase(k)}:${v}`)\n .join(';')\n if (styleStr) {\n parts.push(`style=\"${escapeAttribute(styleStr)}\"`)\n }\n continue\n }\n\n // Handle boolean attributes\n if (BOOLEAN_ATTRS.has(attrName)) {\n if (value) parts.push(attrName)\n continue\n }\n\n // Handle false boolean values - skip entirely\n if (value === false) continue\n\n // Regular attribute\n parts.push(`${attrName}=\"${escapeAttribute(String(value))}\"`)\n }\n\n return parts.length ? ' ' + parts.join(' ') : ''\n}\n\nfunction renderComponentToString(fnode: FNode, includeHydrationMarkers: boolean): string {\n const Component = fnode.type as Function\n\n // Merge props with children\n const props = { ...fnode.props }\n if (fnode.children && fnode.children.length > 0) {\n props.children = fnode.children.length === 1\n ? fnode.children[0]\n : fnode.children\n }\n\n // Check if this is a Context Provider\n const contextId = (Component as any)._contextId\n const isProvider = contextId !== undefined\n let prevContextValue: any\n\n if (isProvider) {\n prevContextValue = pushContext(contextId, props.value)\n }\n\n // Create minimal component instance for server (hooks support)\n const instance: ComponentInstance = {\n hooks: [],\n hookIndex: 0\n }\n\n try {\n // Run component with hook context\n const result = runWithComponent(instance, () => Component(props))\n\n // Render result\n return renderNodeToString(result, includeHydrationMarkers)\n } finally {\n // Restore context if it was a provider\n if (isProvider) {\n popContext(contextId, prevContextValue)\n }\n }\n}\n\nfunction kebabCase(str: string): string {\n return str.replace(/([A-Z])/g, '-$1').toLowerCase()\n}\n"]}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
interface SSROptions {
|
|
2
|
+
/**
|
|
3
|
+
* Whether to include hydration markers (data-fid attributes)
|
|
4
|
+
* @default true
|
|
5
|
+
*/
|
|
6
|
+
hydrate?: boolean;
|
|
7
|
+
}
|
|
8
|
+
interface SSRResult {
|
|
9
|
+
/** Generated HTML string */
|
|
10
|
+
html: string;
|
|
11
|
+
/** State snapshot for hydration transfer */
|
|
12
|
+
state: SerializedState;
|
|
13
|
+
}
|
|
14
|
+
interface SerializedState {
|
|
15
|
+
/** Map of serialized key -> value for keyed states */
|
|
16
|
+
states: Record<string, unknown>;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
export type { SerializedState as S, SSROptions as a, SSRResult as b };
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
interface SSROptions {
|
|
2
|
+
/**
|
|
3
|
+
* Whether to include hydration markers (data-fid attributes)
|
|
4
|
+
* @default true
|
|
5
|
+
*/
|
|
6
|
+
hydrate?: boolean;
|
|
7
|
+
}
|
|
8
|
+
interface SSRResult {
|
|
9
|
+
/** Generated HTML string */
|
|
10
|
+
html: string;
|
|
11
|
+
/** State snapshot for hydration transfer */
|
|
12
|
+
state: SerializedState;
|
|
13
|
+
}
|
|
14
|
+
interface SerializedState {
|
|
15
|
+
/** Map of serialized key -> value for keyed states */
|
|
16
|
+
states: Record<string, unknown>;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
export type { SerializedState as S, SSROptions as a, SSRResult as b };
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
type FNodeChild = FNode | string | number | boolean | null | undefined | FNodeChild[] | (() => FNode);
|
|
2
|
+
interface FNode {
|
|
3
|
+
type: string | Function;
|
|
4
|
+
props: Record<string, any>;
|
|
5
|
+
children: FNodeChild[];
|
|
6
|
+
key?: any;
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
export type { FNodeChild as F, FNode as a };
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
type FNodeChild = FNode | string | number | boolean | null | undefined | FNodeChild[] | (() => FNode);
|
|
2
|
+
interface FNode {
|
|
3
|
+
type: string | Function;
|
|
4
|
+
props: Record<string, any>;
|
|
5
|
+
children: FNodeChild[];
|
|
6
|
+
key?: any;
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
export type { FNodeChild as F, FNode as a };
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "flexium",
|
|
3
|
-
"version": "0.12.
|
|
3
|
+
"version": "0.12.17",
|
|
4
4
|
"description": "A lightweight, signals-based UI framework with cross-platform renderers",
|
|
5
5
|
"publishConfig": {
|
|
6
6
|
"access": "public"
|
|
@@ -30,6 +30,11 @@
|
|
|
30
30
|
"import": "./dist/router.mjs",
|
|
31
31
|
"require": "./dist/router.js"
|
|
32
32
|
},
|
|
33
|
+
"./server": {
|
|
34
|
+
"types": "./dist/server.d.ts",
|
|
35
|
+
"import": "./dist/server.mjs",
|
|
36
|
+
"require": "./dist/server.js"
|
|
37
|
+
},
|
|
33
38
|
"./jsx-runtime": {
|
|
34
39
|
"types": "./dist/jsx-runtime.d.ts",
|
|
35
40
|
"import": "./dist/jsx-runtime.mjs",
|
package/dist/chunk-44RZHCII.mjs
DELETED
|
@@ -1,2 +0,0 @@
|
|
|
1
|
-
var o,r=class{constructor(t,n){this.fn=t;this.scheduler=n;this.deps=[];this.active=true;}run(){if(!this.active)return this.fn();let t=o;try{return this.cleanup(),o=this,this.fn()}finally{o=t;}}stop(){this.active&&(this.cleanup(),this.active=false);}cleanup(){let{deps:t}=this;if(t.length){for(let n=0;n<t.length;n++)t[n].delete(this);t.length=0;}}};function p(e,t={}){let n=new r(e,t.scheduler);n.run();let c=n.run.bind(n);return c.effect=n,c}function d(e){o&&(e.add(o),o.deps.push(e));}var i=new Set,s=false,a=false;function l(e){i.has(e)||(i.add(e),!s&&!a&&(s=true,Promise.resolve().then(h)));}function h(){s=false;let e=[...i];i.clear();for(let t of e)t.active&&t.run();}function v(e){a=e;}function x(e){let t=[...e];for(let n of t)n!==o&&(n.scheduler?n.scheduler():l(n));}var f=null;function g(e,t){let n=f;f=e,e.hookIndex=0;try{return t()}finally{f=n;}}function k(e){if(!f)return e();let t=f,{hooks:n,hookIndex:c}=t;if(c<n.length)return t.hookIndex++,n[c];let u=e();return n.push(u),t.hookIndex++,u}export{o as a,p as b,d as c,h as d,v as e,x as f,g,k as h};//# sourceMappingURL=chunk-44RZHCII.mjs.map
|
|
2
|
-
//# sourceMappingURL=chunk-44RZHCII.mjs.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/core/effect.ts","../src/core/hook.ts"],"names":["activeEffect","ReactiveEffectLike","fn","scheduler","parent","deps","i","unsafeEffect","options","_effect","runner","trackEffect","dep","queue","isFlushPending","isBatching","queueJob","effect","flush","effects","setBatching","value","triggerEffects","currentComponent","runWithComponent","component","prev","hook","factory","instance","hooks","hookIndex"],"mappings":"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","file":"chunk-44RZHCII.mjs","sourcesContent":["export let activeEffect: ReactiveEffect | undefined\n\nexport class ReactiveEffectLike {\n deps: Set<any>[] = []\n active = true\n\n constructor(\n public fn: () => void,\n public scheduler?: () => void\n ) { }\n\n run() {\n if (!this.active) {\n return this.fn()\n }\n\n let parent: ReactiveEffect | undefined = activeEffect\n try {\n this.cleanup()\n activeEffect = this\n return this.fn()\n } finally {\n activeEffect = parent\n }\n }\n\n stop() {\n if (this.active) {\n this.cleanup()\n this.active = false\n }\n }\n\n cleanup() {\n const { deps } = this\n if (deps.length) {\n for (let i = 0; i < deps.length; i++) {\n deps[i].delete(this)\n }\n deps.length = 0\n }\n }\n}\n\nexport type ReactiveEffect = ReactiveEffectLike\n\nexport function unsafeEffect(fn: () => void, options: { scheduler?: () => void } = {}) {\n const _effect = new ReactiveEffectLike(fn, options.scheduler)\n _effect.run()\n\n const runner: any = _effect.run.bind(_effect)\n runner.effect = _effect\n return runner\n}\n\nexport function trackEffect(dep: Set<ReactiveEffect>) {\n if (activeEffect) {\n dep.add(activeEffect)\n activeEffect.deps.push(dep)\n }\n}\n\nconst queue = new Set<ReactiveEffect>()\nlet isFlushPending = false\nlet isBatching = false\n\nexport function queueJob(effect: ReactiveEffect) {\n if (!queue.has(effect)) {\n queue.add(effect)\n if (!isFlushPending && !isBatching) {\n isFlushPending = true\n Promise.resolve().then(flush)\n }\n }\n}\n\nexport function flush() {\n isFlushPending = false\n const effects = [...queue]\n queue.clear()\n for (const effect of effects) {\n if (effect.active) {\n effect.run()\n }\n }\n}\n\nexport function setBatching(value: boolean) {\n isBatching = value\n}\n\nexport function triggerEffects(dep: Set<ReactiveEffect>) {\n const effects = [...dep]\n for (const effect of effects) {\n if (effect !== activeEffect) {\n if (effect.scheduler) {\n effect.scheduler()\n } else {\n queueJob(effect)\n }\n }\n }\n}\n","\nexport interface ComponentInstance {\n hooks: any[]\n hookIndex: number\n}\n\nlet currentComponent: ComponentInstance | null = null\n\nexport function getComponent(): ComponentInstance | null {\n return currentComponent\n}\n\nexport function runWithComponent<T>(component: ComponentInstance, fn: () => T): T {\n const prev = currentComponent\n currentComponent = component\n component.hookIndex = 0\n try {\n return fn()\n } finally {\n currentComponent = prev\n }\n}\n\nexport function hook<T>(factory: () => T): T {\n if (!currentComponent) {\n // Outside component: just run factory\n return factory()\n }\n\n const instance = currentComponent\n const { hooks, hookIndex } = instance\n\n if (hookIndex < hooks.length) {\n // Return existing hook\n instance.hookIndex++\n return hooks[hookIndex] as T\n }\n\n // Create new hook\n const value = factory()\n hooks.push(value)\n instance.hookIndex++\n\n return value\n}\n"]}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/core/reactive.ts"],"names":["REACTIVE_SIGNAL","targetMap","reactiveMap","reactive","target","existingProxy","proxy","key","receiver","res","track","value","oldValue","result","hasChanged","trigger","activeEffect","depsMap","dep","trackEffect","triggerEffects","isReactive"],"mappings":"iEAEO,IAAMA,CAAAA,CAAkB,OAAO,kBAAkB,CAAA,CAIlDC,EAAY,IAAI,OAAA,CAGhBC,EAAc,IAAI,OAAA,CAEjB,SAASC,CAAAA,CAA2BC,CAAAA,CAAc,CACrD,GAAIA,CAAAA,EAAWA,EAAeJ,CAAe,CAAA,CACzC,OAAOI,CAAAA,CAGX,IAAMC,CAAAA,CAAgBH,EAAY,GAAA,CAAIE,CAAM,EAC5C,GAAIC,CAAAA,CACA,OAAOA,CAAAA,CAGX,IAAMC,CAAAA,CAAQ,IAAI,KAAA,CAAMF,CAAAA,CAAQ,CAC5B,GAAA,CAAIA,CAAAA,CAAQG,EAAKC,CAAAA,CAAU,CACvB,GAAID,CAAAA,GAAQP,CAAAA,CAAiB,OAAO,KAAA,CAEpC,IAAMS,CAAAA,CAAM,QAAQ,GAAA,CAAIL,CAAAA,CAAQG,EAAKC,CAAQ,CAAA,CAI7C,OAFAE,CAAAA,CAAMN,CAAAA,CAAQG,CAAG,CAAA,CAEbE,CAAAA,GAAQ,MAAQ,OAAOA,CAAAA,EAAQ,SACxBN,CAAAA,CAASM,CAAG,EAGhBA,CACX,CAAA,CACA,GAAA,CAAIL,CAAAA,CAAQG,CAAAA,CAAKI,CAAAA,CAAOH,EAAU,CAC9B,IAAMI,EAAYR,CAAAA,CAAeG,CAAG,EAC9BM,CAAAA,CAAS,OAAA,CAAQ,GAAA,CAAIT,CAAAA,CAAQG,CAAAA,CAAKI,CAAAA,CAAOH,CAAQ,CAAA,CAEvD,OAAIK,GAAUC,CAAAA,CAAWH,CAAAA,CAAOC,CAAQ,CAAA,EACpCG,CAAAA,CAAQX,CAAAA,CAAQG,CAAG,CAAA,CAGhBM,CACX,CACJ,CAAC,CAAA,CAED,OAAAX,CAAAA,CAAY,GAAA,CAAIE,EAAQE,CAAK,CAAA,CACtBA,CACX,CAEO,SAASI,EAAMN,CAAAA,CAAgBG,CAAAA,CAAc,CAChD,GAAI,CAACS,mBAAc,OAEnB,IAAIC,CAAAA,CAAUhB,CAAAA,CAAU,GAAA,CAAIG,CAAM,EAC7Ba,CAAAA,EACDhB,CAAAA,CAAU,IAAIG,CAAAA,CAASa,CAAAA,CAAU,IAAI,GAAM,CAAA,CAG/C,IAAIC,CAAAA,CAAMD,CAAAA,CAAQ,GAAA,CAAIV,CAAG,CAAA,CACpBW,CAAAA,EACDD,EAAQ,GAAA,CAAIV,CAAAA,CAAMW,EAAM,IAAI,GAAM,CAAA,CAGtCC,kBAAAA,CAAYD,CAAG,EACnB,CAEO,SAASH,CAAAA,CAAQX,EAAgBG,CAAAA,CAAc,CAClD,IAAMU,CAAAA,CAAUhB,CAAAA,CAAU,GAAA,CAAIG,CAAM,CAAA,CACpC,GAAI,CAACa,CAAAA,CAAS,OAEd,IAAMC,CAAAA,CAAMD,CAAAA,CAAQ,IAAIV,CAAG,CAAA,CACvBW,CAAAA,EACAE,kBAAAA,CAAeF,CAAG,EAE1B,CAEA,SAASJ,CAAAA,CAAWH,EAAYC,CAAAA,CAAwB,CACpD,OAAO,CAAC,MAAA,CAAO,EAAA,CAAGD,CAAAA,CAAOC,CAAQ,CACrC,CAEO,SAASS,CAAAA,CAAWV,EAAyB,CAChD,OAAO,CAAC,EAAEA,CAAAA,EAAUA,CAAAA,CAAcX,CAAe,CAAA,CACrD","file":"chunk-7BXR4ZFD.js","sourcesContent":["import { activeEffect, trackEffect, triggerEffects } from './effect'\n\nexport const REACTIVE_SIGNAL = Symbol('flexium.reactive')\n\ntype Dep = Set<any>\ntype KeyToDepMap = Map<any, Dep>\nconst targetMap = new WeakMap<any, KeyToDepMap>()\n\n// WeakMap to store existing proxies to avoid duplicates\nconst reactiveMap = new WeakMap<object, any>()\n\nexport function reactive<T extends object>(target: T): T {\n if (target && (target as any)[REACTIVE_SIGNAL]) {\n return target\n }\n\n const existingProxy = reactiveMap.get(target)\n if (existingProxy) {\n return existingProxy\n }\n\n const proxy = new Proxy(target, {\n get(target, key, receiver) {\n if (key === REACTIVE_SIGNAL) return true\n\n const res = Reflect.get(target, key, receiver)\n\n track(target, key)\n\n if (res !== null && typeof res === 'object') {\n return reactive(res)\n }\n\n return res\n },\n set(target, key, value, receiver) {\n const oldValue = (target as any)[key]\n const result = Reflect.set(target, key, value, receiver)\n\n if (result && hasChanged(value, oldValue)) {\n trigger(target, key)\n }\n\n return result\n }\n })\n\n reactiveMap.set(target, proxy)\n return proxy\n}\n\nexport function track(target: object, key: unknown) {\n if (!activeEffect) return\n\n let depsMap = targetMap.get(target)\n if (!depsMap) {\n targetMap.set(target, (depsMap = new Map()))\n }\n\n let dep = depsMap.get(key)\n if (!dep) {\n depsMap.set(key, (dep = new Set()))\n }\n\n trackEffect(dep)\n}\n\nexport function trigger(target: object, key: unknown) {\n const depsMap = targetMap.get(target)\n if (!depsMap) return\n\n const dep = depsMap.get(key)\n if (dep) {\n triggerEffects(dep)\n }\n}\n\nfunction hasChanged(value: any, oldValue: any): boolean {\n return !Object.is(value, oldValue)\n}\n\nexport function isReactive(value: unknown): boolean {\n return !!(value && (value as any)[REACTIVE_SIGNAL])\n}\n"]}
|
package/dist/chunk-APAMPY43.js
DELETED
|
@@ -1,2 +0,0 @@
|
|
|
1
|
-
'use strict';var chunk7BXR4ZFD_js=require('./chunk-7BXR4ZFD.js'),chunkENWGYQNU_js=require('./chunk-ENWGYQNU.js');var y=new Map;function h(o){return JSON.stringify(o)}function R(o,a){if(a?.key&&!Array.isArray(a.key))throw new Error("State key must be an array");let u=chunkENWGYQNU_js.h(()=>chunk7BXR4ZFD_js.a({container:void 0,serializedKey:void 0})),p=a?.key,i=p?h(p):void 0,v=i!==u.serializedKey;if(typeof o=="function"&&a?.deps!==void 0){let s=o,t=chunkENWGYQNU_js.h(()=>({value:void 0,prevDeps:void 0,hasRun:false})),e=true;if(t.hasRun&&t.prevDeps&&(e=a.deps.length!==t.prevDeps.length||a.deps.some((n,l)=>n!==t.prevDeps[l])),e){let n=s();if(n instanceof Promise)throw new Error("deps option is not supported with async functions");t.value=n,t.prevDeps=[...a.deps],t.hasRun=true;}let c={refetch:async()=>{},get loading(){return false},get error(){return null},get status(){return "success"}};return [t.value,c]}if(!u.container||v)if(u.serializedKey=i,i&&y.has(i))u.container=y.get(i);else {let s;if(typeof o=="function"){let t=o,e=chunk7BXR4ZFD_js.a({type:"resource",value:void 0,loading:true,error:null,status:"idle",run:()=>{}}),c=()=>{try{let n=t();n instanceof Promise?(e.loading=!0,e.status="loading",e.error=null,n.then(l=>{e.value=l,e.status="success",e.loading=!1;}).catch(l=>{e.error=l,e.status="error",e.loading=!1;})):(e.value=n,e.status="success",e.loading=!1,e.error=null);}catch(n){e.error=n,e.status="error",e.loading=false;}};e.run=c,chunkENWGYQNU_js.b(c),s=e;}else s=chunk7BXR4ZFD_js.a({type:"signal",value:o});i&&y.set(i,s),u.container=s;}let r=u.container,g=r.value;return r.type==="signal"?[g,t=>{typeof t=="function"?r.value=t(r.value):r.value=t;}]:[g,{refetch:async()=>{r.run();},get loading(){return r.loading},get error(){return r.error},get status(){return r.status}}]}exports.a=R;//# sourceMappingURL=chunk-APAMPY43.js.map
|
|
2
|
-
//# sourceMappingURL=chunk-APAMPY43.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/core/state.ts"],"names":["globalRegistry","serializeKey","key","state","input","options","stateRef","hook","reactive","currentKey","serializedKey","keyChanged","fn","memoState","hasChanged","d","i","result","control","newContainer","run","data","err","unsafeEffect","container","currentValue","newValue"],"mappings":"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","file":"chunk-APAMPY43.js","sourcesContent":["\nimport { reactive } from './reactive'\nimport { unsafeEffect } from './effect'\nimport { hook } from './hook'\n\nexport type StateSetter<T> = (newValue: T | ((prev: T) => T)) => void\n\nexport type ResourceControl = {\n refetch: () => Promise<void>\n readonly loading: boolean\n readonly error: unknown\n readonly status: 'idle' | 'loading' | 'success' | 'error'\n}\n\nexport type StateAction<T> = StateSetter<T> | ResourceControl\n\nexport interface StateOptions {\n key?: unknown[]\n deps?: any[]\n}\n\n// Global State Registry\nconst globalRegistry = new Map<string, any>()\n\nfunction serializeKey(key: unknown[]): string {\n return JSON.stringify(key)\n}\n\n// Overloads\nexport function state<T>(fn: () => Promise<T>, options?: StateOptions): [T | undefined, ResourceControl]\nexport function state<T>(fn: () => T, options?: StateOptions): [T, ResourceControl]\nexport function state<T>(initialValue: T extends Function ? never : T, options?: StateOptions): [T, StateSetter<T>]\nexport function state<T>(input: T | (() => T) | (() => Promise<T>), options?: StateOptions): any {\n // 0. Validate key if provided\n if (options?.key && !Array.isArray(options.key)) {\n throw new Error('State key must be an array')\n }\n\n // Hook Wrapper: Store container reference and track key\n const stateRef = hook(() => {\n return reactive({\n container: undefined as any,\n serializedKey: undefined as any\n })\n })\n\n // Compute serialized key\n const currentKey = options?.key\n const serializedKey = currentKey ? serializeKey(currentKey) : undefined\n\n // Check if key has changed by comparing serialized strings\n const keyChanged = serializedKey !== stateRef.serializedKey\n\n // DEPS MODE: Handle separately - always check deps on every render\n if (typeof input === 'function' && options?.deps !== undefined) {\n const fn = input as Function\n const memoState = hook(() => ({\n value: undefined as T | undefined,\n prevDeps: undefined as any[] | undefined,\n hasRun: false\n }))\n\n let hasChanged = true\n if (memoState.hasRun && memoState.prevDeps) {\n hasChanged = options.deps.length !== memoState.prevDeps.length ||\n options.deps.some((d, i) => d !== memoState.prevDeps![i])\n }\n\n if (hasChanged) {\n const result = fn()\n if (result instanceof Promise) {\n throw new Error('deps option is not supported with async functions')\n }\n memoState.value = result\n memoState.prevDeps = [...options.deps]\n memoState.hasRun = true\n }\n\n const control: ResourceControl = {\n refetch: async () => { },\n get loading() { return false },\n get error() { return null },\n get status() { return 'success' as const }\n }\n return [memoState.value, control]\n }\n\n // If key changed or first time, get/create container\n if (!stateRef.container || keyChanged) {\n stateRef.serializedKey = serializedKey\n\n // Check Registry FIRST\n if (serializedKey && globalRegistry.has(serializedKey)) {\n stateRef.container = globalRegistry.get(serializedKey)\n } else {\n let newContainer: any\n\n // 1. Function (Computed or Resource) - only async functions reach here now\n if (typeof input === 'function') {\n const fn = input as Function\n\n // REACTIVE MODE: Automatic tracking for async functions\n const state = reactive({\n type: 'resource',\n value: undefined as T | undefined,\n loading: true,\n error: null as any,\n status: 'idle' as 'idle' | 'loading' | 'success' | 'error',\n run: () => { }\n })\n\n const run = () => {\n try {\n const result = fn()\n\n if (result instanceof Promise) {\n state.loading = true\n state.status = 'loading'\n state.error = null\n\n result\n .then(data => {\n state.value = data\n state.status = 'success'\n state.loading = false\n })\n .catch(err => {\n state.error = err\n state.status = 'error'\n state.loading = false\n })\n } else {\n state.value = result\n state.status = 'success'\n state.loading = false\n state.error = null\n }\n } catch (err) {\n state.error = err\n state.status = 'error'\n state.loading = false\n }\n }\n\n state.run = run\n\n // Make it reactive!\n unsafeEffect(run)\n\n newContainer = state\n } else {\n // 2. Value (Signal)\n // We return the reactive proxy itself as the container\n newContainer = reactive({\n type: 'signal',\n value: input\n })\n }\n\n // Register in global registry if needed\n if (serializedKey) {\n globalRegistry.set(serializedKey, newContainer)\n }\n\n stateRef.container = newContainer\n }\n }\n\n const container = stateRef.container\n\n // --- RETURN LOGIC ---\n // Access container.value to track dependency in the component's effect\n const currentValue = container.value\n\n if (container.type === 'signal') {\n const setter = (newValue: T | ((prev: T) => T)) => {\n if (typeof newValue === 'function') {\n container.value = (newValue as Function)(container.value)\n } else {\n container.value = newValue\n }\n }\n return [currentValue, setter]\n } else {\n // Resource / Computed\n const control = {\n refetch: async () => { container.run() },\n get loading() { return container.loading },\n get error() { return container.error },\n get status() { return container.status }\n }\n return [currentValue, control]\n }\n}\n"]}
|
package/dist/chunk-CPJRQL2C.mjs
DELETED
|
@@ -1,2 +0,0 @@
|
|
|
1
|
-
import {a,c,f}from'./chunk-44RZHCII.mjs';var p=Symbol("flexium.reactive"),s=new WeakMap,l=new WeakMap;function M(e){if(e&&e[p])return e;let o=l.get(e);if(o)return o;let t=new Proxy(e,{get(n,r,i){if(r===p)return true;let c=Reflect.get(n,r,i);return b(n,r),c!==null&&typeof c=="object"?M(c):c},set(n,r,i,c){let x=n[r],a=Reflect.set(n,r,i,c);return a&&d(i,x)&&w(n,r),a}});return l.set(e,t),t}function b(e,o){if(!a)return;let t=s.get(e);t||s.set(e,t=new Map);let n=t.get(o);n||t.set(o,n=new Set),c(n);}function w(e,o){let t=s.get(e);if(!t)return;let n=t.get(o);n&&f(n);}function d(e,o){return !Object.is(e,o)}function T(e){return !!(e&&e[p])}export{M as a,T as b};//# sourceMappingURL=chunk-CPJRQL2C.mjs.map
|
|
2
|
-
//# sourceMappingURL=chunk-CPJRQL2C.mjs.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/core/reactive.ts"],"names":["REACTIVE_SIGNAL","targetMap","reactiveMap","reactive","target","existingProxy","proxy","key","receiver","res","track","value","oldValue","result","hasChanged","trigger","activeEffect","depsMap","dep","trackEffect","triggerEffects","isReactive"],"mappings":"yCAEO,IAAMA,CAAAA,CAAkB,OAAO,kBAAkB,CAAA,CAIlDC,EAAY,IAAI,OAAA,CAGhBC,EAAc,IAAI,OAAA,CAEjB,SAASC,CAAAA,CAA2BC,CAAAA,CAAc,CACrD,GAAIA,CAAAA,EAAWA,EAAeJ,CAAe,CAAA,CACzC,OAAOI,CAAAA,CAGX,IAAMC,CAAAA,CAAgBH,EAAY,GAAA,CAAIE,CAAM,EAC5C,GAAIC,CAAAA,CACA,OAAOA,CAAAA,CAGX,IAAMC,CAAAA,CAAQ,IAAI,KAAA,CAAMF,CAAAA,CAAQ,CAC5B,GAAA,CAAIA,CAAAA,CAAQG,EAAKC,CAAAA,CAAU,CACvB,GAAID,CAAAA,GAAQP,CAAAA,CAAiB,OAAO,KAAA,CAEpC,IAAMS,CAAAA,CAAM,QAAQ,GAAA,CAAIL,CAAAA,CAAQG,EAAKC,CAAQ,CAAA,CAI7C,OAFAE,CAAAA,CAAMN,CAAAA,CAAQG,CAAG,CAAA,CAEbE,CAAAA,GAAQ,MAAQ,OAAOA,CAAAA,EAAQ,SACxBN,CAAAA,CAASM,CAAG,EAGhBA,CACX,CAAA,CACA,GAAA,CAAIL,CAAAA,CAAQG,CAAAA,CAAKI,CAAAA,CAAOH,EAAU,CAC9B,IAAMI,EAAYR,CAAAA,CAAeG,CAAG,EAC9BM,CAAAA,CAAS,OAAA,CAAQ,GAAA,CAAIT,CAAAA,CAAQG,CAAAA,CAAKI,CAAAA,CAAOH,CAAQ,CAAA,CAEvD,OAAIK,GAAUC,CAAAA,CAAWH,CAAAA,CAAOC,CAAQ,CAAA,EACpCG,CAAAA,CAAQX,CAAAA,CAAQG,CAAG,CAAA,CAGhBM,CACX,CACJ,CAAC,CAAA,CAED,OAAAX,CAAAA,CAAY,GAAA,CAAIE,EAAQE,CAAK,CAAA,CACtBA,CACX,CAEO,SAASI,EAAMN,CAAAA,CAAgBG,CAAAA,CAAc,CAChD,GAAI,CAACS,EAAc,OAEnB,IAAIC,CAAAA,CAAUhB,CAAAA,CAAU,GAAA,CAAIG,CAAM,EAC7Ba,CAAAA,EACDhB,CAAAA,CAAU,IAAIG,CAAAA,CAASa,CAAAA,CAAU,IAAI,GAAM,CAAA,CAG/C,IAAIC,CAAAA,CAAMD,CAAAA,CAAQ,GAAA,CAAIV,CAAG,CAAA,CACpBW,CAAAA,EACDD,EAAQ,GAAA,CAAIV,CAAAA,CAAMW,EAAM,IAAI,GAAM,CAAA,CAGtCC,CAAAA,CAAYD,CAAG,EACnB,CAEO,SAASH,CAAAA,CAAQX,EAAgBG,CAAAA,CAAc,CAClD,IAAMU,CAAAA,CAAUhB,CAAAA,CAAU,GAAA,CAAIG,CAAM,CAAA,CACpC,GAAI,CAACa,CAAAA,CAAS,OAEd,IAAMC,CAAAA,CAAMD,CAAAA,CAAQ,IAAIV,CAAG,CAAA,CACvBW,CAAAA,EACAE,CAAAA,CAAeF,CAAG,EAE1B,CAEA,SAASJ,CAAAA,CAAWH,EAAYC,CAAAA,CAAwB,CACpD,OAAO,CAAC,MAAA,CAAO,EAAA,CAAGD,CAAAA,CAAOC,CAAQ,CACrC,CAEO,SAASS,CAAAA,CAAWV,EAAyB,CAChD,OAAO,CAAC,EAAEA,CAAAA,EAAUA,CAAAA,CAAcX,CAAe,CAAA,CACrD","file":"chunk-CPJRQL2C.mjs","sourcesContent":["import { activeEffect, trackEffect, triggerEffects } from './effect'\n\nexport const REACTIVE_SIGNAL = Symbol('flexium.reactive')\n\ntype Dep = Set<any>\ntype KeyToDepMap = Map<any, Dep>\nconst targetMap = new WeakMap<any, KeyToDepMap>()\n\n// WeakMap to store existing proxies to avoid duplicates\nconst reactiveMap = new WeakMap<object, any>()\n\nexport function reactive<T extends object>(target: T): T {\n if (target && (target as any)[REACTIVE_SIGNAL]) {\n return target\n }\n\n const existingProxy = reactiveMap.get(target)\n if (existingProxy) {\n return existingProxy\n }\n\n const proxy = new Proxy(target, {\n get(target, key, receiver) {\n if (key === REACTIVE_SIGNAL) return true\n\n const res = Reflect.get(target, key, receiver)\n\n track(target, key)\n\n if (res !== null && typeof res === 'object') {\n return reactive(res)\n }\n\n return res\n },\n set(target, key, value, receiver) {\n const oldValue = (target as any)[key]\n const result = Reflect.set(target, key, value, receiver)\n\n if (result && hasChanged(value, oldValue)) {\n trigger(target, key)\n }\n\n return result\n }\n })\n\n reactiveMap.set(target, proxy)\n return proxy\n}\n\nexport function track(target: object, key: unknown) {\n if (!activeEffect) return\n\n let depsMap = targetMap.get(target)\n if (!depsMap) {\n targetMap.set(target, (depsMap = new Map()))\n }\n\n let dep = depsMap.get(key)\n if (!dep) {\n depsMap.set(key, (dep = new Set()))\n }\n\n trackEffect(dep)\n}\n\nexport function trigger(target: object, key: unknown) {\n const depsMap = targetMap.get(target)\n if (!depsMap) return\n\n const dep = depsMap.get(key)\n if (dep) {\n triggerEffects(dep)\n }\n}\n\nfunction hasChanged(value: any, oldValue: any): boolean {\n return !Object.is(value, oldValue)\n}\n\nexport function isReactive(value: unknown): boolean {\n return !!(value && (value as any)[REACTIVE_SIGNAL])\n}\n"]}
|
package/dist/chunk-ECB5HZOQ.mjs
DELETED
|
@@ -1,2 +0,0 @@
|
|
|
1
|
-
import {a}from'./chunk-CPJRQL2C.mjs';import {h as h$1,b}from'./chunk-44RZHCII.mjs';var y=new Map;function h(o){return JSON.stringify(o)}function R(o,a$1){if(a$1?.key&&!Array.isArray(a$1.key))throw new Error("State key must be an array");let u=h$1(()=>a({container:void 0,serializedKey:void 0})),p=a$1?.key,i=p?h(p):void 0,v=i!==u.serializedKey;if(typeof o=="function"&&a$1?.deps!==void 0){let s=o,t=h$1(()=>({value:void 0,prevDeps:void 0,hasRun:false})),e=true;if(t.hasRun&&t.prevDeps&&(e=a$1.deps.length!==t.prevDeps.length||a$1.deps.some((n,l)=>n!==t.prevDeps[l])),e){let n=s();if(n instanceof Promise)throw new Error("deps option is not supported with async functions");t.value=n,t.prevDeps=[...a$1.deps],t.hasRun=true;}let c={refetch:async()=>{},get loading(){return false},get error(){return null},get status(){return "success"}};return [t.value,c]}if(!u.container||v)if(u.serializedKey=i,i&&y.has(i))u.container=y.get(i);else {let s;if(typeof o=="function"){let t=o,e=a({type:"resource",value:void 0,loading:true,error:null,status:"idle",run:()=>{}}),c=()=>{try{let n=t();n instanceof Promise?(e.loading=!0,e.status="loading",e.error=null,n.then(l=>{e.value=l,e.status="success",e.loading=!1;}).catch(l=>{e.error=l,e.status="error",e.loading=!1;})):(e.value=n,e.status="success",e.loading=!1,e.error=null);}catch(n){e.error=n,e.status="error",e.loading=false;}};e.run=c,b(c),s=e;}else s=a({type:"signal",value:o});i&&y.set(i,s),u.container=s;}let r=u.container,g=r.value;return r.type==="signal"?[g,t=>{typeof t=="function"?r.value=t(r.value):r.value=t;}]:[g,{refetch:async()=>{r.run();},get loading(){return r.loading},get error(){return r.error},get status(){return r.status}}]}export{R as a};//# sourceMappingURL=chunk-ECB5HZOQ.mjs.map
|
|
2
|
-
//# sourceMappingURL=chunk-ECB5HZOQ.mjs.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/core/state.ts"],"names":["globalRegistry","serializeKey","key","state","input","options","stateRef","hook","reactive","currentKey","serializedKey","keyChanged","fn","memoState","hasChanged","d","i","result","control","newContainer","run","data","err","unsafeEffect","container","currentValue","newValue"],"mappings":"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","file":"chunk-ECB5HZOQ.mjs","sourcesContent":["\nimport { reactive } from './reactive'\nimport { unsafeEffect } from './effect'\nimport { hook } from './hook'\n\nexport type StateSetter<T> = (newValue: T | ((prev: T) => T)) => void\n\nexport type ResourceControl = {\n refetch: () => Promise<void>\n readonly loading: boolean\n readonly error: unknown\n readonly status: 'idle' | 'loading' | 'success' | 'error'\n}\n\nexport type StateAction<T> = StateSetter<T> | ResourceControl\n\nexport interface StateOptions {\n key?: unknown[]\n deps?: any[]\n}\n\n// Global State Registry\nconst globalRegistry = new Map<string, any>()\n\nfunction serializeKey(key: unknown[]): string {\n return JSON.stringify(key)\n}\n\n// Overloads\nexport function state<T>(fn: () => Promise<T>, options?: StateOptions): [T | undefined, ResourceControl]\nexport function state<T>(fn: () => T, options?: StateOptions): [T, ResourceControl]\nexport function state<T>(initialValue: T extends Function ? never : T, options?: StateOptions): [T, StateSetter<T>]\nexport function state<T>(input: T | (() => T) | (() => Promise<T>), options?: StateOptions): any {\n // 0. Validate key if provided\n if (options?.key && !Array.isArray(options.key)) {\n throw new Error('State key must be an array')\n }\n\n // Hook Wrapper: Store container reference and track key\n const stateRef = hook(() => {\n return reactive({\n container: undefined as any,\n serializedKey: undefined as any\n })\n })\n\n // Compute serialized key\n const currentKey = options?.key\n const serializedKey = currentKey ? serializeKey(currentKey) : undefined\n\n // Check if key has changed by comparing serialized strings\n const keyChanged = serializedKey !== stateRef.serializedKey\n\n // DEPS MODE: Handle separately - always check deps on every render\n if (typeof input === 'function' && options?.deps !== undefined) {\n const fn = input as Function\n const memoState = hook(() => ({\n value: undefined as T | undefined,\n prevDeps: undefined as any[] | undefined,\n hasRun: false\n }))\n\n let hasChanged = true\n if (memoState.hasRun && memoState.prevDeps) {\n hasChanged = options.deps.length !== memoState.prevDeps.length ||\n options.deps.some((d, i) => d !== memoState.prevDeps![i])\n }\n\n if (hasChanged) {\n const result = fn()\n if (result instanceof Promise) {\n throw new Error('deps option is not supported with async functions')\n }\n memoState.value = result\n memoState.prevDeps = [...options.deps]\n memoState.hasRun = true\n }\n\n const control: ResourceControl = {\n refetch: async () => { },\n get loading() { return false },\n get error() { return null },\n get status() { return 'success' as const }\n }\n return [memoState.value, control]\n }\n\n // If key changed or first time, get/create container\n if (!stateRef.container || keyChanged) {\n stateRef.serializedKey = serializedKey\n\n // Check Registry FIRST\n if (serializedKey && globalRegistry.has(serializedKey)) {\n stateRef.container = globalRegistry.get(serializedKey)\n } else {\n let newContainer: any\n\n // 1. Function (Computed or Resource) - only async functions reach here now\n if (typeof input === 'function') {\n const fn = input as Function\n\n // REACTIVE MODE: Automatic tracking for async functions\n const state = reactive({\n type: 'resource',\n value: undefined as T | undefined,\n loading: true,\n error: null as any,\n status: 'idle' as 'idle' | 'loading' | 'success' | 'error',\n run: () => { }\n })\n\n const run = () => {\n try {\n const result = fn()\n\n if (result instanceof Promise) {\n state.loading = true\n state.status = 'loading'\n state.error = null\n\n result\n .then(data => {\n state.value = data\n state.status = 'success'\n state.loading = false\n })\n .catch(err => {\n state.error = err\n state.status = 'error'\n state.loading = false\n })\n } else {\n state.value = result\n state.status = 'success'\n state.loading = false\n state.error = null\n }\n } catch (err) {\n state.error = err\n state.status = 'error'\n state.loading = false\n }\n }\n\n state.run = run\n\n // Make it reactive!\n unsafeEffect(run)\n\n newContainer = state\n } else {\n // 2. Value (Signal)\n // We return the reactive proxy itself as the container\n newContainer = reactive({\n type: 'signal',\n value: input\n })\n }\n\n // Register in global registry if needed\n if (serializedKey) {\n globalRegistry.set(serializedKey, newContainer)\n }\n\n stateRef.container = newContainer\n }\n }\n\n const container = stateRef.container\n\n // --- RETURN LOGIC ---\n // Access container.value to track dependency in the component's effect\n const currentValue = container.value\n\n if (container.type === 'signal') {\n const setter = (newValue: T | ((prev: T) => T)) => {\n if (typeof newValue === 'function') {\n container.value = (newValue as Function)(container.value)\n } else {\n container.value = newValue\n }\n }\n return [currentValue, setter]\n } else {\n // Resource / Computed\n const control = {\n refetch: async () => { container.run() },\n get loading() { return container.loading },\n get error() { return container.error },\n get status() { return container.status }\n }\n return [currentValue, control]\n }\n}\n"]}
|
package/dist/chunk-ENWGYQNU.js
DELETED
|
@@ -1,2 +0,0 @@
|
|
|
1
|
-
'use strict';exports.a=void 0;var r=class{constructor(t,n){this.fn=t;this.scheduler=n;this.deps=[];this.active=true;}run(){if(!this.active)return this.fn();let t=exports.a;try{return this.cleanup(),exports.a=this,this.fn()}finally{exports.a=t;}}stop(){this.active&&(this.cleanup(),this.active=false);}cleanup(){let{deps:t}=this;if(t.length){for(let n=0;n<t.length;n++)t[n].delete(this);t.length=0;}}};function p(e,t={}){let n=new r(e,t.scheduler);n.run();let c=n.run.bind(n);return c.effect=n,c}function d(e){exports.a&&(e.add(exports.a),exports.a.deps.push(e));}var i=new Set,s=false,a=false;function l(e){i.has(e)||(i.add(e),!s&&!a&&(s=true,Promise.resolve().then(h)));}function h(){s=false;let e=[...i];i.clear();for(let t of e)t.active&&t.run();}function v(e){a=e;}function x(e){let t=[...e];for(let n of t)n!==exports.a&&(n.scheduler?n.scheduler():l(n));}var f=null;function g(e,t){let n=f;f=e,e.hookIndex=0;try{return t()}finally{f=n;}}function k(e){if(!f)return e();let t=f,{hooks:n,hookIndex:c}=t;if(c<n.length)return t.hookIndex++,n[c];let u=e();return n.push(u),t.hookIndex++,u}exports.b=p;exports.c=d;exports.d=h;exports.e=v;exports.f=x;exports.g=g;exports.h=k;//# sourceMappingURL=chunk-ENWGYQNU.js.map
|
|
2
|
-
//# sourceMappingURL=chunk-ENWGYQNU.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/core/effect.ts","../src/core/hook.ts"],"names":["activeEffect","ReactiveEffectLike","fn","scheduler","parent","deps","i","unsafeEffect","options","_effect","runner","trackEffect","dep","queue","isFlushPending","isBatching","queueJob","effect","flush","effects","setBatching","value","triggerEffects","currentComponent","runWithComponent","component","prev","hook","factory","instance","hooks","hookIndex"],"mappings":"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","file":"chunk-ENWGYQNU.js","sourcesContent":["export let activeEffect: ReactiveEffect | undefined\n\nexport class ReactiveEffectLike {\n deps: Set<any>[] = []\n active = true\n\n constructor(\n public fn: () => void,\n public scheduler?: () => void\n ) { }\n\n run() {\n if (!this.active) {\n return this.fn()\n }\n\n let parent: ReactiveEffect | undefined = activeEffect\n try {\n this.cleanup()\n activeEffect = this\n return this.fn()\n } finally {\n activeEffect = parent\n }\n }\n\n stop() {\n if (this.active) {\n this.cleanup()\n this.active = false\n }\n }\n\n cleanup() {\n const { deps } = this\n if (deps.length) {\n for (let i = 0; i < deps.length; i++) {\n deps[i].delete(this)\n }\n deps.length = 0\n }\n }\n}\n\nexport type ReactiveEffect = ReactiveEffectLike\n\nexport function unsafeEffect(fn: () => void, options: { scheduler?: () => void } = {}) {\n const _effect = new ReactiveEffectLike(fn, options.scheduler)\n _effect.run()\n\n const runner: any = _effect.run.bind(_effect)\n runner.effect = _effect\n return runner\n}\n\nexport function trackEffect(dep: Set<ReactiveEffect>) {\n if (activeEffect) {\n dep.add(activeEffect)\n activeEffect.deps.push(dep)\n }\n}\n\nconst queue = new Set<ReactiveEffect>()\nlet isFlushPending = false\nlet isBatching = false\n\nexport function queueJob(effect: ReactiveEffect) {\n if (!queue.has(effect)) {\n queue.add(effect)\n if (!isFlushPending && !isBatching) {\n isFlushPending = true\n Promise.resolve().then(flush)\n }\n }\n}\n\nexport function flush() {\n isFlushPending = false\n const effects = [...queue]\n queue.clear()\n for (const effect of effects) {\n if (effect.active) {\n effect.run()\n }\n }\n}\n\nexport function setBatching(value: boolean) {\n isBatching = value\n}\n\nexport function triggerEffects(dep: Set<ReactiveEffect>) {\n const effects = [...dep]\n for (const effect of effects) {\n if (effect !== activeEffect) {\n if (effect.scheduler) {\n effect.scheduler()\n } else {\n queueJob(effect)\n }\n }\n }\n}\n","\nexport interface ComponentInstance {\n hooks: any[]\n hookIndex: number\n}\n\nlet currentComponent: ComponentInstance | null = null\n\nexport function getComponent(): ComponentInstance | null {\n return currentComponent\n}\n\nexport function runWithComponent<T>(component: ComponentInstance, fn: () => T): T {\n const prev = currentComponent\n currentComponent = component\n component.hookIndex = 0\n try {\n return fn()\n } finally {\n currentComponent = prev\n }\n}\n\nexport function hook<T>(factory: () => T): T {\n if (!currentComponent) {\n // Outside component: just run factory\n return factory()\n }\n\n const instance = currentComponent\n const { hooks, hookIndex } = instance\n\n if (hookIndex < hooks.length) {\n // Return existing hook\n instance.hookIndex++\n return hooks[hookIndex] as T\n }\n\n // Create new hook\n const value = factory()\n hooks.push(value)\n instance.hookIndex++\n\n return value\n}\n"]}
|
package/dist/chunk-IA4FEBFE.js
DELETED
|
@@ -1,2 +0,0 @@
|
|
|
1
|
-
'use strict';var chunkENWGYQNU_js=require('./chunk-ENWGYQNU.js');function r(n,t){let e=chunkENWGYQNU_js.h(()=>({cleanup:void 0,deps:void 0,effect:void 0,hasRun:false})),a=true;if(e.hasRun&&t&&e.deps&&(a=t.some((f,o)=>f!==e.deps[o])),a){e.cleanup&&(e.cleanup(),e.cleanup=void 0);let f=n();typeof f=="function"&&(e.cleanup=f),e.deps=t,e.hasRun=true;}}function c(n){if(n){chunkENWGYQNU_js.e(true);try{n();}finally{chunkENWGYQNU_js.e(false),chunkENWGYQNU_js.d();}}else chunkENWGYQNU_js.d();}function h(n){c(n);}exports.a=r;exports.b=c;exports.c=h;//# sourceMappingURL=chunk-IA4FEBFE.js.map
|
|
2
|
-
//# sourceMappingURL=chunk-IA4FEBFE.js.map
|