diff --git a/.vitepress/cache/deps/_metadata.json b/.vitepress/cache/deps/_metadata.json index b2b50bc8..34f04ccd 100644 --- a/.vitepress/cache/deps/_metadata.json +++ b/.vitepress/cache/deps/_metadata.json @@ -1,29 +1,29 @@ { - "hash": "9d7bd9d3", - "browserHash": "471d76a2", + "hash": "831dfe67", + "browserHash": "531b02b6", "optimized": { "vue": { - "src": "../../../node_modules/.pnpm/vue@3.3.4/node_modules/vue/dist/vue.runtime.esm-browser.js", + "src": "../../../node_modules/.pnpm/vue@3.4.26/node_modules/vue/dist/vue.runtime.esm-browser.js", "file": "vue.js", - "fileHash": "e0742c69", + "fileHash": "7b0cf463", "needsInterop": false }, "vitepress > @vue/devtools-api": { "src": "../../../node_modules/.pnpm/@vue+devtools-api@6.5.0/node_modules/@vue/devtools-api/lib/esm/index.js", "file": "vitepress___@vue_devtools-api.js", - "fileHash": "2f2059e7", + "fileHash": "9b0f0d7d", "needsInterop": false }, "gsap": { "src": "../../../node_modules/.pnpm/gsap@3.9.0/node_modules/gsap/index.js", "file": "gsap.js", - "fileHash": "794a5241", + "fileHash": "301fcb35", "needsInterop": false }, "dynamics.js": { "src": "../../../node_modules/.pnpm/dynamics.js@1.1.5/node_modules/dynamics.js/lib/dynamics.js", "file": "dynamics__js.js", - "fileHash": "3d12462a", + "fileHash": "ce6bea05", "needsInterop": true } }, diff --git a/.vitepress/cache/deps/vue.js b/.vitepress/cache/deps/vue.js index cf229609..e755f543 100644 --- a/.vitepress/cache/deps/vue.js +++ b/.vitepress/cache/deps/vue.js @@ -1,21 +1,17 @@ import "./chunk-76J2PTFD.js"; -// node_modules/.pnpm/vue@3.3.4/node_modules/vue/dist/vue.runtime.esm-browser.js +// node_modules/.pnpm/vue@3.4.26/node_modules/vue/dist/vue.runtime.esm-browser.js function makeMap(str, expectsLowerCase) { - const map2 = /* @__PURE__ */ Object.create(null); - const list = str.split(","); - for (let i = 0; i < list.length; i++) { - map2[list[i]] = true; - } - return expectsLowerCase ? (val) => !!map2[val.toLowerCase()] : (val) => !!map2[val]; + const set2 = new Set(str.split(",")); + return (val) => set2.has(val); } var EMPTY_OBJ = Object.freeze({}); var EMPTY_ARR = Object.freeze([]); var NOOP = () => { }; var NO = () => false; -var onRE = /^on[^a-z]/; -var isOn = (key) => onRE.test(key); +var isOn = (key) => key.charCodeAt(0) === 111 && key.charCodeAt(1) === 110 && // uppercase letter +(key.charCodeAt(2) > 122 || key.charCodeAt(2) < 97); var isModelListener = (key) => key.startsWith("onUpdate:"); var extend = Object.assign; var remove = (arr, el) => { @@ -36,7 +32,7 @@ var isString = (val) => typeof val === "string"; var isSymbol = (val) => typeof val === "symbol"; var isObject = (val) => val !== null && typeof val === "object"; var isPromise = (val) => { - return isObject(val) && isFunction(val.then) && isFunction(val.catch); + return (isObject(val) || isFunction(val)) && isFunction(val.then) && isFunction(val.catch); }; var objectToString = Object.prototype.toString; var toTypeString = (value) => objectToString.call(value); @@ -67,22 +63,24 @@ var hyphenateRE = /\B([A-Z])/g; var hyphenate = cacheStringFunction( (str) => str.replace(hyphenateRE, "-$1").toLowerCase() ); -var capitalize = cacheStringFunction( - (str) => str.charAt(0).toUpperCase() + str.slice(1) -); -var toHandlerKey = cacheStringFunction( - (str) => str ? `on${capitalize(str)}` : `` -); +var capitalize = cacheStringFunction((str) => { + return str.charAt(0).toUpperCase() + str.slice(1); +}); +var toHandlerKey = cacheStringFunction((str) => { + const s = str ? `on${capitalize(str)}` : ``; + return s; +}); var hasChanged = (value, oldValue) => !Object.is(value, oldValue); var invokeArrayFns = (fns, arg) => { for (let i = 0; i < fns.length; i++) { fns[i](arg); } }; -var def = (obj, key, value) => { +var def = (obj, key, value, writable = false) => { Object.defineProperty(obj, key, { configurable: true, enumerable: false, + writable, value }); }; @@ -98,8 +96,8 @@ var _globalThis; var getGlobalThis = () => { return _globalThis || (_globalThis = typeof globalThis !== "undefined" ? globalThis : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : typeof global !== "undefined" ? global : {}); }; -var GLOBALS_WHITE_LISTED = "Infinity,undefined,NaN,isFinite,isNaN,parseFloat,parseInt,decodeURI,decodeURIComponent,encodeURI,encodeURIComponent,Math,Number,Date,Array,Object,Boolean,String,RegExp,Map,Set,JSON,Intl,BigInt,console"; -var isGloballyWhitelisted = makeMap(GLOBALS_WHITE_LISTED); +var GLOBALS_ALLOWED = "Infinity,undefined,NaN,isFinite,isNaN,parseFloat,parseInt,decodeURI,decodeURIComponent,encodeURI,encodeURIComponent,Math,Number,Date,Array,Object,Boolean,String,RegExp,Map,Set,JSON,Intl,BigInt,console,Error"; +var isGloballyAllowed = makeMap(GLOBALS_ALLOWED); function normalizeStyle(value) { if (isArray(value)) { const res = {}; @@ -113,9 +111,7 @@ function normalizeStyle(value) { } } return res; - } else if (isString(value)) { - return value; - } else if (isObject(value)) { + } else if (isString(value) || isObject(value)) { return value; } } @@ -132,6 +128,20 @@ function parseStringStyle(cssText) { }); return ret; } +function stringifyStyle(styles) { + let ret = ""; + if (!styles || isString(styles)) { + return ret; + } + for (const key in styles) { + const value = styles[key]; + const normalizedKey = key.startsWith(`--`) ? key : hyphenate(key); + if (isString(value) || typeof value === "number") { + ret += `${normalizedKey}:${value};`; + } + } + return ret; +} function normalizeClass(value) { let res = ""; if (isString(value)) { @@ -166,13 +176,31 @@ function normalizeProps(props) { } var HTML_TAGS = "html,body,base,head,link,meta,style,title,address,article,aside,footer,header,hgroup,h1,h2,h3,h4,h5,h6,nav,section,div,dd,dl,dt,figcaption,figure,picture,hr,img,li,main,ol,p,pre,ul,a,b,abbr,bdi,bdo,br,cite,code,data,dfn,em,i,kbd,mark,q,rp,rt,ruby,s,samp,small,span,strong,sub,sup,time,u,var,wbr,area,audio,map,track,video,embed,object,param,source,canvas,script,noscript,del,ins,caption,col,colgroup,table,thead,tbody,td,th,tr,button,datalist,fieldset,form,input,label,legend,meter,optgroup,option,output,progress,select,textarea,details,dialog,menu,summary,template,blockquote,iframe,tfoot"; var SVG_TAGS = "svg,animate,animateMotion,animateTransform,circle,clipPath,color-profile,defs,desc,discard,ellipse,feBlend,feColorMatrix,feComponentTransfer,feComposite,feConvolveMatrix,feDiffuseLighting,feDisplacementMap,feDistantLight,feDropShadow,feFlood,feFuncA,feFuncB,feFuncG,feFuncR,feGaussianBlur,feImage,feMerge,feMergeNode,feMorphology,feOffset,fePointLight,feSpecularLighting,feSpotLight,feTile,feTurbulence,filter,foreignObject,g,hatch,hatchpath,image,line,linearGradient,marker,mask,mesh,meshgradient,meshpatch,meshrow,metadata,mpath,path,pattern,polygon,polyline,radialGradient,rect,set,solidcolor,stop,switch,symbol,text,textPath,title,tspan,unknown,use,view"; +var MATH_TAGS = "annotation,annotation-xml,maction,maligngroup,malignmark,math,menclose,merror,mfenced,mfrac,mfraction,mglyph,mi,mlabeledtr,mlongdiv,mmultiscripts,mn,mo,mover,mpadded,mphantom,mprescripts,mroot,mrow,ms,mscarries,mscarry,msgroup,msline,mspace,msqrt,msrow,mstack,mstyle,msub,msubsup,msup,mtable,mtd,mtext,mtr,munder,munderover,none,semantics"; var isHTMLTag = makeMap(HTML_TAGS); var isSVGTag = makeMap(SVG_TAGS); +var isMathMLTag = makeMap(MATH_TAGS); var specialBooleanAttrs = `itemscope,allowfullscreen,formnovalidate,ismap,nomodule,novalidate,readonly`; var isSpecialBooleanAttr = makeMap(specialBooleanAttrs); +var isBooleanAttr = makeMap( + specialBooleanAttrs + `,async,autofocus,autoplay,controls,default,defer,disabled,hidden,inert,loop,open,required,reversed,scoped,seamless,checked,muted,multiple,selected` +); function includeBooleanAttr(value) { return !!value || value === ""; } +var isKnownHtmlAttr = makeMap( + `accept,accept-charset,accesskey,action,align,allow,alt,async,autocapitalize,autocomplete,autofocus,autoplay,background,bgcolor,border,buffered,capture,challenge,charset,checked,cite,class,code,codebase,color,cols,colspan,content,contenteditable,contextmenu,controls,coords,crossorigin,csp,data,datetime,decoding,default,defer,dir,dirname,disabled,download,draggable,dropzone,enctype,enterkeyhint,for,form,formaction,formenctype,formmethod,formnovalidate,formtarget,headers,height,hidden,high,href,hreflang,http-equiv,icon,id,importance,inert,integrity,ismap,itemprop,keytype,kind,label,lang,language,loading,list,loop,low,manifest,max,maxlength,minlength,media,min,multiple,muted,name,novalidate,open,optimum,pattern,ping,placeholder,poster,preload,radiogroup,readonly,referrerpolicy,rel,required,reversed,rows,rowspan,sandbox,scope,scoped,selected,shape,size,sizes,slot,span,spellcheck,src,srcdoc,srclang,srcset,start,step,style,summary,tabindex,target,title,translate,type,usemap,value,width,wrap` +); +var isKnownSvgAttr = makeMap( + `xmlns,accent-height,accumulate,additive,alignment-baseline,alphabetic,amplitude,arabic-form,ascent,attributeName,attributeType,azimuth,baseFrequency,baseline-shift,baseProfile,bbox,begin,bias,by,calcMode,cap-height,class,clip,clipPathUnits,clip-path,clip-rule,color,color-interpolation,color-interpolation-filters,color-profile,color-rendering,contentScriptType,contentStyleType,crossorigin,cursor,cx,cy,d,decelerate,descent,diffuseConstant,direction,display,divisor,dominant-baseline,dur,dx,dy,edgeMode,elevation,enable-background,end,exponent,fill,fill-opacity,fill-rule,filter,filterRes,filterUnits,flood-color,flood-opacity,font-family,font-size,font-size-adjust,font-stretch,font-style,font-variant,font-weight,format,from,fr,fx,fy,g1,g2,glyph-name,glyph-orientation-horizontal,glyph-orientation-vertical,glyphRef,gradientTransform,gradientUnits,hanging,height,href,hreflang,horiz-adv-x,horiz-origin-x,id,ideographic,image-rendering,in,in2,intercept,k,k1,k2,k3,k4,kernelMatrix,kernelUnitLength,kerning,keyPoints,keySplines,keyTimes,lang,lengthAdjust,letter-spacing,lighting-color,limitingConeAngle,local,marker-end,marker-mid,marker-start,markerHeight,markerUnits,markerWidth,mask,maskContentUnits,maskUnits,mathematical,max,media,method,min,mode,name,numOctaves,offset,opacity,operator,order,orient,orientation,origin,overflow,overline-position,overline-thickness,panose-1,paint-order,path,pathLength,patternContentUnits,patternTransform,patternUnits,ping,pointer-events,points,pointsAtX,pointsAtY,pointsAtZ,preserveAlpha,preserveAspectRatio,primitiveUnits,r,radius,referrerPolicy,refX,refY,rel,rendering-intent,repeatCount,repeatDur,requiredExtensions,requiredFeatures,restart,result,rotate,rx,ry,scale,seed,shape-rendering,slope,spacing,specularConstant,specularExponent,speed,spreadMethod,startOffset,stdDeviation,stemh,stemv,stitchTiles,stop-color,stop-opacity,strikethrough-position,strikethrough-thickness,string,stroke,stroke-dasharray,stroke-dashoffset,stroke-linecap,stroke-linejoin,stroke-miterlimit,stroke-opacity,stroke-width,style,surfaceScale,systemLanguage,tabindex,tableValues,target,targetX,targetY,text-anchor,text-decoration,text-rendering,textLength,to,transform,transform-origin,type,u1,u2,underline-position,underline-thickness,unicode,unicode-bidi,unicode-range,units-per-em,v-alphabetic,v-hanging,v-ideographic,v-mathematical,values,vector-effect,version,vert-adv-y,vert-origin-x,vert-origin-y,viewBox,viewTarget,visibility,width,widths,word-spacing,writing-mode,x,x-height,x1,x2,xChannelSelector,xlink:actuate,xlink:arcrole,xlink:href,xlink:role,xlink:show,xlink:title,xlink:type,xmlns:xlink,xml:base,xml:lang,xml:space,y,y1,y2,yChannelSelector,z,zoomAndPan` +); +function isRenderableAttrValue(value) { + if (value == null) { + return false; + } + const type = typeof value; + return type === "string" || type === "number" || type === "boolean"; +} function looseCompareArrays(a, b) { if (a.length !== b.length) return false; @@ -232,21 +260,34 @@ var replacer = (_key, val) => { return replacer(_key, val.value); } else if (isMap(val)) { return { - [`Map(${val.size})`]: [...val.entries()].reduce((entries, [key, val2]) => { - entries[`${key} =>`] = val2; - return entries; - }, {}) + [`Map(${val.size})`]: [...val.entries()].reduce( + (entries, [key, val2], i) => { + entries[stringifySymbol(key, i) + " =>"] = val2; + return entries; + }, + {} + ) }; } else if (isSet(val)) { return { - [`Set(${val.size})`]: [...val.values()] + [`Set(${val.size})`]: [...val.values()].map((v) => stringifySymbol(v)) }; + } else if (isSymbol(val)) { + return stringifySymbol(val); } else if (isObject(val) && !isArray(val) && !isPlainObject(val)) { return String(val); } return val; }; -function warn$1(msg, ...args) { +var stringifySymbol = (v, i = "") => { + var _a; + return ( + // Symbol.description in es2019+ so we need to cast here to pass + // the lib: es2016 check + isSymbol(v) ? `Symbol(${(_a = v.description) != null ? _a : i})` : v + ); +}; +function warn$2(msg, ...args) { console.warn(`[Vue warn] ${msg}`, ...args); } var activeEffectScope; @@ -276,7 +317,7 @@ var EffectScope = class { activeEffectScope = currentEffectScope; } } else { - warn$1(`cannot run an inactive effect scope.`); + warn$2(`cannot run an inactive effect scope.`); } } /** @@ -334,121 +375,111 @@ function onScopeDispose(fn) { if (activeEffectScope) { activeEffectScope.cleanups.push(fn); } else { - warn$1( + warn$2( `onScopeDispose() is called when there is no active effect scope to be associated with.` ); } } -var createDep = (effects) => { - const dep = new Set(effects); - dep.w = 0; - dep.n = 0; - return dep; -}; -var wasTracked = (dep) => (dep.w & trackOpBit) > 0; -var newTracked = (dep) => (dep.n & trackOpBit) > 0; -var initDepMarkers = ({ deps }) => { - if (deps.length) { - for (let i = 0; i < deps.length; i++) { - deps[i].w |= trackOpBit; - } - } -}; -var finalizeDepMarkers = (effect2) => { - const { deps } = effect2; - if (deps.length) { - let ptr = 0; - for (let i = 0; i < deps.length; i++) { - const dep = deps[i]; - if (wasTracked(dep) && !newTracked(dep)) { - dep.delete(effect2); - } else { - deps[ptr++] = dep; - } - dep.w &= ~trackOpBit; - dep.n &= ~trackOpBit; - } - deps.length = ptr; - } -}; -var targetMap = /* @__PURE__ */ new WeakMap(); -var effectTrackDepth = 0; -var trackOpBit = 1; -var maxMarkerBits = 30; var activeEffect; -var ITERATE_KEY = Symbol("iterate"); -var MAP_KEY_ITERATE_KEY = Symbol("Map key iterate"); var ReactiveEffect = class { - constructor(fn, scheduler = null, scope) { + constructor(fn, trigger2, scheduler, scope) { this.fn = fn; + this.trigger = trigger2; this.scheduler = scheduler; this.active = true; this.deps = []; - this.parent = void 0; + this._dirtyLevel = 4; + this._trackId = 0; + this._runnings = 0; + this._shouldSchedule = false; + this._depsLength = 0; recordEffectScope(this, scope); } + get dirty() { + if (this._dirtyLevel === 2 || this._dirtyLevel === 3) { + this._dirtyLevel = 1; + pauseTracking(); + for (let i = 0; i < this._depsLength; i++) { + const dep = this.deps[i]; + if (dep.computed) { + triggerComputed(dep.computed); + if (this._dirtyLevel >= 4) { + break; + } + } + } + if (this._dirtyLevel === 1) { + this._dirtyLevel = 0; + } + resetTracking(); + } + return this._dirtyLevel >= 4; + } + set dirty(v) { + this._dirtyLevel = v ? 4 : 0; + } run() { + this._dirtyLevel = 0; if (!this.active) { return this.fn(); } - let parent = activeEffect; let lastShouldTrack = shouldTrack; - while (parent) { - if (parent === this) { - return; - } - parent = parent.parent; - } + let lastEffect = activeEffect; try { - this.parent = activeEffect; - activeEffect = this; shouldTrack = true; - trackOpBit = 1 << ++effectTrackDepth; - if (effectTrackDepth <= maxMarkerBits) { - initDepMarkers(this); - } else { - cleanupEffect(this); - } + activeEffect = this; + this._runnings++; + preCleanupEffect(this); return this.fn(); } finally { - if (effectTrackDepth <= maxMarkerBits) { - finalizeDepMarkers(this); - } - trackOpBit = 1 << --effectTrackDepth; - activeEffect = this.parent; + postCleanupEffect(this); + this._runnings--; + activeEffect = lastEffect; shouldTrack = lastShouldTrack; - this.parent = void 0; - if (this.deferStop) { - this.stop(); - } } } stop() { - if (activeEffect === this) { - this.deferStop = true; - } else if (this.active) { - cleanupEffect(this); - if (this.onStop) { - this.onStop(); - } + if (this.active) { + preCleanupEffect(this); + postCleanupEffect(this); + this.onStop && this.onStop(); this.active = false; } } }; -function cleanupEffect(effect2) { - const { deps } = effect2; - if (deps.length) { - for (let i = 0; i < deps.length; i++) { - deps[i].delete(effect2); +function triggerComputed(computed2) { + return computed2.value; +} +function preCleanupEffect(effect2) { + effect2._trackId++; + effect2._depsLength = 0; +} +function postCleanupEffect(effect2) { + if (effect2.deps.length > effect2._depsLength) { + for (let i = effect2._depsLength; i < effect2.deps.length; i++) { + cleanupDepEffect(effect2.deps[i], effect2); + } + effect2.deps.length = effect2._depsLength; + } +} +function cleanupDepEffect(dep, effect2) { + const trackId = dep.get(effect2); + if (trackId !== void 0 && effect2._trackId !== trackId) { + dep.delete(effect2); + if (dep.size === 0) { + dep.cleanup(); } - deps.length = 0; } } function effect(fn, options) { - if (fn.effect) { + if (fn.effect instanceof ReactiveEffect) { fn = fn.effect.fn; } - const _effect = new ReactiveEffect(fn); + const _effect = new ReactiveEffect(fn, NOOP, () => { + if (_effect.dirty) { + _effect.run(); + } + }); if (options) { extend(_effect, options); if (options.scope) @@ -465,6 +496,7 @@ function stop(runner) { runner.effect.stop(); } var shouldTrack = true; +var pauseScheduleStack = 0; var trackStack = []; function pauseTracking() { trackStack.push(shouldTrack); @@ -474,6 +506,67 @@ function resetTracking() { const last = trackStack.pop(); shouldTrack = last === void 0 ? true : last; } +function pauseScheduling() { + pauseScheduleStack++; +} +function resetScheduling() { + pauseScheduleStack--; + while (!pauseScheduleStack && queueEffectSchedulers.length) { + queueEffectSchedulers.shift()(); + } +} +function trackEffect(effect2, dep, debuggerEventExtraInfo) { + var _a; + if (dep.get(effect2) !== effect2._trackId) { + dep.set(effect2, effect2._trackId); + const oldDep = effect2.deps[effect2._depsLength]; + if (oldDep !== dep) { + if (oldDep) { + cleanupDepEffect(oldDep, effect2); + } + effect2.deps[effect2._depsLength++] = dep; + } else { + effect2._depsLength++; + } + { + (_a = effect2.onTrack) == null ? void 0 : _a.call(effect2, extend({ effect: effect2 }, debuggerEventExtraInfo)); + } + } +} +var queueEffectSchedulers = []; +function triggerEffects(dep, dirtyLevel, debuggerEventExtraInfo) { + var _a; + pauseScheduling(); + for (const effect2 of dep.keys()) { + let tracking; + if (effect2._dirtyLevel < dirtyLevel && (tracking != null ? tracking : tracking = dep.get(effect2) === effect2._trackId)) { + effect2._shouldSchedule || (effect2._shouldSchedule = effect2._dirtyLevel === 0); + effect2._dirtyLevel = dirtyLevel; + } + if (effect2._shouldSchedule && (tracking != null ? tracking : tracking = dep.get(effect2) === effect2._trackId)) { + { + (_a = effect2.onTrigger) == null ? void 0 : _a.call(effect2, extend({ effect: effect2 }, debuggerEventExtraInfo)); + } + effect2.trigger(); + if ((!effect2._runnings || effect2.allowRecurse) && effect2._dirtyLevel !== 2) { + effect2._shouldSchedule = false; + if (effect2.scheduler) { + queueEffectSchedulers.push(effect2.scheduler); + } + } + } + } + resetScheduling(); +} +var createDep = (cleanup, computed2) => { + const dep = /* @__PURE__ */ new Map(); + dep.cleanup = cleanup; + dep.computed = computed2; + return dep; +}; +var targetMap = /* @__PURE__ */ new WeakMap(); +var ITERATE_KEY = Symbol("iterate"); +var MAP_KEY_ITERATE_KEY = Symbol("Map key iterate"); function track(target, type, key) { if (shouldTrack && activeEffect) { let depsMap = targetMap.get(target); @@ -482,35 +575,17 @@ function track(target, type, key) { } let dep = depsMap.get(key); if (!dep) { - depsMap.set(key, dep = createDep()); - } - const eventInfo = { effect: activeEffect, target, type, key }; - trackEffects(dep, eventInfo); - } -} -function trackEffects(dep, debuggerEventExtraInfo) { - let shouldTrack2 = false; - if (effectTrackDepth <= maxMarkerBits) { - if (!newTracked(dep)) { - dep.n |= trackOpBit; - shouldTrack2 = !wasTracked(dep); - } - } else { - shouldTrack2 = !dep.has(activeEffect); - } - if (shouldTrack2) { - dep.add(activeEffect); - activeEffect.deps.push(dep); - if (activeEffect.onTrack) { - activeEffect.onTrack( - extend( - { - effect: activeEffect - }, - debuggerEventExtraInfo - ) - ); + depsMap.set(key, dep = createDep(() => depsMap.delete(key))); } + trackEffect( + activeEffect, + dep, + { + target, + type, + key + } + ); } } function trigger(target, type, key, newValue, oldValue, oldTarget) { @@ -524,7 +599,7 @@ function trigger(target, type, key, newValue, oldValue, oldTarget) { } else if (key === "length" && isArray(target)) { const newLength = Number(newValue); depsMap.forEach((dep, key2) => { - if (key2 === "length" || key2 >= newLength) { + if (key2 === "length" || !isSymbol(key2) && key2 >= newLength) { deps.push(dep); } }); @@ -558,62 +633,33 @@ function trigger(target, type, key, newValue, oldValue, oldTarget) { break; } } - const eventInfo = { target, type, key, newValue, oldValue, oldTarget }; - if (deps.length === 1) { - if (deps[0]) { - { - triggerEffects(deps[0], eventInfo); - } - } - } else { - const effects = []; - for (const dep of deps) { - if (dep) { - effects.push(...dep); - } - } - { - triggerEffects(createDep(effects), eventInfo); - } - } -} -function triggerEffects(dep, debuggerEventExtraInfo) { - const effects = isArray(dep) ? dep : [...dep]; - for (const effect2 of effects) { - if (effect2.computed) { - triggerEffect(effect2, debuggerEventExtraInfo); - } - } - for (const effect2 of effects) { - if (!effect2.computed) { - triggerEffect(effect2, debuggerEventExtraInfo); - } - } -} -function triggerEffect(effect2, debuggerEventExtraInfo) { - if (effect2 !== activeEffect || effect2.allowRecurse) { - if (effect2.onTrigger) { - effect2.onTrigger(extend({ effect: effect2 }, debuggerEventExtraInfo)); - } - if (effect2.scheduler) { - effect2.scheduler(); - } else { - effect2.run(); + pauseScheduling(); + for (const dep of deps) { + if (dep) { + triggerEffects( + dep, + 4, + { + target, + type, + key, + newValue, + oldValue, + oldTarget + } + ); } } + resetScheduling(); } function getDepFromReactive(object, key) { - var _a; - return (_a = targetMap.get(object)) == null ? void 0 : _a.get(key); + const depsMap = targetMap.get(object); + return depsMap && depsMap.get(key); } var isNonTrackableKeys = makeMap(`__proto__,__v_isRef,__isVue`); var builtInSymbols = new Set( Object.getOwnPropertyNames(Symbol).filter((key) => key !== "arguments" && key !== "caller").map((key) => Symbol[key]).filter(isSymbol) ); -var get$1 = createGetter(); -var shallowGet = createGetter(false, true); -var readonlyGet = createGetter(true); -var shallowReadonlyGet = createGetter(true, true); var arrayInstrumentations = createArrayInstrumentations(); function createArrayInstrumentations() { const instrumentations = {}; @@ -634,7 +680,9 @@ function createArrayInstrumentations() { ["push", "pop", "shift", "unshift", "splice"].forEach((key) => { instrumentations[key] = function(...args) { pauseTracking(); + pauseScheduling(); const res = toRaw(this)[key].apply(this, args); + resetScheduling(); resetTracking(); return res; }; @@ -642,20 +690,32 @@ function createArrayInstrumentations() { return instrumentations; } function hasOwnProperty(key) { + if (!isSymbol(key)) + key = String(key); const obj = toRaw(this); track(obj, "has", key); return obj.hasOwnProperty(key); } -function createGetter(isReadonly2 = false, shallow = false) { - return function get2(target, key, receiver) { +var BaseReactiveHandler = class { + constructor(_isReadonly = false, _isShallow = false) { + this._isReadonly = _isReadonly; + this._isShallow = _isShallow; + } + get(target, key, receiver) { + const isReadonly2 = this._isReadonly, isShallow2 = this._isShallow; if (key === "__v_isReactive") { return !isReadonly2; } else if (key === "__v_isReadonly") { return isReadonly2; } else if (key === "__v_isShallow") { - return shallow; - } else if (key === "__v_raw" && receiver === (isReadonly2 ? shallow ? shallowReadonlyMap : readonlyMap : shallow ? shallowReactiveMap : reactiveMap).get(target)) { - return target; + return isShallow2; + } else if (key === "__v_raw") { + if (receiver === (isReadonly2 ? isShallow2 ? shallowReadonlyMap : readonlyMap : isShallow2 ? shallowReactiveMap : reactiveMap).get(target) || // receiver is not the reactive proxy, but has the same prototype + // this means the reciever is a user proxy of the reactive proxy + Object.getPrototypeOf(target) === Object.getPrototypeOf(receiver)) { + return target; + } + return; } const targetIsArray = isArray(target); if (!isReadonly2) { @@ -673,7 +733,7 @@ function createGetter(isReadonly2 = false, shallow = false) { if (!isReadonly2) { track(target, "get", key); } - if (shallow) { + if (isShallow2) { return res; } if (isRef(res)) { @@ -683,24 +743,27 @@ function createGetter(isReadonly2 = false, shallow = false) { return isReadonly2 ? readonly(res) : reactive(res); } return res; - }; -} -var set$1 = createSetter(); -var shallowSet = createSetter(true); -function createSetter(shallow = false) { - return function set2(target, key, value, receiver) { + } +}; +var MutableReactiveHandler = class extends BaseReactiveHandler { + constructor(isShallow2 = false) { + super(false, isShallow2); + } + set(target, key, value, receiver) { let oldValue = target[key]; - if (isReadonly(oldValue) && isRef(oldValue) && !isRef(value)) { - return false; - } - if (!shallow) { + if (!this._isShallow) { + const isOldValueReadonly = isReadonly(oldValue); if (!isShallow(value) && !isReadonly(value)) { oldValue = toRaw(oldValue); value = toRaw(value); } if (!isArray(target) && isRef(oldValue) && !isRef(value)) { - oldValue.value = value; - return true; + if (isOldValueReadonly) { + return false; + } else { + oldValue.value = value; + return true; + } } } const hadKey = isArray(target) && isIntegerKey(key) ? Number(key) < target.length : hasOwn(target, key); @@ -713,49 +776,48 @@ function createSetter(shallow = false) { } } return result; - }; -} -function deleteProperty(target, key) { - const hadKey = hasOwn(target, key); - const oldValue = target[key]; - const result = Reflect.deleteProperty(target, key); - if (result && hadKey) { - trigger(target, "delete", key, void 0, oldValue); } - return result; -} -function has$1(target, key) { - const result = Reflect.has(target, key); - if (!isSymbol(key) || !builtInSymbols.has(key)) { - track(target, "has", key); + deleteProperty(target, key) { + const hadKey = hasOwn(target, key); + const oldValue = target[key]; + const result = Reflect.deleteProperty(target, key); + if (result && hadKey) { + trigger(target, "delete", key, void 0, oldValue); + } + return result; + } + has(target, key) { + const result = Reflect.has(target, key); + if (!isSymbol(key) || !builtInSymbols.has(key)) { + track(target, "has", key); + } + return result; + } + ownKeys(target) { + track( + target, + "iterate", + isArray(target) ? "length" : ITERATE_KEY + ); + return Reflect.ownKeys(target); } - return result; -} -function ownKeys(target) { - track(target, "iterate", isArray(target) ? "length" : ITERATE_KEY); - return Reflect.ownKeys(target); -} -var mutableHandlers = { - get: get$1, - set: set$1, - deleteProperty, - has: has$1, - ownKeys }; -var readonlyHandlers = { - get: readonlyGet, +var ReadonlyReactiveHandler = class extends BaseReactiveHandler { + constructor(isShallow2 = false) { + super(true, isShallow2); + } set(target, key) { { - warn$1( + warn$2( `Set operation on key "${String(key)}" failed: target is readonly.`, target ); } return true; - }, + } deleteProperty(target, key) { { - warn$1( + warn$2( `Delete operation on key "${String(key)}" failed: target is readonly.`, target ); @@ -763,21 +825,12 @@ var readonlyHandlers = { return true; } }; -var shallowReactiveHandlers = extend( - {}, - mutableHandlers, - { - get: shallowGet, - set: shallowSet - } -); -var shallowReadonlyHandlers = extend( - {}, - readonlyHandlers, - { - get: shallowReadonlyGet - } +var mutableHandlers = new MutableReactiveHandler(); +var readonlyHandlers = new ReadonlyReactiveHandler(); +var shallowReactiveHandlers = new MutableReactiveHandler( + true ); +var shallowReadonlyHandlers = new ReadonlyReactiveHandler(true); var toShallow = (value) => value; var getProto = (v) => Reflect.getPrototypeOf(v); function get(target, key, isReadonly2 = false, isShallow2 = false) { @@ -785,7 +838,7 @@ function get(target, key, isReadonly2 = false, isShallow2 = false) { const rawTarget = toRaw(target); const rawKey = toRaw(key); if (!isReadonly2) { - if (key !== rawKey) { + if (hasChanged(key, rawKey)) { track(rawTarget, "get", key); } track(rawTarget, "get", rawKey); @@ -805,7 +858,7 @@ function has(key, isReadonly2 = false) { const rawTarget = toRaw(target); const rawKey = toRaw(key); if (!isReadonly2) { - if (key !== rawKey) { + if (hasChanged(key, rawKey)) { track(rawTarget, "has", key); } track(rawTarget, "has", rawKey); @@ -921,12 +974,12 @@ function createReadonlyMethod(type) { return function(...args) { { const key = args[0] ? `on key "${args[0]}" ` : ``; - console.warn( + warn$2( `${capitalize(type)} operation ${key}failed: target is readonly.`, toRaw(this) ); } - return type === "delete" ? false : this; + return type === "delete" ? false : type === "clear" ? void 0 : this; }; } function createInstrumentations() { @@ -990,23 +1043,16 @@ function createInstrumentations() { clear: createReadonlyMethod("clear"), forEach: createForEach(true, true) }; - const iteratorMethods = ["keys", "values", "entries", Symbol.iterator]; + const iteratorMethods = [ + "keys", + "values", + "entries", + Symbol.iterator + ]; iteratorMethods.forEach((method) => { - mutableInstrumentations2[method] = createIterableMethod( - method, - false, - false - ); - readonlyInstrumentations2[method] = createIterableMethod( - method, - true, - false - ); - shallowInstrumentations2[method] = createIterableMethod( - method, - false, - true - ); + mutableInstrumentations2[method] = createIterableMethod(method, false, false); + readonlyInstrumentations2[method] = createIterableMethod(method, true, false); + shallowInstrumentations2[method] = createIterableMethod(method, false, true); shallowReadonlyInstrumentations2[method] = createIterableMethod( method, true, @@ -1059,7 +1105,7 @@ function checkIdentityKeys(target, has2, key) { const rawKey = toRaw(key); if (rawKey !== key && has2.call(target, rawKey)) { const type = toRawType(target); - console.warn( + warn$2( `Reactive ${type} contains both the raw and reactive versions of the same object${type === `Map` ? ` as keys` : ``}, which can lead to inconsistencies. Avoid differentiating between the raw and reactive versions of an object and only use the reactive version if possible.` ); } @@ -1127,7 +1173,7 @@ function shallowReadonly(target) { function createReactiveObject(target, isReadonly2, baseHandlers, collectionHandlers, proxyMap) { if (!isObject(target)) { { - console.warn(`value cannot be made reactive: ${String(target)}`); + warn$2(`value cannot be made reactive: ${String(target)}`); } return target; } @@ -1162,42 +1208,119 @@ function isShallow(value) { return !!(value && value["__v_isShallow"]); } function isProxy(value) { - return isReactive(value) || isReadonly(value); + return value ? !!value["__v_raw"] : false; } function toRaw(observed) { const raw = observed && observed["__v_raw"]; return raw ? toRaw(raw) : observed; } function markRaw(value) { - def(value, "__v_skip", true); + if (Object.isExtensible(value)) { + def(value, "__v_skip", true); + } return value; } var toReactive = (value) => isObject(value) ? reactive(value) : value; var toReadonly = (value) => isObject(value) ? readonly(value) : value; +var COMPUTED_SIDE_EFFECT_WARN = `Computed is still dirty after getter evaluation, likely because a computed is mutating its own dependency in its getter. State mutations in computed getters should be avoided. Check the docs for more details: https://vuejs.org/guide/essentials/computed.html#getters-should-be-side-effect-free`; +var ComputedRefImpl = class { + constructor(getter, _setter, isReadonly2, isSSR) { + this.getter = getter; + this._setter = _setter; + this.dep = void 0; + this.__v_isRef = true; + this["__v_isReadonly"] = false; + this.effect = new ReactiveEffect( + () => getter(this._value), + () => triggerRefValue( + this, + this.effect._dirtyLevel === 2 ? 2 : 3 + ) + ); + this.effect.computed = this; + this.effect.active = this._cacheable = !isSSR; + this["__v_isReadonly"] = isReadonly2; + } + get value() { + const self2 = toRaw(this); + if ((!self2._cacheable || self2.effect.dirty) && hasChanged(self2._value, self2._value = self2.effect.run())) { + triggerRefValue(self2, 4); + } + trackRefValue(self2); + if (self2.effect._dirtyLevel >= 2) { + if (this._warnRecursive) { + warn$2(COMPUTED_SIDE_EFFECT_WARN, ` + +getter: `, this.getter); + } + triggerRefValue(self2, 2); + } + return self2._value; + } + set value(newValue) { + this._setter(newValue); + } + // #region polyfill _dirty for backward compatibility third party code for Vue <= 3.3.x + get _dirty() { + return this.effect.dirty; + } + set _dirty(v) { + this.effect.dirty = v; + } + // #endregion +}; +function computed$1(getterOrOptions, debugOptions, isSSR = false) { + let getter; + let setter; + const onlyGetter = isFunction(getterOrOptions); + if (onlyGetter) { + getter = getterOrOptions; + setter = () => { + warn$2("Write operation failed: computed value is readonly"); + }; + } else { + getter = getterOrOptions.get; + setter = getterOrOptions.set; + } + const cRef = new ComputedRefImpl(getter, setter, onlyGetter || !setter, isSSR); + if (debugOptions && !isSSR) { + cRef.effect.onTrack = debugOptions.onTrack; + cRef.effect.onTrigger = debugOptions.onTrigger; + } + return cRef; +} function trackRefValue(ref2) { + var _a; if (shouldTrack && activeEffect) { ref2 = toRaw(ref2); - { - trackEffects(ref2.dep || (ref2.dep = createDep()), { + trackEffect( + activeEffect, + (_a = ref2.dep) != null ? _a : ref2.dep = createDep( + () => ref2.dep = void 0, + ref2 instanceof ComputedRefImpl ? ref2 : void 0 + ), + { target: ref2, type: "get", key: "value" - }); - } + } + ); } } -function triggerRefValue(ref2, newVal) { +function triggerRefValue(ref2, dirtyLevel = 4, newVal) { ref2 = toRaw(ref2); const dep = ref2.dep; if (dep) { - { - triggerEffects(dep, { + triggerEffects( + dep, + dirtyLevel, + { target: ref2, type: "set", key: "value", newValue: newVal - }); - } + } + ); } } function isRef(r) { @@ -1233,12 +1356,12 @@ var RefImpl = class { if (hasChanged(newVal, this._rawValue)) { this._rawValue = newVal; this._value = useDirectValue ? newVal : toReactive(newVal); - triggerRefValue(this, newVal); + triggerRefValue(this, 4, newVal); } } }; function triggerRef(ref2) { - triggerRefValue(ref2, ref2.value); + triggerRefValue(ref2, 4, ref2.value); } function unref(ref2) { return isRef(ref2) ? ref2.value : ref2; @@ -1284,7 +1407,7 @@ function customRef(factory) { } function toRefs(object) { if (!isProxy(object)) { - console.warn(`toRefs() expects a reactive object but received a plain one.`); + warn$2(`toRefs() expects a reactive object but received a plain one.`); } const ret = isArray(object) ? new Array(object.length) : {}; for (const key in object) { @@ -1333,62 +1456,19 @@ function toRef(source, key, defaultValue) { } function propertyToRef(source, key, defaultValue) { const val = source[key]; - return isRef(val) ? val : new ObjectRefImpl( - source, - key, - defaultValue - ); + return isRef(val) ? val : new ObjectRefImpl(source, key, defaultValue); } -var ComputedRefImpl = class { - constructor(getter, _setter, isReadonly2, isSSR) { - this._setter = _setter; - this.dep = void 0; - this.__v_isRef = true; - this["__v_isReadonly"] = false; - this._dirty = true; - this.effect = new ReactiveEffect(getter, () => { - if (!this._dirty) { - this._dirty = true; - triggerRefValue(this); - } - }); - this.effect.computed = this; - this.effect.active = this._cacheable = !isSSR; - this["__v_isReadonly"] = isReadonly2; - } - get value() { - const self2 = toRaw(this); - trackRefValue(self2); - if (self2._dirty || !self2._cacheable) { - self2._dirty = false; - self2._value = self2.effect.run(); - } - return self2._value; - } - set value(newValue) { - this._setter(newValue); - } +var TrackOpTypes = { + "GET": "get", + "HAS": "has", + "ITERATE": "iterate" +}; +var TriggerOpTypes = { + "SET": "set", + "ADD": "add", + "DELETE": "delete", + "CLEAR": "clear" }; -function computed$1(getterOrOptions, debugOptions, isSSR = false) { - let getter; - let setter; - const onlyGetter = isFunction(getterOrOptions); - if (onlyGetter) { - getter = getterOrOptions; - setter = () => { - console.warn("Write operation failed: computed value is readonly"); - }; - } else { - getter = getterOrOptions.get; - setter = getterOrOptions.set; - } - const cRef = new ComputedRefImpl(getter, setter, onlyGetter || !setter, isSSR); - if (debugOptions && !isSSR) { - cRef.effect.onTrack = debugOptions.onTrack; - cRef.effect.onTrigger = debugOptions.onTrigger; - } - return cRef; -} var stack = []; function pushWarningContext(vnode) { stack.push(vnode); @@ -1396,7 +1476,7 @@ function pushWarningContext(vnode) { function popWarningContext() { stack.pop(); } -function warn(msg, ...args) { +function warn$1(msg, ...args) { pauseTracking(); const instance = stack.length ? stack[stack.length - 1].component : null; const appWarnHandler = instance && instance.appContext.config.warnHandler; @@ -1407,7 +1487,10 @@ function warn(msg, ...args) { instance, 11, [ - msg + args.join(""), + msg + args.map((a) => { + var _a, _b; + return (_b = (_a = a.toString) == null ? void 0 : _a.call(a)) != null ? _b : JSON.stringify(a); + }).join(""), instance && instance.proxy, trace.map( ({ vnode }) => `at <${formatComponentName(instance, vnode.type)}>` @@ -1497,12 +1580,44 @@ function assertNumber(val, type) { if (val === void 0) { return; } else if (typeof val !== "number") { - warn(`${type} is not a valid number - got ${JSON.stringify(val)}.`); + warn$1(`${type} is not a valid number - got ${JSON.stringify(val)}.`); } else if (isNaN(val)) { - warn(`${type} is NaN - the duration expression might be incorrect.`); - } -} -var ErrorTypeStrings = { + warn$1(`${type} is NaN - the duration expression might be incorrect.`); + } +} +var ErrorCodes = { + "SETUP_FUNCTION": 0, + "0": "SETUP_FUNCTION", + "RENDER_FUNCTION": 1, + "1": "RENDER_FUNCTION", + "WATCH_GETTER": 2, + "2": "WATCH_GETTER", + "WATCH_CALLBACK": 3, + "3": "WATCH_CALLBACK", + "WATCH_CLEANUP": 4, + "4": "WATCH_CLEANUP", + "NATIVE_EVENT_HANDLER": 5, + "5": "NATIVE_EVENT_HANDLER", + "COMPONENT_EVENT_HANDLER": 6, + "6": "COMPONENT_EVENT_HANDLER", + "VNODE_HOOK": 7, + "7": "VNODE_HOOK", + "DIRECTIVE_HOOK": 8, + "8": "DIRECTIVE_HOOK", + "TRANSITION_HOOK": 9, + "9": "TRANSITION_HOOK", + "APP_ERROR_HANDLER": 10, + "10": "APP_ERROR_HANDLER", + "APP_WARN_HANDLER": 11, + "11": "APP_WARN_HANDLER", + "FUNCTION_REF": 12, + "12": "FUNCTION_REF", + "ASYNC_COMPONENT_LOADER": 13, + "13": "ASYNC_COMPONENT_LOADER", + "SCHEDULER": 14, + "14": "SCHEDULER" +}; +var ErrorTypeStrings$1 = { ["sp"]: "serverPrefetch hook", ["bc"]: "beforeCreate hook", ["c"]: "created hook", @@ -1531,16 +1646,14 @@ var ErrorTypeStrings = { [11]: "app warnHandler", [12]: "ref function", [13]: "async component loader", - [14]: "scheduler flush. This is likely a Vue internals bug. Please open an issue at https://new-issue.vuejs.org/?repo=vuejs/core" + [14]: "scheduler flush. This is likely a Vue internals bug. Please open an issue at https://github.com/vuejs/core ." }; function callWithErrorHandling(fn, instance, type, args) { - let res; try { - res = args ? fn(...args) : fn(); + return args ? fn(...args) : fn(); } catch (err) { handleError(err, instance, type); } - return res; } function callWithAsyncErrorHandling(fn, instance, type, args) { if (isFunction(fn)) { @@ -1552,18 +1665,24 @@ function callWithAsyncErrorHandling(fn, instance, type, args) { } return res; } - const values = []; - for (let i = 0; i < fn.length; i++) { - values.push(callWithAsyncErrorHandling(fn[i], instance, type, args)); + if (isArray(fn)) { + const values = []; + for (let i = 0; i < fn.length; i++) { + values.push(callWithAsyncErrorHandling(fn[i], instance, type, args)); + } + return values; + } else { + warn$1( + `Invalid value type passed to callWithAsyncErrorHandling(): ${typeof fn}` + ); } - return values; } function handleError(err, instance, type, throwInDev = true) { const contextVNode = instance ? instance.vnode : null; if (instance) { let cur = instance.parent; const exposedInstance = instance.proxy; - const errorInfo = ErrorTypeStrings[type]; + const errorInfo = ErrorTypeStrings$1[type]; while (cur) { const errorCapturedHooks = cur.ec; if (errorCapturedHooks) { @@ -1577,12 +1696,14 @@ function handleError(err, instance, type, throwInDev = true) { } const appErrorHandler = instance.appContext.config.errorHandler; if (appErrorHandler) { + pauseTracking(); callWithErrorHandling( appErrorHandler, null, 10, [err, exposedInstance, errorInfo] ); + resetTracking(); return; } } @@ -1590,11 +1711,11 @@ function handleError(err, instance, type, throwInDev = true) { } function logError(err, type, contextVNode, throwInDev = true) { { - const info = ErrorTypeStrings[type]; + const info = ErrorTypeStrings$1[type]; if (contextVNode) { pushWarningContext(contextVNode); } - warn(`Unhandled error${info ? ` during execution of ${info}` : ``}`); + warn$1(`Unhandled error${info ? ` during execution of ${info}` : ``}`); if (contextVNode) { popWarningContext(); } @@ -1624,8 +1745,13 @@ function findInsertionIndex(id) { let end = queue.length; while (start < end) { const middle = start + end >>> 1; - const middleJobId = getId(queue[middle]); - middleJobId < id ? start = middle + 1 : end = middle; + const middleJob = queue[middle]; + const middleJobId = getId(middleJob); + if (middleJobId < id || middleJobId === id && middleJob.pre) { + start = middle + 1; + } else { + end = middle; + } } return start; } @@ -1667,13 +1793,16 @@ function queuePostFlushCb(cb) { } queueFlush(); } -function flushPreFlushCbs(seen, i = isFlushing ? flushIndex + 1 : 0) { +function flushPreFlushCbs(instance, seen, i = isFlushing ? flushIndex + 1 : 0) { { seen = seen || /* @__PURE__ */ new Map(); } for (; i < queue.length; i++) { const cb = queue[i]; if (cb && cb.pre) { + if (instance && cb.id !== instance.uid) { + continue; + } if (checkRecursiveUpdates(seen, cb)) { continue; } @@ -1685,7 +1814,9 @@ function flushPreFlushCbs(seen, i = isFlushing ? flushIndex + 1 : 0) { } function flushPostFlushCbs(seen) { if (pendingPostFlushCbs.length) { - const deduped = [...new Set(pendingPostFlushCbs)]; + const deduped = [...new Set(pendingPostFlushCbs)].sort( + (a, b) => getId(a) - getId(b) + ); pendingPostFlushCbs.length = 0; if (activePostFlushCbs) { activePostFlushCbs.push(...deduped); @@ -1695,7 +1826,6 @@ function flushPostFlushCbs(seen) { { seen = seen || /* @__PURE__ */ new Map(); } - activePostFlushCbs.sort((a, b) => getId(a) - getId(b)); for (postFlushIndex = 0; postFlushIndex < activePostFlushCbs.length; postFlushIndex++) { if (checkRecursiveUpdates(seen, activePostFlushCbs[postFlushIndex])) { continue; @@ -1754,8 +1884,10 @@ function checkRecursiveUpdates(seen, fn) { if (count > RECURSION_LIMIT) { const instance = fn.ownerInstance; const componentName = instance && getComponentName(instance.type); - warn( - `Maximum recursive updates exceeded${componentName ? ` in component <${componentName}>` : ``}. This means you have a reactive effect that is mutating its own dependencies and thus recursively triggering itself. Possible sources include component template, render function, updated hook or watcher source function.` + handleError( + `Maximum recursive updates exceeded${componentName ? ` in component <${componentName}>` : ``}. This means you have a reactive effect that is mutating its own dependencies and thus recursively triggering itself. Possible sources include component template, render function, updated hook or watcher source function.`, + null, + 10 ); return true; } else { @@ -1811,6 +1943,7 @@ function rerender(id, newRender) { } instance.renderCache = []; isHmrUpdating = true; + instance.effect.dirty = true; instance.update(); isHmrUpdating = false; }); @@ -1838,6 +1971,7 @@ function reload(id, newComp) { instance.ceReload(newComp.styles); hmrDirtyComponents.delete(oldComp); } else if (instance.parent) { + instance.parent.effect.dirty = true; queueJob(instance.parent.update); } else if (instance.appContext.reload) { instance.appContext.reload(); @@ -1877,22 +2011,22 @@ function tryWrap(fn) { } }; } -var devtools; +var devtools$1; var buffer = []; var devtoolsNotInstalled = false; function emit$1(event, ...args) { - if (devtools) { - devtools.emit(event, ...args); + if (devtools$1) { + devtools$1.emit(event, ...args); } else if (!devtoolsNotInstalled) { buffer.push({ event, args }); } } -function setDevtoolsHook(hook, target) { +function setDevtoolsHook$1(hook, target) { var _a, _b; - devtools = hook; - if (devtools) { - devtools.enabled = true; - buffer.forEach(({ event, args }) => devtools.emit(event, ...args)); + devtools$1 = hook; + if (devtools$1) { + devtools$1.enabled = true; + buffer.forEach(({ event, args }) => devtools$1.emit(event, ...args)); buffer = []; } else if ( // handle late devtools injection - only do this if we are in an actual @@ -1904,10 +2038,10 @@ function setDevtoolsHook(hook, target) { ) { const replay = target.__VUE_DEVTOOLS_HOOK_REPLAY__ = target.__VUE_DEVTOOLS_HOOK_REPLAY__ || []; replay.push((newHook) => { - setDevtoolsHook(newHook, target); + setDevtoolsHook$1(newHook, target); }); setTimeout(() => { - if (!devtools) { + if (!devtools$1) { target.__VUE_DEVTOOLS_HOOK_REPLAY__ = null; devtoolsNotInstalled = true; buffer = []; @@ -1942,8 +2076,8 @@ var _devtoolsComponentRemoved = createDevtoolsComponentHook( /* COMPONENT_REMOVED */ ); var devtoolsComponentRemoved = (component) => { - if (devtools && typeof devtools.cleanupBuffer === "function" && // remove the component if it wasn't buffered - !devtools.cleanupBuffer(component)) { + if (devtools$1 && typeof devtools$1.cleanupBuffer === "function" && // remove the component if it wasn't buffered + !devtools$1.cleanupBuffer(component)) { _devtoolsComponentRemoved(component); } }; @@ -1992,7 +2126,7 @@ function emit(instance, event, ...rawArgs) { if (emitsOptions) { if (!(event in emitsOptions) && true) { if (!propsOptions || !(toHandlerKey(event) in propsOptions)) { - warn( + warn$1( `Component emitted event "${event}" but it is neither declared in the emits option nor as an "${toHandlerKey(event)}" prop.` ); } @@ -2001,7 +2135,7 @@ function emit(instance, event, ...rawArgs) { if (isFunction(validator)) { const isValid = validator(...rawArgs); if (!isValid) { - warn( + warn$1( `Invalid event arguments: event validation failed for event "${event}".` ); } @@ -2028,11 +2162,13 @@ function emit(instance, event, ...rawArgs) { { const lowerCaseEvent = event.toLowerCase(); if (lowerCaseEvent !== event && props[toHandlerKey(lowerCaseEvent)]) { - warn( + warn$1( `Event "${lowerCaseEvent}" is emitted in component ${formatComponentName( instance, instance.type - )} but the handler is registered for "${event}". Note that HTML attributes are case-insensitive and you cannot use v-on to listen to camelCase events when using in-DOM templates. You should probably use "${hyphenate(event)}" instead of "${event}".` + )} but the handler is registered for "${event}". Note that HTML attributes are case-insensitive and you cannot use v-on to listen to camelCase events when using in-DOM templates. You should probably use "${hyphenate( + event + )}" instead of "${event}".` ); } } @@ -2171,33 +2307,43 @@ function renderComponentRoot(instance) { vnode, proxy, withProxy, - props, propsOptions: [propsOptions], slots, attrs, emit: emit2, render: render2, renderCache, + props, data, setupState, ctx, inheritAttrs } = instance; + const prev = setCurrentRenderingInstance(instance); let result; let fallthroughAttrs; - const prev = setCurrentRenderingInstance(instance); { accessedAttrs = false; } try { if (vnode.shapeFlag & 4) { const proxyToUse = withProxy || proxy; + const thisProxy = setupState.__isScriptSetup ? new Proxy(proxyToUse, { + get(target, key, receiver) { + warn$1( + `Property '${String( + key + )}' was accessed via 'this'. Avoid using 'this' in templates.` + ); + return Reflect.get(target, key, receiver); + } + }) : proxyToUse; result = normalizeVNode( render2.call( - proxyToUse, + thisProxy, proxyToUse, renderCache, - props, + true ? shallowReadonly(props) : props, setupState, data, ctx @@ -2211,19 +2357,18 @@ function renderComponentRoot(instance) { } result = normalizeVNode( render22.length > 1 ? render22( - props, + true ? shallowReadonly(props) : props, true ? { get attrs() { markAttrsAccessed(); - return attrs; + return shallowReadonly(attrs); }, slots, emit: emit2 } : { attrs, slots, emit: emit2 } ) : render22( - props, + true ? shallowReadonly(props) : props, null - /* we know it doesn't need it */ ) ); fallthroughAttrs = Component.props ? attrs : getFunctionalFallthrough(attrs); @@ -2249,7 +2394,7 @@ function renderComponentRoot(instance) { propsOptions ); } - root = cloneVNode(root, fallthroughAttrs); + root = cloneVNode(root, fallthroughAttrs, false, true); } else if (!accessedAttrs && root.type !== Comment) { const allAttrs = Object.keys(attrs); const eventAttrs = []; @@ -2265,12 +2410,12 @@ function renderComponentRoot(instance) { } } if (extraAttrs.length) { - warn( + warn$1( `Extraneous non-props attributes (${extraAttrs.join(", ")}) were passed to component but could not be automatically inherited because component renders fragment or text root nodes.` ); } if (eventAttrs.length) { - warn( + warn$1( `Extraneous non-emits event listeners (${eventAttrs.join(", ")}) were passed to component but could not be automatically inherited because component renders fragment or text root nodes. If the listener is intended to be a component custom event listener only, declare it using the "emits" option.` ); } @@ -2279,16 +2424,16 @@ function renderComponentRoot(instance) { } if (vnode.dirs) { if (!isElementRoot(root)) { - warn( + warn$1( `Runtime directive used on component with non-element root node. The directives will not function as intended.` ); } - root = cloneVNode(root); + root = cloneVNode(root, null, false, true); root.dirs = root.dirs ? root.dirs.concat(vnode.dirs) : vnode.dirs; } if (vnode.transition) { if (!isElementRoot(root)) { - warn( + warn$1( `Component inside renders non-element root node that cannot be animated.` ); } @@ -2305,9 +2450,11 @@ function renderComponentRoot(instance) { var getChildRoot = (vnode) => { const rawChildren = vnode.children; const dynamicChildren = vnode.dynamicChildren; - const childRoot = filterSingleRoot(rawChildren); + const childRoot = filterSingleRoot(rawChildren, false); if (!childRoot) { return [vnode, void 0]; + } else if (childRoot.patchFlag > 0 && childRoot.patchFlag & 2048) { + return getChildRoot(childRoot); } const index = rawChildren.indexOf(childRoot); const dynamicIndex = dynamicChildren ? dynamicChildren.indexOf(childRoot) : -1; @@ -2323,7 +2470,7 @@ var getChildRoot = (vnode) => { }; return [normalizeVNode(childRoot), setRoot]; }; -function filterSingleRoot(children) { +function filterSingleRoot(children, recurse = true) { let singleRoot; for (let i = 0; i < children.length; i++) { const child = children[i]; @@ -2333,6 +2480,9 @@ function filterSingleRoot(children) { return; } else { singleRoot = child; + if (recurse && singleRoot.patchFlag > 0 && singleRoot.patchFlag & 2048) { + return filterSingleRoot(singleRoot.children); + } } } } else { @@ -2423,12 +2573,74 @@ function hasPropsChanged(prevProps, nextProps, emitsOptions) { return false; } function updateHOCHostEl({ vnode, parent }, el) { - while (parent && parent.subTree === vnode) { - (vnode = parent.vnode).el = el; - parent = parent.parent; + while (parent) { + const root = parent.subTree; + if (root.suspense && root.suspense.activeBranch === vnode) { + root.el = vnode.el; + } + if (root === vnode) { + (vnode = parent.vnode).el = el; + parent = parent.parent; + } else { + break; + } + } +} +var COMPONENTS = "components"; +var DIRECTIVES = "directives"; +function resolveComponent(name, maybeSelfReference) { + return resolveAsset(COMPONENTS, name, true, maybeSelfReference) || name; +} +var NULL_DYNAMIC_COMPONENT = Symbol.for("v-ndc"); +function resolveDynamicComponent(component) { + if (isString(component)) { + return resolveAsset(COMPONENTS, component, false) || component; + } else { + return component || NULL_DYNAMIC_COMPONENT; + } +} +function resolveDirective(name) { + return resolveAsset(DIRECTIVES, name); +} +function resolveAsset(type, name, warnMissing = true, maybeSelfReference = false) { + const instance = currentRenderingInstance || currentInstance; + if (instance) { + const Component = instance.type; + if (type === COMPONENTS) { + const selfName = getComponentName( + Component, + false + ); + if (selfName && (selfName === name || selfName === camelize(name) || selfName === capitalize(camelize(name)))) { + return Component; + } + } + const res = ( + // local registration + // check instance[type] first which is resolved for options API + resolve(instance[type] || Component[type], name) || // global registration + resolve(instance.appContext[type], name) + ); + if (!res && maybeSelfReference) { + return Component; + } + if (warnMissing && !res) { + const extra = type === COMPONENTS ? ` +If this is a native custom element, make sure to exclude it from component resolution via compilerOptions.isCustomElement.` : ``; + warn$1(`Failed to resolve ${type.slice(0, -1)}: ${name}${extra}`); + } + return res; + } else { + warn$1( + `resolve${capitalize(type.slice(0, -1))} can only be used in render() or setup().` + ); } } +function resolve(registry, name) { + return registry && (registry[name] || registry[camelize(name)] || registry[capitalize(camelize(name))]); +} var isSuspense = (type) => type.__isSuspense; +var suspenseId = 0; var SuspenseImpl = { name: "Suspense", // In order to make Suspense tree-shakable, we need to avoid importing it @@ -2436,7 +2648,7 @@ var SuspenseImpl = { // on a vnode's type and calls the `process` method, passing in renderer // internals. __isSuspense: true, - process(n1, n2, container, anchor, parentComponent, parentSuspense, isSVG, slotScopeIds, optimized, rendererInternals) { + process(n1, n2, container, anchor, parentComponent, parentSuspense, namespace, slotScopeIds, optimized, rendererInternals) { if (n1 == null) { mountSuspense( n2, @@ -2444,19 +2656,25 @@ var SuspenseImpl = { anchor, parentComponent, parentSuspense, - isSVG, + namespace, slotScopeIds, optimized, rendererInternals ); } else { + if (parentSuspense && parentSuspense.deps > 0 && !n1.suspense.isInFallback) { + n2.suspense = n1.suspense; + n2.suspense.vnode = n2; + n2.el = n1.el; + return; + } patchSuspense( n1, n2, container, anchor, parentComponent, - isSVG, + namespace, slotScopeIds, optimized, rendererInternals @@ -2474,7 +2692,7 @@ function triggerEvent(vnode, name) { eventListener(); } } -function mountSuspense(vnode, container, anchor, parentComponent, parentSuspense, isSVG, slotScopeIds, optimized, rendererInternals) { +function mountSuspense(vnode, container, anchor, parentComponent, parentSuspense, namespace, slotScopeIds, optimized, rendererInternals) { const { p: patch, o: { createElement } @@ -2487,7 +2705,7 @@ function mountSuspense(vnode, container, anchor, parentComponent, parentSuspense container, hiddenContainer, anchor, - isSVG, + namespace, slotScopeIds, optimized, rendererInternals @@ -2499,7 +2717,7 @@ function mountSuspense(vnode, container, anchor, parentComponent, parentSuspense null, parentComponent, suspense, - isSVG, + namespace, slotScopeIds ); if (suspense.deps > 0) { @@ -2513,7 +2731,7 @@ function mountSuspense(vnode, container, anchor, parentComponent, parentSuspense parentComponent, null, // fallback tree will not have suspense context - isSVG, + namespace, slotScopeIds ); setActiveBranch(suspense, vnode.ssFallback); @@ -2521,7 +2739,7 @@ function mountSuspense(vnode, container, anchor, parentComponent, parentSuspense suspense.resolve(false, true); } } -function patchSuspense(n1, n2, container, anchor, parentComponent, isSVG, slotScopeIds, optimized, { p: patch, um: unmount, o: { createElement } }) { +function patchSuspense(n1, n2, container, anchor, parentComponent, namespace, slotScopeIds, optimized, { p: patch, um: unmount, o: { createElement } }) { const suspense = n2.suspense = n1.suspense; suspense.vnode = n2; n2.el = n1.el; @@ -2538,29 +2756,31 @@ function patchSuspense(n1, n2, container, anchor, parentComponent, isSVG, slotSc null, parentComponent, suspense, - isSVG, + namespace, slotScopeIds, optimized ); if (suspense.deps <= 0) { suspense.resolve(); } else if (isInFallback) { - patch( - activeBranch, - newFallback, - container, - anchor, - parentComponent, - null, - // fallback tree will not have suspense context - isSVG, - slotScopeIds, - optimized - ); - setActiveBranch(suspense, newFallback); + if (!isHydrating) { + patch( + activeBranch, + newFallback, + container, + anchor, + parentComponent, + null, + // fallback tree will not have suspense context + namespace, + slotScopeIds, + optimized + ); + setActiveBranch(suspense, newFallback); + } } } else { - suspense.pendingId++; + suspense.pendingId = suspenseId++; if (isHydrating) { suspense.isHydrating = false; suspense.activeBranch = pendingBranch; @@ -2578,7 +2798,7 @@ function patchSuspense(n1, n2, container, anchor, parentComponent, isSVG, slotSc null, parentComponent, suspense, - isSVG, + namespace, slotScopeIds, optimized ); @@ -2593,7 +2813,7 @@ function patchSuspense(n1, n2, container, anchor, parentComponent, isSVG, slotSc parentComponent, null, // fallback tree will not have suspense context - isSVG, + namespace, slotScopeIds, optimized ); @@ -2607,7 +2827,7 @@ function patchSuspense(n1, n2, container, anchor, parentComponent, isSVG, slotSc anchor, parentComponent, suspense, - isSVG, + namespace, slotScopeIds, optimized ); @@ -2620,7 +2840,7 @@ function patchSuspense(n1, n2, container, anchor, parentComponent, isSVG, slotSc null, parentComponent, suspense, - isSVG, + namespace, slotScopeIds, optimized ); @@ -2638,7 +2858,7 @@ function patchSuspense(n1, n2, container, anchor, parentComponent, isSVG, slotSc anchor, parentComponent, suspense, - isSVG, + namespace, slotScopeIds, optimized ); @@ -2646,7 +2866,11 @@ function patchSuspense(n1, n2, container, anchor, parentComponent, isSVG, slotSc } else { triggerEvent(n2, "onPending"); suspense.pendingBranch = newBranch; - suspense.pendingId++; + if (newBranch.shapeFlag & 512) { + suspense.pendingId = newBranch.component.suspenseId; + } else { + suspense.pendingId = suspenseId++; + } patch( null, newBranch, @@ -2654,7 +2878,7 @@ function patchSuspense(n1, n2, container, anchor, parentComponent, isSVG, slotSc null, parentComponent, suspense, - isSVG, + namespace, slotScopeIds, optimized ); @@ -2676,7 +2900,7 @@ function patchSuspense(n1, n2, container, anchor, parentComponent, isSVG, slotSc } } var hasWarned = false; -function createSuspenseBoundary(vnode, parentSuspense, parentComponent, container, hiddenContainer, anchor, isSVG, slotScopeIds, optimized, rendererInternals, isHydrating = false) { +function createSuspenseBoundary(vnode, parentSuspense, parentComponent, container, hiddenContainer, anchor, namespace, slotScopeIds, optimized, rendererInternals, isHydrating = false) { if (!hasWarned) { hasWarned = true; console[console.info ? "info" : "log"]( @@ -2693,7 +2917,7 @@ function createSuspenseBoundary(vnode, parentSuspense, parentComponent, containe let parentSuspenseId; const isSuspensible = isVNodeSuspensible(vnode); if (isSuspensible) { - if (parentSuspense == null ? void 0 : parentSuspense.pendingBranch) { + if (parentSuspense && parentSuspense.pendingBranch) { parentSuspenseId = parentSuspense.pendingId; parentSuspense.deps++; } @@ -2702,20 +2926,20 @@ function createSuspenseBoundary(vnode, parentSuspense, parentComponent, containe { assertNumber(timeout, `Suspense timeout`); } + const initialAnchor = anchor; const suspense = { vnode, parent: parentSuspense, parentComponent, - isSVG, + namespace, container, hiddenContainer, - anchor, deps: 0, - pendingId: 0, + pendingId: suspenseId++, timeout: typeof timeout === "number" ? timeout : -1, activeBranch: null, pendingBranch: null, - isInFallback: true, + isInFallback: !isHydrating, isHydrating, isUnmounted: false, effects: [], @@ -2741,24 +2965,32 @@ function createSuspenseBoundary(vnode, parentSuspense, parentComponent, containe parentComponent: parentComponent2, container: container2 } = suspense; + let delayEnter = false; if (suspense.isHydrating) { suspense.isHydrating = false; } else if (!resume) { - const delayEnter = activeBranch && pendingBranch.transition && pendingBranch.transition.mode === "out-in"; + delayEnter = activeBranch && pendingBranch.transition && pendingBranch.transition.mode === "out-in"; if (delayEnter) { activeBranch.transition.afterLeave = () => { if (pendingId === suspense.pendingId) { - move(pendingBranch, container2, anchor2, 0); + move( + pendingBranch, + container2, + anchor === initialAnchor ? next(activeBranch) : anchor, + 0 + ); + queuePostFlushCb(effects); } }; } - let { anchor: anchor2 } = suspense; if (activeBranch) { - anchor2 = next(activeBranch); + if (parentNode(activeBranch.el) !== suspense.hiddenContainer) { + anchor = next(activeBranch); + } unmount(activeBranch, parentComponent2, suspense, true); } if (!delayEnter) { - move(pendingBranch, container2, anchor2, 0); + move(pendingBranch, container2, anchor, 0); } } setActiveBranch(suspense, pendingBranch); @@ -2774,7 +3006,7 @@ function createSuspenseBoundary(vnode, parentSuspense, parentComponent, containe } parent = parent.parent; } - if (!hasUnresolvedAncestor) { + if (!hasUnresolvedAncestor && !delayEnter) { queuePostFlushCb(effects); } suspense.effects = []; @@ -2792,7 +3024,7 @@ function createSuspenseBoundary(vnode, parentSuspense, parentComponent, containe if (!suspense.pendingBranch) { return; } - const { vnode: vnode2, activeBranch, parentComponent: parentComponent2, container: container2, isSVG: isSVG2 } = suspense; + const { vnode: vnode2, activeBranch, parentComponent: parentComponent2, container: container2, namespace: namespace2 } = suspense; triggerEvent(vnode2, "onFallback"); const anchor2 = next(activeBranch); const mountFallback = () => { @@ -2807,7 +3039,7 @@ function createSuspenseBoundary(vnode, parentSuspense, parentComponent, containe parentComponent2, null, // fallback tree will not have suspense context - isSVG2, + namespace2, slotScopeIds, optimized ); @@ -2870,7 +3102,7 @@ function createSuspenseBoundary(vnode, parentSuspense, parentComponent, containe // consider the comment placeholder case. hydratedEl ? null : next(instance.subTree), suspense, - isSVG, + namespace, optimized ); if (placeholder) { @@ -2907,20 +3139,20 @@ function createSuspenseBoundary(vnode, parentSuspense, parentComponent, containe }; return suspense; } -function hydrateSuspense(node, vnode, parentComponent, parentSuspense, isSVG, slotScopeIds, optimized, rendererInternals, hydrateNode) { +function hydrateSuspense(node, vnode, parentComponent, parentSuspense, namespace, slotScopeIds, optimized, rendererInternals, hydrateNode) { const suspense = vnode.suspense = createSuspenseBoundary( vnode, parentSuspense, parentComponent, node.parentNode, + // eslint-disable-next-line no-restricted-globals document.createElement("div"), null, - isSVG, + namespace, slotScopeIds, optimized, rendererInternals, true - /* hydrating */ ); const result = hydrateNode( node, @@ -2960,8 +3192,8 @@ function normalizeSuspenseSlot(s) { } if (isArray(s)) { const singleChild = filterSingleRoot(s); - if (!singleChild) { - warn(` slots expect a single root node.`); + if (!singleChild && s.filter((child) => child !== NULL_DYNAMIC_COMPONENT).length > 0) { + warn$1(` slots expect a single root node.`); } s = singleChild; } @@ -2985,16 +3217,33 @@ function queueEffectWithSuspense(fn, suspense) { function setActiveBranch(suspense, branch) { suspense.activeBranch = branch; const { vnode, parentComponent } = suspense; - const el = vnode.el = branch.el; + let el = branch.el; + while (!el && branch.component) { + branch = branch.component.subTree; + el = branch.el; + } + vnode.el = el; if (parentComponent && parentComponent.subTree === vnode) { parentComponent.vnode.el = el; updateHOCHostEl(parentComponent, el); } } function isVNodeSuspensible(vnode) { - var _a; - return ((_a = vnode.props) == null ? void 0 : _a.suspensible) != null && vnode.props.suspensible !== false; + const suspensible = vnode.props && vnode.props.suspensible; + return suspensible != null && suspensible !== false; } +var ssrContextKey = Symbol.for("v-scx"); +var useSSRContext = () => { + { + const ctx = inject(ssrContextKey); + if (!ctx) { + warn$1( + `Server rendering context not provided. Make sure to only call useSSRContext() conditionally in the server build.` + ); + } + return ctx; + } +}; function watchEffect(effect2, options) { return doWatch(effect2, null, options); } @@ -3015,34 +3264,61 @@ function watchSyncEffect(effect2, options) { var INITIAL_WATCHER_VALUE = {}; function watch(source, cb, options) { if (!isFunction(cb)) { - warn( + warn$1( `\`watch(fn, options?)\` signature has been moved to a separate API. Use \`watchEffect(fn, options?)\` instead. \`watch\` now only supports \`watch(source, cb, options?) signature.` ); } return doWatch(source, cb, options); } -function doWatch(source, cb, { immediate, deep, flush, onTrack, onTrigger } = EMPTY_OBJ) { - var _a; +function doWatch(source, cb, { + immediate, + deep, + flush, + once, + onTrack, + onTrigger +} = EMPTY_OBJ) { + if (cb && once) { + const _cb = cb; + cb = (...args) => { + _cb(...args); + unwatch(); + }; + } + if (deep !== void 0 && typeof deep === "number") { + warn$1( + `watch() "deep" option with number value will be used as watch depth in future versions. Please use a boolean instead to avoid potential breakage.` + ); + } if (!cb) { if (immediate !== void 0) { - warn( + warn$1( `watch() "immediate" option is only respected when using the watch(source, callback, options?) signature.` ); } if (deep !== void 0) { - warn( + warn$1( `watch() "deep" option is only respected when using the watch(source, callback, options?) signature.` ); } + if (once !== void 0) { + warn$1( + `watch() "once" option is only respected when using the watch(source, callback, options?) signature.` + ); + } } const warnInvalidSource = (s) => { - warn( + warn$1( `Invalid watch source: `, s, `A watch source can only be a getter/effect function, a ref, a reactive object, or an array of these types.` ); }; - const instance = getCurrentScope() === ((_a = currentInstance) == null ? void 0 : _a.scope) ? currentInstance : null; + const instance = currentInstance; + const reactiveGetter = (source2) => deep === true ? source2 : ( + // for deep: false, only traverse root-level properties + traverse(source2, deep === false ? 1 : void 0) + ); let getter; let forceTrigger = false; let isMultiSource = false; @@ -3050,8 +3326,8 @@ function doWatch(source, cb, { immediate, deep, flush, onTrack, onTrigger } = EM getter = () => source.value; forceTrigger = isShallow(source); } else if (isReactive(source)) { - getter = () => source; - deep = true; + getter = () => reactiveGetter(source); + forceTrigger = true; } else if (isArray(source)) { isMultiSource = true; forceTrigger = source.some((s) => isReactive(s) || isShallow(s)); @@ -3059,7 +3335,7 @@ function doWatch(source, cb, { immediate, deep, flush, onTrack, onTrigger } = EM if (isRef(s)) { return s.value; } else if (isReactive(s)) { - return traverse(s); + return reactiveGetter(s); } else if (isFunction(s)) { return callWithErrorHandling(s, instance, 2); } else { @@ -3071,9 +3347,6 @@ function doWatch(source, cb, { immediate, deep, flush, onTrack, onTrigger } = EM getter = () => callWithErrorHandling(source, instance, 2); } else { getter = () => { - if (instance && instance.isUnmounted) { - return; - } if (cleanup) { cleanup(); } @@ -3097,18 +3370,17 @@ function doWatch(source, cb, { immediate, deep, flush, onTrack, onTrigger } = EM let onCleanup = (fn) => { cleanup = effect2.onStop = () => { callWithErrorHandling(fn, instance, 4); + cleanup = effect2.onStop = void 0; }; }; let oldValue = isMultiSource ? new Array(source.length).fill(INITIAL_WATCHER_VALUE) : INITIAL_WATCHER_VALUE; const job = () => { - if (!effect2.active) { + if (!effect2.active || !effect2.dirty) { return; } if (cb) { const newValue = effect2.run(); - if (deep || forceTrigger || (isMultiSource ? newValue.some( - (v, i) => hasChanged(v, oldValue[i]) - ) : hasChanged(newValue, oldValue)) || false) { + if (deep || forceTrigger || (isMultiSource ? newValue.some((v, i) => hasChanged(v, oldValue[i])) : hasChanged(newValue, oldValue)) || false) { if (cleanup) { cleanup(); } @@ -3136,7 +3408,14 @@ function doWatch(source, cb, { immediate, deep, flush, onTrack, onTrigger } = EM job.id = instance.uid; scheduler = () => queueJob(job); } - const effect2 = new ReactiveEffect(getter, scheduler); + const effect2 = new ReactiveEffect(getter, NOOP, scheduler); + const scope = getCurrentScope(); + const unwatch = () => { + effect2.stop(); + if (scope) { + remove(scope.effects, effect2); + } + }; { effect2.onTrack = onTrack; effect2.onTrigger = onTrigger; @@ -3155,12 +3434,6 @@ function doWatch(source, cb, { immediate, deep, flush, onTrack, onTrigger } = EM } else { effect2.run(); } - const unwatch = () => { - effect2.stop(); - if (instance && instance.scope) { - remove(instance.scope.effects, effect2); - } - }; return unwatch; } function instanceWatch(source, value, options) { @@ -3173,14 +3446,9 @@ function instanceWatch(source, value, options) { cb = value.handler; options = value; } - const cur = currentInstance; - setCurrentInstance(this); + const reset = setCurrentInstance(this); const res = doWatch(getter, cb.bind(publicThis), options); - if (cur) { - setCurrentInstance(cur); - } else { - unsetCurrentInstance(); - } + reset(); return res; } function createPathGetter(ctx, path) { @@ -3193,8 +3461,8 @@ function createPathGetter(ctx, path) { return cur; }; } -function traverse(value, seen) { - if (!isObject(value) || value["__v_skip"]) { +function traverse(value, depth = Infinity, seen) { + if (depth <= 0 || !isObject(value) || value["__v_skip"]) { return value; } seen = seen || /* @__PURE__ */ new Set(); @@ -3202,35 +3470,35 @@ function traverse(value, seen) { return value; } seen.add(value); + depth--; if (isRef(value)) { - traverse(value.value, seen); + traverse(value.value, depth, seen); } else if (isArray(value)) { for (let i = 0; i < value.length; i++) { - traverse(value[i], seen); + traverse(value[i], depth, seen); } } else if (isSet(value) || isMap(value)) { value.forEach((v) => { - traverse(v, seen); + traverse(v, depth, seen); }); } else if (isPlainObject(value)) { for (const key in value) { - traverse(value[key], seen); + traverse(value[key], depth, seen); } } return value; } function validateDirectiveName(name) { if (isBuiltInDirective(name)) { - warn("Do not use built-in directive ids as custom directive id: " + name); + warn$1("Do not use built-in directive ids as custom directive id: " + name); } } function withDirectives(vnode, directives) { - const internalInstance = currentRenderingInstance; - if (internalInstance === null) { - warn(`withDirectives can only be used inside render functions.`); + if (currentRenderingInstance === null) { + warn$1(`withDirectives can only be used inside render functions.`); return vnode; } - const instance = getExposeProxy(internalInstance) || internalInstance.proxy; + const instance = getExposeProxy(currentRenderingInstance) || currentRenderingInstance.proxy; const bindings = vnode.dirs || (vnode.dirs = []); for (let i = 0; i < directives.length; i++) { let [dir, value, arg, modifiers = EMPTY_OBJ] = directives[i]; @@ -3277,6 +3545,8 @@ function invokeDirectiveHook(vnode, prevVNode, instance, name) { } } } +var leaveCbKey = Symbol("_leaveCb"); +var enterCbKey$1 = Symbol("_enterCb"); function useTransitionState() { const state = { isMounted: false, @@ -3319,7 +3589,6 @@ var BaseTransitionImpl = { setup(props, { slots }) { const instance = getCurrentInstance(); const state = useTransitionState(); - let prevTransitionKey; return () => { const children = slots.default && getTransitionRawChildren(slots.default(), true); if (!children || !children.length) { @@ -3331,7 +3600,7 @@ var BaseTransitionImpl = { for (const c of children) { if (c.type !== Comment) { if (hasFound) { - warn( + warn$1( " can only be used on a single element or component. Use for lists." ); break; @@ -3344,7 +3613,7 @@ var BaseTransitionImpl = { const rawProps = toRaw(props); const { mode } = rawProps; if (mode && mode !== "in-out" && mode !== "out-in" && mode !== "default") { - warn(`invalid mode: ${mode}`); + warn$1(`invalid mode: ${mode}`); } if (state.isLeaving) { return emptyPlaceholder(child); @@ -3362,18 +3631,7 @@ var BaseTransitionImpl = { setTransitionHooks(innerChild, enterHooks); const oldChild = instance.subTree; const oldInnerChild = oldChild && getKeepAliveChild(oldChild); - let transitionKeyChanged = false; - const { getTransitionKey } = innerChild.type; - if (getTransitionKey) { - const key = getTransitionKey(); - if (prevTransitionKey === void 0) { - prevTransitionKey = key; - } else if (key !== prevTransitionKey) { - prevTransitionKey = key; - transitionKeyChanged = true; - } - } - if (oldInnerChild && oldInnerChild.type !== Comment && (!isSameVNodeType(innerChild, oldInnerChild) || transitionKeyChanged)) { + if (oldInnerChild && oldInnerChild.type !== Comment && !isSameVNodeType(innerChild, oldInnerChild)) { const leavingHooks = resolveTransitionHooks( oldInnerChild, rawProps, @@ -3381,11 +3639,12 @@ var BaseTransitionImpl = { instance ); setTransitionHooks(oldInnerChild, leavingHooks); - if (mode === "out-in") { + if (mode === "out-in" && innerChild.type !== Comment) { state.isLeaving = true; leavingHooks.afterLeave = () => { state.isLeaving = false; if (instance.update.active !== false) { + instance.effect.dirty = true; instance.update(); } }; @@ -3397,9 +3656,9 @@ var BaseTransitionImpl = { oldInnerChild ); leavingVNodesCache[String(oldInnerChild.key)] = oldInnerChild; - el._leaveCb = () => { + el[leaveCbKey] = () => { earlyRemove(); - el._leaveCb = void 0; + el[leaveCbKey] = void 0; delete enterHooks.delayedLeave; }; enterHooks.delayedLeave = delayedLeave; @@ -3470,15 +3729,15 @@ function resolveTransitionHooks(vnode, props, state, instance) { return; } } - if (el._leaveCb) { - el._leaveCb( + if (el[leaveCbKey]) { + el[leaveCbKey]( true /* cancelled */ ); } const leavingVNode = leavingVNodesCache[key]; - if (leavingVNode && isSameVNodeType(vnode, leavingVNode) && leavingVNode.el._leaveCb) { - leavingVNode.el._leaveCb(); + if (leavingVNode && isSameVNodeType(vnode, leavingVNode) && leavingVNode.el[leaveCbKey]) { + leavingVNode.el[leaveCbKey](); } callHook2(hook, [el]); }, @@ -3496,7 +3755,7 @@ function resolveTransitionHooks(vnode, props, state, instance) { } } let called = false; - const done = el._enterCb = (cancelled) => { + const done = el[enterCbKey$1] = (cancelled) => { if (called) return; called = true; @@ -3508,7 +3767,7 @@ function resolveTransitionHooks(vnode, props, state, instance) { if (hooks.delayedLeave) { hooks.delayedLeave(); } - el._enterCb = void 0; + el[enterCbKey$1] = void 0; }; if (hook) { callAsyncHook(hook, [el, done]); @@ -3518,8 +3777,8 @@ function resolveTransitionHooks(vnode, props, state, instance) { }, leave(el, remove2) { const key2 = String(vnode.key); - if (el._enterCb) { - el._enterCb( + if (el[enterCbKey$1]) { + el[enterCbKey$1]( true /* cancelled */ ); @@ -3529,7 +3788,7 @@ function resolveTransitionHooks(vnode, props, state, instance) { } callHook2(onBeforeLeave, [el]); let called = false; - const done = el._leaveCb = (cancelled) => { + const done = el[leaveCbKey] = (cancelled) => { if (called) return; called = true; @@ -3539,7 +3798,7 @@ function resolveTransitionHooks(vnode, props, state, instance) { } else { callHook2(onAfterLeave, [el]); } - el._leaveCb = void 0; + el[leaveCbKey] = void 0; if (leavingVNodesCache[key2] === vnode) { delete leavingVNodesCache[key2]; } @@ -3565,7 +3824,21 @@ function emptyPlaceholder(vnode) { } } function getKeepAliveChild(vnode) { - return isKeepAlive(vnode) ? vnode.children ? vnode.children[0] : void 0 : vnode; + if (!isKeepAlive(vnode)) { + return vnode; + } + if (vnode.component) { + return vnode.component.subTree; + } + const { shapeFlag, children } = vnode; + if (children) { + if (shapeFlag & 16) { + return children[0]; + } + if (shapeFlag & 32 && isFunction(children.default)) { + return children.default(); + } + } } function setTransitionHooks(vnode, hooks) { if (vnode.shapeFlag & 6 && vnode.component) { @@ -3648,7 +3921,7 @@ function defineAsyncComponent(source) { return pendingRequest; } if (!comp) { - warn( + warn$1( `Async component loader resolved to undefined. If you are using retry(), make sure to return its return value.` ); } @@ -3680,7 +3953,6 @@ function defineAsyncComponent(source) { instance, 13, !errorComponent - /* do not throw in dev if user provided error component */ ); }; if (suspensible && instance.suspense || false) { @@ -3715,6 +3987,7 @@ function defineAsyncComponent(source) { load().then(() => { loaded.value = true; if (instance.parent && isKeepAlive(instance.parent.vnode)) { + instance.parent.effect.dirty = true; queueJob(instance.parent.update); } }).catch((err) => { @@ -3774,7 +4047,7 @@ var KeepAliveImpl = { } } = sharedContext; const storageContainer = createElement("div"); - sharedContext.activate = (vnode, container, anchor, isSVG, optimized) => { + sharedContext.activate = (vnode, container, anchor, namespace, optimized) => { const instance2 = vnode.component; move(vnode, container, anchor, 0, parentSuspense); patch( @@ -3784,7 +4057,7 @@ var KeepAliveImpl = { anchor, instance2, parentSuspense, - isSVG, + namespace, vnode.slotScopeIds, optimized ); @@ -3880,7 +4153,7 @@ var KeepAliveImpl = { const rawVNode = children[0]; if (children.length > 1) { { - warn(`KeepAlive should contain exactly one component child.`); + warn$1(`KeepAlive should contain exactly one component child.`); } current = null; return children; @@ -3994,9 +4267,9 @@ function injectHook(type, hook, target = currentInstance, prepend = false) { return; } pauseTracking(); - setCurrentInstance(target); + const reset = setCurrentInstance(target); const res = callWithAsyncErrorHandling(hook, target, type, args); - unsetCurrentInstance(); + reset(); resetTracking(); return res; }); @@ -4007,8 +4280,8 @@ function injectHook(type, hook, target = currentInstance, prepend = false) { } return wrappedHook; } else { - const apiName = toHandlerKey(ErrorTypeStrings[type].replace(/ hook$/, "")); - warn( + const apiName = toHandlerKey(ErrorTypeStrings$1[type].replace(/ hook$/, "")); + warn$1( `${apiName} is called when there is no active component instance to be associated with. Lifecycle injection APIs can only be used during execution of setup(). If you are using async setup(), make sure to register lifecycle hooks before the first await statement.` ); } @@ -4033,97 +4306,43 @@ var onRenderTracked = createHook( function onErrorCaptured(hook, target = currentInstance) { injectHook("ec", hook, target); } -var COMPONENTS = "components"; -var DIRECTIVES = "directives"; -function resolveComponent(name, maybeSelfReference) { - return resolveAsset(COMPONENTS, name, true, maybeSelfReference) || name; -} -var NULL_DYNAMIC_COMPONENT = Symbol.for("v-ndc"); -function resolveDynamicComponent(component) { - if (isString(component)) { - return resolveAsset(COMPONENTS, component, false) || component; +function renderList(source, renderItem, cache, index) { + let ret; + const cached = cache && cache[index]; + if (isArray(source) || isString(source)) { + ret = new Array(source.length); + for (let i = 0, l = source.length; i < l; i++) { + ret[i] = renderItem(source[i], i, void 0, cached && cached[i]); + } + } else if (typeof source === "number") { + if (!Number.isInteger(source)) { + warn$1(`The v-for range expect an integer value but got ${source}.`); + } + ret = new Array(source); + for (let i = 0; i < source; i++) { + ret[i] = renderItem(i + 1, i, void 0, cached && cached[i]); + } + } else if (isObject(source)) { + if (source[Symbol.iterator]) { + ret = Array.from( + source, + (item, i) => renderItem(item, i, void 0, cached && cached[i]) + ); + } else { + const keys = Object.keys(source); + ret = new Array(keys.length); + for (let i = 0, l = keys.length; i < l; i++) { + const key = keys[i]; + ret[i] = renderItem(source[key], key, i, cached && cached[i]); + } + } } else { - return component || NULL_DYNAMIC_COMPONENT; + ret = []; } -} -function resolveDirective(name) { - return resolveAsset(DIRECTIVES, name); -} -function resolveAsset(type, name, warnMissing = true, maybeSelfReference = false) { - const instance = currentRenderingInstance || currentInstance; - if (instance) { - const Component = instance.type; - if (type === COMPONENTS) { - const selfName = getComponentName( - Component, - false - /* do not include inferred name to avoid breaking existing code */ - ); - if (selfName && (selfName === name || selfName === camelize(name) || selfName === capitalize(camelize(name)))) { - return Component; - } - } - const res = ( - // local registration - // check instance[type] first which is resolved for options API - resolve(instance[type] || Component[type], name) || // global registration - resolve(instance.appContext[type], name) - ); - if (!res && maybeSelfReference) { - return Component; - } - if (warnMissing && !res) { - const extra = type === COMPONENTS ? ` -If this is a native custom element, make sure to exclude it from component resolution via compilerOptions.isCustomElement.` : ``; - warn(`Failed to resolve ${type.slice(0, -1)}: ${name}${extra}`); - } - return res; - } else { - warn( - `resolve${capitalize(type.slice(0, -1))} can only be used in render() or setup().` - ); - } -} -function resolve(registry, name) { - return registry && (registry[name] || registry[camelize(name)] || registry[capitalize(camelize(name))]); -} -function renderList(source, renderItem, cache, index) { - let ret; - const cached = cache && cache[index]; - if (isArray(source) || isString(source)) { - ret = new Array(source.length); - for (let i = 0, l = source.length; i < l; i++) { - ret[i] = renderItem(source[i], i, void 0, cached && cached[i]); - } - } else if (typeof source === "number") { - if (!Number.isInteger(source)) { - warn(`The v-for range expect an integer value but got ${source}.`); - } - ret = new Array(source); - for (let i = 0; i < source; i++) { - ret[i] = renderItem(i + 1, i, void 0, cached && cached[i]); - } - } else if (isObject(source)) { - if (source[Symbol.iterator]) { - ret = Array.from( - source, - (item, i) => renderItem(item, i, void 0, cached && cached[i]) - ); - } else { - const keys = Object.keys(source); - ret = new Array(keys.length); - for (let i = 0, l = keys.length; i < l; i++) { - const key = keys[i]; - ret[i] = renderItem(source[key], key, i, cached && cached[i]); - } - } - } else { - ret = []; - } - if (cache) { - cache[index] = ret; - } - return ret; + if (cache) { + cache[index] = ret; + } + return ret; } function createSlots(slots, dynamicSlots) { for (let i = 0; i < dynamicSlots.length; i++) { @@ -4151,7 +4370,7 @@ function renderSlot(slots, name, props = {}, fallback, noSlotted) { } let slot = slots[name]; if (slot && slot.length > 1) { - warn( + warn$1( `SSR-optimized slot function detected in a non-SSR-optimized render function. You need to mark this component with $dynamic-slots in the parent template.` ); slot = () => []; @@ -4193,7 +4412,7 @@ function ensureValidVNode(vnodes) { function toHandlers(obj, preserveCaseIfNecessary) { const ret = {}; if (!isObject(obj)) { - warn(`v-on with no argument expects an object value.`); + warn$1(`v-on with no argument expects an object value.`); return ret; } for (const key in obj) { @@ -4223,7 +4442,10 @@ var publicPropertiesMap = ( $root: (i) => getPublicInstance(i.root), $emit: (i) => i.emit, $options: (i) => resolveMergedOptions(i), - $forceUpdate: (i) => i.f || (i.f = () => queueJob(i.update)), + $forceUpdate: (i) => i.f || (i.f = () => { + i.effect.dirty = true; + queueJob(i.update); + }), $nextTick: (i) => i.n || (i.n = nextTick.bind(i.proxy)), $watch: (i) => instanceWatch.bind(i) }) @@ -4232,6 +4454,9 @@ var isReservedPrefix = (key) => key === "_" || key === "$"; var hasSetupBinding = (state, key) => state !== EMPTY_OBJ && !state.__isScriptSetup && hasOwn(state, key); var PublicInstanceProxyHandlers = { get({ _: instance }, key) { + if (key === "__v_skip") { + return true; + } const { ctx, setupState, data, props, accessCache, type, appContext } = instance; if (key === "__isVue") { return true; @@ -4274,7 +4499,7 @@ var PublicInstanceProxyHandlers = { let cssModule, globalProperties; if (publicGetter) { if (key === "$attrs") { - track(instance, "get", key); + track(instance.attrs, "get", ""); markAttrsAccessed(); } else if (key === "$slots") { track(instance, "get", key); @@ -4299,13 +4524,13 @@ var PublicInstanceProxyHandlers = { // to infinite warning loop key.indexOf("__v") !== 0)) { if (data !== EMPTY_OBJ && isReservedPrefix(key[0]) && hasOwn(data, key)) { - warn( + warn$1( `Property ${JSON.stringify( key )} must be accessed via $data because it starts with a reserved character ("$" or "_") and is not proxied on the render context.` ); } else if (instance === currentRenderingInstance) { - warn( + warn$1( `Property ${JSON.stringify(key)} was accessed during render but is not defined on instance.` ); } @@ -4317,17 +4542,17 @@ var PublicInstanceProxyHandlers = { setupState[key] = value; return true; } else if (setupState.__isScriptSetup && hasOwn(setupState, key)) { - warn(`Cannot mutate diff --git a/src/partners/partners.json b/src/partners/partners.json index 0af53d40..6f34833f 100644 --- a/src/partners/partners.json +++ b/src/partners/partners.json @@ -1,25 +1,25 @@ [ { - "name": "Vehikl", + "name": "vehikl", "logo": "vehikl.svg", "flipLogo": true, - "intro": "Vehikl has deep knowledge of Vue and will act as an extension of your team. We focus on writing clean, maintainable code. We are passionate about continual improvement, and we practice Mob Programming and Pair Programming on a daily basis.", + "intro": "تتمتع فيهكل بمعرفة عميقة في فيو وستعمل كامل التمديد لفريقك. نحن متخصصون في كتابة رمز نظيف وقابل للصيانة. نحن متحمسون للتحسين المستمر، ونمارس البرمجة الجماعية والبرمجة بالأزواج يوميًا.", "description": [ - "Vehikl is a Team that values Caring, Growing, and Delivering. We instill those values in everything we do, and everyone we work with. Our goal is to be an extension of your development efforts, and build exceptional web and mobile applications.", - "Our Team has a strong specialty and deep knowledge of Vue, Laravel, and React frameworks. In addition to this, our Team of 75 has worked with every tech stack you can imagine. We’re proud test-driven developers who focus on writing clean, maintainable code. Our Team is passionate about continual improvement, and we practice Mob Programming and Pair Programming on a daily basis.", - "We’ve worked on projects from a wide range of companies ranging from startups to enterprise-level organizations. We are one team with our clients and we share in their successes.", - "So what does working with us look like?", - "- Daily communication with your team", - "- Collaborate with you on weekly or bi-weekly Sprint Planning", - "- Demos & Retrospectives at the end of each Sprint", - "- Collaborative PR reviews", - "- Daily Pairing and Mobbing sessions", - "We’re always looking for opportunities to learn new things and refine our skills using lean Agile development, open communication, and collaboration. We combine one-on-one communication, and the iterative values of the Agile methodology to deliver high quality code.", - "We’re active members of the JavaScript and PHP community, and love to collaborate with other enthusiasts." + "فهيكل فريق يقدّر الرعاية، والنمو، والتسليم. نحن نغرس هذه القيم في كل ما نقوم به، ومع كل شخص نتعامل معه. هدفنا هو أن نكون تمديدًا لجهود تطويركم، وأن نبني تطبيقات ويب ومحمولة استثنائية.", + "فريقنا لديه تخصص قوي ومعرفة عميقة في إطارات فيو و لارافل و ريآكت. بالإضافة إلى ذلك، عمل فريقنا المؤلف من 75 شخصًا مع كل تراكم تكنولوجي يمكن تخيله. نحن نفخر بكوننا مطورين يعتمدون على الاختبارات ونركز على كتابة رمز نظيف وقابل للصيانة. فريقنا متحمس للتحسين المستمر، ونمارس البرمجة الجماعية والبرمجة بالأزواج يوميًا.", + "لقد عملنا على مشاريع من مجموعة واسعة من الشركات، بدءًا من الشركات الناشئة وصولاً إلى المؤسسات ذات المستوى الشامل. نحن فريق واحد مع عملائنا ونشارك في نجاحاتهم.", + "كيف يبدو العمل معنا؟", + "- تواصل يومي مع فريقك", + "- التعاون معك في التخطيط الأسبوعي أو كل أسبوعين للتنمية.", + "- عروض العمل النهائية والتقييمات في نهاية كل دورة عمل.", + "- مراجعات طلبات سحب الكود التعاونية", + "- جلسات المشاركة البرمجية اليومية وبرمجة العصف الذهني الجماعية", + "نحن دائمًا نبحث عن فرص لتعلم أشياء جديدة وصقل مهاراتنا باستخدام منهجية آجيل الرشيقة والاتصال المفتوح والتعاون. نحن نجمع بين التواصل الفردي والقيم المتكررة لمنهجية آجيل لتقديم أكواد عالية الجودة.", + "نحن أعضاء نشطاء في مجتمعات جافا سكريبت وبي إتش بي، ونحب التعاون مع المتحمسين الآخرين." ], - "proficiencies": ["Vue", "Laravel", "React", "Node.js", "Unity"], - "region": ["North America"], - "location": ["Ontario, Canada"], + "proficiencies": ["فيو", "لارافل", "ريآكت", "نود", "يونيتي"], + "region": ["أمريكا الشمالية"], + "location": ["أونتاريو - كندا"], "website": { "text": "www.vehikl.com", "url": "https://www.vehikl.com?utm_source=vue_partners_page" @@ -32,17 +32,17 @@ "name": "Passionate People", "logo": "passionatepeople.png", "flipLogo": true, - "intro": "We provide you with additional technical capacity to power-up your digital transformation journeys with our teams of first-class engineers and consultants. Full stack JavaScript Cloud Engineers ready to work with you and your teams.", + "intro": "نمنحك موارد تقنية إضافية لدفع رحلات التحول الرقمي الخاصة بك إلى الأمام من خلال فرقنا من مهندسي البرامج والاستشاريين ذوي الخبرة العالية. لدينا فريق متخصص في البرمجيات الشاملة من مهندسي جافاسكريبت السحابي جاهزون للعمل معك ومع فرقك.", "description": [ - "Founded in October 2017, Passionate People is the leading JavaScript consultancy in the Netherlands.", - "Our aim is to help our customers speed up their digital transformation initiatives at scale, and our standard is the highest in the sector.", - "We have a wide client base spanning industries such as FinTech, E-commerce, Logistics, Supply Chain, Industrial Automation, etc. To achieve their digital goals and to make their products scalable and secure for millions of users, companies such as Albert Heijn Digital, GrandVision, Nationale Nederlanden, Talpa and AKQA have trusted us to deliver top-notch work.", - "Besides being the leading JavaScript Consultancy in the Netherlands, Passionate People is also proud to host the largest tech conferences and community events in the world.", - "Starting in February 2018 with Frontend Love and Vue.js Amsterdam, we are now responsible for many other conferences in Europe under the Frontend Love brand: React Live, AngularNL, Vue.js Amsterdam, and JS World Conference." + "تأسست شركة باشونيت بيبول في أكتوبر 2017 وهي شركة استشارات جافاسكريبت الرائدة في هولندا.", + "هدفنا هو مساعدة عملائنا على تسريع مبادرات التحول الرقمي الخاصة بهم على نطاق واسع، ومعاييرنا هي الأعلى في المجال.", + "هنا في باشونيت بيبول، نمتلك قاعدة عملاء واسعة تمتد عبر قطاعات مختلفة مثل التكنولوجيا المالية والتجارة الإلكترونية والخدمات اللوجستية وسلسلة التوريد والأتمتة الصناعية وما إلى ذلك. لمساعدة هذه الشركات على تحقيق أهدافها الرقمية وجعل منتجاتها قابلة للتوسع وآمنة لملايين المستخدمين، فقد وضعت شركات مثل ألبرت هاين ديجيتال و جراند فيجن و الوطنية الهولندية و تالبا و إي-كي-كيو-كي ثقتها فينا لتقديم أعمال متميزة.", + "إلى جانب كونها شركة استشارات جافاسكريبت الرائدة في هولندا، تفخر باشونيت بيبول أيضًا باستضافة أكبر مؤتمرات التكنولوجيا وفعاليات المجتمع في العالم.", + "انطلاقًا من فبراير 2018 مع فرونت إند لوف و فيو أمستردام، نحن الآن مسؤولون عن العديد من المؤتمرات الأخرى في أوروبا تحت علامة فرونت إند لوف التجارية: ريآكت لايف و أنجولار إن إل و فيو أمستردام و مؤتمر جافاسكريبت العالمي." ], - "proficiencies": ["Vue", "Nuxt", "Node.js", "JAMStack"], - "region": ["Europe"], - "location": ["Amsterdam, Netherlands"], + "proficiencies": ["فيو", "نوكست", "نود", "جام ستاك"], + "region": ["أوروبا"], + "location": ["أمستردام, هولندا"], "website": { "text": "passionatepeople.io", "url": "https://passionatepeople.io/" @@ -54,27 +54,27 @@ "name": "Monterail", "logo": "monterail.png", "flipLogo": true, - "intro": "Monterail is a full-service software development company from Poland. Since 2010, we have been building innovative software for start-ups, SMBs, and enterprises from various industries globally. Our Vue experts, using battle-tested technologies and frameworks, have delivered more than 30 Vue-based projects.", + "intro": "شركة مونتريال هي شركة تطوير برمجيات متكاملة الخدمات، تتخذ من بولندا مقراً لها. منذ عام 2010، ونحن نعمل على بناء برمجيات مبتكرة للشركات الناشئة والشركات الصغيرة والمتوسطة والمؤسسات من مختلف الصناعات حول العالم. لقد قام خبراء فيو لدينا، باستخدام تقنيات وأطر عمل مجربة، بتسليم أكثر من 30 مشروعًا قائمًا على فيو.", "description": [ - "At a full-service consultancy like Monterail, you get every competence under one roof. From concept, to design, and product release. Depending on the product lifecycle stage, we guide clients through building applications from scratch or scaling them quickly.", - "A diverse pool of experts, including Product Designers, QA specialists and Business Analysts, take care of professional tech stack consultation and business idea validation. We work within the Agile methodology ensuring smooth communication flow and aim for long-term partnerships. We've developed all kinds of Vue applications from virtual real estate tours to donation platforms.", - "Why Monterail?", - "- Listed in the Financial Times 1000 rank twice in a row (2018 & 2019)", - "- Recognized by Deloitte as one of the fastest-growing tech companies in Central Europe (2016 & 2017)", - "- Rated 4.7/5 on Clutch.", - "- NPS Score - 71", - "- Experts in software development and design with solid business experience", - "- A team experienced with remote work in a multicultural environment", - "- Detailed budget estimation received in weeks, not months" + "في شركة استشارات متكاملة الخدمات مثل مونتريال، تحصل على جميع الخبرات تحت سقف واحد. بدءًا من المفهوم إلى التصميم وإصدار المنتج. وفقًا للمرحلة التي يمر بها دورة حياة المنتج، فإننا نوجه العملاء خلال بناء تطبيقات من البداية أو توسيع نطاقها بسرعة.", + "تمتلك مونتريال مجموعة متنوعة من الخبراء، بما في ذلك مصممي المنتجات، واخصائيين ضمان الجودة، ومحللي الأعمال، الذين يهتمون بالاستشارات المهنية للمكدس التقني وإثبات صحة أفكار الأعمال. نعمل وفقًا لمنهجية آجايل لضمان تدفق اتصال سلس ونهدف إلى شراكات طويلة الأجل. قمنا بتطوير جميع أنواع تطبيقات فيو بدءًا من الجولات العقارية الافتراضية إلى منصات التبرعات.", + "لماذا مونتريال؟", + "- أُدرجت مونتريال ضمن قائمة فاينانشال تايمز 1000 للشركات الأوروبية الأسرع نموًا لعامين متتالين (2018 و 2019).", + "- أُقرت مونتريال من قِبل ديلويت كإحدى أسرع شركات التقنية نموًا في وسط أوروبا (2016 & 2017)", + "- حققت مونتريال تقييمًا قدره 4.7 / 5 على كلاتش", + "- NPS (معدل صافي المروجين) لشركة مونتريال هو 71", + "- خبراء في تطوير وتصميم البرمجيات مع خبرة تجارية قوية", + "- فريق لديه خبرة في العمل عن بعد في بيئة متعددة الثقافات", + "- تقدير مفصل للميزانية يتم استلامه خلال أسابيع ، وليس شهورًا" ], "proficiencies": [ - "Vue.js", - "Ruby on Rails", - "Node.js", - "React Native", - "Flutter" + "فيو", + "روبي اون ريلز", + "نود", + "ريآكت نيتيف", + "فلاتر" ], - "region": ["Europe"], + "region": ["أوروبا"], "website": { "text": "www.monterail.com", "url": "https://www.monterail.com/services/vue/?utm_source=vuejs.org" @@ -86,24 +86,24 @@ { "name": "Curotec", "logo": "curotec.png", - "intro": "Work with a team that understands Vue.js inside and out. SaaS and enterprise teams leverage Curotec for best-in-class project execution and staff augmentation services focused on Vue.js.", + "intro": "اعمل مع فريق يفهم فيو تمامًا. تستفيد فرق SaaS والمؤسسات من كيوروتيك للحصول على أفضل تنفيذ للمشاريع وخدمات تعزيز الموظفين التي تركز على فيو", "description": [ - "Whether you need a firm to build your idea, support an existing codebase, or augment your front-end dev team, we’ve got you covered. SaaS and enterprise product teams turn to Curotec for a firm that can get the job done right.", - "We've got an all-shores model with team members in the US, LATAM, and South Asia. We'll create a flexible engagement for your needs aligned with your budget, timezone, and project goals. We also cover three main focus areas which include:", - "- Enterprise software development", - "- SaaS product development", - "- Headless / Jamstack website development", - "If you're looking for a Vue.js-focused front-end development team that writes great quality code and gets stuff done, click the contact button below and get in touch!" + "سواء كنت تبحث عن شركة لبناء فكرتك أو دعم قاعدة كودية موجودة أو تعزيز فريق تطوير واجهة المستخدم لديك، فنحن نضمن لك ذلك. تلجأ فرق منتجات SaaS والمؤسسات إلى كيوروتيك للحصول على شركة يمكنها إنجاز المهمة بشكل صحيح", + "لدينا نموذج عمل شمولي بفريق عمل موزع جغرافيا في الولايات المتحدة الأمريكية و أمريكا اللاتينية و جنوب آسيا. سننشئ ارتباطًا مرنًا لاحتياجاتك بما يتماشى مع ميزانيتك ومنطقتك الزمنية وأهداف المشروع، كما نغطي ثلاث مجالات رئيسية تشمل:", + "- تطوير برمجيات مؤسسية", + "- تطوير تطبيقات SASS", + "- طوير مواقع الويب الثابتة الحديثة / باستخدام جملة أدوات جامستاك", + "إذا كنت تبحث عن فريق تطوير واجهة مستخدم متخصص في فيو يكتب أكواد عالية الجودة وينجز المهام ، فانقر على زر الاتصال أدناه وتواصل معنا!" ], - "region": ["North America", "Latin America"], + "region": ["أمريكا الشمالية", "أمريكا اللاتينية"], "proficiencies": [ - "Vue.js", - "Nuxt", - "Laravel", - "Headless", - "Node.js", - "Python", - "WordPress" + "فيو", + "نوكست", + "لارافل", + "هيدليس", + "نود", + "بايثون", + "ووردبريس" ], "website": { "text": "www.curotec.com", @@ -117,15 +117,15 @@ "name": "Tighten", "logo": "tighten.svg", "flipLogo": true, - "intro": "Treat people well, solve the right problems, build spectacular software—that's how we roll. We're ultra-focused and deeply experienced in the technology powering modern business, including Vue.js. Via our signature method, our meticulously assembled team delivers unparalleled service, helping you do more with your software, and do right by your business.", + "intro": "نتميز بالتعامل الراقي ونحل المشكلات الصحيحة ونبني برمجيات مذهلة - هذه هي طريقتنا. نحن نركز بشكل كبير ونتمتع بخبرة عميقة في التقنية التي تدعم الأعمال التجارية الحديثة ، بما في ذلك فيو. من خلال منهجيتنا المميزة ، يقدم فريقنا الذي تم تجميعه بدقة خدمة لا مثيل لها ، مما يساعدك على تحقيق المزيد من خلال برمجياتك ، والقيام بالأعمال التجارية بشكل صحيح.", "description": [ - "Empathetically opinionated, expertly executed development. That's what we deliver.", - "At Tighten, we sweat the hell out of the details to give your app the fit-and-finish today's users expect, while giving you the clarity and confidence to charge ahead.", - "Whether you’re looking to simply enhance a user interface or build a sophisticated JavaScript-based application, we’ve got you covered. Vue.js is a flexible and robust framework, capable of powering a complex single-page application. We typically combine it with a Laravel-based API.", - "If you're building a development team, you know it takes time and diligence, and it could be the make-or-break factor for your business. Companies turn to Tighten at key turning points, to propel their technology forward while they assemble the right team for their business." + "تطوير مدروس يتم تنفيذه بخبرة. هذا ما نقدمه.", + "في تيتن، نركز بشدة على التفاصيل لنمنح تطبيقك المظهر والوظيفة التي يتوقعها مستخدمو اليوم، بينما نمنحك الوضوح والثقة للمضي قدمًا.", + "سواء كنت ترغب في تحسين واجهة مستخدم بسيطة أو بناء تطبيق معقد يستند إلى جافاسكريبت، فنحن نضمن لك ذلك. يُعد فيو إطار عمل مرنًا وقويًا، قادرًا على تشغيل تطبيق بتقنية الصفحة-الواحدة المعقد. عادة ما نقوم بربطه بواجهة برمجة تطبيقات", + "إذا كنت تبني فريق تطوير، فأنت تعلم أن الأمر يستغرق وقتًا واجتهادًا، ويمكن أن يكون عامل نجاح أو فشل لشركتك. تلجأ الشركات إلى تيتن في نقاط تحول رئيسية، لدفع تقنيتها إلى الأمام بينما تقوم بتجميع الفريق المناسب لأعمالها." ], - "region": ["North America", "Europe", "Latin America"], - "proficiencies": ["Vue", "Nuxt", "Laravel", "Inertia", "Tailwind"], + "region": ["أمريكا الشمالية", "أوروبا", "أمريكا اللاتينية"], + "proficiencies": ["فيو", "نوكست", "لارافيل", "إينيرشيا", "تيلويند"], "website": { "text": "tighten.com", "url": "https://tighten.com/vue" @@ -136,21 +136,21 @@ { "name": "Redberry", "logo": "redberry.png", - "intro": "We are a 100+ award-winning, Laravel & Vue partner software design, development, and growth marketing agency from Tbilisi. In 8 years, we have taken 300+ products from zero to hero using Vue, Laravel, React and React Native for clients ranging from startups and government institutions to international agencies and enterprises.", + "intro": "نحن شركة حائزة على جوائز متعددة، يزيد عدد موظفينا عن 100 موظف، نتخذ من تبليسي مقراً لنا ونعمل في مجال تصميم وتطوير البرمجيات وتسويق النمو، ونعتبر شركاء رسميين لكل من لارافيل و فيو. على مدار ثماني سنوات، قمنا بأخذ أكثر من 300 منتج من البداية إلى النجاح باستخدام فيو و لارافيل و ريآكت و ريآكت وذلك لمجموعة متنوعة من العملاء بدءًا من الشركات الناشئة والمؤسسات الحكومية وصولاً إلى الوكالات والمؤسسات الدولية.", "description": [ - "Redberry was born in 2014 as a four friends’ venture to bring digital transformation to the brick-to-mortar business in Georgia. Today, we are more than 150 and represent the biggest Georgian agency. We are multifaceted in every way - technology, services, people. We accompany our clients along the entire product journey - from product design to development to its growth. We boast a 100+ international award-winning team of legendary UX/UI designers, software developers, DevOps engineers, project managers, scrum masters, digital strategists, copywriters, content creators, and growth hackers. So call us your swiss-army-knife digital partner if you like; we do.", - "While we are a top-tier agency, one of the most beautiful things about us is our location, both literally and metaphorically. We are based in Georgia (country, not the state), where IT outsourcing is almost tax-free. As a result, our EU and US-based partner startups, agencies, and companies enjoy a longer runway and more significant project margins. Luckily, we have a substantial capacity and easy access to the rapidly growing local tech talent, so we are our clients’ reliable and scalable partner.", - "Besides being an official Laravel and now Vue Partner software house, we are a Google and Facebook partner creative growth agency, making us an ideal, full-service partner for 80+ companies of all sizes to grow their business progressively. It has also earned us the Best Agency of the Year titles twice in 3 years, 2019 and 2021. Our client’s business is our business, so we remain results-oriented at all times, on and off work hours, weekdays and weekends, to ensure we deliver the solutions that drive your business results. That mindset has shaped our list of clients with industry leaders and runner-ups in finance, insurance, real estate, auto, education, healthcare, etc.", - "As for the methodology, running our startup studio has imprinted agile into our DNA. We have built a dozen MVPs and continued developing them over time according to the ever-changing business requirements, honing our ability to optimize for low initial time-to-market and high development velocity on any project we take on. We also internalized and standardized setting up and maintaining adequate codebase test coverage and regularly using CI/CD pipelines, making our lives and codes that much more manageable.", - "If you would like to collaborate on extending your product team, you can contact us through our website." + "ولدت ريدبيري عام 2014 كمغامرة لأربعة أصدقاء بهدف جلب التحول الرقمي إلى الشركات التقليدية في جورجيا. اليوم ، نحن أكثر من 150 موظفًا ونمثل أكبر وكالة جورجية. نحن متعدد الأوجه من جميع النواحي - التكنولوجيا والخدمات والأشخاص. نرافق عملاءنا طوال رحلة المنتج - من تصميم المنتج إلى التطوير إلى نموه. نحن نتمتع بفريق حائز على أكثر من 100 جائزة دولية يضم نخبة من مصممي UX / UI ، ومطوري البرامج ، ومهندسي DevOps ، ومديري المشاريع ، ورؤساء سكروم ، والاستراتيجيين الرقميين ، وكتاب النصوص ، ومنشئي المحتوى ، ومخترقي النمو. إذن يمكنك تسميتنا بالشريك الرقمي متعدد الاستخدامات ، تمامًا مثل السكين السويسري ، فنحن كذلك بالفعل.", + "على الرغم من كوننا وكالة متميزة ، فإن أحد أجمل الأشياء المتعلقة بنا هو موقعنا ، حرفيًا مجازيًا. نحن مقيمون في جورجيا (الدولة ، وليس الولاية الأمريكية) ، حيث يكون الاستعانة الخارجية في مجال تكنولوجيا المعلومات معفاة من الضرائب تقريبًا. ونتيجة لذلك ، يتمتع شركاؤنا من الشركات الناشئة والوكالات والشركات التي تتخذ من الاتحاد الأوروبي والولايات المتحدة مقراً لها بهامش مشروع أطول وأرباح أكبر. لحسن الحظ ، لدينا قدرة كبيرة ووصول سهل إلى المواهب التكنولوجية المحلية التي تشهد نموًا سريعًا ، لذلك نحن شريك موثوق وقابل للتطوير لعملائنا.", + "إلى جانب كوننا شركة تطوير برمجيات رسمية شريكة لكل من لارافيل و فيو، نحن أيضًا وكالة نمو إبداعية شريكة لكل من جوجل وفيسبوك، مما يجعلنا شريكًا مثاليًا يقدم خدمات كاملة لأكثر من 80 شركة من جميع الأحجام لتنمية أعمالها تدريجيًا. كما منحنا هذا الأمر لقب أفضل وكالة للعام مرتين خلال ثلاث سنوات ، 2019 و 2021. عمل عملائنا هو عملنا ، لذلك نركز على النتائج دائمًا ، داخل وخارج ساعات العمل ، في أيام الأسبوع وعطلات نهاية الأسبوع ، لضمان تقديم الحلول التي تحقق نتائج أعمالك. شكلت هذه العقلية قائمة عملائنا التي تضم رواد الصناعة والوصافة في مجالات التمويل والتأمين والعقارات والسيارات والتعليم والرعاية الصحية وما إلى ذلك.", + "بالنسبة إلى المنهجية ، فإن تشغيل استوديو الشركات الناشئة الخاص بنا قد غرس مبادئ تطوير البرمجيات الرشيقة (آجايل) في صميم عملنا. قمنا ببناء عشرات من نماذج منتجات بالحد الأدنى من الميزات (MVPs) واستمرينا في تطويرها بمرور الوقت وفقًا لمتطلبات الأعمال المتغيرة باستمرار ، وصقلنا قدرتنا على التحسين من أجل تقليل وقت طرح المنتج الأولي وسرعة تطوير عالية في أي مشروع نتعهد به. كما قمنا بتوحيد وترسيخ إعداد والحفاظ على تغطية اختبار قاعدة الكود المناسبة واستخدام خطوط أنابيب الاندماج المستمر والتسليم المستمر (CI/CD) بشكل منتظم ، مما يجعل حياتنا وشفراتنا أكثر قابلية للإدارة.", + "للتعاون معنا في توسيع فريق منتجاتكم، يمكنكم الاتصال بنا من خلال موقعنا الإلكتروني." ], - "region": ["Europe"], + "region": ["أوروبا"], "proficiencies": [ - "Vue", - "Laravel", - "Node.js", - "React", - "React Native" + "فيو", + "لارافل", + "نود", + "ريآكت", + "ريآكت نيتيف" ], "website": { "text": "redberry.international", @@ -161,14 +161,14 @@ { "name": "WebReinvent", "logo": "webreinvent.png", - "intro": "WebReinvent is a software development company that provides a range of end-to-end software products, real-time apps, multi-tenant SaaS applications, low latency API & mobile app development services. We have delivered MVP to enterprise-level software globally from startup to MNC. Email us, and let's build your software product.", + "intro": "شركة ويب رينفنت هي شركة تطوير برمجيات تقدم مجموعة واسعة من منتجات البرامج المتكاملة وتطبيقات الوقت الفعلي وتطبيقات SaaS متعددة المستأجرين وخدمات تطوير واجهات برمجة التطبيقات ذات التأخير المنخفض وتطوير تطبيقات الجوال. لقد قمنا بتسليم منتجات بالحد الأدنى من الميزات (MVP) إلى برامج على مستوى المؤسسات على الصعيد العالمي ، بدءًا من الشركات الناشئة وحتى الشركات متعددة الجنسيات. أرسل لنا بريدًا إلكترونيًا ، لنبني معًا منتج البرامج الخاص بك.", "description": [ - "WebReinvent is a process-oriented software development company that provides a range of end-to-end software products, real-time apps, multi-tenant SaaS applications, low latency API & mobile apps development services. Our team is well versed with VueJs and its ecosystem. We have delivered MVP to enterprise-level software from startup to MNC. Not only client projects we have developed multiple open-source products which are based on VueJs. We are proud to mention that we are one of the few official Laravel & Nuxt partners too.", - "Our team loves to follow the industry standards, some of which are managing git repo, code review, release deployments via CI/CD (DevOps), automated software testing, maintaining detailed technical documentation, application performance monitoring, etc.", - "Email us, and let's build your software product." + "شركة ويب رينفنت هي شركة تطوير برمجيات تركز على العمليات وتقدم مجموعة واسعة من منتجات البرامج المتكاملة وتطبيقات الوقت الفعلي وتطبيقات SaaS متعددة المستأجرين وخدمات تطوير واجهات برمجة التطبيقات ذات التأخير المنخفض وتطوير تطبيقات الجوال. يتمتع فريقنا بخبرة واسعة في إطار فيو ونظامها البيئي. لقد قمنا بتسليم منتجات بالحد الأدنى من الميزات (MVP) إلى برامج على مستوى المؤسسات على الصعيد العالمي ، بدءًا من الشركات الناشئة وحتى الشركات متعددة الجنسيات. لم نقتصر على مشاريع العملاء ، بل قمنا أيضًا بتطوير العديد من المنتجات مفتوحة المصدر التي تعتمد على فيو. نفخر بأن نكون من بين الشركاء القليلين الرسميين لكل من لارافيل ونوكست.", + "فريقنا يحرص على اتباع معايير الصناعة ، بما في ذلك إدارة مستودع جيت، ومراجعة الكود، ونشر عمليات النشر عبر الاندماج المستمر والتسليم المستمر (DevOps)، والاختبار الآلي للبرامج، والحفاظ على وثائق تقنية مفصلة، ومراقبة أداء التطبيق، وما إلى ذلك.", + "تواصل معنا عبر البريد الإلكتروني لنناقش مشروعك التالي." ], - "region": ["North America", "Asia", "Europe"], - "proficiencies": ["Vue", "Laravel", "Nuxt", "Ionic", "Node.js"], + "region": ["أمريكا الشمالية", "آسيا", "أوروبا"], + "proficiencies": ["فيو", "لارافيل", "نوكست", "أيوني", "نود"], "website": { "text": "webreinvent.com", "url": "https://webreinvent.com/?utm_source=vuejs.org&utm_medium=website&utm_campaign=partners" @@ -180,25 +180,25 @@ "name": "Dreamonkey", "logo": "dreamonkey.png", "hero": "dreamonkey-hero.png", - "intro": "We are an Italian software house, including international team collaborators, with 8 years of experience in software design and development. We build software from scratch or re-design it and support other companies’ teams, especially for industrial IoT, delivery, finance, medical, automotive and supply chain, working mostly for American and Canadian clients. We are proud sponsors of the Quasar framework and members of its core team.", + "intro": "نحن شركة برمجيات إيطالية تضم فريق تعاون دولي، تمتلك خبرة 8 سنوات في تصميم وتطوير البرمجيات. نقوم ببناء البرامج من البداية أو إعادة تصميمها ونساعد فرق الشركات الأخرى ، خاصة في مجالات إنترنت الأشياء الصناعية والتوصيل والتمويل والطب والسيارات وسلسلة التوريد ، ونعمل بشكل أساسي مع عملاء أمريكيين وكنديين. نحن فخورون برعاية إطار عمل كواسر وكوننا أعضاء في فريقه الأساسي.", "description": [ - "Our stack includes Vue, Quasar, Laravel and, when requested, Angular too. We strive to produce high quality, clean and well-documented code, making it rock-solid by means of automatic tests. Our frontend follows the main guidelines of Google Material Design.", - "We are able to lead projects from the very start to their deployment, including requirements analysis, UX/UI design, design assets hand-off, development and setup of CI/CD pipelines on AWS. We can merge with the client’s agile methodology and, when requested, we can take care of project management too with a dedicated professional.", - "We have experience with different project complexity, from startup to enterprise-level. We can provide static UIs, working MPVs, fully operative SPA or mobile apps. We also split our team in order to provide the client just with the specific expertise that is needed, be it development, design or just a feasibility analysis.", - "If you need to integrate new skills in your team, we can structure a training program focusing on development or design topics of your interest and help your employees progress with dedicated lessons." + "الكومة التقنية الخاصة بنا تشمل فيو و كواسر و لارافل ، وعند الطلب ، أنجولار أيضًا. نسعى جاهدين لإنتاج كود عالي الجودة ونظيف وموثق جيدًا ، مما يجعله قويًا للغاية من خلال الاختبارات الآلية. تتبع واجهة المستخدم الخاصة بنا الإرشادات الرئيسية لتصميم المواد الرقمية الصادرة عن جوجل.", + "نمتلك القدرة على قيادة المشاريع من البداية وحتى نشرها ، بما في ذلك تحليل المتطلبات ، وتصميم تجربة المستخدم / واجهة المستخدم ، وتسليم أصول التصميم ، والتطوير وإعداد خطوط أنابيب الاندماج المستمر والتسليم المستمر (DevOps) على منصة أمازون AWS. يمكننا الاندماج مع منهجية العميل الرشيقة ، وعند الطلب ، يمكننا أيضًا الاهتمام بإدارة المشروع مع محترف متخصص.", + "نتمتع بخبرة في مشاريع مختلفة التعقيد ، بدءًا من الشركات الناشئة وحتى مستوى المؤسسات. يمكننا تقديم واجهات مستخدم ثابتة، وتطبيقات MVP عاملة، وتطبيقات SPA أو تطبيقات جوالة تعمل بكامل طاقتها. كما نقوم بتقسيم فريقنا لتزويد العميل فقط بالخبرات المحددة المطلوبة، سواء كانت تطويرًا أو تصميمًا أو مجرد تحليل جدوى.", + "إذا كنت بحاجة إلى دمج مهارات جديدة في فريقك، فيمكننا بناء برنامج تدريبي يركز على مواضيع التطوير أو التصميم التي تهمك، ومساعدة موظفيك على التقدم من خلال دروس مخصصة." ], "proficiencies": [ - "Vue", - "Quasar", - "Angular", - "Capacitor", - "Laravel", - "Node.js", - "NestJS", - "UX Design", - "AWS" + "فيو", + "كواسر", + "أنجولار", + "كاباسيتور", + "لارافل", + "نود", + "نست جي إس", + "UX تصميم", + "خدمات أمازون AWS" ], - "region": ["Europe", "North America"], + "region": ["أوروبا", "أمريكا الشمالية"], "website": { "text": "dreamonkey.com", "url": "https://dreamonkey.com/en/vue-partner" @@ -211,16 +211,16 @@ "logo": "herodevs.png", "flipLogo": true, "hero": "herodevs-hero.png", - "intro": "End-of-life of open source software versions creates massive challenges for companies. HeroDevs offers two solutions: (1) We provide never-ending support for sunsetted open source software, and (2) we provide consulting and engineering to help companies migrate to in-support open source software.", + "intro": "نهاية صلاحية إصدارات البرامج مفتوحة المصدر تشكل تحديات كبيرة للشركات. تقدم هيروديفز حلين: (1) نقدم دعمًا لا ينتهي للبرامج مفتوحة المصدر التي تم إيقاف تشغيلها ، و (2) نقدم الاستشارات والهندسة لمساعدة الشركات على الانتقال إلى البرامج مفتوحة المصدر المدعومة.", "description": [ - "When open source software is reaching end-of-life, you’re faced with a difficult decision: do you spend months or years of dev time migrating your code, or do you risk being non-compliant with industry regulations and your company’s SLAs?", - "At HeroDevs we pride ourselves in being the experts that help you navigate end-of-life events in your technology stack. Companies offering enterprise support for open source libraries stop at the end of life. That’s where our value prop begins with our Never-Ending Support (NES) products. Our team has not only provided over 450 organizations with supported, secured versions of open source software beyond their end of life, but has also helped dozens of companies migrate their codebase to a modern, supported open source stack.", - "With all NES Products we offer: continuous source code scanning for vulnerabilities, 5-minute installation without leaving your network, scanning for possible IP infringement in your code, and checks for platform, browser and 3rd-party library compatibility.", - "Need to migrate? HeroDevs can help with that too. Hire our team of experts to help you navigate the challenges that come with migrating your code.", - "Want to learn more? Find us at herodevs.com or send us a note at hello@herodevs.com." + "عندما تصل البرامج مفتوحة المصدر إلى نهاية صلاحيتها ، تواجه قرارًا صعبًا: هل تنفق شهورًا أو سنوات من وقت المطورين في ترحيل الكود الخاص بك ، أم تخاطر بعدم الامتثال للوائح التنظيمية للصناعة واتفاقيات مستوى الخدمة (SLAs) الخاصة بشركتك؟", + "في هيروديفز نفخر بأن نكون الخبراء الذين نساعدك على التنقل في أحداث نهاية عمر الخدمة في كومة التقنية الخاصة بك. تتوقف الشركات التي تقدم الدعم المؤسسي لمكتبات المصدر المفتوح عند نهاية عمر الخدمة. هنا تبدأ قيمة اقتراحنا مع منتجات الدعم المستمر لدينا (NES). لم يقم فريقنا فقط بتزويد أكثر من 450 مؤسسة بإصدارات مدعومة وآمنة من البرامج مفتوحة المصدر بعد نهاية عمر الخدمة، ولكنه ساعد أيضًا عشرات الشركات على نقل قاعدة الكود الخاصة بها إلى كومة برامج مفتوحة مصدر حديثة ومدعومة.", + "تقدم هيروديفز مع جميع منتجات NES ما يلي: الفحص المستمر لكود المصدر الخاص بك بحثًا عن الثغرات الأمنية، والتثبيت خلال 5 دقائق دون مغادرة شبكتك، والبحث عن احتمال انتهاك الملكية الفكرية في الكود الخاص بك، وإجراء عمليات التحقق من توافق النظام الأساسي والمتصفح ومكتبات الطرف الثالث.", + "تحتاج إلى الانتقال إلى نظام تشغيل آخر؟ يمكن أن تساعدك هيروديفز أيضًا في ذلك. استعن بفريق خبرائنا لمساعدتك على تجاوز التحديات التي تأتي مع نقل كودك.", + "تريد معرفة المزيد؟ تواصل معنا على موقعنا الإلكتروني أو أرسل لنا رسالة على hello@herodevs.com." ], - "proficiencies": ["Vue", "Angular", "Migration", "EOL Support"], - "region": ["North America"], + "proficiencies": ["فيو", "أنجولار", "مايجريشن", "EOL دعم"], + "region": ["أمريكا الشمالية"], "website": { "text": "herodevs.com", "url": "https://www.herodevs.com/support/vue"