@unsetsoft/ryunixjs 1.1.38 → 1.2.0-canary.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/Ryunix.js +260 -33
- package/dist/Ryunix.min.js +1 -1
- package/package.json +1 -1
package/dist/Ryunix.js
CHANGED
|
@@ -640,6 +640,134 @@
|
|
|
640
640
|
return renderProcess
|
|
641
641
|
};
|
|
642
642
|
|
|
643
|
+
/**
|
|
644
|
+
* Renders a Ryunix component tree to an HTML string (SSR/SSG), con soporte para obtención de datos.
|
|
645
|
+
* Si el componente raíz exporta una función estática `fetchSSRData` o `fetchSSGData`, esta será ejecutada antes del renderizado
|
|
646
|
+
* y sus datos serán inyectados como props.
|
|
647
|
+
*
|
|
648
|
+
* @param {Object} element - El elemento raíz a renderizar.
|
|
649
|
+
* @param {Object} [options] - Contexto opcional para SSR/SSG (ej: route, params, props).
|
|
650
|
+
* @returns {Promise<Object>} { html, head, data } - HTML renderizado, metadatos y datos obtenidos.
|
|
651
|
+
*
|
|
652
|
+
* Uso SSR con datos:
|
|
653
|
+
* App.fetchSSRData = async (ctx) => ({ user: await fetchUser(ctx.route) })
|
|
654
|
+
* const { html, head, data } = await renderToString(<App />, { route: '/about' })
|
|
655
|
+
*
|
|
656
|
+
* Uso SSG con datos:
|
|
657
|
+
* App.fetchSSGData = async (ctx) => ({ posts: await fetchPosts() })
|
|
658
|
+
* const { html, head, data } = await renderToString(<App />, { route: '/blog' })
|
|
659
|
+
*/
|
|
660
|
+
async function renderToString(element, options = {}) {
|
|
661
|
+
// Soporte para obtención de datos SSR/SSG
|
|
662
|
+
let data = undefined;
|
|
663
|
+
let rootType = element && element.type;
|
|
664
|
+
// Si no se pasa location en ssrContext, usar '/'
|
|
665
|
+
if (options && !options.location) {
|
|
666
|
+
options.location = '/';
|
|
667
|
+
}
|
|
668
|
+
if (rootType && typeof rootType === 'function') {
|
|
669
|
+
if (typeof rootType.fetchSSRData === 'function' && options.ssr !== false) {
|
|
670
|
+
data = await rootType.fetchSSRData(options);
|
|
671
|
+
} else if (
|
|
672
|
+
typeof rootType.fetchSSGData === 'function' &&
|
|
673
|
+
options.ssg !== false
|
|
674
|
+
) {
|
|
675
|
+
data = await rootType.fetchSSGData(options);
|
|
676
|
+
}
|
|
677
|
+
}
|
|
678
|
+
// Inyectar los datos como props
|
|
679
|
+
if (data) {
|
|
680
|
+
element = { ...element, props: { ...element.props, ...data } };
|
|
681
|
+
}
|
|
682
|
+
// Temporary global context for SSR/SSG metadata collection
|
|
683
|
+
const ssrContext = { head: [] };
|
|
684
|
+
const prevContext = globalThis.__RYUNIX_SSR_CONTEXT__;
|
|
685
|
+
globalThis.__RYUNIX_SSR_CONTEXT__ = ssrContext;
|
|
686
|
+
|
|
687
|
+
function renderNode(node) {
|
|
688
|
+
if (typeof node === 'string' || typeof node === 'number') {
|
|
689
|
+
return String(node)
|
|
690
|
+
}
|
|
691
|
+
if (!node || typeof node !== 'object') return ''
|
|
692
|
+
if (node.type === 'FRAGMENT' || node.type === undefined) {
|
|
693
|
+
return (Array.isArray(node.children) ? node.children : [node.children])
|
|
694
|
+
.map(renderNode)
|
|
695
|
+
.join('')
|
|
696
|
+
}
|
|
697
|
+
if (typeof node.type === 'function') {
|
|
698
|
+
const rendered = node.type({ ...node.props, ...options });
|
|
699
|
+
return renderNode(rendered)
|
|
700
|
+
}
|
|
701
|
+
let html = `<${node.type}`;
|
|
702
|
+
if (node.props) {
|
|
703
|
+
for (const [key, value] of Object.entries(node.props)) {
|
|
704
|
+
if (key === 'children' || value == null || typeof value === 'object')
|
|
705
|
+
continue
|
|
706
|
+
html += ` ${key}="${String(value)}"`;
|
|
707
|
+
}
|
|
708
|
+
}
|
|
709
|
+
html += '>';
|
|
710
|
+
if (node.props && node.props.children) {
|
|
711
|
+
html += Array.isArray(node.props.children)
|
|
712
|
+
? node.props.children.map(renderNode).join('')
|
|
713
|
+
: renderNode(node.props.children);
|
|
714
|
+
}
|
|
715
|
+
html += `</${node.type}>`;
|
|
716
|
+
return html
|
|
717
|
+
}
|
|
718
|
+
|
|
719
|
+
const html = renderNode(element);
|
|
720
|
+
// Restore previous context to avoid leaking between renders
|
|
721
|
+
globalThis.__RYUNIX_SSR_CONTEXT__ = prevContext;
|
|
722
|
+
return { html, head: ssrContext.head.join('\n'), data }
|
|
723
|
+
}
|
|
724
|
+
|
|
725
|
+
/**
|
|
726
|
+
* Helper para asociar una función de obtención de datos SSR a un componente Ryunix.
|
|
727
|
+
* @param {Function} Component - Componente Ryunix.
|
|
728
|
+
* @param {Function} fetchFn - Función async (ctx) => datos.
|
|
729
|
+
* @returns {Function} El mismo componente, con fetchSSRData asignado.
|
|
730
|
+
* @example
|
|
731
|
+
* export default withSSRData(App, async (ctx) => ({ user: await fetchUser(ctx.route) }))
|
|
732
|
+
*/
|
|
733
|
+
function withSSRData(Component, fetchFn) {
|
|
734
|
+
Component.fetchSSRData = fetchFn;
|
|
735
|
+
return Component
|
|
736
|
+
}
|
|
737
|
+
|
|
738
|
+
/**
|
|
739
|
+
* Helper para asociar una función de obtención de datos SSG a un componente Ryunix.
|
|
740
|
+
* @param {Function} Component - Componente Ryunix.
|
|
741
|
+
* @param {Function} fetchFn - Función async (ctx) => datos.
|
|
742
|
+
* @returns {Function} El mismo componente, con fetchSSGData asignado.
|
|
743
|
+
* @example
|
|
744
|
+
* export default withSSGData(App, async (ctx) => ({ posts: await fetchPosts() }))
|
|
745
|
+
*/
|
|
746
|
+
function withSSGData(Component, fetchFn) {
|
|
747
|
+
Component.fetchSSGData = fetchFn;
|
|
748
|
+
return Component
|
|
749
|
+
}
|
|
750
|
+
|
|
751
|
+
/**
|
|
752
|
+
* Hidrata una aplicación Ryunix renderizada por SSR/SSG, enlazando eventos y estado sobre el DOM existente.
|
|
753
|
+
* @function hydrate
|
|
754
|
+
* @param {Object|HTMLElement} element - El elemento raíz a hidratar.
|
|
755
|
+
* @param {string|HTMLElement} [root='__ryunix'] - El contenedor raíz (id o elemento DOM).
|
|
756
|
+
* @description Busca el contenedor en el DOM y reutiliza el HTML existente, enlazando el árbol de componentes Ryunix.
|
|
757
|
+
* @example
|
|
758
|
+
* // En el cliente, tras recibir HTML SSR/SSG:
|
|
759
|
+
* import { hydrate } from 'ryunix';
|
|
760
|
+
* hydrate(<App />, '__ryunix');
|
|
761
|
+
*/
|
|
762
|
+
function hydrate(MainElement, root = '__ryunix') {
|
|
763
|
+
let container =
|
|
764
|
+
typeof root === 'string' ? document.getElementById(root) : root;
|
|
765
|
+
if (!container) throw new Error('No se encontró el contenedor para hidratar')
|
|
766
|
+
// Reutiliza el DOM existente y conecta el árbol Ryunix
|
|
767
|
+
// (En este ejemplo, simplemente delegamos a render, pero en el futuro se puede optimizar para diff/hidratación real)
|
|
768
|
+
return render(MainElement, container)
|
|
769
|
+
}
|
|
770
|
+
|
|
643
771
|
/**
|
|
644
772
|
* @description The function creates a state.
|
|
645
773
|
* @param initial - The initial value of the state for the hook.
|
|
@@ -714,16 +842,18 @@
|
|
|
714
842
|
};
|
|
715
843
|
|
|
716
844
|
/**
|
|
717
|
-
*
|
|
718
|
-
* @param effect -
|
|
719
|
-
*
|
|
720
|
-
* or subscribing to events.
|
|
721
|
-
* @param deps - An array of dependencies that the effect depends on. If any of the dependencies change
|
|
722
|
-
* between renders, the effect will be re-run. If the array is empty, the effect will only run once on
|
|
723
|
-
* mount and never again.
|
|
845
|
+
* useEffect seguro para SSR/SSG: no ejecuta efectos en el servidor.
|
|
846
|
+
* @param effect - Función de efecto.
|
|
847
|
+
* @param deps - Dependencias.
|
|
724
848
|
*/
|
|
725
849
|
|
|
726
850
|
const useEffect = (callback, deps) => {
|
|
851
|
+
// No ejecutar efectos en SSR/SSG
|
|
852
|
+
if (typeof window === 'undefined') {
|
|
853
|
+
vars.hookIndex++;
|
|
854
|
+
return
|
|
855
|
+
}
|
|
856
|
+
|
|
727
857
|
const oldHook =
|
|
728
858
|
vars.wipFiber.alternate &&
|
|
729
859
|
vars.wipFiber.alternate.hooks &&
|
|
@@ -856,7 +986,9 @@
|
|
|
856
986
|
}
|
|
857
987
|
};
|
|
858
988
|
|
|
989
|
+
// Proteger hooks que usan window/document
|
|
859
990
|
const useQuery = () => {
|
|
991
|
+
if (typeof window === 'undefined') return {}
|
|
860
992
|
const searchParams = new URLSearchParams(window.location.search);
|
|
861
993
|
const query = {};
|
|
862
994
|
for (let [key, value] of searchParams.entries()) {
|
|
@@ -866,6 +998,7 @@
|
|
|
866
998
|
};
|
|
867
999
|
|
|
868
1000
|
const useHash = () => {
|
|
1001
|
+
if (typeof window === 'undefined') return ''
|
|
869
1002
|
const [hash, setHash] = useStore(window.location.hash);
|
|
870
1003
|
useEffect(() => {
|
|
871
1004
|
const onHashChange = () => {
|
|
@@ -933,31 +1066,46 @@
|
|
|
933
1066
|
return notFound
|
|
934
1067
|
};
|
|
935
1068
|
|
|
936
|
-
|
|
937
|
-
|
|
938
|
-
|
|
1069
|
+
/**
|
|
1070
|
+
* RouterProvider universal: acepta contexto externo (SSR/SSG) o usa window.location (SPA).
|
|
1071
|
+
* @param {Object} props - { routes, children, ssrContext }
|
|
1072
|
+
* @example
|
|
1073
|
+
* // SSR/SSG:
|
|
1074
|
+
* <RouterProvider routes={routes} ssrContext={{ location: '/about', query: { q: 'x' } }}>
|
|
1075
|
+
* ...
|
|
1076
|
+
* </RouterProvider>
|
|
1077
|
+
*/
|
|
1078
|
+
const RouterProvider = ({ routes, children, ssrContext }) => {
|
|
1079
|
+
// Si hay contexto externo (SSR/SSG), úsalo
|
|
1080
|
+
const isSSR = typeof window === 'undefined' || !!ssrContext;
|
|
1081
|
+
const location = isSSR
|
|
1082
|
+
? (ssrContext && ssrContext.location) || '/'
|
|
1083
|
+
: window.location.pathname;
|
|
1084
|
+
const [loc, setLoc] = useStore(location);
|
|
1085
|
+
|
|
1086
|
+
// SPA: escucha cambios de ruta
|
|
939
1087
|
useEffect(() => {
|
|
940
|
-
|
|
941
|
-
|
|
1088
|
+
if (isSSR) return
|
|
1089
|
+
const update = () => setLoc(window.location.pathname);
|
|
942
1090
|
window.addEventListener('popstate', update);
|
|
943
1091
|
window.addEventListener('hashchange', update);
|
|
944
1092
|
return () => {
|
|
945
1093
|
window.removeEventListener('popstate', update);
|
|
946
1094
|
window.removeEventListener('hashchange', update);
|
|
947
1095
|
}
|
|
948
|
-
}, [
|
|
1096
|
+
}, [loc]);
|
|
949
1097
|
|
|
950
1098
|
const navigate = (path) => {
|
|
1099
|
+
if (isSSR) return
|
|
951
1100
|
window.history.pushState({}, '', path);
|
|
952
|
-
|
|
1101
|
+
setLoc(path);
|
|
953
1102
|
};
|
|
954
1103
|
|
|
955
|
-
const currentRouteData = findRoute(routes,
|
|
956
|
-
|
|
957
|
-
const query = useQuery();
|
|
1104
|
+
const currentRouteData = findRoute(routes, loc) || {};
|
|
1105
|
+
const query = isSSR ? (ssrContext && ssrContext.query) || {} : useQuery();
|
|
958
1106
|
|
|
959
1107
|
const contextValue = {
|
|
960
|
-
location,
|
|
1108
|
+
location: loc,
|
|
961
1109
|
params: currentRouteData.params || {},
|
|
962
1110
|
query,
|
|
963
1111
|
navigate,
|
|
@@ -967,12 +1115,16 @@
|
|
|
967
1115
|
return createElement(
|
|
968
1116
|
RouterContext.Provider,
|
|
969
1117
|
{ value: contextValue },
|
|
970
|
-
Fragment({
|
|
971
|
-
children: children,
|
|
972
|
-
}),
|
|
1118
|
+
Fragment({ children }),
|
|
973
1119
|
)
|
|
974
1120
|
};
|
|
975
1121
|
|
|
1122
|
+
/**
|
|
1123
|
+
* Universal useRouter: obtiene el contexto de ruta, compatible con SSR/SSG y SPA.
|
|
1124
|
+
* @returns {Object} { location, params, query, navigate, route }
|
|
1125
|
+
* @example
|
|
1126
|
+
* const { location, params, query } = useRouter();
|
|
1127
|
+
*/
|
|
976
1128
|
const useRouter = () => {
|
|
977
1129
|
return RouterContext.useContext('ryunix.navigation')
|
|
978
1130
|
};
|
|
@@ -1036,17 +1188,93 @@
|
|
|
1036
1188
|
};
|
|
1037
1189
|
|
|
1038
1190
|
/**
|
|
1039
|
-
* useMetadata: Hook
|
|
1040
|
-
*
|
|
1041
|
-
*
|
|
1042
|
-
* @param {Object}
|
|
1043
|
-
|
|
1191
|
+
* useMetadata: Hook para gestionar dinámicamente metadatos SEO y recursos en <head>.
|
|
1192
|
+
* Ahora soporta title, meta, link, script, style y bloques personalizados en SSR/SSG.
|
|
1193
|
+
*
|
|
1194
|
+
* @param {Object} tags - Metadatos y recursos a insertar/actualizar.
|
|
1195
|
+
* Soporta: title, canonical, meta, og:*, twitter:*, script, style, custom.
|
|
1196
|
+
* - script/style/custom pueden ser string o array de strings (contenido o etiquetas completas).
|
|
1197
|
+
* @param {Object} options - Opcional. Permite definir template y default para el título.
|
|
1198
|
+
*
|
|
1199
|
+
* Ejemplo avanzado SSR/SSG:
|
|
1200
|
+
* useMetadata({
|
|
1201
|
+
* title: 'Mi página',
|
|
1202
|
+
* description: 'Desc',
|
|
1203
|
+
* script: [
|
|
1204
|
+
* '<script src="/analytics.js"></script>',
|
|
1205
|
+
* '<script>console.log("hi")</script>'
|
|
1206
|
+
* ],
|
|
1207
|
+
* style: '<style>body{background:#000}</style>',
|
|
1208
|
+
* custom: '<!-- Bloque personalizado -->'
|
|
1209
|
+
* })
|
|
1044
1210
|
*/
|
|
1045
|
-
|
|
1046
1211
|
const useMetadata = (tags = {}, options = {}) => {
|
|
1212
|
+
// SSR/SSG: collect metadata in global context if available
|
|
1213
|
+
const ssrContext =
|
|
1214
|
+
typeof globalThis !== 'undefined' && globalThis.__RYUNIX_SSR_CONTEXT__;
|
|
1215
|
+
if (ssrContext) {
|
|
1216
|
+
let finalTitle = '';
|
|
1217
|
+
let template = undefined;
|
|
1218
|
+
let defaultTitle = 'Ryunix App';
|
|
1219
|
+
if (options.title && typeof options.title === 'object') {
|
|
1220
|
+
template = options.title.template;
|
|
1221
|
+
if (typeof options.title.prefix === 'string') {
|
|
1222
|
+
defaultTitle = options.title.prefix;
|
|
1223
|
+
}
|
|
1224
|
+
}
|
|
1225
|
+
let pageTitle = tags.pageTitle || tags.title;
|
|
1226
|
+
if (typeof pageTitle === 'string') {
|
|
1227
|
+
if (pageTitle.trim() === '') {
|
|
1228
|
+
finalTitle = defaultTitle;
|
|
1229
|
+
} else if (template && template.includes('%s')) {
|
|
1230
|
+
finalTitle = template.replace('%s', pageTitle);
|
|
1231
|
+
} else {
|
|
1232
|
+
finalTitle = pageTitle;
|
|
1233
|
+
}
|
|
1234
|
+
} else if (typeof pageTitle === 'object' && pageTitle !== null) {
|
|
1235
|
+
finalTitle = defaultTitle;
|
|
1236
|
+
} else if (!pageTitle) {
|
|
1237
|
+
finalTitle = defaultTitle;
|
|
1238
|
+
}
|
|
1239
|
+
if (finalTitle) {
|
|
1240
|
+
ssrContext.head.push(`<title>${finalTitle}</title>`);
|
|
1241
|
+
}
|
|
1242
|
+
if (tags.canonical) {
|
|
1243
|
+
ssrContext.head.push(`<link rel="canonical" href="${tags.canonical}" />`);
|
|
1244
|
+
}
|
|
1245
|
+
Object.entries(tags).forEach(([key, value]) => {
|
|
1246
|
+
if (key === 'title' || key === 'pageTitle' || key === 'canonical') return
|
|
1247
|
+
if (key.startsWith('og:') || key.startsWith('twitter:')) {
|
|
1248
|
+
ssrContext.head.push(`<meta property="${key}" content="${value}" />`);
|
|
1249
|
+
} else {
|
|
1250
|
+
ssrContext.head.push(`<meta name="${key}" content="${value}" />`);
|
|
1251
|
+
}
|
|
1252
|
+
});
|
|
1253
|
+
// Soporte para script/style/custom
|
|
1254
|
+
if (tags.script) {
|
|
1255
|
+
(Array.isArray(tags.script) ? tags.script : [tags.script]).forEach(
|
|
1256
|
+
(s) => {
|
|
1257
|
+
ssrContext.head.push(s);
|
|
1258
|
+
},
|
|
1259
|
+
);
|
|
1260
|
+
}
|
|
1261
|
+
if (tags.style) {
|
|
1262
|
+
(Array.isArray(tags.style) ? tags.style : [tags.style]).forEach((s) => {
|
|
1263
|
+
ssrContext.head.push(s);
|
|
1264
|
+
});
|
|
1265
|
+
}
|
|
1266
|
+
if (tags.custom) {
|
|
1267
|
+
(Array.isArray(tags.custom) ? tags.custom : [tags.custom]).forEach(
|
|
1268
|
+
(c) => {
|
|
1269
|
+
ssrContext.head.push(c);
|
|
1270
|
+
},
|
|
1271
|
+
);
|
|
1272
|
+
}
|
|
1273
|
+
return
|
|
1274
|
+
}
|
|
1275
|
+
// SPA: fallback to DOM logic
|
|
1047
1276
|
useEffect(() => {
|
|
1048
1277
|
if (typeof document === 'undefined') return // SSR safe
|
|
1049
|
-
|
|
1050
1278
|
let finalTitle = '';
|
|
1051
1279
|
let template = undefined;
|
|
1052
1280
|
let defaultTitle = 'Ryunix App';
|
|
@@ -1056,10 +1284,7 @@
|
|
|
1056
1284
|
defaultTitle = options.title.prefix;
|
|
1057
1285
|
}
|
|
1058
1286
|
}
|
|
1059
|
-
|
|
1060
|
-
// pageTitle tiene prioridad sobre title
|
|
1061
1287
|
let pageTitle = tags.pageTitle || tags.title;
|
|
1062
|
-
|
|
1063
1288
|
if (typeof pageTitle === 'string') {
|
|
1064
1289
|
if (pageTitle.trim() === '') {
|
|
1065
1290
|
finalTitle = defaultTitle;
|
|
@@ -1074,7 +1299,6 @@
|
|
|
1074
1299
|
finalTitle = defaultTitle;
|
|
1075
1300
|
}
|
|
1076
1301
|
document.title = finalTitle;
|
|
1077
|
-
// Canonical
|
|
1078
1302
|
if (tags.canonical) {
|
|
1079
1303
|
let link = document.querySelector('link[rel="canonical"]');
|
|
1080
1304
|
if (!link) {
|
|
@@ -1084,7 +1308,6 @@
|
|
|
1084
1308
|
}
|
|
1085
1309
|
link.setAttribute('href', tags.canonical);
|
|
1086
1310
|
}
|
|
1087
|
-
// Meta tags
|
|
1088
1311
|
Object.entries(tags).forEach(([key, value]) => {
|
|
1089
1312
|
if (key === 'title' || key === 'pageTitle' || key === 'canonical') return
|
|
1090
1313
|
let selector = `meta[name='${key}']`;
|
|
@@ -1129,6 +1352,10 @@
|
|
|
1129
1352
|
init,
|
|
1130
1353
|
Fragment,
|
|
1131
1354
|
Hooks,
|
|
1355
|
+
hydrate,
|
|
1356
|
+
renderToString,
|
|
1357
|
+
withSSRData,
|
|
1358
|
+
withSSGData,
|
|
1132
1359
|
};
|
|
1133
1360
|
|
|
1134
1361
|
window.Ryunix = Ryunix;
|
package/dist/Ryunix.min.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
!function(e,t){"object"==typeof exports&&"undefined"!=typeof module?t(exports,require("lodash")):"function"==typeof define&&define.amd?define(["exports","lodash"],t):t((e="undefined"!=typeof globalThis?globalThis:e||self).Ryunix={},e.lodash)}(this,function(e,t){"use strict";let o={containerRoot:null,nextUnitOfWork:null,currentRoot:null,wipRoot:null,deletions:null,wipFiber:null,hookIndex:null,effects:null};const n=/[A-Z]/g,r=Object.freeze({TEXT_ELEMENT:Symbol("text.element").toString(),Ryunix_ELEMENT:Symbol("ryunix.element").toString(),RYUNIX_EFFECT:Symbol("ryunix.effect").toString(),RYUNIX_MEMO:Symbol("ryunix.memo").toString(),RYUNIX_URL_QUERY:Symbol("ryunix.urlQuery").toString(),RYUNIX_REF:Symbol("ryunix.ref").toString(),RYUNIX_STORE:Symbol("ryunix.store").toString(),RYUNIX_REDUCE:Symbol("ryunix.reduce").toString(),RYUNIX_FRAGMENT:Symbol("ryunix.fragment").toString(),RYUNIX_CONTEXT:Symbol("ryunix.context").toString()}),i=Object.freeze({object:"object",function:"function",style:"ryunix-style",className:"ryunix-class",children:"children",boolean:"boolean",string:"string"}),s=Object.freeze({style:"style",className:"className"}),l=Object.freeze({PLACEMENT:Symbol("ryunix.reconciler.status.placement").toString(),UPDATE:Symbol("ryunix.reconciler.status.update").toString(),DELETION:Symbol("ryunix.reconciler.status.deletion").toString(),NO_EFFECT:Symbol("ryunix.reconciler.status.no_efect").toString()}),a=(e,t,...o)=>({type:e,props:{...t,children:o.flat().map(e=>typeof e===i.object?e:c(e))}}),c=e=>({type:r.TEXT_ELEMENT,props:{nodeValue:e,children:[]}}),u=e=>{const t=Array.isArray(e.children)?e.children:[e.children];return a(r.RYUNIX_FRAGMENT,{},...t)},p=e=>e.startsWith("on"),d=e=>e!==i.children&&!p(e),h=(e,t)=>o=>e[o]!==t[o],f=e=>t=>!(t in e),y=e=>{e&&(e.hooks&&e.hooks.length>0&&e.hooks.filter(e=>e.type===r.RYUNIX_EFFECT&&typeof e.cancel===i.function).forEach(e=>{e.cancel()}),e.child&&y(e.child),e.sibling&&y(e.sibling))},m=e=>{if(e.hooks&&0!==e.hooks.length)for(let t=0;t<e.hooks.length;t++){const o=e.hooks[t];if(o.type===r.RYUNIX_EFFECT&&typeof o.effect===i.function&&null!==o.effect){typeof o.cancel===i.function&&o.cancel();const e=o.effect();o.cancel="function"==typeof e?e:void 0}}},E=(e,t,o)=>{Object.keys(t).filter(p).filter(e=>f(o)(e)||h(t,o)(e)).forEach(o=>{const n=o.toLowerCase().substring(2);e.removeEventListener(n,t[o])}),Object.keys(t).filter(d).filter(f(o)).forEach(t=>{e[t]=""}),Object.keys(o).filter(d).filter(h(t,o)).forEach(n=>{if(n===i.style)b(e,o["ryunix-style"]);else if(n===s.style)b(e,o.style);else if(n===i.className){if(""===o["ryunix-class"])throw new Error("data-class cannot be empty.");t["ryunix-class"]&&e.classList.remove(...t["ryunix-class"].split(/\s+/).filter(Boolean)||[]),e.classList.add(...o["ryunix-class"].split(/\s+/).filter(Boolean))}else if(n===s.className){if(""===o.className)throw new Error("className cannot be empty.");t.className&&e.classList.remove(...t.className.split(/\s+/).filter(Boolean)||[]),e.classList.add(...o.className.split(/\s+/).filter(Boolean))}else e[n]=o[n]}),Object.keys(o).filter(p).filter(h(t,o)).forEach(t=>{const n=t.toLowerCase().substring(2);e.addEventListener(n,o[t])})},b=(e,t)=>{e.style=Object.keys(t).reduce((e,o)=>e+=`${o.replace(n,function(e){return"-"+e.toLowerCase()})}: ${t[o]};`,"")},w=e=>{if(!e)return;let t=e.parent;for(;!t.dom;)t=t.parent;const o=t.dom;if(e.effectTag===l.PLACEMENT)null!=e.dom&&o.appendChild(e.dom),m(e);else if(e.effectTag===l.UPDATE)(e=>{e.hooks&&e.hooks.length>0&&e.hooks.filter(e=>e.type===r.RYUNIX_EFFECT&&e.cancel).forEach(e=>{e.cancel()})})(e),null!=e.dom&&E(e.dom,e.alternate.props,e.props),m(e);else if(e.effectTag===l.DELETION)return y(e),void g(e,o);w(e.child),w(e.sibling)},g=(e,t)=>{if(e.dom)t.removeChild(e.dom);else{let o=e.child;for(;o;)g(o,t),o=o.sibling}},x=(e,t)=>{let n,r=0,i=e.alternate&&e.alternate.child;for(;r<t.length||null!=i;){const s=t[r];let a;const c=i&&s&&s.type==i.type;c&&(a={type:i.type,props:s.props,dom:i.dom,parent:e,alternate:i,effectTag:l.UPDATE,hooks:i.hooks}),s&&!c&&(a={type:s.type,props:s.props,dom:null,parent:e,alternate:null,effectTag:l.PLACEMENT}),i&&!c&&(i.effectTag=l.DELETION,o.deletions.push(i)),i&&(i=i.sibling),0===r?e.child=a:s&&(n.sibling=a),n=a,r++}},k=e=>{const t=Array.isArray(e.props.children)?e.props.children.flat():[e.props.children];e.type===r.RYUNIX_FRAGMENT||e.dom||(e.dom=(e=>{if(e.type===r.RYUNIX_FRAGMENT)return null;const t=e.type==r.TEXT_ELEMENT?document.createTextNode(""):document.createElement(e.type);return E(t,{},e.props),t})(e)),x(e,t)},R=({src:e,props:t})=>{const o=new URLSearchParams,n=!e.startsWith("http")||!e.startsWith("https");t.width&&o.set("width",t.width),t.height&&o.set("height",t.height),t.quality&&o.set("quality",t.quality);const r=t.extension?`@${t.extension}`:"";return n?(()=>{const{hostname:e}=window.location;return"localhost"===e||"127.0.0.1"===e})()?(console.warn("Image optimizations only work with full links and must not contain localhost."),e):`${window.location.origin}/${e}`:`https://image.unsetsoft.com/image/${e}${r}?${o.toString()}`},N=e=>{let t=!1;for(;o.nextUnitOfWork&&!t;)o.nextUnitOfWork=I(o.nextUnitOfWork),t=e.timeRemaining()<1;!o.nextUnitOfWork&&o.wipRoot&&(o.deletions.forEach(w),w(o.wipRoot.child),o.currentRoot=o.wipRoot,o.wipRoot=null),requestIdleCallback(N)};requestIdleCallback(N);const I=e=>{if(e.type instanceof Function?(e=>{o.wipFiber=e,o.hookIndex=0,o.wipFiber.hooks=[];const t=[e.type(e.props)];e.type._contextId&&void 0!==e.props.value&&(e._contextId=e.type._contextId,e._contextValue=e.props.value),x(e,t)})(e):k(e),e.child)return e.child;let t=e;for(;t;){if(t.sibling)return t.sibling;t=t.parent}},v=e=>{o.nextUnitOfWork=e,o.wipRoot=e,o.deletions=[],o.hookIndex=0,o.effects=[],requestIdleCallback(N)},T=(e,t)=>(o.wipRoot={dom:t,props:{children:[e]},alternate:o.currentRoot},o.nextUnitOfWork=o.wipRoot,o.deletions=[],v(o.wipRoot),o.wipRoot),F=(e,t)=>_((e,t)=>"function"==typeof t?t(e):t,e,t),_=(e,t,n)=>{const s=o.wipFiber.alternate&&o.wipFiber.alternate.hooks&&o.wipFiber.alternate.hooks[o.hookIndex],l={hookID:o.hookIndex,type:r.RYUNIX_STORE,state:s?s.state:n?n(t):t,queue:s&&Array.isArray(s.queue)?s.queue.slice():[]};s&&Array.isArray(s.queue)&&s.queue.forEach(t=>{l.state=e(l.state,t)});return l.queue.forEach(t=>{l.state=e(l.state,t)}),o.wipFiber.hooks[o.hookIndex]=l,o.hookIndex++,[l.state,e=>{l.queue.push(typeof e===i.function?e:t=>e),o.wipRoot={dom:o.currentRoot.dom,props:o.currentRoot.props,alternate:o.currentRoot},o.deletions=[],o.hookIndex=0,v(o.wipRoot)}]},S=(e,t)=>{const n=o.wipFiber.alternate&&o.wipFiber.alternate.hooks&&o.wipFiber.alternate.hooks[o.hookIndex],i=(s=n?.deps,l=t,!s||!l||s.length!==l.length||s.some((e,t)=>e!==l[t]));var s,l;const a={hookID:o.hookIndex,type:r.RYUNIX_EFFECT,deps:t,effect:i?e:null,cancel:n?.cancel};o.wipFiber.hooks[o.hookIndex]=a,o.hookIndex++},U=e=>{const t=o.wipFiber.alternate&&o.wipFiber.alternate.hooks&&o.wipFiber.alternate.hooks[o.hookIndex],n={type:r.RYUNIX_REF,value:t?t.value:{current:e}};return o.wipFiber.hooks[o.hookIndex]=n,o.hookIndex++,n.value},C=(e,n)=>{const i=o.wipFiber.alternate&&o.wipFiber.alternate.hooks&&o.wipFiber.alternate.hooks[o.hookIndex],s={type:r.RYUNIX_MEMO,value:null,deps:n};return i&&t.isEqual(i.deps,s.deps)?s.value=i.value:s.value=e(),o.wipFiber.hooks[o.hookIndex]=s,o.hookIndex++,s.value},O=(e,t)=>C(()=>e,t),L=(e=r.RYUNIX_CONTEXT,t={})=>{const n=({children:e})=>u({children:e});n._contextId=e;return{Provider:n,useContext:(e=r.RYUNIX_CONTEXT)=>{let n=o.wipFiber;for(;n;){if(n.type&&n.type._contextId===e)return n.props&&"value"in n.props?n.props.value:void 0;n=n.parent}return t}}},A=()=>{const e=new URLSearchParams(window.location.search),t={};for(let[o,n]of e.entries())t[o]=n;return t},X=()=>{const[e,t]=F(window.location.hash);return S(()=>{const e=()=>{t(window.location.hash)};return window.addEventListener("hashchange",e),()=>window.removeEventListener("hashchange",e)},[]),e},q=L("ryunix.navigation",{location:"/",params:{},query:{},navigate:e=>{},route:null}),Y=(e,t)=>{const o=t.split("?")[0].split("#")[0],n=e.find(e=>e.NotFound),r=n?{route:{component:n.NotFound},params:{}}:{route:{component:null},params:{}};for(const n of e){if(n.subRoutes){const e=Y(n.subRoutes,t);if(e)return e}if("*"===n.path)return r;if(!n.path||"string"!=typeof n.path){console.warn("Invalid route detected:",n),console.info("if you are using { NotFound: NotFound } please add { path: '*', NotFound: NotFound }");continue}const e=[],i=new RegExp(`^${n.path.replace(/:\w+/g,t=>(e.push(t.substring(1)),"([^/]+)"))}$`),s=o.match(i);if(s){return{route:n,params:e.reduce((e,t,o)=>(e[t]=s[o+1],e),{})}}}return r},M=({routes:e,children:t})=>{const[o,n]=F(window.location.pathname);S(()=>{const e=()=>n(window.location.pathname);return window.addEventListener("popstate",e),window.addEventListener("hashchange",e),()=>{window.removeEventListener("popstate",e),window.removeEventListener("hashchange",e)}},[o]);const r=Y(e,o)||{},i=A(),s={location:o,params:r.params||{},query:i,navigate:e=>{window.history.pushState({},"",e),n(e)},route:r.route};return a(q.Provider,{value:s},u({children:t}))},j=()=>q.useContext("ryunix.navigation"),W=()=>{const{route:e,params:t,query:o,location:n}=j();if(!e||!e.component)return null;const r=X();return S(()=>{if(r){const e=r.slice(1),t=document.getElementById(e);t&&t.scrollIntoView({block:"start",behavior:"smooth"})}},[r]),a(e.component,{key:n,params:t,query:o,hash:r})},P=({to:e,exact:t=!1,...o})=>{const{location:n,navigate:r}=j(),i=t?n===e:n.startsWith(e),s=o["ryunix-class"]?"ryunix-class":"className",l="function"==typeof(c=o["ryunix-class"]||o.className)?c({isActive:i}):c||"";var c;const{"ryunix-class":u,className:p,...d}=o;return a("a",{href:e,onClick:t=>{t.preventDefault(),r(e)},[s]:l,...d},o.children)},$=(e={},t={})=>{S(()=>{if("undefined"==typeof document)return;let o,n="",r="Ryunix App";t.title&&"object"==typeof t.title&&(o=t.title.template,"string"==typeof t.title.prefix&&(r=t.title.prefix));let i=e.pageTitle||e.title;if("string"==typeof i?n=""===i.trim()?r:o&&o.includes("%s")?o.replace("%s",i):i:"object"==typeof i&&null!==i?n=r:i||(n=r),document.title=n,e.canonical){let t=document.querySelector('link[rel="canonical"]');t||(t=document.createElement("link"),t.setAttribute("rel","canonical"),document.head.appendChild(t)),t.setAttribute("href",e.canonical)}Object.entries(e).forEach(([e,t])=>{if("title"===e||"pageTitle"===e||"canonical"===e)return;let o=`meta[name='${e}']`;(e.startsWith("og:")||e.startsWith("twitter:"))&&(o=`meta[property='${e}']`);let n=document.head.querySelector(o);n||(n=document.createElement("meta"),e.startsWith("og:")||e.startsWith("twitter:")?n.setAttribute("property",e):n.setAttribute("name",e),document.head.appendChild(n)),n.setAttribute("content",t)})},[JSON.stringify(e),JSON.stringify(t)])};var D={createElement:a,render:T,init:(e,t="__ryunix")=>{o.containerRoot=document.getElementById(t);return T(e,o.containerRoot)},Fragment:u,Hooks:Object.freeze({__proto__:null,Children:W,NavLink:P,RouterProvider:M,createContext:L,useCallback:O,useEffect:S,useHash:X,useMemo:C,useMetadata:$,useQuery:A,useRef:U,useRouter:j,useStore:F})};window.Ryunix=D,e.Children=W,e.Image=({src:e,...t})=>{const o={src:"true"===t.optimization?R({src:e,props:t}):e,...t};return a("img",o,null)},e.NavLink=P,e.RouterProvider=M,e.createContext=L,e.default=D,e.useCallback=O,e.useEffect=S,e.useHash=X,e.useMemo=C,e.useMetadata=$,e.useQuery=A,e.useRef=U,e.useRouter=j,e.useStore=F,Object.defineProperty(e,"__esModule",{value:!0})});
|
|
1
|
+
!function(e,t){"object"==typeof exports&&"undefined"!=typeof module?t(exports,require("lodash")):"function"==typeof define&&define.amd?define(["exports","lodash"],t):t((e="undefined"!=typeof globalThis?globalThis:e||self).Ryunix={},e.lodash)}(this,function(e,t){"use strict";let o={containerRoot:null,nextUnitOfWork:null,currentRoot:null,wipRoot:null,deletions:null,wipFiber:null,hookIndex:null,effects:null};const n=/[A-Z]/g,r=Object.freeze({TEXT_ELEMENT:Symbol("text.element").toString(),Ryunix_ELEMENT:Symbol("ryunix.element").toString(),RYUNIX_EFFECT:Symbol("ryunix.effect").toString(),RYUNIX_MEMO:Symbol("ryunix.memo").toString(),RYUNIX_URL_QUERY:Symbol("ryunix.urlQuery").toString(),RYUNIX_REF:Symbol("ryunix.ref").toString(),RYUNIX_STORE:Symbol("ryunix.store").toString(),RYUNIX_REDUCE:Symbol("ryunix.reduce").toString(),RYUNIX_FRAGMENT:Symbol("ryunix.fragment").toString(),RYUNIX_CONTEXT:Symbol("ryunix.context").toString()}),i=Object.freeze({object:"object",function:"function",style:"ryunix-style",className:"ryunix-class",children:"children",boolean:"boolean",string:"string"}),s=Object.freeze({style:"style",className:"className"}),a=Object.freeze({PLACEMENT:Symbol("ryunix.reconciler.status.placement").toString(),UPDATE:Symbol("ryunix.reconciler.status.update").toString(),DELETION:Symbol("ryunix.reconciler.status.deletion").toString(),NO_EFFECT:Symbol("ryunix.reconciler.status.no_efect").toString()}),l=(e,t,...o)=>({type:e,props:{...t,children:o.flat().map(e=>typeof e===i.object?e:c(e))}}),c=e=>({type:r.TEXT_ELEMENT,props:{nodeValue:e,children:[]}}),u=e=>{const t=Array.isArray(e.children)?e.children:[e.children];return l(r.RYUNIX_FRAGMENT,{},...t)},p=e=>e.startsWith("on"),d=e=>e!==i.children&&!p(e),f=(e,t)=>o=>e[o]!==t[o],h=e=>t=>!(t in e),y=e=>{e&&(e.hooks&&e.hooks.length>0&&e.hooks.filter(e=>e.type===r.RYUNIX_EFFECT&&typeof e.cancel===i.function).forEach(e=>{e.cancel()}),e.child&&y(e.child),e.sibling&&y(e.sibling))},m=e=>{if(e.hooks&&0!==e.hooks.length)for(let t=0;t<e.hooks.length;t++){const o=e.hooks[t];if(o.type===r.RYUNIX_EFFECT&&typeof o.effect===i.function&&null!==o.effect){typeof o.cancel===i.function&&o.cancel();const e=o.effect();o.cancel="function"==typeof e?e:void 0}}},E=(e,t,o)=>{Object.keys(t).filter(p).filter(e=>h(o)(e)||f(t,o)(e)).forEach(o=>{const n=o.toLowerCase().substring(2);e.removeEventListener(n,t[o])}),Object.keys(t).filter(d).filter(h(o)).forEach(t=>{e[t]=""}),Object.keys(o).filter(d).filter(f(t,o)).forEach(n=>{if(n===i.style)w(e,o["ryunix-style"]);else if(n===s.style)w(e,o.style);else if(n===i.className){if(""===o["ryunix-class"])throw new Error("data-class cannot be empty.");t["ryunix-class"]&&e.classList.remove(...t["ryunix-class"].split(/\s+/).filter(Boolean)||[]),e.classList.add(...o["ryunix-class"].split(/\s+/).filter(Boolean))}else if(n===s.className){if(""===o.className)throw new Error("className cannot be empty.");t.className&&e.classList.remove(...t.className.split(/\s+/).filter(Boolean)||[]),e.classList.add(...o.className.split(/\s+/).filter(Boolean))}else e[n]=o[n]}),Object.keys(o).filter(p).filter(f(t,o)).forEach(t=>{const n=t.toLowerCase().substring(2);e.addEventListener(n,o[t])})},w=(e,t)=>{e.style=Object.keys(t).reduce((e,o)=>e+=`${o.replace(n,function(e){return"-"+e.toLowerCase()})}: ${t[o]};`,"")},g=e=>{if(!e)return;let t=e.parent;for(;!t.dom;)t=t.parent;const o=t.dom;if(e.effectTag===a.PLACEMENT)null!=e.dom&&o.appendChild(e.dom),m(e);else if(e.effectTag===a.UPDATE)(e=>{e.hooks&&e.hooks.length>0&&e.hooks.filter(e=>e.type===r.RYUNIX_EFFECT&&e.cancel).forEach(e=>{e.cancel()})})(e),null!=e.dom&&E(e.dom,e.alternate.props,e.props),m(e);else if(e.effectTag===a.DELETION)return y(e),void b(e,o);g(e.child),g(e.sibling)},b=(e,t)=>{if(e.dom)t.removeChild(e.dom);else{let o=e.child;for(;o;)b(o,t),o=o.sibling}},x=(e,t)=>{let n,r=0,i=e.alternate&&e.alternate.child;for(;r<t.length||null!=i;){const s=t[r];let l;const c=i&&s&&s.type==i.type;c&&(l={type:i.type,props:s.props,dom:i.dom,parent:e,alternate:i,effectTag:a.UPDATE,hooks:i.hooks}),s&&!c&&(l={type:s.type,props:s.props,dom:null,parent:e,alternate:null,effectTag:a.PLACEMENT}),i&&!c&&(i.effectTag=a.DELETION,o.deletions.push(i)),i&&(i=i.sibling),0===r?e.child=l:s&&(n.sibling=l),n=l,r++}},R=e=>{const t=Array.isArray(e.props.children)?e.props.children.flat():[e.props.children];e.type===r.RYUNIX_FRAGMENT||e.dom||(e.dom=(e=>{if(e.type===r.RYUNIX_FRAGMENT)return null;const t=e.type==r.TEXT_ELEMENT?document.createTextNode(""):document.createElement(e.type);return E(t,{},e.props),t})(e)),x(e,t)},k=({src:e,props:t})=>{const o=new URLSearchParams,n=!e.startsWith("http")||!e.startsWith("https");t.width&&o.set("width",t.width),t.height&&o.set("height",t.height),t.quality&&o.set("quality",t.quality);const r=t.extension?`@${t.extension}`:"";return n?(()=>{const{hostname:e}=window.location;return"localhost"===e||"127.0.0.1"===e})()?(console.warn("Image optimizations only work with full links and must not contain localhost."),e):`${window.location.origin}/${e}`:`https://image.unsetsoft.com/image/${e}${r}?${o.toString()}`},N=e=>{let t=!1;for(;o.nextUnitOfWork&&!t;)o.nextUnitOfWork=S(o.nextUnitOfWork),t=e.timeRemaining()<1;!o.nextUnitOfWork&&o.wipRoot&&(o.deletions.forEach(g),g(o.wipRoot.child),o.currentRoot=o.wipRoot,o.wipRoot=null),requestIdleCallback(N)};requestIdleCallback(N);const S=e=>{if(e.type instanceof Function?(e=>{o.wipFiber=e,o.hookIndex=0,o.wipFiber.hooks=[];const t=[e.type(e.props)];e.type._contextId&&void 0!==e.props.value&&(e._contextId=e.type._contextId,e._contextValue=e.props.value),x(e,t)})(e):R(e),e.child)return e.child;let t=e;for(;t;){if(t.sibling)return t.sibling;t=t.parent}},_=e=>{o.nextUnitOfWork=e,o.wipRoot=e,o.deletions=[],o.hookIndex=0,o.effects=[],requestIdleCallback(N)},T=(e,t)=>(o.wipRoot={dom:t,props:{children:[e]},alternate:o.currentRoot},o.nextUnitOfWork=o.wipRoot,o.deletions=[],_(o.wipRoot),o.wipRoot);const I=(e,t)=>v((e,t)=>"function"==typeof t?t(e):t,e,t),v=(e,t,n)=>{const s=o.wipFiber.alternate&&o.wipFiber.alternate.hooks&&o.wipFiber.alternate.hooks[o.hookIndex],a={hookID:o.hookIndex,type:r.RYUNIX_STORE,state:s?s.state:n?n(t):t,queue:s&&Array.isArray(s.queue)?s.queue.slice():[]};s&&Array.isArray(s.queue)&&s.queue.forEach(t=>{a.state=e(a.state,t)});return a.queue.forEach(t=>{a.state=e(a.state,t)}),o.wipFiber.hooks[o.hookIndex]=a,o.hookIndex++,[a.state,e=>{a.queue.push(typeof e===i.function?e:t=>e),o.wipRoot={dom:o.currentRoot.dom,props:o.currentRoot.props,alternate:o.currentRoot},o.deletions=[],o.hookIndex=0,_(o.wipRoot)}]},F=(e,t)=>{if("undefined"==typeof window)return void o.hookIndex++;const n=o.wipFiber.alternate&&o.wipFiber.alternate.hooks&&o.wipFiber.alternate.hooks[o.hookIndex],i=(s=n?.deps,a=t,!s||!a||s.length!==a.length||s.some((e,t)=>e!==a[t]));var s,a;const l={hookID:o.hookIndex,type:r.RYUNIX_EFFECT,deps:t,effect:i?e:null,cancel:n?.cancel};o.wipFiber.hooks[o.hookIndex]=l,o.hookIndex++},U=e=>{const t=o.wipFiber.alternate&&o.wipFiber.alternate.hooks&&o.wipFiber.alternate.hooks[o.hookIndex],n={type:r.RYUNIX_REF,value:t?t.value:{current:e}};return o.wipFiber.hooks[o.hookIndex]=n,o.hookIndex++,n.value},A=(e,n)=>{const i=o.wipFiber.alternate&&o.wipFiber.alternate.hooks&&o.wipFiber.alternate.hooks[o.hookIndex],s={type:r.RYUNIX_MEMO,value:null,deps:n};return i&&t.isEqual(i.deps,s.deps)?s.value=i.value:s.value=e(),o.wipFiber.hooks[o.hookIndex]=s,o.hookIndex++,s.value},O=(e,t)=>A(()=>e,t),C=(e=r.RYUNIX_CONTEXT,t={})=>{const n=({children:e})=>u({children:e});n._contextId=e;return{Provider:n,useContext:(e=r.RYUNIX_CONTEXT)=>{let n=o.wipFiber;for(;n;){if(n.type&&n.type._contextId===e)return n.props&&"value"in n.props?n.props.value:void 0;n=n.parent}return t}}},X=()=>{if("undefined"==typeof window)return{};const e=new URLSearchParams(window.location.search),t={};for(let[o,n]of e.entries())t[o]=n;return t},L=()=>{if("undefined"==typeof window)return"";const[e,t]=I(window.location.hash);return F(()=>{const e=()=>{t(window.location.hash)};return window.addEventListener("hashchange",e),()=>window.removeEventListener("hashchange",e)},[]),e},j=C("ryunix.navigation",{location:"/",params:{},query:{},navigate:e=>{},route:null}),Y=(e,t)=>{const o=t.split("?")[0].split("#")[0],n=e.find(e=>e.NotFound),r=n?{route:{component:n.NotFound},params:{}}:{route:{component:null},params:{}};for(const n of e){if(n.subRoutes){const e=Y(n.subRoutes,t);if(e)return e}if("*"===n.path)return r;if(!n.path||"string"!=typeof n.path){console.warn("Invalid route detected:",n),console.info("if you are using { NotFound: NotFound } please add { path: '*', NotFound: NotFound }");continue}const e=[],i=new RegExp(`^${n.path.replace(/:\w+/g,t=>(e.push(t.substring(1)),"([^/]+)"))}$`),s=o.match(i);if(s){return{route:n,params:e.reduce((e,t,o)=>(e[t]=s[o+1],e),{})}}}return r},q=({routes:e,children:t,ssrContext:o})=>{const n="undefined"==typeof window||!!o,r=n?o&&o.location||"/":window.location.pathname,[i,s]=I(r);F(()=>{if(n)return;const e=()=>s(window.location.pathname);return window.addEventListener("popstate",e),window.addEventListener("hashchange",e),()=>{window.removeEventListener("popstate",e),window.removeEventListener("hashchange",e)}},[i]);const a=Y(e,i)||{},c=n?o&&o.query||{}:X(),p={location:i,params:a.params||{},query:c,navigate:e=>{n||(window.history.pushState({},"",e),s(e))},route:a.route};return l(j.Provider,{value:p},u({children:t}))},$=()=>j.useContext("ryunix.navigation"),M=()=>{const{route:e,params:t,query:o,location:n}=$();if(!e||!e.component)return null;const r=L();return F(()=>{if(r){const e=r.slice(1),t=document.getElementById(e);t&&t.scrollIntoView({block:"start",behavior:"smooth"})}},[r]),l(e.component,{key:n,params:t,query:o,hash:r})},D=({to:e,exact:t=!1,...o})=>{const{location:n,navigate:r}=$(),i=t?n===e:n.startsWith(e),s=o["ryunix-class"]?"ryunix-class":"className",a="function"==typeof(c=o["ryunix-class"]||o.className)?c({isActive:i}):c||"";var c;const{"ryunix-class":u,className:p,...d}=o;return l("a",{href:e,onClick:t=>{t.preventDefault(),r(e)},[s]:a,...d},o.children)},W=(e={},t={})=>{const o="undefined"!=typeof globalThis&&globalThis.__RYUNIX_SSR_CONTEXT__;if(o){let n,r="",i="Ryunix App";t.title&&"object"==typeof t.title&&(n=t.title.template,"string"==typeof t.title.prefix&&(i=t.title.prefix));let s=e.pageTitle||e.title;return"string"==typeof s?r=""===s.trim()?i:n&&n.includes("%s")?n.replace("%s",s):s:"object"==typeof s&&null!==s?r=i:s||(r=i),r&&o.head.push(`<title>${r}</title>`),e.canonical&&o.head.push(`<link rel="canonical" href="${e.canonical}" />`),Object.entries(e).forEach(([e,t])=>{"title"!==e&&"pageTitle"!==e&&"canonical"!==e&&(e.startsWith("og:")||e.startsWith("twitter:")?o.head.push(`<meta property="${e}" content="${t}" />`):o.head.push(`<meta name="${e}" content="${t}" />`))}),e.script&&(Array.isArray(e.script)?e.script:[e.script]).forEach(e=>{o.head.push(e)}),e.style&&(Array.isArray(e.style)?e.style:[e.style]).forEach(e=>{o.head.push(e)}),void(e.custom&&(Array.isArray(e.custom)?e.custom:[e.custom]).forEach(e=>{o.head.push(e)}))}F(()=>{if("undefined"==typeof document)return;let o,n="",r="Ryunix App";t.title&&"object"==typeof t.title&&(o=t.title.template,"string"==typeof t.title.prefix&&(r=t.title.prefix));let i=e.pageTitle||e.title;if("string"==typeof i?n=""===i.trim()?r:o&&o.includes("%s")?o.replace("%s",i):i:"object"==typeof i&&null!==i?n=r:i||(n=r),document.title=n,e.canonical){let t=document.querySelector('link[rel="canonical"]');t||(t=document.createElement("link"),t.setAttribute("rel","canonical"),document.head.appendChild(t)),t.setAttribute("href",e.canonical)}Object.entries(e).forEach(([e,t])=>{if("title"===e||"pageTitle"===e||"canonical"===e)return;let o=`meta[name='${e}']`;(e.startsWith("og:")||e.startsWith("twitter:"))&&(o=`meta[property='${e}']`);let n=document.head.querySelector(o);n||(n=document.createElement("meta"),e.startsWith("og:")||e.startsWith("twitter:")?n.setAttribute("property",e):n.setAttribute("name",e),document.head.appendChild(n)),n.setAttribute("content",t)})},[JSON.stringify(e),JSON.stringify(t)])};var P={createElement:l,render:T,init:(e,t="__ryunix")=>{o.containerRoot=document.getElementById(t);return T(e,o.containerRoot)},Fragment:u,Hooks:Object.freeze({__proto__:null,Children:M,NavLink:D,RouterProvider:q,createContext:C,useCallback:O,useEffect:F,useHash:L,useMemo:A,useMetadata:W,useQuery:X,useRef:U,useRouter:$,useStore:I}),hydrate:function(e,t="__ryunix"){let o="string"==typeof t?document.getElementById(t):t;if(!o)throw new Error("No se encontró el contenedor para hidratar");return T(e,o)},renderToString:async function(e,t={}){let o,n=e&&e.type;t&&!t.location&&(t.location="/"),n&&"function"==typeof n&&("function"==typeof n.fetchSSRData&&!1!==t.ssr?o=await n.fetchSSRData(t):"function"==typeof n.fetchSSGData&&!1!==t.ssg&&(o=await n.fetchSSGData(t))),o&&(e={...e,props:{...e.props,...o}});const r={head:[]},i=globalThis.__RYUNIX_SSR_CONTEXT__;globalThis.__RYUNIX_SSR_CONTEXT__=r;const s=function e(o){if("string"==typeof o||"number"==typeof o)return String(o);if(!o||"object"!=typeof o)return"";if("FRAGMENT"===o.type||void 0===o.type)return(Array.isArray(o.children)?o.children:[o.children]).map(e).join("");if("function"==typeof o.type){return e(o.type({...o.props,...t}))}let n=`<${o.type}`;if(o.props)for(const[e,t]of Object.entries(o.props))"children"!==e&&null!=t&&"object"!=typeof t&&(n+=` ${e}="${String(t)}"`);return n+=">",o.props&&o.props.children&&(n+=Array.isArray(o.props.children)?o.props.children.map(e).join(""):e(o.props.children)),n+=`</${o.type}>`,n}(e);return globalThis.__RYUNIX_SSR_CONTEXT__=i,{html:s,head:r.head.join("\n"),data:o}},withSSRData:function(e,t){return e.fetchSSRData=t,e},withSSGData:function(e,t){return e.fetchSSGData=t,e}};window.Ryunix=P,e.Children=M,e.Image=({src:e,...t})=>{const o={src:"true"===t.optimization?k({src:e,props:t}):e,...t};return l("img",o,null)},e.NavLink=D,e.RouterProvider=q,e.createContext=C,e.default=P,e.useCallback=O,e.useEffect=F,e.useHash=L,e.useMemo=A,e.useMetadata=W,e.useQuery=X,e.useRef=U,e.useRouter=$,e.useStore=I,Object.defineProperty(e,"__esModule",{value:!0})});
|