@unsetsoft/ryunixjs 1.1.37 → 1.2.0-canary.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/Ryunix.js +189 -21
- package/dist/Ryunix.min.js +1 -1
- package/package.json +6 -6
package/dist/Ryunix.js
CHANGED
|
@@ -714,16 +714,18 @@
|
|
|
714
714
|
};
|
|
715
715
|
|
|
716
716
|
/**
|
|
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.
|
|
717
|
+
* useEffect seguro para SSR/SSG: no ejecuta efectos en el servidor.
|
|
718
|
+
* @param effect - Función de efecto.
|
|
719
|
+
* @param deps - Dependencias.
|
|
724
720
|
*/
|
|
725
721
|
|
|
726
722
|
const useEffect = (callback, deps) => {
|
|
723
|
+
// No ejecutar efectos en SSR/SSG
|
|
724
|
+
if (typeof window === 'undefined') {
|
|
725
|
+
vars.hookIndex++;
|
|
726
|
+
return
|
|
727
|
+
}
|
|
728
|
+
|
|
727
729
|
const oldHook =
|
|
728
730
|
vars.wipFiber.alternate &&
|
|
729
731
|
vars.wipFiber.alternate.hooks &&
|
|
@@ -856,7 +858,9 @@
|
|
|
856
858
|
}
|
|
857
859
|
};
|
|
858
860
|
|
|
861
|
+
// Proteger hooks que usan window/document
|
|
859
862
|
const useQuery = () => {
|
|
863
|
+
if (typeof window === 'undefined') return {}
|
|
860
864
|
const searchParams = new URLSearchParams(window.location.search);
|
|
861
865
|
const query = {};
|
|
862
866
|
for (let [key, value] of searchParams.entries()) {
|
|
@@ -866,6 +870,7 @@
|
|
|
866
870
|
};
|
|
867
871
|
|
|
868
872
|
const useHash = () => {
|
|
873
|
+
if (typeof window === 'undefined') return ''
|
|
869
874
|
const [hash, setHash] = useStore(window.location.hash);
|
|
870
875
|
useEffect(() => {
|
|
871
876
|
const onHashChange = () => {
|
|
@@ -933,31 +938,46 @@
|
|
|
933
938
|
return notFound
|
|
934
939
|
};
|
|
935
940
|
|
|
936
|
-
|
|
937
|
-
|
|
938
|
-
|
|
941
|
+
/**
|
|
942
|
+
* RouterProvider universal: acepta contexto externo (SSR/SSG) o usa window.location (SPA).
|
|
943
|
+
* @param {Object} props - { routes, children, ssrContext }
|
|
944
|
+
* @example
|
|
945
|
+
* // SSR/SSG:
|
|
946
|
+
* <RouterProvider routes={routes} ssrContext={{ location: '/about', query: { q: 'x' } }}>
|
|
947
|
+
* ...
|
|
948
|
+
* </RouterProvider>
|
|
949
|
+
*/
|
|
950
|
+
const RouterProvider = ({ routes, children, ssrContext }) => {
|
|
951
|
+
// Si hay contexto externo (SSR/SSG), úsalo
|
|
952
|
+
const isSSR = typeof window === 'undefined' || !!ssrContext;
|
|
953
|
+
const location = isSSR
|
|
954
|
+
? (ssrContext && ssrContext.location) || '/'
|
|
955
|
+
: window.location.pathname;
|
|
956
|
+
const [loc, setLoc] = useStore(location);
|
|
957
|
+
|
|
958
|
+
// SPA: escucha cambios de ruta
|
|
939
959
|
useEffect(() => {
|
|
940
|
-
|
|
941
|
-
|
|
960
|
+
if (isSSR) return
|
|
961
|
+
const update = () => setLoc(window.location.pathname);
|
|
942
962
|
window.addEventListener('popstate', update);
|
|
943
963
|
window.addEventListener('hashchange', update);
|
|
944
964
|
return () => {
|
|
945
965
|
window.removeEventListener('popstate', update);
|
|
946
966
|
window.removeEventListener('hashchange', update);
|
|
947
967
|
}
|
|
948
|
-
}, [
|
|
968
|
+
}, [loc]);
|
|
949
969
|
|
|
950
970
|
const navigate = (path) => {
|
|
971
|
+
if (isSSR) return
|
|
951
972
|
window.history.pushState({}, '', path);
|
|
952
|
-
|
|
973
|
+
setLoc(path);
|
|
953
974
|
};
|
|
954
975
|
|
|
955
|
-
const currentRouteData = findRoute(routes,
|
|
956
|
-
|
|
957
|
-
const query = useQuery();
|
|
976
|
+
const currentRouteData = findRoute(routes, loc) || {};
|
|
977
|
+
const query = isSSR ? (ssrContext && ssrContext.query) || {} : useQuery();
|
|
958
978
|
|
|
959
979
|
const contextValue = {
|
|
960
|
-
location,
|
|
980
|
+
location: loc,
|
|
961
981
|
params: currentRouteData.params || {},
|
|
962
982
|
query,
|
|
963
983
|
navigate,
|
|
@@ -967,12 +987,16 @@
|
|
|
967
987
|
return createElement(
|
|
968
988
|
RouterContext.Provider,
|
|
969
989
|
{ value: contextValue },
|
|
970
|
-
Fragment({
|
|
971
|
-
children: children,
|
|
972
|
-
}),
|
|
990
|
+
Fragment({ children }),
|
|
973
991
|
)
|
|
974
992
|
};
|
|
975
993
|
|
|
994
|
+
/**
|
|
995
|
+
* Universal useRouter: obtiene el contexto de ruta, compatible con SSR/SSG y SPA.
|
|
996
|
+
* @returns {Object} { location, params, query, navigate, route }
|
|
997
|
+
* @example
|
|
998
|
+
* const { location, params, query } = useRouter();
|
|
999
|
+
*/
|
|
976
1000
|
const useRouter = () => {
|
|
977
1001
|
return RouterContext.useContext('ryunix.navigation')
|
|
978
1002
|
};
|
|
@@ -1035,6 +1059,148 @@
|
|
|
1035
1059
|
)
|
|
1036
1060
|
};
|
|
1037
1061
|
|
|
1062
|
+
/**
|
|
1063
|
+
* useMetadata: Hook para gestionar dinámicamente metadatos SEO y recursos en <head>.
|
|
1064
|
+
* Ahora soporta title, meta, link, script, style y bloques personalizados en SSR/SSG.
|
|
1065
|
+
*
|
|
1066
|
+
* @param {Object} tags - Metadatos y recursos a insertar/actualizar.
|
|
1067
|
+
* Soporta: title, canonical, meta, og:*, twitter:*, script, style, custom.
|
|
1068
|
+
* - script/style/custom pueden ser string o array de strings (contenido o etiquetas completas).
|
|
1069
|
+
* @param {Object} options - Opcional. Permite definir template y default para el título.
|
|
1070
|
+
*
|
|
1071
|
+
* Ejemplo avanzado SSR/SSG:
|
|
1072
|
+
* useMetadata({
|
|
1073
|
+
* title: 'Mi página',
|
|
1074
|
+
* description: 'Desc',
|
|
1075
|
+
* script: [
|
|
1076
|
+
* '<script src="/analytics.js"></script>',
|
|
1077
|
+
* '<script>console.log("hi")</script>'
|
|
1078
|
+
* ],
|
|
1079
|
+
* style: '<style>body{background:#000}</style>',
|
|
1080
|
+
* custom: '<!-- Bloque personalizado -->'
|
|
1081
|
+
* })
|
|
1082
|
+
*/
|
|
1083
|
+
const useMetadata = (tags = {}, options = {}) => {
|
|
1084
|
+
// SSR/SSG: collect metadata in global context if available
|
|
1085
|
+
const ssrContext =
|
|
1086
|
+
typeof globalThis !== 'undefined' && globalThis.__RYUNIX_SSR_CONTEXT__;
|
|
1087
|
+
if (ssrContext) {
|
|
1088
|
+
let finalTitle = '';
|
|
1089
|
+
let template = undefined;
|
|
1090
|
+
let defaultTitle = 'Ryunix App';
|
|
1091
|
+
if (options.title && typeof options.title === 'object') {
|
|
1092
|
+
template = options.title.template;
|
|
1093
|
+
if (typeof options.title.prefix === 'string') {
|
|
1094
|
+
defaultTitle = options.title.prefix;
|
|
1095
|
+
}
|
|
1096
|
+
}
|
|
1097
|
+
let pageTitle = tags.pageTitle || tags.title;
|
|
1098
|
+
if (typeof pageTitle === 'string') {
|
|
1099
|
+
if (pageTitle.trim() === '') {
|
|
1100
|
+
finalTitle = defaultTitle;
|
|
1101
|
+
} else if (template && template.includes('%s')) {
|
|
1102
|
+
finalTitle = template.replace('%s', pageTitle);
|
|
1103
|
+
} else {
|
|
1104
|
+
finalTitle = pageTitle;
|
|
1105
|
+
}
|
|
1106
|
+
} else if (typeof pageTitle === 'object' && pageTitle !== null) {
|
|
1107
|
+
finalTitle = defaultTitle;
|
|
1108
|
+
} else if (!pageTitle) {
|
|
1109
|
+
finalTitle = defaultTitle;
|
|
1110
|
+
}
|
|
1111
|
+
if (finalTitle) {
|
|
1112
|
+
ssrContext.head.push(`<title>${finalTitle}</title>`);
|
|
1113
|
+
}
|
|
1114
|
+
if (tags.canonical) {
|
|
1115
|
+
ssrContext.head.push(`<link rel="canonical" href="${tags.canonical}" />`);
|
|
1116
|
+
}
|
|
1117
|
+
Object.entries(tags).forEach(([key, value]) => {
|
|
1118
|
+
if (key === 'title' || key === 'pageTitle' || key === 'canonical') return
|
|
1119
|
+
if (key.startsWith('og:') || key.startsWith('twitter:')) {
|
|
1120
|
+
ssrContext.head.push(`<meta property="${key}" content="${value}" />`);
|
|
1121
|
+
} else {
|
|
1122
|
+
ssrContext.head.push(`<meta name="${key}" content="${value}" />`);
|
|
1123
|
+
}
|
|
1124
|
+
});
|
|
1125
|
+
// Soporte para script/style/custom
|
|
1126
|
+
if (tags.script) {
|
|
1127
|
+
(Array.isArray(tags.script) ? tags.script : [tags.script]).forEach(
|
|
1128
|
+
(s) => {
|
|
1129
|
+
ssrContext.head.push(s);
|
|
1130
|
+
},
|
|
1131
|
+
);
|
|
1132
|
+
}
|
|
1133
|
+
if (tags.style) {
|
|
1134
|
+
(Array.isArray(tags.style) ? tags.style : [tags.style]).forEach((s) => {
|
|
1135
|
+
ssrContext.head.push(s);
|
|
1136
|
+
});
|
|
1137
|
+
}
|
|
1138
|
+
if (tags.custom) {
|
|
1139
|
+
(Array.isArray(tags.custom) ? tags.custom : [tags.custom]).forEach(
|
|
1140
|
+
(c) => {
|
|
1141
|
+
ssrContext.head.push(c);
|
|
1142
|
+
},
|
|
1143
|
+
);
|
|
1144
|
+
}
|
|
1145
|
+
return
|
|
1146
|
+
}
|
|
1147
|
+
// SPA: fallback to DOM logic
|
|
1148
|
+
useEffect(() => {
|
|
1149
|
+
if (typeof document === 'undefined') return // SSR safe
|
|
1150
|
+
let finalTitle = '';
|
|
1151
|
+
let template = undefined;
|
|
1152
|
+
let defaultTitle = 'Ryunix App';
|
|
1153
|
+
if (options.title && typeof options.title === 'object') {
|
|
1154
|
+
template = options.title.template;
|
|
1155
|
+
if (typeof options.title.prefix === 'string') {
|
|
1156
|
+
defaultTitle = options.title.prefix;
|
|
1157
|
+
}
|
|
1158
|
+
}
|
|
1159
|
+
let pageTitle = tags.pageTitle || tags.title;
|
|
1160
|
+
if (typeof pageTitle === 'string') {
|
|
1161
|
+
if (pageTitle.trim() === '') {
|
|
1162
|
+
finalTitle = defaultTitle;
|
|
1163
|
+
} else if (template && template.includes('%s')) {
|
|
1164
|
+
finalTitle = template.replace('%s', pageTitle);
|
|
1165
|
+
} else {
|
|
1166
|
+
finalTitle = pageTitle;
|
|
1167
|
+
}
|
|
1168
|
+
} else if (typeof pageTitle === 'object' && pageTitle !== null) {
|
|
1169
|
+
finalTitle = defaultTitle;
|
|
1170
|
+
} else if (!pageTitle) {
|
|
1171
|
+
finalTitle = defaultTitle;
|
|
1172
|
+
}
|
|
1173
|
+
document.title = finalTitle;
|
|
1174
|
+
if (tags.canonical) {
|
|
1175
|
+
let link = document.querySelector('link[rel="canonical"]');
|
|
1176
|
+
if (!link) {
|
|
1177
|
+
link = document.createElement('link');
|
|
1178
|
+
link.setAttribute('rel', 'canonical');
|
|
1179
|
+
document.head.appendChild(link);
|
|
1180
|
+
}
|
|
1181
|
+
link.setAttribute('href', tags.canonical);
|
|
1182
|
+
}
|
|
1183
|
+
Object.entries(tags).forEach(([key, value]) => {
|
|
1184
|
+
if (key === 'title' || key === 'pageTitle' || key === 'canonical') return
|
|
1185
|
+
let selector = `meta[name='${key}']`;
|
|
1186
|
+
if (key.startsWith('og:') || key.startsWith('twitter:')) {
|
|
1187
|
+
selector = `meta[property='${key}']`;
|
|
1188
|
+
}
|
|
1189
|
+
let meta = document.head.querySelector(selector);
|
|
1190
|
+
if (!meta) {
|
|
1191
|
+
meta = document.createElement('meta');
|
|
1192
|
+
if (key.startsWith('og:') || key.startsWith('twitter:')) {
|
|
1193
|
+
meta.setAttribute('property', key);
|
|
1194
|
+
} else {
|
|
1195
|
+
meta.setAttribute('name', key);
|
|
1196
|
+
}
|
|
1197
|
+
document.head.appendChild(meta);
|
|
1198
|
+
}
|
|
1199
|
+
meta.setAttribute('content', value);
|
|
1200
|
+
});
|
|
1201
|
+
}, [JSON.stringify(tags), JSON.stringify(options)]);
|
|
1202
|
+
};
|
|
1203
|
+
|
|
1038
1204
|
var Hooks = /*#__PURE__*/Object.freeze({
|
|
1039
1205
|
__proto__: null,
|
|
1040
1206
|
Children: Children,
|
|
@@ -1045,6 +1211,7 @@
|
|
|
1045
1211
|
useEffect: useEffect,
|
|
1046
1212
|
useHash: useHash,
|
|
1047
1213
|
useMemo: useMemo,
|
|
1214
|
+
useMetadata: useMetadata,
|
|
1048
1215
|
useQuery: useQuery,
|
|
1049
1216
|
useRef: useRef,
|
|
1050
1217
|
useRouter: useRouter,
|
|
@@ -1071,6 +1238,7 @@
|
|
|
1071
1238
|
exports.useEffect = useEffect;
|
|
1072
1239
|
exports.useHash = useHash;
|
|
1073
1240
|
exports.useMemo = useMemo;
|
|
1241
|
+
exports.useMetadata = useMetadata;
|
|
1074
1242
|
exports.useQuery = useQuery;
|
|
1075
1243
|
exports.useRef = useRef;
|
|
1076
1244
|
exports.useRouter = useRouter;
|
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)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(h(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]};`),"")},b=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 x(e,o);b(e.child),b(e.sibling)},x=(e,t)=>{if(e.dom)t.removeChild(e.dom);else{let o=e.child;for(;o;)x(o,t),o=o.sibling}},g=(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)),g(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(b),b(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),g(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)},F=(e,t)=>(o.wipRoot={dom:t,props:{children:[e]},alternate:o.currentRoot},o.nextUnitOfWork=o.wipRoot,o.deletions=[],v(o.wipRoot),o.wipRoot),T=(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},L=(e,t)=>C((()=>e),t),O=(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=()=>{const e=new URLSearchParams(window.location.search),t={};for(let[o,n]of e.entries())t[o]=n;return t},Y=()=>{const[e,t]=T(window.location.hash);return S((()=>{const e=()=>{t(window.location.hash)};return window.addEventListener("hashchange",e),()=>window.removeEventListener("hashchange",e)}),[]),e},A=O("ryunix.navigation",{location:"/",params:{},query:{},navigate:e=>{},route:null}),q=(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=q(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]=T(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=q(e,o)||{},i=X(),s={location:o,params:r.params||{},query:i,navigate:e=>{window.history.pushState({},"",e),n(e)},route:r.route};return a(A.Provider,{value:s},u({children:t}))},j=()=>A.useContext("ryunix.navigation"),P=()=>{const{route:e,params:t,query:o,location:n}=j();if(!e||!e.component)return null;const r=Y();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})},W=({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)};var D={createElement:a,render:F,init:(e,t="__ryunix")=>{o.containerRoot=document.getElementById(t);return F(e,o.containerRoot)},Fragment:u,Hooks:Object.freeze({__proto__:null,Children:P,NavLink:W,RouterProvider:M,createContext:O,useCallback:L,useEffect:S,useHash:Y,useMemo:C,useQuery:X,useRef:U,useRouter:j,useStore:T})};window.Ryunix=D,e.Children=P,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=W,e.RouterProvider=M,e.createContext=O,e.default=D,e.useCallback=L,e.useEffect=S,e.useHash=Y,e.useMemo=C,e.useQuery=X,e.useRef=U,e.useRouter=j,e.useStore=T,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),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)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(h(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]};`,"")},b=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 g(e,o);b(e.child),b(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 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++}},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(b),b(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}},T=e=>{o.nextUnitOfWork=e,o.wipRoot=e,o.deletions=[],o.hookIndex=0,o.effects=[],requestIdleCallback(N)},v=(e,t)=>(o.wipRoot={dom:t,props:{children:[e]},alternate:o.currentRoot},o.nextUnitOfWork=o.wipRoot,o.deletions=[],T(o.wipRoot),o.wipRoot),_=(e,t)=>F((e,t)=>"function"==typeof t?t(e):t,e,t),F=(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,T(o.wipRoot)}]},S=(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},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),A=(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}}},L=()=>{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},X=()=>{if("undefined"==typeof window)return"";const[e,t]=_(window.location.hash);return S(()=>{const e=()=>{t(window.location.hash)};return window.addEventListener("hashchange",e),()=>window.removeEventListener("hashchange",e)},[]),e},q=A("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},j=({routes:e,children:t,ssrContext:o})=>{const n="undefined"==typeof window||!!o,r=n?o&&o.location||"/":window.location.pathname,[i,s]=_(r);S(()=>{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||{}:L(),p={location:i,params:a.params||{},query:c,navigate:e=>{n||(window.history.pushState({},"",e),s(e))},route:a.route};return l(q.Provider,{value:p},u({children:t}))},M=()=>q.useContext("ryunix.navigation"),$=()=>{const{route:e,params:t,query:o,location:n}=M();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]),l(e.component,{key:n,params:t,query:o,hash:r})},W=({to:e,exact:t=!1,...o})=>{const{location:n,navigate:r}=M(),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)},P=(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)}))}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:l,render:v,init:(e,t="__ryunix")=>{o.containerRoot=document.getElementById(t);return v(e,o.containerRoot)},Fragment:u,Hooks:Object.freeze({__proto__:null,Children:$,NavLink:W,RouterProvider:j,createContext:A,useCallback:O,useEffect:S,useHash:X,useMemo:C,useMetadata:P,useQuery:L,useRef:U,useRouter:M,useStore:_})};window.Ryunix=D,e.Children=$,e.Image=({src:e,...t})=>{const o={src:"true"===t.optimization?R({src:e,props:t}):e,...t};return l("img",o,null)},e.NavLink=W,e.RouterProvider=j,e.createContext=A,e.default=D,e.useCallback=O,e.useEffect=S,e.useHash=X,e.useMemo=C,e.useMetadata=P,e.useQuery=L,e.useRef=U,e.useRouter=M,e.useStore=_,Object.defineProperty(e,"__esModule",{value:!0})});
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@unsetsoft/ryunixjs",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.2.0-canary.0",
|
|
4
4
|
"license": "MIT",
|
|
5
5
|
"main": "./dist/Ryunix.min.js",
|
|
6
6
|
"types": "./dist/Ryunix.d.ts",
|
|
@@ -22,16 +22,16 @@
|
|
|
22
22
|
},
|
|
23
23
|
"dependencies": {
|
|
24
24
|
"@rollup/plugin-terser": "0.4.4",
|
|
25
|
-
"eslint": "
|
|
25
|
+
"eslint": "9.29.0",
|
|
26
26
|
"lodash": "^4.17.21",
|
|
27
27
|
"rollup": "^4.41.0"
|
|
28
28
|
},
|
|
29
29
|
"devDependencies": {
|
|
30
|
-
"@babel/core": "7.
|
|
30
|
+
"@babel/core": "7.27.4",
|
|
31
31
|
"@babel/preset-env": "^7.27.2",
|
|
32
|
-
"babel-jest": "
|
|
33
|
-
"jest": "
|
|
34
|
-
"jest-environment-jsdom": "^
|
|
32
|
+
"babel-jest": "30.0.2",
|
|
33
|
+
"jest": "30.0.2",
|
|
34
|
+
"jest-environment-jsdom": "^30.0.2"
|
|
35
35
|
},
|
|
36
36
|
"engines": {
|
|
37
37
|
"node": "^18 || ^20 || ^22"
|