diff --git a/vitepress/.gitignore b/vitepress/.gitignore new file mode 100644 index 0000000..b512c09 --- /dev/null +++ b/vitepress/.gitignore @@ -0,0 +1 @@ +node_modules \ No newline at end of file diff --git a/vitepress/docs/.vitepress/cache/deps/_metadata.json b/vitepress/docs/.vitepress/cache/deps/_metadata.json new file mode 100644 index 0000000..9c2531e --- /dev/null +++ b/vitepress/docs/.vitepress/cache/deps/_metadata.json @@ -0,0 +1,52 @@ +{ + "hash": "188b5bde", + "configHash": "58a9edf7", + "lockfileHash": "ddbd7476", + "browserHash": "ca644250", + "optimized": { + "vue": { + "src": "../../../../node_modules/vue/dist/vue.runtime.esm-bundler.js", + "file": "vue.js", + "fileHash": "e3b15aae", + "needsInterop": false + }, + "vitepress > @vue/devtools-api": { + "src": "../../../../node_modules/@vue/devtools-api/dist/index.js", + "file": "vitepress___@vue_devtools-api.js", + "fileHash": "7ebe442e", + "needsInterop": false + }, + "vitepress > @vueuse/core": { + "src": "../../../../node_modules/@vueuse/core/index.mjs", + "file": "vitepress___@vueuse_core.js", + "fileHash": "896ec476", + "needsInterop": false + }, + "vitepress > @vueuse/integrations/useFocusTrap": { + "src": "../../../../node_modules/@vueuse/integrations/useFocusTrap.mjs", + "file": "vitepress___@vueuse_integrations_useFocusTrap.js", + "fileHash": "909cad6c", + "needsInterop": false + }, + "vitepress > mark.js/src/vanilla.js": { + "src": "../../../../node_modules/mark.js/src/vanilla.js", + "file": "vitepress___mark__js_src_vanilla__js.js", + "fileHash": "e1c654be", + "needsInterop": false + }, + "vitepress > minisearch": { + "src": "../../../../node_modules/minisearch/dist/es/index.js", + "file": "vitepress___minisearch.js", + "fileHash": "9a23cf6b", + "needsInterop": false + } + }, + "chunks": { + "chunk-WPDAVDJT": { + "file": "chunk-WPDAVDJT.js" + }, + "chunk-CKQ4TNQ3": { + "file": "chunk-CKQ4TNQ3.js" + } + } +} \ No newline at end of file diff --git a/vitepress/docs/.vitepress/cache/deps/chunk-CKQ4TNQ3.js b/vitepress/docs/.vitepress/cache/deps/chunk-CKQ4TNQ3.js new file mode 100644 index 0000000..e34271c --- /dev/null +++ b/vitepress/docs/.vitepress/cache/deps/chunk-CKQ4TNQ3.js @@ -0,0 +1,11402 @@ +// node_modules/@vue/shared/dist/shared.esm-bundler.js +function makeMap(str, expectsLowerCase) { + const set2 = new Set(str.split(",")); + return expectsLowerCase ? (val) => set2.has(val.toLowerCase()) : (val) => set2.has(val); +} +var EMPTY_OBJ = true ? Object.freeze({}) : {}; +var EMPTY_ARR = true ? Object.freeze([]) : []; +var NOOP = () => { +}; +var NO = () => false; +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) => { + const i = arr.indexOf(el); + if (i > -1) { + arr.splice(i, 1); + } +}; +var hasOwnProperty = Object.prototype.hasOwnProperty; +var hasOwn = (val, key) => hasOwnProperty.call(val, key); +var isArray = Array.isArray; +var isMap = (val) => toTypeString(val) === "[object Map]"; +var isSet = (val) => toTypeString(val) === "[object Set]"; +var isDate = (val) => toTypeString(val) === "[object Date]"; +var isRegExp = (val) => toTypeString(val) === "[object RegExp]"; +var isFunction = (val) => typeof val === "function"; +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)) && isFunction(val.then) && isFunction(val.catch); +}; +var objectToString = Object.prototype.toString; +var toTypeString = (value) => objectToString.call(value); +var toRawType = (value) => { + return toTypeString(value).slice(8, -1); +}; +var isPlainObject = (val) => toTypeString(val) === "[object Object]"; +var isIntegerKey = (key) => isString(key) && key !== "NaN" && key[0] !== "-" && "" + parseInt(key, 10) === key; +var isReservedProp = makeMap( + // the leading comma is intentional so empty string "" is also included + ",key,ref,ref_for,ref_key,onVnodeBeforeMount,onVnodeMounted,onVnodeBeforeUpdate,onVnodeUpdated,onVnodeBeforeUnmount,onVnodeUnmounted" +); +var isBuiltInDirective = makeMap( + "bind,cloak,else-if,else,for,html,if,model,on,once,pre,show,slot,text,memo" +); +var cacheStringFunction = (fn) => { + const cache = /* @__PURE__ */ Object.create(null); + return (str) => { + const hit = cache[str]; + return hit || (cache[str] = fn(str)); + }; +}; +var camelizeRE = /-(\w)/g; +var camelize = cacheStringFunction((str) => { + return str.replace(camelizeRE, (_, c) => c ? c.toUpperCase() : ""); +}); +var hyphenateRE = /\B([A-Z])/g; +var hyphenate = cacheStringFunction( + (str) => str.replace(hyphenateRE, "-$1").toLowerCase() +); +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) => { + Object.defineProperty(obj, key, { + configurable: true, + enumerable: false, + value + }); +}; +var looseToNumber = (val) => { + const n = parseFloat(val); + return isNaN(n) ? val : n; +}; +var toNumber = (val) => { + const n = isString(val) ? Number(val) : NaN; + return isNaN(n) ? val : n; +}; +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_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 = {}; + for (let i = 0; i < value.length; i++) { + const item = value[i]; + const normalized = isString(item) ? parseStringStyle(item) : normalizeStyle(item); + if (normalized) { + for (const key in normalized) { + res[key] = normalized[key]; + } + } + } + return res; + } else if (isString(value) || isObject(value)) { + return value; + } +} +var listDelimiterRE = /;(?![^(]*\))/g; +var propertyDelimiterRE = /:([^]+)/; +var styleCommentRE = /\/\*[^]*?\*\//g; +function parseStringStyle(cssText) { + const ret = {}; + cssText.replace(styleCommentRE, "").split(listDelimiterRE).forEach((item) => { + if (item) { + const tmp = item.split(propertyDelimiterRE); + tmp.length > 1 && (ret[tmp[0].trim()] = tmp[1].trim()); + } + }); + 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)) { + res = value; + } else if (isArray(value)) { + for (let i = 0; i < value.length; i++) { + const normalized = normalizeClass(value[i]); + if (normalized) { + res += normalized + " "; + } + } + } else if (isObject(value)) { + for (const name in value) { + if (value[name]) { + res += name + " "; + } + } + } + return res.trim(); +} +function normalizeProps(props) { + if (!props) + return null; + let { class: klass, style } = props; + if (klass && !isString(klass)) { + props.class = normalizeClass(klass); + } + if (style) { + props.style = normalizeStyle(style); + } + return 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 VOID_TAGS = "area,base,br,col,embed,hr,img,input,link,meta,param,source,track,wbr"; +var isHTMLTag = makeMap(HTML_TAGS); +var isSVGTag = makeMap(SVG_TAGS); +var isMathMLTag = makeMap(MATH_TAGS); +var isVoidTag = makeMap(VOID_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; + let equal = true; + for (let i = 0; equal && i < a.length; i++) { + equal = looseEqual(a[i], b[i]); + } + return equal; +} +function looseEqual(a, b) { + if (a === b) + return true; + let aValidType = isDate(a); + let bValidType = isDate(b); + if (aValidType || bValidType) { + return aValidType && bValidType ? a.getTime() === b.getTime() : false; + } + aValidType = isSymbol(a); + bValidType = isSymbol(b); + if (aValidType || bValidType) { + return a === b; + } + aValidType = isArray(a); + bValidType = isArray(b); + if (aValidType || bValidType) { + return aValidType && bValidType ? looseCompareArrays(a, b) : false; + } + aValidType = isObject(a); + bValidType = isObject(b); + if (aValidType || bValidType) { + if (!aValidType || !bValidType) { + return false; + } + const aKeysCount = Object.keys(a).length; + const bKeysCount = Object.keys(b).length; + if (aKeysCount !== bKeysCount) { + return false; + } + for (const key in a) { + const aHasKey = a.hasOwnProperty(key); + const bHasKey = b.hasOwnProperty(key); + if (aHasKey && !bHasKey || !aHasKey && bHasKey || !looseEqual(a[key], b[key])) { + return false; + } + } + } + return String(a) === String(b); +} +function looseIndexOf(arr, val) { + return arr.findIndex((item) => looseEqual(item, val)); +} +var toDisplayString = (val) => { + return isString(val) ? val : val == null ? "" : isArray(val) || isObject(val) && (val.toString === objectToString || !isFunction(val.toString)) ? JSON.stringify(val, replacer, 2) : String(val); +}; +var replacer = (_key, val) => { + if (val && val.__v_isRef) { + return replacer(_key, val.value); + } else if (isMap(val)) { + return { + [`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()].map((v) => stringifySymbol(v)) + }; + } else if (isSymbol(val)) { + return stringifySymbol(val); + } else if (isObject(val) && !isArray(val) && !isPlainObject(val)) { + return String(val); + } + return val; +}; +var stringifySymbol = (v, i = "") => { + var _a; + return isSymbol(v) ? `Symbol(${(_a = v.description) != null ? _a : i})` : v; +}; + +// node_modules/@vue/reactivity/dist/reactivity.esm-bundler.js +function warn(msg, ...args) { + console.warn(`[Vue warn] ${msg}`, ...args); +} +var activeEffectScope; +var EffectScope = class { + constructor(detached = false) { + this.detached = detached; + this._active = true; + this.effects = []; + this.cleanups = []; + this.parent = activeEffectScope; + if (!detached && activeEffectScope) { + this.index = (activeEffectScope.scopes || (activeEffectScope.scopes = [])).push( + this + ) - 1; + } + } + get active() { + return this._active; + } + run(fn) { + if (this._active) { + const currentEffectScope = activeEffectScope; + try { + activeEffectScope = this; + return fn(); + } finally { + activeEffectScope = currentEffectScope; + } + } else if (true) { + warn(`cannot run an inactive effect scope.`); + } + } + /** + * This should only be called on non-detached scopes + * @internal + */ + on() { + activeEffectScope = this; + } + /** + * This should only be called on non-detached scopes + * @internal + */ + off() { + activeEffectScope = this.parent; + } + stop(fromParent) { + if (this._active) { + let i, l; + for (i = 0, l = this.effects.length; i < l; i++) { + this.effects[i].stop(); + } + for (i = 0, l = this.cleanups.length; i < l; i++) { + this.cleanups[i](); + } + if (this.scopes) { + for (i = 0, l = this.scopes.length; i < l; i++) { + this.scopes[i].stop(true); + } + } + if (!this.detached && this.parent && !fromParent) { + const last = this.parent.scopes.pop(); + if (last && last !== this) { + this.parent.scopes[this.index] = last; + last.index = this.index; + } + } + this.parent = void 0; + this._active = false; + } + } +}; +function effectScope(detached) { + return new EffectScope(detached); +} +function recordEffectScope(effect2, scope = activeEffectScope) { + if (scope && scope.active) { + scope.effects.push(effect2); + } +} +function getCurrentScope() { + return activeEffectScope; +} +function onScopeDispose(fn) { + if (activeEffectScope) { + activeEffectScope.cleanups.push(fn); + } else if (true) { + warn( + `onScopeDispose() is called when there is no active effect scope to be associated with.` + ); + } +} +var activeEffect; +var ReactiveEffect = class { + constructor(fn, trigger2, scheduler, scope) { + this.fn = fn; + this.trigger = trigger2; + this.scheduler = scheduler; + this.active = true; + this.deps = []; + 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 lastShouldTrack = shouldTrack; + let lastEffect = activeEffect; + try { + shouldTrack = true; + activeEffect = this; + this._runnings++; + preCleanupEffect(this); + return this.fn(); + } finally { + postCleanupEffect(this); + this._runnings--; + activeEffect = lastEffect; + shouldTrack = lastShouldTrack; + } + } + stop() { + var _a; + if (this.active) { + preCleanupEffect(this); + postCleanupEffect(this); + (_a = this.onStop) == null ? void 0 : _a.call(this); + this.active = false; + } + } +}; +function triggerComputed(computed3) { + return computed3.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(); + } + } +} +function effect(fn, options) { + if (fn.effect instanceof ReactiveEffect) { + fn = fn.effect.fn; + } + const _effect = new ReactiveEffect(fn, NOOP, () => { + if (_effect.dirty) { + _effect.run(); + } + }); + if (options) { + extend(_effect, options); + if (options.scope) + recordEffectScope(_effect, options.scope); + } + if (!options || !options.lazy) { + _effect.run(); + } + const runner = _effect.run.bind(_effect); + runner.effect = _effect; + return runner; +} +function stop(runner) { + runner.effect.stop(); +} +var shouldTrack = true; +var pauseScheduleStack = 0; +var trackStack = []; +function pauseTracking() { + trackStack.push(shouldTrack); + shouldTrack = false; +} +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++; + } + if (true) { + (_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)) { + if (true) { + (_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, computed3) => { + const dep = /* @__PURE__ */ new Map(); + dep.cleanup = cleanup; + dep.computed = computed3; + return dep; +}; +var targetMap = /* @__PURE__ */ new WeakMap(); +var ITERATE_KEY = Symbol(true ? "iterate" : ""); +var MAP_KEY_ITERATE_KEY = Symbol(true ? "Map key iterate" : ""); +function track(target, type, key) { + if (shouldTrack && activeEffect) { + let depsMap = targetMap.get(target); + if (!depsMap) { + targetMap.set(target, depsMap = /* @__PURE__ */ new Map()); + } + let dep = depsMap.get(key); + if (!dep) { + depsMap.set(key, dep = createDep(() => depsMap.delete(key))); + } + trackEffect( + activeEffect, + dep, + true ? { + target, + type, + key + } : void 0 + ); + } +} +function trigger(target, type, key, newValue, oldValue, oldTarget) { + const depsMap = targetMap.get(target); + if (!depsMap) { + return; + } + let deps = []; + if (type === "clear") { + deps = [...depsMap.values()]; + } else if (key === "length" && isArray(target)) { + const newLength = Number(newValue); + depsMap.forEach((dep, key2) => { + if (key2 === "length" || !isSymbol(key2) && key2 >= newLength) { + deps.push(dep); + } + }); + } else { + if (key !== void 0) { + deps.push(depsMap.get(key)); + } + switch (type) { + case "add": + if (!isArray(target)) { + deps.push(depsMap.get(ITERATE_KEY)); + if (isMap(target)) { + deps.push(depsMap.get(MAP_KEY_ITERATE_KEY)); + } + } else if (isIntegerKey(key)) { + deps.push(depsMap.get("length")); + } + break; + case "delete": + if (!isArray(target)) { + deps.push(depsMap.get(ITERATE_KEY)); + if (isMap(target)) { + deps.push(depsMap.get(MAP_KEY_ITERATE_KEY)); + } + } + break; + case "set": + if (isMap(target)) { + deps.push(depsMap.get(ITERATE_KEY)); + } + break; + } + } + pauseScheduling(); + for (const dep of deps) { + if (dep) { + triggerEffects( + dep, + 4, + true ? { + target, + type, + key, + newValue, + oldValue, + oldTarget + } : void 0 + ); + } + } + resetScheduling(); +} +function getDepFromReactive(object, key) { + var _a; + return (_a = targetMap.get(object)) == null ? void 0 : _a.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 arrayInstrumentations = createArrayInstrumentations(); +function createArrayInstrumentations() { + const instrumentations = {}; + ["includes", "indexOf", "lastIndexOf"].forEach((key) => { + instrumentations[key] = function(...args) { + const arr = toRaw(this); + for (let i = 0, l = this.length; i < l; i++) { + track(arr, "get", i + ""); + } + const res = arr[key](...args); + if (res === -1 || res === false) { + return arr[key](...args.map(toRaw)); + } else { + return res; + } + }; + }); + ["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; + }; + }); + return instrumentations; +} +function hasOwnProperty2(key) { + const obj = toRaw(this); + track(obj, "has", key); + return obj.hasOwnProperty(key); +} +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 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) { + if (targetIsArray && hasOwn(arrayInstrumentations, key)) { + return Reflect.get(arrayInstrumentations, key, receiver); + } + if (key === "hasOwnProperty") { + return hasOwnProperty2; + } + } + const res = Reflect.get(target, key, receiver); + if (isSymbol(key) ? builtInSymbols.has(key) : isNonTrackableKeys(key)) { + return res; + } + if (!isReadonly2) { + track(target, "get", key); + } + if (isShallow2) { + return res; + } + if (isRef(res)) { + return targetIsArray && isIntegerKey(key) ? res : res.value; + } + if (isObject(res)) { + return isReadonly2 ? readonly(res) : reactive(res); + } + return res; + } +}; +var MutableReactiveHandler = class extends BaseReactiveHandler { + constructor(isShallow2 = false) { + super(false, isShallow2); + } + set(target, key, value, receiver) { + let oldValue = target[key]; + 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)) { + if (isOldValueReadonly) { + return false; + } else { + oldValue.value = value; + return true; + } + } + } + const hadKey = isArray(target) && isIntegerKey(key) ? Number(key) < target.length : hasOwn(target, key); + const result = Reflect.set(target, key, value, receiver); + if (target === toRaw(receiver)) { + if (!hadKey) { + trigger(target, "add", key, value); + } else if (hasChanged(value, oldValue)) { + trigger(target, "set", key, value, oldValue); + } + } + return result; + } + 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); + } +}; +var ReadonlyReactiveHandler = class extends BaseReactiveHandler { + constructor(isShallow2 = false) { + super(true, isShallow2); + } + set(target, key) { + if (true) { + warn( + `Set operation on key "${String(key)}" failed: target is readonly.`, + target + ); + } + return true; + } + deleteProperty(target, key) { + if (true) { + warn( + `Delete operation on key "${String(key)}" failed: target is readonly.`, + target + ); + } + return true; + } +}; +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) { + target = target["__v_raw"]; + const rawTarget = toRaw(target); + const rawKey = toRaw(key); + if (!isReadonly2) { + if (hasChanged(key, rawKey)) { + track(rawTarget, "get", key); + } + track(rawTarget, "get", rawKey); + } + const { has: has2 } = getProto(rawTarget); + const wrap = isShallow2 ? toShallow : isReadonly2 ? toReadonly : toReactive; + if (has2.call(rawTarget, key)) { + return wrap(target.get(key)); + } else if (has2.call(rawTarget, rawKey)) { + return wrap(target.get(rawKey)); + } else if (target !== rawTarget) { + target.get(key); + } +} +function has(key, isReadonly2 = false) { + const target = this["__v_raw"]; + const rawTarget = toRaw(target); + const rawKey = toRaw(key); + if (!isReadonly2) { + if (hasChanged(key, rawKey)) { + track(rawTarget, "has", key); + } + track(rawTarget, "has", rawKey); + } + return key === rawKey ? target.has(key) : target.has(key) || target.has(rawKey); +} +function size(target, isReadonly2 = false) { + target = target["__v_raw"]; + !isReadonly2 && track(toRaw(target), "iterate", ITERATE_KEY); + return Reflect.get(target, "size", target); +} +function add(value) { + value = toRaw(value); + const target = toRaw(this); + const proto = getProto(target); + const hadKey = proto.has.call(target, value); + if (!hadKey) { + target.add(value); + trigger(target, "add", value, value); + } + return this; +} +function set(key, value) { + value = toRaw(value); + const target = toRaw(this); + const { has: has2, get: get2 } = getProto(target); + let hadKey = has2.call(target, key); + if (!hadKey) { + key = toRaw(key); + hadKey = has2.call(target, key); + } else if (true) { + checkIdentityKeys(target, has2, key); + } + const oldValue = get2.call(target, key); + target.set(key, value); + if (!hadKey) { + trigger(target, "add", key, value); + } else if (hasChanged(value, oldValue)) { + trigger(target, "set", key, value, oldValue); + } + return this; +} +function deleteEntry(key) { + const target = toRaw(this); + const { has: has2, get: get2 } = getProto(target); + let hadKey = has2.call(target, key); + if (!hadKey) { + key = toRaw(key); + hadKey = has2.call(target, key); + } else if (true) { + checkIdentityKeys(target, has2, key); + } + const oldValue = get2 ? get2.call(target, key) : void 0; + const result = target.delete(key); + if (hadKey) { + trigger(target, "delete", key, void 0, oldValue); + } + return result; +} +function clear() { + const target = toRaw(this); + const hadItems = target.size !== 0; + const oldTarget = true ? isMap(target) ? new Map(target) : new Set(target) : void 0; + const result = target.clear(); + if (hadItems) { + trigger(target, "clear", void 0, void 0, oldTarget); + } + return result; +} +function createForEach(isReadonly2, isShallow2) { + return function forEach(callback, thisArg) { + const observed = this; + const target = observed["__v_raw"]; + const rawTarget = toRaw(target); + const wrap = isShallow2 ? toShallow : isReadonly2 ? toReadonly : toReactive; + !isReadonly2 && track(rawTarget, "iterate", ITERATE_KEY); + return target.forEach((value, key) => { + return callback.call(thisArg, wrap(value), wrap(key), observed); + }); + }; +} +function createIterableMethod(method, isReadonly2, isShallow2) { + return function(...args) { + const target = this["__v_raw"]; + const rawTarget = toRaw(target); + const targetIsMap = isMap(rawTarget); + const isPair = method === "entries" || method === Symbol.iterator && targetIsMap; + const isKeyOnly = method === "keys" && targetIsMap; + const innerIterator = target[method](...args); + const wrap = isShallow2 ? toShallow : isReadonly2 ? toReadonly : toReactive; + !isReadonly2 && track( + rawTarget, + "iterate", + isKeyOnly ? MAP_KEY_ITERATE_KEY : ITERATE_KEY + ); + return { + // iterator protocol + next() { + const { value, done } = innerIterator.next(); + return done ? { value, done } : { + value: isPair ? [wrap(value[0]), wrap(value[1])] : wrap(value), + done + }; + }, + // iterable protocol + [Symbol.iterator]() { + return this; + } + }; + }; +} +function createReadonlyMethod(type) { + return function(...args) { + if (true) { + const key = args[0] ? `on key "${args[0]}" ` : ``; + warn( + `${capitalize(type)} operation ${key}failed: target is readonly.`, + toRaw(this) + ); + } + return type === "delete" ? false : type === "clear" ? void 0 : this; + }; +} +function createInstrumentations() { + const mutableInstrumentations2 = { + get(key) { + return get(this, key); + }, + get size() { + return size(this); + }, + has, + add, + set, + delete: deleteEntry, + clear, + forEach: createForEach(false, false) + }; + const shallowInstrumentations2 = { + get(key) { + return get(this, key, false, true); + }, + get size() { + return size(this); + }, + has, + add, + set, + delete: deleteEntry, + clear, + forEach: createForEach(false, true) + }; + const readonlyInstrumentations2 = { + get(key) { + return get(this, key, true); + }, + get size() { + return size(this, true); + }, + has(key) { + return has.call(this, key, true); + }, + add: createReadonlyMethod("add"), + set: createReadonlyMethod("set"), + delete: createReadonlyMethod("delete"), + clear: createReadonlyMethod("clear"), + forEach: createForEach(true, false) + }; + const shallowReadonlyInstrumentations2 = { + get(key) { + return get(this, key, true, true); + }, + get size() { + return size(this, true); + }, + has(key) { + return has.call(this, key, true); + }, + add: createReadonlyMethod("add"), + set: createReadonlyMethod("set"), + delete: createReadonlyMethod("delete"), + clear: createReadonlyMethod("clear"), + forEach: createForEach(true, true) + }; + 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 + ); + shallowReadonlyInstrumentations2[method] = createIterableMethod( + method, + true, + true + ); + }); + return [ + mutableInstrumentations2, + readonlyInstrumentations2, + shallowInstrumentations2, + shallowReadonlyInstrumentations2 + ]; +} +var [ + mutableInstrumentations, + readonlyInstrumentations, + shallowInstrumentations, + shallowReadonlyInstrumentations +] = createInstrumentations(); +function createInstrumentationGetter(isReadonly2, shallow) { + const instrumentations = shallow ? isReadonly2 ? shallowReadonlyInstrumentations : shallowInstrumentations : isReadonly2 ? readonlyInstrumentations : mutableInstrumentations; + return (target, key, receiver) => { + if (key === "__v_isReactive") { + return !isReadonly2; + } else if (key === "__v_isReadonly") { + return isReadonly2; + } else if (key === "__v_raw") { + return target; + } + return Reflect.get( + hasOwn(instrumentations, key) && key in target ? instrumentations : target, + key, + receiver + ); + }; +} +var mutableCollectionHandlers = { + get: createInstrumentationGetter(false, false) +}; +var shallowCollectionHandlers = { + get: createInstrumentationGetter(false, true) +}; +var readonlyCollectionHandlers = { + get: createInstrumentationGetter(true, false) +}; +var shallowReadonlyCollectionHandlers = { + get: createInstrumentationGetter(true, true) +}; +function checkIdentityKeys(target, has2, key) { + const rawKey = toRaw(key); + if (rawKey !== key && has2.call(target, rawKey)) { + const type = toRawType(target); + warn( + `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.` + ); + } +} +var reactiveMap = /* @__PURE__ */ new WeakMap(); +var shallowReactiveMap = /* @__PURE__ */ new WeakMap(); +var readonlyMap = /* @__PURE__ */ new WeakMap(); +var shallowReadonlyMap = /* @__PURE__ */ new WeakMap(); +function targetTypeMap(rawType) { + switch (rawType) { + case "Object": + case "Array": + return 1; + case "Map": + case "Set": + case "WeakMap": + case "WeakSet": + return 2; + default: + return 0; + } +} +function getTargetType(value) { + return value["__v_skip"] || !Object.isExtensible(value) ? 0 : targetTypeMap(toRawType(value)); +} +function reactive(target) { + if (isReadonly(target)) { + return target; + } + return createReactiveObject( + target, + false, + mutableHandlers, + mutableCollectionHandlers, + reactiveMap + ); +} +function shallowReactive(target) { + return createReactiveObject( + target, + false, + shallowReactiveHandlers, + shallowCollectionHandlers, + shallowReactiveMap + ); +} +function readonly(target) { + return createReactiveObject( + target, + true, + readonlyHandlers, + readonlyCollectionHandlers, + readonlyMap + ); +} +function shallowReadonly(target) { + return createReactiveObject( + target, + true, + shallowReadonlyHandlers, + shallowReadonlyCollectionHandlers, + shallowReadonlyMap + ); +} +function createReactiveObject(target, isReadonly2, baseHandlers, collectionHandlers, proxyMap) { + if (!isObject(target)) { + if (true) { + warn(`value cannot be made reactive: ${String(target)}`); + } + return target; + } + if (target["__v_raw"] && !(isReadonly2 && target["__v_isReactive"])) { + return target; + } + const existingProxy = proxyMap.get(target); + if (existingProxy) { + return existingProxy; + } + const targetType = getTargetType(target); + if (targetType === 0) { + return target; + } + const proxy = new Proxy( + target, + targetType === 2 ? collectionHandlers : baseHandlers + ); + proxyMap.set(target, proxy); + return proxy; +} +function isReactive(value) { + if (isReadonly(value)) { + return isReactive(value["__v_raw"]); + } + return !!(value && value["__v_isReactive"]); +} +function isReadonly(value) { + return !!(value && value["__v_isReadonly"]); +} +function isShallow(value) { + return !!(value && value["__v_isShallow"]); +} +function isProxy(value) { + return isReactive(value) || isReadonly(value); +} +function toRaw(observed) { + const raw = observed && observed["__v_raw"]; + return raw ? toRaw(raw) : observed; +} +function markRaw(value) { + 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(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(getterOrOptions, debugOptions, isSSR = false) { + let getter; + let setter; + const onlyGetter = isFunction(getterOrOptions); + if (onlyGetter) { + getter = getterOrOptions; + setter = true ? () => { + warn("Write operation failed: computed value is readonly"); + } : NOOP; + } 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); + trackEffect( + activeEffect, + (_a = ref2.dep) != null ? _a : ref2.dep = createDep( + () => ref2.dep = void 0, + ref2 instanceof ComputedRefImpl ? ref2 : void 0 + ), + true ? { + target: ref2, + type: "get", + key: "value" + } : void 0 + ); + } +} +function triggerRefValue(ref2, dirtyLevel = 4, newVal) { + ref2 = toRaw(ref2); + const dep = ref2.dep; + if (dep) { + triggerEffects( + dep, + dirtyLevel, + true ? { + target: ref2, + type: "set", + key: "value", + newValue: newVal + } : void 0 + ); + } +} +function isRef(r) { + return !!(r && r.__v_isRef === true); +} +function ref(value) { + return createRef(value, false); +} +function shallowRef(value) { + return createRef(value, true); +} +function createRef(rawValue, shallow) { + if (isRef(rawValue)) { + return rawValue; + } + return new RefImpl(rawValue, shallow); +} +var RefImpl = class { + constructor(value, __v_isShallow) { + this.__v_isShallow = __v_isShallow; + this.dep = void 0; + this.__v_isRef = true; + this._rawValue = __v_isShallow ? value : toRaw(value); + this._value = __v_isShallow ? value : toReactive(value); + } + get value() { + trackRefValue(this); + return this._value; + } + set value(newVal) { + const useDirectValue = this.__v_isShallow || isShallow(newVal) || isReadonly(newVal); + newVal = useDirectValue ? newVal : toRaw(newVal); + if (hasChanged(newVal, this._rawValue)) { + this._rawValue = newVal; + this._value = useDirectValue ? newVal : toReactive(newVal); + triggerRefValue(this, 4, newVal); + } + } +}; +function triggerRef(ref2) { + triggerRefValue(ref2, 4, true ? ref2.value : void 0); +} +function unref(ref2) { + return isRef(ref2) ? ref2.value : ref2; +} +function toValue(source) { + return isFunction(source) ? source() : unref(source); +} +var shallowUnwrapHandlers = { + get: (target, key, receiver) => unref(Reflect.get(target, key, receiver)), + set: (target, key, value, receiver) => { + const oldValue = target[key]; + if (isRef(oldValue) && !isRef(value)) { + oldValue.value = value; + return true; + } else { + return Reflect.set(target, key, value, receiver); + } + } +}; +function proxyRefs(objectWithRefs) { + return isReactive(objectWithRefs) ? objectWithRefs : new Proxy(objectWithRefs, shallowUnwrapHandlers); +} +var CustomRefImpl = class { + constructor(factory) { + this.dep = void 0; + this.__v_isRef = true; + const { get: get2, set: set2 } = factory( + () => trackRefValue(this), + () => triggerRefValue(this) + ); + this._get = get2; + this._set = set2; + } + get value() { + return this._get(); + } + set value(newVal) { + this._set(newVal); + } +}; +function customRef(factory) { + return new CustomRefImpl(factory); +} +function toRefs(object) { + if (!isProxy(object)) { + warn(`toRefs() expects a reactive object but received a plain one.`); + } + const ret = isArray(object) ? new Array(object.length) : {}; + for (const key in object) { + ret[key] = propertyToRef(object, key); + } + return ret; +} +var ObjectRefImpl = class { + constructor(_object, _key, _defaultValue) { + this._object = _object; + this._key = _key; + this._defaultValue = _defaultValue; + this.__v_isRef = true; + } + get value() { + const val = this._object[this._key]; + return val === void 0 ? this._defaultValue : val; + } + set value(newVal) { + this._object[this._key] = newVal; + } + get dep() { + return getDepFromReactive(toRaw(this._object), this._key); + } +}; +var GetterRefImpl = class { + constructor(_getter) { + this._getter = _getter; + this.__v_isRef = true; + this.__v_isReadonly = true; + } + get value() { + return this._getter(); + } +}; +function toRef(source, key, defaultValue) { + if (isRef(source)) { + return source; + } else if (isFunction(source)) { + return new GetterRefImpl(source); + } else if (isObject(source) && arguments.length > 1) { + return propertyToRef(source, key, defaultValue); + } else { + return ref(source); + } +} +function propertyToRef(source, key, defaultValue) { + const val = source[key]; + return isRef(val) ? val : new ObjectRefImpl(source, key, defaultValue); +} +var TrackOpTypes = { + "GET": "get", + "HAS": "has", + "ITERATE": "iterate" +}; +var TriggerOpTypes = { + "SET": "set", + "ADD": "add", + "DELETE": "delete", + "CLEAR": "clear" +}; + +// node_modules/@vue/runtime-core/dist/runtime-core.esm-bundler.js +var stack = []; +function pushWarningContext(vnode) { + stack.push(vnode); +} +function popWarningContext() { + stack.pop(); +} +function warn$1(msg, ...args) { + pauseTracking(); + const instance = stack.length ? stack[stack.length - 1].component : null; + const appWarnHandler = instance && instance.appContext.config.warnHandler; + const trace = getComponentTrace(); + if (appWarnHandler) { + callWithErrorHandling( + appWarnHandler, + instance, + 11, + [ + 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)}>` + ).join("\n"), + trace + ] + ); + } else { + const warnArgs = [`[Vue warn]: ${msg}`, ...args]; + if (trace.length && // avoid spamming console during tests + true) { + warnArgs.push(` +`, ...formatTrace(trace)); + } + console.warn(...warnArgs); + } + resetTracking(); +} +function getComponentTrace() { + let currentVNode = stack[stack.length - 1]; + if (!currentVNode) { + return []; + } + const normalizedStack = []; + while (currentVNode) { + const last = normalizedStack[0]; + if (last && last.vnode === currentVNode) { + last.recurseCount++; + } else { + normalizedStack.push({ + vnode: currentVNode, + recurseCount: 0 + }); + } + const parentInstance = currentVNode.component && currentVNode.component.parent; + currentVNode = parentInstance && parentInstance.vnode; + } + return normalizedStack; +} +function formatTrace(trace) { + const logs = []; + trace.forEach((entry, i) => { + logs.push(...i === 0 ? [] : [` +`], ...formatTraceEntry(entry)); + }); + return logs; +} +function formatTraceEntry({ vnode, recurseCount }) { + const postfix = recurseCount > 0 ? `... (${recurseCount} recursive calls)` : ``; + const isRoot = vnode.component ? vnode.component.parent == null : false; + const open = ` at <${formatComponentName( + vnode.component, + vnode.type, + isRoot + )}`; + const close = `>` + postfix; + return vnode.props ? [open, ...formatProps(vnode.props), close] : [open + close]; +} +function formatProps(props) { + const res = []; + const keys = Object.keys(props); + keys.slice(0, 3).forEach((key) => { + res.push(...formatProp(key, props[key])); + }); + if (keys.length > 3) { + res.push(` ...`); + } + return res; +} +function formatProp(key, value, raw) { + if (isString(value)) { + value = JSON.stringify(value); + return raw ? value : [`${key}=${value}`]; + } else if (typeof value === "number" || typeof value === "boolean" || value == null) { + return raw ? value : [`${key}=${value}`]; + } else if (isRef(value)) { + value = formatProp(key, toRaw(value.value), true); + return raw ? value : [`${key}=Ref<`, value, `>`]; + } else if (isFunction(value)) { + return [`${key}=fn${value.name ? `<${value.name}>` : ``}`]; + } else { + value = toRaw(value); + return raw ? value : [`${key}=`, value]; + } +} +function assertNumber(val, type) { + if (false) + return; + if (val === void 0) { + return; + } else if (typeof val !== "number") { + warn$1(`${type} is not a valid number - got ${JSON.stringify(val)}.`); + } else if (isNaN(val)) { + 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", + ["bm"]: "beforeMount hook", + ["m"]: "mounted hook", + ["bu"]: "beforeUpdate hook", + ["u"]: "updated", + ["bum"]: "beforeUnmount hook", + ["um"]: "unmounted hook", + ["a"]: "activated hook", + ["da"]: "deactivated hook", + ["ec"]: "errorCaptured hook", + ["rtc"]: "renderTracked hook", + ["rtg"]: "renderTriggered hook", + [0]: "setup function", + [1]: "render function", + [2]: "watcher getter", + [3]: "watcher callback", + [4]: "watcher cleanup function", + [5]: "native event handler", + [6]: "component event handler", + [7]: "vnode hook", + [8]: "directive hook", + [9]: "transition hook", + [10]: "app errorHandler", + [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://github.com/vuejs/core ." +}; +function callWithErrorHandling(fn, instance, type, args) { + try { + return args ? fn(...args) : fn(); + } catch (err) { + handleError(err, instance, type); + } +} +function callWithAsyncErrorHandling(fn, instance, type, args) { + if (isFunction(fn)) { + const res = callWithErrorHandling(fn, instance, type, args); + if (res && isPromise(res)) { + res.catch((err) => { + handleError(err, instance, type); + }); + } + return res; + } + const values = []; + for (let i = 0; i < fn.length; i++) { + values.push(callWithAsyncErrorHandling(fn[i], instance, type, args)); + } + 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 = true ? ErrorTypeStrings$1[type] : `https://vuejs.org/error-reference/#runtime-${type}`; + while (cur) { + const errorCapturedHooks = cur.ec; + if (errorCapturedHooks) { + for (let i = 0; i < errorCapturedHooks.length; i++) { + if (errorCapturedHooks[i](err, exposedInstance, errorInfo) === false) { + return; + } + } + } + cur = cur.parent; + } + const appErrorHandler = instance.appContext.config.errorHandler; + if (appErrorHandler) { + callWithErrorHandling( + appErrorHandler, + null, + 10, + [err, exposedInstance, errorInfo] + ); + return; + } + } + logError(err, type, contextVNode, throwInDev); +} +function logError(err, type, contextVNode, throwInDev = true) { + if (true) { + const info = ErrorTypeStrings$1[type]; + if (contextVNode) { + pushWarningContext(contextVNode); + } + warn$1(`Unhandled error${info ? ` during execution of ${info}` : ``}`); + if (contextVNode) { + popWarningContext(); + } + if (throwInDev) { + throw err; + } else { + console.error(err); + } + } else { + console.error(err); + } +} +var isFlushing = false; +var isFlushPending = false; +var queue = []; +var flushIndex = 0; +var pendingPostFlushCbs = []; +var activePostFlushCbs = null; +var postFlushIndex = 0; +var resolvedPromise = Promise.resolve(); +var currentFlushPromise = null; +var RECURSION_LIMIT = 100; +function nextTick(fn) { + const p2 = currentFlushPromise || resolvedPromise; + return fn ? p2.then(this ? fn.bind(this) : fn) : p2; +} +function findInsertionIndex(id) { + let start = flushIndex + 1; + let end = queue.length; + while (start < end) { + const middle = start + end >>> 1; + const middleJob = queue[middle]; + const middleJobId = getId(middleJob); + if (middleJobId < id || middleJobId === id && middleJob.pre) { + start = middle + 1; + } else { + end = middle; + } + } + return start; +} +function queueJob(job) { + if (!queue.length || !queue.includes( + job, + isFlushing && job.allowRecurse ? flushIndex + 1 : flushIndex + )) { + if (job.id == null) { + queue.push(job); + } else { + queue.splice(findInsertionIndex(job.id), 0, job); + } + queueFlush(); + } +} +function queueFlush() { + if (!isFlushing && !isFlushPending) { + isFlushPending = true; + currentFlushPromise = resolvedPromise.then(flushJobs); + } +} +function invalidateJob(job) { + const i = queue.indexOf(job); + if (i > flushIndex) { + queue.splice(i, 1); + } +} +function queuePostFlushCb(cb) { + if (!isArray(cb)) { + if (!activePostFlushCbs || !activePostFlushCbs.includes( + cb, + cb.allowRecurse ? postFlushIndex + 1 : postFlushIndex + )) { + pendingPostFlushCbs.push(cb); + } + } else { + pendingPostFlushCbs.push(...cb); + } + queueFlush(); +} +function flushPreFlushCbs(instance, seen, i = isFlushing ? flushIndex + 1 : 0) { + if (true) { + 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; + } + queue.splice(i, 1); + i--; + cb(); + } + } +} +function flushPostFlushCbs(seen) { + if (pendingPostFlushCbs.length) { + const deduped = [...new Set(pendingPostFlushCbs)].sort( + (a, b) => getId(a) - getId(b) + ); + pendingPostFlushCbs.length = 0; + if (activePostFlushCbs) { + activePostFlushCbs.push(...deduped); + return; + } + activePostFlushCbs = deduped; + if (true) { + seen = seen || /* @__PURE__ */ new Map(); + } + for (postFlushIndex = 0; postFlushIndex < activePostFlushCbs.length; postFlushIndex++) { + if (checkRecursiveUpdates(seen, activePostFlushCbs[postFlushIndex])) { + continue; + } + activePostFlushCbs[postFlushIndex](); + } + activePostFlushCbs = null; + postFlushIndex = 0; + } +} +var getId = (job) => job.id == null ? Infinity : job.id; +var comparator = (a, b) => { + const diff = getId(a) - getId(b); + if (diff === 0) { + if (a.pre && !b.pre) + return -1; + if (b.pre && !a.pre) + return 1; + } + return diff; +}; +function flushJobs(seen) { + isFlushPending = false; + isFlushing = true; + if (true) { + seen = seen || /* @__PURE__ */ new Map(); + } + queue.sort(comparator); + const check = true ? (job) => checkRecursiveUpdates(seen, job) : NOOP; + try { + for (flushIndex = 0; flushIndex < queue.length; flushIndex++) { + const job = queue[flushIndex]; + if (job && job.active !== false) { + if (check(job)) { + continue; + } + callWithErrorHandling(job, null, 14); + } + } + } finally { + flushIndex = 0; + queue.length = 0; + flushPostFlushCbs(seen); + isFlushing = false; + currentFlushPromise = null; + if (queue.length || pendingPostFlushCbs.length) { + flushJobs(seen); + } + } +} +function checkRecursiveUpdates(seen, fn) { + if (!seen.has(fn)) { + seen.set(fn, 1); + } else { + const count = seen.get(fn); + if (count > RECURSION_LIMIT) { + const instance = fn.ownerInstance; + const componentName = instance && getComponentName(instance.type); + 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 { + seen.set(fn, count + 1); + } + } +} +var isHmrUpdating = false; +var hmrDirtyComponents = /* @__PURE__ */ new Set(); +if (true) { + getGlobalThis().__VUE_HMR_RUNTIME__ = { + createRecord: tryWrap(createRecord), + rerender: tryWrap(rerender), + reload: tryWrap(reload) + }; +} +var map = /* @__PURE__ */ new Map(); +function registerHMR(instance) { + const id = instance.type.__hmrId; + let record = map.get(id); + if (!record) { + createRecord(id, instance.type); + record = map.get(id); + } + record.instances.add(instance); +} +function unregisterHMR(instance) { + map.get(instance.type.__hmrId).instances.delete(instance); +} +function createRecord(id, initialDef) { + if (map.has(id)) { + return false; + } + map.set(id, { + initialDef: normalizeClassComponent(initialDef), + instances: /* @__PURE__ */ new Set() + }); + return true; +} +function normalizeClassComponent(component) { + return isClassComponent(component) ? component.__vccOpts : component; +} +function rerender(id, newRender) { + const record = map.get(id); + if (!record) { + return; + } + record.initialDef.render = newRender; + [...record.instances].forEach((instance) => { + if (newRender) { + instance.render = newRender; + normalizeClassComponent(instance.type).render = newRender; + } + instance.renderCache = []; + isHmrUpdating = true; + instance.effect.dirty = true; + instance.update(); + isHmrUpdating = false; + }); +} +function reload(id, newComp) { + const record = map.get(id); + if (!record) + return; + newComp = normalizeClassComponent(newComp); + updateComponentDef(record.initialDef, newComp); + const instances = [...record.instances]; + for (const instance of instances) { + const oldComp = normalizeClassComponent(instance.type); + if (!hmrDirtyComponents.has(oldComp)) { + if (oldComp !== record.initialDef) { + updateComponentDef(oldComp, newComp); + } + hmrDirtyComponents.add(oldComp); + } + instance.appContext.propsCache.delete(instance.type); + instance.appContext.emitsCache.delete(instance.type); + instance.appContext.optionsCache.delete(instance.type); + if (instance.ceReload) { + hmrDirtyComponents.add(oldComp); + 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(); + } else if (typeof window !== "undefined") { + window.location.reload(); + } else { + console.warn( + "[HMR] Root or manually mounted instance modified. Full reload required." + ); + } + } + queuePostFlushCb(() => { + for (const instance of instances) { + hmrDirtyComponents.delete( + normalizeClassComponent(instance.type) + ); + } + }); +} +function updateComponentDef(oldComp, newComp) { + extend(oldComp, newComp); + for (const key in oldComp) { + if (key !== "__file" && !(key in newComp)) { + delete oldComp[key]; + } + } +} +function tryWrap(fn) { + return (id, arg) => { + try { + return fn(id, arg); + } catch (e) { + console.error(e); + console.warn( + `[HMR] Something went wrong during Vue component hot-reload. Full reload required.` + ); + } + }; +} +var devtools$1; +var buffer = []; +var devtoolsNotInstalled = false; +function emit$1(event, ...args) { + if (devtools$1) { + devtools$1.emit(event, ...args); + } else if (!devtoolsNotInstalled) { + buffer.push({ event, args }); + } +} +function setDevtoolsHook$1(hook, target) { + var _a, _b; + 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 + // browser environment to avoid the timer handle stalling test runner exit + // (#4815) + typeof window !== "undefined" && // some envs mock window but not fully + window.HTMLElement && // also exclude jsdom + !((_b = (_a = window.navigator) == null ? void 0 : _a.userAgent) == null ? void 0 : _b.includes("jsdom")) + ) { + const replay = target.__VUE_DEVTOOLS_HOOK_REPLAY__ = target.__VUE_DEVTOOLS_HOOK_REPLAY__ || []; + replay.push((newHook) => { + setDevtoolsHook$1(newHook, target); + }); + setTimeout(() => { + if (!devtools$1) { + target.__VUE_DEVTOOLS_HOOK_REPLAY__ = null; + devtoolsNotInstalled = true; + buffer = []; + } + }, 3e3); + } else { + devtoolsNotInstalled = true; + buffer = []; + } +} +function devtoolsInitApp(app, version2) { + emit$1("app:init", app, version2, { + Fragment, + Text, + Comment, + Static + }); +} +function devtoolsUnmountApp(app) { + emit$1("app:unmount", app); +} +var devtoolsComponentAdded = createDevtoolsComponentHook( + "component:added" + /* COMPONENT_ADDED */ +); +var devtoolsComponentUpdated = createDevtoolsComponentHook( + "component:updated" + /* COMPONENT_UPDATED */ +); +var _devtoolsComponentRemoved = createDevtoolsComponentHook( + "component:removed" + /* COMPONENT_REMOVED */ +); +var devtoolsComponentRemoved = (component) => { + if (devtools$1 && typeof devtools$1.cleanupBuffer === "function" && // remove the component if it wasn't buffered + !devtools$1.cleanupBuffer(component)) { + _devtoolsComponentRemoved(component); + } +}; +function createDevtoolsComponentHook(hook) { + return (component) => { + emit$1( + hook, + component.appContext.app, + component.uid, + component.parent ? component.parent.uid : void 0, + component + ); + }; +} +var devtoolsPerfStart = createDevtoolsPerformanceHook( + "perf:start" + /* PERFORMANCE_START */ +); +var devtoolsPerfEnd = createDevtoolsPerformanceHook( + "perf:end" + /* PERFORMANCE_END */ +); +function createDevtoolsPerformanceHook(hook) { + return (component, type, time) => { + emit$1(hook, component.appContext.app, component.uid, component, type, time); + }; +} +function devtoolsComponentEmit(component, event, params) { + emit$1( + "component:emit", + component.appContext.app, + component, + event, + params + ); +} +function emit(instance, event, ...rawArgs) { + if (instance.isUnmounted) + return; + const props = instance.vnode.props || EMPTY_OBJ; + if (true) { + const { + emitsOptions, + propsOptions: [propsOptions] + } = instance; + if (emitsOptions) { + if (!(event in emitsOptions) && true) { + if (!propsOptions || !(toHandlerKey(event) in propsOptions)) { + warn$1( + `Component emitted event "${event}" but it is neither declared in the emits option nor as an "${toHandlerKey(event)}" prop.` + ); + } + } else { + const validator = emitsOptions[event]; + if (isFunction(validator)) { + const isValid = validator(...rawArgs); + if (!isValid) { + warn$1( + `Invalid event arguments: event validation failed for event "${event}".` + ); + } + } + } + } + } + let args = rawArgs; + const isModelListener2 = event.startsWith("update:"); + const modelArg = isModelListener2 && event.slice(7); + if (modelArg && modelArg in props) { + const modifiersKey = `${modelArg === "modelValue" ? "model" : modelArg}Modifiers`; + const { number, trim } = props[modifiersKey] || EMPTY_OBJ; + if (trim) { + args = rawArgs.map((a) => isString(a) ? a.trim() : a); + } + if (number) { + args = rawArgs.map(looseToNumber); + } + } + if (true) { + devtoolsComponentEmit(instance, event, args); + } + if (true) { + const lowerCaseEvent = event.toLowerCase(); + if (lowerCaseEvent !== event && props[toHandlerKey(lowerCaseEvent)]) { + 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}".` + ); + } + } + let handlerName; + let handler = props[handlerName = toHandlerKey(event)] || // also try camelCase event handler (#2249) + props[handlerName = toHandlerKey(camelize(event))]; + if (!handler && isModelListener2) { + handler = props[handlerName = toHandlerKey(hyphenate(event))]; + } + if (handler) { + callWithAsyncErrorHandling( + handler, + instance, + 6, + args + ); + } + const onceHandler = props[handlerName + `Once`]; + if (onceHandler) { + if (!instance.emitted) { + instance.emitted = {}; + } else if (instance.emitted[handlerName]) { + return; + } + instance.emitted[handlerName] = true; + callWithAsyncErrorHandling( + onceHandler, + instance, + 6, + args + ); + } +} +function normalizeEmitsOptions(comp, appContext, asMixin = false) { + const cache = appContext.emitsCache; + const cached = cache.get(comp); + if (cached !== void 0) { + return cached; + } + const raw = comp.emits; + let normalized = {}; + let hasExtends = false; + if (__VUE_OPTIONS_API__ && !isFunction(comp)) { + const extendEmits = (raw2) => { + const normalizedFromExtend = normalizeEmitsOptions(raw2, appContext, true); + if (normalizedFromExtend) { + hasExtends = true; + extend(normalized, normalizedFromExtend); + } + }; + if (!asMixin && appContext.mixins.length) { + appContext.mixins.forEach(extendEmits); + } + if (comp.extends) { + extendEmits(comp.extends); + } + if (comp.mixins) { + comp.mixins.forEach(extendEmits); + } + } + if (!raw && !hasExtends) { + if (isObject(comp)) { + cache.set(comp, null); + } + return null; + } + if (isArray(raw)) { + raw.forEach((key) => normalized[key] = null); + } else { + extend(normalized, raw); + } + if (isObject(comp)) { + cache.set(comp, normalized); + } + return normalized; +} +function isEmitListener(options, key) { + if (!options || !isOn(key)) { + return false; + } + key = key.slice(2).replace(/Once$/, ""); + return hasOwn(options, key[0].toLowerCase() + key.slice(1)) || hasOwn(options, hyphenate(key)) || hasOwn(options, key); +} +var currentRenderingInstance = null; +var currentScopeId = null; +function setCurrentRenderingInstance(instance) { + const prev = currentRenderingInstance; + currentRenderingInstance = instance; + currentScopeId = instance && instance.type.__scopeId || null; + return prev; +} +function pushScopeId(id) { + currentScopeId = id; +} +function popScopeId() { + currentScopeId = null; +} +var withScopeId = (_id) => withCtx; +function withCtx(fn, ctx = currentRenderingInstance, isNonScopedSlot) { + if (!ctx) + return fn; + if (fn._n) { + return fn; + } + const renderFnWithContext = (...args) => { + if (renderFnWithContext._d) { + setBlockTracking(-1); + } + const prevInstance = setCurrentRenderingInstance(ctx); + let res; + try { + res = fn(...args); + } finally { + setCurrentRenderingInstance(prevInstance); + if (renderFnWithContext._d) { + setBlockTracking(1); + } + } + if (true) { + devtoolsComponentUpdated(ctx); + } + return res; + }; + renderFnWithContext._n = true; + renderFnWithContext._c = true; + renderFnWithContext._d = true; + return renderFnWithContext; +} +var accessedAttrs = false; +function markAttrsAccessed() { + accessedAttrs = true; +} +function renderComponentRoot(instance) { + const { + type: Component, + vnode, + proxy, + withProxy, + props, + propsOptions: [propsOptions], + slots, + attrs, + emit: emit2, + render: render2, + renderCache, + data, + setupState, + ctx, + inheritAttrs + } = instance; + let result; + let fallthroughAttrs; + const prev = setCurrentRenderingInstance(instance); + if (true) { + 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( + thisProxy, + proxyToUse, + renderCache, + props, + setupState, + data, + ctx + ) + ); + fallthroughAttrs = attrs; + } else { + const render22 = Component; + if (attrs === props) { + markAttrsAccessed(); + } + result = normalizeVNode( + render22.length > 1 ? render22( + props, + true ? { + get attrs() { + markAttrsAccessed(); + return attrs; + }, + slots, + emit: emit2 + } : { attrs, slots, emit: emit2 } + ) : render22( + props, + null + /* we know it doesn't need it */ + ) + ); + fallthroughAttrs = Component.props ? attrs : getFunctionalFallthrough(attrs); + } + } catch (err) { + blockStack.length = 0; + handleError(err, instance, 1); + result = createVNode(Comment); + } + let root = result; + let setRoot = void 0; + if (result.patchFlag > 0 && result.patchFlag & 2048) { + [root, setRoot] = getChildRoot(result); + } + if (fallthroughAttrs && inheritAttrs !== false) { + const keys = Object.keys(fallthroughAttrs); + const { shapeFlag } = root; + if (keys.length) { + if (shapeFlag & (1 | 6)) { + if (propsOptions && keys.some(isModelListener)) { + fallthroughAttrs = filterModelListeners( + fallthroughAttrs, + propsOptions + ); + } + root = cloneVNode(root, fallthroughAttrs); + } else if (!accessedAttrs && root.type !== Comment) { + const allAttrs = Object.keys(attrs); + const eventAttrs = []; + const extraAttrs = []; + for (let i = 0, l = allAttrs.length; i < l; i++) { + const key = allAttrs[i]; + if (isOn(key)) { + if (!isModelListener(key)) { + eventAttrs.push(key[2].toLowerCase() + key.slice(3)); + } + } else { + extraAttrs.push(key); + } + } + if (extraAttrs.length) { + 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$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.` + ); + } + } + } + } + if (vnode.dirs) { + if (!isElementRoot(root)) { + warn$1( + `Runtime directive used on component with non-element root node. The directives will not function as intended.` + ); + } + root = cloneVNode(root); + root.dirs = root.dirs ? root.dirs.concat(vnode.dirs) : vnode.dirs; + } + if (vnode.transition) { + if (!isElementRoot(root)) { + warn$1( + `Component inside renders non-element root node that cannot be animated.` + ); + } + root.transition = vnode.transition; + } + if (setRoot) { + setRoot(root); + } else { + result = root; + } + setCurrentRenderingInstance(prev); + return result; +} +var getChildRoot = (vnode) => { + const rawChildren = vnode.children; + const dynamicChildren = vnode.dynamicChildren; + 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; + const setRoot = (updatedRoot) => { + rawChildren[index] = updatedRoot; + if (dynamicChildren) { + if (dynamicIndex > -1) { + dynamicChildren[dynamicIndex] = updatedRoot; + } else if (updatedRoot.patchFlag > 0) { + vnode.dynamicChildren = [...dynamicChildren, updatedRoot]; + } + } + }; + return [normalizeVNode(childRoot), setRoot]; +}; +function filterSingleRoot(children, recurse = true) { + let singleRoot; + for (let i = 0; i < children.length; i++) { + const child = children[i]; + if (isVNode(child)) { + if (child.type !== Comment || child.children === "v-if") { + if (singleRoot) { + return; + } else { + singleRoot = child; + if (recurse && singleRoot.patchFlag > 0 && singleRoot.patchFlag & 2048) { + return filterSingleRoot(singleRoot.children); + } + } + } + } else { + return; + } + } + return singleRoot; +} +var getFunctionalFallthrough = (attrs) => { + let res; + for (const key in attrs) { + if (key === "class" || key === "style" || isOn(key)) { + (res || (res = {}))[key] = attrs[key]; + } + } + return res; +}; +var filterModelListeners = (attrs, props) => { + const res = {}; + for (const key in attrs) { + if (!isModelListener(key) || !(key.slice(9) in props)) { + res[key] = attrs[key]; + } + } + return res; +}; +var isElementRoot = (vnode) => { + return vnode.shapeFlag & (6 | 1) || vnode.type === Comment; +}; +function shouldUpdateComponent(prevVNode, nextVNode, optimized) { + const { props: prevProps, children: prevChildren, component } = prevVNode; + const { props: nextProps, children: nextChildren, patchFlag } = nextVNode; + const emits = component.emitsOptions; + if ((prevChildren || nextChildren) && isHmrUpdating) { + return true; + } + if (nextVNode.dirs || nextVNode.transition) { + return true; + } + if (optimized && patchFlag >= 0) { + if (patchFlag & 1024) { + return true; + } + if (patchFlag & 16) { + if (!prevProps) { + return !!nextProps; + } + return hasPropsChanged(prevProps, nextProps, emits); + } else if (patchFlag & 8) { + const dynamicProps = nextVNode.dynamicProps; + for (let i = 0; i < dynamicProps.length; i++) { + const key = dynamicProps[i]; + if (nextProps[key] !== prevProps[key] && !isEmitListener(emits, key)) { + return true; + } + } + } + } else { + if (prevChildren || nextChildren) { + if (!nextChildren || !nextChildren.$stable) { + return true; + } + } + if (prevProps === nextProps) { + return false; + } + if (!prevProps) { + return !!nextProps; + } + if (!nextProps) { + return true; + } + return hasPropsChanged(prevProps, nextProps, emits); + } + return false; +} +function hasPropsChanged(prevProps, nextProps, emitsOptions) { + const nextKeys = Object.keys(nextProps); + if (nextKeys.length !== Object.keys(prevProps).length) { + return true; + } + for (let i = 0; i < nextKeys.length; i++) { + const key = nextKeys[i]; + if (nextProps[key] !== prevProps[key] && !isEmitListener(emitsOptions, key)) { + return true; + } + } + return false; +} +function updateHOCHostEl({ vnode, parent }, el) { + 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 if (true) { + 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 + // directly in the renderer. The renderer checks for the __isSuspense flag + // on a vnode's type and calls the `process` method, passing in renderer + // internals. + __isSuspense: true, + process(n1, n2, container, anchor, parentComponent, parentSuspense, namespace, slotScopeIds, optimized, rendererInternals) { + if (n1 == null) { + mountSuspense( + n2, + container, + anchor, + parentComponent, + parentSuspense, + 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, + namespace, + slotScopeIds, + optimized, + rendererInternals + ); + } + }, + hydrate: hydrateSuspense, + create: createSuspenseBoundary, + normalize: normalizeSuspenseChildren +}; +var Suspense = SuspenseImpl; +function triggerEvent(vnode, name) { + const eventListener = vnode.props && vnode.props[name]; + if (isFunction(eventListener)) { + eventListener(); + } +} +function mountSuspense(vnode, container, anchor, parentComponent, parentSuspense, namespace, slotScopeIds, optimized, rendererInternals) { + const { + p: patch, + o: { createElement } + } = rendererInternals; + const hiddenContainer = createElement("div"); + const suspense = vnode.suspense = createSuspenseBoundary( + vnode, + parentSuspense, + parentComponent, + container, + hiddenContainer, + anchor, + namespace, + slotScopeIds, + optimized, + rendererInternals + ); + patch( + null, + suspense.pendingBranch = vnode.ssContent, + hiddenContainer, + null, + parentComponent, + suspense, + namespace, + slotScopeIds + ); + if (suspense.deps > 0) { + triggerEvent(vnode, "onPending"); + triggerEvent(vnode, "onFallback"); + patch( + null, + vnode.ssFallback, + container, + anchor, + parentComponent, + null, + // fallback tree will not have suspense context + namespace, + slotScopeIds + ); + setActiveBranch(suspense, vnode.ssFallback); + } else { + suspense.resolve(false, true); + } +} +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; + const newBranch = n2.ssContent; + const newFallback = n2.ssFallback; + const { activeBranch, pendingBranch, isInFallback, isHydrating } = suspense; + if (pendingBranch) { + suspense.pendingBranch = newBranch; + if (isSameVNodeType(newBranch, pendingBranch)) { + patch( + pendingBranch, + newBranch, + suspense.hiddenContainer, + null, + parentComponent, + suspense, + namespace, + slotScopeIds, + optimized + ); + if (suspense.deps <= 0) { + suspense.resolve(); + } else if (isInFallback) { + 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 = suspenseId++; + if (isHydrating) { + suspense.isHydrating = false; + suspense.activeBranch = pendingBranch; + } else { + unmount(pendingBranch, parentComponent, suspense); + } + suspense.deps = 0; + suspense.effects.length = 0; + suspense.hiddenContainer = createElement("div"); + if (isInFallback) { + patch( + null, + newBranch, + suspense.hiddenContainer, + null, + parentComponent, + suspense, + namespace, + slotScopeIds, + optimized + ); + if (suspense.deps <= 0) { + suspense.resolve(); + } else { + patch( + activeBranch, + newFallback, + container, + anchor, + parentComponent, + null, + // fallback tree will not have suspense context + namespace, + slotScopeIds, + optimized + ); + setActiveBranch(suspense, newFallback); + } + } else if (activeBranch && isSameVNodeType(newBranch, activeBranch)) { + patch( + activeBranch, + newBranch, + container, + anchor, + parentComponent, + suspense, + namespace, + slotScopeIds, + optimized + ); + suspense.resolve(true); + } else { + patch( + null, + newBranch, + suspense.hiddenContainer, + null, + parentComponent, + suspense, + namespace, + slotScopeIds, + optimized + ); + if (suspense.deps <= 0) { + suspense.resolve(); + } + } + } + } else { + if (activeBranch && isSameVNodeType(newBranch, activeBranch)) { + patch( + activeBranch, + newBranch, + container, + anchor, + parentComponent, + suspense, + namespace, + slotScopeIds, + optimized + ); + setActiveBranch(suspense, newBranch); + } else { + triggerEvent(n2, "onPending"); + suspense.pendingBranch = newBranch; + if (newBranch.shapeFlag & 512) { + suspense.pendingId = newBranch.component.suspenseId; + } else { + suspense.pendingId = suspenseId++; + } + patch( + null, + newBranch, + suspense.hiddenContainer, + null, + parentComponent, + suspense, + namespace, + slotScopeIds, + optimized + ); + if (suspense.deps <= 0) { + suspense.resolve(); + } else { + const { timeout, pendingId } = suspense; + if (timeout > 0) { + setTimeout(() => { + if (suspense.pendingId === pendingId) { + suspense.fallback(newFallback); + } + }, timeout); + } else if (timeout === 0) { + suspense.fallback(newFallback); + } + } + } + } +} +var hasWarned = false; +function createSuspenseBoundary(vnode, parentSuspense, parentComponent, container, hiddenContainer, anchor, namespace, slotScopeIds, optimized, rendererInternals, isHydrating = false) { + if (!hasWarned) { + hasWarned = true; + console[console.info ? "info" : "log"]( + ` is an experimental feature and its API will likely change.` + ); + } + const { + p: patch, + m: move, + um: unmount, + n: next, + o: { parentNode, remove: remove2 } + } = rendererInternals; + let parentSuspenseId; + const isSuspensible = isVNodeSuspensible(vnode); + if (isSuspensible) { + if (parentSuspense == null ? void 0 : parentSuspense.pendingBranch) { + parentSuspenseId = parentSuspense.pendingId; + parentSuspense.deps++; + } + } + const timeout = vnode.props ? toNumber(vnode.props.timeout) : void 0; + if (true) { + assertNumber(timeout, `Suspense timeout`); + } + const initialAnchor = anchor; + const suspense = { + vnode, + parent: parentSuspense, + parentComponent, + namespace, + container, + hiddenContainer, + deps: 0, + pendingId: suspenseId++, + timeout: typeof timeout === "number" ? timeout : -1, + activeBranch: null, + pendingBranch: null, + isInFallback: !isHydrating, + isHydrating, + isUnmounted: false, + effects: [], + resolve(resume = false, sync = false) { + if (true) { + if (!resume && !suspense.pendingBranch) { + throw new Error( + `suspense.resolve() is called without a pending branch.` + ); + } + if (suspense.isUnmounted) { + throw new Error( + `suspense.resolve() is called on an already unmounted suspense boundary.` + ); + } + } + const { + vnode: vnode2, + activeBranch, + pendingBranch, + pendingId, + effects, + parentComponent: parentComponent2, + container: container2 + } = suspense; + let delayEnter = false; + if (suspense.isHydrating) { + suspense.isHydrating = false; + } else if (!resume) { + delayEnter = activeBranch && pendingBranch.transition && pendingBranch.transition.mode === "out-in"; + if (delayEnter) { + activeBranch.transition.afterLeave = () => { + if (pendingId === suspense.pendingId) { + move( + pendingBranch, + container2, + anchor === initialAnchor ? next(activeBranch) : anchor, + 0 + ); + queuePostFlushCb(effects); + } + }; + } + if (activeBranch) { + if (parentNode(activeBranch.el) !== suspense.hiddenContainer) { + anchor = next(activeBranch); + } + unmount(activeBranch, parentComponent2, suspense, true); + } + if (!delayEnter) { + move(pendingBranch, container2, anchor, 0); + } + } + setActiveBranch(suspense, pendingBranch); + suspense.pendingBranch = null; + suspense.isInFallback = false; + let parent = suspense.parent; + let hasUnresolvedAncestor = false; + while (parent) { + if (parent.pendingBranch) { + parent.effects.push(...effects); + hasUnresolvedAncestor = true; + break; + } + parent = parent.parent; + } + if (!hasUnresolvedAncestor && !delayEnter) { + queuePostFlushCb(effects); + } + suspense.effects = []; + if (isSuspensible) { + if (parentSuspense && parentSuspense.pendingBranch && parentSuspenseId === parentSuspense.pendingId) { + parentSuspense.deps--; + if (parentSuspense.deps === 0 && !sync) { + parentSuspense.resolve(); + } + } + } + triggerEvent(vnode2, "onResolve"); + }, + fallback(fallbackVNode) { + if (!suspense.pendingBranch) { + return; + } + const { vnode: vnode2, activeBranch, parentComponent: parentComponent2, container: container2, namespace: namespace2 } = suspense; + triggerEvent(vnode2, "onFallback"); + const anchor2 = next(activeBranch); + const mountFallback = () => { + if (!suspense.isInFallback) { + return; + } + patch( + null, + fallbackVNode, + container2, + anchor2, + parentComponent2, + null, + // fallback tree will not have suspense context + namespace2, + slotScopeIds, + optimized + ); + setActiveBranch(suspense, fallbackVNode); + }; + const delayEnter = fallbackVNode.transition && fallbackVNode.transition.mode === "out-in"; + if (delayEnter) { + activeBranch.transition.afterLeave = mountFallback; + } + suspense.isInFallback = true; + unmount( + activeBranch, + parentComponent2, + null, + // no suspense so unmount hooks fire now + true + // shouldRemove + ); + if (!delayEnter) { + mountFallback(); + } + }, + move(container2, anchor2, type) { + suspense.activeBranch && move(suspense.activeBranch, container2, anchor2, type); + suspense.container = container2; + }, + next() { + return suspense.activeBranch && next(suspense.activeBranch); + }, + registerDep(instance, setupRenderEffect) { + const isInPendingSuspense = !!suspense.pendingBranch; + if (isInPendingSuspense) { + suspense.deps++; + } + const hydratedEl = instance.vnode.el; + instance.asyncDep.catch((err) => { + handleError(err, instance, 0); + }).then((asyncSetupResult) => { + if (instance.isUnmounted || suspense.isUnmounted || suspense.pendingId !== instance.suspenseId) { + return; + } + instance.asyncResolved = true; + const { vnode: vnode2 } = instance; + if (true) { + pushWarningContext(vnode2); + } + handleSetupResult(instance, asyncSetupResult, false); + if (hydratedEl) { + vnode2.el = hydratedEl; + } + const placeholder = !hydratedEl && instance.subTree.el; + setupRenderEffect( + instance, + vnode2, + // component may have been moved before resolve. + // if this is not a hydration, instance.subTree will be the comment + // placeholder. + parentNode(hydratedEl || instance.subTree.el), + // anchor will not be used if this is hydration, so only need to + // consider the comment placeholder case. + hydratedEl ? null : next(instance.subTree), + suspense, + namespace, + optimized + ); + if (placeholder) { + remove2(placeholder); + } + updateHOCHostEl(instance, vnode2.el); + if (true) { + popWarningContext(); + } + if (isInPendingSuspense && --suspense.deps === 0) { + suspense.resolve(); + } + }); + }, + unmount(parentSuspense2, doRemove) { + suspense.isUnmounted = true; + if (suspense.activeBranch) { + unmount( + suspense.activeBranch, + parentComponent, + parentSuspense2, + doRemove + ); + } + if (suspense.pendingBranch) { + unmount( + suspense.pendingBranch, + parentComponent, + parentSuspense2, + doRemove + ); + } + } + }; + return suspense; +} +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, + namespace, + slotScopeIds, + optimized, + rendererInternals, + true + ); + const result = hydrateNode( + node, + suspense.pendingBranch = vnode.ssContent, + parentComponent, + suspense, + slotScopeIds, + optimized + ); + if (suspense.deps === 0) { + suspense.resolve(false, true); + } + return result; +} +function normalizeSuspenseChildren(vnode) { + const { shapeFlag, children } = vnode; + const isSlotChildren = shapeFlag & 32; + vnode.ssContent = normalizeSuspenseSlot( + isSlotChildren ? children.default : children + ); + vnode.ssFallback = isSlotChildren ? normalizeSuspenseSlot(children.fallback) : createVNode(Comment); +} +function normalizeSuspenseSlot(s) { + let block; + if (isFunction(s)) { + const trackBlock = isBlockTreeEnabled && s._c; + if (trackBlock) { + s._d = false; + openBlock(); + } + s = s(); + if (trackBlock) { + s._d = true; + block = currentBlock; + closeBlock(); + } + } + if (isArray(s)) { + const singleChild = filterSingleRoot(s); + if (!singleChild && s.filter((child) => child !== NULL_DYNAMIC_COMPONENT).length > 0) { + warn$1(` slots expect a single root node.`); + } + s = singleChild; + } + s = normalizeVNode(s); + if (block && !s.dynamicChildren) { + s.dynamicChildren = block.filter((c) => c !== s); + } + return s; +} +function queueEffectWithSuspense(fn, suspense) { + if (suspense && suspense.pendingBranch) { + if (isArray(fn)) { + suspense.effects.push(...fn); + } else { + suspense.effects.push(fn); + } + } else { + queuePostFlushCb(fn); + } +} +function setActiveBranch(suspense, branch) { + suspense.activeBranch = branch; + const { vnode, parentComponent } = suspense; + 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; +} +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); +} +function watchPostEffect(effect2, options) { + return doWatch( + effect2, + null, + true ? extend({}, options, { flush: "post" }) : { flush: "post" } + ); +} +function watchSyncEffect(effect2, options) { + return doWatch( + effect2, + null, + true ? extend({}, options, { flush: "sync" }) : { flush: "sync" } + ); +} +var INITIAL_WATCHER_VALUE = {}; +function watch(source, cb, options) { + if (!isFunction(cb)) { + 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, + 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$1( + `watch() "immediate" option is only respected when using the watch(source, callback, options?) signature.` + ); + } + if (deep !== void 0) { + 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$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 = 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; + if (isRef(source)) { + getter = () => source.value; + forceTrigger = isShallow(source); + } else if (isReactive(source)) { + getter = () => reactiveGetter(source); + forceTrigger = true; + } else if (isArray(source)) { + isMultiSource = true; + forceTrigger = source.some((s) => isReactive(s) || isShallow(s)); + getter = () => source.map((s) => { + if (isRef(s)) { + return s.value; + } else if (isReactive(s)) { + return reactiveGetter(s); + } else if (isFunction(s)) { + return callWithErrorHandling(s, instance, 2); + } else { + warnInvalidSource(s); + } + }); + } else if (isFunction(source)) { + if (cb) { + getter = () => callWithErrorHandling(source, instance, 2); + } else { + getter = () => { + if (cleanup) { + cleanup(); + } + return callWithAsyncErrorHandling( + source, + instance, + 3, + [onCleanup] + ); + }; + } + } else { + getter = NOOP; + warnInvalidSource(source); + } + if (cb && deep) { + const baseGetter = getter; + getter = () => traverse(baseGetter()); + } + let cleanup; + let onCleanup = (fn) => { + cleanup = effect2.onStop = () => { + callWithErrorHandling(fn, instance, 4); + cleanup = effect2.onStop = void 0; + }; + }; + let ssrCleanup; + if (isInSSRComponentSetup) { + onCleanup = NOOP; + if (!cb) { + getter(); + } else if (immediate) { + callWithAsyncErrorHandling(cb, instance, 3, [ + getter(), + isMultiSource ? [] : void 0, + onCleanup + ]); + } + if (flush === "sync") { + const ctx = useSSRContext(); + ssrCleanup = ctx.__watcherHandles || (ctx.__watcherHandles = []); + } else { + return NOOP; + } + } + let oldValue = isMultiSource ? new Array(source.length).fill(INITIAL_WATCHER_VALUE) : INITIAL_WATCHER_VALUE; + const job = () => { + 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 (cleanup) { + cleanup(); + } + callWithAsyncErrorHandling(cb, instance, 3, [ + newValue, + // pass undefined as the old value when it's changed for the first time + oldValue === INITIAL_WATCHER_VALUE ? void 0 : isMultiSource && oldValue[0] === INITIAL_WATCHER_VALUE ? [] : oldValue, + onCleanup + ]); + oldValue = newValue; + } + } else { + effect2.run(); + } + }; + job.allowRecurse = !!cb; + let scheduler; + if (flush === "sync") { + scheduler = job; + } else if (flush === "post") { + scheduler = () => queuePostRenderEffect(job, instance && instance.suspense); + } else { + job.pre = true; + if (instance) + job.id = instance.uid; + scheduler = () => queueJob(job); + } + const effect2 = new ReactiveEffect(getter, NOOP, scheduler); + const scope = getCurrentScope(); + const unwatch = () => { + effect2.stop(); + if (scope) { + remove(scope.effects, effect2); + } + }; + if (true) { + effect2.onTrack = onTrack; + effect2.onTrigger = onTrigger; + } + if (cb) { + if (immediate) { + job(); + } else { + oldValue = effect2.run(); + } + } else if (flush === "post") { + queuePostRenderEffect( + effect2.run.bind(effect2), + instance && instance.suspense + ); + } else { + effect2.run(); + } + if (ssrCleanup) + ssrCleanup.push(unwatch); + return unwatch; +} +function instanceWatch(source, value, options) { + const publicThis = this.proxy; + const getter = isString(source) ? source.includes(".") ? createPathGetter(publicThis, source) : () => publicThis[source] : source.bind(publicThis, publicThis); + let cb; + if (isFunction(value)) { + cb = value; + } else { + cb = value.handler; + options = value; + } + const reset = setCurrentInstance(this); + const res = doWatch(getter, cb.bind(publicThis), options); + reset(); + return res; +} +function createPathGetter(ctx, path) { + const segments = path.split("."); + return () => { + let cur = ctx; + for (let i = 0; i < segments.length && cur; i++) { + cur = cur[segments[i]]; + } + return cur; + }; +} +function traverse(value, depth, currentDepth = 0, seen) { + if (!isObject(value) || value["__v_skip"]) { + return value; + } + if (depth && depth > 0) { + if (currentDepth >= depth) { + return value; + } + currentDepth++; + } + seen = seen || /* @__PURE__ */ new Set(); + if (seen.has(value)) { + return value; + } + seen.add(value); + if (isRef(value)) { + traverse(value.value, depth, currentDepth, seen); + } else if (isArray(value)) { + for (let i = 0; i < value.length; i++) { + traverse(value[i], depth, currentDepth, seen); + } + } else if (isSet(value) || isMap(value)) { + value.forEach((v) => { + traverse(v, depth, currentDepth, seen); + }); + } else if (isPlainObject(value)) { + for (const key in value) { + traverse(value[key], depth, currentDepth, seen); + } + } + return value; +} +function validateDirectiveName(name) { + if (isBuiltInDirective(name)) { + warn$1("Do not use built-in directive ids as custom directive id: " + name); + } +} +function withDirectives(vnode, directives) { + if (currentRenderingInstance === null) { + warn$1(`withDirectives can only be used inside render functions.`); + return vnode; + } + 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]; + if (dir) { + if (isFunction(dir)) { + dir = { + mounted: dir, + updated: dir + }; + } + if (dir.deep) { + traverse(value); + } + bindings.push({ + dir, + instance, + value, + oldValue: void 0, + arg, + modifiers + }); + } + } + return vnode; +} +function invokeDirectiveHook(vnode, prevVNode, instance, name) { + const bindings = vnode.dirs; + const oldBindings = prevVNode && prevVNode.dirs; + for (let i = 0; i < bindings.length; i++) { + const binding = bindings[i]; + if (oldBindings) { + binding.oldValue = oldBindings[i].value; + } + let hook = binding.dir[name]; + if (hook) { + pauseTracking(); + callWithAsyncErrorHandling(hook, instance, 8, [ + vnode.el, + binding, + vnode, + prevVNode + ]); + resetTracking(); + } + } +} +var leaveCbKey = Symbol("_leaveCb"); +var enterCbKey = Symbol("_enterCb"); +function useTransitionState() { + const state = { + isMounted: false, + isLeaving: false, + isUnmounting: false, + leavingVNodes: /* @__PURE__ */ new Map() + }; + onMounted(() => { + state.isMounted = true; + }); + onBeforeUnmount(() => { + state.isUnmounting = true; + }); + return state; +} +var TransitionHookValidator = [Function, Array]; +var BaseTransitionPropsValidators = { + mode: String, + appear: Boolean, + persisted: Boolean, + // enter + onBeforeEnter: TransitionHookValidator, + onEnter: TransitionHookValidator, + onAfterEnter: TransitionHookValidator, + onEnterCancelled: TransitionHookValidator, + // leave + onBeforeLeave: TransitionHookValidator, + onLeave: TransitionHookValidator, + onAfterLeave: TransitionHookValidator, + onLeaveCancelled: TransitionHookValidator, + // appear + onBeforeAppear: TransitionHookValidator, + onAppear: TransitionHookValidator, + onAfterAppear: TransitionHookValidator, + onAppearCancelled: TransitionHookValidator +}; +var BaseTransitionImpl = { + name: `BaseTransition`, + props: BaseTransitionPropsValidators, + setup(props, { slots }) { + const instance = getCurrentInstance(); + const state = useTransitionState(); + return () => { + const children = slots.default && getTransitionRawChildren(slots.default(), true); + if (!children || !children.length) { + return; + } + let child = children[0]; + if (children.length > 1) { + let hasFound = false; + for (const c of children) { + if (c.type !== Comment) { + if (hasFound) { + warn$1( + " can only be used on a single element or component. Use for lists." + ); + break; + } + child = c; + hasFound = true; + if (false) + break; + } + } + } + const rawProps = toRaw(props); + const { mode } = rawProps; + if (mode && mode !== "in-out" && mode !== "out-in" && mode !== "default") { + warn$1(`invalid mode: ${mode}`); + } + if (state.isLeaving) { + return emptyPlaceholder(child); + } + const innerChild = getKeepAliveChild(child); + if (!innerChild) { + return emptyPlaceholder(child); + } + const enterHooks = resolveTransitionHooks( + innerChild, + rawProps, + state, + instance + ); + setTransitionHooks(innerChild, enterHooks); + const oldChild = instance.subTree; + const oldInnerChild = oldChild && getKeepAliveChild(oldChild); + if (oldInnerChild && oldInnerChild.type !== Comment && !isSameVNodeType(innerChild, oldInnerChild)) { + const leavingHooks = resolveTransitionHooks( + oldInnerChild, + rawProps, + state, + instance + ); + setTransitionHooks(oldInnerChild, leavingHooks); + if (mode === "out-in") { + state.isLeaving = true; + leavingHooks.afterLeave = () => { + state.isLeaving = false; + if (instance.update.active !== false) { + instance.effect.dirty = true; + instance.update(); + } + }; + return emptyPlaceholder(child); + } else if (mode === "in-out" && innerChild.type !== Comment) { + leavingHooks.delayLeave = (el, earlyRemove, delayedLeave) => { + const leavingVNodesCache = getLeavingNodesForType( + state, + oldInnerChild + ); + leavingVNodesCache[String(oldInnerChild.key)] = oldInnerChild; + el[leaveCbKey] = () => { + earlyRemove(); + el[leaveCbKey] = void 0; + delete enterHooks.delayedLeave; + }; + enterHooks.delayedLeave = delayedLeave; + }; + } + } + return child; + }; + } +}; +var BaseTransition = BaseTransitionImpl; +function getLeavingNodesForType(state, vnode) { + const { leavingVNodes } = state; + let leavingVNodesCache = leavingVNodes.get(vnode.type); + if (!leavingVNodesCache) { + leavingVNodesCache = /* @__PURE__ */ Object.create(null); + leavingVNodes.set(vnode.type, leavingVNodesCache); + } + return leavingVNodesCache; +} +function resolveTransitionHooks(vnode, props, state, instance) { + const { + appear, + mode, + persisted = false, + onBeforeEnter, + onEnter, + onAfterEnter, + onEnterCancelled, + onBeforeLeave, + onLeave, + onAfterLeave, + onLeaveCancelled, + onBeforeAppear, + onAppear, + onAfterAppear, + onAppearCancelled + } = props; + const key = String(vnode.key); + const leavingVNodesCache = getLeavingNodesForType(state, vnode); + const callHook3 = (hook, args) => { + hook && callWithAsyncErrorHandling( + hook, + instance, + 9, + args + ); + }; + const callAsyncHook = (hook, args) => { + const done = args[1]; + callHook3(hook, args); + if (isArray(hook)) { + if (hook.every((hook2) => hook2.length <= 1)) + done(); + } else if (hook.length <= 1) { + done(); + } + }; + const hooks = { + mode, + persisted, + beforeEnter(el) { + let hook = onBeforeEnter; + if (!state.isMounted) { + if (appear) { + hook = onBeforeAppear || onBeforeEnter; + } else { + return; + } + } + if (el[leaveCbKey]) { + el[leaveCbKey]( + true + /* cancelled */ + ); + } + const leavingVNode = leavingVNodesCache[key]; + if (leavingVNode && isSameVNodeType(vnode, leavingVNode) && leavingVNode.el[leaveCbKey]) { + leavingVNode.el[leaveCbKey](); + } + callHook3(hook, [el]); + }, + enter(el) { + let hook = onEnter; + let afterHook = onAfterEnter; + let cancelHook = onEnterCancelled; + if (!state.isMounted) { + if (appear) { + hook = onAppear || onEnter; + afterHook = onAfterAppear || onAfterEnter; + cancelHook = onAppearCancelled || onEnterCancelled; + } else { + return; + } + } + let called = false; + const done = el[enterCbKey] = (cancelled) => { + if (called) + return; + called = true; + if (cancelled) { + callHook3(cancelHook, [el]); + } else { + callHook3(afterHook, [el]); + } + if (hooks.delayedLeave) { + hooks.delayedLeave(); + } + el[enterCbKey] = void 0; + }; + if (hook) { + callAsyncHook(hook, [el, done]); + } else { + done(); + } + }, + leave(el, remove2) { + const key2 = String(vnode.key); + if (el[enterCbKey]) { + el[enterCbKey]( + true + /* cancelled */ + ); + } + if (state.isUnmounting) { + return remove2(); + } + callHook3(onBeforeLeave, [el]); + let called = false; + const done = el[leaveCbKey] = (cancelled) => { + if (called) + return; + called = true; + remove2(); + if (cancelled) { + callHook3(onLeaveCancelled, [el]); + } else { + callHook3(onAfterLeave, [el]); + } + el[leaveCbKey] = void 0; + if (leavingVNodesCache[key2] === vnode) { + delete leavingVNodesCache[key2]; + } + }; + leavingVNodesCache[key2] = vnode; + if (onLeave) { + callAsyncHook(onLeave, [el, done]); + } else { + done(); + } + }, + clone(vnode2) { + return resolveTransitionHooks(vnode2, props, state, instance); + } + }; + return hooks; +} +function emptyPlaceholder(vnode) { + if (isKeepAlive(vnode)) { + vnode = cloneVNode(vnode); + vnode.children = null; + return vnode; + } +} +function getKeepAliveChild(vnode) { + return isKeepAlive(vnode) ? ( + // #7121 ensure get the child component subtree in case + // it's been replaced during HMR + vnode.component ? vnode.component.subTree : vnode.children ? vnode.children[0] : void 0 + ) : vnode; +} +function setTransitionHooks(vnode, hooks) { + if (vnode.shapeFlag & 6 && vnode.component) { + setTransitionHooks(vnode.component.subTree, hooks); + } else if (vnode.shapeFlag & 128) { + vnode.ssContent.transition = hooks.clone(vnode.ssContent); + vnode.ssFallback.transition = hooks.clone(vnode.ssFallback); + } else { + vnode.transition = hooks; + } +} +function getTransitionRawChildren(children, keepComment = false, parentKey) { + let ret = []; + let keyedFragmentCount = 0; + for (let i = 0; i < children.length; i++) { + let child = children[i]; + const key = parentKey == null ? child.key : String(parentKey) + String(child.key != null ? child.key : i); + if (child.type === Fragment) { + if (child.patchFlag & 128) + keyedFragmentCount++; + ret = ret.concat( + getTransitionRawChildren(child.children, keepComment, key) + ); + } else if (keepComment || child.type !== Comment) { + ret.push(key != null ? cloneVNode(child, { key }) : child); + } + } + if (keyedFragmentCount > 1) { + for (let i = 0; i < ret.length; i++) { + ret[i].patchFlag = -2; + } + } + return ret; +} +function defineComponent(options, extraOptions) { + return isFunction(options) ? ( + // #8326: extend call and options.name access are considered side-effects + // by Rollup, so we have to wrap it in a pure-annotated IIFE. + (() => extend({ name: options.name }, extraOptions, { setup: options }))() + ) : options; +} +var isAsyncWrapper = (i) => !!i.type.__asyncLoader; +function defineAsyncComponent(source) { + if (isFunction(source)) { + source = { loader: source }; + } + const { + loader, + loadingComponent, + errorComponent, + delay = 200, + timeout, + // undefined = never times out + suspensible = true, + onError: userOnError + } = source; + let pendingRequest = null; + let resolvedComp; + let retries = 0; + const retry = () => { + retries++; + pendingRequest = null; + return load(); + }; + const load = () => { + let thisRequest; + return pendingRequest || (thisRequest = pendingRequest = loader().catch((err) => { + err = err instanceof Error ? err : new Error(String(err)); + if (userOnError) { + return new Promise((resolve2, reject) => { + const userRetry = () => resolve2(retry()); + const userFail = () => reject(err); + userOnError(err, userRetry, userFail, retries + 1); + }); + } else { + throw err; + } + }).then((comp) => { + if (thisRequest !== pendingRequest && pendingRequest) { + return pendingRequest; + } + if (!comp) { + warn$1( + `Async component loader resolved to undefined. If you are using retry(), make sure to return its return value.` + ); + } + if (comp && (comp.__esModule || comp[Symbol.toStringTag] === "Module")) { + comp = comp.default; + } + if (comp && !isObject(comp) && !isFunction(comp)) { + throw new Error(`Invalid async component load result: ${comp}`); + } + resolvedComp = comp; + return comp; + })); + }; + return defineComponent({ + name: "AsyncComponentWrapper", + __asyncLoader: load, + get __asyncResolved() { + return resolvedComp; + }, + setup() { + const instance = currentInstance; + if (resolvedComp) { + return () => createInnerComp(resolvedComp, instance); + } + const onError = (err) => { + pendingRequest = null; + handleError( + err, + instance, + 13, + !errorComponent + ); + }; + if (suspensible && instance.suspense || isInSSRComponentSetup) { + return load().then((comp) => { + return () => createInnerComp(comp, instance); + }).catch((err) => { + onError(err); + return () => errorComponent ? createVNode(errorComponent, { + error: err + }) : null; + }); + } + const loaded = ref(false); + const error = ref(); + const delayed = ref(!!delay); + if (delay) { + setTimeout(() => { + delayed.value = false; + }, delay); + } + if (timeout != null) { + setTimeout(() => { + if (!loaded.value && !error.value) { + const err = new Error( + `Async component timed out after ${timeout}ms.` + ); + onError(err); + error.value = err; + } + }, timeout); + } + load().then(() => { + loaded.value = true; + if (instance.parent && isKeepAlive(instance.parent.vnode)) { + instance.parent.effect.dirty = true; + queueJob(instance.parent.update); + } + }).catch((err) => { + onError(err); + error.value = err; + }); + return () => { + if (loaded.value && resolvedComp) { + return createInnerComp(resolvedComp, instance); + } else if (error.value && errorComponent) { + return createVNode(errorComponent, { + error: error.value + }); + } else if (loadingComponent && !delayed.value) { + return createVNode(loadingComponent); + } + }; + } + }); +} +function createInnerComp(comp, parent) { + const { ref: ref2, props, children, ce } = parent.vnode; + const vnode = createVNode(comp, props, children); + vnode.ref = ref2; + vnode.ce = ce; + delete parent.vnode.ce; + return vnode; +} +var isKeepAlive = (vnode) => vnode.type.__isKeepAlive; +var KeepAliveImpl = { + name: `KeepAlive`, + // Marker for special handling inside the renderer. We are not using a === + // check directly on KeepAlive in the renderer, because importing it directly + // would prevent it from being tree-shaken. + __isKeepAlive: true, + props: { + include: [String, RegExp, Array], + exclude: [String, RegExp, Array], + max: [String, Number] + }, + setup(props, { slots }) { + const instance = getCurrentInstance(); + const sharedContext = instance.ctx; + if (!sharedContext.renderer) { + return () => { + const children = slots.default && slots.default(); + return children && children.length === 1 ? children[0] : children; + }; + } + const cache = /* @__PURE__ */ new Map(); + const keys = /* @__PURE__ */ new Set(); + let current = null; + if (true) { + instance.__v_cache = cache; + } + const parentSuspense = instance.suspense; + const { + renderer: { + p: patch, + m: move, + um: _unmount, + o: { createElement } + } + } = sharedContext; + const storageContainer = createElement("div"); + sharedContext.activate = (vnode, container, anchor, namespace, optimized) => { + const instance2 = vnode.component; + move(vnode, container, anchor, 0, parentSuspense); + patch( + instance2.vnode, + vnode, + container, + anchor, + instance2, + parentSuspense, + namespace, + vnode.slotScopeIds, + optimized + ); + queuePostRenderEffect(() => { + instance2.isDeactivated = false; + if (instance2.a) { + invokeArrayFns(instance2.a); + } + const vnodeHook = vnode.props && vnode.props.onVnodeMounted; + if (vnodeHook) { + invokeVNodeHook(vnodeHook, instance2.parent, vnode); + } + }, parentSuspense); + if (true) { + devtoolsComponentAdded(instance2); + } + }; + sharedContext.deactivate = (vnode) => { + const instance2 = vnode.component; + move(vnode, storageContainer, null, 1, parentSuspense); + queuePostRenderEffect(() => { + if (instance2.da) { + invokeArrayFns(instance2.da); + } + const vnodeHook = vnode.props && vnode.props.onVnodeUnmounted; + if (vnodeHook) { + invokeVNodeHook(vnodeHook, instance2.parent, vnode); + } + instance2.isDeactivated = true; + }, parentSuspense); + if (true) { + devtoolsComponentAdded(instance2); + } + }; + function unmount(vnode) { + resetShapeFlag(vnode); + _unmount(vnode, instance, parentSuspense, true); + } + function pruneCache(filter) { + cache.forEach((vnode, key) => { + const name = getComponentName(vnode.type); + if (name && (!filter || !filter(name))) { + pruneCacheEntry(key); + } + }); + } + function pruneCacheEntry(key) { + const cached = cache.get(key); + if (!current || !isSameVNodeType(cached, current)) { + unmount(cached); + } else if (current) { + resetShapeFlag(current); + } + cache.delete(key); + keys.delete(key); + } + watch( + () => [props.include, props.exclude], + ([include, exclude]) => { + include && pruneCache((name) => matches(include, name)); + exclude && pruneCache((name) => !matches(exclude, name)); + }, + // prune post-render after `current` has been updated + { flush: "post", deep: true } + ); + let pendingCacheKey = null; + const cacheSubtree = () => { + if (pendingCacheKey != null) { + cache.set(pendingCacheKey, getInnerChild(instance.subTree)); + } + }; + onMounted(cacheSubtree); + onUpdated(cacheSubtree); + onBeforeUnmount(() => { + cache.forEach((cached) => { + const { subTree, suspense } = instance; + const vnode = getInnerChild(subTree); + if (cached.type === vnode.type && cached.key === vnode.key) { + resetShapeFlag(vnode); + const da = vnode.component.da; + da && queuePostRenderEffect(da, suspense); + return; + } + unmount(cached); + }); + }); + return () => { + pendingCacheKey = null; + if (!slots.default) { + return null; + } + const children = slots.default(); + const rawVNode = children[0]; + if (children.length > 1) { + if (true) { + warn$1(`KeepAlive should contain exactly one component child.`); + } + current = null; + return children; + } else if (!isVNode(rawVNode) || !(rawVNode.shapeFlag & 4) && !(rawVNode.shapeFlag & 128)) { + current = null; + return rawVNode; + } + let vnode = getInnerChild(rawVNode); + const comp = vnode.type; + const name = getComponentName( + isAsyncWrapper(vnode) ? vnode.type.__asyncResolved || {} : comp + ); + const { include, exclude, max } = props; + if (include && (!name || !matches(include, name)) || exclude && name && matches(exclude, name)) { + current = vnode; + return rawVNode; + } + const key = vnode.key == null ? comp : vnode.key; + const cachedVNode = cache.get(key); + if (vnode.el) { + vnode = cloneVNode(vnode); + if (rawVNode.shapeFlag & 128) { + rawVNode.ssContent = vnode; + } + } + pendingCacheKey = key; + if (cachedVNode) { + vnode.el = cachedVNode.el; + vnode.component = cachedVNode.component; + if (vnode.transition) { + setTransitionHooks(vnode, vnode.transition); + } + vnode.shapeFlag |= 512; + keys.delete(key); + keys.add(key); + } else { + keys.add(key); + if (max && keys.size > parseInt(max, 10)) { + pruneCacheEntry(keys.values().next().value); + } + } + vnode.shapeFlag |= 256; + current = vnode; + return isSuspense(rawVNode.type) ? rawVNode : vnode; + }; + } +}; +var KeepAlive = KeepAliveImpl; +function matches(pattern, name) { + if (isArray(pattern)) { + return pattern.some((p2) => matches(p2, name)); + } else if (isString(pattern)) { + return pattern.split(",").includes(name); + } else if (isRegExp(pattern)) { + return pattern.test(name); + } + return false; +} +function onActivated(hook, target) { + registerKeepAliveHook(hook, "a", target); +} +function onDeactivated(hook, target) { + registerKeepAliveHook(hook, "da", target); +} +function registerKeepAliveHook(hook, type, target = currentInstance) { + const wrappedHook = hook.__wdc || (hook.__wdc = () => { + let current = target; + while (current) { + if (current.isDeactivated) { + return; + } + current = current.parent; + } + return hook(); + }); + injectHook(type, wrappedHook, target); + if (target) { + let current = target.parent; + while (current && current.parent) { + if (isKeepAlive(current.parent.vnode)) { + injectToKeepAliveRoot(wrappedHook, type, target, current); + } + current = current.parent; + } + } +} +function injectToKeepAliveRoot(hook, type, target, keepAliveRoot) { + const injected = injectHook( + type, + hook, + keepAliveRoot, + true + /* prepend */ + ); + onUnmounted(() => { + remove(keepAliveRoot[type], injected); + }, target); +} +function resetShapeFlag(vnode) { + vnode.shapeFlag &= ~256; + vnode.shapeFlag &= ~512; +} +function getInnerChild(vnode) { + return vnode.shapeFlag & 128 ? vnode.ssContent : vnode; +} +function injectHook(type, hook, target = currentInstance, prepend = false) { + if (target) { + const hooks = target[type] || (target[type] = []); + const wrappedHook = hook.__weh || (hook.__weh = (...args) => { + if (target.isUnmounted) { + return; + } + pauseTracking(); + const reset = setCurrentInstance(target); + const res = callWithAsyncErrorHandling(hook, target, type, args); + reset(); + resetTracking(); + return res; + }); + if (prepend) { + hooks.unshift(wrappedHook); + } else { + hooks.push(wrappedHook); + } + return wrappedHook; + } else if (true) { + 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.` + ); + } +} +var createHook = (lifecycle) => (hook, target = currentInstance) => ( + // post-create lifecycle registrations are noops during SSR (except for serverPrefetch) + (!isInSSRComponentSetup || lifecycle === "sp") && injectHook(lifecycle, (...args) => hook(...args), target) +); +var onBeforeMount = createHook("bm"); +var onMounted = createHook("m"); +var onBeforeUpdate = createHook("bu"); +var onUpdated = createHook("u"); +var onBeforeUnmount = createHook("bum"); +var onUnmounted = createHook("um"); +var onServerPrefetch = createHook("sp"); +var onRenderTriggered = createHook( + "rtg" +); +var onRenderTracked = createHook( + "rtc" +); +function onErrorCaptured(hook, target = currentInstance) { + injectHook("ec", hook, target); +} +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 { + ret = []; + } + if (cache) { + cache[index] = ret; + } + return ret; +} +function createSlots(slots, dynamicSlots) { + for (let i = 0; i < dynamicSlots.length; i++) { + const slot = dynamicSlots[i]; + if (isArray(slot)) { + for (let j = 0; j < slot.length; j++) { + slots[slot[j].name] = slot[j].fn; + } + } else if (slot) { + slots[slot.name] = slot.key ? (...args) => { + const res = slot.fn(...args); + if (res) + res.key = slot.key; + return res; + } : slot.fn; + } + } + return slots; +} +function renderSlot(slots, name, props = {}, fallback, noSlotted) { + if (currentRenderingInstance.isCE || currentRenderingInstance.parent && isAsyncWrapper(currentRenderingInstance.parent) && currentRenderingInstance.parent.isCE) { + if (name !== "default") + props.name = name; + return createVNode("slot", props, fallback && fallback()); + } + let slot = slots[name]; + if (slot && slot.length > 1) { + 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 = () => []; + } + if (slot && slot._c) { + slot._d = false; + } + openBlock(); + const validSlotContent = slot && ensureValidVNode(slot(props)); + const rendered = createBlock( + Fragment, + { + key: props.key || // slot content array of a dynamic conditional slot may have a branch + // key attached in the `createSlots` helper, respect that + validSlotContent && validSlotContent.key || `_${name}` + }, + validSlotContent || (fallback ? fallback() : []), + validSlotContent && slots._ === 1 ? 64 : -2 + ); + if (!noSlotted && rendered.scopeId) { + rendered.slotScopeIds = [rendered.scopeId + "-s"]; + } + if (slot && slot._c) { + slot._d = true; + } + return rendered; +} +function ensureValidVNode(vnodes) { + return vnodes.some((child) => { + if (!isVNode(child)) + return true; + if (child.type === Comment) + return false; + if (child.type === Fragment && !ensureValidVNode(child.children)) + return false; + return true; + }) ? vnodes : null; +} +function toHandlers(obj, preserveCaseIfNecessary) { + const ret = {}; + if (!isObject(obj)) { + warn$1(`v-on with no argument expects an object value.`); + return ret; + } + for (const key in obj) { + ret[preserveCaseIfNecessary && /[A-Z]/.test(key) ? `on:${key}` : toHandlerKey(key)] = obj[key]; + } + return ret; +} +var getPublicInstance = (i) => { + if (!i) + return null; + if (isStatefulComponent(i)) + return getExposeProxy(i) || i.proxy; + return getPublicInstance(i.parent); +}; +var publicPropertiesMap = ( + // Move PURE marker to new line to workaround compiler discarding it + // due to type annotation + extend(/* @__PURE__ */ Object.create(null), { + $: (i) => i, + $el: (i) => i.vnode.el, + $data: (i) => i.data, + $props: (i) => true ? shallowReadonly(i.props) : i.props, + $attrs: (i) => true ? shallowReadonly(i.attrs) : i.attrs, + $slots: (i) => true ? shallowReadonly(i.slots) : i.slots, + $refs: (i) => true ? shallowReadonly(i.refs) : i.refs, + $parent: (i) => getPublicInstance(i.parent), + $root: (i) => getPublicInstance(i.root), + $emit: (i) => i.emit, + $options: (i) => __VUE_OPTIONS_API__ ? resolveMergedOptions(i) : i.type, + $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) => __VUE_OPTIONS_API__ ? instanceWatch.bind(i) : NOOP + }) +); +var isReservedPrefix = (key) => key === "_" || key === "$"; +var hasSetupBinding = (state, key) => state !== EMPTY_OBJ && !state.__isScriptSetup && hasOwn(state, key); +var PublicInstanceProxyHandlers = { + get({ _: instance }, key) { + const { ctx, setupState, data, props, accessCache, type, appContext } = instance; + if (key === "__isVue") { + return true; + } + let normalizedProps; + if (key[0] !== "$") { + const n = accessCache[key]; + if (n !== void 0) { + switch (n) { + case 1: + return setupState[key]; + case 2: + return data[key]; + case 4: + return ctx[key]; + case 3: + return props[key]; + } + } else if (hasSetupBinding(setupState, key)) { + accessCache[key] = 1; + return setupState[key]; + } else if (data !== EMPTY_OBJ && hasOwn(data, key)) { + accessCache[key] = 2; + return data[key]; + } else if ( + // only cache other properties when instance has declared (thus stable) + // props + (normalizedProps = instance.propsOptions[0]) && hasOwn(normalizedProps, key) + ) { + accessCache[key] = 3; + return props[key]; + } else if (ctx !== EMPTY_OBJ && hasOwn(ctx, key)) { + accessCache[key] = 4; + return ctx[key]; + } else if (!__VUE_OPTIONS_API__ || shouldCacheAccess) { + accessCache[key] = 0; + } + } + const publicGetter = publicPropertiesMap[key]; + let cssModule, globalProperties; + if (publicGetter) { + if (key === "$attrs") { + track(instance, "get", key); + markAttrsAccessed(); + } else if (key === "$slots") { + track(instance, "get", key); + } + return publicGetter(instance); + } else if ( + // css module (injected by vue-loader) + (cssModule = type.__cssModules) && (cssModule = cssModule[key]) + ) { + return cssModule; + } else if (ctx !== EMPTY_OBJ && hasOwn(ctx, key)) { + accessCache[key] = 4; + return ctx[key]; + } else if ( + // global properties + globalProperties = appContext.config.globalProperties, hasOwn(globalProperties, key) + ) { + { + return globalProperties[key]; + } + } else if (currentRenderingInstance && (!isString(key) || // #1091 avoid internal isRef/isVNode checks on component instance leading + // to infinite warning loop + key.indexOf("__v") !== 0)) { + if (data !== EMPTY_OBJ && isReservedPrefix(key[0]) && hasOwn(data, key)) { + 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$1( + `Property ${JSON.stringify(key)} was accessed during render but is not defined on instance.` + ); + } + } + }, + set({ _: instance }, key, value) { + const { data, setupState, ctx } = instance; + if (hasSetupBinding(setupState, key)) { + setupState[key] = value; + return true; + } else if (setupState.__isScriptSetup && hasOwn(setupState, key)) { + warn$1(`Cannot mutate + + + + + + + + +
Skip to content

404

PAGE NOT FOUND

But if you don't change your direction, and if you keep looking, you may end up where you are heading.
+ + + + \ No newline at end of file diff --git a/vitepress/docs/.vitepress/dist/assets/288755758-175ae9d7-3e6d-42ba-9b12-a1e89bf0df53.BLU9lmvg.png b/vitepress/docs/.vitepress/dist/assets/288755758-175ae9d7-3e6d-42ba-9b12-a1e89bf0df53.BLU9lmvg.png new file mode 100644 index 0000000..ac91d56 Binary files /dev/null and b/vitepress/docs/.vitepress/dist/assets/288755758-175ae9d7-3e6d-42ba-9b12-a1e89bf0df53.BLU9lmvg.png differ diff --git a/vitepress/docs/.vitepress/dist/assets/288759376-65fb76bd-40b8-4301-b292-a776ea55f17e.CSnjBM8e.png b/vitepress/docs/.vitepress/dist/assets/288759376-65fb76bd-40b8-4301-b292-a776ea55f17e.CSnjBM8e.png new file mode 100644 index 0000000..ec395ac Binary files /dev/null and b/vitepress/docs/.vitepress/dist/assets/288759376-65fb76bd-40b8-4301-b292-a776ea55f17e.CSnjBM8e.png differ diff --git a/vitepress/docs/.vitepress/dist/assets/289078069-79daecf4-41df-45e4-bdfd-34120ecb2d9b.DqQEPRQ3.png b/vitepress/docs/.vitepress/dist/assets/289078069-79daecf4-41df-45e4-bdfd-34120ecb2d9b.DqQEPRQ3.png new file mode 100644 index 0000000..7ad4527 Binary files /dev/null and b/vitepress/docs/.vitepress/dist/assets/289078069-79daecf4-41df-45e4-bdfd-34120ecb2d9b.DqQEPRQ3.png differ diff --git a/vitepress/docs/.vitepress/dist/assets/289086561-8042a459-ead2-4b1a-ba59-41b673d9b7d8.DDX45esF.png b/vitepress/docs/.vitepress/dist/assets/289086561-8042a459-ead2-4b1a-ba59-41b673d9b7d8.DDX45esF.png new file mode 100644 index 0000000..6f64661 Binary files /dev/null and b/vitepress/docs/.vitepress/dist/assets/289086561-8042a459-ead2-4b1a-ba59-41b673d9b7d8.DDX45esF.png differ diff --git a/vitepress/docs/.vitepress/dist/assets/289088717-bc864112-bd55-43b6-8369-9d78e896376e.CgwlTyfo.png b/vitepress/docs/.vitepress/dist/assets/289088717-bc864112-bd55-43b6-8369-9d78e896376e.CgwlTyfo.png new file mode 100644 index 0000000..45a6d80 Binary files /dev/null and b/vitepress/docs/.vitepress/dist/assets/289088717-bc864112-bd55-43b6-8369-9d78e896376e.CgwlTyfo.png differ diff --git a/vitepress/docs/.vitepress/dist/assets/289275766-33a7f3de-c80c-47db-b195-35cf25023b27.CVLMUrnd.png b/vitepress/docs/.vitepress/dist/assets/289275766-33a7f3de-c80c-47db-b195-35cf25023b27.CVLMUrnd.png new file mode 100644 index 0000000..a3b8429 Binary files /dev/null and b/vitepress/docs/.vitepress/dist/assets/289275766-33a7f3de-c80c-47db-b195-35cf25023b27.CVLMUrnd.png differ diff --git a/vitepress/docs/.vitepress/dist/assets/289276022-2b29397f-f3d1-41cb-a25c-84aff19487bf.DNIwmI-g.png b/vitepress/docs/.vitepress/dist/assets/289276022-2b29397f-f3d1-41cb-a25c-84aff19487bf.DNIwmI-g.png new file mode 100644 index 0000000..7ba7c8e Binary files /dev/null and b/vitepress/docs/.vitepress/dist/assets/289276022-2b29397f-f3d1-41cb-a25c-84aff19487bf.DNIwmI-g.png differ diff --git a/vitepress/docs/.vitepress/dist/assets/289277030-71da2fbe-ea92-48ae-b243-edf07876a7db.BSjnj2JO.png b/vitepress/docs/.vitepress/dist/assets/289277030-71da2fbe-ea92-48ae-b243-edf07876a7db.BSjnj2JO.png new file mode 100644 index 0000000..6f69954 Binary files /dev/null and b/vitepress/docs/.vitepress/dist/assets/289277030-71da2fbe-ea92-48ae-b243-edf07876a7db.BSjnj2JO.png differ diff --git a/vitepress/docs/.vitepress/dist/assets/289311225-21b28d91-4031-4e02-bbcd-0232c1c24a16.BzZG4-5V.png b/vitepress/docs/.vitepress/dist/assets/289311225-21b28d91-4031-4e02-bbcd-0232c1c24a16.BzZG4-5V.png new file mode 100644 index 0000000..6be3da7 Binary files /dev/null and b/vitepress/docs/.vitepress/dist/assets/289311225-21b28d91-4031-4e02-bbcd-0232c1c24a16.BzZG4-5V.png differ diff --git a/vitepress/docs/.vitepress/dist/assets/290205035-be5d7e97-b86c-4a0f-94d3-673886cc49a3.wE_Ms7Jv.png b/vitepress/docs/.vitepress/dist/assets/290205035-be5d7e97-b86c-4a0f-94d3-673886cc49a3.wE_Ms7Jv.png new file mode 100644 index 0000000..543a8b1 Binary files /dev/null and b/vitepress/docs/.vitepress/dist/assets/290205035-be5d7e97-b86c-4a0f-94d3-673886cc49a3.wE_Ms7Jv.png differ diff --git a/vitepress/docs/.vitepress/dist/assets/290218954-e41f72f9-dabc-4735-a4df-ab3260c30f3f.09D_xvWf.png b/vitepress/docs/.vitepress/dist/assets/290218954-e41f72f9-dabc-4735-a4df-ab3260c30f3f.09D_xvWf.png new file mode 100644 index 0000000..780974e Binary files /dev/null and b/vitepress/docs/.vitepress/dist/assets/290218954-e41f72f9-dabc-4735-a4df-ab3260c30f3f.09D_xvWf.png differ diff --git a/vitepress/docs/.vitepress/dist/assets/290220401-8f9b33a4-3f00-4caf-9be3-2d06a10584a5.BMzNTl1l.png b/vitepress/docs/.vitepress/dist/assets/290220401-8f9b33a4-3f00-4caf-9be3-2d06a10584a5.BMzNTl1l.png new file mode 100644 index 0000000..608fd2a Binary files /dev/null and b/vitepress/docs/.vitepress/dist/assets/290220401-8f9b33a4-3f00-4caf-9be3-2d06a10584a5.BMzNTl1l.png differ diff --git a/vitepress/docs/.vitepress/dist/assets/290225173-8c00a858-3507-4de4-84e0-536c094532f8.GQqlKtKq.png b/vitepress/docs/.vitepress/dist/assets/290225173-8c00a858-3507-4de4-84e0-536c094532f8.GQqlKtKq.png new file mode 100644 index 0000000..0985c96 Binary files /dev/null and b/vitepress/docs/.vitepress/dist/assets/290225173-8c00a858-3507-4de4-84e0-536c094532f8.GQqlKtKq.png differ diff --git a/vitepress/docs/.vitepress/dist/assets/290225251-23ad63ff-3ee2-4767-a7c0-438cc2c20ece.VCEr0iJR.png b/vitepress/docs/.vitepress/dist/assets/290225251-23ad63ff-3ee2-4767-a7c0-438cc2c20ece.VCEr0iJR.png new file mode 100644 index 0000000..b27be64 Binary files /dev/null and b/vitepress/docs/.vitepress/dist/assets/290225251-23ad63ff-3ee2-4767-a7c0-438cc2c20ece.VCEr0iJR.png differ diff --git a/vitepress/docs/.vitepress/dist/assets/291728755-273dca85-faa0-47ae-91df-cadf50a8d93c.85Xk1nI_.png b/vitepress/docs/.vitepress/dist/assets/291728755-273dca85-faa0-47ae-91df-cadf50a8d93c.85Xk1nI_.png new file mode 100644 index 0000000..a6f18ae Binary files /dev/null and b/vitepress/docs/.vitepress/dist/assets/291728755-273dca85-faa0-47ae-91df-cadf50a8d93c.85Xk1nI_.png differ diff --git a/vitepress/docs/.vitepress/dist/assets/291729573-749ebf4e-e79c-40ba-aba4-d53d68980d2e.DjW8FgZr.png b/vitepress/docs/.vitepress/dist/assets/291729573-749ebf4e-e79c-40ba-aba4-d53d68980d2e.DjW8FgZr.png new file mode 100644 index 0000000..cec9143 Binary files /dev/null and b/vitepress/docs/.vitepress/dist/assets/291729573-749ebf4e-e79c-40ba-aba4-d53d68980d2e.DjW8FgZr.png differ diff --git a/vitepress/docs/.vitepress/dist/assets/291729726-29d54dfe-1e52-4825-a725-72ef104637f6.Dml7mBnh.png b/vitepress/docs/.vitepress/dist/assets/291729726-29d54dfe-1e52-4825-a725-72ef104637f6.Dml7mBnh.png new file mode 100644 index 0000000..36326a7 Binary files /dev/null and b/vitepress/docs/.vitepress/dist/assets/291729726-29d54dfe-1e52-4825-a725-72ef104637f6.Dml7mBnh.png differ diff --git a/vitepress/docs/.vitepress/dist/assets/291731440-2a8a10d3-4846-4c5a-8596-b4fcd74b8557.BdPjwJSF.png b/vitepress/docs/.vitepress/dist/assets/291731440-2a8a10d3-4846-4c5a-8596-b4fcd74b8557.BdPjwJSF.png new file mode 100644 index 0000000..1f8a86f Binary files /dev/null and b/vitepress/docs/.vitepress/dist/assets/291731440-2a8a10d3-4846-4c5a-8596-b4fcd74b8557.BdPjwJSF.png differ diff --git a/vitepress/docs/.vitepress/dist/assets/292773723-4e84051a-1fec-4af3-9247-f77801e5cf2f.DPH5HlJX.png b/vitepress/docs/.vitepress/dist/assets/292773723-4e84051a-1fec-4af3-9247-f77801e5cf2f.DPH5HlJX.png new file mode 100644 index 0000000..98b5acd Binary files /dev/null and b/vitepress/docs/.vitepress/dist/assets/292773723-4e84051a-1fec-4af3-9247-f77801e5cf2f.DPH5HlJX.png differ diff --git a/vitepress/docs/.vitepress/dist/assets/292774360-4866ca27-dcd8-44d5-bc7f-d5cc864c7569.DlhRBBRV.png b/vitepress/docs/.vitepress/dist/assets/292774360-4866ca27-dcd8-44d5-bc7f-d5cc864c7569.DlhRBBRV.png new file mode 100644 index 0000000..361c421 Binary files /dev/null and b/vitepress/docs/.vitepress/dist/assets/292774360-4866ca27-dcd8-44d5-bc7f-d5cc864c7569.DlhRBBRV.png differ diff --git a/vitepress/docs/.vitepress/dist/assets/292776696-6843784a-f791-4bd5-ab46-4ff7474071a4.B3kSNbXp.png b/vitepress/docs/.vitepress/dist/assets/292776696-6843784a-f791-4bd5-ab46-4ff7474071a4.B3kSNbXp.png new file mode 100644 index 0000000..ea0a944 Binary files /dev/null and b/vitepress/docs/.vitepress/dist/assets/292776696-6843784a-f791-4bd5-ab46-4ff7474071a4.B3kSNbXp.png differ diff --git a/vitepress/docs/.vitepress/dist/assets/292776780-7a00c116-9d7b-447f-a495-06d36b22412a.jMbfBvi5.png b/vitepress/docs/.vitepress/dist/assets/292776780-7a00c116-9d7b-447f-a495-06d36b22412a.jMbfBvi5.png new file mode 100644 index 0000000..44e753d Binary files /dev/null and b/vitepress/docs/.vitepress/dist/assets/292776780-7a00c116-9d7b-447f-a495-06d36b22412a.jMbfBvi5.png differ diff --git a/vitepress/docs/.vitepress/dist/assets/292776889-1c43a42c-e7d9-4023-ba05-acdc68054c4d.B3lF5OxB.png b/vitepress/docs/.vitepress/dist/assets/292776889-1c43a42c-e7d9-4023-ba05-acdc68054c4d.B3lF5OxB.png new file mode 100644 index 0000000..4bd520d Binary files /dev/null and b/vitepress/docs/.vitepress/dist/assets/292776889-1c43a42c-e7d9-4023-ba05-acdc68054c4d.B3lF5OxB.png differ diff --git a/vitepress/docs/.vitepress/dist/assets/292777024-b01e455d-d2d3-435e-9208-6b8fc11c3afb.Dcc4DmSJ.png b/vitepress/docs/.vitepress/dist/assets/292777024-b01e455d-d2d3-435e-9208-6b8fc11c3afb.Dcc4DmSJ.png new file mode 100644 index 0000000..9778bde Binary files /dev/null and b/vitepress/docs/.vitepress/dist/assets/292777024-b01e455d-d2d3-435e-9208-6b8fc11c3afb.Dcc4DmSJ.png differ diff --git a/vitepress/docs/.vitepress/dist/assets/292777301-a9a5c486-b7e3-4f15-964d-678cc622e8d7.Cy5Owgdo.png b/vitepress/docs/.vitepress/dist/assets/292777301-a9a5c486-b7e3-4f15-964d-678cc622e8d7.Cy5Owgdo.png new file mode 100644 index 0000000..4b3164d Binary files /dev/null and b/vitepress/docs/.vitepress/dist/assets/292777301-a9a5c486-b7e3-4f15-964d-678cc622e8d7.Cy5Owgdo.png differ diff --git a/vitepress/docs/.vitepress/dist/assets/292777538-c0bbee71-c62d-4873-8d20-e04598d39a8a.Bg_JNI9Y.png b/vitepress/docs/.vitepress/dist/assets/292777538-c0bbee71-c62d-4873-8d20-e04598d39a8a.Bg_JNI9Y.png new file mode 100644 index 0000000..fe5d0b4 Binary files /dev/null and b/vitepress/docs/.vitepress/dist/assets/292777538-c0bbee71-c62d-4873-8d20-e04598d39a8a.Bg_JNI9Y.png differ diff --git a/vitepress/docs/.vitepress/dist/assets/292777602-6f4ee12a-ddac-4dfb-9516-c093cc9282f0.CXjiaS2U.png b/vitepress/docs/.vitepress/dist/assets/292777602-6f4ee12a-ddac-4dfb-9516-c093cc9282f0.CXjiaS2U.png new file mode 100644 index 0000000..b8d1655 Binary files /dev/null and b/vitepress/docs/.vitepress/dist/assets/292777602-6f4ee12a-ddac-4dfb-9516-c093cc9282f0.CXjiaS2U.png differ diff --git a/vitepress/docs/.vitepress/dist/assets/292777671-998be8d3-8e5f-4541-a938-0b3c016991ea.Br2fgusV.png b/vitepress/docs/.vitepress/dist/assets/292777671-998be8d3-8e5f-4541-a938-0b3c016991ea.Br2fgusV.png new file mode 100644 index 0000000..164a73a Binary files /dev/null and b/vitepress/docs/.vitepress/dist/assets/292777671-998be8d3-8e5f-4541-a938-0b3c016991ea.Br2fgusV.png differ diff --git a/vitepress/docs/.vitepress/dist/assets/294049976-589c99ab-cfb1-4274-bdea-e1c6c630adee.JemQ_fhc.png b/vitepress/docs/.vitepress/dist/assets/294049976-589c99ab-cfb1-4274-bdea-e1c6c630adee.JemQ_fhc.png new file mode 100644 index 0000000..4ee3006 Binary files /dev/null and b/vitepress/docs/.vitepress/dist/assets/294049976-589c99ab-cfb1-4274-bdea-e1c6c630adee.JemQ_fhc.png differ diff --git a/vitepress/docs/.vitepress/dist/assets/294050118-afc6df54-903b-4821-8e0d-e57a396d126f.DCWfcER7.png b/vitepress/docs/.vitepress/dist/assets/294050118-afc6df54-903b-4821-8e0d-e57a396d126f.DCWfcER7.png new file mode 100644 index 0000000..9cfb491 Binary files /dev/null and b/vitepress/docs/.vitepress/dist/assets/294050118-afc6df54-903b-4821-8e0d-e57a396d126f.DCWfcER7.png differ diff --git a/vitepress/docs/.vitepress/dist/assets/294050559-b6bcc0f9-8745-4ead-ac9b-98a7cf92ef38.70zhE0u1.png b/vitepress/docs/.vitepress/dist/assets/294050559-b6bcc0f9-8745-4ead-ac9b-98a7cf92ef38.70zhE0u1.png new file mode 100644 index 0000000..c6b8459 Binary files /dev/null and b/vitepress/docs/.vitepress/dist/assets/294050559-b6bcc0f9-8745-4ead-ac9b-98a7cf92ef38.70zhE0u1.png differ diff --git a/vitepress/docs/.vitepress/dist/assets/294185554-0a53d571-a6d4-4d9c-8473-e1a497cb4771.BlrqqiBi.png b/vitepress/docs/.vitepress/dist/assets/294185554-0a53d571-a6d4-4d9c-8473-e1a497cb4771.BlrqqiBi.png new file mode 100644 index 0000000..cbb31a0 Binary files /dev/null and b/vitepress/docs/.vitepress/dist/assets/294185554-0a53d571-a6d4-4d9c-8473-e1a497cb4771.BlrqqiBi.png differ diff --git a/vitepress/docs/.vitepress/dist/assets/294203476-c38ee8dd-d990-491b-ac01-5940b5237aeb.BC4ZRAsI.png b/vitepress/docs/.vitepress/dist/assets/294203476-c38ee8dd-d990-491b-ac01-5940b5237aeb.BC4ZRAsI.png new file mode 100644 index 0000000..85b7cb3 Binary files /dev/null and b/vitepress/docs/.vitepress/dist/assets/294203476-c38ee8dd-d990-491b-ac01-5940b5237aeb.BC4ZRAsI.png differ diff --git a/vitepress/docs/.vitepress/dist/assets/294206249-2c01dacd-b0e9-4160-8f63-01d73c758f9b.VTgm5Fcw.png b/vitepress/docs/.vitepress/dist/assets/294206249-2c01dacd-b0e9-4160-8f63-01d73c758f9b.VTgm5Fcw.png new file mode 100644 index 0000000..55b6134 Binary files /dev/null and b/vitepress/docs/.vitepress/dist/assets/294206249-2c01dacd-b0e9-4160-8f63-01d73c758f9b.VTgm5Fcw.png differ diff --git a/vitepress/docs/.vitepress/dist/assets/294212416-ca6367a9-3d9d-46f2-bb61-8683320171dc.Daxz8nah.png b/vitepress/docs/.vitepress/dist/assets/294212416-ca6367a9-3d9d-46f2-bb61-8683320171dc.Daxz8nah.png new file mode 100644 index 0000000..7e1d025 Binary files /dev/null and b/vitepress/docs/.vitepress/dist/assets/294212416-ca6367a9-3d9d-46f2-bb61-8683320171dc.Daxz8nah.png differ diff --git a/vitepress/docs/.vitepress/dist/assets/298200622-2dd8fd0b-c69c-41c3-a787-87e4f7ffe95c.GYWIUQtH.png b/vitepress/docs/.vitepress/dist/assets/298200622-2dd8fd0b-c69c-41c3-a787-87e4f7ffe95c.GYWIUQtH.png new file mode 100644 index 0000000..7ffc3b2 Binary files /dev/null and b/vitepress/docs/.vitepress/dist/assets/298200622-2dd8fd0b-c69c-41c3-a787-87e4f7ffe95c.GYWIUQtH.png differ diff --git a/vitepress/docs/.vitepress/dist/assets/307929568-c4514d57-633d-48d7-acd8-85b15c785dee.BSCw5qYK.png b/vitepress/docs/.vitepress/dist/assets/307929568-c4514d57-633d-48d7-acd8-85b15c785dee.BSCw5qYK.png new file mode 100644 index 0000000..962c0b7 Binary files /dev/null and b/vitepress/docs/.vitepress/dist/assets/307929568-c4514d57-633d-48d7-acd8-85b15c785dee.BSCw5qYK.png differ diff --git a/vitepress/docs/.vitepress/dist/assets/309739868-01361acc-6dcc-4519-a990-1e00dd02c666.HXoiJ2NJ.png b/vitepress/docs/.vitepress/dist/assets/309739868-01361acc-6dcc-4519-a990-1e00dd02c666.HXoiJ2NJ.png new file mode 100644 index 0000000..61d356e Binary files /dev/null and b/vitepress/docs/.vitepress/dist/assets/309739868-01361acc-6dcc-4519-a990-1e00dd02c666.HXoiJ2NJ.png differ diff --git a/vitepress/docs/.vitepress/dist/assets/309740243-cc8fe788-5dbb-40ee-aceb-aa74e4ed643b.BN1YkZEd.png b/vitepress/docs/.vitepress/dist/assets/309740243-cc8fe788-5dbb-40ee-aceb-aa74e4ed643b.BN1YkZEd.png new file mode 100644 index 0000000..e6b2afd Binary files /dev/null and b/vitepress/docs/.vitepress/dist/assets/309740243-cc8fe788-5dbb-40ee-aceb-aa74e4ed643b.BN1YkZEd.png differ diff --git a/vitepress/docs/.vitepress/dist/assets/312113267-388b181e-16bd-4444-a586-8efcfe5e5da4.Bzix7piI.png b/vitepress/docs/.vitepress/dist/assets/312113267-388b181e-16bd-4444-a586-8efcfe5e5da4.Bzix7piI.png new file mode 100644 index 0000000..9ee1131 Binary files /dev/null and b/vitepress/docs/.vitepress/dist/assets/312113267-388b181e-16bd-4444-a586-8efcfe5e5da4.Bzix7piI.png differ diff --git a/vitepress/docs/.vitepress/dist/assets/312120479-2e3ad0ad-158e-44f9-9380-766c60734ef3.xCg6zAM_.png b/vitepress/docs/.vitepress/dist/assets/312120479-2e3ad0ad-158e-44f9-9380-766c60734ef3.xCg6zAM_.png new file mode 100644 index 0000000..81e9548 Binary files /dev/null and b/vitepress/docs/.vitepress/dist/assets/312120479-2e3ad0ad-158e-44f9-9380-766c60734ef3.xCg6zAM_.png differ diff --git a/vitepress/docs/.vitepress/dist/assets/312123307-6526427d-5ece-4ed1-b980-a84cfb4b2ff1.D4k-Dzkc.png b/vitepress/docs/.vitepress/dist/assets/312123307-6526427d-5ece-4ed1-b980-a84cfb4b2ff1.D4k-Dzkc.png new file mode 100644 index 0000000..8d5e905 Binary files /dev/null and b/vitepress/docs/.vitepress/dist/assets/312123307-6526427d-5ece-4ed1-b980-a84cfb4b2ff1.D4k-Dzkc.png differ diff --git a/vitepress/docs/.vitepress/dist/assets/312123621-2ed9b518-98c0-4a67-85f2-5524997c72d9.Clk86AQj.png b/vitepress/docs/.vitepress/dist/assets/312123621-2ed9b518-98c0-4a67-85f2-5524997c72d9.Clk86AQj.png new file mode 100644 index 0000000..1098cf0 Binary files /dev/null and b/vitepress/docs/.vitepress/dist/assets/312123621-2ed9b518-98c0-4a67-85f2-5524997c72d9.Clk86AQj.png differ diff --git a/vitepress/docs/.vitepress/dist/assets/312123846-8e11055e-5ac9-4da6-a9da-cd4d854a3779.DkRh_3BN.png b/vitepress/docs/.vitepress/dist/assets/312123846-8e11055e-5ac9-4da6-a9da-cd4d854a3779.DkRh_3BN.png new file mode 100644 index 0000000..1f03d8c Binary files /dev/null and b/vitepress/docs/.vitepress/dist/assets/312123846-8e11055e-5ac9-4da6-a9da-cd4d854a3779.DkRh_3BN.png differ diff --git a/vitepress/docs/.vitepress/dist/assets/313493455-1a5c12f5-6368-4675-af20-051a7cb2598b.CjOJ3DU1.png b/vitepress/docs/.vitepress/dist/assets/313493455-1a5c12f5-6368-4675-af20-051a7cb2598b.CjOJ3DU1.png new file mode 100644 index 0000000..a5d190a Binary files /dev/null and b/vitepress/docs/.vitepress/dist/assets/313493455-1a5c12f5-6368-4675-af20-051a7cb2598b.CjOJ3DU1.png differ diff --git a/vitepress/docs/.vitepress/dist/assets/313493538-f05df190-b27f-4511-8554-ee5dc86efcb2.DAi3nME1.png b/vitepress/docs/.vitepress/dist/assets/313493538-f05df190-b27f-4511-8554-ee5dc86efcb2.DAi3nME1.png new file mode 100644 index 0000000..320a1b9 Binary files /dev/null and b/vitepress/docs/.vitepress/dist/assets/313493538-f05df190-b27f-4511-8554-ee5dc86efcb2.DAi3nME1.png differ diff --git a/vitepress/docs/.vitepress/dist/assets/313495844-578b6da9-b01c-4b00-a7fb-9bd4be45b912.wiOJK8eL.png b/vitepress/docs/.vitepress/dist/assets/313495844-578b6da9-b01c-4b00-a7fb-9bd4be45b912.wiOJK8eL.png new file mode 100644 index 0000000..e47b109 Binary files /dev/null and b/vitepress/docs/.vitepress/dist/assets/313495844-578b6da9-b01c-4b00-a7fb-9bd4be45b912.wiOJK8eL.png differ diff --git a/vitepress/docs/.vitepress/dist/assets/313500818-99069c93-a869-4b6e-bb50-b101c0c029ad.C5DJ4UvH.png b/vitepress/docs/.vitepress/dist/assets/313500818-99069c93-a869-4b6e-bb50-b101c0c029ad.C5DJ4UvH.png new file mode 100644 index 0000000..0903890 Binary files /dev/null and b/vitepress/docs/.vitepress/dist/assets/313500818-99069c93-a869-4b6e-bb50-b101c0c029ad.C5DJ4UvH.png differ diff --git a/vitepress/docs/.vitepress/dist/assets/313507258-a79717d3-36f2-41a5-b120-dd2bc51232eb.DP5RsCfL.png b/vitepress/docs/.vitepress/dist/assets/313507258-a79717d3-36f2-41a5-b120-dd2bc51232eb.DP5RsCfL.png new file mode 100644 index 0000000..e4089ad Binary files /dev/null and b/vitepress/docs/.vitepress/dist/assets/313507258-a79717d3-36f2-41a5-b120-dd2bc51232eb.DP5RsCfL.png differ diff --git a/vitepress/docs/.vitepress/dist/assets/313507304-f06738b3-4be6-4734-8bea-1f87556a0df3.CxBYw3G2.png b/vitepress/docs/.vitepress/dist/assets/313507304-f06738b3-4be6-4734-8bea-1f87556a0df3.CxBYw3G2.png new file mode 100644 index 0000000..d0c326a Binary files /dev/null and b/vitepress/docs/.vitepress/dist/assets/313507304-f06738b3-4be6-4734-8bea-1f87556a0df3.CxBYw3G2.png differ diff --git a/vitepress/docs/.vitepress/dist/assets/313508003-11f8175a-c432-4050-91e5-88b84a5d726b.Dw_qJO7t.png b/vitepress/docs/.vitepress/dist/assets/313508003-11f8175a-c432-4050-91e5-88b84a5d726b.Dw_qJO7t.png new file mode 100644 index 0000000..0504cd8 Binary files /dev/null and b/vitepress/docs/.vitepress/dist/assets/313508003-11f8175a-c432-4050-91e5-88b84a5d726b.Dw_qJO7t.png differ diff --git a/vitepress/docs/.vitepress/dist/assets/321053647-821ddb0c-400a-4139-8e72-56f6ed73743c.vAP2jue7.png b/vitepress/docs/.vitepress/dist/assets/321053647-821ddb0c-400a-4139-8e72-56f6ed73743c.vAP2jue7.png new file mode 100644 index 0000000..5e59173 Binary files /dev/null and b/vitepress/docs/.vitepress/dist/assets/321053647-821ddb0c-400a-4139-8e72-56f6ed73743c.vAP2jue7.png differ diff --git a/vitepress/docs/.vitepress/dist/assets/321053704-feda8ef3-32b9-484c-8413-23d09d8d08d3.xRS3UhYx.png b/vitepress/docs/.vitepress/dist/assets/321053704-feda8ef3-32b9-484c-8413-23d09d8d08d3.xRS3UhYx.png new file mode 100644 index 0000000..aa8db8c Binary files /dev/null and b/vitepress/docs/.vitepress/dist/assets/321053704-feda8ef3-32b9-484c-8413-23d09d8d08d3.xRS3UhYx.png differ diff --git a/vitepress/docs/.vitepress/dist/assets/321054351-b9a3e3bb-5c9b-43a7-9819-f638fbfa64a9.DYWMGxS_.png b/vitepress/docs/.vitepress/dist/assets/321054351-b9a3e3bb-5c9b-43a7-9819-f638fbfa64a9.DYWMGxS_.png new file mode 100644 index 0000000..960c16c Binary files /dev/null and b/vitepress/docs/.vitepress/dist/assets/321054351-b9a3e3bb-5c9b-43a7-9819-f638fbfa64a9.DYWMGxS_.png differ diff --git a/vitepress/docs/.vitepress/dist/assets/321064922-2e21e8bb-a216-416b-9690-09a883198c52.BoFCh8E9.png b/vitepress/docs/.vitepress/dist/assets/321064922-2e21e8bb-a216-416b-9690-09a883198c52.BoFCh8E9.png new file mode 100644 index 0000000..f17d2da Binary files /dev/null and b/vitepress/docs/.vitepress/dist/assets/321064922-2e21e8bb-a216-416b-9690-09a883198c52.BoFCh8E9.png differ diff --git a/vitepress/docs/.vitepress/dist/assets/PerfUtil-38a2ddbf1777887d70563a644c72aa64.Bzv4J9fN.png b/vitepress/docs/.vitepress/dist/assets/PerfUtil-38a2ddbf1777887d70563a644c72aa64.Bzv4J9fN.png new file mode 100644 index 0000000..c37353d Binary files /dev/null and b/vitepress/docs/.vitepress/dist/assets/PerfUtil-38a2ddbf1777887d70563a644c72aa64.Bzv4J9fN.png differ diff --git a/vitepress/docs/.vitepress/dist/assets/ReactDevToolsConnection-2fcfc362befab4699fd8afceefa5903e.8_VLXZ0K.gif b/vitepress/docs/.vitepress/dist/assets/ReactDevToolsConnection-2fcfc362befab4699fd8afceefa5903e.8_VLXZ0K.gif new file mode 100644 index 0000000..55947bd Binary files /dev/null and b/vitepress/docs/.vitepress/dist/assets/ReactDevToolsConnection-2fcfc362befab4699fd8afceefa5903e.8_VLXZ0K.gif differ diff --git a/vitepress/docs/.vitepress/dist/assets/ReactDevToolsInspector-fed7286dac8ef8a793245cdd9d3d0f9c.DAvzAGx1.gif b/vitepress/docs/.vitepress/dist/assets/ReactDevToolsInspector-fed7286dac8ef8a793245cdd9d3d0f9c.DAvzAGx1.gif new file mode 100644 index 0000000..b4b9144 Binary files /dev/null and b/vitepress/docs/.vitepress/dist/assets/ReactDevToolsInspector-fed7286dac8ef8a793245cdd9d3d0f9c.DAvzAGx1.gif differ diff --git a/vitepress/docs/.vitepress/dist/assets/app.C8dk6id_.js b/vitepress/docs/.vitepress/dist/assets/app.C8dk6id_.js new file mode 100644 index 0000000..bc0f559 --- /dev/null +++ b/vitepress/docs/.vitepress/dist/assets/app.C8dk6id_.js @@ -0,0 +1,7 @@ +function __vite__mapDeps(indexes) { + if (!__vite__mapDeps.viteFileDeps) { + __vite__mapDeps.viteFileDeps = [] + } + return indexes.map((i) => __vite__mapDeps.viteFileDeps[i]) +} +import{j as o,a5 as p,a6 as u,a7 as l,a8 as c,a9 as f,aa as d,ab as m,ac as h,ad as g,ae as A,Y as P,d as _,u as v,l as y,z as C,af as E,ag as b,ah as w,ai as R}from"./chunks/framework.nQaBHiNx.js";import{t as S}from"./chunks/theme.Dx0ZSJLU.js";function i(e){if(e.extends){const a=i(e.extends);return{...a,...e,async enhanceApp(t){a.enhanceApp&&await a.enhanceApp(t),e.enhanceApp&&await e.enhanceApp(t)}}}return e}const s=i(S),T=_({name:"VitePressApp",setup(){const{site:e,lang:a,dir:t}=v();return y(()=>{C(()=>{document.documentElement.lang=a.value,document.documentElement.dir=t.value})}),e.value.router.prefetchLinks&&E(),b(),w(),s.setup&&s.setup(),()=>R(s.Layout)}});async function D(){globalThis.__VITEPRESS__=!0;const e=L(),a=j();a.provide(u,e);const t=l(e.route);return a.provide(c,t),a.component("Content",f),a.component("ClientOnly",d),Object.defineProperties(a.config.globalProperties,{$frontmatter:{get(){return t.frontmatter.value}},$params:{get(){return t.page.value.params}}}),s.enhanceApp&&await s.enhanceApp({app:a,router:e,siteData:m}),{app:a,router:e,data:t}}function j(){return h(T)}function L(){let e=o,a;return g(t=>{let n=A(t),r=null;return n&&(e&&(a=n),(e||a===n)&&(n=n.replace(/\.js$/,".lean.js")),r=P(()=>import(n),__vite__mapDeps([]))),o&&(e=!1),r},s.NotFound)}o&&D().then(({app:e,router:a,data:t})=>{a.go().then(()=>{p(a.route,t.site),e.mount("#app")})});export{D as createApp}; diff --git a/vitepress/docs/.vitepress/dist/assets/async-on-layout.BrDeWvQE.gif b/vitepress/docs/.vitepress/dist/assets/async-on-layout.BrDeWvQE.gif new file mode 100644 index 0000000..82fa165 Binary files /dev/null and b/vitepress/docs/.vitepress/dist/assets/async-on-layout.BrDeWvQE.gif differ diff --git a/vitepress/docs/.vitepress/dist/assets/chunks/289088717-bc864112-bd55-43b6-8369-9d78e896376e.CT8xxMv0.js b/vitepress/docs/.vitepress/dist/assets/chunks/289088717-bc864112-bd55-43b6-8369-9d78e896376e.CT8xxMv0.js new file mode 100644 index 0000000..7f1d5b0 --- /dev/null +++ b/vitepress/docs/.vitepress/dist/assets/chunks/289088717-bc864112-bd55-43b6-8369-9d78e896376e.CT8xxMv0.js @@ -0,0 +1 @@ +const s="/assets/289088717-bc864112-bd55-43b6-8369-9d78e896376e.CgwlTyfo.png";export{s as _}; diff --git a/vitepress/docs/.vitepress/dist/assets/chunks/@localSearchIndexroot.BSIqPQjv.js b/vitepress/docs/.vitepress/dist/assets/chunks/@localSearchIndexroot.BSIqPQjv.js new file mode 100644 index 0000000..4254b08 --- /dev/null +++ b/vitepress/docs/.vitepress/dist/assets/chunks/@localSearchIndexroot.BSIqPQjv.js @@ -0,0 +1 @@ +const e='{"documentCount":770,"nextId":770,"documentIds":{"0":"/docs/accessibility.html#acessibilidade","1":"/docs/accessibility.html#propriedades-de-acessibilidade","2":"/docs/accessibility.html#accessible","3":"/docs/accessibility.html#accessibilitylabel","4":"/docs/accessibility.html#accessibilitylabelledby-android","5":"/docs/accessibility.html#accessibilityhint","6":"/docs/accessibility.html#ios","7":"/docs/accessibility.html#android","8":"/docs/accessibility.html#accessibilitylanguage-ios","9":"/docs/accessibility.html#acessibilidadeignoresinvertcolors-ios","10":"/docs/accessibility.html#accessibilityliveregion-android","11":"/docs/accessibility.html#accessibilityrole","12":"/docs/accessibility.html#accessibilitystate","13":"/docs/accessibility.html#accessibilityvalue","14":"/docs/accessibility.html#accessibilityviewismodal-ios","15":"/docs/accessibility.html#accessibilityelementshidden-ios","16":"/docs/accessibility.html#aria-valuemax","17":"/docs/accessibility.html#aria-valuemin","18":"/docs/accessibility.html#aria-valuenow","19":"/docs/accessibility.html#aria-valuetext","20":"/docs/accessibility.html#aria-busy","21":"/docs/accessibility.html#aria-checked","22":"/docs/accessibility.html#aria-disabled","23":"/docs/accessibility.html#aria-expanded","24":"/docs/accessibility.html#aria-hidden","25":"/docs/accessibility.html#aria-label","26":"/docs/accessibility.html#aria-labelledby-android","27":"/docs/accessibility.html#aria-live-android","28":"/docs/accessibility.html#aria-modal-ios","29":"/docs/accessibility.html#aria-selected","30":"/docs/accessibility.html#importantforaccessibility-android","31":"/docs/accessibility.html#onaccessibilityescape-ios","32":"/docs/accessibility.html#onaccessibilitytap","33":"/docs/accessibility.html#onmagictap-ios","34":"/docs/accessibility.html#role","35":"/docs/accessibility.html#acoes-de-acessibilidade","36":"/docs/accessibility.html#verificando-se-um-leitor-de-tela-esta-ativado","37":"/docs/accessibility.html#envio-de-eventos-de-acessibilidade-android-android","38":"/docs/accessibility.html#testando-o-suporte-do-talkback-android","39":"/docs/accessibility.html#testando-o-suporte-do-voiceover-ios","40":"/docs/accessibility.html#recursos-adicionais","41":"/docs/app-extensions.html#extensoes-de-aplicativos","42":"/docs/app-extensions.html#uso-de-memoria-em-extensoes","43":"/docs/app-extensions.html#widget-today","44":"/docs/app-extensions.html#outras-extensoes-de-aplicativos","45":"/docs/animations.html#animacoes","46":"/docs/animations.html#animated-api","47":"/docs/animations.html#configurando-animacoes","48":"/docs/animations.html#compondo-animacoes","49":"/docs/animations.html#combinando-valores-animados","50":"/docs/animations.html#interpolacao","51":"/docs/animations.html#rastreando-valores-dinamicos","52":"/docs/animations.html#gestos-de-rastreamento","53":"/docs/animations.html#scrollview-com-exemplo-de-evento-animado","54":"/docs/animations.html#panresponder-com-exemplo-de-evento-animado","55":"/docs/animations.html#respondendo-ao-valor-atual-da-animacao","56":"/docs/animations.html#usando-o-driver-nativo","57":"/docs/animations.html#ressalvas","58":"/docs/animations.html#tenha-em-mente","59":"/docs/animations.html#exemplos-adicionais","60":"/docs/animations.html#api-layoutanimation","61":"/docs/animations.html#notas-adicionais","62":"/docs/animations.html#requestanimationframe","63":"/docs/animations.html#setnativeprops","64":"/docs/build-speed.html#acelerando-sua-fase-de-construcao","65":"/docs/build-speed.html#crie-apenas-uma-abi-durante-o-desenvolvimento-somente-android","66":"/docs/build-speed.html#use-um-cache-do-compilador","67":"/docs/build-speed.html#caches-locais","68":"/docs/build-speed.html#configuracao-especifica-do-xcode","69":"/docs/build-speed.html#usando-esta-abordagem-em-um-ic","70":"/docs/build-speed.html#caches-distribuidos","71":"/docs/building-for-tv.html#construcao-para-dispositivos-de-tv","72":"/docs/building-for-tv.html#android-tv","73":"/docs/building-for-tv.html#mudancas-de-compilacao","74":"/docs/building-for-tv.html#mudancas-de-codigo","75":"/docs/building-for-tv.html#tvos","76":"/docs/building-for-tv.html#alteracoes-de-compilacao","77":"/docs/building-for-tv.html#mudancas-de-codigo-1","78":"/docs/building-for-tv.html#problemas-conhecidos","79":"/docs/colors.html#referencia-de-cores","80":"/docs/colors.html#apis-de-cores","81":"/docs/colors.html#representacoes-de-cores","82":"/docs/colors.html#vermelho-verde-azul-rgb","83":"/docs/colors.html#tonalidade-saturacao-iluminacao-hsl","84":"/docs/colors.html#matiz-brancura-escuridao-hwb","85":"/docs/colors.html#informacoes-de-cor","86":"/docs/colors.html#cores-nomeadas","87":"/docs/colors.html#transparent","88":"/docs/colors.html#palavras-chave-das-cores","89":"/docs/communication-android.html#comunicacao-entre-nativo-e-react-native","90":"/docs/communication-android.html#introducao","91":"/docs/communication-android.html#propriedades","92":"/docs/communication-android.html#passando-propriedades-de-native-para-react-native","93":"/docs/communication-android.html#passando-propriedades-do-react-native-para-native","94":"/docs/communication-android.html#limites-de-propriedades","95":"/docs/communication-android.html#outras-formas-de-interacao-entre-idiomas-eventos-e-modulos-nativos","96":"/docs/communication-android.html#chamando-funcoes-react-native-a-partir-de-nativos-eventos","97":"/docs/communication-android.html#chamando-funcoes-nativas-do-react-native-modulos-nativos","98":"/docs/communication-ios.html#comunicacao-entre-nativo-e-react-native","99":"/docs/communication-ios.html#introducao","100":"/docs/communication-ios.html#propriedades","101":"/docs/communication-ios.html#passando-propriedades-de-native-para-react-native","102":"/docs/communication-ios.html#passando-propriedades-do-react-native-para-native","103":"/docs/communication-ios.html#limites-de-propriedades","104":"/docs/communication-ios.html#outras-formas-de-interacao-entre-linguagens-eventos-e-modulos-nativos","105":"/docs/communication-ios.html#chamando-funcoes-react-native-a-partir-de-nativos-eventos","106":"/docs/communication-ios.html#chamando-funcoes-nativas-do-react-native-modulos-nativos","107":"/docs/communication-ios.html#fluxo-de-calculo-de-layout","108":"/docs/communication-ios.html#layout-de-um-componente-nativo-incorporado-no-react-native","109":"/docs/communication-ios.html#layout-de-um-componente-react-native-incorporado-no-nativo","110":"/docs/communication-ios.html#react-native-com-tamanho-fixo","111":"/docs/communication-ios.html#react-native-com-tamanho-flexivel","112":"/docs/direct-manipulation.html#manipulacao-direta","113":"/docs/direct-manipulation.html#setnativeprops-com-touchableopacity","114":"/docs/direct-manipulation.html#componentes-compostos-e-setnativeprops","115":"/docs/direct-manipulation.html#encaminha-setnativeprops-para-um-filho","116":"/docs/direct-manipulation.html#setnativeprops-para-editar-o-valor-textinput","117":"/docs/direct-manipulation.html#evitando-conflitos-com-a-funcao-render","118":"/docs/direct-manipulation.html#setnativeprops-e-shouldcomponentupdate","119":"/docs/direct-manipulation.html#outros-metodos-nativos","120":"/docs/direct-manipulation.html#measure-callback","121":"/docs/direct-manipulation.html#measureinwindow-callback","122":"/docs/direct-manipulation.html#measurelayout-relativetonativecomponentref-onsuccess-onfail","123":"/docs/direct-manipulation.html#focus","124":"/docs/direct-manipulation.html#blur","125":"/docs/debugging.html#nocoes-basicas-de-depuracao","126":"/docs/debugging.html#acessando-o-menu-de-desenvolvimento","127":"/docs/debugging.html#logbox","128":"/docs/debugging.html#erros-e-avisos-do-console","129":"/docs/debugging.html#erros-nao-tratados","130":"/docs/debugging.html#erros-de-sintaxe","131":"/docs/debugging.html#ferramentas-para-desenvolvedores-do-chrome","132":"/docs/debugging.html#depuracao-em-um-dispositivo-fisico","133":"/docs/debugging.html#android","134":"/docs/debugging.html#ios","135":"/docs/debugging.html#ferramentas-para-desenvolvedores-safari","136":"/docs/debugging.html#monitor-de-desempenho","137":"/docs/environment-setup/linux/android.html#instalando-dependencias","138":"/docs/environment-setup/linux/android.html#node","139":"/docs/environment-setup/linux/android.html#kit-de-desenvolvimento-do-java","140":"/docs/environment-setup/linux/android.html#ambiente-de-desenvolvimento-android","141":"/docs/environment-setup/linux/android.html#_1-instale-o-android-studio","142":"/docs/environment-setup/linux/android.html#_2-instale-o-android-sdk","143":"/docs/environment-setup/linux/android.html#watchman","144":"/docs/environment-setup/linux/android.html#interface-de-linha-de-comando-nativa-do-react","145":"/docs/environment-setup/linux/android.html#criando-um-novo-aplicativo","146":"/docs/environment-setup/linux/android.html#opcional-usando-uma-versao-ou-modelo-especifico","147":"/docs/environment-setup/linux/android.html#preparando-o-dispositivo-android","148":"/docs/environment-setup/linux/android.html#usando-um-dispositivo-fisico","149":"/docs/environment-setup/linux/android.html#usando-um-dispositivo-virtual","150":"/docs/environment-setup/linux/android.html#executando-seu-aplicativo-react-native","151":"/docs/environment-setup/linux/android.html#etapa-1-iniciar-o-metro","152":"/docs/environment-setup/linux/android.html#etapa-2-inicie-seu-aplicativo","153":"/docs/environment-setup/linux/android.html#modificando-seu-aplicativo","154":"/docs/environment-setup/linux/android.html#e-isso","155":"/docs/environment-setup/linux/android.html#e-agora","156":"/docs/environment-setup.html#configurando-o-ambiente-de-desenvolvimento","157":"/docs/environment-setup.html#expo-go-inicio-rapido","158":"/docs/environment-setup.html#executando-seu-aplicativo-react-native","159":"/docs/environment-setup.html#react-native-cli-inicio-rapido","160":"/docs/environment-setup.html#macos","161":"/docs/environment-setup.html#windows","162":"/docs/environment-setup.html#linux","163":"/docs/environment-setup/mac-os/android.html#android","164":"/docs/environment-setup/mac-os/android.html#instalando-dependencias","165":"/docs/environment-setup/mac-os/android.html#node-watchman","166":"/docs/environment-setup/mac-os/android.html#kit-de-desenvolvimento-do-java","167":"/docs/environment-setup/mac-os/android.html#_1-instale-o-android-studio","168":"/docs/environment-setup/mac-os/android.html#_2-instale-o-android-sdk","169":"/docs/environment-setup/mac-os/android.html#interface-de-linha-de-comando-nativa-do-react","170":"/docs/environment-setup/mac-os/android.html#criando-um-novo-aplicativo","171":"/docs/environment-setup/mac-os/android.html#opcional-usando-uma-versao-ou-modelo-especifico","172":"/docs/environment-setup/mac-os/android.html#preparando-o-dispositivo-android","173":"/docs/environment-setup/mac-os/android.html#usando-um-dispositivo-fisico","174":"/docs/environment-setup/mac-os/android.html#usando-um-dispositivo-virtual","175":"/docs/environment-setup/mac-os/android.html#executando-seu-aplicativo-react-native","176":"/docs/environment-setup/mac-os/android.html#etapa-1-iniciar-o-metro","177":"/docs/environment-setup/mac-os/android.html#step-2-inicie-sua-aplicacao","178":"/docs/environment-setup/mac-os/android.html#modificando-seu-aplicativo","179":"/docs/environment-setup/mac-os/android.html#e-isso","180":"/docs/environment-setup/mac-os/android.html#e-agora","181":"/docs/environment-setup/mac-os/ios.html#ios","182":"/docs/environment-setup/mac-os/ios.html#instalando-dependencias","183":"/docs/environment-setup/mac-os/ios.html#node-e-watchman","184":"/docs/environment-setup/mac-os/ios.html#xcode","185":"/docs/environment-setup/mac-os/ios.html#ferramentas-de-linha-de-comando","186":"/docs/environment-setup/mac-os/ios.html#instalando-um-simulador-ios-no-xcode","187":"/docs/environment-setup/mac-os/ios.html#cocoapods","188":"/docs/environment-setup/mac-os/ios.html#interface-de-linha-de-comando-nativa-do-react","189":"/docs/environment-setup/mac-os/ios.html#criando-um-novo-aplicativo","190":"/docs/environment-setup/mac-os/ios.html#opcional-usando-uma-versao-ou-modelo-especifico","191":"/docs/environment-setup/mac-os/ios.html#opcional-configurando-seu-ambiente","192":"/docs/environment-setup/mac-os/ios.html#executando-seu-aplicativo-react-native","193":"/docs/environment-setup/mac-os/ios.html#etapa-1-iniciar-o-metro","194":"/docs/environment-setup/mac-os/ios.html#etapa-2-inicie-seu-aplicativo","195":"/docs/environment-setup/mac-os/ios.html#executando-em-um-dispositivo","196":"/docs/environment-setup/mac-os/ios.html#modificando-seu-aplicativo","197":"/docs/environment-setup/mac-os/ios.html#e-isso","198":"/docs/environment-setup/mac-os/ios.html#e-agora","199":"/docs/environment-setup/windows/android.html#instalando-dependencias","200":"/docs/environment-setup/windows/android.html#node-jdk","201":"/docs/environment-setup/windows/android.html#ambiente-de-desenvolvimento-android","202":"/docs/environment-setup/windows/android.html#_1-instale-o-android-studio","203":"/docs/environment-setup/windows/android.html#_2-instale-o-android-sdk","204":"/docs/environment-setup/windows/android.html#interface-de-linha-de-comando-nativa-do-react","205":"/docs/environment-setup/windows/android.html#criando-um-novo-aplicativo","206":"/docs/environment-setup/windows/android.html#opcional-usando-uma-versao-ou-modelo-especifico","207":"/docs/environment-setup/windows/android.html#preparando-o-dispositivo-android","208":"/docs/environment-setup/windows/android.html#usando-um-dispositivo-fisico","209":"/docs/environment-setup/windows/android.html#usando-um-dispositivo-virtual","210":"/docs/environment-setup/windows/android.html#executando-seu-aplicativo-react-native","211":"/docs/environment-setup/windows/android.html#etapa-1-iniciar-o-metro","212":"/docs/environment-setup/windows/android.html#etapa-2-inicie-seu-aplicativo","213":"/docs/environment-setup/windows/android.html#modificando-seu-aplicativo","214":"/docs/environment-setup/windows/android.html#e-isso","215":"/docs/environment-setup/windows/android.html#e-agora","216":"/docs/fast-refresh.html#atualizacao-rapida","217":"/docs/fast-refresh.html#como-funciona","218":"/docs/fast-refresh.html#resiliencia-a-erros","219":"/docs/fast-refresh.html#limitacoes","220":"/docs/fast-refresh.html#dicas","221":"/docs/fast-refresh.html#atualizacao-rapida-e-ganchos","222":"/docs/flexbox.html#layout-com-flexbox","223":"/docs/flexbox.html#flex","224":"/docs/flexbox.html#direcao-flexivel","225":"/docs/flexbox.html#direcao-do-layout","226":"/docs/flexbox.html#justificar-o-conteudo","227":"/docs/flexbox.html#alinhar-itens","228":"/docs/flexbox.html#alinhar-se","229":"/docs/flexbox.html#alinhar-conteudo","230":"/docs/flexbox.html#flex-wrap","231":"/docs/flexbox.html#base-flexivel-crescer-e-encolher","232":"/docs/flexbox.html#lacuna-de-linha-lacuna-de-coluna-e-lacuna","233":"/docs/flexbox.html#largura-e-altura","234":"/docs/flexbox.html#layout-absoluto-e-relativo","235":"/docs/flexbox.html#indo-mais-fundo","236":"/docs/getting-started.html#introducao","237":"/docs/getting-started.html#como-usar-esses-documentos","238":"/docs/getting-started.html#pre-requisitos","239":"/docs/getting-started.html#exemplos-interativos","240":"/docs/getting-started.html#notas-do-desenvolvedor","241":"/docs/getting-started.html#formatacao","242":"/docs/handling-text-input.html#tratamento-de-entrada-de-texto","243":"/docs/handling-touches.html#lidando-com-toques","244":"/docs/handling-touches.html#exibindo-um-botao-basico","245":"/docs/handling-touches.html#tocaveis","246":"/docs/handling-touches.html#rolar-e-deslizar","247":"/docs/handling-touches.html#problemas-conhecidos","248":"/docs/gesture-responder-system.html#sistema-de-resposta-por-gestos","249":"/docs/gesture-responder-system.html#melhores-praticas","250":"/docs/gesture-responder-system.html#touchablehighlight-and-touchable","251":"/docs/gesture-responder-system.html#ciclo-de-vida-do-respondente","252":"/docs/gesture-responder-system.html#capturar-manipuladores-shouldset","253":"/docs/gesture-responder-system.html#panresponder","254":"/docs/headless-js-android.html#headless-js","255":"/docs/headless-js-android.html#a-api-js","256":"/docs/headless-js-android.html#a-api-da-plataforma","257":"/docs/headless-js-android.html#novas-tentativas","258":"/docs/headless-js-android.html#ressalvas","259":"/docs/headless-js-android.html#exemplo-de-uso","260":"/docs/height-and-width.html#altura-e-largura","261":"/docs/height-and-width.html#dimensoes-fixas","262":"/docs/height-and-width.html#dimensoes-flexiveis","263":"/docs/height-and-width.html#dimensoes-percentuais","264":"/docs/integration-with-existing-apps/android-java.html#android-java","265":"/docs/integration-with-existing-apps/android-java.html#conceitos-chave","266":"/docs/integration-with-existing-apps/android-java.html#pre-requisitos","267":"/docs/integration-with-existing-apps/android-java.html#_1-configure-a-estrutura-de-diretorios","268":"/docs/integration-with-existing-apps/android-java.html#_2-instale-dependencias-javascript","269":"/docs/integration-with-existing-apps/android-java.html#adicionando-react-native-ao-seu-aplicativo","270":"/docs/integration-with-existing-apps/android-java.html#configurando-o-gradle","271":"/docs/integration-with-existing-apps/android-java.html#habilitar-autolinking-de-modulos-nativos","272":"/docs/integration-with-existing-apps/android-java.html#configurando-permissoes","273":"/docs/integration-with-existing-apps/android-java.html#trafego-de-texto-simples-nivel-de-api-28","274":"/docs/integration-with-existing-apps/android-java.html#integracao-de-codigo","275":"/docs/integration-with-existing-apps/android-java.html#o-componente-react-native","276":"/docs/integration-with-existing-apps/android-java.html#_1-crie-um-arquivo-index-js","277":"/docs/integration-with-existing-apps/android-java.html#_2-adicione-seu-codigo-react-native","278":"/docs/integration-with-existing-apps/android-java.html#_3-configure-permissoes-para-sobreposicao-de-erros-de-desenvolvimento","279":"/docs/integration-with-existing-apps/android-java.html#a-magica-reactrootview","280":"/docs/integration-with-existing-apps/android-java.html#teste-sua-integracao","281":"/docs/integration-with-existing-apps/android-java.html#_1-execute-o-empacotador","282":"/docs/integration-with-existing-apps/android-java.html#_2-execute-o-aplicativo","283":"/docs/integration-with-existing-apps/android-java.html#criando-uma-versao-de-lancamento-no-android-studio","284":"/docs/integration-with-existing-apps/android-java.html#e-agora","285":"/docs/integration-with-existing-apps.html#integracao-com-aplicativos-existentes","286":"/docs/integration-with-existing-apps/android-kotlin.html#android-kotlin","287":"/docs/integration-with-existing-apps/android-kotlin.html#conceitos-chave","288":"/docs/integration-with-existing-apps/android-kotlin.html#pre-requisitos","289":"/docs/integration-with-existing-apps/android-kotlin.html#adicionando-react-native-ao-seu-aplicativo","290":"/docs/integration-with-existing-apps/android-kotlin.html#configurando-o-gradle","291":"/docs/integration-with-existing-apps/android-kotlin.html#habilitar-autolinking-de-modulos-nativos","292":"/docs/integration-with-existing-apps/android-kotlin.html#configurando-permissoes","293":"/docs/integration-with-existing-apps/android-kotlin.html#trafego-de-texto-simples-nivel-de-api-28","294":"/docs/integration-with-existing-apps/android-kotlin.html#integracao-de-codigo","295":"/docs/integration-with-existing-apps/android-kotlin.html#o-componente-react-native","296":"/docs/integration-with-existing-apps/android-kotlin.html#_1-crie-um-arquivo-index-js","297":"/docs/integration-with-existing-apps/android-kotlin.html#_2-adicione-seu-codigo-react-native","298":"/docs/integration-with-existing-apps/android-kotlin.html#_3-configure-permissoes-para-sobreposicao-de-erros-de-desenvolvimento","299":"/docs/integration-with-existing-apps/android-kotlin.html#a-magica-reactrootview","300":"/docs/integration-with-existing-apps/android-kotlin.html#teste-sua-integracao","301":"/docs/integration-with-existing-apps/android-kotlin.html#_1-execute-o-empacotador","302":"/docs/integration-with-existing-apps/android-kotlin.html#_2-execute-o-aplicativo","303":"/docs/integration-with-existing-apps/android-kotlin.html#criando-uma-versao-de-lancamento-no-android-studio","304":"/docs/integration-with-existing-apps/android-kotlin.html#e-agora","305":"/docs/integration-with-existing-apps/ios-objective-c.html#ios-objective-c","306":"/docs/integration-with-existing-apps/ios-objective-c.html#conceitos-chave","307":"/docs/integration-with-existing-apps/ios-objective-c.html#pre-requisitos","308":"/docs/integration-with-existing-apps/ios-objective-c.html#_1-configure-a-estrutura-de-diretorios","309":"/docs/integration-with-existing-apps/ios-objective-c.html#_2-instale-dependencias-javascript","310":"/docs/integration-with-existing-apps/ios-objective-c.html#_3-instale-cocoapods","311":"/docs/integration-with-existing-apps/ios-objective-c.html#adicionando-react-native-ao-seu-aplicativo","312":"/docs/integration-with-existing-apps/ios-objective-c.html#ferramentas-de-linha-de-comando-para-xcode","313":"/docs/integration-with-existing-apps/ios-objective-c.html#configurando-dependencias-do-cocoapods","314":"/docs/integration-with-existing-apps/ios-objective-c.html#integracao-de-codigo","315":"/docs/integration-with-existing-apps/ios-objective-c.html#o-componente-react-native","316":"/docs/integration-with-existing-apps/ios-objective-c.html#_1-crie-um-arquivo-index-js","317":"/docs/integration-with-existing-apps/ios-objective-c.html#_2-adicione-seu-codigo-react-native","318":"/docs/integration-with-existing-apps/ios-objective-c.html#a-magica-rctrootview","319":"/docs/integration-with-existing-apps/ios-objective-c.html#_1-crie-um-caminho-de-evento","320":"/docs/integration-with-existing-apps/ios-objective-c.html#_2-manipulador-de-eventos","321":"/docs/integration-with-existing-apps/ios-objective-c.html#_3-conecte","322":"/docs/integration-with-existing-apps/ios-objective-c.html#teste-sua-integracao","323":"/docs/integration-with-existing-apps/ios-objective-c.html#_1-adicionar-excecao-de-seguranca-de-transporte-de-aplicativos","324":"/docs/integration-with-existing-apps/ios-objective-c.html#_2-execute-o-empacotador","325":"/docs/integration-with-existing-apps/ios-objective-c.html#_3-execute-o-aplicativo","326":"/docs/integration-with-existing-apps/ios-objective-c.html#e-agora","327":"/docs/images.html#imagens","328":"/docs/images.html#recursos-de-imagem-estatica","329":"/docs/images.html#recursos-estaticos-sem-imagem","330":"/docs/images.html#imagens-dos-recursos-do-aplicativo-hibrido","331":"/docs/images.html#imagens-de-rede","332":"/docs/images.html#solicitacoes-de-rede-para-imagens","333":"/docs/images.html#uri-com-dados","334":"/docs/images.html#controle-de-cache-somente-ios","335":"/docs/images.html#imagens-do-sistema-de-arquivos-local","336":"/docs/images.html#melhor-imagem-do-rolo-da-camera","337":"/docs/images.html#por-que-nao-dimensionar-tudo-automaticamente","338":"/docs/images.html#fonte-como-um-objeto","339":"/docs/images.html#imagem-de-fundo-via-aninhamento","340":"/docs/images.html#estilo-arredondado-do-ios","341":"/docs/images.html#decodificacao-fora-do-thread","342":"/docs/images.html#configurando-limites-de-cache-de-imagens-do-ios","343":"/docs/intro-react.html#fundamentos-do-react","344":"/docs/intro-react.html#seu-primeiro-componente","345":"/docs/intro-react.html#jsx","346":"/docs/intro-react.html#componentes-personalizados","347":"/docs/intro-react.html#notas-do-desenvolvedor","348":"/docs/intro-react.html#aderecos","349":"/docs/intro-react.html#estado","350":"/docs/integration-with-existing-apps/ios-swift.html#ios-swift","351":"/docs/integration-with-existing-apps/ios-swift.html#conceitos-chave","352":"/docs/integration-with-existing-apps/ios-swift.html#pre-requisitos","353":"/docs/integration-with-existing-apps/ios-swift.html#_1-configure-a-estrutura-de-diretorios","354":"/docs/integration-with-existing-apps/ios-swift.html#_2-instale-dependencias-javascript","355":"/docs/integration-with-existing-apps/ios-swift.html#_3-instale-cocoapods","356":"/docs/integration-with-existing-apps/ios-swift.html#adicionando-react-native-ao-seu-aplicativo","357":"/docs/integration-with-existing-apps/ios-swift.html#ferramentas-de-linha-de-comando-para-xcode","358":"/docs/integration-with-existing-apps/ios-swift.html#configurando-dependencias-do-cocoapods","359":"/docs/integration-with-existing-apps/ios-swift.html#integracao-de-codigo","360":"/docs/integration-with-existing-apps/ios-swift.html#o-componente-react-native","361":"/docs/integration-with-existing-apps/ios-swift.html#_1-crie-um-arquivo-index-js","362":"/docs/integration-with-existing-apps/ios-swift.html#_2-adicione-seu-codigo-react-native","363":"/docs/integration-with-existing-apps/ios-swift.html#a-magica-rctrootview","364":"/docs/integration-with-existing-apps/ios-swift.html#_1-crie-um-caminho-de-evento","365":"/docs/integration-with-existing-apps/ios-swift.html#_2-manipulador-de-eventos","366":"/docs/integration-with-existing-apps/ios-swift.html#_3-conecte","367":"/docs/integration-with-existing-apps/ios-swift.html#_4-referencia-da-janela","368":"/docs/integration-with-existing-apps/ios-swift.html#teste-sua-integracao","369":"/docs/integration-with-existing-apps/ios-swift.html#_1-adicionar-excecao-de-seguranca-de-transporte-de-aplicativos","370":"/docs/integration-with-existing-apps/ios-swift.html#_2-execute-o-empacotador","371":"/docs/integration-with-existing-apps/ios-swift.html#_3-execute-o-aplicativo","372":"/docs/integration-with-existing-apps/ios-swift.html#e-agora","373":"/docs/introduction.html#introducao","374":"/docs/libraries.html#usando-bibliotecas","375":"/docs/libraries.html#selecionando-um-gerenciador-de-pacotes","376":"/docs/libraries.html#instalando-uma-biblioteca","377":"/docs/libraries.html#vinculando-codigo-nativo-no-ios","378":"/docs/libraries.html#vinculando-codigo-nativo-no-android","379":"/docs/libraries.html#encontrando-bibliotecas","380":"/docs/libraries.html#determinando-a-compatibilidade-da-biblioteca","381":"/docs/libraries.html#funciona-com-react-native","382":"/docs/libraries.html#funciona-nas-plataformas-suportadas-pelo-meu-aplicativo","383":"/docs/libraries.html#funciona-com-a-versao-do-meu-aplicativo-react-native","384":"/docs/intro-react-native-components.html#componentes-principais-e-componentes-nativos","385":"/docs/intro-react-native-components.html#visualizacoes-e-desenvolvimento-movel","386":"/docs/intro-react-native-components.html#componentes-nativos","387":"/docs/intro-react-native-components.html#core-componentes","388":"/docs/javascript-environment.html#ambiente-javascript","389":"/docs/javascript-environment.html#tempo-de-execucao-javascript","390":"/docs/javascript-environment.html#transformadores-de-sintaxe-javascript","391":"/docs/javascript-environment.html#polifills","392":"/docs/javascript-environment.html#navegador","393":"/docs/javascript-environment.html#ecmascript-2015-es6","394":"/docs/javascript-environment.html#ecmascript-2016-es7","395":"/docs/javascript-environment.html#ecmascript-2017-es8","396":"/docs/javascript-environment.html#especifico","397":"/docs/metro.html#metro","398":"/docs/metro.html#configurando-metro","399":"/docs/metro.html#avancado-usando-uma-funcao-de-configuracao","400":"/docs/integration-with-android-fragment.html#integracao-com-um-fragmento-android","401":"/docs/integration-with-android-fragment.html#_1-adicione-react-native-ao-seu-aplicativo","402":"/docs/integration-with-android-fragment.html#_2-integrando-seu-aplicativo-com-um-fragmento-react-native","403":"/docs/integration-with-android-fragment.html#_3-adicione-um-framelayout-para-o-fragmento-react-native","404":"/docs/integration-with-android-fragment.html#_4-adicionar-um-fragmento-react-native-ao-framelayout","405":"/docs/integration-with-android-fragment.html#_5-teste-sua-integracao","406":"/docs/integration-with-android-fragment.html#_6-configuracao-adicional-–-modulos-nativos","407":"/docs/linking-libraries-ios.html#vinculando-bibliotecas","408":"/docs/linking-libraries-ios.html#aqui-estao-algumas-etapas-para-vincular-suas-bibliotecas-que-contem-codigo-nativo","409":"/docs/linking-libraries-ios.html#vinculacao-automatica","410":"/docs/linking-libraries-ios.html#vinculacao-manual","411":"/docs/linking-libraries-ios.html#passo-1","412":"/docs/linking-libraries-ios.html#passo-2","413":"/docs/linking-libraries-ios.html#etapa-3","414":"/docs/more-resources.html#mais-recursos","415":"/docs/more-resources.html#mergulho-profundo","416":"/docs/more-resources.html#ides","417":"/docs/more-resources.html#plataformas-para-experimentar","418":"/docs/more-resources.html#aplicativos-de-exemplo","419":"/docs/more-resources.html#encontre-crie-e-compartilhe-seus-proprios-componentes-nativos-e-turbomodules","420":"/docs/native-components-android.html#componentes-de-iu-nativos-do-android","421":"/docs/native-components-android.html#exemplo-de-imageview","422":"/docs/native-components-android.html#_1-crie-a-subclasse-viewmanager","423":"/docs/native-components-android.html#_2-implementar-o-metodo-createviewinstance","424":"/docs/native-components-android.html#_3-exponha-os-configuradores-de-propriedades-de-visualizacao-usando-a-anotacao-reactprop-ou-reactpropgroup","425":"/docs/native-components-android.html#_4-cadastre-o-viewmanager","426":"/docs/native-components-android.html#_5-implemente-o-modulo-javascript","427":"/docs/native-components-android.html#eventos","428":"/docs/native-components-android.html#exemplo-de-integracao-com-um-fragmento-android","429":"/docs/native-components-android.html#_1-crie-um-exemplo-de-visualizacao-personalizada","430":"/docs/native-components-android.html#_2-crie-um-fragmento","431":"/docs/native-components-android.html#_3-crie-a-subclasse-viewmanager","432":"/docs/native-components-android.html#_4-cadastre-o-viewmanager-1","433":"/docs/native-components-android.html#_5-registre-o-package","434":"/docs/native-components-android.html#_6-implemente-o-modulo-javascript","435":"/docs/native-debugging.html#debug-nativo","436":"/docs/native-debugging.html#acessando-logs-nativos","437":"/docs/native-debugging.html#depurando-codigo-nativo","438":"/docs/native-debugging.html#android-studio","439":"/docs/native-debugging.html#xcode","440":"/docs/native-components-ios.html#componentes-de-ui-nativos-do-ios","441":"/docs/native-components-ios.html#exemplo-de-mapview-para-ios","442":"/docs/native-components-ios.html#propriedades","443":"/docs/native-components-ios.html#eventos","444":"/docs/native-components-ios.html#lidando-com-multiplas-visualizacoes-nativas","445":"/docs/native-components-ios.html#estilos","446":"/docs/native-modules-intro.html#introducao-aos-modulos-nativos","447":"/docs/native-modules-intro.html#configuracao-do-modulo-nativo","448":"/docs/native-modules-intro.html#comecando","449":"/docs/native-modules-android.html#modulos-nativos-do-android","450":"/docs/native-modules-android.html#crie-um-modulo-nativo-de-calendario","451":"/docs/native-modules-android.html#configurar","452":"/docs/native-modules-android.html#crie-um-arquivo-de-modulo-nativo-personalizado","453":"/docs/native-modules-android.html#nome-do-modulo","454":"/docs/native-modules-android.html#exportar-um-metodo-nativo-para-javascript","455":"/docs/native-modules-android.html#metodos-sincronos","456":"/docs/native-modules-android.html#registre-o-modulo-especifico-para-android","457":"/docs/native-modules-android.html#teste-o-que-voce-construiu","458":"/docs/native-modules-android.html#construindo-enquanto-voce-itera","459":"/docs/native-modules-android.html#recapitulacao✨","460":"/docs/native-modules-android.html#alem-de-um-modulo-nativo-de-calendario","461":"/docs/native-modules-android.html#melhor-exportacao-de-modulo-nativo","462":"/docs/native-modules-android.html#tipos-de-argumento","463":"/docs/native-modules-android.html#exportando-constantes","464":"/docs/native-modules-android.html#callbacks","465":"/docs/native-modules-android.html#promises","466":"/docs/native-modules-android.html#enviando-eventos-para-javascript","467":"/docs/native-modules-android.html#obtendo-o-resultado-da-atividade-de-startactivityforresult","468":"/docs/native-modules-android.html#ouvindo-eventos-do-ciclo-de-vida","469":"/docs/native-modules-android.html#threading","470":"/docs/native-modules-setup.html#configuracao-do-pacote-npm-de-modulos-nativos","471":"/docs/navigation.html#navegando-entre-telas","472":"/docs/navigation.html#navegacao-de-reacao","473":"/docs/navigation.html#react-native-navigation","474":"/docs/native-modules-ios.html#modulos-nativos-ios","475":"/docs/native-modules-ios.html#crie-um-modulo-nativo-de-calendario","476":"/docs/native-modules-ios.html#configurar","477":"/docs/native-modules-ios.html#crie-arquivos-de-modulo-nativos-personalizados","478":"/docs/native-modules-ios.html#nome-do-modulo","479":"/docs/native-modules-ios.html#exportar-um-metodo-nativo-para-javascript","480":"/docs/native-modules-ios.html#metodos-sincronos","481":"/docs/native-modules-ios.html#teste-o-que-voce-construiu","482":"/docs/native-modules-ios.html#construindo-enquanto-voce-itera","483":"/docs/native-modules-ios.html#recapitulacao✨","484":"/docs/native-modules-ios.html#alem-de-um-modulo-nativo-de-calendario","485":"/docs/native-modules-ios.html#melhor-exportacao-de-modulo-nativo","486":"/docs/native-modules-ios.html#tipos-de-argumento","487":"/docs/native-modules-ios.html#exportando-constantes","488":"/docs/native-modules-ios.html#callback","489":"/docs/native-modules-ios.html#promises","490":"/docs/native-modules-ios.html#enviando-eventos-para-javascript","491":"/docs/native-modules-ios.html#threading","492":"/docs/native-modules-ios.html#injecao-de-dependencia","493":"/docs/native-modules-ios.html#exportando-swift","494":"/docs/native-modules-ios.html#nomes-de-metodos-reservados","495":"/docs/native-modules-ios.html#invalidate","496":"/docs/optimizing-flatlist-configuration.html#otimizando-a-configuracao-da-flatlist","497":"/docs/optimizing-flatlist-configuration.html#termos","498":"/docs/optimizing-flatlist-configuration.html#props","499":"/docs/optimizing-flatlist-configuration.html#removeclippedsubviews","500":"/docs/optimizing-flatlist-configuration.html#maxtorenderperbatch","501":"/docs/optimizing-flatlist-configuration.html#updatecellsbatchingperiod","502":"/docs/optimizing-flatlist-configuration.html#initialnumtorender","503":"/docs/optimizing-flatlist-configuration.html#windowsize","504":"/docs/optimizing-flatlist-configuration.html#lista-de-itens","505":"/docs/optimizing-flatlist-configuration.html#use-componentes-basicos","506":"/docs/optimizing-flatlist-configuration.html#use-componentes-leves","507":"/docs/optimizing-flatlist-configuration.html#usar-shouldcomponentupdate","508":"/docs/optimizing-flatlist-configuration.html#use-imagens-otimizadas-em-cache","509":"/docs/optimizing-flatlist-configuration.html#use-getitemlayout","510":"/docs/optimizing-flatlist-configuration.html#use-keyextractor-ou-key","511":"/docs/optimizing-flatlist-configuration.html#evite-funcao-anonima-em-renderitem","512":"/docs/out-of-tree-platforms.html#plataformas-fora-da-arvore","513":"/docs/out-of-tree-platforms.html#de-parceiros","514":"/docs/out-of-tree-platforms.html#da-comunidade","515":"/docs/out-of-tree-platforms.html#criando-sua-propria-plataforma-react-native","516":"/docs/out-of-tree-platforms.html#bundling","517":"/docs/network.html#rede","518":"/docs/network.html#usando-o-fetch","519":"/docs/network.html#fazendo-requisicoes","520":"/docs/network.html#lidando-com-a-resposta","521":"/docs/network.html#usando-outras-bibliotecas-de-rede","522":"/docs/network.html#suporte-websocket","523":"/docs/network.html#problemas-conhecidos-com-autenticacao-baseada-em-busca-e-cookie","524":"/docs/network.html#configurando-nsurlsession-no-ios","525":"/docs/profile-hermes.html#perfil-com-hermes","526":"/docs/profile-hermes.html#grave-um-perfil-de-amostragem-hermes","527":"/docs/profile-hermes.html#execute-o-comando-da-cli","528":"/docs/profile-hermes.html#habilitando-mapa-de-origem","529":"/docs/profile-hermes.html#erros-comuns","530":"/docs/profile-hermes.html#abra-o-perfil-baixado-no-chrome-devtools","531":"/docs/profile-hermes.html#como-funciona-o-transformador-de-perfil-hermes","532":"/docs/performance.html#visao-geral-do-desempenho","533":"/docs/performance.html#o-que-voce-precisa-saber-sobre-frames","534":"/docs/performance.html#taxa-de-quadros-js-thread-javascript","535":"/docs/performance.html#taxa-de-quadros-da-ui-thread-principal","536":"/docs/performance.html#fontes-comuns-de-problemas-de-desempenho","537":"/docs/performance.html#executando-em-modo-de-desenvolvimento-dev-true","538":"/docs/performance.html#usando-instrucoes-console-log","539":"/docs/performance.html#a-renderizacao-inicial-do-listview-e-muito-lenta-ou-o-desempenho-da-rolagem-e-ruim-para-listas-grandes","540":"/docs/performance.html#js-fps-despenca-ao-renderizar-novamente-uma-visualizacao-que-quase-nao-muda","541":"/docs/performance.html#descartando-o-fps-do-thread-js-por-causa-de-muito-trabalho-no-thread-javascript-ao-mesmo-tempo","542":"/docs/performance.html#mover-uma-visualizacao-na-tela-rolar-traduzir-girar-elimina-o-fps-do-thread-da-ui","543":"/docs/performance.html#animar-o-tamanho-de-uma-imagem-reduz-o-fps-do-thread-da-interface-do-usuario","544":"/docs/performance.html#minha-visualizacao-touchablex-nao-responde-muito-bem","545":"/docs/performance.html#transicoes-lentas-do-navegador","546":"/docs/publishing-to-app-store.html#publicacao-na-apple-app-store","547":"/docs/publishing-to-app-store.html#_1-configurar-esquema-de-liberacao","548":"/docs/publishing-to-app-store.html#dicas-profissionais","549":"/docs/publishing-to-app-store.html#_2-construir-aplicativo-para-lancamento","550":"/docs/publishing-to-app-store.html#_4-capturas-de-tela","551":"/docs/profiling.html#perfil","552":"/docs/profiling.html#criacao-de-perfil-de-desempenho-da-interface-do-android-com-systrace","553":"/docs/profiling.html#_1-coletando-um-rastro","554":"/docs/profiling.html#_2-lendo-o-rastreamento","555":"/docs/profiling.html#_3-encontre-o-seu-processo","556":"/docs/profiling.html#identificando-um-culpado","557":"/docs/profiling.html#resolvendo-problemas-de-javascript","558":"/docs/profiling.html#resolvendo-problemas-de-ui-nativa","559":"/docs/profiling.html#muito-trabalho-de-gpu","560":"/docs/profiling.html#criando-novas-visualizacoes-no-thread-da-ui","561":"/docs/platform-specific-code.html#codigo-especifico-da-plataforma","562":"/docs/platform-specific-code.html#modulo-de-plataforma","563":"/docs/platform-specific-code.html#detectando-a-versao-do-android","564":"/docs/platform-specific-code.html#detectando-a-versao-do-ios","565":"/docs/platform-specific-code.html#extensoes-especificas-da-plataforma","566":"/docs/platform-specific-code.html#extensoes-especificas-nativas-ou-seja-compartilhamento-de-codigo-com-nodejs-e-web","567":"/docs/react-devtools.html#ferramentas-de-desenvolvedor-react","568":"/docs/react-devtools.html#integracao-com-react-native-inspector","569":"/docs/react-devtools.html#depurando-o-estado-do-aplicativo","570":"/docs/react-devtools.html#solucao-de-problemas","571":"/docs/ram-bundles-inline-requires.html#pacotes-de-ram-e-require-inline","572":"/docs/ram-bundles-inline-requires.html#carregando-javascript","573":"/docs/ram-bundles-inline-requires.html#require-inline","574":"/docs/ram-bundles-inline-requires.html#habilite-o-formato-ram","575":"/docs/ram-bundles-inline-requires.html#configurar-pre-carregamento-e-requisitos-embutidos","576":"/docs/ram-bundles-inline-requires.html#investigando-os-modulos-carregados","577":"/docs/ram-bundles-inline-requires.html#atualizando-metro-config-js","578":"/docs/ram-bundles-inline-requires.html#teste-e-meca-melhorias","579":"/docs/react-native-gradle-plugin.html#plug-in-react-native-gradle","580":"/docs/react-native-gradle-plugin.html#usando-o-plugin","581":"/docs/react-native-gradle-plugin.html#configurando-o-plugin","582":"/docs/react-native-gradle-plugin.html#root","583":"/docs/react-native-gradle-plugin.html#reactnativedir","584":"/docs/react-native-gradle-plugin.html#codegendir","585":"/docs/react-native-gradle-plugin.html#clifile","586":"/docs/react-native-gradle-plugin.html#debuggablevariants","587":"/docs/react-native-gradle-plugin.html#nodeexecutableandargs","588":"/docs/react-native-gradle-plugin.html#bundlecommand","589":"/docs/react-native-gradle-plugin.html#bundleconfig","590":"/docs/react-native-gradle-plugin.html#bundleassetname","591":"/docs/react-native-gradle-plugin.html#entryfile","592":"/docs/react-native-gradle-plugin.html#extrapackagerargs","593":"/docs/react-native-gradle-plugin.html#hermescommand","594":"/docs/react-native-gradle-plugin.html#hermesflags","595":"/docs/react-native-gradle-plugin.html#usando-sabores-e-variantes-de-construcao","596":"/docs/react-native-gradle-plugin.html#o-que-o-plugin-esta-fazendo-nos-bastidores","597":"/docs/running-on-device/android-mac-os.html#mac-os-android","598":"/docs/running-on-device/android-mac-os.html#_1-habilite-a-depuracao-via-usb","599":"/docs/running-on-device/android-mac-os.html#_2-conecte-seu-dispositivo-via-usb","600":"/docs/running-on-device/android-mac-os.html#_3-execute-seu-aplicativo","601":"/docs/running-on-device/android-mac-os.html#conectando-se-ao-servidor-de-desenvolvimento","602":"/docs/running-on-device/android-mac-os.html#metodo-1-usando-adb-reverse-recomendado","603":"/docs/running-on-device/android-mac-os.html#metodo-2-conectar-via-wi-fi","604":"/docs/running-on-device/android-mac-os.html#construindo-seu-aplicativo-para-producao","605":"/docs/running-on-device.html#executando-no-dispositivo","606":"/docs/running-on-device/android-linux.html#linux-android","607":"/docs/running-on-device/android-linux.html#_1-habilite-a-depuracao-via-usb","608":"/docs/running-on-device/android-linux.html#_2-conecte-seu-dispositivo-via-usb","609":"/docs/running-on-device/android-linux.html#_3-execute-seu-aplicativo","610":"/docs/running-on-device/android-linux.html#conectando-se-ao-servidor-de-desenvolvimento","611":"/docs/running-on-device/android-linux.html#metodo-1-usando-adb-reverse-recomendado","612":"/docs/running-on-device/android-linux.html#metodo-2-conectar-via-wi-fi","613":"/docs/running-on-device/android-linux.html#construindo-seu-aplicativo-para-producao","614":"/docs/running-on-device/ios-macos.html#mac-os-ios","615":"/docs/running-on-device/ios-macos.html#_1-conecte-seu-dispositivo-via-usb","616":"/docs/running-on-device/ios-macos.html#_2-configure-a-assinatura-de-codigo","617":"/docs/running-on-device/ios-macos.html#_3-crie-e-execute-seu-aplicativo","618":"/docs/running-on-device/ios-macos.html#conectando-se-ao-servidor-de-desenvolvimento","619":"/docs/running-on-device/ios-macos.html#solucao-de-problemas","620":"/docs/running-on-device/ios-macos.html#_1-rede-wi-fi","621":"/docs/running-on-device/ios-macos.html#_2-endereco-ip","622":"/docs/running-on-device/ios-macos.html#construindo-seu-aplicativo-para-producao","623":"/docs/running-on-simulator-ios.html#executando-no-simulador","624":"/docs/running-on-simulator-ios.html#iniciando-o-simulador","625":"/docs/running-on-simulator-ios.html#especificando-um-dispositivo","626":"/docs/running-on-simulator-ios.html#especificando-uma-versao-do-dispositivo","627":"/docs/running-on-simulator-ios.html#especificando-um-udid","628":"/docs/security.html#seguranca","629":"/docs/security.html#armazenando-informacoes-confidenciais","630":"/docs/security.html#armazenamento-assincrono","631":"/docs/security.html#armazenamento-seguro","632":"/docs/security.html#ios-servicos-de-chaveiro","633":"/docs/security.html#android-preferencias-compartilhadas-seguras","634":"/docs/security.html#android-armazenamento-de-chaves","635":"/docs/security.html#autenticacao-e-links-diretos","636":"/docs/security.html#oauth2-e-redirecionamentos","637":"/docs/security.html#seguranca-de-rede","638":"/docs/security.html#ssl-pinning","639":"/docs/security.html#resumo","640":"/docs/running-on-device/android-windows.html#windows-android","641":"/docs/running-on-device/android-windows.html#_1-habilite-a-depuracao-via-usb","642":"/docs/running-on-device/android-windows.html#_2-conecte-seu-dispositivo-via-usb","643":"/docs/running-on-device/android-windows.html#_3-execute-seu-aplicativo","644":"/docs/running-on-device/android-windows.html#conectando-se-ao-servidor-de-desenvolvimento","645":"/docs/running-on-device/android-windows.html#metodo-1-usando-adb-reverse-recomendado","646":"/docs/running-on-device/android-windows.html#metodo-2-conectar-via-wi-fi","647":"/docs/running-on-device/android-windows.html#construindo-seu-aplicativo-para-producao","648":"/docs/signed-apk-android.html#publicacao-na-google-play-store","649":"/docs/signed-apk-android.html#gerando-uma-chave-de-upload","650":"/docs/signed-apk-android.html#windows","651":"/docs/signed-apk-android.html#mac-os","652":"/docs/signed-apk-android.html#configurando-variaveis-​​gradle","653":"/docs/signed-apk-android.html#adicionando-configuracao-de-assinatura-a-configuracao-gradle-do-seu-aplicativo","654":"/docs/signed-apk-android.html#gerando-uma-release-aab","655":"/docs/signed-apk-android.html#testando-a-versao-de-lancamento-do-seu-aplicativo","656":"/docs/signed-apk-android.html#publicacao-em-outras-lojas","657":"/docs/signed-apk-android.html#habilitando-o-proguard-para-reduzir-o-tamanho-do-apk-opcional","658":"/docs/signed-apk-android.html#migrando-aplicativos-antigos-do-android-react-native-para-usar-o-app-signing-do-google-play","659":"/docs/signed-apk-android.html#permissoes-padrao","660":"/docs/sourcemaps.html#mapas-de-origem","661":"/docs/sourcemaps.html#habilitar-mapas-de-origem-no-android","662":"/docs/sourcemaps.html#hermes","663":"/docs/sourcemaps.html#habilitar-mapas-de-origem-no-ios","664":"/docs/sourcemaps.html#simbolizacao-manual","665":"/docs/speeding-ci-builds.html#acelerando-as-compilacoes-de-ci","666":"/docs/speeding-ci-builds.html#desative-o-flipper-para-ios","667":"/docs/speeding-ci-builds.html#lidar-com-dependencias-transitivas","668":"/docs/style.html#estilo","669":"/docs/style.html#problemas-conhecidos","670":"/docs/testing-overview.html#teste","671":"/docs/testing-overview.html#por-que-testar","672":"/docs/testing-overview.html#analise-estatica","673":"/docs/testing-overview.html#escrevendo-codigo-testavel","674":"/docs/testing-overview.html#escrevendo-testes","675":"/docs/testing-overview.html#estruturando-testes","676":"/docs/testing-overview.html#testes-unitarios","677":"/docs/testing-overview.html#mock","678":"/docs/testing-overview.html#testes-de-integracao","679":"/docs/testing-overview.html#testes-de-componentes","680":"/docs/testing-overview.html#testando-interacoes-do-usuario","681":"/docs/testing-overview.html#testando-saida-renderizada","682":"/docs/testing-overview.html#testes-ponta-a-ponta","683":"/docs/testing-overview.html#resumo","684":"/docs/testing-overview.html#links","685":"/docs/symbolication.html#simbolizando-um-rastreamento-de-pilha","686":"/docs/symbolication.html#notas-sobre-mapas-de-origem","687":"/docs/the-new-architecture/landing-page.html#sobre-a-nova-arquitetura","688":"/docs/the-new-architecture/landing-page.html#por-que-uma-nova-arquitetura","689":"/docs/the-new-architecture/landing-page.html#layout-e-efeitos-sincronos","690":"/docs/the-new-architecture/landing-page.html#exemplo-renderizando-uma-dica-de-ferramenta","691":"/docs/the-new-architecture/landing-page.html#suporte-para-renderizacao-e-recursos-simultaneos","692":"/docs/the-new-architecture/landing-page.html#exemplo-usando-starttransition","693":"/docs/the-new-architecture/landing-page.html#javascript-rapido-interface-nativa","694":"/docs/the-new-architecture/landing-page.html#saber-mais","695":"/docs/the-new-architecture/landing-page.html#o-que-posso-esperar-ao-ativar-a-nova-arquitetura","696":"/docs/the-new-architecture/landing-page.html#devo-usar-a-nova-arquitetura-hoje","697":"/docs/the-new-architecture/landing-page.html#habilite-a-nova-arquitetura","698":"/docs/timers.html#temporizadores","699":"/docs/timers.html#temporizadores-1","700":"/docs/timers.html#gerenciador-de-interacao","701":"/docs/troubleshooting.html#solucao-de-problemas","702":"/docs/troubleshooting.html#porta-ja-em-uso-port-already-in-use","703":"/docs/troubleshooting.html#encerrando-um-processo-na-porta-8081","704":"/docs/troubleshooting.html#usando-uma-porta-diferente-de-8081","705":"/docs/troubleshooting.html#erro-de-bloqueio-npm","706":"/docs/troubleshooting.html#bibliotecas-ausentes-para-react","707":"/docs/troubleshooting.html#react-native-nao-compila-ao-ser-usado-como-cocoapod","708":"/docs/troubleshooting.html#lista-de-argumentos-muito-longa-falha-na-expansao-do-cabecalho-recursivo","709":"/docs/troubleshooting.html#nao-ha-transportes-disponiveis","710":"/docs/troubleshooting.html#excecao-sem-resposta-do-comando-shell","711":"/docs/troubleshooting.html#inicializacao-travada-do-react-native","712":"/docs/troubleshooting.html#npm","713":"/docs/troubleshooting.html#yarn","714":"/docs/troubleshooting.html#nao-e-possivel-iniciar-o-gerenciador-de-pacotes-react-native-no-linux","715":"/docs/troubleshooting.html#caso-1-erro-codigo-enospc-errno-enospc","716":"/docs/troubleshooting.html#error-spawnsync-gradlew-eacces","717":"/docs/upgrading.html#atualizando-para-novas-versoes","718":"/docs/upgrading.html#projetos-de-expo","719":"/docs/upgrading.html#projetos-react-native","720":"/docs/upgrading.html#cli-react-native","721":"/docs/upgrading.html#_1-execute-o-comando-upgrade","722":"/docs/upgrading.html#_2-resolva-os-conflitos","723":"/docs/upgrading.html#ajudante-de-atualizacao","724":"/docs/upgrading.html#_1-selecione-as-versoes","725":"/docs/upgrading.html#_2-atualizar-dependencias","726":"/docs/upgrading.html#_3-atualize-seus-arquivos-de-projeto","727":"/docs/upgrading.html#solucao-de-problemas","728":"/docs/upgrading.html#quero-atualizar-com-react-native-cli-mas-nao-uso-git","729":"/docs/upgrading.html#fiz-todas-as-alteracoes-mas-meu-aplicativo-ainda-usa-uma-versao-antiga","730":"/docs/using-a-listview.html#usando-list-view","731":"/docs/using-a-scrollview.html#usando-um-scrollview","732":"/docs/typescript.html#usando-typescript","733":"/docs/typescript.html#introducao-ao-typescript","734":"/docs/typescript.html#adicionando-typescript-a-um-projeto-existente","735":"/docs/typescript.html#usando-javascript-em-vez-de-typescript","736":"/docs/typescript.html#como-funcionam-o-typescript-e-o-react-native","737":"/docs/typescript.html#qual-e-a-aparencia-do-react-native-typescript","738":"/docs/typescript.html#onde-encontrar-conselhos-uteis","739":"/docs/typescript.html#usando-aliases-de-caminho-personalizados-com-typescript","740":"/docs/using-hermes.html#usando-o-hermes","741":"/docs/using-hermes.html#pacote-hermes","742":"/docs/using-hermes.html#confirmando-que-hermes-esta-em-uso","743":"/docs/using-hermes.html#android","744":"/docs/using-hermes.html#ios","745":"/docs/using-hermes.html#depurando-js-no-hermes-usando-devtools-do-google-chrome","746":"/docs/using-hermes.html#habilitando-hermes-em-versoes-mais-antigas-do-react-native","747":"/docs/using-hermes.html#android-1","748":"/docs/using-hermes.html#ios-1","749":"/docs/using-hermes.html#voltando-para-javascriptcore","750":"/docs/using-hermes.html#android-2","751":"/docs/using-hermes.html#ios-2","752":"/#documentacao-em-portugues-do-react-native-0-72","753":"/#basico","754":"/#configuracao-do-ambiente","755":"/#workflow","756":"/#ui-interacao","757":"/#interacao","758":"/#connectivity","759":"/#inclusion","760":"/#debugging","761":"/#testando","762":"/#performance","763":"/#javascript-runtime","764":"/#modulos-nativos","765":"/#componentes-nativos","766":"/#guias-android-e-ios","767":"/#android","768":"/#ios","769":"/#experimental"},"fieldIds":{"title":0,"titles":1,"text":2},"fieldLength":{"0":[1,1,49],"1":[3,1,1],"2":[1,4,65],"3":[1,4,89],"4":[3,4,49],"5":[1,4,65],"6":[1,5,31],"7":[1,5,20],"8":[3,4,43],"9":[3,4,46],"10":[3,4,85],"11":[1,4,164],"12":[1,4,68],"13":[1,4,55],"14":[3,4,48],"15":[3,4,49],"16":[2,4,17],"17":[2,4,17],"18":[2,4,17],"19":[2,4,7],"20":[2,4,31],"21":[2,4,28],"22":[2,4,21],"23":[2,4,15],"24":[2,4,39],"25":[2,4,11],"26":[4,4,38],"27":[4,4,46],"28":[4,4,22],"29":[2,4,12],"30":[3,4,87],"31":[3,4,63],"32":[1,4,25],"33":[3,4,59],"34":[1,4,153],"35":[3,1,195],"36":[8,1,22],"37":[6,1,61],"38":[7,1,98],"39":[7,1,84],"40":[2,1,6],"41":[3,1,37],"42":[5,3,79],"43":[2,7,117],"44":[4,7,43],"45":[1,1,59],"46":[2,1,223],"47":[2,1,138],"48":[2,1,119],"49":[3,1,55],"50":[1,1,173],"51":[3,1,102],"52":[3,1,78],"53":[6,1,157],"54":[6,1,76],"55":[6,1,139],"56":[4,1,162],"57":[1,1,84],"58":[3,1,56],"59":[2,1,13],"60":[2,1,195],"61":[2,1,1],"62":[1,3,54],"63":[1,3,110],"64":[5,1,62],"65":[10,5,202],"66":[5,5,30],"67":[2,10,229],"68":[4,10,201],"69":[6,10,93],"70":[2,5,48],"71":[5,1,32],"72":[2,5,1],"73":[3,6,75],"74":[3,6,242],"75":[1,5,21],"76":[3,6,80],"77":[3,6,287],"78":[2,6,24],"79":[3,1,37],"80":[3,3,45],"81":[3,3,1],"82":[5,5,20],"83":[5,5,14],"84":[5,5,13],"85":[3,5,30],"86":[2,5,25],"87":[1,6,11],"88":[4,6,295],"89":[6,1,50],"90":[1,6,93],"91":[1,6,23],"92":[6,7,169],"93":[6,7,42],"94":[3,7,80],"95":[11,6,100],"96":[10,15,105],"97":[9,15,50],"98":[6,1,50],"99":[1,6,93],"100":[1,6,23],"101":[6,7,164],"102":[6,7,40],"103":[3,7,81],"104":[11,6,100],"105":[10,15,128],"106":[9,15,125],"107":[4,6,31],"108":[9,10,31],"109":[9,10,1],"110":[5,15,136],"111":[5,15,268],"112":[2,1,102],"113":[3,2,177],"114":[4,2,115],"115":[5,7,120],"116":[6,2,122],"117":[6,2,43],"118":[3,2,30],"119":[3,2,38],"120":[3,5,73],"121":[3,5,47],"122":[5,5,114],"123":[2,5,20],"124":[2,5,13],"125":[4,1,1],"126":[5,4,66],"127":[1,4,22],"128":[5,4,91],"129":[3,4,47],"130":[3,4,58],"131":[5,4,130],"132":[5,4,13],"133":[1,4,48],"134":[1,4,123],"135":[4,4,116],"136":[3,4,21],"137":[2,1,36],"138":[1,2,18],"139":[5,2,33],"140":[4,2,39],"141":[5,6,60],"142":[5,6,178],"143":[1,2,57],"144":[7,2,49],"145":[4,2,88],"146":[8,2,32],"147":[4,2,35],"148":[4,6,29],"149":[4,6,86],"150":[5,2,1],"151":[5,7,52],"152":[5,7,64],"153":[3,2,43],"154":[3,2,13],"155":[3,2,28],"156":[5,1,99],"157":[4,5,31],"158":[5,9,36],"159":[5,5,60],"160":[1,10,3],"161":[1,10,5],"162":[1,10,5],"163":[1,1,1],"164":[2,1,37],"165":[3,1,54],"166":[5,1,98],"167":[5,6,61],"168":[5,6,181],"169":[7,1,49],"170":[4,1,88],"171":[8,1,32],"172":[4,1,35],"173":[4,4,29],"174":[4,4,73],"175":[5,1,1],"176":[5,6,52],"177":[5,6,47],"178":[3,6,44],"179":[3,1,13],"180":[3,6,28],"181":[1,1,1],"182":[2,1,34],"183":[3,1,54],"184":[1,1,45],"185":[4,2,33],"186":[6,2,41],"187":[1,1,35],"188":[7,1,49],"189":[4,1,98],"190":[8,1,52],"191":[5,1,124],"192":[5,1,1],"193":[5,6,52],"194":[5,6,61],"195":[4,1,27],"196":[3,5,38],"197":[3,1,13],"198":[3,1,28],"199":[2,1,36],"200":[2,2,122],"201":[4,2,39],"202":[5,6,74],"203":[5,6,180],"204":[7,2,49],"205":[4,2,88],"206":[8,2,32],"207":[4,2,35],"208":[4,6,29],"209":[4,6,85],"210":[5,2,1],"211":[5,7,52],"212":[5,7,63],"213":[3,2,44],"214":[3,2,13],"215":[3,2,28],"216":[2,1,49],"217":[2,2,101],"218":[3,2,111],"219":[1,2,85],"220":[1,2,68],"221":[4,2,118],"222":[3,1,69],"223":[1,3,89],"224":[2,3,160],"225":[3,3,157],"226":[3,3,181],"227":[2,3,185],"228":[2,3,143],"229":[2,3,177],"230":[2,3,163],"231":[5,3,214],"232":[6,1,129],"233":[3,6,169],"234":[4,6,171],"235":[3,6,42],"236":[1,1,69],"237":[4,1,34],"238":[2,1,30],"239":[2,1,79],"240":[3,1,32],"241":[1,1,40],"242":[4,1,147],"243":[3,1,60],"244":[4,3,140],"245":[1,3,212],"246":[3,3,35],"247":[2,3,24],"248":[5,1,70],"249":[2,5,64],"250":[4,5,45],"251":[5,5,163],"252":[3,9,96],"253":[1,5,9],"254":[2,1,34],"255":[3,2,80],"256":[4,2,135],"257":[2,2,118],"258":[1,2,62],"259":[3,2,242],"260":[3,1,14],"261":[2,3,105],"262":[2,3,118],"263":[2,3,77],"264":[3,1,1],"265":[2,3,47],"266":[2,3,21],"267":[6,4,21],"268":[4,4,99],"269":[6,3,1],"270":[3,8,103],"271":[5,3,42],"272":[2,7,52],"273":[8,3,69],"274":[3,3,12],"275":[4,5,23],"276":[6,5,47],"277":[6,5,55],"278":[8,5,148],"279":[3,3,302],"280":[3,3,31],"281":[4,5,29],"282":[4,5,29],"283":[8,3,106],"284":[3,3,26],"285":[4,1,60],"286":[3,1,1],"287":[2,3,46],"288":[2,3,130],"289":[6,3,1],"290":[3,8,102],"291":[5,3,42],"292":[2,3,52],"293":[8,3,69],"294":[3,3,12],"295":[4,5,23],"296":[6,9,47],"297":[6,9,55],"298":[8,9,145],"299":[3,5,295],"300":[3,3,31],"301":[4,5,29],"302":[4,5,29],"303":[8,3,106],"304":[3,3,26],"305":[4,1,1],"306":[2,4,54],"307":[2,4,21],"308":[6,5,21],"309":[4,5,106],"310":[3,5,52],"311":[6,4,23],"312":[6,4,29],"313":[4,4,247],"314":[3,4,24],"315":[4,6,23],"316":[6,6,47],"317":[6,6,89],"318":[3,4,49],"319":[6,6,20],"320":[4,6,216],"321":[2,6,47],"322":[3,4,31],"323":[7,6,54],"324":[4,6,29],"325":[4,6,74],"326":[3,4,26],"327":[1,1,1],"328":[4,1,208],"329":[4,1,89],"330":[6,1,77],"331":[3,1,71],"332":[5,1,52],"333":[3,1,74],"334":[6,4,125],"335":[6,1,16],"336":[6,6,86],"337":[7,1,109],"338":[4,1,122],"339":[5,1,82],"340":[4,1,24],"341":[4,1,60],"342":[7,1,55],"343":[3,1,61],"344":[3,3,144],"345":[1,3,110],"346":[2,3,73],"347":[3,6,119],"348":[1,3,169],"349":[1,3,288],"350":[3,1,1],"351":[2,3,53],"352":[2,3,21],"353":[6,4,21],"354":[4,4,97],"355":[3,4,52],"356":[6,3,23],"357":[6,3,28],"358":[4,3,222],"359":[3,3,24],"360":[4,5,23],"361":[6,5,47],"362":[6,5,89],"363":[3,3,49],"364":[6,5,21],"365":[4,5,216],"366":[2,5,47],"367":[4,5,49],"368":[3,3,31],"369":[7,5,54],"370":[4,5,29],"371":[4,5,78],"372":[3,3,26],"373":[1,1,1],"374":[2,1,47],"375":[5,2,75],"376":[3,2,45],"377":[5,2,79],"378":[5,2,32],"379":[2,2,114],"380":[5,2,1],"381":[5,7,76],"382":[8,7,34],"383":[10,7,50],"384":[5,1,56],"385":[4,5,62],"386":[2,5,97],"387":[2,5,178],"388":[2,1,1],"389":[4,2,83],"390":[4,2,234],"391":[1,2,15],"392":[1,4,24],"393":[4,4,13],"394":[4,4,4],"395":[4,4,4],"396":[1,4,2],"397":[1,1,12],"398":[2,1,96],"399":[6,2,113],"400":[5,1,41],"401":[7,5,31],"402":[9,5,192],"403":[9,5,80],"404":[8,5,209],"405":[4,5,39],"406":[5,5,34],"407":[2,1,102],"408":[12,2,1],"409":[2,14,58],"410":[2,14,1],"411":[2,16,27],"412":[2,16,33],"413":[2,16,85],"414":[2,1,43],"415":[2,2,23],"416":[1,2,15],"417":[3,2,101],"418":[3,2,37],"419":[9,2,63],"420":[6,1,134],"421":[3,6,101],"422":[5,8,66],"423":[5,8,47],"424":[14,8,189],"425":[4,8,45],"426":[5,8,89],"427":[1,6,155],"428":[7,6,62],"429":[7,11,77],"430":[4,11,103],"431":[5,11,208],"432":[4,11,42],"433":[4,11,22],"434":[5,11,84],"435":[2,1,35],"436":[3,2,68],"437":[3,2,53],"438":[2,5,29],"439":[1,5,24],"440":[6,1,133],"441":[5,6,235],"442":[1,9,304],"443":[1,6,200],"444":[5,6,193],"445":[1,6,161],"446":[4,1,128],"447":[4,4,61],"448":[1,4,72],"449":[4,1,52],"450":[6,4,36],"451":[1,10,57],"452":[7,10,154],"453":[3,4,59],"454":[6,4,112],"455":[2,10,88],"456":[7,4,231],"457":[5,10,122],"458":[4,4,65],"459":[1,4,87],"460":[6,4,1],"461":[5,10,145],"462":[3,10,133],"463":[2,10,119],"464":[1,4,216],"465":[1,4,198],"466":[4,5,140],"467":[7,4,189],"468":[6,4,57],"469":[1,4,60],"470":[7,1,156],"471":[3,1,83],"472":[3,3,36],"473":[3,3,39],"474":[3,1,52],"475":[6,3,34],"476":[1,3,44],"477":[6,4,113],"478":[3,4,98],"479":[6,4,145],"480":[2,4,110],"481":[5,4,122],"482":[4,4,67],"483":[1,4,86],"484":[6,3,1],"485":[5,9,148],"486":[3,9,121],"487":[2,9,134],"488":[1,3,244],"489":[1,3,105],"490":[4,3,149],"491":[1,3,205],"492":[3,4,68],"493":[2,4,190],"494":[4,3,1],"495":[2,7,44],"496":[5,1,1],"497":[1,5,93],"498":[1,5,16],"499":[1,6,79],"500":[1,6,61],"501":[1,6,58],"502":[1,6,49],"503":[1,6,62],"504":[3,5,22],"505":[3,8,46],"506":[3,8,46],"507":[2,8,62],"508":[5,8,45],"509":[2,8,58],"510":[4,8,32],"511":[5,8,56],"512":[4,1,23],"513":[2,4,14],"514":[2,4,24],"515":[6,4,30],"516":[1,4,95],"517":[1,1,29],"518":[3,1,36],"519":[2,4,65],"520":[4,4,226],"521":[5,1,74],"522":[2,1,52],"523":[9,1,94],"524":[4,1,98],"525":[3,1,73],"526":[6,3,61],"527":[5,3,32],"528":[4,8,11],"529":[2,8,86],"530":[7,3,20],"531":[8,3,193],"532":[4,1,103],"533":[7,4,112],"534":[7,4,173],"535":[8,4,62],"536":[5,4,1],"537":[7,8,46],"538":[4,8,90],"539":[17,8,52],"540":[12,8,94],"541":[16,8,119],"542":[15,8,67],"543":[13,8,55],"544":[7,8,60],"545":[4,8,134],"546":[5,1,49],"547":[5,6,72],"548":[2,6,112],"549":[5,6,156],"550":[4,6,34],"551":[1,1,118],"552":[10,1,109],"553":[4,11,131],"554":[4,11,109],"555":[5,11,158],"556":[3,1,107],"557":[4,1,62],"558":[5,1,40],"559":[4,6,79],"560":[7,6,78],"561":[4,1,74],"562":[3,4,141],"563":[5,6,54],"564":[5,4,51],"565":[4,4,63],"566":[13,4,87],"567":[4,1,81],"568":[5,4,62],"569":[5,4,58],"570":[3,4,46],"571":[6,1,78],"572":[2,6,60],"573":[2,6,115],"574":[4,8,131],"575":[6,6,65],"576":[4,6,137],"577":[4,6,110],"578":[4,6,26],"579":[5,1,21],"580":[3,5,63],"581":[3,5,64],"582":[1,8,31],"583":[1,8,43],"584":[1,8,43],"585":[1,8,59],"586":[1,8,66],"587":[1,8,32],"588":[1,8,39],"589":[1,8,46],"590":[1,8,25],"591":[1,8,28],"592":[1,8,30],"593":[1,8,30],"594":[1,8,27],"595":[6,5,117],"596":[9,5,118],"597":[4,1,1],"598":[6,4,61],"599":[6,4,78],"600":[4,4,43],"601":[6,4,36],"602":[7,9,72],"603":[6,9,115],"604":[5,9,46],"605":[3,1,69],"606":[3,1,1],"607":[6,3,63],"608":[6,3,182],"609":[4,3,41],"610":[6,3,36],"611":[7,8,72],"612":[6,8,114],"613":[5,3,46],"614":[4,1,1],"615":[6,4,61],"616":[6,4,62],"617":[6,4,63],"618":[6,4,44],"619":[3,4,105],"620":[5,6,15],"621":[3,6,41],"622":[5,4,45],"623":[3,1,1],"624":[3,3,39],"625":[3,3,65],"626":[5,6,39],"627":[3,3,33],"628":[1,1,102],"629":[3,1,166],"630":[2,4,68],"631":[2,4,24],"632":[4,6,34],"633":[4,6,33],"634":[4,6,109],"635":[4,1,184],"636":[3,1,239],"637":[3,1,43],"638":[2,3,131],"639":[1,1,57],"640":[3,1,1],"641":[6,3,62],"642":[6,3,64],"643":[4,3,42],"644":[6,3,36],"645":[7,8,72],"646":[6,8,116],"647":[5,8,46],"648":[5,1,106],"649":[5,5,11],"650":[1,10,80],"651":[2,10,90],"652":[3,5,109],"653":[9,5,57],"654":[4,5,123],"655":[8,5,67],"656":[4,5,125],"657":[10,5,65],"658":[14,5,74],"659":[2,5,32],"660":[3,1,92],"661":[6,3,1],"662":[1,7,104],"663":[6,3,96],"664":[2,3,15],"665":[5,1,54],"666":[5,5,106],"667":[4,10,94],"668":[1,1,166],"669":[2,1,39],"670":[1,1,64],"671":[3,1,114],"672":[2,1,92],"673":[3,1,161],"674":[2,1,71],"675":[2,3,193],"676":[2,1,72],"677":[1,1,138],"678":[3,1,124],"679":[3,1,160],"680":[4,1,213],"681":[3,5,226],"682":[3,1,173],"683":[1,1,51],"684":[1,1,12],"685":[5,1,145],"686":[5,5,57],"687":[4,1,84],"688":[6,4,52],"689":[4,10,81],"690":[6,4,130],"691":[6,10,131],"692":[3,4,120],"693":[4,7,118],"694":[2,7,32],"695":[10,4,97],"696":[7,4,73],"697":[4,8,36],"698":[1,1,18],"699":[1,1,120],"700":[3,1,138],"701":[3,1,26],"702":[9,3,26],"703":[6,12,41],"704":[6,12,59],"705":[4,3,32],"706":[4,3,109],"707":[9,7,28],"708":[11,7,90],"709":[4,3,43],"710":[6,3,37],"711":[5,3,63],"712":[1,18,5],"713":[1,18,4],"714":[13,3,1],"715":[8,15,41],"716":[4,15,34],"717":[4,1,32],"718":[3,4,49],"719":[3,4,37],"720":[3,4,39],"721":[5,7,82],"722":[4,7,84],"723":[3,4,41],"724":[4,7,48],"725":[3,7,46],"726":[6,7,122],"727":[3,4,1],"728":[10,7,63],"729":[12,7,31],"730":[3,1,187],"731":[3,1,161],"732":[2,1,28],"733":[3,2,48],"734":[6,2,100],"735":[6,2,37],"736":[7,2,49],"737":[9,2,105],"738":[4,2,18],"739":[7,2,96],"740":[3,1,43],"741":[2,3,63],"742":[6,3,87],"743":[1,8,9],"744":[1,8,29],"745":[9,8,143],"746":[9,3,102],"747":[1,11,101],"748":[1,11,109],"749":[3,3,20],"750":[1,6,31],"751":[1,6,56],"752":[8,1,1],"753":[1,8,26],"754":[3,8,20],"755":[1,8,21],"756":[3,8,12],"757":[1,11,13],"758":[1,11,3],"759":[1,11,2],"760":[1,8,10],"761":[1,8,2],"762":[1,8,27],"763":[2,8,7],"764":[2,8,13],"765":[2,8,11],"766":[4,8,1],"767":[1,12,17],"768":[1,12,20],"769":[1,8,5]},"averageFieldLength":[3.916883116883117,4.390909090909087,72.27532467532464],"storedFields":{"0":{"title":"Acessibilidade","titles":[]},"1":{"title":"Propriedades de acessibilidade","titles":["Acessibilidade"]},"2":{"title":"accessible","titles":["Acessibilidade","Propriedades de acessibilidade"]},"3":{"title":"accessibilityLabel","titles":["Acessibilidade","Propriedades de acessibilidade"]},"4":{"title":"accessibilityLabelledBy [Android]","titles":["Acessibilidade","Propriedades de acessibilidade"]},"5":{"title":"accessibilityHint","titles":["Acessibilidade","Propriedades de acessibilidade"]},"6":{"title":"iOS","titles":["Acessibilidade","Propriedades de acessibilidade","accessibilityHint"]},"7":{"title":"Android","titles":["Acessibilidade","Propriedades de acessibilidade","accessibilityHint"]},"8":{"title":"accessibilityLanguage [iOS]","titles":["Acessibilidade","Propriedades de acessibilidade"]},"9":{"title":"acessibilidadeIgnoresInvertColors [iOS]","titles":["Acessibilidade","Propriedades de acessibilidade"]},"10":{"title":"accessibilityLiveRegion [Android]","titles":["Acessibilidade","Propriedades de acessibilidade"]},"11":{"title":"accessibilityRole","titles":["Acessibilidade","Propriedades de acessibilidade"]},"12":{"title":"accessibilityState","titles":["Acessibilidade","Propriedades de acessibilidade"]},"13":{"title":"accessibilityValue","titles":["Acessibilidade","Propriedades de acessibilidade"]},"14":{"title":"accessibilityViewIsModal [iOS]","titles":["Acessibilidade","Propriedades de acessibilidade"]},"15":{"title":"accessibilityElementsHidden [iOS]","titles":["Acessibilidade","Propriedades de acessibilidade"]},"16":{"title":"aria-valuemax","titles":["Acessibilidade","Propriedades de acessibilidade"]},"17":{"title":"aria-valuemin","titles":["Acessibilidade","Propriedades de acessibilidade"]},"18":{"title":"aria-valuenow","titles":["Acessibilidade","Propriedades de acessibilidade"]},"19":{"title":"aria-valuetext","titles":["Acessibilidade","Propriedades de acessibilidade"]},"20":{"title":"aria-busy","titles":["Acessibilidade","Propriedades de acessibilidade"]},"21":{"title":"aria-checked","titles":["Acessibilidade","Propriedades de acessibilidade"]},"22":{"title":"aria-disabled","titles":["Acessibilidade","Propriedades de acessibilidade"]},"23":{"title":"aria-expanded","titles":["Acessibilidade","Propriedades de acessibilidade"]},"24":{"title":"aria-hidden","titles":["Acessibilidade","Propriedades de acessibilidade"]},"25":{"title":"aria-label","titles":["Acessibilidade","Propriedades de acessibilidade"]},"26":{"title":"aria-labelledby [Android]","titles":["Acessibilidade","Propriedades de acessibilidade"]},"27":{"title":"aria-live [Android]","titles":["Acessibilidade","Propriedades de acessibilidade"]},"28":{"title":"aria-modal [iOS]","titles":["Acessibilidade","Propriedades de acessibilidade"]},"29":{"title":"aria-selected","titles":["Acessibilidade","Propriedades de acessibilidade"]},"30":{"title":"importantForAccessibility [Android]","titles":["Acessibilidade","Propriedades de acessibilidade"]},"31":{"title":"onAccessibilityEscape [iOS]","titles":["Acessibilidade","Propriedades de acessibilidade"]},"32":{"title":"onAccessibilityTap","titles":["Acessibilidade","Propriedades de acessibilidade"]},"33":{"title":"onMagicTap [iOS]","titles":["Acessibilidade","Propriedades de acessibilidade"]},"34":{"title":"role","titles":["Acessibilidade","Propriedades de acessibilidade"]},"35":{"title":"Ações de acessibilidade","titles":["Acessibilidade"]},"36":{"title":"Verificando se um leitor de tela está ativado","titles":["Acessibilidade"]},"37":{"title":"Envio de eventos de acessibilidade Android [Android]","titles":["Acessibilidade"]},"38":{"title":"Testando o suporte do TalkBack [Android]","titles":["Acessibilidade"]},"39":{"title":"Testando o suporte do VoiceOver [iOS]","titles":["Acessibilidade"]},"40":{"title":"Recursos adicionais","titles":["Acessibilidade"]},"41":{"title":"Extensões de aplicativos","titles":[]},"42":{"title":"Uso de memória em extensões","titles":["Extensões de aplicativos"]},"43":{"title":"Widget Today","titles":["Extensões de aplicativos","Uso de memória em extensões"]},"44":{"title":"Outras extensões de aplicativos","titles":["Extensões de aplicativos","Uso de memória em extensões"]},"45":{"title":"Animações","titles":[]},"46":{"title":"Animated API","titles":["Animações"]},"47":{"title":"Configurando animações","titles":["Animações"]},"48":{"title":"Compondo animações","titles":["Animações"]},"49":{"title":"Combinando valores animados","titles":["Animações"]},"50":{"title":"Interpolação","titles":["Animações"]},"51":{"title":"Rastreando valores dinâmicos","titles":["Animações"]},"52":{"title":"Gestos de rastreamento","titles":["Animações"]},"53":{"title":"ScrollView com exemplo de evento animado","titles":["Animações"]},"54":{"title":"PanResponder com exemplo de evento animado","titles":["Animações"]},"55":{"title":"Respondendo ao valor atual da animação","titles":["Animações"]},"56":{"title":"Usando o driver nativo","titles":["Animações"]},"57":{"title":"Ressalvas","titles":["Animações"]},"58":{"title":"Tenha em mente","titles":["Animações"]},"59":{"title":"Exemplos adicionais","titles":["Animações"]},"60":{"title":"API LayoutAnimation","titles":["Animações"]},"61":{"title":"Notas Adicionais","titles":["Animações"]},"62":{"title":"requestAnimationFrame","titles":["Animações","Notas Adicionais"]},"63":{"title":"setNativeProps","titles":["Animações","Notas Adicionais"]},"64":{"title":"Acelerando sua fase de construção","titles":[]},"65":{"title":"Crie apenas uma ABI durante o desenvolvimento (somente Android)","titles":["Acelerando sua fase de construção"]},"66":{"title":"Use um cache do compilador","titles":["Acelerando sua fase de construção"]},"67":{"title":"Caches locais","titles":["Acelerando sua fase de construção","Use um cache do compilador"]},"68":{"title":"Configuração específica do XCode","titles":["Acelerando sua fase de construção","Use um cache do compilador"]},"69":{"title":"Usando esta abordagem em um IC","titles":["Acelerando sua fase de construção","Use um cache do compilador"]},"70":{"title":"Caches distribuídos","titles":["Acelerando sua fase de construção"]},"71":{"title":"Construção para dispositivos de TV","titles":[]},"72":{"title":"Android TV","titles":["Construção para dispositivos de TV"]},"73":{"title":"Mudanças de compilação","titles":["Construção para dispositivos de TV","Android TV"]},"74":{"title":"Mudanças de código","titles":["Construção para dispositivos de TV","Android TV"]},"75":{"title":"tvOS","titles":["Construção para dispositivos de TV"]},"76":{"title":"Alterações de compilação","titles":["Construção para dispositivos de TV","tvOS"]},"77":{"title":"Mudanças de código","titles":["Construção para dispositivos de TV","tvOS"]},"78":{"title":"Problemas conhecidos","titles":["Construção para dispositivos de TV","tvOS"]},"79":{"title":"Referência de Cores","titles":[]},"80":{"title":"APIs de cores","titles":["Referência de Cores"]},"81":{"title":"Representações de cores","titles":["Referência de Cores"]},"82":{"title":"Vermelho Verde Azul (RGB)","titles":["Referência de Cores","Representações de cores"]},"83":{"title":"Tonalidade Saturação Iluminação (HSL)","titles":["Referência de Cores","Representações de cores"]},"84":{"title":"Matiz Brancura Escuridão (HWB)","titles":["Referência de Cores","Representações de cores"]},"85":{"title":"Informações de cor","titles":["Referência de Cores","Representações de cores"]},"86":{"title":"Cores nomeadas","titles":["Referência de Cores","Representações de cores"]},"87":{"title":"transparent","titles":["Referência de Cores","Representações de cores","Cores nomeadas"]},"88":{"title":"Palavras-chave das cores","titles":["Referência de Cores","Representações de cores","Cores nomeadas"]},"89":{"title":"Comunicação entre nativo e React Native","titles":[]},"90":{"title":"Introdução","titles":["Comunicação entre nativo e React Native"]},"91":{"title":"Propriedades","titles":["Comunicação entre nativo e React Native"]},"92":{"title":"Passando propriedades de Native para React Native","titles":["Comunicação entre nativo e React Native","Propriedades"]},"93":{"title":"Passando propriedades do React Native para Native","titles":["Comunicação entre nativo e React Native","Propriedades"]},"94":{"title":"Limites de propriedades","titles":["Comunicação entre nativo e React Native","Propriedades"]},"95":{"title":"Outras formas de interação entre idiomas (eventos e módulos nativos)","titles":["Comunicação entre nativo e React Native"]},"96":{"title":"Chamando funções React Native a partir de nativos (eventos)","titles":["Comunicação entre nativo e React Native","Outras formas de interação entre idiomas (eventos e módulos nativos)"]},"97":{"title":"Chamando funções nativas do React Native (módulos nativos)","titles":["Comunicação entre nativo e React Native","Outras formas de interação entre idiomas (eventos e módulos nativos)"]},"98":{"title":"Comunicação entre nativo e React Native","titles":[]},"99":{"title":"Introdução","titles":["Comunicação entre nativo e React Native"]},"100":{"title":"Propriedades","titles":["Comunicação entre nativo e React Native"]},"101":{"title":"Passando propriedades de Native para React Native","titles":["Comunicação entre nativo e React Native","Propriedades"]},"102":{"title":"Passando propriedades do React Native para Native","titles":["Comunicação entre nativo e React Native","Propriedades"]},"103":{"title":"Limites de propriedades","titles":["Comunicação entre nativo e React Native","Propriedades"]},"104":{"title":"Outras formas de interação entre linguagens (eventos e módulos nativos)","titles":["Comunicação entre nativo e React Native"]},"105":{"title":"Chamando funções React Native a partir de nativos (eventos)","titles":["Comunicação entre nativo e React Native","Outras formas de interação entre linguagens (eventos e módulos nativos)"]},"106":{"title":"Chamando funções nativas do React Native (módulos nativos)","titles":["Comunicação entre nativo e React Native","Outras formas de interação entre linguagens (eventos e módulos nativos)"]},"107":{"title":"Fluxo de cálculo de layout","titles":["Comunicação entre nativo e React Native"]},"108":{"title":"Layout de um componente nativo incorporado no React Native","titles":["Comunicação entre nativo e React Native","Fluxo de cálculo de layout"]},"109":{"title":"Layout de um componente React Native incorporado no nativo","titles":["Comunicação entre nativo e React Native","Fluxo de cálculo de layout"]},"110":{"title":"React Native com tamanho fixo","titles":["Comunicação entre nativo e React Native","Fluxo de cálculo de layout","Layout de um componente React Native incorporado no nativo"]},"111":{"title":"React Native com tamanho flexível","titles":["Comunicação entre nativo e React Native","Fluxo de cálculo de layout","Layout de um componente React Native incorporado no nativo"]},"112":{"title":"Manipulação Direta","titles":[]},"113":{"title":"setNativeProps com TouchableOpacity","titles":["Manipulação Direta"]},"114":{"title":"Componentes compostos e setNativeProps","titles":["Manipulação Direta"]},"115":{"title":"Encaminha setNativeProps para um filho","titles":["Manipulação Direta","Componentes compostos e setNativeProps",null]},"116":{"title":"setNativeProps para editar o valor TextInput","titles":["Manipulação Direta"]},"117":{"title":"Evitando conflitos com a função render","titles":["Manipulação Direta"]},"118":{"title":"setNativeProps e shouldComponentUpdate","titles":["Manipulação Direta"]},"119":{"title":"Outros métodos nativos","titles":["Manipulação Direta"]},"120":{"title":"measure(callback)","titles":["Manipulação Direta","Outros métodos nativos"]},"121":{"title":"measureInWindow(callback)","titles":["Manipulação Direta","Outros métodos nativos"]},"122":{"title":"measureLayout(relativeToNativeComponentRef, onSuccess, onFail)","titles":["Manipulação Direta","Outros métodos nativos"]},"123":{"title":"focus()","titles":["Manipulação Direta","Outros métodos nativos"]},"124":{"title":"blur()","titles":["Manipulação Direta","Outros métodos nativos"]},"125":{"title":"Noções básicas de depuração","titles":[]},"126":{"title":"Acessando o menu de desenvolvimento","titles":["Noções básicas de depuração"]},"127":{"title":"LogBox","titles":["Noções básicas de depuração"]},"128":{"title":"Erros e avisos do console","titles":["Noções básicas de depuração"]},"129":{"title":"Erros não tratados","titles":["Noções básicas de depuração"]},"130":{"title":"Erros de sintaxe","titles":["Noções básicas de depuração"]},"131":{"title":"Ferramentas para desenvolvedores do Chrome","titles":["Noções básicas de depuração"]},"132":{"title":"Depuração em um dispositivo físico","titles":["Noções básicas de depuração"]},"133":{"title":"Android","titles":["Noções básicas de depuração"]},"134":{"title":"iOS","titles":["Noções básicas de depuração"]},"135":{"title":"Ferramentas para desenvolvedores Safari","titles":["Noções básicas de depuração"]},"136":{"title":"Monitor de desempenho","titles":["Noções básicas de depuração"]},"137":{"title":"Instalando dependências","titles":[]},"138":{"title":"Node","titles":["Instalando dependências"]},"139":{"title":"Kit de desenvolvimento do Java","titles":["Instalando dependências"]},"140":{"title":"Ambiente de desenvolvimento Android","titles":["Instalando dependências"]},"141":{"title":"1. Instale o Android Studio","titles":["Instalando dependências","Ambiente de desenvolvimento Android"]},"142":{"title":"2. Instale o Android SDK","titles":["Instalando dependências","Ambiente de desenvolvimento Android"]},"143":{"title":"Watchman","titles":["Instalando dependências"]},"144":{"title":"Interface de linha de comando nativa do React","titles":["Instalando dependências"]},"145":{"title":"Criando um novo aplicativo","titles":["Instalando dependências"]},"146":{"title":"[Opcional] Usando uma versão ou modelo específico","titles":["Instalando dependências"]},"147":{"title":"Preparando o dispositivo Android","titles":["Instalando dependências"]},"148":{"title":"Usando um dispositivo físico","titles":["Instalando dependências","Preparando o dispositivo Android"]},"149":{"title":"Usando um dispositivo virtual","titles":["Instalando dependências","Preparando o dispositivo Android"]},"150":{"title":"Executando seu aplicativo React Native","titles":["Instalando dependências"]},"151":{"title":"Etapa 1: iniciar o Metro","titles":["Instalando dependências","Executando seu aplicativo React Native"]},"152":{"title":"Etapa 2: inicie seu aplicativo","titles":["Instalando dependências","Executando seu aplicativo React Native"]},"153":{"title":"Modificando seu aplicativo","titles":["Instalando dependências"]},"154":{"title":"É isso!","titles":["Instalando dependências"]},"155":{"title":"E agora?","titles":["Instalando dependências"]},"156":{"title":"Configurando o ambiente de desenvolvimento","titles":[]},"157":{"title":"Expo Go Início Rápido","titles":["Configurando o ambiente de desenvolvimento"]},"158":{"title":"Executando seu aplicativo React Native","titles":["Configurando o ambiente de desenvolvimento","Expo Go Início Rápido"]},"159":{"title":"React Native CLI Início Rápido","titles":["Configurando o ambiente de desenvolvimento"]},"160":{"title":"macOS","titles":["Configurando o ambiente de desenvolvimento","React Native CLI Início Rápido"]},"161":{"title":"Windows","titles":["Configurando o ambiente de desenvolvimento","React Native CLI Início Rápido"]},"162":{"title":"Linux","titles":["Configurando o ambiente de desenvolvimento","React Native CLI Início Rápido"]},"163":{"title":"Android","titles":[]},"164":{"title":"Instalando dependências","titles":["Android"]},"165":{"title":"Node & Watchman","titles":["Android"]},"166":{"title":"kit de desenvolvimento do Java","titles":["Android"]},"167":{"title":"1. Instale o Android Studio","titles":["Android","kit de desenvolvimento do Java"]},"168":{"title":"2. Instale o Android SDK","titles":["Android","kit de desenvolvimento do Java"]},"169":{"title":"Interface de linha de comando nativa do React","titles":["Android"]},"170":{"title":"Criando um novo aplicativo","titles":["Android"]},"171":{"title":"[Opcional] Usando uma versão ou modelo específico","titles":["Android"]},"172":{"title":"Preparando o dispositivo Android","titles":["Android"]},"173":{"title":"Usando um dispositivo físico","titles":["Android","Preparando o dispositivo Android"]},"174":{"title":"Usando um dispositivo virtual","titles":["Android","Preparando o dispositivo Android"]},"175":{"title":"Executando seu aplicativo React Native","titles":["Android"]},"176":{"title":"Etapa 1: iniciar o Metro","titles":["Android","Executando seu aplicativo React Native"]},"177":{"title":"Step 2: Inicie sua aplicação","titles":["Android","Executando seu aplicativo React Native"]},"178":{"title":"Modificando seu aplicativo","titles":["Android","Executando seu aplicativo React Native"]},"179":{"title":"É isso!","titles":["Android"]},"180":{"title":"E agora?","titles":["Android","É isso!","Modificando seu aplicativo"]},"181":{"title":"iOS","titles":[]},"182":{"title":"Instalando dependências","titles":["iOS"]},"183":{"title":"Node e Watchman","titles":["iOS"]},"184":{"title":"Xcode","titles":["iOS"]},"185":{"title":"Ferramentas de linha de comando","titles":["iOS","Xcode"]},"186":{"title":"Instalando um simulador iOS no Xcode","titles":["iOS","Xcode"]},"187":{"title":"CocoaPods","titles":["iOS"]},"188":{"title":"Interface de linha de comando nativa do React","titles":["iOS"]},"189":{"title":"Criando um novo aplicativo","titles":["iOS"]},"190":{"title":"[Opcional] Usando uma versão ou modelo específico","titles":["iOS"]},"191":{"title":"[Opcional] Configurando seu ambiente","titles":["iOS"]},"192":{"title":"Executando seu aplicativo React Native","titles":["iOS"]},"193":{"title":"Etapa 1: iniciar o Metro","titles":["iOS","Executando seu aplicativo React Native"]},"194":{"title":"Etapa 2: inicie seu aplicativo","titles":["iOS","Executando seu aplicativo React Native"]},"195":{"title":"Executando em um dispositivo","titles":["iOS"]},"196":{"title":"Modificando seu aplicativo","titles":["iOS","Executando em um dispositivo"]},"197":{"title":"É isso!","titles":["iOS"]},"198":{"title":"E agora?","titles":["iOS"]},"199":{"title":"Instalando dependências","titles":[]},"200":{"title":"Node, JDK","titles":["Instalando dependências"]},"201":{"title":"Ambiente de desenvolvimento Android","titles":["Instalando dependências"]},"202":{"title":"1. Instale o Android Studio","titles":["Instalando dependências","Ambiente de desenvolvimento Android"]},"203":{"title":"2. Instale o Android SDK","titles":["Instalando dependências","Ambiente de desenvolvimento Android"]},"204":{"title":"Interface de linha de comando nativa do React","titles":["Instalando dependências"]},"205":{"title":"Criando um novo aplicativo","titles":["Instalando dependências"]},"206":{"title":"[Opcional] Usando uma versão ou modelo específico","titles":["Instalando dependências"]},"207":{"title":"Preparando o dispositivo Android","titles":["Instalando dependências"]},"208":{"title":"Usando um dispositivo físico","titles":["Instalando dependências","Preparando o dispositivo Android"]},"209":{"title":"Usando um dispositivo virtual","titles":["Instalando dependências","Preparando o dispositivo Android"]},"210":{"title":"Executando seu aplicativo React Native","titles":["Instalando dependências"]},"211":{"title":"Etapa 1: iniciar o Metro","titles":["Instalando dependências","Executando seu aplicativo React Native"]},"212":{"title":"Etapa 2: inicie seu aplicativo","titles":["Instalando dependências","Executando seu aplicativo React Native"]},"213":{"title":"Modificando seu aplicativo","titles":["Instalando dependências"]},"214":{"title":"É isso!","titles":["Instalando dependências"]},"215":{"title":"E agora?","titles":["Instalando dependências"]},"216":{"title":"Atualização rápida","titles":[]},"217":{"title":"Como funciona","titles":["Atualização rápida"]},"218":{"title":"Resiliência a erros","titles":["Atualização rápida"]},"219":{"title":"Limitações","titles":["Atualização rápida"]},"220":{"title":"Dicas","titles":["Atualização rápida"]},"221":{"title":"Atualização rápida e ganchos","titles":["Atualização rápida"]},"222":{"title":"Layout com Flexbox","titles":[]},"223":{"title":"Flex","titles":["Layout com Flexbox"]},"224":{"title":"Direção flexível","titles":["Layout com Flexbox"]},"225":{"title":"Direção do layout","titles":["Layout com Flexbox"]},"226":{"title":"Justificar o conteúdo","titles":["Layout com Flexbox"]},"227":{"title":"Alinhar itens","titles":["Layout com Flexbox"]},"228":{"title":"Alinhar-se","titles":["Layout com Flexbox"]},"229":{"title":"Alinhar conteúdo","titles":["Layout com Flexbox"]},"230":{"title":"Flex Wrap","titles":["Layout com Flexbox"]},"231":{"title":"Base Flexível, Crescer e Encolher","titles":["Layout com Flexbox"]},"232":{"title":"Lacuna de linha, lacuna de coluna e lacuna","titles":[]},"233":{"title":"Largura e altura","titles":["Lacuna de linha, lacuna de coluna e lacuna"]},"234":{"title":"Layout Absoluto e Relativo","titles":["Lacuna de linha, lacuna de coluna e lacuna"]},"235":{"title":"Indo mais fundo","titles":["Lacuna de linha, lacuna de coluna e lacuna"]},"236":{"title":"Introdução","titles":[]},"237":{"title":"Como usar esses documentos","titles":["Introdução"]},"238":{"title":"Pré-requisitos","titles":["Introdução"]},"239":{"title":"Exemplos interativos","titles":["Introdução"]},"240":{"title":"Notas do desenvolvedor","titles":["Introdução"]},"241":{"title":"Formatação","titles":["Introdução"]},"242":{"title":"Tratamento de entrada de texto","titles":[]},"243":{"title":"Lidando com toques","titles":[]},"244":{"title":"Exibindo um botão básico","titles":["Lidando com toques"]},"245":{"title":"Tocáveis","titles":["Lidando com toques"]},"246":{"title":"Rolar e deslizar","titles":["Lidando com toques"]},"247":{"title":"Problemas conhecidos","titles":["Lidando com toques"]},"248":{"title":"Sistema de resposta por gestos","titles":[]},"249":{"title":"Melhores Práticas","titles":["Sistema de resposta por gestos"]},"250":{"title":"TouchableHighlight and Touchable*","titles":["Sistema de resposta por gestos"]},"251":{"title":"Ciclo de vida do Respondente","titles":["Sistema de resposta por gestos"]},"252":{"title":"Capturar manipuladores ShouldSet","titles":["Sistema de resposta por gestos","Ciclo de vida do Respondente"]},"253":{"title":"PanResponder","titles":["Sistema de resposta por gestos"]},"254":{"title":"Headless JS","titles":[]},"255":{"title":"A API JS","titles":["Headless JS"]},"256":{"title":"A API da plataforma","titles":["Headless JS"]},"257":{"title":"Novas tentativas","titles":["Headless JS"]},"258":{"title":"Ressalvas","titles":["Headless JS"]},"259":{"title":"Exemplo de uso","titles":["Headless JS"]},"260":{"title":"Altura e Largura","titles":[]},"261":{"title":"Dimensões fixas","titles":["Altura e Largura"]},"262":{"title":"Dimensões flexíveis","titles":["Altura e Largura"]},"263":{"title":"Dimensões percentuais","titles":["Altura e Largura"]},"264":{"title":"Android (Java)","titles":[]},"265":{"title":"Conceitos chave","titles":["Android (Java)"]},"266":{"title":"Pré-requisitos","titles":["Android (Java)"]},"267":{"title":"1. Configure a estrutura de diretórios","titles":["Android (Java)","Pré-requisitos"]},"268":{"title":"2. Instale dependências JavaScript","titles":["Android (Java)","Pré-requisitos"]},"269":{"title":"Adicionando React Native ao seu aplicativo","titles":["Android (Java)"]},"270":{"title":"Configurando o Gradle","titles":["Android (Java)","Adicionando React Native ao seu aplicativo"]},"271":{"title":"Habilitar autolinking de módulos nativos","titles":["Android (Java)"]},"272":{"title":"Configurando permissões","titles":["Android (Java)","Habilitar autolinking de módulos nativos"]},"273":{"title":"Tráfego de texto simples (nível de API 28+)","titles":["Android (Java)"]},"274":{"title":"Integração de código","titles":["Android (Java)"]},"275":{"title":"O componente React Native","titles":["Android (Java)","Integração de código"]},"276":{"title":"1. Crie um arquivo index.js","titles":["Android (Java)","Integração de código"]},"277":{"title":"2. Adicione seu código React Native","titles":["Android (Java)","Integração de código"]},"278":{"title":"3. Configure permissões para sobreposição de erros de desenvolvimento","titles":["Android (Java)","Integração de código"]},"279":{"title":"A mágica: ReactRootView","titles":["Android (Java)"]},"280":{"title":"Teste sua integração","titles":["Android (Java)"]},"281":{"title":"1. Execute o empacotador","titles":["Android (Java)","Teste sua integração"]},"282":{"title":"2. Execute o aplicativo","titles":["Android (Java)","Teste sua integração"]},"283":{"title":"Criando uma versão de lançamento no Android Studio","titles":["Android (Java)"]},"284":{"title":"E agora?","titles":["Android (Java)"]},"285":{"title":"Integração com aplicativos existentes","titles":[]},"286":{"title":"Android (Kotlin)","titles":[]},"287":{"title":"Conceitos chave","titles":["Android (Kotlin)"]},"288":{"title":"Pré-requisitos","titles":["Android (Kotlin)"]},"289":{"title":"Adicionando React Native ao seu aplicativo","titles":["Android (Kotlin)"]},"290":{"title":"Configurando o Gradle","titles":["Android (Kotlin)","Adicionando React Native ao seu aplicativo"]},"291":{"title":"Habilitar autolinking de módulos nativos","titles":["Android (Kotlin)"]},"292":{"title":"Configurando permissões","titles":["Android (Kotlin)"]},"293":{"title":"Tráfego de texto simples (nível de API 28+)","titles":["Android (Kotlin)"]},"294":{"title":"Integração de código","titles":["Android (Kotlin)"]},"295":{"title":"O componente React Native","titles":["Android (Kotlin)","Integração de código"]},"296":{"title":"1. Crie um arquivo index.js","titles":["Android (Kotlin)","Integração de código","O componente React Native"]},"297":{"title":"2. Adicione seu código React Native","titles":["Android (Kotlin)","Integração de código","O componente React Native"]},"298":{"title":"3. Configure permissões para sobreposição de erros de desenvolvimento","titles":["Android (Kotlin)","Integração de código","O componente React Native"]},"299":{"title":"A mágica: ReactRootView","titles":["Android (Kotlin)","Integração de código"]},"300":{"title":"Teste sua integração","titles":["Android (Kotlin)"]},"301":{"title":"1. Execute o empacotador","titles":["Android (Kotlin)","Teste sua integração"]},"302":{"title":"2. Execute o aplicativo","titles":["Android (Kotlin)","Teste sua integração"]},"303":{"title":"Criando uma versão de lançamento no Android Studio","titles":["Android (Kotlin)"]},"304":{"title":"E agora?","titles":["Android (Kotlin)"]},"305":{"title":"iOS (Objective-C)","titles":[]},"306":{"title":"Conceitos chave","titles":["iOS (Objective-C)"]},"307":{"title":"Pré-requisitos","titles":["iOS (Objective-C)"]},"308":{"title":"1. Configure a estrutura de diretórios","titles":["iOS (Objective-C)","Pré-requisitos"]},"309":{"title":"2. Instale dependências JavaScript","titles":["iOS (Objective-C)","Pré-requisitos"]},"310":{"title":"3. Instale CocoaPods","titles":["iOS (Objective-C)","Pré-requisitos"]},"311":{"title":"Adicionando React Native ao seu aplicativo","titles":["iOS (Objective-C)"]},"312":{"title":"Ferramentas de linha de comando para Xcode","titles":["iOS (Objective-C)"]},"313":{"title":"Configurando dependências do CocoaPods","titles":["iOS (Objective-C)"]},"314":{"title":"Integração de código","titles":["iOS (Objective-C)"]},"315":{"title":"O componente React Native","titles":["iOS (Objective-C)","Integração de código"]},"316":{"title":"1. Crie um arquivo index.js","titles":["iOS (Objective-C)","Integração de código"]},"317":{"title":"2. Adicione seu código React Native","titles":["iOS (Objective-C)","Integração de código"]},"318":{"title":"A mágica: RCTRootView","titles":["iOS (Objective-C)"]},"319":{"title":"1. Crie um caminho de evento","titles":["iOS (Objective-C)","A mágica: RCTRootView"]},"320":{"title":"2. Manipulador de eventos","titles":["iOS (Objective-C)","A mágica: RCTRootView"]},"321":{"title":"3. Conecte","titles":["iOS (Objective-C)","A mágica: RCTRootView"]},"322":{"title":"Teste sua integração","titles":["iOS (Objective-C)"]},"323":{"title":"1. Adicionar exceção de segurança de transporte de aplicativos","titles":["iOS (Objective-C)","Teste sua integração"]},"324":{"title":"2. Execute o empacotador","titles":["iOS (Objective-C)","Teste sua integração"]},"325":{"title":"3. Execute o aplicativo","titles":["iOS (Objective-C)","Teste sua integração"]},"326":{"title":"E agora?","titles":["iOS (Objective-C)"]},"327":{"title":"Imagens","titles":[]},"328":{"title":"Recursos de imagem estática","titles":["Imagens"]},"329":{"title":"Recursos estáticos sem imagem","titles":["Imagens"]},"330":{"title":"Imagens dos recursos do aplicativo híbrido","titles":["Imagens"]},"331":{"title":"Imagens de rede","titles":["Imagens"]},"332":{"title":"Solicitações de rede para imagens","titles":["Imagens"]},"333":{"title":"URI com dados","titles":["Imagens"]},"334":{"title":"Controle de cache (somente iOS)","titles":["Imagens","URI com dados"]},"335":{"title":"Imagens do sistema de arquivos local","titles":["Imagens"]},"336":{"title":"Melhor imagem do rolo da câmera","titles":["Imagens","Imagens do sistema de arquivos local"]},"337":{"title":"Por que não dimensionar tudo automaticamente?","titles":["Imagens"]},"338":{"title":"Fonte como um objeto","titles":["Imagens"]},"339":{"title":"Imagem de fundo via aninhamento","titles":["Imagens"]},"340":{"title":"Estilo arredondado do iOS","titles":["Imagens"]},"341":{"title":"Decodificação fora do thread","titles":["Imagens"]},"342":{"title":"Configurando limites de cache de imagens do iOS","titles":["Imagens"]},"343":{"title":"Fundamentos do React","titles":[]},"344":{"title":"Seu primeiro componente","titles":["Fundamentos do React"]},"345":{"title":"JSX","titles":["Fundamentos do React"]},"346":{"title":"Componentes personalizados","titles":["Fundamentos do React"]},"347":{"title":"Notas do desenvolvedor","titles":["Fundamentos do React","Componentes personalizados",null]},"348":{"title":"Adereços","titles":["Fundamentos do React"]},"349":{"title":"Estado","titles":["Fundamentos do React"]},"350":{"title":"iOS (Swift)","titles":[]},"351":{"title":"Conceitos chave","titles":["iOS (Swift)"]},"352":{"title":"Pré-requisitos","titles":["iOS (Swift)"]},"353":{"title":"1. Configure a estrutura de diretórios","titles":["iOS (Swift)","Pré-requisitos"]},"354":{"title":"2. Instale dependências JavaScript","titles":["iOS (Swift)","Pré-requisitos"]},"355":{"title":"3. Instale CocoaPods","titles":["iOS (Swift)","Pré-requisitos"]},"356":{"title":"Adicionando React Native ao seu aplicativo","titles":["iOS (Swift)"]},"357":{"title":"Ferramentas de linha de comando para Xcode","titles":["iOS (Swift)"]},"358":{"title":"Configurando dependências do CocoaPods","titles":["iOS (Swift)"]},"359":{"title":"Integração de código","titles":["iOS (Swift)"]},"360":{"title":"O componente React Native","titles":["iOS (Swift)","Integração de código"]},"361":{"title":"1. Crie um arquivo index.js","titles":["iOS (Swift)","Integração de código"]},"362":{"title":"2. Adicione seu código React Native","titles":["iOS (Swift)","Integração de código"]},"363":{"title":"A mágica: RCTRootView","titles":["iOS (Swift)"]},"364":{"title":"1. Crie um caminho de evento","titles":["iOS (Swift)","A mágica: RCTRootView"]},"365":{"title":"2. Manipulador de eventos","titles":["iOS (Swift)","A mágica: RCTRootView"]},"366":{"title":"3. Conecte","titles":["iOS (Swift)","A mágica: RCTRootView"]},"367":{"title":"4. Referência da janela","titles":["iOS (Swift)","A mágica: RCTRootView"]},"368":{"title":"Teste sua integração","titles":["iOS (Swift)"]},"369":{"title":"1. Adicionar exceção de segurança de transporte de aplicativos","titles":["iOS (Swift)","Teste sua integração"]},"370":{"title":"2. Execute o empacotador","titles":["iOS (Swift)","Teste sua integração"]},"371":{"title":"3. Execute o aplicativo","titles":["iOS (Swift)","Teste sua integração"]},"372":{"title":"E agora?","titles":["iOS (Swift)"]},"373":{"title":"Introdução","titles":[null]},"374":{"title":"Usando bibliotecas","titles":[]},"375":{"title":"Selecionando um gerenciador de pacotes","titles":["Usando bibliotecas"]},"376":{"title":"Instalando uma biblioteca","titles":["Usando bibliotecas"]},"377":{"title":"Vinculando código nativo no iOS","titles":["Usando bibliotecas"]},"378":{"title":"Vinculando código nativo no Android","titles":["Usando bibliotecas"]},"379":{"title":"Encontrando Bibliotecas","titles":["Usando bibliotecas"]},"380":{"title":"Determinando a compatibilidade da biblioteca","titles":["Usando bibliotecas"]},"381":{"title":"Funciona com React Native?","titles":["Usando bibliotecas","Determinando a compatibilidade da biblioteca"]},"382":{"title":"Funciona nas plataformas suportadas pelo meu aplicativo?","titles":["Usando bibliotecas","Determinando a compatibilidade da biblioteca"]},"383":{"title":"Funciona com a versão do meu aplicativo React Native?","titles":["Usando bibliotecas","Determinando a compatibilidade da biblioteca"]},"384":{"title":"Componentes principais e componentes nativos","titles":[]},"385":{"title":"Visualizações e desenvolvimento móvel","titles":["Componentes principais e componentes nativos"]},"386":{"title":"Componentes nativos","titles":["Componentes principais e componentes nativos"]},"387":{"title":"Core Componentes","titles":["Componentes principais e componentes nativos"]},"388":{"title":"Ambiente JavaScript","titles":[]},"389":{"title":"Tempo de execução JavaScript","titles":["Ambiente JavaScript"]},"390":{"title":"Transformadores de sintaxe JavaScript","titles":["Ambiente JavaScript"]},"391":{"title":"Polifills","titles":["Ambiente JavaScript"]},"392":{"title":"Navegador","titles":["Ambiente JavaScript","Polifills",null]},"393":{"title":"ECMAScript 2015 (ES6)","titles":["Ambiente JavaScript","Polifills",null]},"394":{"title":"ECMAScript 2016 (ES7)","titles":["Ambiente JavaScript","Polifills",null]},"395":{"title":"ECMAScript 2017 (ES8)","titles":["Ambiente JavaScript","Polifills",null]},"396":{"title":"Específico","titles":["Ambiente JavaScript","Polifills",null]},"397":{"title":"Metro","titles":[]},"398":{"title":"Configurando Metro","titles":["Metro"]},"399":{"title":"Avançado: usando uma função de configuração","titles":["Metro","Configurando Metro"]},"400":{"title":"Integração com um fragmento Android","titles":[]},"401":{"title":"1. Adicione React Native ao seu aplicativo","titles":["Integração com um fragmento Android"]},"402":{"title":"2. Integrando seu aplicativo com um fragmento React Native","titles":["Integração com um fragmento Android"]},"403":{"title":"3. Adicione um FrameLayout para o fragmento React Native","titles":["Integração com um fragmento Android"]},"404":{"title":"4. Adicionar um fragmento React Native ao FrameLayout","titles":["Integração com um fragmento Android"]},"405":{"title":"5. Teste sua integração","titles":["Integração com um fragmento Android"]},"406":{"title":"6. Configuração adicional – Módulos nativos","titles":["Integração com um fragmento Android"]},"407":{"title":"Vinculando Bibliotecas","titles":[]},"408":{"title":"Aqui estão algumas etapas para vincular suas bibliotecas que contêm código nativo","titles":["Vinculando Bibliotecas"]},"409":{"title":"Vinculação automática","titles":["Vinculando Bibliotecas","Aqui estão algumas etapas para vincular suas bibliotecas que contêm código nativo"]},"410":{"title":"Vinculação manual","titles":["Vinculando Bibliotecas","Aqui estão algumas etapas para vincular suas bibliotecas que contêm código nativo"]},"411":{"title":"Passo 1","titles":["Vinculando Bibliotecas","Aqui estão algumas etapas para vincular suas bibliotecas que contêm código nativo","Vinculação manual"]},"412":{"title":"Passo 2","titles":["Vinculando Bibliotecas","Aqui estão algumas etapas para vincular suas bibliotecas que contêm código nativo","Vinculação manual"]},"413":{"title":"Etapa 3","titles":["Vinculando Bibliotecas","Aqui estão algumas etapas para vincular suas bibliotecas que contêm código nativo","Vinculação manual"]},"414":{"title":"Mais recursos","titles":[]},"415":{"title":"Mergulho profundo","titles":["Mais recursos"]},"416":{"title":"IDEs","titles":["Mais recursos"]},"417":{"title":"Plataformas para experimentar","titles":["Mais recursos"]},"418":{"title":"Aplicativos de exemplo","titles":["Mais recursos"]},"419":{"title":"Encontre, crie e compartilhe seus próprios componentes nativos e TurboModules","titles":["Mais recursos"]},"420":{"title":"Componentes de IU nativos do Android","titles":[]},"421":{"title":"Exemplo de ImageView","titles":["Componentes de IU nativos do Android"]},"422":{"title":"1. Crie a subclasse ViewManager","titles":["Componentes de IU nativos do Android","Exemplo de ImageView"]},"423":{"title":"2. Implementar o método createViewInstance","titles":["Componentes de IU nativos do Android","Exemplo de ImageView"]},"424":{"title":"3. Exponha os configuradores de propriedades de visualização usando a anotação @ReactProp (ou @ReactPropGroup)","titles":["Componentes de IU nativos do Android","Exemplo de ImageView"]},"425":{"title":"4. Cadastre o ViewManager","titles":["Componentes de IU nativos do Android","Exemplo de ImageView"]},"426":{"title":"5. Implemente o módulo JavaScript","titles":["Componentes de IU nativos do Android","Exemplo de ImageView"]},"427":{"title":"Eventos","titles":["Componentes de IU nativos do Android"]},"428":{"title":"Exemplo de integração com um fragmento Android","titles":["Componentes de IU nativos do Android"]},"429":{"title":"1. Crie um exemplo de visualização personalizada","titles":["Componentes de IU nativos do Android","Exemplo de integração com um fragmento Android"]},"430":{"title":"2. Crie um fragmento","titles":["Componentes de IU nativos do Android","Exemplo de integração com um fragmento Android"]},"431":{"title":"3. Crie a subclasse ViewManager","titles":["Componentes de IU nativos do Android","Exemplo de integração com um fragmento Android"]},"432":{"title":"4. Cadastre o ViewManager","titles":["Componentes de IU nativos do Android","Exemplo de integração com um fragmento Android"]},"433":{"title":"5. Registre o Package","titles":["Componentes de IU nativos do Android","Exemplo de integração com um fragmento Android"]},"434":{"title":"6. Implemente o módulo JavaScript","titles":["Componentes de IU nativos do Android","Exemplo de integração com um fragmento Android"]},"435":{"title":"Debug Nativo","titles":[]},"436":{"title":"Acessando logs nativos","titles":["Debug Nativo"]},"437":{"title":"Depurando código nativo","titles":["Debug Nativo"]},"438":{"title":"Android Studio","titles":["Debug Nativo","Depurando código nativo"]},"439":{"title":"Xcode","titles":["Debug Nativo","Depurando código nativo"]},"440":{"title":"Componentes de UI nativos do iOS","titles":[]},"441":{"title":"Exemplo de MapView para iOS","titles":["Componentes de UI nativos do iOS"]},"442":{"title":"Propriedades","titles":["Componentes de UI nativos do iOS","Exemplo de MapView para iOS"]},"443":{"title":"Eventos","titles":["Componentes de UI nativos do iOS"]},"444":{"title":"Lidando com múltiplas visualizações nativas","titles":["Componentes de UI nativos do iOS"]},"445":{"title":"Estilos","titles":["Componentes de UI nativos do iOS"]},"446":{"title":"Introdução aos módulos nativos","titles":[]},"447":{"title":"Configuração do módulo nativo","titles":["Introdução aos módulos nativos"]},"448":{"title":"Começando","titles":["Introdução aos módulos nativos"]},"449":{"title":"Módulos nativos do Android","titles":[]},"450":{"title":"Crie um módulo nativo de calendário","titles":["Módulos nativos do Android"]},"451":{"title":"Configurar","titles":["Módulos nativos do Android","Crie um módulo nativo de calendário"]},"452":{"title":"Crie um arquivo de módulo nativo personalizado","titles":["Módulos nativos do Android","Crie um módulo nativo de calendário"]},"453":{"title":"Nome do módulo","titles":["Módulos nativos do Android"]},"454":{"title":"Exportar um método nativo para JavaScript","titles":["Módulos nativos do Android"]},"455":{"title":"Métodos Síncronos","titles":["Módulos nativos do Android","Exportar um método nativo para JavaScript"]},"456":{"title":"Registre o módulo (específico para Android)","titles":["Módulos nativos do Android"]},"457":{"title":"Teste o que você construiu","titles":["Módulos nativos do Android","Registre o módulo (específico para Android)"]},"458":{"title":"Construindo enquanto você itera","titles":["Módulos nativos do Android"]},"459":{"title":"Recapitulação✨","titles":["Módulos nativos do Android"]},"460":{"title":"Além de um módulo nativo de calendário","titles":["Módulos nativos do Android"]},"461":{"title":"Melhor exportação de módulo nativo","titles":["Módulos nativos do Android","Além de um módulo nativo de calendário"]},"462":{"title":"Tipos de argumento","titles":["Módulos nativos do Android","Além de um módulo nativo de calendário"]},"463":{"title":"Exportando Constantes","titles":["Módulos nativos do Android","Além de um módulo nativo de calendário"]},"464":{"title":"Callbacks","titles":["Módulos nativos do Android"]},"465":{"title":"Promises","titles":["Módulos nativos do Android"]},"466":{"title":"Enviando eventos para JavaScript","titles":["Módulos nativos do Android","Promises"]},"467":{"title":"Obtendo o resultado da atividade de startActivityForResult","titles":["Módulos nativos do Android"]},"468":{"title":"Ouvindo eventos do ciclo de vida","titles":["Módulos nativos do Android"]},"469":{"title":"Threading","titles":["Módulos nativos do Android"]},"470":{"title":"Configuração do pacote NPM de módulos nativos","titles":[]},"471":{"title":"Navegando entre telas","titles":[]},"472":{"title":"Navegação de reação","titles":["Navegando entre telas"]},"473":{"title":"React Native Navigation","titles":["Navegando entre telas"]},"474":{"title":"Módulos nativos iOS","titles":[]},"475":{"title":"Crie um módulo nativo de calendário","titles":["Módulos nativos iOS"]},"476":{"title":"Configurar","titles":["Módulos nativos iOS"]},"477":{"title":"Crie arquivos de módulo nativos personalizados","titles":["Módulos nativos iOS","Configurar"]},"478":{"title":"Nome do módulo","titles":["Módulos nativos iOS","Configurar"]},"479":{"title":"Exportar um método nativo para JavaScript","titles":["Módulos nativos iOS","Configurar"]},"480":{"title":"Métodos Síncronos","titles":["Módulos nativos iOS","Configurar"]},"481":{"title":"Teste o que você construiu","titles":["Módulos nativos iOS","Configurar"]},"482":{"title":"Construindo enquanto você itera","titles":["Módulos nativos iOS","Configurar"]},"483":{"title":"Recapitulação✨","titles":["Módulos nativos iOS","Configurar"]},"484":{"title":"Além de um módulo nativo de calendário","titles":["Módulos nativos iOS"]},"485":{"title":"Melhor exportação de módulo nativo","titles":["Módulos nativos iOS","Além de um módulo nativo de calendário"]},"486":{"title":"Tipos de argumento","titles":["Módulos nativos iOS","Além de um módulo nativo de calendário"]},"487":{"title":"Exportando Constantes","titles":["Módulos nativos iOS","Além de um módulo nativo de calendário"]},"488":{"title":"Callback","titles":["Módulos nativos iOS"]},"489":{"title":"Promises","titles":["Módulos nativos iOS"]},"490":{"title":"Enviando eventos para JavaScript","titles":["Módulos nativos iOS"]},"491":{"title":"Threading","titles":["Módulos nativos iOS"]},"492":{"title":"Injeção de dependência","titles":["Módulos nativos iOS","Threading"]},"493":{"title":"Exportando Swift","titles":["Módulos nativos iOS","Threading"]},"494":{"title":"Nomes de métodos reservados","titles":["Módulos nativos iOS"]},"495":{"title":"invalidate()","titles":["Módulos nativos iOS","Nomes de métodos reservados"]},"496":{"title":"Otimizando a configuração da Flatlist","titles":[]},"497":{"title":"Termos","titles":["Otimizando a configuração da Flatlist"]},"498":{"title":"Props","titles":["Otimizando a configuração da Flatlist"]},"499":{"title":"removeClippedSubviews","titles":["Otimizando a configuração da Flatlist","Props"]},"500":{"title":"maxToRenderPerBatch","titles":["Otimizando a configuração da Flatlist","Props"]},"501":{"title":"updateCellsBatchingPeriod","titles":["Otimizando a configuração da Flatlist","Props"]},"502":{"title":"initialNumToRender","titles":["Otimizando a configuração da Flatlist","Props"]},"503":{"title":"windowSize","titles":["Otimizando a configuração da Flatlist","Props"]},"504":{"title":"Lista de itens","titles":["Otimizando a configuração da Flatlist"]},"505":{"title":"Use componentes básicos","titles":["Otimizando a configuração da Flatlist","Lista de itens"]},"506":{"title":"Use componentes leves","titles":["Otimizando a configuração da Flatlist","Lista de itens"]},"507":{"title":"Usar shouldComponentUpdate","titles":["Otimizando a configuração da Flatlist","Lista de itens"]},"508":{"title":"Use imagens otimizadas em cache","titles":["Otimizando a configuração da Flatlist","Lista de itens"]},"509":{"title":"Use getItemLayout","titles":["Otimizando a configuração da Flatlist","Lista de itens"]},"510":{"title":"Use keyExtractor ou key","titles":["Otimizando a configuração da Flatlist","Lista de itens"]},"511":{"title":"Evite função anônima em renderItem","titles":["Otimizando a configuração da Flatlist","Lista de itens"]},"512":{"title":"Plataformas fora da árvore","titles":[]},"513":{"title":"De parceiros","titles":["Plataformas fora da árvore"]},"514":{"title":"Da comunidade","titles":["Plataformas fora da árvore"]},"515":{"title":"Criando sua própria plataforma React Native","titles":["Plataformas fora da árvore"]},"516":{"title":"Bundling","titles":["Plataformas fora da árvore"]},"517":{"title":"Rede","titles":[]},"518":{"title":"Usando o Fetch","titles":["Rede"]},"519":{"title":"Fazendo requisições","titles":["Rede","Usando o Fetch"]},"520":{"title":"Lidando com a resposta","titles":["Rede","Usando o Fetch"]},"521":{"title":"Usando outras bibliotecas de rede","titles":["Rede"]},"522":{"title":"Suporte WebSocket","titles":["Rede"]},"523":{"title":"Problemas conhecidos com autenticação baseada em busca e cookie","titles":["Rede"]},"524":{"title":"Configurando NSURLSession no iOS","titles":["Rede"]},"525":{"title":"Perfil com Hermes","titles":[]},"526":{"title":"Grave um perfil de amostragem Hermes","titles":["Perfil com Hermes"]},"527":{"title":"Execute o comando da CLI","titles":["Perfil com Hermes"]},"528":{"title":"Habilitando mapa de origem","titles":["Perfil com Hermes","Execute o comando da CLI"]},"529":{"title":"Erros comuns","titles":["Perfil com Hermes","Execute o comando da CLI"]},"530":{"title":"Abra o perfil baixado no Chrome DevTools","titles":["Perfil com Hermes"]},"531":{"title":"Como funciona o transformador de perfil Hermes?","titles":["Perfil com Hermes"]},"532":{"title":"Visão geral do desempenho","titles":[]},"533":{"title":"O que você precisa saber sobre frames","titles":["Visão geral do desempenho"]},"534":{"title":"Taxa de quadros JS (thread JavaScript)","titles":["Visão geral do desempenho"]},"535":{"title":"Taxa de quadros da UI (thread principal)","titles":["Visão geral do desempenho"]},"536":{"title":"Fontes comuns de problemas de desempenho","titles":["Visão geral do desempenho"]},"537":{"title":"Executando em modo de desenvolvimento (dev=true)","titles":["Visão geral do desempenho","Fontes comuns de problemas de desempenho"]},"538":{"title":"Usando instruções console.log","titles":["Visão geral do desempenho","Fontes comuns de problemas de desempenho"]},"539":{"title":"A renderização inicial do ListView é muito lenta ou o desempenho da rolagem é ruim para listas grandes","titles":["Visão geral do desempenho","Fontes comuns de problemas de desempenho"]},"540":{"title":"JS FPS despenca ao renderizar novamente uma visualização que quase não muda","titles":["Visão geral do desempenho","Fontes comuns de problemas de desempenho"]},"541":{"title":"Descartando o FPS do thread JS por causa de muito trabalho no thread JavaScript ao mesmo tempo","titles":["Visão geral do desempenho","Fontes comuns de problemas de desempenho"]},"542":{"title":"Mover uma visualização na tela (rolar, traduzir, girar) elimina o FPS do thread da UI","titles":["Visão geral do desempenho","Fontes comuns de problemas de desempenho"]},"543":{"title":"Animar o tamanho de uma imagem reduz o FPS do thread da interface do usuário","titles":["Visão geral do desempenho","Fontes comuns de problemas de desempenho"]},"544":{"title":"Minha visualização TouchableX não responde muito bem","titles":["Visão geral do desempenho","Fontes comuns de problemas de desempenho"]},"545":{"title":"Transições lentas do navegador","titles":["Visão geral do desempenho","Fontes comuns de problemas de desempenho"]},"546":{"title":"Publicação na Apple App Store","titles":[]},"547":{"title":"1. Configurar esquema de liberação","titles":["Publicação na Apple App Store",null]},"548":{"title":"Dicas profissionais","titles":["Publicação na Apple App Store",null]},"549":{"title":"2. Construir aplicativo para lançamento","titles":["Publicação na Apple App Store",null]},"550":{"title":"4. Capturas de tela","titles":["Publicação na Apple App Store",null]},"551":{"title":"Perfil","titles":[]},"552":{"title":"Criação de perfil de desempenho da interface do Android com systrace","titles":["Perfil"]},"553":{"title":"1. Coletando um rastro","titles":["Perfil","Criação de perfil de desempenho da interface do Android com systrace"]},"554":{"title":"2. Lendo o rastreamento","titles":["Perfil","Criação de perfil de desempenho da interface do Android com systrace"]},"555":{"title":"3. Encontre o seu processo","titles":["Perfil","Criação de perfil de desempenho da interface do Android com systrace"]},"556":{"title":"Identificando um culpado","titles":["Perfil"]},"557":{"title":"Resolvendo problemas de JavaScript","titles":["Perfil"]},"558":{"title":"Resolvendo problemas de UI nativa","titles":["Perfil"]},"559":{"title":"Muito trabalho de GPU","titles":["Perfil","Resolvendo problemas de UI nativa"]},"560":{"title":"Criando novas visualizações no thread da UI","titles":["Perfil","Resolvendo problemas de UI nativa"]},"561":{"title":"Código específico da plataforma","titles":[]},"562":{"title":"Módulo de plataforma","titles":["Código específico da plataforma"]},"563":{"title":"Detectando a versão do Android","titles":["Código específico da plataforma","Módulo de plataforma"]},"564":{"title":"Detectando a versão do iOS","titles":["Código específico da plataforma"]},"565":{"title":"Extensões específicas da plataforma","titles":["Código específico da plataforma"]},"566":{"title":"Extensões específicas nativas (ou seja, compartilhamento de código com NodeJS e Web)","titles":["Código específico da plataforma"]},"567":{"title":"Ferramentas de desenvolvedor React","titles":[]},"568":{"title":"Integração com React Native Inspector","titles":["Ferramentas de desenvolvedor React"]},"569":{"title":"Depurando o estado do aplicativo","titles":["Ferramentas de desenvolvedor React"]},"570":{"title":"Solução de problemas","titles":["Ferramentas de desenvolvedor React"]},"571":{"title":"Pacotes de RAM e require inline","titles":[]},"572":{"title":"Carregando JavaScript","titles":["Pacotes de RAM e require inline"]},"573":{"title":"Require Inline","titles":["Pacotes de RAM e require inline"]},"574":{"title":"Habilite o formato RAM","titles":["Pacotes de RAM e require inline","Require Inline"]},"575":{"title":"Configurar pré-carregamento e requisitos embutidos","titles":["Pacotes de RAM e require inline"]},"576":{"title":"Investigando os Módulos Carregados","titles":["Pacotes de RAM e require inline"]},"577":{"title":"Atualizando metro.config.js","titles":["Pacotes de RAM e require inline"]},"578":{"title":"Teste e meça melhorias","titles":["Pacotes de RAM e require inline"]},"579":{"title":"Plug-in React Native Gradle","titles":[]},"580":{"title":"Usando o plugin","titles":["Plug-in React Native Gradle"]},"581":{"title":"Configurando o plugin","titles":["Plug-in React Native Gradle"]},"582":{"title":"root","titles":["Plug-in React Native Gradle","Configurando o plugin"]},"583":{"title":"reactNativeDir","titles":["Plug-in React Native Gradle","Configurando o plugin"]},"584":{"title":"codegenDir","titles":["Plug-in React Native Gradle","Configurando o plugin"]},"585":{"title":"cliFile","titles":["Plug-in React Native Gradle","Configurando o plugin"]},"586":{"title":"debuggableVariants","titles":["Plug-in React Native Gradle","Configurando o plugin"]},"587":{"title":"nodeExecutableAndArgs","titles":["Plug-in React Native Gradle","Configurando o plugin"]},"588":{"title":"bundleCommand","titles":["Plug-in React Native Gradle","Configurando o plugin"]},"589":{"title":"bundleConfig","titles":["Plug-in React Native Gradle","Configurando o plugin"]},"590":{"title":"bundleAssetName","titles":["Plug-in React Native Gradle","Configurando o plugin"]},"591":{"title":"entryFile","titles":["Plug-in React Native Gradle","Configurando o plugin"]},"592":{"title":"extraPackagerArgs","titles":["Plug-in React Native Gradle","Configurando o plugin"]},"593":{"title":"hermesCommand","titles":["Plug-in React Native Gradle","Configurando o plugin"]},"594":{"title":"hermesFlags","titles":["Plug-in React Native Gradle","Configurando o plugin"]},"595":{"title":"Usando sabores e variantes de construção","titles":["Plug-in React Native Gradle"]},"596":{"title":"O que o plugin está fazendo nos bastidores?","titles":["Plug-in React Native Gradle"]},"597":{"title":"Mac OS (Android)","titles":[]},"598":{"title":"1. Habilite a depuração via USB","titles":["Mac OS (Android)"]},"599":{"title":"2. Conecte seu dispositivo via USB","titles":["Mac OS (Android)"]},"600":{"title":"3. Execute seu aplicativo","titles":["Mac OS (Android)"]},"601":{"title":"Conectando-se ao servidor de desenvolvimento","titles":["Mac OS (Android)"]},"602":{"title":"Método 1: usando adb reverse (recomendado)","titles":["Mac OS (Android)","Conectando-se ao servidor de desenvolvimento"]},"603":{"title":"Método 2: conectar via Wi-Fi","titles":["Mac OS (Android)","Conectando-se ao servidor de desenvolvimento"]},"604":{"title":"Construindo seu aplicativo para produção","titles":["Mac OS (Android)","Conectando-se ao servidor de desenvolvimento"]},"605":{"title":"Executando no dispositivo","titles":[]},"606":{"title":"Linux (Android)","titles":[]},"607":{"title":"1. Habilite a depuração via USB","titles":["Linux (Android)"]},"608":{"title":"2. Conecte seu dispositivo via USB","titles":["Linux (Android)"]},"609":{"title":"3. Execute seu aplicativo","titles":["Linux (Android)"]},"610":{"title":"Conectando-se ao servidor de desenvolvimento","titles":["Linux (Android)"]},"611":{"title":"Método 1: usando adb reverse (recomendado)","titles":["Linux (Android)","Conectando-se ao servidor de desenvolvimento"]},"612":{"title":"Método 2: conectar via Wi-Fi","titles":["Linux (Android)","Conectando-se ao servidor de desenvolvimento"]},"613":{"title":"Construindo seu aplicativo para produção","titles":["Linux (Android)"]},"614":{"title":"Mac OS (iOS)","titles":[]},"615":{"title":"1. Conecte seu dispositivo via USB","titles":["Mac OS (iOS)"]},"616":{"title":"2. Configure a assinatura de código","titles":["Mac OS (iOS)"]},"617":{"title":"3. Crie e execute seu aplicativo","titles":["Mac OS (iOS)"]},"618":{"title":"Conectando-se ao servidor de desenvolvimento","titles":["Mac OS (iOS)"]},"619":{"title":"Solução de problemas","titles":["Mac OS (iOS)"]},"620":{"title":"1. Rede Wi-Fi.","titles":["Mac OS (iOS)","Solução de problemas"]},"621":{"title":"2. Endereço IP","titles":["Mac OS (iOS)","Solução de problemas"]},"622":{"title":"Construindo seu aplicativo para produção","titles":["Mac OS (iOS)"]},"623":{"title":"Executando no Simulador","titles":[]},"624":{"title":"Iniciando o simulador","titles":["Executando no Simulador"]},"625":{"title":"Especificando um dispositivo","titles":["Executando no Simulador"]},"626":{"title":"Especificando uma versão do dispositivo","titles":["Executando no Simulador","Especificando um dispositivo"]},"627":{"title":"Especificando um UDID","titles":["Executando no Simulador"]},"628":{"title":"Segurança","titles":[]},"629":{"title":"Armazenando informações confidenciais","titles":["Segurança"]},"630":{"title":"Armazenamento assíncrono","titles":["Segurança","Armazenando informações confidenciais"]},"631":{"title":"Armazenamento seguro","titles":["Segurança","Armazenando informações confidenciais"]},"632":{"title":"iOS - Serviços de chaveiro","titles":["Segurança","Armazenando informações confidenciais","Armazenamento seguro"]},"633":{"title":"Android - Preferências compartilhadas seguras","titles":["Segurança","Armazenando informações confidenciais","Armazenamento seguro"]},"634":{"title":"Android - armazenamento de chaves","titles":["Segurança","Armazenando informações confidenciais","Armazenamento seguro"]},"635":{"title":"Autenticação e links diretos","titles":["Segurança"]},"636":{"title":"OAuth2 e redirecionamentos","titles":["Segurança"]},"637":{"title":"Segurança de rede","titles":["Segurança"]},"638":{"title":"SSL Pinning","titles":["Segurança","Segurança de rede"]},"639":{"title":"Resumo","titles":["Segurança"]},"640":{"title":"Windows (Android)","titles":[]},"641":{"title":"1. Habilite a depuração via USB","titles":["Windows (Android)"]},"642":{"title":"2. Conecte seu dispositivo via USB","titles":["Windows (Android)"]},"643":{"title":"3. Execute seu aplicativo","titles":["Windows (Android)"]},"644":{"title":"Conectando-se ao servidor de desenvolvimento","titles":["Windows (Android)"]},"645":{"title":"Método 1: usando adb reverse (recomendado)","titles":["Windows (Android)","Conectando-se ao servidor de desenvolvimento"]},"646":{"title":"Método 2: conectar via Wi-Fi","titles":["Windows (Android)","Conectando-se ao servidor de desenvolvimento"]},"647":{"title":"Construindo seu aplicativo para produção","titles":["Windows (Android)","Conectando-se ao servidor de desenvolvimento"]},"648":{"title":"Publicação na Google Play Store","titles":[]},"649":{"title":"Gerando uma chave de upload","titles":["Publicação na Google Play Store"]},"650":{"title":"Windows","titles":["Publicação na Google Play Store","Gerando uma chave de upload"]},"651":{"title":"Mac OS","titles":["Publicação na Google Play Store","Gerando uma chave de upload"]},"652":{"title":"Configurando variáveis ​​Gradle","titles":["Publicação na Google Play Store"]},"653":{"title":"Adicionando configuração de assinatura à configuração Gradle do seu aplicativo","titles":["Publicação na Google Play Store"]},"654":{"title":"Gerando uma release AAB","titles":["Publicação na Google Play Store"]},"655":{"title":"Testando a versão de lançamento do seu aplicativo","titles":["Publicação na Google Play Store"]},"656":{"title":"Publicação em outras lojas","titles":["Publicação na Google Play Store"]},"657":{"title":"Habilitando o Proguard para reduzir o tamanho do APK (opcional)","titles":["Publicação na Google Play Store"]},"658":{"title":"Migrando aplicativos antigos do Android React Native para usar o App Signing do Google Play","titles":["Publicação na Google Play Store"]},"659":{"title":"Permissões padrão","titles":["Publicação na Google Play Store"]},"660":{"title":"Mapas de origem","titles":[]},"661":{"title":"Habilitar mapas de origem no Android","titles":["Mapas de origem"]},"662":{"title":"Hermes","titles":["Mapas de origem","Habilitar mapas de origem no Android"]},"663":{"title":"Habilitar mapas de origem no iOS","titles":["Mapas de origem"]},"664":{"title":"Simbolização Manual","titles":["Mapas de origem"]},"665":{"title":"Acelerando as compilações de CI","titles":[]},"666":{"title":"Desative o Flipper para iOS","titles":["Acelerando as compilações de CI"]},"667":{"title":"Lidar com dependências transitivas","titles":["Acelerando as compilações de CI","Desative o Flipper para iOS"]},"668":{"title":"Estilo","titles":[]},"669":{"title":"Problemas conhecidos","titles":["Estilo"]},"670":{"title":"Teste","titles":[]},"671":{"title":"Por que testar","titles":["Teste"]},"672":{"title":"Análise Estática","titles":["Teste"]},"673":{"title":"Escrevendo código testável","titles":["Teste"]},"674":{"title":"Escrevendo testes","titles":["Teste"]},"675":{"title":"Estruturando Testes","titles":["Teste","Escrevendo testes"]},"676":{"title":"Testes Unitários","titles":["Teste"]},"677":{"title":"Mock","titles":["Teste"]},"678":{"title":"Testes de Integração","titles":["Teste"]},"679":{"title":"Testes de Componentes","titles":["Teste"]},"680":{"title":"Testando interações do usuário","titles":["Teste"]},"681":{"title":"Testando saída renderizada","titles":["Teste","Testando interações do usuário"]},"682":{"title":"Testes ponta a ponta","titles":["Teste"]},"683":{"title":"Resumo","titles":["Teste"]},"684":{"title":"Links","titles":["Teste"]},"685":{"title":"Simbolizando um rastreamento de pilha","titles":[]},"686":{"title":"Notas sobre mapas de origem","titles":["Simbolizando um rastreamento de pilha"]},"687":{"title":"Sobre a Nova Arquitetura","titles":[]},"688":{"title":"Por que uma nova arquitetura?","titles":["Sobre a Nova Arquitetura"]},"689":{"title":"Layout e efeitos síncronos","titles":["Sobre a Nova Arquitetura","Por que uma nova arquitetura?"]},"690":{"title":"Exemplo: renderizando uma dica de ferramenta","titles":["Sobre a Nova Arquitetura"]},"691":{"title":"Suporte para renderização e recursos simultâneos","titles":["Sobre a Nova Arquitetura","Exemplo: renderizando uma dica de ferramenta"]},"692":{"title":"Exemplo: Usando startTransition","titles":["Sobre a Nova Arquitetura"]},"693":{"title":"JavaScript rápido/interface nativa","titles":["Sobre a Nova Arquitetura","Exemplo: Usando startTransition"]},"694":{"title":"Saber mais","titles":["Sobre a Nova Arquitetura","Exemplo: Usando startTransition"]},"695":{"title":"O que posso esperar ao ativar a Nova Arquitetura?","titles":["Sobre a Nova Arquitetura"]},"696":{"title":"Devo usar a Nova Arquitetura hoje?","titles":["Sobre a Nova Arquitetura"]},"697":{"title":"Habilite a nova arquitetura","titles":["Sobre a Nova Arquitetura","Devo usar a Nova Arquitetura hoje?"]},"698":{"title":"Temporizadores","titles":[]},"699":{"title":"Temporizadores","titles":["Temporizadores"]},"700":{"title":"Gerenciador de interação","titles":["Temporizadores"]},"701":{"title":"Solução de problemas","titles":[]},"702":{"title":"Porta já em uso (Port already in use)","titles":["Solução de problemas"]},"703":{"title":"Encerrando um processo na porta 8081","titles":["Solução de problemas","Porta já em uso (Port already in use)"]},"704":{"title":"Usando uma porta diferente de 8081","titles":["Solução de problemas","Porta já em uso (Port already in use)"]},"705":{"title":"Erro de bloqueio NPM","titles":["Solução de problemas"]},"706":{"title":"Bibliotecas ausentes para React","titles":["Solução de problemas"]},"707":{"title":"React Native não compila ao ser usado como CocoaPod","titles":["Solução de problemas","Bibliotecas ausentes para React"]},"708":{"title":"Lista de argumentos muito longa: falha na expansão do cabeçalho recursivo","titles":["Solução de problemas","Bibliotecas ausentes para React"]},"709":{"title":"Não há transportes disponíveis","titles":["Solução de problemas"]},"710":{"title":"Exceção sem resposta do comando Shell","titles":["Solução de problemas"]},"711":{"title":"inicialização travada do react-native","titles":["Solução de problemas"]},"712":{"title":"npm","titles":["Solução de problemas","inicialização travada do react-native","Lista de argumentos muito longa: falha na expansão do cabeçalho recursivo",null]},"713":{"title":"yarn","titles":["Solução de problemas","inicialização travada do react-native","Lista de argumentos muito longa: falha na expansão do cabeçalho recursivo",null]},"714":{"title":"Não é possível iniciar o gerenciador de pacotes react-native (no Linux)","titles":["Solução de problemas"]},"715":{"title":"Caso 1: Erro "código":"ENOSPC","errno":"ENOSPC"","titles":["Solução de problemas","Não é possível iniciar o gerenciador de pacotes react-native (no Linux)"]},"716":{"title":"Error: spawnSync ./gradlew EACCES","titles":["Solução de problemas","Não é possível iniciar o gerenciador de pacotes react-native (no Linux)"]},"717":{"title":"Atualizando para novas versões","titles":[]},"718":{"title":"Projetos de expo","titles":["Atualizando para novas versões"]},"719":{"title":"Projetos React Native","titles":["Atualizando para novas versões"]},"720":{"title":"CLI React Native","titles":["Atualizando para novas versões"]},"721":{"title":"1. Execute o comando upgrade","titles":["Atualizando para novas versões","CLI React Native"]},"722":{"title":"2. Resolva os conflitos","titles":["Atualizando para novas versões","CLI React Native"]},"723":{"title":"Ajudante de atualização","titles":["Atualizando para novas versões"]},"724":{"title":"1. Selecione as versões","titles":["Atualizando para novas versões","Ajudante de atualização"]},"725":{"title":"2. Atualizar dependências","titles":["Atualizando para novas versões","Ajudante de atualização"]},"726":{"title":"3. Atualize seus arquivos de projeto","titles":["Atualizando para novas versões","Ajudante de atualização"]},"727":{"title":"Solução de problemas","titles":["Atualizando para novas versões"]},"728":{"title":"Quero atualizar com React Native CLI, mas não uso Git","titles":["Atualizando para novas versões","Solução de problemas"]},"729":{"title":"Fiz todas as alterações, mas meu aplicativo ainda usa uma versão antiga","titles":["Atualizando para novas versões","Solução de problemas"]},"730":{"title":"Usando List View","titles":[]},"731":{"title":"Usando um ScrollView","titles":[]},"732":{"title":"Usando TypeScript","titles":[]},"733":{"title":"Introdução ao TypeScript","titles":["Usando TypeScript"]},"734":{"title":"Adicionando TypeScript a um projeto existente","titles":["Usando TypeScript"]},"735":{"title":"Usando JavaScript em vez de TypeScript","titles":["Usando TypeScript"]},"736":{"title":"Como funcionam o TypeScript e o React Native","titles":["Usando TypeScript"]},"737":{"title":"Qual é a aparência do React Native + TypeScript","titles":["Usando TypeScript"]},"738":{"title":"Onde encontrar conselhos úteis","titles":["Usando TypeScript"]},"739":{"title":"Usando aliases de caminho personalizados com TypeScript","titles":["Usando TypeScript"]},"740":{"title":"Usando o Hermes","titles":[]},"741":{"title":"Pacote Hermes","titles":["Usando o Hermes"]},"742":{"title":"Confirmando que Hermes está em uso","titles":["Usando o Hermes"]},"743":{"title":"Android","titles":["Usando o Hermes","Confirmando que Hermes está em uso"]},"744":{"title":"iOS","titles":["Usando o Hermes","Confirmando que Hermes está em uso"]},"745":{"title":"Depurando JS no Hermes usando DevTools do Google Chrome","titles":["Usando o Hermes","Confirmando que Hermes está em uso"]},"746":{"title":"Habilitando Hermes em versões mais antigas do React Native","titles":["Usando o Hermes"]},"747":{"title":"Android","titles":["Usando o Hermes","Habilitando Hermes em versões mais antigas do React Native"]},"748":{"title":"iOS","titles":["Usando o Hermes","Habilitando Hermes em versões mais antigas do React Native"]},"749":{"title":"Voltando para JavaScriptCore","titles":["Usando o Hermes"]},"750":{"title":"Android","titles":["Usando o Hermes","Voltando para JavaScriptCore"]},"751":{"title":"iOS","titles":["Usando o Hermes","Voltando para JavaScriptCore"]},"752":{"title":"Documentação em português do React Native 0.72","titles":[]},"753":{"title":"Básico","titles":["Documentação em português do React Native 0.72"]},"754":{"title":"Configuração do ambiente","titles":["Documentação em português do React Native 0.72"]},"755":{"title":"Workflow","titles":["Documentação em português do React Native 0.72"]},"756":{"title":"UI & Interação","titles":["Documentação em português do React Native 0.72"]},"757":{"title":"Interação","titles":["Documentação em português do React Native 0.72","UI & Interação"]},"758":{"title":"Connectivity","titles":["Documentação em português do React Native 0.72","UI & Interação"]},"759":{"title":"Inclusion","titles":["Documentação em português do React Native 0.72","UI & Interação"]},"760":{"title":"Debugging","titles":["Documentação em português do React Native 0.72"]},"761":{"title":"Testando","titles":["Documentação em português do React Native 0.72"]},"762":{"title":"Performance","titles":["Documentação em português do React Native 0.72"]},"763":{"title":"JavaScript Runtime","titles":["Documentação em português do React Native 0.72"]},"764":{"title":"Módulos Nativos","titles":["Documentação em português do React Native 0.72"]},"765":{"title":"Componentes Nativos","titles":["Documentação em português do React Native 0.72"]},"766":{"title":"Guias Android e iOS","titles":["Documentação em português do React Native 0.72"]},"767":{"title":"Android","titles":["Documentação em português do React Native 0.72","Guias Android e iOS"]},"768":{"title":"iOS","titles":["Documentação em português do React Native 0.72","Guias Android e iOS"]},"769":{"title":"Experimental","titles":["Documentação em português do React Native 0.72"]}},"dirtCount":0,"index":[["êxito",{"2":{"636":1}}],["⇧",{"2":{"617":1}}],["^nsurlsessionconfiguration",{"2":{"524":1}}],["^",{"2":{"444":1,"491":1}}],["^2",{"2":{"383":1}}],["😦",{"2":{"441":1}}],["😃",{"2":{"74":1,"77":1}}],["✅",{"2":{"399":1}}],["áudio",{"2":{"329":1,"693":1}}],["áreas",{"2":{"497":1,"500":1,"501":1,"502":1,"503":1,"532":1}}],["área",{"2":{"233":2,"247":1,"497":2,"669":1,"695":1}}],["árvores",{"2":{"681":1}}],["árvore",{"0":{"512":1},"1":{"513":1,"514":1,"515":1,"516":1},"2":{"217":1,"328":1,"444":1,"634":1,"681":1,"754":1}}],["└──",{"2":{"328":2}}],["├──",{"2":{"328":3}}],["ótimo",{"2":{"249":1,"259":1,"285":1,"604":1,"613":1,"622":1,"647":1}}],["ótimas",{"2":{"629":1}}],["ótima",{"2":{"45":1}}],["🍕",{"2":{"242":5}}],["🎉",{"2":{"239":1}}],["®",{"2":{"202":1}}],["qr",{"2":{"158":2,"605":1}}],["quão",{"2":{"555":1}}],["quiserem",{"2":{"461":1,"485":1}}],["quiser",{"2":{"50":1,"76":1,"96":1,"105":1,"146":1,"156":1,"171":1,"190":1,"200":1,"206":1,"245":1,"252":1,"263":2,"313":1,"332":1,"343":1,"347":1,"358":1,"417":1,"428":1,"445":1,"458":1,"467":1,"482":1,"491":1,"548":1,"549":1,"574":1,"656":1,"681":1}}],["quisermos",{"2":{"47":1,"110":1}}],["quot",{"0":{"715":8},"2":{"3":2,"10":2,"11":2,"12":2,"15":2,"21":2,"31":2,"33":2,"34":2,"38":2,"51":2,"57":2,"60":2,"63":2,"74":2,"77":2,"114":2,"131":4,"134":8,"135":8,"136":2,"142":18,"145":4,"149":10,"157":2,"159":2,"167":2,"168":18,"170":4,"174":6,"186":2,"189":4,"191":2,"200":2,"203":18,"205":4,"209":8,"213":2,"216":2,"242":4,"244":6,"245":8,"250":2,"251":4,"255":2,"275":2,"279":2,"288":4,"295":2,"299":2,"313":2,"314":2,"315":2,"320":4,"325":2,"345":6,"348":6,"358":4,"359":2,"360":2,"364":2,"365":4,"371":2,"387":2,"402":4,"404":4,"424":6,"436":2,"438":4,"439":6,"442":4,"453":2,"478":6,"483":2,"516":4,"533":2,"541":4,"545":2,"549":4,"551":2,"564":2,"567":4,"568":4,"574":6,"594":4,"598":4,"607":4,"616":2,"625":2,"641":4,"650":2,"663":2,"668":2,"676":2,"678":2,"681":2,"682":2,"690":2,"691":2,"699":2,"722":8,"724":4,"745":6}}],["quatro",{"2":{"608":1}}],["quarto",{"2":{"258":1}}],["quase",{"0":{"540":1},"2":{"216":1,"539":1,"556":1,"656":1}}],["quaisquer",{"2":{"113":1,"128":1,"339":1,"423":1,"464":1,"466":2,"469":1,"478":1,"490":1,"492":1,"520":1,"534":1,"638":1,"681":1,"689":1,"700":1,"718":1,"726":1}}],["quais",{"2":{"48":1,"50":1,"80":1,"96":1,"105":1,"219":1,"242":1,"306":1,"313":3,"349":1,"351":1,"358":3,"442":1,"462":1,"483":1,"486":1,"520":1,"540":1,"553":1,"555":1,"577":1,"595":1,"628":1,"635":1,"720":1}}],["quadros",{"0":{"534":1,"535":1},"2":{"55":1,"62":1,"63":3,"341":2,"499":1,"532":1,"533":4,"534":3,"535":1,"544":1,"545":1,"553":1,"693":3,"699":1}}],["quadro",{"2":{"46":1,"56":2,"110":2,"111":1,"341":1,"404":1,"445":1,"533":3,"534":3,"541":2,"542":1,"544":1,"545":3,"552":1,"554":1,"556":6,"557":1,"558":1,"559":3}}],["qualidade",{"2":{"336":1,"671":1,"672":1,"687":1}}],["qualified",{"2":{"68":1}}],["qualquer",{"2":{"63":1,"68":2,"92":2,"96":1,"101":2,"105":1,"115":1,"117":1,"137":1,"147":1,"149":1,"156":1,"164":1,"172":1,"174":1,"182":1,"191":1,"199":1,"207":1,"209":1,"217":1,"220":1,"228":1,"231":6,"245":3,"248":1,"250":1,"255":1,"278":1,"298":1,"345":1,"347":1,"349":1,"381":1,"386":1,"389":1,"403":1,"429":1,"430":5,"442":2,"461":1,"477":1,"485":1,"486":1,"487":1,"488":1,"516":1,"520":1,"531":1,"539":1,"542":1,"544":1,"546":2,"549":1,"562":1,"566":1,"568":1,"572":1,"577":1,"604":1,"613":1,"622":1,"629":2,"632":1,"635":2,"636":1,"647":1,"648":1,"655":2,"656":1,"662":1,"673":1,"678":1,"682":2,"707":1,"739":2}}],["qual",{"0":{"737":1},"2":{"3":1,"8":1,"26":1,"62":1,"65":1,"90":1,"99":1,"224":2,"225":1,"243":1,"244":1,"248":1,"348":1,"383":1,"402":1,"403":1,"444":3,"469":1,"478":1,"491":2,"497":1,"524":1,"562":1,"563":1,"596":1,"608":1,"635":2,"700":1,"724":1}}],["quantidades",{"2":{"571":1}}],["quantidade",{"2":{"500":1,"501":1,"502":1,"559":1,"693":1}}],["quanta",{"2":{"497":1}}],["quantos",{"2":{"347":1,"576":2,"691":1}}],["quanto",{"2":{"0":1,"91":1,"100":1,"231":1,"233":1,"262":1,"283":1,"303":1,"407":1,"505":1,"506":1,"508":1,"552":1,"665":2,"673":1,"682":1,"687":1,"739":1}}],["quando",{"2":{"2":2,"3":2,"5":1,"9":1,"10":2,"11":17,"31":1,"32":1,"33":1,"34":15,"35":6,"37":1,"46":2,"55":1,"57":1,"60":1,"74":5,"77":5,"89":1,"90":1,"92":1,"98":1,"99":1,"101":1,"110":2,"111":1,"112":1,"116":3,"128":1,"129":1,"130":1,"221":2,"229":1,"230":1,"234":1,"242":1,"245":3,"249":1,"251":1,"252":1,"257":2,"259":1,"279":4,"285":1,"299":4,"317":1,"339":1,"341":1,"349":4,"362":1,"377":1,"399":1,"420":1,"427":2,"440":1,"442":3,"443":1,"444":1,"446":1,"449":1,"454":1,"456":2,"462":1,"465":2,"467":2,"470":3,"474":1,"486":1,"489":1,"490":2,"491":1,"493":1,"495":1,"497":2,"523":1,"524":1,"529":1,"534":1,"535":1,"537":1,"542":1,"543":1,"545":2,"549":1,"552":1,"562":3,"565":3,"566":1,"568":1,"571":1,"573":2,"575":1,"576":1,"577":1,"605":1,"630":1,"635":1,"638":1,"667":1,"671":1,"675":3,"676":1,"677":4,"679":2,"680":4,"681":2,"683":1,"692":1,"711":1,"726":1,"733":1,"740":1}}],["quero",{"0":{"728":1}}],["quer",{"2":{"608":1,"677":1,"678":1}}],["querer",{"2":{"20":1,"50":1,"131":1,"156":1,"191":2,"220":1,"242":1,"245":1,"252":1,"334":1,"338":1,"445":1,"517":1,"557":1,"561":1,"573":1,"576":1,"677":1,"679":1,"711":1}}],["queremos",{"2":{"10":1,"106":1,"407":1,"441":2,"442":1,"445":1}}],["questão",{"2":{"552":1,"636":1}}],["questões",{"2":{"523":1}}],["questions",{"2":{"259":2}}],["queuebuffer",{"2":{"555":1}}],["queue",{"2":{"491":9}}],["queira",{"2":{"339":1,"446":1,"491":1,"595":1}}],["quebrar",{"2":{"680":1}}],["quebrada",{"2":{"679":1}}],["quebradas",{"2":{"229":5}}],["quebra",{"2":{"224":1}}],["quedas",{"2":{"535":1,"541":1}}],["queda",{"2":{"63":1,"341":1}}],["que",{"0":{"337":1,"408":1,"457":1,"481":1,"533":1,"540":1,"596":1,"671":1,"688":1,"695":1,"742":1},"1":{"409":1,"410":1,"411":1,"412":1,"413":1,"689":1,"743":1,"744":1,"745":1},"2":{"0":2,"2":1,"3":2,"9":1,"10":1,"11":6,"14":4,"15":3,"20":3,"22":1,"24":2,"25":1,"26":1,"27":2,"28":2,"31":4,"33":4,"34":5,"35":2,"39":3,"42":4,"43":4,"44":1,"45":1,"46":6,"47":2,"48":1,"49":1,"50":5,"51":2,"52":1,"53":1,"55":3,"56":6,"57":5,"58":1,"60":9,"62":1,"63":4,"64":1,"65":5,"67":10,"68":5,"69":2,"70":1,"71":1,"74":1,"77":6,"80":1,"90":2,"92":2,"93":1,"94":6,"95":3,"96":4,"99":2,"101":6,"103":6,"104":3,"105":5,"106":4,"110":3,"111":13,"112":2,"113":8,"114":1,"115":7,"116":1,"117":3,"119":2,"120":2,"122":1,"126":1,"128":2,"129":1,"130":1,"134":2,"135":3,"141":2,"142":2,"143":1,"144":3,"145":2,"147":1,"153":1,"156":1,"159":1,"165":1,"166":1,"167":2,"168":2,"169":3,"170":2,"172":1,"178":1,"183":1,"184":1,"186":1,"188":3,"191":4,"196":1,"200":3,"202":2,"203":4,"204":3,"205":2,"207":1,"213":1,"216":1,"217":5,"218":5,"219":4,"220":2,"221":2,"222":1,"223":3,"225":1,"227":2,"228":1,"230":2,"231":2,"234":1,"235":3,"236":1,"237":1,"239":1,"241":1,"242":6,"244":2,"245":6,"246":1,"248":1,"249":4,"250":1,"251":3,"252":6,"255":4,"256":1,"257":2,"258":1,"259":5,"261":1,"262":4,"268":1,"270":2,"271":1,"273":1,"275":2,"276":2,"278":1,"279":6,"282":1,"283":3,"285":1,"288":1,"290":2,"291":1,"293":1,"295":2,"296":2,"298":1,"299":6,"302":1,"303":3,"309":1,"310":1,"311":1,"313":3,"315":2,"316":2,"317":1,"318":2,"320":6,"328":6,"329":3,"330":2,"331":2,"333":1,"334":1,"335":1,"336":2,"337":3,"338":3,"339":3,"340":1,"341":1,"343":1,"344":4,"345":2,"347":2,"348":1,"349":12,"354":1,"355":1,"356":1,"358":4,"360":2,"361":2,"362":1,"363":2,"365":6,"374":1,"376":1,"377":1,"379":4,"381":3,"382":1,"385":1,"386":3,"387":3,"389":2,"390":2,"398":3,"399":1,"400":2,"402":5,"403":1,"404":3,"406":1,"407":5,"409":1,"412":2,"413":2,"417":2,"418":1,"419":2,"420":3,"421":1,"422":1,"424":6,"426":3,"427":3,"428":1,"429":2,"430":5,"431":1,"436":1,"440":3,"441":5,"442":18,"443":7,"444":9,"445":5,"446":6,"447":2,"448":2,"449":1,"450":2,"452":7,"453":1,"454":3,"455":2,"456":14,"457":3,"458":2,"459":1,"461":11,"463":3,"464":6,"465":3,"466":2,"467":1,"470":2,"471":2,"472":1,"473":1,"474":1,"475":2,"477":3,"478":3,"479":4,"480":3,"481":3,"482":2,"483":1,"485":12,"486":1,"487":6,"488":7,"489":2,"490":1,"491":5,"492":1,"493":7,"497":5,"498":1,"499":3,"500":2,"501":1,"502":1,"507":1,"511":4,"512":1,"516":5,"519":1,"520":5,"521":2,"522":1,"523":1,"524":2,"525":1,"529":6,"531":6,"532":2,"533":3,"534":4,"535":4,"538":2,"540":4,"541":3,"542":2,"543":1,"544":4,"545":4,"547":3,"548":2,"549":3,"550":2,"551":1,"552":4,"553":7,"554":1,"555":7,"556":5,"557":2,"558":1,"559":5,"560":6,"561":3,"562":3,"564":1,"565":1,"566":2,"568":1,"569":1,"571":4,"572":4,"573":1,"574":2,"575":2,"576":6,"577":2,"580":1,"586":1,"587":1,"589":1,"590":1,"592":1,"596":4,"599":1,"602":1,"603":2,"605":1,"608":4,"611":1,"612":2,"615":1,"616":1,"618":1,"619":2,"620":1,"621":1,"625":1,"628":6,"629":10,"630":1,"632":1,"634":3,"635":4,"636":9,"637":2,"638":4,"639":2,"642":1,"645":1,"646":2,"648":2,"650":1,"651":1,"652":2,"653":1,"654":5,"655":3,"656":5,"657":3,"658":2,"660":1,"662":3,"665":1,"666":3,"667":2,"668":7,"670":3,"671":6,"672":4,"673":6,"674":1,"675":10,"676":4,"677":7,"678":8,"679":10,"680":7,"681":7,"682":6,"683":4,"686":2,"687":1,"688":2,"689":2,"690":3,"691":3,"692":3,"693":4,"694":2,"695":2,"699":3,"700":7,"701":2,"702":1,"703":1,"706":2,"707":1,"708":1,"709":2,"711":2,"715":1,"716":1,"720":1,"721":2,"722":1,"723":2,"725":2,"726":2,"730":2,"731":3,"732":1,"733":2,"736":1,"737":1,"739":2,"741":3,"742":2,"744":1,"745":8,"746":2,"747":2}}],["~",{"2":{"142":2,"168":6,"191":2,"652":4,"705":1}}],["⌥",{"2":{"131":1}}],["→",{"2":{"131":1,"135":7,"142":2,"168":2,"203":2,"547":2,"549":4,"598":3,"603":2,"607":3,"612":1,"641":3,"646":1}}],["⌘",{"2":{"126":2,"130":1,"131":1,"178":1,"196":1,"549":1,"617":2}}],["​​geralmente",{"2":{"689":1}}],["​​globais",{"2":{"652":1}}],["​​gradle",{"0":{"652":1},"2":{"652":1}}],["​​assim",{"2":{"595":1}}],["​​full",{"2":{"595":1}}],["​​estão",{"2":{"346":1}}],["​​e",{"2":{"344":1}}],["​​para",{"2":{"95":1,"104":1,"106":1,"349":1,"592":1,"594":1}}],["​​como",{"2":{"94":1,"103":1}}],["​​dentro",{"2":{"345":1}}],["​​de",{"2":{"90":1,"99":1}}],["96",{"2":{"731":5}}],["9",{"2":{"273":1,"293":1,"493":1,"520":1,"564":1,"703":1}}],["9acd32",{"2":{"88":1}}],["98fb98",{"2":{"88":1}}],["9370db",{"2":{"88":1}}],["90ee90",{"2":{"88":1}}],["9400d3",{"2":{"88":1}}],["9932cc",{"2":{"88":1}}],["997",{"2":{"48":1}}],["ícones",{"2":{"333":1}}],["ícone",{"2":{"73":1,"149":1,"174":1,"186":1,"209":1}}],["$location",{"2":{"454":1}}],["$name",{"2":{"454":1}}],["$nvm",{"2":{"191":2}}],["$packagename",{"2":{"298":1}}],["$path",{"2":{"67":1,"142":1,"168":1}}],["$android",{"2":{"142":3,"168":3}}],["$home",{"2":{"142":4,"191":1}}],["$user",{"2":{"69":1,"705":2}}],["$",{"2":{"67":6,"358":1,"390":1,"464":5,"465":1,"488":5,"489":1,"548":1,"553":1,"576":1,"663":1,"722":6,"730":1}}],["72",{"0":{"752":1},"1":{"753":1,"754":1,"755":1,"756":1,"757":1,"758":1,"759":1,"760":1,"761":1,"762":1,"763":1,"764":1,"765":1,"766":1,"767":1,"768":1,"769":1},"2":{"399":1}}],["7b68ee",{"2":{"88":1}}],["778899",{"2":{"88":1}}],["7cfc00",{"2":{"88":1}}],["7fff00",{"2":{"88":1}}],["7fffd4",{"2":{"88":1}}],["708090",{"2":{"88":1}}],["70",{"2":{"84":1,"268":1,"288":1,"746":1}}],["71",{"2":{"64":1,"666":1,"747":1}}],["7",{"2":{"53":1,"270":1,"290":1,"328":2}}],["75",{"2":{"50":1,"65":1,"234":2}}],["8489993",{"2":{"259":2}}],["841584",{"2":{"244":2,"457":1,"481":1}}],["820",{"2":{"685":7}}],["82",{"2":{"126":1}}],["87ceeb",{"2":{"88":1}}],["87cefa",{"2":{"88":1}}],["8b4513",{"2":{"88":1}}],["8b0000",{"2":{"88":1}}],["8b008b",{"2":{"88":1}}],["8097",{"2":{"570":2}}],["80",{"2":{"229":1,"230":1,"231":1,"232":1,"233":1,"731":1}}],["8088",{"2":{"704":1}}],["8087",{"2":{"608":4}}],["8081",{"0":{"703":1,"704":1},"2":{"131":1,"133":2,"320":1,"365":1,"599":2,"602":2,"603":1,"611":2,"612":1,"619":1,"645":2,"646":1,"702":1,"703":3,"704":2,"745":2}}],["808000",{"2":{"88":1}}],["808080",{"2":{"88":2}}],["800080",{"2":{"88":1}}],["800000",{"2":{"88":1}}],["8fbc8f",{"2":{"88":1}}],["8a2be2",{"2":{"88":1}}],["8",{"2":{"53":5,"224":2,"225":2,"226":2,"227":2,"228":2,"229":2,"230":2,"231":2,"232":1,"233":1,"234":2}}],["887f6717d7e4",{"2":{"53":1}}],["+x",{"2":{"716":1}}],["+requermainqueuesetup",{"2":{"487":1}}],["+requiremainqueuesetup",{"2":{"487":2}}],["+=",{"2":{"466":2}}],["+id",{"2":{"403":1,"404":1}}],["+",{"0":{"737":1},"2":{"53":2,"60":2,"126":3,"130":1,"131":5,"153":1,"178":1,"186":1,"196":1,"213":1,"278":1,"279":2,"299":2,"328":2,"345":8,"402":1,"442":4,"454":3,"549":1,"595":1,"617":3,"699":1,"737":2,"738":1,"748":1}}],["68",{"2":{"687":1}}],["67",{"2":{"533":2}}],["69",{"2":{"191":1}}],["696969",{"2":{"88":2}}],["61",{"2":{"721":2}}],["61dafb",{"2":{"122":2}}],["6136",{"2":{"67":1}}],["6a5acd",{"2":{"88":1}}],["66",{"2":{"263":1}}],["663399",{"2":{"88":1}}],["66cdaa",{"2":{"88":1}}],["6b8e23",{"2":{"88":1}}],["62",{"2":{"75":1,"313":1,"358":1}}],["6495ed",{"2":{"88":1}}],["64",{"2":{"65":4,"142":1,"168":2,"203":1,"656":2,"660":1,"731":2,"746":1,"748":1}}],["600x400",{"2":{"92":8,"101":4}}],["60",{"2":{"55":1,"63":1,"67":1,"233":1,"245":1,"532":1,"533":1,"545":1,"556":2,"746":1}}],["6",{"0":{"406":1,"434":1},"2":{"53":1,"67":2,"223":4,"224":2,"225":2,"226":2,"227":2,"228":2,"229":2,"230":2,"231":1,"234":2,"595":1,"603":1}}],["ws",{"2":{"522":7}}],["weight",{"2":{"531":1}}],["we",{"2":{"457":1,"481":1}}],["welcome",{"2":{"429":2,"681":1}}],["websocket",{"0":{"522":1},"2":{"522":1}}],["websockets",{"2":{"389":1,"455":1,"480":1,"522":1,"709":2}}],["webview",{"2":{"376":3,"532":1}}],["webpack",{"2":{"151":1,"176":1,"193":1,"211":1,"566":1}}],["web",{"0":{"566":1},"2":{"77":1,"79":1,"135":3,"151":1,"176":1,"193":1,"211":1,"222":1,"229":1,"231":1,"239":1,"240":1,"245":1,"250":1,"339":1,"341":1,"347":2,"379":2,"381":1,"382":1,"387":1,"415":1,"417":1,"514":2,"521":1,"562":1,"566":3,"630":1,"635":2,"636":4,"668":1,"669":1,"691":1,"695":1,"723":1}}],["writing",{"2":{"662":2,"663":2}}],["writablearrays",{"2":{"464":1}}],["writablemap",{"2":{"427":1,"465":2,"466":5}}],["writeablemaps",{"2":{"464":1}}],["wrap",{"0":{"230":1},"2":{"224":1,"225":1,"226":1,"227":1,"228":1,"229":2,"230":3,"231":1,"232":1,"233":1,"234":1,"404":1}}],["wrapper",{"2":{"51":1,"56":1,"92":1,"101":1,"113":1,"200":2,"427":1,"441":1,"442":2,"443":1,"444":1,"461":1,"485":1}}],["word",{"2":{"242":2}}],["world",{"2":{"239":1,"277":1,"297":1,"390":1}}],["workflow",{"0":{"755":1}}],["work",{"2":{"564":1}}],["workspaces",{"2":{"375":1}}],["workaround",{"2":{"68":1}}],["workers",{"2":{"65":1}}],["watches=582222",{"2":{"715":1}}],["watch",{"2":{"676":1}}],["watchman",{"0":{"143":1,"165":1,"183":1},"2":{"143":4,"164":1,"165":3,"182":1,"183":3,"715":1}}],["waiting",{"2":{"576":1}}],["waitingmodulenames",{"2":{"576":2}}],["wars",{"2":{"520":1}}],["warn",{"2":{"392":1,"521":1,"705":1}}],["warning",{"2":{"128":1,"309":1,"354":1}}],["wasd",{"2":{"554":1}}],["was",{"2":{"467":2}}],["want",{"2":{"430":1}}],["wav",{"2":{"329":1}}],["wakelock",{"2":{"259":1}}],["who",{"2":{"390":2}}],["when",{"2":{"259":2,"431":1,"467":1}}],["whether",{"2":{"256":2}}],["wheat",{"2":{"88":1}}],["which",{"2":{"67":8,"431":1}}],["whitesmoke",{"2":{"88":1}}],["white",{"2":{"53":1,"88":1,"224":1,"225":1,"226":1,"227":1,"228":1,"229":1,"230":1,"233":1,"234":1,"245":3}}],["w",{"2":{"60":4}}],["wi",{"0":{"603":1,"612":1,"620":1,"646":1},"2":{"601":1,"603":2,"610":1,"612":2,"618":1,"619":1,"620":1,"644":1,"646":2}}],["will",{"2":{"431":1,"457":1,"481":1}}],["wifi",{"2":{"259":3}}],["withextension",{"2":{"320":1,"365":1}}],["with",{"2":{"245":1,"279":1,"299":1,"358":1,"402":1,"404":1,"409":1,"412":1,"429":2,"430":2,"431":2,"432":1,"444":1,"454":2,"464":1,"465":1,"488":1,"489":1,"748":1}}],["wix",{"2":{"235":1}}],["window",{"2":{"278":2,"298":2,"367":1,"497":1,"548":1,"659":1}}],["windowsize",{"0":{"503":1},"2":{"503":2}}],["windows",{"0":{"161":1,"640":1,"650":1},"1":{"641":1,"642":1,"643":1,"644":1,"645":1,"646":1,"647":1},"2":{"126":1,"131":1,"200":3,"203":2,"328":1,"379":1,"382":1,"513":2,"605":2,"650":1,"703":1,"746":1}}],["windowwidth",{"2":{"53":5}}],["width=",{"2":{"403":1,"404":1}}],["widthvalues",{"2":{"233":3}}],["widthvalues=",{"2":{"233":1}}],["widthtype=",{"2":{"233":1}}],["widthtype",{"2":{"233":7}}],["widthheightbasics",{"2":{"233":2}}],["width",{"2":{"46":1,"53":5,"54":1,"60":2,"110":1,"111":1,"116":2,"120":1,"121":1,"122":5,"224":1,"225":1,"226":1,"227":3,"228":2,"229":1,"230":1,"231":3,"232":2,"233":3,"234":1,"245":1,"261":4,"262":1,"263":2,"328":1,"330":2,"331":1,"332":1,"333":1,"334":1,"337":1,"338":1,"339":1,"348":3,"387":1,"431":8,"434":1,"445":1,"690":4,"731":1}}],["widgets",{"2":{"420":1,"440":1}}],["widget",{"0":{"43":1},"2":{"43":6,"44":1,"248":1,"429":5,"431":2}}],["||",{"2":{"259":2,"444":1}}],["|config|",{"2":{"68":1}}],["|target|",{"2":{"68":1}}],["|installer|",{"2":{"68":1}}],["|",{"2":{"50":2,"122":1,"233":2,"234":3,"426":2,"562":3,"608":1,"685":1,"715":1}}],["56",{"2":{"726":1}}],["5s",{"2":{"699":1}}],["54",{"2":{"685":2}}],["58",{"2":{"685":7}}],["5554",{"2":{"599":1,"608":1,"642":1}}],["556b2f",{"2":{"88":1}}],["5+",{"2":{"555":1}}],["57",{"2":{"516":1,"726":1}}],["573",{"2":{"337":1}}],["5fd3f3",{"2":{"429":2}}],["5f9ea0",{"2":{"88":1}}],["591",{"2":{"337":1}}],["5940",{"2":{"67":1}}],["51",{"2":{"333":2,"608":1}}],["52",{"2":{"309":1,"354":1}}],["5",{"0":{"405":1,"426":1,"433":1},"2":{"50":3,"53":2,"54":1,"68":1,"113":1,"133":1,"268":1,"279":1,"288":1,"299":1,"317":1,"328":1,"362":1,"390":1,"555":1,"602":1,"611":1,"645":1}}],["5x",{"2":{"49":1}}],["5000",{"2":{"256":2,"257":2}}],["500",{"2":{"56":1,"224":1,"225":1,"226":1,"227":1,"228":1,"229":1,"230":1,"231":1,"233":1,"234":1}}],["50|",{"2":{"50":2}}],["50",{"2":{"46":1,"84":1,"114":2,"115":2,"116":2,"224":2,"225":2,"226":2,"227":4,"228":3,"229":1,"230":1,"231":3,"232":2,"233":2,"234":4,"261":2,"263":1,"336":1,"338":1,"501":1,"572":3,"668":1}}],["yyyy",{"2":{"462":2}}],["yoga",{"2":{"229":1,"313":2}}],["yourothervalue",{"2":{"519":1}}],["yourvalue",{"2":{"519":1}}],["your",{"2":{"256":2,"283":2,"303":2,"313":3,"332":1,"344":3,"348":1,"430":2,"431":2,"432":1,"452":5,"456":6,"457":1,"481":1,"529":1,"549":1,"553":3,"651":1}}],["yourapp",{"2":{"239":2}}],["you",{"2":{"65":1,"68":1,"244":2,"245":2,"349":3,"387":1,"430":1,"491":1,"731":1,"748":1}}],["yarnios",{"2":{"470":1}}],["yarn",{"0":{"713":1},"2":{"65":1,"67":1,"151":1,"157":1,"268":2,"288":2,"309":2,"354":3,"375":2,"405":2,"470":1,"549":1,"600":1,"609":1,"643":1,"716":1,"725":3,"734":1,"745":1}}],["y",{"2":{"48":2,"51":1,"53":3,"54":3,"56":1,"120":1,"121":1,"122":1,"131":1,"200":1,"251":2,"390":2,"690":4,"699":1}}],["yellowgreen",{"2":{"88":1}}],["yellow",{"2":{"30":2,"88":1}}],["yes",{"2":{"30":2,"320":1,"442":1,"443":1,"490":1,"548":1}}],["2797",{"2":{"711":1}}],["2e76",{"2":{"608":3}}],["2e8b57",{"2":{"88":1}}],["22",{"2":{"730":2}}],["227785",{"2":{"660":1}}],["22b8",{"2":{"608":5}}],["228b22",{"2":{"88":1}}],["21",{"2":{"503":2}}],["2196f3",{"2":{"245":1}}],["23185",{"2":{"523":1}}],["23",{"2":{"278":2,"298":2}}],["2345",{"2":{"134":2}}],["2948",{"2":{"441":1}}],["29",{"2":{"259":2,"726":1}}],["29308",{"2":{"247":1,"669":1}}],["260",{"2":{"245":1}}],["2f4f4f",{"2":{"88":1}}],["256",{"2":{"636":3}}],["25",{"2":{"234":2,"563":1,"685":7}}],["255",{"2":{"82":8}}],["250",{"2":{"46":1,"53":1}}],["2024",{"2":{"687":1,"696":1}}],["2022",{"2":{"390":1}}],["2020",{"2":{"390":1,"488":1}}],["2014",{"2":{"520":1}}],["2010",{"2":{"520":1}}],["2015",{"0":{"393":1},"2":{"746":1}}],["2019",{"2":{"390":1}}],["2018",{"2":{"390":1,"687":1}}],["2017",{"0":{"395":1},"2":{"390":1,"520":1,"648":1}}],["2016",{"0":{"394":1},"2":{"390":1}}],["20115",{"2":{"101":1}}],["2048",{"2":{"311":1,"314":1,"317":1,"356":1,"358":3,"359":1,"362":1,"650":1,"651":1}}],["20b2aa",{"2":{"88":1}}],["20",{"2":{"60":1,"67":1,"116":2,"223":1,"244":2,"245":1,"277":1,"297":1,"317":1,"338":1,"362":1,"573":1,"675":1,"681":1,"737":1}}],["200x200",{"2":{"336":1}}],["200",{"2":{"60":2,"110":2,"116":2,"134":1,"227":1,"228":1,"231":1,"233":1,"234":1,"342":2,"348":6,"387":2,"434":2,"521":1,"534":1,"562":1}}],["200|",{"2":{"50":2}}],["2000",{"2":{"47":1,"675":1}}],["247",{"2":{"730":3}}],["24",{"2":{"53":1,"54":1,"224":1,"225":1,"226":1,"227":1,"228":1,"229":1,"230":1,"233":1,"234":1,"520":1}}],["2d",{"2":{"51":1}}],["2x",{"2":{"49":1,"328":3}}],["2",{"0":{"142":1,"152":1,"168":1,"177":1,"194":1,"203":1,"212":1,"268":1,"277":1,"282":1,"297":1,"302":1,"309":1,"317":1,"320":1,"324":1,"354":1,"362":1,"365":1,"370":1,"402":1,"412":1,"423":1,"430":1,"549":1,"554":1,"599":1,"603":1,"608":1,"612":1,"616":1,"621":1,"642":1,"646":1,"722":1,"725":1},"2":{"47":1,"49":1,"74":1,"77":1,"221":1,"223":3,"262":1,"309":2,"348":1,"354":2,"390":2,"401":1,"461":2,"485":2,"576":1,"608":6,"617":1,"636":1,"638":1,"665":1,"710":1,"730":2}}],["28+",{"0":{"273":1,"293":1}}],["2872",{"2":{"67":2}}],["28",{"2":{"46":1,"273":2,"293":2,"520":1,"726":1}}],["`true`",{"2":{"748":2}}],["`targetrect`",{"2":{"690":1}}],["`basiclistentry",{"2":{"730":1}}],["`module",{"2":{"576":1}}],["`event",{"2":{"464":2,"488":2}}],["`error",{"2":{"464":2,"488":2}}],["`created",{"2":{"464":1,"465":1,"488":1,"489":1}}],["`onactivityresult`",{"2":{"467":1}}],["`ondestroy`",{"2":{"430":2,"468":2}}],["`onresume`",{"2":{"430":2,"468":2}}],["`onpause`",{"2":{"430":2,"468":2}}],["`oncreate`",{"2":{"430":2}}],["`runafterinteractions`",{"2":{"700":1}}],["`rctmycustomview`",{"2":{"427":1}}],["`react`",{"2":{"313":1,"358":1}}],["`app",{"2":{"279":1,"299":1}}],["`settings",{"2":{"279":1,"299":1}}],["`height",{"2":{"262":1,"263":1}}],["`$",{"2":{"233":1}}],["`",{"2":{"223":2,"233":1,"263":1,"313":2,"358":1,"404":1,"464":3,"465":1,"488":3,"489":1,"576":1,"730":1,"748":1}}],["`flags",{"2":{"748":1}}],["`flex",{"2":{"262":2}}],["`flexdirection`",{"2":{"223":1}}],["`false`",{"2":{"748":2}}],["`fadeinview`",{"2":{"46":1}}],["`view`",{"2":{"46":1,"426":1}}],["07",{"2":{"685":6}}],["0666",{"2":{"608":1}}],["04",{"2":{"488":1}}],["0f",{"2":{"424":2}}],["0o7",{"2":{"390":1}}],["0b11",{"2":{"390":1}}],["0+",{"2":{"133":1}}],["0x0",{"2":{"337":1}}],["0xaarrggbb",{"2":{"85":1}}],["0xrrggbbaa",{"2":{"85":1}}],["0xff00ff00",{"2":{"85":1}}],["004",{"2":{"608":2}}],["003",{"2":{"608":4}}],["001",{"2":{"608":14}}],["0024",{"2":{"608":4}}],["002",{"2":{"608":8}}],["000",{"2":{"650":1}}],["0003",{"2":{"608":2}}],["0002",{"2":{"608":6}}],["0009",{"2":{"390":1}}],["000a",{"2":{"390":1}}],["000080",{"2":{"88":1}}],["00008b",{"2":{"88":1}}],["0000cd",{"2":{"88":1}}],["0000ff",{"2":{"88":1}}],["000000",{"2":{"88":1,"92":6,"101":3}}],["00fa9a",{"2":{"88":1}}],["00ff7f",{"2":{"88":1}}],["00ff00",{"2":{"88":1}}],["00ffff",{"2":{"88":2}}],["008080",{"2":{"88":1}}],["008000",{"2":{"88":1}}],["008b8b",{"2":{"88":1}}],["00bfff",{"2":{"88":1}}],["00ced1",{"2":{"88":1}}],["006400",{"2":{"88":1}}],["00",{"2":{"67":3}}],["0deg",{"2":{"50":1}}],["0|",{"2":{"50":1}}],["0px",{"2":{"50":1}}],["0",{"0":{"752":1},"1":{"753":1,"754":1,"755":1,"756":1,"757":1,"758":1,"759":1,"760":1,"761":1,"762":1,"763":1,"764":1,"765":1,"766":1,"767":1,"768":1,"769":1},"2":{"46":3,"48":3,"49":1,"50":25,"51":3,"53":5,"54":2,"64":1,"67":3,"74":1,"75":1,"77":1,"82":6,"83":2,"84":6,"87":4,"110":2,"111":4,"113":1,"142":2,"168":2,"186":1,"191":1,"203":2,"222":1,"224":1,"225":1,"226":1,"227":1,"228":1,"229":1,"230":1,"231":7,"233":2,"234":1,"262":2,"268":4,"288":4,"309":4,"313":2,"349":1,"354":4,"358":2,"383":2,"390":1,"399":1,"431":8,"442":2,"443":2,"466":6,"491":1,"516":1,"520":1,"526":1,"545":1,"555":1,"602":1,"603":1,"608":8,"611":1,"612":1,"621":1,"626":3,"645":1,"646":1,"666":1,"687":1,"691":1,"699":1,"721":6,"726":4,"730":1,"737":4,"746":3,"747":1,"748":1}}],["11",{"2":{"635":1}}],["1d6b",{"2":{"608":8}}],["1`",{"2":{"262":2}}],["1+2+3",{"2":{"223":1}}],["13b07f951a680f5b00a75b9a",{"2":{"722":1}}],["131119",{"2":{"685":1}}],["131854",{"2":{"685":1}}],["132084",{"2":{"685":1}}],["132161",{"2":{"685":3}}],["13",{"2":{"142":2,"168":2,"203":2}}],["17",{"2":{"139":1,"166":2}}],["18998",{"2":{"685":7}}],["18979",{"2":{"685":8}}],["18837",{"2":{"523":1}}],["18",{"2":{"138":1,"165":1,"183":1,"200":1,"268":1,"288":1,"691":3,"730":2}}],["1e90ff",{"2":{"88":1}}],["123",{"2":{"488":2,"621":1}}],["122",{"2":{"442":1,"443":1}}],["12",{"2":{"68":1,"122":4,"224":1,"225":1,"226":1,"227":1,"228":1,"229":1,"230":1,"233":1,"234":1,"488":1,"534":1,"570":1}}],["120",{"2":{"44":1}}],["1999",{"2":{"520":1}}],["1985",{"2":{"520":1}}],["1977",{"2":{"520":1}}],["191970",{"2":{"88":1}}],["19",{"2":{"67":1}}],["196",{"2":{"67":3}}],["14ed2fcc",{"2":{"599":1,"608":1,"642":1}}],["14",{"2":{"54":1,"186":1,"625":1,"626":3,"730":1}}],["15",{"2":{"60":4,"233":1,"263":1,"660":1,"685":7}}],["1556740749",{"2":{"53":1}}],["150",{"2":{"50":3,"54":2,"261":2}}],["150px",{"2":{"50":1}}],["10dp",{"2":{"404":1}}],["1024",{"2":{"342":4}}],["1037",{"2":{"65":1}}],["101|",{"2":{"50":1}}],["101",{"2":{"50":1}}],["1000x",{"2":{"699":1}}],["1000",{"2":{"58":1,"257":2,"691":1,"692":1}}],["10000",{"2":{"46":1,"650":1,"651":1}}],["100|",{"2":{"50":2}}],["100",{"2":{"47":1,"50":6,"60":2,"83":8,"84":3,"231":2,"261":2,"263":2,"339":2,"534":1,"562":1,"679":1}}],["10",{"2":{"46":1,"184":1,"221":1,"224":2,"225":2,"226":2,"227":2,"228":2,"229":2,"230":2,"231":8,"232":3,"233":4,"234":2,"242":2,"277":1,"297":1,"317":1,"320":1,"338":1,"362":1,"365":1,"390":4,"500":1,"502":1,"503":2,"552":1,"564":2,"603":1,"612":1,"621":1,"646":1,"650":1,"675":1,"685":7,"693":1,"730":4}}],["1",{"0":{"141":1,"151":1,"167":1,"176":1,"193":1,"202":1,"211":1,"267":1,"276":1,"281":1,"296":1,"301":1,"308":1,"316":1,"319":1,"323":1,"353":1,"361":1,"364":1,"369":1,"401":1,"411":1,"422":1,"429":1,"547":1,"553":1,"598":1,"602":1,"607":1,"611":1,"615":1,"620":1,"641":1,"645":1,"715":1,"721":1,"724":1},"2":{"46":3,"49":2,"50":9,"51":1,"53":5,"54":1,"56":3,"60":1,"67":1,"74":1,"77":1,"82":2,"83":2,"113":2,"116":4,"122":2,"222":1,"223":5,"224":3,"225":3,"226":3,"227":3,"228":3,"229":3,"230":3,"231":9,"232":3,"233":1,"234":3,"239":1,"244":1,"262":3,"268":2,"270":1,"277":1,"278":1,"288":2,"290":1,"297":1,"298":1,"309":1,"313":1,"317":1,"346":1,"354":1,"358":1,"362":1,"387":1,"390":2,"399":1,"401":1,"431":4,"441":2,"442":4,"443":2,"461":2,"466":2,"467":2,"485":2,"503":1,"520":1,"562":2,"603":2,"612":2,"621":1,"635":3,"638":1,"646":2,"660":2,"680":1,"685":6,"692":4,"693":1,"710":1,"722":1,"730":3,"737":4}}],["16ms",{"2":{"554":1}}],["16",{"2":{"43":3,"53":3,"231":1,"309":1,"354":1,"429":8,"442":1,"443":1,"533":2,"552":1,"556":1,"626":3,"737":1}}],["44",{"2":{"730":2}}],["4277021",{"2":{"660":1}}],["42",{"2":{"242":1,"320":1,"365":1,"390":2}}],["40",{"2":{"242":1,"330":4,"338":1,"346":1,"387":1}}],["400",{"2":{"229":1,"230":1,"232":1,"331":2,"332":2,"334":2}}],["400|",{"2":{"50":1}}],["40e0d0",{"2":{"88":1}}],["4682b4",{"2":{"88":1}}],["4169e1",{"2":{"88":1}}],["4b0082",{"2":{"88":1}}],["4",{"0":{"367":1,"404":1,"425":1,"432":1,"550":1},"2":{"53":3,"65":1,"69":1,"111":1,"224":1,"225":1,"226":1,"227":1,"228":1,"229":1,"230":1,"231":1,"232":1,"233":1,"234":1,"306":1,"342":2,"521":1,"746":1}}],["450",{"2":{"50":1}}],["48d1cc",{"2":{"88":1}}],["483d8b",{"2":{"88":1}}],["48",{"2":{"44":1,"224":1,"225":1,"226":1,"227":1,"228":1,"229":1,"230":1,"234":1,"442":1,"443":1}}],["47",{"2":{"8":1}}],["keep",{"2":{"747":2}}],["kernel",{"2":{"555":2}}],["keypassword",{"2":{"653":1}}],["keyalias",{"2":{"653":1}}],["keyalg",{"2":{"650":1,"651":1}}],["keytool",{"2":{"649":1,"650":1,"651":2}}],["keychain",{"2":{"632":1,"634":3,"652":1}}],["keycode",{"2":{"279":4,"299":4}}],["keysize",{"2":{"650":1,"651":1}}],["keystore",{"2":{"634":2,"650":6,"651":3,"652":3}}],["keys",{"2":{"576":1}}],["keyextractor=",{"2":{"520":1,"730":1}}],["keyextractor",{"0":{"510":1},"2":{"510":1}}],["keyevent",{"2":{"126":1,"279":2,"299":2}}],["key",{"0":{"510":1},"2":{"390":2,"510":1,"511":1,"531":1,"636":1,"650":3,"651":2,"652":5,"653":2,"730":11}}],["key>localhost",{"2":{"323":1,"369":1}}],["key>nstemporaryexceptionallowsinsecurehttploads",{"2":{"323":1,"369":1}}],["key>nsexceptiondomains",{"2":{"323":1,"369":1}}],["key>nsapptransportsecurity",{"2":{"323":1,"369":1}}],["key>",{"2":{"323":4,"369":4}}],["key=",{"2":{"53":2,"224":1,"225":1,"226":1,"227":1,"228":1,"229":1,"230":1,"233":2,"234":1,"317":1,"362":1,"511":1,"680":1}}],["keyboardkey",{"2":{"11":1}}],["kmodulename",{"2":{"492":1}}],["ktclass",{"2":{"402":1}}],["kt",{"2":{"402":1,"404":1,"429":1,"430":2,"431":2,"432":2,"433":1,"452":1,"453":1,"456":2}}],["ktoverride",{"2":{"299":1,"433":1}}],["kibble",{"2":{"348":1}}],["kit",{"0":{"139":1,"166":1},"1":{"167":1,"168":1},"2":{"139":1,"200":3,"279":1,"299":1,"404":1,"417":1}}],["kilobytes",{"2":{"134":1}}],["kotlinreactcontext",{"2":{"468":1}}],["kotlincode",{"2":{"465":1}}],["kotlinconst",{"2":{"463":1}}],["kotlinclass",{"2":{"92":1,"299":1,"402":1,"422":1,"427":2,"467":1}}],["kotlinpromise",{"2":{"465":1}}],["kotlinprivate",{"2":{"404":2}}],["kotlinpackage",{"2":{"256":1,"452":1,"456":1}}],["kotlinoverride",{"2":{"298":1,"299":2,"404":1,"456":1,"463":1,"467":1,"468":1}}],["kotlinimport",{"2":{"259":1,"402":1,"404":1,"454":1,"464":1,"465":1}}],["kotlinval",{"2":{"256":1,"257":1,"462":1}}],["kotlinvar",{"2":{"92":1}}],["kotlin",{"0":{"286":1},"1":{"287":1,"288":1,"289":1,"290":1,"291":1,"292":1,"293":1,"294":1,"295":1,"296":1,"297":1,"298":1,"299":1,"300":1,"301":1,"302":1,"303":1,"304":1},"2":{"97":1,"285":1,"386":1,"402":1,"406":1,"423":1,"424":4,"425":1,"426":1,"429":1,"450":1,"451":1,"452":6,"453":2,"454":1,"455":1,"456":1,"462":4,"464":5,"465":3,"466":1}}],["khaki",{"2":{"88":1}}],["kramer",{"2":{"42":1}}],["xctoolchain",{"2":{"722":1}}],["xcbuildconfiguration",{"2":{"722":1}}],["xcworkspace",{"2":{"549":1,"615":1,"706":1}}],["xcconfig",{"2":{"358":1}}],["xcassets",{"2":{"335":1}}],["xcrun",{"2":{"313":1,"358":1,"625":1,"627":1}}],["xcodedefault",{"2":{"722":1}}],["xcodeproj",{"2":{"411":1,"412":1,"615":1,"704":1,"706":2}}],["xcodebuild",{"2":{"68":3}}],["xcode",{"0":{"68":1,"184":1,"186":1,"312":1,"357":1,"439":1},"1":{"185":1,"186":1},"2":{"39":1,"43":1,"67":1,"68":6,"76":2,"156":1,"182":2,"184":3,"185":3,"186":3,"191":6,"194":1,"312":1,"313":1,"320":1,"325":1,"329":1,"330":1,"357":1,"358":1,"365":1,"371":1,"411":2,"417":1,"437":2,"439":1,"476":3,"493":3,"547":1,"548":1,"549":1,"574":3,"615":3,"616":1,"617":1,"625":1,"635":1,"663":2,"704":1,"706":1,"708":2,"722":1}}],["xxx",{"2":{"651":1}}],["xx",{"2":{"146":2,"171":2,"190":2,"206":2}}],["xmlns",{"2":{"403":1}}],["xmlhttprequest",{"2":{"392":1,"518":1,"521":4}}],["xml",{"2":{"73":2,"256":1,"259":1,"272":4,"273":2,"279":1,"292":4,"293":2,"402":1,"403":2,"404":1,"553":1}}],["x86",{"2":{"65":5,"142":2,"168":2,"203":2,"656":4}}],["x26",{"2":{"54":1,"60":2,"74":10,"77":10,"122":4,"191":2,"224":4,"225":4,"226":4,"227":4,"228":4,"229":4,"230":4,"231":1,"233":8,"234":4,"242":2,"259":6,"279":2,"299":2,"715":2,"747":2,"748":2}}],["x",{"2":{"48":2,"51":2,"52":3,"53":4,"54":3,"120":1,"121":1,"122":1,"146":4,"171":4,"190":4,"206":4,"221":5,"251":2,"390":7,"545":4,"628":1,"650":3,"651":2,"690":4}}],["xposition",{"2":{"47":1}}],["x3c",{"2":{"2":6,"3":6,"4":5,"5":6,"8":4,"10":8,"26":5,"30":10,"35":1,"46":10,"53":17,"54":7,"56":6,"58":1,"60":9,"65":1,"73":7,"92":7,"101":3,"113":13,"114":14,"115":15,"116":15,"122":19,"223":5,"224":18,"225":18,"226":18,"227":18,"228":19,"229":22,"230":22,"231":32,"232":24,"233":28,"234":20,"239":4,"242":5,"244":13,"245":32,"256":1,"259":6,"261":5,"262":5,"263":5,"272":2,"273":5,"277":4,"279":3,"292":2,"293":5,"297":4,"299":3,"317":8,"320":1,"323":15,"328":5,"330":2,"331":2,"332":1,"333":1,"334":1,"338":1,"339":4,"344":6,"345":6,"346":5,"347":11,"348":23,"349":24,"362":8,"369":15,"387":10,"402":3,"403":1,"404":2,"409":1,"422":2,"425":2,"427":4,"431":4,"432":2,"433":2,"434":1,"441":4,"442":7,"443":7,"444":15,"445":3,"456":11,"457":1,"463":4,"477":2,"479":1,"481":1,"490":3,"492":1,"493":2,"511":5,"520":7,"524":1,"553":2,"562":2,"564":1,"573":9,"602":1,"611":1,"645":1,"668":10,"680":8,"681":2,"685":1,"690":14,"692":11,"703":1,"722":7,"730":12,"731":39,"737":9}}],["3rd",{"2":{"625":2}}],["3ª",{"2":{"625":1}}],["37",{"2":{"442":1,"443":1}}],["3x",{"2":{"328":3}}],["35",{"2":{"263":1}}],["333333",{"2":{"317":1,"362":1}}],["33",{"2":{"142":2,"149":1,"168":2,"174":1,"203":2,"209":1,"263":1}}],["3n",{"2":{"131":1,"699":1}}],["3cb371",{"2":{"88":1}}],["398779994",{"2":{"523":1}}],["39",{"2":{"67":2}}],["302",{"2":{"523":1}}],["30",{"2":{"245":1,"668":1}}],["3068",{"2":{"67":4}}],["300`",{"2":{"262":1}}],["300|",{"2":{"50":1}}],["300",{"2":{"50":4,"51":1,"53":1,"233":1}}],["320",{"2":{"545":1}}],["3264x2448",{"2":{"336":1}}],["32cd32",{"2":{"88":1}}],["32",{"2":{"65":1}}],["360deg",{"2":{"50":1}}],["360",{"2":{"48":1,"50":1,"83":4,"84":1}}],["3",{"0":{"278":1,"298":1,"310":1,"321":1,"325":1,"355":1,"366":1,"371":1,"403":1,"413":1,"424":1,"431":1,"555":1,"600":1,"609":1,"617":1,"643":1,"726":1},"2":{"38":1,"67":2,"74":1,"77":1,"223":3,"231":1,"232":1,"257":2,"262":1,"270":1,"290":1,"313":1,"358":1,"390":1,"444":1,"564":1,"608":2,"710":1,"721":2}}],["==",{"2":{"245":1,"259":6,"278":1,"279":1,"298":1,"299":1,"399":1,"431":4,"466":4,"467":7,"521":1,"548":1,"573":1,"608":1}}],["=======",{"2":{"722":1}}],["===",{"2":{"37":1,"74":5,"77":5,"224":2,"225":2,"226":2,"227":2,"228":2,"229":2,"230":2,"233":4,"234":2,"245":1,"521":1,"551":1,"562":1,"563":1}}],["=",{"2":{"46":3,"49":2,"52":1,"53":8,"54":4,"60":4,"68":4,"73":2,"74":2,"76":3,"77":2,"92":8,"101":5,"110":2,"111":8,"113":3,"114":4,"115":4,"116":8,"122":11,"221":2,"223":3,"224":5,"225":5,"226":5,"227":5,"228":5,"229":5,"230":5,"231":9,"232":6,"233":7,"234":5,"239":1,"242":2,"244":1,"245":1,"251":8,"252":2,"255":1,"256":6,"257":4,"259":21,"261":1,"262":1,"263":1,"277":2,"278":2,"279":9,"297":2,"298":2,"299":4,"317":3,"320":4,"328":2,"344":4,"345":6,"346":1,"347":2,"348":6,"349":12,"362":3,"365":6,"387":1,"390":31,"398":3,"399":8,"402":6,"404":7,"422":4,"423":1,"424":8,"425":1,"426":1,"427":7,"429":2,"430":2,"431":31,"432":1,"433":2,"434":5,"441":1,"442":6,"443":6,"444":2,"445":3,"453":2,"455":3,"456":5,"457":4,"461":2,"462":7,"463":4,"464":7,"465":4,"466":8,"467":30,"478":2,"481":4,"485":2,"487":1,"488":6,"489":3,"490":3,"492":3,"511":1,"520":11,"521":2,"522":5,"524":2,"548":3,"562":4,"564":2,"573":4,"574":2,"576":6,"577":8,"582":1,"583":1,"584":1,"585":1,"586":1,"587":1,"588":1,"589":1,"590":1,"591":1,"592":1,"594":1,"595":1,"657":1,"662":1,"667":1,"668":2,"680":5,"690":1,"692":3,"700":1,"722":8,"730":4,"731":2,"737":8,"742":1}}],["=>",{"2":{"35":1,"46":3,"53":3,"54":3,"60":1,"113":3,"114":4,"115":4,"116":4,"122":7,"223":1,"224":5,"225":5,"226":5,"227":5,"228":5,"229":5,"230":5,"231":8,"232":6,"233":8,"234":5,"239":1,"242":3,"244":1,"255":2,"257":1,"261":1,"262":1,"263":1,"277":2,"297":2,"313":28,"317":3,"344":4,"345":5,"346":1,"347":2,"348":5,"349":9,"362":3,"387":1,"399":1,"434":3,"443":1,"444":2,"457":3,"464":7,"465":1,"466":3,"481":3,"488":7,"489":1,"511":1,"520":10,"521":1,"522":4,"544":1,"562":4,"573":2,"576":5,"577":2,"668":1,"675":1,"680":4,"690":4,"692":2,"700":1,"706":2,"730":6,"731":1,"737":4,"742":1,"748":3,"751":3}}],["ões",{"2":{"35":1}}],["zebra",{"2":{"554":1}}],["zero",{"2":{"50":1,"67":1,"285":1,"515":1,"742":1}}],["zoomenabled=",{"2":{"442":2,"443":1}}],["zoomenabled",{"2":{"442":3,"443":1}}],["zoom",{"2":{"427":1,"441":1,"442":5,"443":1,"557":1,"731":1}}],["zona",{"2":{"50":1}}],["zonas",{"2":{"50":1}}],["zulu17",{"2":{"166":2}}],["zulu",{"2":{"166":3}}],["zprofile",{"2":{"142":2,"168":2}}],["zshenv",{"2":{"191":1}}],["zshrc",{"2":{"142":1,"168":1,"191":1}}],["zsh",{"2":{"142":1,"191":2}}],["z",{"2":{"31":1}}],["única",{"2":{"230":1,"285":1,"471":1,"522":1,"635":1,"650":1}}],["único",{"2":{"2":1,"35":1,"62":1,"222":1,"228":1,"320":1,"347":1,"365":1,"464":1,"488":1,"493":1,"574":3,"656":1,"690":2,"700":1,"731":1}}],["últimas",{"2":{"652":1}}],["última",{"2":{"229":1,"325":1,"371":1,"479":1,"653":1,"670":1}}],["últimos",{"2":{"200":1}}],["último",{"2":{"30":1,"128":1,"226":2,"251":1,"464":1,"465":1,"489":1,"490":1,"555":2,"621":1,"668":1,"671":1,"675":1,"699":1}}],["úteis",{"0":{"738":1},"2":{"50":1,"338":1,"416":1,"540":1,"556":1,"569":1}}],["útil",{"2":{"37":1,"50":1,"55":2,"56":1,"60":3,"63":1,"65":1,"70":1,"128":2,"220":1,"251":1,"279":1,"299":1,"343":1,"348":1,"349":2,"399":1,"452":1,"470":1,"566":1,"571":2,"588":1,"724":1}}],["jni",{"2":{"747":1}}],["j",{"2":{"730":1}}],["jimmy",{"2":{"730":2}}],["jillian",{"2":{"730":2}}],["jit",{"2":{"389":1}}],["jwt",{"2":{"636":3}}],["jest",{"2":{"674":2,"675":3,"676":1,"677":1,"681":3,"684":1,"734":2}}],["jellylorum",{"2":{"348":2}}],["jetify",{"2":{"65":1}}],["jetifier",{"2":{"65":3}}],["jpg",{"2":{"338":1}}],["john",{"2":{"730":2}}],["joel",{"2":{"320":1,"365":1,"730":2}}],["jogo",{"2":{"311":1,"319":1,"356":1,"364":1}}],["join",{"2":{"242":1,"737":1}}],["jornada",{"2":{"236":1}}],["jdkx",{"2":{"650":1,"651":1}}],["jdk17",{"2":{"200":1}}],["jdks",{"2":{"166":1}}],["jdk",{"0":{"200":1},"2":{"137":1,"139":2,"164":1,"166":7,"199":1,"200":4,"651":4}}],["julie",{"2":{"730":2}}],["juntas",{"2":{"231":1}}],["juntos",{"2":{"346":1,"673":1,"675":1}}],["junto",{"2":{"96":1,"105":1,"232":1,"332":1,"400":1,"456":1,"679":1,"706":1,"735":1}}],["justificativa",{"2":{"520":1}}],["justificar",{"0":{"226":1}}],["justifycontentbasics",{"2":{"226":2}}],["justifycontent",{"2":{"46":1,"53":4,"54":1,"60":1,"116":2,"122":4,"222":1,"226":4,"227":1,"232":1,"239":1,"244":2,"277":1,"297":1,"317":1,"362":1,"737":1}}],["james",{"2":{"730":2}}],["jackson",{"2":{"730":2}}],["janeiro",{"2":{"520":1}}],["janelas",{"2":{"278":1,"298":1}}],["janela",{"0":{"367":1},"2":{"14":1,"15":1,"24":1,"120":2,"121":1,"203":1,"367":2,"497":1,"499":1,"501":1,"502":1,"503":3,"549":1,"715":1}}],["javareactcontext",{"2":{"467":1,"468":1}}],["javastring",{"2":{"462":1,"465":1}}],["javascriptexception",{"2":{"685":1}}],["javascriptcore",{"0":{"749":1},"1":{"750":1,"751":1},"2":{"389":2,"740":1,"749":1}}],["javascript",{"0":{"268":1,"309":1,"354":1,"388":1,"389":1,"390":1,"426":1,"434":1,"454":1,"466":1,"479":1,"490":1,"534":1,"541":1,"557":1,"572":1,"693":1,"735":1,"763":1},"1":{"389":1,"390":1,"391":1,"392":1,"393":1,"394":1,"395":1,"396":1,"455":1},"2":{"55":2,"62":1,"63":1,"71":1,"73":1,"74":1,"76":1,"77":3,"79":1,"93":1,"105":1,"129":1,"130":1,"131":1,"134":2,"151":2,"176":2,"193":2,"211":2,"238":2,"254":1,"265":1,"268":1,"272":1,"279":3,"282":1,"287":1,"288":2,"292":1,"299":3,"302":1,"306":1,"309":1,"328":1,"343":1,"344":4,"345":3,"348":1,"351":1,"354":1,"375":1,"379":2,"381":1,"384":1,"386":1,"389":5,"390":2,"391":1,"397":1,"405":1,"407":1,"413":2,"415":2,"421":3,"422":1,"424":1,"426":2,"427":2,"441":7,"443":1,"446":3,"448":3,"450":2,"452":2,"453":1,"454":3,"456":1,"457":2,"458":2,"459":1,"461":5,"462":3,"463":2,"464":7,"465":3,"466":3,"467":1,"470":1,"475":2,"478":2,"479":3,"481":2,"482":2,"483":2,"485":5,"486":3,"487":3,"488":9,"489":2,"490":3,"493":2,"500":1,"508":1,"516":2,"525":3,"526":1,"534":7,"535":2,"537":1,"538":1,"541":1,"545":5,"547":1,"551":2,"555":1,"577":1,"602":1,"603":1,"611":1,"612":1,"618":1,"645":1,"646":1,"648":1,"654":2,"655":1,"668":2,"679":2,"693":4,"695":1,"699":1,"704":1,"719":1,"732":2,"734":1,"735":3,"740":1,"742":1,"744":1,"745":3,"749":1,"763":1}}],["javamainapplication",{"2":{"433":1}}],["javamypackage",{"2":{"432":1}}],["javamyviewmanager",{"2":{"431":1}}],["javamyfragment",{"2":{"430":1}}],["javaconst",{"2":{"463":1}}],["javacustomview",{"2":{"429":1}}],["javaclass",{"2":{"427":1}}],["javakoltin",{"2":{"402":1,"454":1}}],["javakotlin",{"2":{"92":2,"256":2,"257":1,"259":1,"402":2,"404":4,"422":1,"423":1,"424":1,"427":2,"452":1,"453":1,"454":1,"455":1,"456":2,"462":1,"463":2,"464":4,"465":3,"466":1,"467":2,"468":2}}],["javaimport",{"2":{"259":1,"402":1,"404":1,"454":1,"464":1,"465":1}}],["javaintent",{"2":{"256":1}}],["javaheadlessjsretrypolicy",{"2":{"257":1}}],["javax",{"2":{"256":1}}],["javapromise",{"2":{"465":1}}],["javaprivate",{"2":{"278":1,"404":2}}],["javapackage",{"2":{"256":1,"452":1,"456":1}}],["javapublic",{"2":{"92":1,"279":1,"402":2,"422":1,"427":1,"467":1}}],["javavirtualmachines",{"2":{"166":1,"651":1}}],["java",{"0":{"139":1,"166":1,"264":1},"1":{"167":1,"168":1,"265":1,"266":1,"267":1,"268":1,"269":1,"270":1,"271":1,"272":1,"273":1,"274":1,"275":1,"276":1,"277":1,"278":1,"279":1,"280":1,"281":1,"282":1,"283":1,"284":1},"2":{"97":1,"139":1,"166":2,"200":3,"256":1,"259":2,"278":1,"279":3,"285":1,"386":1,"402":3,"404":2,"406":1,"423":1,"424":4,"425":1,"426":1,"427":1,"429":1,"430":1,"431":2,"432":3,"433":1,"446":2,"450":1,"451":1,"452":10,"453":3,"454":1,"455":1,"456":9,"462":7,"463":1,"464":5,"465":4,"466":2,"467":1,"468":1,"477":1,"650":1,"651":2,"657":2,"677":1}}],["javabundle",{"2":{"92":1}}],["javauimanager",{"2":{"60":1}}],["já",{"0":{"702":1},"1":{"703":1,"704":1},"2":{"50":1,"89":1,"98":1,"132":1,"140":1,"156":2,"159":1,"165":1,"166":1,"183":1,"184":1,"191":1,"200":2,"201":1,"237":1,"239":1,"283":1,"303":1,"330":1,"334":1,"341":1,"346":1,"375":1,"379":1,"387":1,"420":1,"436":1,"440":1,"442":1,"471":1,"478":1,"518":1,"580":1,"655":2,"662":1,"702":1,"746":1,"747":1}}],["jsproject",{"2":{"662":1}}],["jsandassets",{"2":{"596":1}}],["jsanimated",{"2":{"47":1,"56":1}}],["jsrequire",{"2":{"576":1}}],["jshandleonpress",{"2":{"544":1}}],["jsfetch",{"2":{"519":2}}],["jsshouldcomponentupdate",{"2":{"507":1}}],["jsexport",{"2":{"531":3}}],["jse",{"2":{"444":1}}],["jsbundle",{"2":{"320":1,"365":1,"663":3}}],["jscall",{"2":{"555":1}}],["jsc",{"2":{"320":1,"365":1,"596":1,"747":1,"750":1}}],["jscodelocation",{"2":{"320":2,"365":2}}],["jscontexts",{"2":{"135":1}}],["jscontext",{"2":{"135":4}}],["jsconst",{"2":{"74":1,"76":1,"77":1,"398":1,"399":3,"453":1,"478":2,"487":1,"520":2,"521":1,"522":1,"576":1,"577":1,"700":1,"742":1}}],["jsinteractionmanager",{"2":{"700":1}}],["jsinspector",{"2":{"313":2}}],["jsit",{"2":{"675":1}}],["jsiexecutor",{"2":{"313":2}}],["jsi",{"2":{"313":2,"693":6,"695":1}}],["jsimport",{"2":{"115":1,"365":1,"387":1,"520":1}}],["jstasks",{"2":{"256":2}}],["json",{"2":{"101":1,"122":2,"268":3,"288":3,"309":3,"354":3,"409":1,"442":14,"443":2,"480":2,"486":1,"516":2,"519":4,"520":12,"531":2,"538":1,"567":1,"576":1,"582":1,"596":1,"636":1,"718":1,"725":1,"726":1,"734":3,"739":6}}],["js",{"0":{"254":1,"255":1,"276":1,"296":1,"316":1,"361":1,"534":1,"540":1,"541":1,"577":1,"745":1},"1":{"255":1,"256":1,"257":1,"258":1,"259":1},"2":{"56":1,"60":1,"65":1,"73":1,"74":1,"76":1,"77":1,"92":1,"94":3,"95":3,"97":2,"101":1,"103":3,"104":3,"106":3,"110":1,"111":3,"113":1,"134":3,"135":1,"144":1,"145":1,"156":1,"169":1,"170":1,"188":1,"191":1,"204":1,"205":1,"217":4,"239":2,"254":1,"255":1,"256":1,"257":2,"276":3,"277":1,"279":3,"283":1,"296":3,"297":1,"299":3,"303":1,"316":3,"317":1,"318":1,"320":1,"328":3,"345":1,"348":3,"361":3,"362":1,"363":1,"365":1,"375":2,"379":1,"381":1,"398":2,"399":1,"401":1,"404":2,"424":2,"427":1,"431":2,"442":6,"443":2,"444":1,"446":4,"453":1,"454":1,"455":2,"461":6,"462":2,"463":2,"465":2,"478":2,"480":2,"482":1,"483":1,"485":8,"486":2,"487":1,"488":1,"489":2,"516":1,"535":1,"541":1,"555":3,"556":2,"557":3,"560":1,"565":2,"566":4,"572":1,"573":1,"574":1,"576":3,"577":2,"585":2,"589":1,"591":4,"595":1,"603":1,"612":1,"646":1,"654":1,"660":2,"667":4,"677":1,"679":1,"682":1,"685":3,"700":1,"734":1,"739":5,"741":1,"742":1,"745":2,"747":1,"750":1,"767":1}}],["jsvalue",{"2":{"50":3}}],["jsxtest",{"2":{"680":1}}],["jsxfunction",{"2":{"680":1,"690":2,"692":1}}],["jsxreturn",{"2":{"339":1}}],["jsxonpanrespondermove=",{"2":{"53":1}}],["jsxconst",{"2":{"49":1,"73":1,"457":2,"511":1,"562":2}}],["jsxanimated",{"2":{"48":1,"51":1}}],["jsximport",{"2":{"37":1,"53":1,"54":1,"60":1,"114":1,"116":1,"122":1,"128":1,"223":1,"224":1,"242":1,"244":1,"245":1,"261":1,"262":1,"263":1,"277":1,"297":1,"317":1,"344":1,"345":2,"346":1,"347":1,"348":2,"349":1,"362":1,"457":2,"485":1,"562":2,"563":1,"564":1,"565":1,"566":1,"668":1,"709":1,"730":2,"731":1}}],["jsx",{"0":{"345":1},"2":{"4":1,"5":1,"26":1,"30":1,"35":1,"50":1,"52":1,"56":1,"58":1,"151":1,"176":1,"193":1,"211":1,"328":2,"330":2,"331":1,"332":1,"333":1,"334":1,"337":1,"338":1,"343":1,"344":1,"345":5,"348":2,"349":3,"390":1,"511":1,"573":2,"681":2,"735":1,"737":1}}],["gpu",{"0":{"559":1},"2":{"558":1,"559":2}}],["gfx",{"2":{"553":3}}],["gcd",{"2":{"491":1}}],["gcc",{"2":{"67":7}}],["globais",{"2":{"567":1,"630":1}}],["globalmente",{"2":{"60":1,"144":1,"145":1,"169":1,"170":1,"188":1,"190":1,"204":1,"205":1,"567":1}}],["global",{"2":{"45":1,"145":1,"170":1,"189":1,"205":1,"328":1,"491":1,"567":1,"742":2}}],["glog",{"2":{"313":2}}],["guiá",{"2":{"605":1}}],["guiar",{"2":{"77":1,"554":1}}],["guias",{"0":{"766":1},"1":{"767":1,"768":1},"2":{"11":1,"34":1,"77":2,"79":1,"89":1,"98":1,"131":1,"415":1,"419":1,"448":1,"458":1,"470":1,"471":1,"482":1,"687":1}}],["guia",{"2":{"11":1,"34":1,"41":2,"89":2,"98":2,"131":1,"135":1,"142":2,"143":1,"155":1,"168":2,"180":1,"187":1,"198":1,"203":2,"215":1,"239":1,"241":1,"266":1,"288":1,"307":1,"345":1,"347":1,"352":1,"375":1,"400":1,"401":1,"420":3,"435":1,"440":3,"445":1,"447":3,"450":1,"470":1,"471":1,"472":1,"473":1,"475":1,"518":1,"525":1,"530":1,"532":1,"541":1,"546":2,"547":1,"549":1,"551":2,"579":1,"581":1,"595":1,"604":1,"605":1,"613":1,"622":1,"628":1,"647":1,"648":3,"670":1,"672":1,"674":1,"678":1,"683":1}}],["gutter",{"2":{"232":3}}],["g",{"2":{"145":1,"170":1,"189":1,"205":1,"430":4,"567":1}}],["given",{"2":{"675":1,"680":1}}],["give",{"2":{"349":3}}],["gitlab",{"2":{"652":1}}],["git",{"0":{"728":1},"2":{"652":2,"721":5,"728":8}}],["gitignore",{"2":{"268":1,"288":1,"309":1,"354":1}}],["github",{"2":{"101":1,"113":1,"313":2,"325":1,"358":1,"371":1,"398":1,"418":1,"419":1,"523":2,"701":1}}],["girar",{"0":{"542":1},"2":{"48":1}}],["gira",{"2":{"48":2}}],["ghostwhite",{"2":{"88":1}}],["gasta",{"2":{"577":1,"665":1}}],["gastará",{"2":{"682":1}}],["gastar",{"2":{"156":1,"490":1}}],["gasto",{"2":{"499":1,"552":1,"559":2,"671":1}}],["galleryintent",{"2":{"467":5}}],["gancho",{"2":{"349":2,"480":1,"508":1,"511":1,"628":1}}],["ganchos",{"0":{"221":1},"2":{"219":1,"221":1,"445":1,"680":1}}],["gato",{"2":{"344":1,"345":2,"349":1}}],["gatos",{"2":{"344":1,"347":1,"349":4}}],["gap",{"2":{"232":7}}],["gargalos",{"2":{"551":1}}],["gargalo",{"2":{"112":1,"538":1,"695":1}}],["garantem",{"2":{"681":1}}],["garante",{"2":{"111":1,"252":1,"270":1,"290":1,"574":1,"636":1,"671":1,"672":1}}],["garantido",{"2":{"636":1,"690":1}}],["garantidos",{"2":{"636":1}}],["garantias",{"2":{"96":1,"105":1}}],["garantirá",{"2":{"65":1,"166":1,"741":1}}],["garantir",{"2":{"56":1,"68":1,"110":2,"191":1,"203":1,"267":1,"288":1,"308":1,"330":1,"353":1,"491":1,"493":1,"576":1,"670":1,"673":1,"678":1,"679":2,"691":1,"700":1}}],["gainsboro",{"2":{"88":1}}],["game2048",{"2":{"74":1,"77":1}}],["gb",{"2":{"67":1,"693":1}}],["g++",{"2":{"67":3}}],["gt",{"2":{"49":1,"68":1,"115":1,"126":1,"144":1,"169":1,"186":3,"188":1,"204":1,"221":2,"231":2,"241":1,"251":8,"252":2,"277":2,"297":2,"313":3,"317":2,"339":4,"344":3,"345":3,"347":6,"348":2,"349":6,"358":3,"362":2,"383":2,"387":20,"390":5,"402":1,"403":1,"436":1,"444":1,"462":4,"486":4,"493":1,"553":1,"555":3,"589":1,"596":1,"706":2,"737":1}}],["genkey",{"2":{"651":1}}],["genkeypair",{"2":{"650":1}}],["generatetileviews",{"2":{"692":1}}],["generated",{"2":{"662":1,"685":2}}],["generator",{"2":{"660":1}}],["generation",{"2":{"625":2}}],["generating",{"2":{"313":1,"358":1}}],["general",{"2":{"616":1}}],["generalizar",{"2":{"552":1}}],["generalizado",{"2":{"552":1}}],["genérico",{"2":{"387":1,"730":1,"731":1}}],["gem",{"2":{"187":1}}],["geolocalização",{"2":{"106":1}}],["getbytext",{"2":{"680":2}}],["getbyplaceholdertext",{"2":{"680":2}}],["getdata",{"2":{"467":1}}],["getdefaultconfig",{"2":{"398":2,"399":3,"577":2}}],["getmovies",{"2":{"520":2}}],["getmoviesfromapiasync",{"2":{"520":1}}],["getmoviesfromapi",{"2":{"520":1}}],["getmodules",{"2":{"576":1}}],["getmodule",{"2":{"456":2}}],["getmaincomponentname",{"2":{"92":1}}],["getviewmanagerconfig",{"2":{"444":1}}],["getviewtreeobserver",{"2":{"431":1}}],["getpixelsizeforlayoutsize",{"2":{"434":2}}],["getpackages",{"2":{"279":1,"402":5,"433":3,"456":6}}],["getpackagename",{"2":{"259":2,"278":1}}],["getcurrentactivity",{"2":{"431":1,"467":1}}],["getconstants",{"2":{"463":10,"487":2}}],["getcontext",{"2":{"427":1,"430":1}}],["getcommandsmap",{"2":{"431":2}}],["getitemlayout",{"0":{"509":1},"2":{"509":1,"539":1}}],["getinstance",{"2":{"431":4,"462":2}}],["getint",{"2":{"431":2}}],["getid",{"2":{"427":2}}],["getexclamationmarks",{"2":{"737":2}}],["getexportedcustombubblingeventtypeconstants",{"2":{"427":3}}],["getextras",{"2":{"256":1}}],["getjsmodule",{"2":{"427":2,"466":2}}],["getname",{"2":{"422":3,"431":2,"453":4,"467":2,"480":1}}],["getnetworkcapabilities",{"2":{"259":2}}],["getsupportfragmentmanager",{"2":{"404":3,"431":1}}],["getsystemservice",{"2":{"259":4}}],["getreactmoduleinfoprovider",{"2":{"456":1}}],["getreactnativehost",{"2":{"402":3}}],["getrunningappprocesses",{"2":{"259":1}}],["getusedevelopersupport",{"2":{"402":3}}],["getfullname",{"2":{"345":5}}],["getallbytext",{"2":{"680":3}}],["getactivenetworkinfo",{"2":{"259":1}}],["getactivenetwork",{"2":{"259":1}}],["getapplication",{"2":{"279":2}}],["getapplicationcontext",{"2":{"256":2}}],["getappproperties",{"2":{"92":2}}],["gettransformoptions",{"2":{"577":1}}],["gettaskconfig",{"2":{"256":3}}],["getter",{"2":{"92":1,"101":1,"349":1}}],["get",{"2":{"203":1,"491":2,"521":1,"751":1}}],["getlaunchoptions",{"2":{"92":3,"404":5}}],["gerente",{"2":{"443":1}}],["gerenciado",{"2":{"435":1,"469":1,"728":1}}],["gerenciadora",{"2":{"422":1}}],["gerenciador",{"0":{"375":1,"700":1,"714":1},"1":{"715":1,"716":1},"2":{"191":1,"200":2,"309":1,"375":1,"421":1,"422":1,"424":1,"434":1,"441":3,"442":1,"583":1,"584":1,"585":1,"703":1,"707":1}}],["gerenciadas",{"2":{"189":1}}],["gerenciada",{"2":{"117":1}}],["gerenciamento",{"2":{"187":1,"310":1,"355":1,"417":1,"471":1}}],["gerenciar",{"2":{"144":1,"169":1,"188":1,"204":1,"328":1,"377":1,"378":1,"399":1,"509":1,"648":1}}],["gerenciarão",{"2":{"62":1}}],["gerencia",{"2":{"106":1,"248":1,"471":1}}],["gerando",{"0":{"649":1,"654":1},"1":{"650":1,"651":1},"2":{"658":1}}],["geração",{"2":{"533":1,"548":1,"591":1,"625":1}}],["gerados",{"2":{"660":1,"686":1,"726":1}}],["gerado",{"2":{"445":1,"531":1,"554":1,"577":2,"590":1,"654":1,"656":1,"685":1,"706":1,"711":1}}],["geradores",{"2":{"417":1}}],["gerada",{"2":{"35":1,"636":1,"681":1}}],["gerará",{"2":{"407":1,"651":1,"708":1}}],["gerar",{"2":{"145":1,"159":1,"170":1,"189":1,"205":1,"320":1,"338":2,"365":1,"488":1,"531":1,"533":2,"600":1,"604":1,"608":1,"609":1,"613":1,"636":1,"643":1,"647":1,"649":1,"711":1}}],["gerais",{"2":{"79":1}}],["geralmente",{"2":{"64":1,"79":1,"119":1,"217":1,"245":1,"313":2,"358":2,"379":1,"411":1,"470":1,"497":1,"526":1,"534":1,"554":1,"558":1,"571":1,"579":1,"593":1,"657":1,"668":2,"675":1,"677":1,"729":1,"730":1}}],["geral",{"0":{"532":1},"1":{"533":1,"534":1,"535":1,"536":1,"537":1,"538":1,"539":1,"540":1,"541":1,"542":1,"543":1,"544":1,"545":1},"2":{"39":1,"62":1,"77":1,"110":1,"261":1,"349":1,"551":1,"654":1,"680":1,"738":1,"762":1}}],["gera",{"2":{"35":4,"452":1,"555":1,"595":1,"650":1,"716":1}}],["gesturestate",{"2":{"48":2,"53":6}}],["gestos",{"0":{"52":1,"248":1},"1":{"249":1,"250":1,"251":1,"252":1,"253":1},"2":{"52":2,"55":2,"77":1,"113":1,"243":4,"245":1,"246":1,"248":2,"253":1,"441":1,"442":1,"731":2,"757":1}}],["gesto",{"2":{"31":2,"33":1,"35":1,"48":1,"56":1,"245":2,"249":1,"442":1}}],["gráficas",{"2":{"553":1}}],["gráfico",{"2":{"551":1,"552":1}}],["grocery",{"2":{"680":2}}],["groceryitem",{"2":{"680":4}}],["groceryshoppinglist",{"2":{"680":3}}],["groovyhermesflags",{"2":{"594":1}}],["groovyextrapackagerargs",{"2":{"592":1}}],["groovyentryfile",{"2":{"591":1}}],["groovybundleassetname",{"2":{"590":1}}],["groovybundleconfig",{"2":{"589":1}}],["groovybundlecommand",{"2":{"588":1}}],["groovynodeexecutableandargs",{"2":{"587":1}}],["groovydebuggablevariants",{"2":{"586":1}}],["groovyclifile",{"2":{"585":1}}],["groovycodegendir",{"2":{"584":1}}],["groovyreactnativedir",{"2":{"583":1}}],["groovyroot",{"2":{"582":1}}],["groovyapply",{"2":{"581":1}}],["group=",{"2":{"608":1}}],["groupend",{"2":{"392":1}}],["groupcollapsed",{"2":{"392":1}}],["group",{"2":{"392":1}}],["grow",{"2":{"231":1}}],["greeting",{"2":{"390":1,"737":2}}],["greenyellow",{"2":{"88":1}}],["green",{"2":{"30":1,"88":1,"223":1,"562":1}}],["great",{"2":{"244":1}}],["grey",{"2":{"88":1}}],["grau",{"2":{"652":1}}],["graphql",{"2":{"630":1}}],["graphics",{"2":{"429":2}}],["graça",{"2":{"552":1}}],["graças",{"2":{"10":1,"409":1,"648":1}}],["gravado",{"2":{"745":1}}],["gravados",{"2":{"629":2}}],["gravar",{"2":{"526":1,"529":1}}],["gravação",{"2":{"92":1,"101":1,"526":1}}],["grave",{"0":{"526":1},"2":{"525":1}}],["gravável",{"2":{"389":1}}],["grandes",{"0":{"539":1},"2":{"505":1,"543":1,"571":1,"681":2,"686":1}}],["grande",{"2":{"337":1,"502":1,"538":1,"540":1,"545":1,"571":2,"573":1,"636":1,"676":1,"708":2}}],["granted",{"2":{"298":1}}],["granularidade",{"2":{"441":1}}],["granulares",{"2":{"218":1}}],["granular",{"2":{"45":1,"428":1}}],["gray",{"2":{"88":1,"346":1,"387":1}}],["gradle`",{"2":{"279":2,"299":2}}],["gradlew",{"0":{"716":1},"2":{"65":2,"716":2,"747":1}}],["gradle",{"0":{"270":1,"290":1,"579":1,"653":1},"1":{"580":1,"581":1,"582":1,"583":1,"584":1,"585":1,"586":1,"587":1,"588":1,"589":1,"590":1,"591":1,"592":1,"593":1,"594":1,"595":1,"596":1},"2":{"65":3,"200":5,"270":11,"271":4,"279":1,"283":2,"290":11,"291":4,"299":1,"303":2,"378":1,"402":1,"404":1,"451":1,"574":2,"579":1,"580":1,"581":1,"595":1,"596":1,"652":12,"653":1,"654":4,"656":1,"657":1,"658":2,"662":1,"710":2,"747":2,"750":1,"767":1}}],["gradual",{"2":{"47":1}}],["gradualmente",{"2":{"46":1,"47":1}}],["graduais",{"2":{"47":1}}],["grade",{"2":{"11":2,"34":2}}],["gridview",{"2":{"11":1,"34":1}}],["grid",{"2":{"11":1,"34":1}}],["grupo",{"2":{"11":1,"34":1,"48":2,"411":1,"687":1,"694":1,"697":2}}],["gostado",{"2":{"683":1}}],["gostamos",{"2":{"675":1}}],["gostaria",{"2":{"313":1,"336":1,"339":1,"358":1,"382":1,"429":1,"457":1,"470":1,"481":1,"540":1}}],["gostaríamos",{"2":{"111":1,"532":1}}],["goes",{"2":{"332":1}}],["goldenrod",{"2":{"88":1}}],["gold",{"2":{"88":1}}],["google",{"0":{"648":1,"658":1,"745":1},"1":{"649":1,"650":1,"651":1,"652":1,"653":1,"654":1,"655":1,"656":1,"657":1,"658":1,"659":1},"2":{"38":5,"142":1,"168":2,"203":1,"270":1,"290":1,"446":1,"455":3,"480":3,"531":1,"554":1,"596":1,"598":1,"599":1,"607":1,"608":1,"629":1,"641":1,"642":1,"648":5,"654":5,"658":3,"767":1}}],["go",{"0":{"157":1},"1":{"158":1},"2":{"5":1,"156":1,"158":2,"605":1}}],["hbc",{"2":{"742":1}}],["humanos",{"2":{"671":2,"681":1}}],["hub",{"2":{"608":12}}],["hungry",{"2":{"349":2}}],["híbrido",{"0":{"330":1},"2":{"330":1}}],["html",{"2":{"329":1,"347":1,"553":1,"554":2}}],["http",{"2":{"131":1,"320":1,"323":1,"332":1,"365":1,"369":1,"403":1,"519":1,"520":2,"619":1,"637":1}}],["https",{"2":{"53":1,"92":8,"101":5,"113":1,"259":2,"313":2,"331":3,"332":1,"334":1,"348":1,"358":1,"387":1,"398":1,"519":2,"520":4,"521":1,"523":2,"637":1,"638":2,"652":1,"731":1}}],["h>",{"2":{"320":1,"441":2,"442":4,"443":4,"444":3,"477":1,"479":1,"490":2,"493":2,"524":1}}],["hyper",{"2":{"202":2}}],["hwb",{"0":{"84":1},"2":{"84":5}}],["hsla",{"2":{"83":3}}],["hsl",{"0":{"83":1},"2":{"83":3}}],["hacker",{"2":{"639":1}}],["happen",{"2":{"430":4}}],["handling",{"2":{"349":1}}],["handle",{"2":{"431":1,"700":2}}],["handlerowgapchange",{"2":{"232":3}}],["handlerowgapchange=",{"2":{"232":1}}],["handlecolumngapchange",{"2":{"232":3}}],["handlecolumngapchange=",{"2":{"232":1}}],["handlepress",{"2":{"113":1}}],["hardware",{"2":{"279":2,"299":2,"552":1}}],["hasproperty",{"2":{"653":1}}],["haste",{"2":{"516":2}}],["hastransport",{"2":{"259":6}}],["haslisteners",{"2":{"490":4}}],["has",{"2":{"268":1,"309":1,"354":1}}],["hasinternet",{"2":{"259":6}}],["hashmapof",{"2":{"463":1}}],["hashmap",{"2":{"452":1,"463":1}}],["hash",{"2":{"69":1,"636":1}}],["haja",{"2":{"255":1,"726":1}}],["haverá",{"2":{"656":1}}],["haver",{"2":{"248":1,"411":1}}],["haxm",{"2":{"202":1,"209":2}}],["habilite",{"0":{"574":1,"598":1,"607":1,"641":1,"697":1},"2":{"574":2,"658":1,"695":1}}],["habilitá",{"2":{"135":1,"663":1,"696":1,"740":1}}],["habilita",{"2":{"553":1}}],["habilitando",{"0":{"528":1,"657":1,"746":1},"1":{"747":1,"748":1}}],["habilitar",{"0":{"271":1,"291":1,"661":1,"663":1},"1":{"272":1,"662":1},"2":{"131":1,"598":1,"607":1,"641":1,"662":1,"695":2,"696":1,"746":3,"748":1}}],["habilitada",{"2":{"130":1,"216":1}}],["habilitadas",{"2":{"6":1,"390":1}}],["habilitados",{"2":{"135":1,"596":1,"662":1}}],["habilitado",{"2":{"38":1,"681":1,"751":1}}],["h",{"2":{"60":4,"131":1,"442":2,"443":4,"477":3,"488":1,"490":1,"493":2,"699":1}}],["heterogêneos",{"2":{"731":1}}],["helper",{"2":{"313":2,"358":1,"719":1,"723":1,"726":1,"734":1}}],["helloworld",{"2":{"277":2,"279":1,"297":2,"299":1,"404":3}}],["hello",{"2":{"239":1,"277":2,"297":2,"365":1,"390":4,"737":4}}],["herdar",{"2":{"668":1}}],["hermesenabled=false",{"2":{"750":1}}],["hermesenabled=true",{"2":{"747":1}}],["hermesenabled",{"2":{"747":1,"750":1}}],["hermesinternal",{"2":{"742":3}}],["hermesflagsdebug",{"2":{"662":1}}],["hermesflagsrelease",{"2":{"662":2}}],["hermesflags",{"0":{"594":1}}],["hermesc",{"2":{"593":1,"594":1,"596":1}}],["hermescommand",{"0":{"593":1}}],["hermescpuprofile",{"2":{"531":1}}],["hermesstackframe",{"2":{"531":3}}],["hermessample",{"2":{"531":2}}],["hermes",{"0":{"525":1,"526":1,"531":1,"662":1,"740":1,"741":1,"742":1,"745":1,"746":1},"1":{"526":1,"527":1,"528":1,"529":1,"530":1,"531":1,"741":1,"742":1,"743":2,"744":2,"745":2,"746":1,"747":2,"748":2,"749":1,"750":1,"751":1},"2":{"270":1,"290":1,"389":2,"525":6,"527":2,"529":2,"531":6,"574":3,"593":2,"596":2,"685":1,"740":3,"741":5,"742":3,"745":4,"746":8,"747":2,"748":11,"749":1,"750":1,"751":4,"762":1,"763":1}}],["here",{"2":{"68":1,"242":1,"332":1,"457":1,"481":1}}],["hexadecimal",{"2":{"82":1}}],["height=",{"2":{"403":1,"404":1}}],["heightvalues",{"2":{"233":3}}],["heightvalues=",{"2":{"233":1}}],["heighttype=",{"2":{"233":1}}],["heighttype",{"2":{"233":7}}],["height",{"2":{"46":1,"53":3,"54":1,"60":2,"116":2,"120":1,"121":1,"122":5,"224":1,"225":1,"226":1,"227":1,"228":1,"229":1,"230":1,"231":2,"232":1,"233":3,"234":1,"242":1,"261":4,"262":1,"263":4,"328":1,"330":2,"331":1,"332":1,"333":1,"334":1,"337":1,"338":1,"339":1,"346":1,"348":3,"387":2,"431":8,"434":1,"445":1,"562":1,"690":4,"730":2,"731":1}}],["headlessjsretrypolicy",{"2":{"257":3}}],["headlessjstask",{"2":{"257":1}}],["headlessjstaskerror",{"2":{"257":2}}],["headlessjstaskretrypolicy",{"2":{"257":1}}],["headlessjstaskconfig",{"2":{"256":6,"257":3}}],["headlessjstaskservice",{"2":{"256":5,"258":1,"259":4}}],["headless",{"0":{"254":1},"1":{"255":1,"256":1,"257":1,"258":1,"259":1},"2":{"254":1,"257":2,"767":1}}],["heads",{"2":{"51":1}}],["heading",{"2":{"34":1}}],["headers",{"2":{"68":1,"332":2,"519":1}}],["header",{"2":{"11":1,"413":1,"493":1,"708":3,"722":1}}],["hockeysdk",{"2":{"722":3}}],["hotspot",{"2":{"619":1}}],["hotpink",{"2":{"88":1}}],["house",{"2":{"450":1,"464":1,"465":1,"475":1,"489":1}}],["houver",{"2":{"9":1,"328":1,"334":2,"336":1,"490":1,"679":1,"726":2}}],["hold",{"2":{"431":1}}],["hook",{"2":{"221":1,"349":1}}],["hooks",{"2":{"219":1,"220":1,"349":1,"680":1}}],["homebrew",{"2":{"165":2,"166":3,"183":2,"310":1,"355":1}}],["home=$home",{"2":{"142":1,"168":1}}],["home",{"2":{"142":5,"166":2,"168":5,"203":3,"651":2}}],["host",{"2":{"133":1,"522":1,"603":1,"612":1,"646":1}}],["hospedagem",{"2":{"110":1,"111":2}}],["hospedado",{"2":{"101":1}}],["honeydew",{"2":{"88":1}}],["hora",{"2":{"69":1,"156":1,"241":1,"531":5,"674":1}}],["horizontalmente",{"2":{"226":1,"731":2}}],["horizontal=",{"2":{"53":1}}],["horizontal",{"2":{"52":2,"509":1,"731":1}}],["hoje",{"0":{"696":1},"1":{"697":1},"2":{"43":1,"386":1,"636":1,"689":1,"696":2}}],["há",{"0":{"709":1},"2":{"39":1,"55":1,"69":1,"92":2,"94":1,"101":3,"103":1,"110":1,"111":1,"128":1,"242":1,"283":1,"303":1,"328":1,"414":1,"442":2,"445":1,"491":1,"521":1,"532":1,"541":1,"552":1,"558":1,"560":1,"562":1,"575":1,"576":1,"577":1,"629":1,"635":1,"671":1,"672":1,"677":1,"679":1,"680":1,"683":1,"700":1,"736":1}}],["hipóteses",{"2":{"746":1}}],["historicamente",{"2":{"741":1}}],["histórico",{"2":{"563":1}}],["hi",{"2":{"390":1}}],["highlight",{"2":{"554":1}}],["highscorebuttontapped",{"2":{"365":1}}],["highscorebuttonpressed",{"2":{"320":1}}],["highscorestitle",{"2":{"317":2,"362":2}}],["high",{"2":{"275":1,"295":1,"314":1,"315":1,"317":1,"319":1,"320":1,"325":1,"359":1,"360":1,"362":1,"364":1,"371":1}}],["hits",{"2":{"67":2}}],["hierarquia",{"2":{"31":2,"33":1,"63":1,"90":1,"99":1,"112":1,"113":1,"225":1,"461":1,"485":1,"499":1,"567":1}}],["hierarquicamente",{"2":{"31":1}}],["hidden",{"0":{"24":1},"2":{"24":1,"53":1,"111":1}}],["hide",{"2":{"15":1,"30":2}}],["hint",{"2":{"8":1}}],["às",{"2":{"37":1,"95":1,"104":1,"111":1,"112":2,"116":1,"219":1,"220":1,"221":1,"252":1,"257":1,"263":1,"333":1,"386":1,"407":1,"446":1,"467":1,"497":1,"532":1,"534":1,"544":1,"552":1,"555":1,"663":1,"677":2,"678":1,"689":2}}],["à",{"0":{"653":1},"2":{"5":1,"10":2,"15":1,"42":1,"45":1,"46":1,"56":1,"64":1,"77":2,"85":1,"106":1,"113":1,"122":1,"158":1,"203":1,"219":1,"224":4,"225":2,"227":1,"229":1,"236":1,"251":1,"259":1,"268":1,"278":1,"288":1,"298":1,"309":1,"328":2,"329":1,"334":2,"338":1,"354":1,"385":1,"387":1,"389":1,"403":1,"407":1,"424":1,"428":1,"442":1,"456":4,"458":1,"461":1,"482":1,"485":1,"491":1,"503":1,"509":1,"548":1,"552":1,"553":1,"555":2,"567":1,"571":1,"584":1,"585":1,"599":1,"602":1,"608":2,"611":1,"625":1,"629":1,"638":2,"639":2,"642":1,"645":1,"648":1,"656":1,"668":1,"670":1,"671":1,"673":2,"676":1,"677":1,"687":1}}],["cpus",{"2":{"656":1}}],["cpu",{"2":{"531":1,"656":2}}],["cpuprofile",{"2":{"526":1,"529":2}}],["cpprct",{"2":{"479":1}}],["cpp",{"2":{"477":2,"478":2}}],["cgfloat",{"2":{"486":1}}],["cgrectgetwidth",{"2":{"445":1}}],["cgrectgetheight",{"2":{"445":1}}],["cgrect",{"2":{"111":2}}],["cgrectmake",{"2":{"110":1,"111":1}}],["cjs",{"2":{"390":1}}],["câmeras",{"2":{"693":1}}],["câmera",{"0":{"336":1},"2":{"336":1}}],["ctrl",{"2":{"126":1,"130":1,"131":1,"153":1,"213":1,"279":1,"299":1}}],["ctypedef",{"2":{"111":1}}],["ctime",{"2":{"68":1}}],["cnsarray",{"2":{"101":2}}],["c0c0c0",{"2":{"88":1}}],["cd",{"2":{"157":2,"189":1,"651":1}}],["cd853f",{"2":{"88":1}}],["cd5c5c",{"2":{"88":1}}],["c71585",{"2":{"88":1}}],["cyan",{"2":{"88":1}}],["css3",{"2":{"87":1,"88":1}}],["css",{"2":{"79":1,"222":1,"668":2,"669":1}}],["cm",{"2":{"259":9}}],["cmd",{"2":{"74":1,"77":1,"126":2,"130":1,"131":1,"178":1,"196":1,"549":1,"617":2}}],["cmp",{"2":{"74":10,"77":10}}],["cxxreact",{"2":{"313":2}}],["cxx",{"2":{"68":1}}],["ccc",{"2":{"116":2}}],["cc",{"2":{"67":2,"68":1}}],["ccache",{"2":{"67":19,"68":12,"69":4}}],["c++",{"2":{"66":1,"67":3,"446":2,"477":1,"693":1,"746":1}}],["códigos",{"2":{"656":1,"736":1}}],["código",{"0":{"74":1,"77":1,"274":1,"277":1,"294":1,"297":1,"314":1,"317":1,"359":1,"362":1,"377":1,"378":1,"408":1,"437":1,"561":1,"566":1,"616":1,"673":1,"715":1},"1":{"275":1,"276":1,"277":1,"278":1,"295":1,"296":1,"297":1,"298":1,"299":1,"315":1,"316":1,"317":1,"360":1,"361":1,"362":1,"409":1,"410":1,"411":1,"412":1,"413":1,"438":1,"439":1,"562":1,"563":1,"564":1,"565":1,"566":1},"2":{"53":1,"56":2,"71":1,"73":1,"74":3,"76":1,"77":8,"95":1,"104":1,"111":1,"112":1,"113":2,"116":1,"131":1,"135":1,"142":2,"143":1,"155":1,"158":2,"159":2,"168":2,"180":1,"191":1,"198":1,"203":2,"215":1,"217":1,"218":1,"219":1,"221":1,"239":1,"256":1,"275":2,"276":1,"278":2,"279":2,"282":1,"295":2,"296":1,"298":2,"299":2,"302":1,"310":1,"315":2,"316":1,"320":2,"328":4,"330":1,"336":1,"341":1,"342":2,"343":1,"347":1,"355":1,"360":2,"361":1,"365":2,"376":1,"384":2,"389":4,"390":2,"397":1,"401":2,"404":1,"405":1,"406":2,"407":2,"409":1,"411":1,"416":1,"418":1,"427":1,"435":2,"437":1,"442":2,"445":1,"446":2,"448":2,"451":3,"453":1,"457":1,"458":2,"461":1,"464":1,"465":1,"466":1,"470":2,"472":1,"476":2,"478":1,"481":1,"482":2,"485":1,"487":1,"489":1,"490":1,"491":1,"493":2,"520":1,"532":1,"540":1,"548":2,"551":1,"552":2,"557":1,"561":3,"562":1,"565":2,"566":2,"569":1,"571":1,"572":2,"573":2,"602":1,"603":1,"605":1,"608":1,"611":1,"612":1,"618":1,"629":4,"636":3,"645":1,"646":1,"655":1,"656":2,"668":1,"670":2,"671":6,"672":5,"673":6,"674":2,"675":1,"676":2,"677":2,"679":3,"681":1,"682":1,"686":1,"687":2,"691":3,"695":2,"700":3,"707":1,"708":1,"736":1,"740":1,"745":1,"753":1}}],["cálculos",{"2":{"509":1}}],["cálculo",{"0":{"107":1},"1":{"108":1,"109":1,"110":1,"111":1},"2":{"49":1,"111":2,"231":1,"251":1}}],["celular",{"2":{"562":1}}],["cellular",{"2":{"259":2}}],["cercados",{"2":{"552":1}}],["cerca",{"2":{"156":1,"533":1}}],["certificação",{"2":{"638":1}}],["certificado",{"2":{"638":5,"648":1}}],["certificados",{"2":{"632":1,"638":6}}],["certifique",{"2":{"38":1,"56":1,"58":1,"73":1,"140":1,"141":1,"142":3,"165":1,"167":1,"168":3,"183":1,"184":1,"200":1,"201":1,"202":1,"203":2,"258":1,"270":1,"272":1,"290":1,"292":1,"309":1,"313":1,"323":1,"358":2,"369":1,"402":1,"405":1,"441":1,"511":1,"525":1,"529":2,"537":1,"538":1,"539":1,"549":3,"551":1,"559":1,"576":1,"578":1,"603":1,"608":1,"612":1,"616":1,"619":1,"620":1,"621":1,"646":1,"654":1,"657":1,"662":1,"675":1,"686":3,"706":2,"709":1,"726":1,"745":1,"746":2,"747":1}}],["certas",{"2":{"688":1}}],["certa",{"2":{"532":1,"681":1}}],["certamente",{"2":{"420":1,"440":1,"540":1}}],["certeza",{"2":{"252":1,"651":1}}],["certos",{"2":{"135":1,"143":1,"561":1}}],["certo",{"2":{"68":1,"557":1,"629":1,"675":1}}],["cena",{"2":{"534":1,"545":5}}],["centrados",{"2":{"680":1}}],["centralizado",{"2":{"635":1,"636":1}}],["centralizar",{"2":{"226":1}}],["central",{"2":{"596":1}}],["centro",{"2":{"226":1,"227":1,"229":1,"251":2,"346":1,"442":2}}],["center",{"2":{"46":3,"53":8,"54":2,"60":2,"116":4,"122":8,"224":2,"225":2,"226":4,"227":4,"228":3,"229":4,"230":2,"231":3,"232":2,"233":1,"234":2,"239":2,"244":1,"245":3,"277":2,"297":2,"317":4,"362":4,"443":2,"681":1,"737":2}}],["cenários",{"2":{"558":1,"561":1}}],["cenário",{"2":{"110":1,"523":1,"557":1,"559":1,"560":1}}],["crucial",{"2":{"635":1}}],["cruzando",{"2":{"556":1}}],["cruzado",{"2":{"227":3,"229":5}}],["crashlytics",{"2":{"634":1}}],["crct",{"2":{"480":1,"488":4,"489":1,"491":1}}],["crctconvert+mapkit",{"2":{"442":1}}],["críticos",{"2":{"420":1,"440":1}}],["crop",{"2":{"338":1}}],["criptografia",{"2":{"637":2}}],["criptografam",{"2":{"633":1}}],["criptografados",{"2":{"633":1}}],["criptografado",{"2":{"273":4,"293":3,"323":1,"369":1,"630":1}}],["criptográfico",{"2":{"636":1}}],["criptográficas",{"2":{"634":1}}],["criou",{"2":{"268":1,"288":1,"309":1,"354":1,"402":1,"456":1,"459":1,"483":1,"549":1,"742":1,"747":1}}],["criteriosamente",{"2":{"113":1}}],["crimson",{"2":{"88":1}}],["criação",{"0":{"552":1},"1":{"553":1,"554":1,"555":1},"2":{"345":1,"477":1,"515":1,"552":2,"560":1,"596":1}}],["criaturas",{"2":{"344":1}}],["cria",{"2":{"279":1,"299":1,"349":3,"386":1,"404":1,"450":1,"456":1,"475":1,"491":1,"636":1,"681":1,"730":1,"731":1}}],["crianças",{"2":{"227":1,"231":1,"431":1}}],["criança",{"2":{"113":2,"227":1}}],["criando",{"0":{"145":1,"170":1,"189":1,"205":1,"283":1,"303":1,"515":1,"560":1},"2":{"67":2,"386":1,"419":2,"477":1,"490":1,"492":1,"555":1,"560":1,"635":1,"682":1,"700":1}}],["criamos",{"2":{"111":1,"320":1,"365":1,"422":1}}],["criadas",{"2":{"379":1,"421":1,"423":1,"441":1,"560":1}}],["criada",{"2":{"97":1,"106":1,"421":1,"441":1,"533":1,"681":1}}],["criador",{"2":{"526":1,"529":1,"551":3}}],["criados",{"2":{"76":1,"580":1,"595":1,"662":1,"706":1,"720":1,"733":1,"736":1}}],["criado",{"2":{"67":1,"76":1,"135":1,"318":1,"321":1,"363":1,"366":1,"464":1,"488":1,"548":1,"549":1,"574":1,"580":1,"624":1,"666":1,"681":1,"706":1,"726":1}}],["criaremos",{"2":{"320":2,"365":2}}],["criará",{"2":{"67":1,"448":1,"450":1,"454":1,"475":1,"491":1,"492":1,"574":1}}],["criar",{"2":{"4":1,"35":1,"45":1,"46":1,"47":1,"49":1,"60":1,"65":2,"73":1,"74":1,"77":1,"97":1,"106":1,"110":1,"112":2,"145":1,"149":2,"157":1,"159":1,"164":1,"170":1,"174":2,"189":1,"199":1,"203":1,"205":1,"209":2,"245":1,"257":1,"279":2,"283":4,"299":2,"303":4,"313":2,"318":1,"320":2,"346":1,"358":2,"363":1,"365":2,"402":1,"409":1,"419":3,"426":1,"427":1,"429":1,"434":1,"437":1,"441":1,"443":1,"448":1,"452":1,"459":1,"461":1,"464":1,"477":1,"480":1,"483":1,"485":1,"492":1,"493":2,"525":2,"534":1,"546":1,"549":1,"551":1,"553":1,"554":1,"561":1,"574":1,"578":1,"579":1,"585":1,"588":1,"595":1,"628":1,"635":1,"648":1,"652":1,"656":1,"666":1,"688":1}}],["criem",{"2":{"687":1}}],["crie",{"0":{"65":1,"276":1,"296":1,"316":1,"319":1,"361":1,"364":1,"419":1,"422":1,"429":1,"430":1,"431":1,"450":1,"452":1,"475":1,"477":1,"617":1},"1":{"451":1,"452":1},"2":{"92":1,"101":1,"128":1,"267":1,"268":1,"276":1,"277":1,"282":1,"283":1,"288":2,"296":1,"297":1,"302":1,"303":1,"308":1,"309":1,"316":1,"317":1,"325":1,"339":1,"353":1,"354":1,"361":1,"362":1,"371":1,"386":1,"401":1,"421":1,"456":1,"461":1,"477":2,"485":1,"493":1,"505":1,"507":1,"656":1,"667":1,"734":1}}],["credenciais",{"2":{"652":1}}],["credentials",{"2":{"523":1}}],["cresçam",{"2":{"231":1}}],["crescer",{"0":{"231":1}}],["cresce",{"2":{"64":1,"668":1}}],["createinteractionhandle",{"2":{"700":1}}],["createbundle",{"2":{"596":1}}],["createchooser",{"2":{"467":2}}],["createcalendareventcallback",{"2":{"488":4}}],["createcalendareventmethod",{"2":{"488":1}}],["createcalendarevent",{"2":{"450":1,"454":6,"457":3,"459":2,"461":4,"464":11,"465":3,"475":1,"479":4,"481":3,"483":1,"485":4,"488":3,"489":3}}],["createnativemodules",{"2":{"456":6}}],["createnavigationcontainer",{"2":{"219":1}}],["createfragment",{"2":{"431":6,"434":2}}],["createmap",{"2":{"427":2,"466":2}}],["createviewmanagers",{"2":{"421":1,"425":3,"432":2,"456":2}}],["createviewinstance",{"0":{"423":1},"2":{"421":1,"423":3,"431":2}}],["createreactclass",{"2":{"114":1,"390":1}}],["createreactactivitydelegate",{"2":{"92":2}}],["create",{"2":{"53":1,"54":2,"60":1,"116":2,"122":2,"149":1,"157":2,"174":1,"209":1,"218":2,"223":1,"224":1,"225":1,"226":1,"227":1,"228":1,"229":1,"230":1,"231":1,"232":1,"233":1,"234":1,"244":1,"245":1,"277":1,"297":1,"317":1,"362":1,"431":12,"434":2,"445":1,"454":2,"465":4,"470":3,"479":1,"488":1,"491":1,"562":2,"605":1,"668":2,"730":2,"733":1,"737":1}}],["createanimatedcomponent",{"2":{"46":1}}],["cidade",{"2":{"677":1}}],["cid",{"2":{"492":1}}],["ci",{"0":{"665":1},"1":{"666":1,"667":1},"2":{"65":1,"69":5,"665":5,"666":3,"762":1}}],["ciclo",{"0":{"251":1,"468":1},"1":{"252":1},"2":{"60":1,"248":1,"279":2,"299":2,"428":1,"452":1,"524":1,"665":1}}],["ciente",{"2":{"43":1,"69":1,"499":1}}],["cima",{"2":{"35":1,"90":1,"94":2,"99":1,"103":2,"224":2,"268":1,"288":1,"309":1,"354":1,"531":2,"535":1,"541":1,"721":1}}],["custam",{"2":{"665":1}}],["custos",{"2":{"693":2}}],["custo",{"2":{"342":2,"541":1}}],["customtype",{"2":{"431":2}}],["customview",{"2":{"429":5,"430":22}}],["customização",{"2":{"524":1}}],["customizada",{"2":{"422":1}}],["customizadas",{"2":{"35":2}}],["customizar",{"2":{"191":1}}],["custom",{"2":{"102":1,"431":1,"442":1,"443":1}}],["culpado",{"0":{"556":1}}],["culpa",{"2":{"552":1}}],["cumprir",{"2":{"465":1,"489":1}}],["cumulativa",{"2":{"337":1}}],["cujo",{"2":{"261":1,"673":1}}],["cuja",{"2":{"114":1}}],["cuidar",{"2":{"341":1}}],["cuidará",{"2":{"110":1,"111":1,"270":1,"290":1,"462":1,"486":1}}],["cuidadosa",{"2":{"680":1}}],["cuidadosamente",{"2":{"140":1,"201":1}}],["cuidado",{"2":{"67":1,"85":1,"97":1,"106":2,"111":1,"222":1,"261":1,"279":1,"299":1,"404":1,"456":1,"525":1,"542":1,"675":1,"681":1,"742":1}}],["curtos",{"2":{"675":1}}],["curta",{"2":{"134":1}}],["curly",{"2":{"345":1}}],["curioso",{"2":{"155":1,"180":1,"198":1,"215":1}}],["curva",{"2":{"47":1,"50":1}}],["currentdevice",{"2":{"480":1}}],["currentactivity",{"2":{"431":1,"467":4}}],["current",{"2":{"46":1,"53":1,"54":2,"74":1,"113":1,"116":2,"122":8,"434":1,"690":2,"722":1}}],["curso",{"2":{"10":1,"27":1,"343":1}}],["cut",{"2":{"35":4}}],["chmod",{"2":{"716":1}}],["chuvosa",{"2":{"677":1}}],["chown",{"2":{"705":2}}],["chovendo",{"2":{"677":1}}],["chooserintent",{"2":{"467":4}}],["choreographer",{"2":{"431":8,"555":1}}],["chocolatey",{"2":{"200":2}}],["chocolate",{"2":{"88":1}}],["chrome",{"0":{"131":1,"530":1,"745":1},"2":{"131":5,"134":2,"389":3,"455":3,"480":3,"483":1,"525":2,"527":1,"530":2,"531":1,"551":3,"554":4,"745":9}}],["cheatsheets",{"2":{"738":1}}],["chegarem",{"2":{"637":1}}],["chegada",{"2":{"635":1}}],["chegamos",{"2":{"532":1}}],["cheia",{"2":{"128":1,"130":1}}],["check",{"2":{"69":1,"259":2,"328":6}}],["checked",{"0":{"21":1},"2":{"12":1}}],["checkbox",{"2":{"11":1,"34":1}}],["childitem",{"2":{"203":1}}],["child",{"2":{"114":1}}],["children",{"2":{"46":1,"224":2,"225":2,"226":2,"227":2,"228":2,"229":2,"230":2,"232":2,"233":2,"234":2,"431":1}}],["challenge",{"2":{"636":4}}],["chamá",{"2":{"413":1,"465":1,"489":1}}],["chame",{"2":{"406":1,"479":1}}],["chamava",{"2":{"533":1}}],["chamasse",{"2":{"115":1}}],["chamando",{"0":{"96":1,"97":1,"105":1,"106":1},"2":{"67":1,"349":3,"434":2,"443":1}}],["chamamos",{"2":{"95":1,"104":1,"386":1}}],["chamam",{"2":{"51":1,"68":1,"115":1}}],["chama",{"2":{"48":1,"62":1,"454":1,"680":1}}],["chamará",{"2":{"244":1}}],["chamar",{"2":{"46":1,"62":1,"114":1,"258":1,"349":1,"406":1,"431":1,"443":1,"444":1,"450":1,"455":1,"462":1,"464":1,"465":1,"475":1,"478":1,"480":1,"486":1,"490":1,"534":1,"575":1,"677":1,"699":1}}],["chamados",{"2":{"67":1,"251":1,"252":1,"444":1,"469":1}}],["chamado",{"2":{"46":1,"111":3,"120":1,"121":1,"122":1,"145":1,"157":1,"170":1,"189":1,"205":1,"251":1,"252":1,"279":1,"299":1,"337":1,"342":1,"348":1,"424":2,"427":1,"431":1,"443":2,"444":1,"459":1,"461":1,"467":1,"477":1,"478":1,"485":1,"490":2,"491":2,"524":2,"557":2,"576":2,"579":1,"650":1,"667":1,"668":1,"707":1}}],["chamadas",{"2":{"67":1,"95":1,"104":1,"105":1,"221":1,"345":1,"465":1,"491":1,"531":6,"534":1,"538":3,"555":1,"575":1}}],["chamada",{"2":{"31":1,"32":1,"33":2,"55":2,"90":2,"92":1,"94":3,"99":2,"103":3,"113":1,"115":1,"120":2,"121":2,"166":1,"219":1,"242":2,"251":1,"259":2,"268":1,"279":1,"299":1,"318":1,"333":1,"338":1,"349":1,"363":1,"398":1,"423":1,"424":1,"427":3,"443":5,"456":1,"457":1,"459":1,"464":21,"465":8,"469":2,"470":1,"479":2,"481":1,"483":1,"488":16,"489":1,"511":1,"531":2,"538":1,"552":1,"678":1,"680":1,"689":1,"699":1,"700":1}}],["chaining",{"2":{"390":1}}],["changetext",{"2":{"680":2}}],["changetouches",{"2":{"251":1}}],["change",{"2":{"259":1,"564":1,"748":1}}],["chance",{"2":{"141":1,"167":1,"202":1,"503":2}}],["chartreuse",{"2":{"88":1}}],["chaveiro",{"0":{"632":1}}],["chaves",{"0":{"634":1},"2":{"345":3,"348":3,"442":1,"562":1,"629":2,"633":1,"634":1}}],["chave",{"0":{"88":1,"265":1,"287":1,"306":1,"351":1,"649":1},"1":{"650":1,"651":1},"2":{"465":1,"489":1,"510":1,"531":2,"541":1,"562":2,"581":1,"629":2,"630":1,"633":1,"648":2,"649":1,"650":3,"651":1,"652":1,"653":1,"658":3}}],["chat",{"2":{"51":1}}],["c",{"0":{"305":1},"1":{"306":1,"307":1,"308":1,"309":1,"310":1,"311":1,"312":1,"313":1,"314":1,"315":1,"316":1,"317":1,"318":1,"319":1,"320":1,"321":1,"322":1,"323":1,"324":1,"325":1,"326":1},"2":{"14":2,"66":1,"77":1,"106":1,"110":1,"111":1,"285":1,"320":2,"386":1,"390":4,"441":1,"442":3,"443":3,"444":1,"445":1,"446":2,"477":1,"478":3,"479":1,"486":4,"487":1,"488":1,"490":2,"491":2,"493":5,"548":1,"650":1,"677":1}}],["ca",{"2":{"638":1}}],["cafe",{"2":{"347":3,"348":4,"349":6}}],["café",{"2":{"344":1,"347":1,"349":1}}],["catálogo",{"2":{"628":1}}],["catálogos",{"2":{"330":1}}],["cativos",{"2":{"619":1}}],["categoria",{"2":{"442":2}}],["category",{"2":{"73":2,"531":1}}],["catch",{"2":{"390":3,"465":3,"467":2,"488":1,"489":1,"520":3}}],["cat2",{"2":{"387":1}}],["cat1",{"2":{"348":1}}],["catapp",{"2":{"348":2}}],["catprops",{"2":{"348":2,"349":3}}],["cat",{"2":{"344":12,"345":6,"346":2,"347":8,"348":12,"349":10}}],["cabem",{"2":{"731":1}}],["cabe",{"2":{"330":1}}],["cabeça",{"2":{"143":1}}],["cabeçalhos",{"2":{"413":1,"519":1,"523":1,"730":1}}],["cabeçalho",{"0":{"708":1},"1":{"712":1,"713":1},"2":{"11":1,"34":1,"320":1,"477":1,"479":1,"490":1,"493":5,"523":1,"708":1}}],["cabo",{"2":{"148":1,"173":1,"208":1,"601":1,"603":1,"610":1,"612":1,"615":1,"644":1,"646":1}}],["causado",{"2":{"715":1}}],["causas",{"2":{"711":1}}],["causa",{"0":{"541":1},"2":{"555":1}}],["causar",{"2":{"111":1,"145":1,"170":1,"189":1,"205":1,"413":1,"480":1,"497":1,"501":2,"502":1,"523":1,"538":1,"574":1,"639":1,"686":1}}],["cause",{"2":{"534":1}}],["causem",{"2":{"257":1}}],["caught",{"2":{"131":1}}],["cair",{"2":{"96":1,"105":1}}],["caixas",{"2":{"12":1,"21":1,"141":2,"167":2,"202":2,"549":1}}],["caixa",{"2":{"11":2,"34":2,"142":4,"168":4,"203":4,"218":3,"554":1,"635":1}}],["capturá",{"2":{"257":1}}],["capturas",{"0":{"550":1},"2":{"550":2}}],["capturando",{"2":{"445":1}}],["captura",{"2":{"252":2}}],["capturar",{"0":{"252":1},"2":{"245":1,"520":1}}],["captadas",{"2":{"77":1}}],["captado",{"2":{"74":1,"77":1}}],["capacidades",{"2":{"688":1}}],["capacidade",{"2":{"245":1,"249":1,"251":1,"471":1,"497":3,"500":1,"501":1}}],["capaz",{"2":{"114":1,"249":1,"418":1,"459":2}}],["capítulo",{"2":{"95":2,"104":2}}],["cadeado",{"2":{"628":1}}],["cadetblue",{"2":{"88":1}}],["cadastrar",{"2":{"516":1}}],["cadastre",{"0":{"425":1,"432":1},"2":{"421":1}}],["cada",{"2":{"35":1,"46":1,"48":1,"50":1,"56":2,"69":1,"74":1,"79":1,"90":1,"97":1,"99":1,"106":1,"113":1,"219":1,"220":1,"223":1,"226":1,"227":1,"242":1,"249":1,"251":1,"257":3,"283":1,"303":1,"347":2,"348":1,"421":1,"441":1,"452":1,"456":2,"463":1,"464":1,"465":1,"483":1,"491":1,"500":1,"502":1,"508":1,"511":2,"531":2,"533":2,"534":1,"541":1,"542":1,"543":1,"545":2,"552":1,"553":1,"556":2,"558":1,"574":1,"576":1,"581":1,"596":1,"628":1,"629":1,"630":1,"638":1,"656":1,"657":1,"675":1,"685":1,"687":1,"730":1,"734":1,"746":1}}],["camel",{"2":{"668":1}}],["cameraroll",{"2":{"335":1}}],["camera",{"2":{"158":1}}],["caminho",{"0":{"319":1,"364":1,"739":1},"2":{"142":3,"166":1,"168":2,"191":2,"203":3,"318":2,"363":2,"413":1,"456":1,"467":1,"516":1,"589":1,"593":1,"660":1,"730":1,"739":4}}],["caminhos",{"2":{"68":1,"241":1,"283":1,"303":1,"358":1}}],["camadas",{"2":{"95":1,"104":1,"339":1}}],["camada",{"2":{"73":2,"76":2,"112":1,"334":1,"426":1,"629":1,"636":1}}],["campos",{"2":{"12":1,"13":1,"35":1,"650":1,"667":1}}],["campo",{"2":{"11":2,"12":1,"21":1,"34":2,"35":2,"404":1}}],["cached",{"2":{"334":2}}],["caches",{"0":{"67":1,"70":1},"2":{"66":3,"69":1,"70":1}}],["cache",{"0":{"66":1,"334":1,"342":1,"508":1},"1":{"67":1,"68":1,"69":1},"2":{"66":1,"67":6,"68":2,"69":3,"70":1,"332":1,"334":10,"342":3,"510":1,"526":1,"529":2,"729":2}}],["canais",{"2":{"522":1}}],["cannot",{"2":{"444":1,"660":2}}],["cancelar",{"2":{"749":1}}],["cancelados",{"2":{"700":1}}],["cancelanimationframe",{"2":{"699":1}}],["cancelando",{"2":{"490":1}}],["cancelamento",{"2":{"249":1}}],["canceled",{"2":{"467":2}}],["cancelled",{"2":{"467":8}}],["cancel",{"2":{"392":1}}],["candrawoverlays",{"2":{"278":3,"298":3}}],["canto",{"2":{"142":1,"168":1,"203":1,"244":1,"340":1,"554":1}}],["can",{"2":{"65":1,"68":1,"358":1,"387":1,"491":1,"680":1,"748":1}}],["calendareventreminderreceived",{"2":{"490":1}}],["calendarmanagerbridge",{"2":{"493":1}}],["calendarmanager",{"2":{"490":1,"493":5}}],["calendarmodulefoo",{"2":{"478":5}}],["calendarmoduleclass",{"2":{"452":1}}],["calendarmodule",{"2":{"450":2,"452":6,"453":6,"454":4,"456":5,"457":4,"461":13,"463":2,"464":3,"465":1,"475":2,"477":1,"478":2,"479":1,"481":4,"485":8,"487":1,"488":3,"489":1,"490":2,"493":1}}],["calendar",{"2":{"462":3}}],["calendarinterface",{"2":{"461":2,"485":2}}],["calendário",{"0":{"450":1,"460":1,"475":1,"484":1},"1":{"451":1,"452":1,"461":1,"462":1,"463":1,"485":1,"486":1,"487":1},"2":{"448":5,"450":2,"454":1,"466":2,"475":2,"477":1,"485":1,"490":2}}],["calljavamodulemethod",{"2":{"555":1}}],["callnativemethod",{"2":{"444":8}}],["called",{"2":{"431":1,"454":2}}],["callercontext",{"2":{"422":1,"423":1}}],["call",{"2":{"390":1,"431":1,"491":1,"660":2}}],["callinvoker",{"2":{"313":1}}],["callbacks",{"0":{"464":1}}],["callback",{"0":{"120":1,"121":1,"488":1},"2":{"55":2,"462":2,"464":24,"488":7,"491":4}}],["calculado",{"2":{"261":1}}],["calcula",{"2":{"233":1,"541":1}}],["calculará",{"2":{"636":1}}],["calcular",{"2":{"60":1,"69":1,"338":1,"545":1}}],["cara",{"2":{"560":1}}],["caras",{"2":{"534":1,"700":1}}],["caracteres",{"2":{"116":1}}],["carimbo",{"2":{"531":3}}],["carimbos",{"2":{"69":1,"531":2}}],["carga",{"2":{"490":1,"559":1,"673":1}}],["caro",{"2":{"64":1,"507":1,"543":1}}],["card",{"2":{"53":2}}],["carregá",{"2":{"709":1}}],["carregado",{"2":{"508":1,"572":1,"574":1,"575":1,"577":1,"648":1,"654":1}}],["carregados",{"0":{"576":1},"2":{"334":2,"572":1,"575":1,"576":2,"577":3}}],["carregada",{"2":{"203":1}}],["carregadas",{"2":{"42":2,"337":2}}],["carregamento",{"0":{"575":1},"2":{"323":1,"334":3,"369":1,"571":1}}],["carrega",{"2":{"191":1,"575":1}}],["carregará",{"2":{"565":1,"574":1}}],["carregar",{"2":{"43":1,"142":1,"168":1,"282":1,"302":1,"331":1,"334":1,"405":1,"517":1,"530":1,"572":3,"574":1,"576":1,"704":1,"709":1,"742":1}}],["carregando",{"0":{"572":1},"2":{"42":1,"56":1,"558":1}}],["carreiras",{"2":{"236":1}}],["carrossel",{"2":{"52":1}}],["casquem",{"2":{"668":1}}],["cask",{"2":{"166":4}}],["case",{"2":{"35":3,"431":1,"668":1}}],["casos",{"2":{"49":1,"51":1,"111":1,"140":1,"143":1,"201":1,"217":1,"219":1,"245":1,"252":1,"261":1,"278":1,"298":1,"334":2,"339":1,"377":1,"389":1,"399":1,"520":1,"559":1,"669":1,"670":1,"696":1}}],["caso",{"0":{"715":1},"2":{"30":1,"46":1,"67":1,"108":1,"110":1,"116":1,"191":1,"217":1,"218":1,"231":1,"244":1,"259":2,"276":1,"283":1,"296":1,"303":1,"316":1,"336":1,"339":1,"341":1,"349":2,"361":1,"407":2,"419":1,"421":1,"424":5,"437":1,"441":1,"442":1,"444":1,"487":1,"520":1,"541":1,"548":1,"554":1,"555":5,"556":3,"608":3,"616":1,"619":1,"651":1,"662":1,"667":3,"681":2,"726":1,"734":1}}],["clean",{"2":{"729":1,"747":1}}],["clearinteractionhandle",{"2":{"700":1}}],["clearinterval",{"2":{"699":1}}],["clearimmediate",{"2":{"699":1}}],["cleartimeout",{"2":{"699":1}}],["clear",{"2":{"67":1,"116":1,"392":1}}],["cloud",{"2":{"629":1}}],["cllocationcoordinate2d",{"2":{"442":1}}],["cllocationdegrees",{"2":{"442":2}}],["clima",{"2":{"677":1}}],["clifile",{"0":{"585":1},"2":{"585":1}}],["cliente",{"2":{"636":4,"637":1,"638":5}}],["client",{"2":{"313":1,"358":1}}],["clique",{"2":{"141":1,"142":2,"149":2,"167":1,"168":2,"174":2,"186":1,"200":1,"202":1,"203":11,"209":3,"412":1,"439":1,"530":1,"549":8,"551":1,"708":1,"745":1}}],["cli",{"0":{"159":1,"527":1,"720":1,"728":1},"1":{"160":1,"161":1,"162":1,"528":1,"529":1,"721":1,"722":1},"2":{"65":3,"132":1,"144":2,"145":5,"156":1,"169":2,"170":5,"188":2,"189":5,"190":2,"204":2,"205":5,"266":1,"271":2,"288":1,"291":2,"307":1,"352":1,"375":2,"417":1,"436":1,"437":1,"525":1,"527":1,"529":2,"549":1,"585":4,"589":2,"592":1,"600":1,"609":1,"643":1,"705":1,"719":1,"720":1,"726":2,"733":1}}],["clicks",{"2":{"500":1}}],["click",{"2":{"457":1,"481":1}}],["clicked",{"2":{"10":1}}],["clicando",{"2":{"39":1,"244":2,"438":1}}],["clicar",{"2":{"35":1,"149":1,"166":1,"174":1,"209":1,"321":1,"325":1,"366":1,"371":1,"404":1,"444":1,"568":1,"724":1}}],["clangplusplus=clang++",{"2":{"68":1}}],["clang=clang",{"2":{"68":1}}],["clang++",{"2":{"67":2,"68":2}}],["clang",{"2":{"67":2,"68":2}}],["classificado",{"2":{"531":1}}],["classic",{"2":{"375":2}}],["classthatimplementsrctbridgedelegate",{"2":{"492":1}}],["classpath",{"2":{"270":2,"290":2}}],["classes",{"2":{"97":1,"106":1,"390":1,"441":1,"446":1,"452":2,"676":1}}],["classe",{"2":{"74":2,"77":3,"106":1,"219":2,"279":2,"299":2,"402":7,"404":2,"422":1,"424":1,"429":1,"441":2,"444":1,"452":5,"454":1,"456":1,"466":1,"477":4,"478":4,"486":2,"490":1,"492":1,"493":2,"511":1,"633":1,"680":2,"693":1}}],["class",{"2":{"60":1,"74":1,"77":1,"92":2,"101":1,"244":1,"245":1,"256":4,"259":4,"279":1,"367":1,"390":3,"402":2,"422":5,"427":4,"429":2,"430":2,"431":6,"432":2,"442":1,"443":2,"444":2,"452":2,"456":2,"466":2,"467":1,"493":1,"573":2,"747":2}}],["clara",{"2":{"55":1,"678":1}}],["claro",{"2":{"5":1,"80":1,"244":1,"675":1,"722":1}}],["clamp",{"2":{"50":1,"53":1}}],["cobertos",{"2":{"696":1}}],["cobertura",{"2":{"679":1,"683":1}}],["cobriu",{"2":{"349":1}}],["cobririam",{"2":{"502":1}}],["cobrir",{"2":{"343":1,"502":1,"675":1,"682":1}}],["cobrem",{"2":{"676":1}}],["cobre",{"2":{"95":1,"104":1}}],["cofres",{"2":{"628":1}}],["cooperação",{"2":{"678":1}}],["cooperativo",{"2":{"555":1}}],["cookies",{"2":{"523":1}}],["cookie",{"0":{"523":1},"2":{"523":2}}],["coordenadas",{"2":{"121":1,"122":1,"442":3}}],["coordenação",{"2":{"60":1,"697":1}}],["cocoapod",{"0":{"707":1},"2":{"708":1}}],["cocoapods",{"0":{"187":1,"310":1,"313":1,"355":1,"358":1},"2":{"182":1,"187":4,"189":1,"306":1,"310":4,"313":2,"351":1,"355":4,"358":3,"377":1,"413":1,"615":1,"706":2,"707":2,"708":2}}],["cocoa",{"2":{"513":1}}],["could",{"2":{"430":1}}],["count",{"2":{"10":2,"466":4}}],["cover",{"2":{"426":1}}],["costumava",{"2":{"413":1}}],["costume",{"2":{"283":1,"303":1}}],["coalescing",{"2":{"390":1}}],["codificadas",{"2":{"531":1}}],["codificados",{"2":{"333":1,"730":1}}],["codepush",{"2":{"722":1}}],["codegen",{"2":{"584":3,"596":3}}],["codegendir",{"0":{"584":1},"2":{"584":1}}],["code",{"2":{"278":3,"298":3,"416":1,"465":1,"491":1,"522":1,"548":1,"574":1,"636":9,"663":1,"722":2}}],["codes",{"2":{"259":2,"278":2,"298":2}}],["coisa",{"2":{"217":1,"251":2,"255":1,"442":1,"532":1,"545":1,"629":1,"635":1,"675":2,"739":1}}],["coisas",{"2":{"35":1,"57":2,"69":1,"131":1,"140":1,"201":1,"242":1,"250":1,"255":1,"332":1,"348":1,"349":1,"442":1,"443":1,"446":1,"459":1,"483":1,"499":1,"552":1,"555":3,"679":1,"680":2,"699":1,"731":1}}],["copiando",{"2":{"726":1}}],["copiar",{"2":{"399":1}}],["copie",{"2":{"203":1,"267":1,"288":1,"308":1,"353":1}}],["copy",{"2":{"35":4,"443":1}}],["colando",{"2":{"726":1}}],["colar",{"2":{"239":1}}],["collections",{"2":{"456":2}}],["columngap=",{"2":{"232":1}}],["columngap",{"2":{"232":8}}],["column",{"2":{"223":1,"224":5,"231":2,"531":1}}],["colunas",{"2":{"232":2}}],["coluna",{"0":{"232":1},"1":{"233":1,"234":1,"235":1},"2":{"222":1,"226":1,"599":1,"608":1,"642":1}}],["colegas",{"2":{"666":1}}],["coleções",{"2":{"553":1}}],["coleção",{"2":{"464":1}}],["coletado",{"2":{"553":2}}],["coletando",{"0":{"553":1}}],["cole",{"2":{"203":1}}],["colisões",{"2":{"96":2,"97":1,"105":2,"106":1,"328":1,"441":2}}],["coloque",{"2":{"328":1,"349":1,"548":1,"576":2,"652":1}}],["colocá",{"2":{"156":1}}],["colocados",{"2":{"402":2}}],["colocadas",{"2":{"230":1}}],["colocando",{"2":{"399":1}}],["colocar",{"2":{"339":1,"347":1,"547":1,"690":1}}],["colocaremos",{"2":{"276":1,"296":1,"316":1,"361":1}}],["coloca",{"2":{"35":5,"347":1}}],["colorforduedate",{"2":{"675":2}}],["colorido",{"2":{"552":1}}],["color=",{"2":{"231":3,"244":2,"457":1,"481":1,"737":2}}],["color",{"2":{"53":1,"60":1,"224":2,"225":2,"226":2,"227":2,"228":2,"229":2,"230":2,"231":4,"233":2,"234":2,"244":1,"245":1,"317":1,"362":1,"390":1,"429":4,"668":3}}],["corp",{"2":{"608":4}}],["corpo",{"2":{"442":1,"479":1}}],["corte",{"2":{"556":1}}],["cors",{"2":{"521":1}}],["corelocation",{"2":{"442":2}}],["coremodules",{"2":{"313":2}}],["core",{"0":{"387":1},"2":{"246":1,"313":5,"358":1,"466":2,"541":1,"753":1}}],["cores",{"0":{"79":1,"80":1,"81":1,"86":1,"88":1},"1":{"80":1,"81":1,"82":2,"83":2,"84":2,"85":2,"86":2,"87":3,"88":3},"2":{"9":1,"50":1,"79":2,"80":3,"85":4,"86":3,"88":1,"756":1}}],["corrige",{"2":{"671":1}}],["corrigi",{"2":{"218":1}}],["corrigida",{"2":{"130":1}}],["corrigido",{"2":{"128":1,"131":1,"218":1,"671":1}}],["corrigirão",{"2":{"603":1,"612":1,"646":1}}],["corrigir",{"2":{"128":1,"529":3,"671":1,"675":1}}],["corrija",{"2":{"130":1,"699":1}}],["correr",{"2":{"534":1,"682":1}}],["correspondência",{"2":{"336":1}}],["corresponda",{"2":{"328":1,"477":1,"686":1}}],["corresponde",{"2":{"531":1,"636":1,"669":1,"672":1}}],["correspondem",{"2":{"79":1,"555":1,"625":1,"668":1}}],["correspondentes",{"2":{"334":1,"386":1,"424":1,"531":2,"680":1}}],["correspondente",{"2":{"69":1,"186":1,"328":1,"334":1,"424":2,"443":1,"465":1,"477":1,"489":1,"531":1,"580":1,"747":1}}],["corresponderem",{"2":{"636":1}}],["corresponderá",{"2":{"478":1}}],["corresponder",{"2":{"4":1,"26":1,"133":1,"227":1,"229":1,"279":1,"299":1,"441":1,"516":1,"621":1,"734":1}}],["correção",{"2":{"218":1,"707":1}}],["corretos",{"2":{"251":1,"283":1,"303":1}}],["correto",{"2":{"142":1,"168":1,"222":1,"337":1,"444":1,"565":1,"593":1,"619":1,"681":1}}],["corretamente",{"2":{"67":1,"68":1,"73":1,"74":1,"77":1,"131":1,"152":1,"177":1,"212":1,"431":1,"493":1,"523":1,"529":1,"554":1,"599":1,"608":1,"617":1,"621":1,"624":1,"636":1,"642":1,"662":1,"663":1,"667":1,"673":1,"679":3,"699":1}}],["correta",{"2":{"65":1,"652":1,"667":1,"679":2,"681":1}}],["cornsilk",{"2":{"88":1}}],["cornflowerblue",{"2":{"88":1}}],["coral",{"2":{"88":1,"224":2,"225":2,"226":2,"227":2,"228":2,"229":2,"230":2,"233":2,"234":2}}],["cor",{"0":{"85":1},"2":{"244":1,"421":1,"429":2,"444":1,"556":1,"562":3}}],["congelar",{"2":{"534":1}}],["convincente",{"2":{"532":1}}],["converse",{"2":{"506":1}}],["conversão",{"2":{"442":3,"462":4,"479":2,"486":1}}],["converte",{"2":{"434":2,"462":1,"486":1}}],["converter",{"2":{"50":1,"442":1,"527":1,"531":1}}],["convertido",{"2":{"101":1}}],["convenientes",{"2":{"442":1}}],["conveniente",{"2":{"344":1,"421":1}}],["convenção",{"2":{"344":1,"377":1,"464":1,"477":1,"488":1}}],["connect",{"2":{"549":2,"636":1}}],["connectivitymanager",{"2":{"259":8}}],["connectivity",{"0":{"758":1},"2":{"259":3}}],["conn",{"2":{"259":1}}],["conexões",{"2":{"259":2}}],["conexão",{"2":{"259":3,"520":1,"522":3,"570":1,"619":2}}],["conectá",{"2":{"454":1,"570":1}}],["conecte",{"0":{"321":1,"366":1,"599":1,"608":1,"615":1,"642":1},"2":{"158":1,"273":1,"293":1,"321":1,"366":1,"553":1,"599":1,"608":1,"615":1,"642":1}}],["conecta",{"2":{"745":1}}],["conectar",{"0":{"603":1,"612":1,"646":1},"2":{"279":2,"299":2,"349":1,"442":1,"452":1,"567":1,"596":1,"603":1,"612":1,"619":2,"646":1,"745":1}}],["conectando",{"0":{"601":1,"610":1,"618":1,"644":1},"1":{"602":1,"603":1,"604":1,"611":1,"612":1,"645":1,"646":1,"647":1},"2":{"148":1,"173":1,"208":1,"601":1,"610":1,"644":1}}],["conectados",{"2":{"133":1,"608":1,"677":1}}],["conectado",{"2":{"65":1,"259":4,"529":1,"547":1,"599":3,"602":1,"608":3,"611":1,"642":3,"645":1}}],["conheceu",{"2":{"346":1}}],["conhecer",{"2":{"241":1,"413":1}}],["conhece",{"2":{"237":1,"328":1}}],["conhecimento",{"2":{"113":1,"248":1}}],["conhecidas",{"2":{"111":1,"718":1}}],["conhecidos",{"0":{"78":1,"247":1,"523":1,"669":1},"2":{"74":1,"520":1}}],["conhecido",{"2":{"55":1,"101":1,"110":1,"111":2,"224":1,"328":1,"471":1,"493":1,"675":1,"685":1}}],["conjunto",{"2":{"156":1,"374":1,"386":1,"418":1,"531":1,"555":1,"574":1,"595":1,"675":1,"678":1,"688":1,"723":1,"730":2}}],["condição",{"2":{"675":1}}],["condições",{"2":{"11":1,"34":1,"540":1}}],["condition",{"2":{"257":2}}],["conduzir",{"2":{"95":1,"104":1}}],["conrad",{"2":{"42":1}}],["conselhos",{"0":{"738":1}}],["consegue",{"2":{"419":1,"497":1,"529":1}}],["conseguido",{"2":{"278":1,"298":1}}],["conseguimos",{"2":{"111":1}}],["conseguir",{"2":{"60":1,"67":1,"70":1,"89":1,"98":1,"143":1,"152":1,"177":1,"194":1,"212":1,"379":1,"413":1,"483":1,"533":1,"667":1,"694":1,"747":2,"748":1}}],["consome",{"2":{"682":1}}],["consolidar",{"2":{"107":1}}],["console",{"0":{"128":1,"538":1},"2":{"65":1,"122":1,"128":4,"131":1,"135":1,"244":1,"392":1,"436":2,"457":1,"463":2,"464":5,"465":2,"466":1,"479":1,"481":1,"483":1,"487":1,"488":5,"489":2,"520":3,"521":2,"522":3,"538":5,"554":1,"563":1,"564":1,"573":1,"576":3,"625":1,"654":1}}],["consciente",{"2":{"639":1}}],["consumindo",{"2":{"741":1}}],["consumir",{"2":{"596":1}}],["consumidores",{"2":{"461":1,"485":1,"629":1}}],["consumo",{"2":{"497":1,"503":1}}],["consultas",{"2":{"680":1}}],["consulta",{"2":{"679":1,"680":1}}],["consultar",{"2":{"345":1,"518":1,"581":1}}],["consulte",{"2":{"36":1,"60":1,"74":1,"77":1,"78":1,"101":1,"113":1,"145":1,"152":1,"155":1,"170":1,"177":1,"180":1,"189":1,"194":1,"198":1,"205":1,"212":1,"215":1,"242":1,"273":1,"284":1,"293":1,"304":1,"313":1,"325":1,"326":1,"329":1,"335":1,"339":1,"358":1,"371":1,"372":1,"377":1,"382":1,"383":1,"398":1,"424":1,"434":1,"435":1,"441":1,"486":1,"488":1,"493":1,"520":1,"541":1,"563":1,"577":1,"580":1,"586":1,"595":1,"605":1,"617":1,"654":1,"657":1,"658":1,"681":1,"711":1,"718":1,"746":1,"747":1}}],["consiga",{"2":{"560":1}}],["considera",{"2":{"586":1,"700":1}}],["consideração",{"2":{"546":1,"604":1,"613":1,"622":1,"647":1,"679":1}}],["considerações",{"2":{"546":1,"604":1,"613":1,"622":1,"647":1}}],["considerada",{"2":{"636":1,"696":1}}],["consideradas",{"2":{"452":1,"634":1}}],["considerado",{"2":{"231":1,"334":1,"534":1,"636":1,"681":1}}],["considerar",{"2":{"70":1,"245":1,"413":1,"424":1,"445":1,"541":1}}],["considere",{"2":{"114":1,"120":2,"217":1,"565":1,"571":1,"673":1,"680":1,"682":1}}],["consistente",{"2":{"111":1,"222":1,"232":1,"278":1,"298":1,"533":1,"678":1}}],["constantstoexport",{"2":{"445":1,"487":6,"493":1}}],["constants",{"2":{"390":1,"445":1,"463":3}}],["constante",{"2":{"217":2,"463":2,"487":1,"539":1}}],["constantes",{"0":{"463":1,"487":1},"2":{"47":1,"97":1,"106":1,"445":2,"463":3,"487":3}}],["constrói",{"2":{"65":1,"447":1}}],["constructor",{"2":{"427":1}}],["construída",{"2":{"666":2}}],["construídas",{"2":{"379":2,"381":1}}],["construídos",{"2":{"156":1,"700":1}}],["construído",{"2":{"3":1,"547":1,"666":1}}],["construiu",{"0":{"457":1,"481":1},"2":{"604":1,"613":1,"622":1,"647":1}}],["construindo",{"0":{"458":1,"482":1,"604":1,"613":1,"622":1,"647":1},"2":{"90":1,"99":1,"330":1,"477":1,"558":1,"665":1,"688":1,"741":1,"754":1}}],["construir",{"0":{"549":1},"2":{"64":1,"65":3,"137":1,"142":2,"156":1,"168":2,"182":1,"184":1,"203":2,"266":1,"268":1,"280":1,"288":2,"300":1,"307":1,"309":1,"320":1,"322":1,"348":2,"352":1,"354":1,"365":1,"368":1,"384":1,"386":1,"397":1,"398":1,"417":2,"420":1,"440":1,"448":1,"531":1,"547":1,"549":1,"577":1,"628":1,"629":1,"689":1}}],["construção",{"0":{"64":1,"71":1,"595":1},"1":{"65":1,"66":1,"67":1,"68":1,"69":1,"70":1,"72":1,"73":1,"74":1,"75":1,"76":1,"77":1,"78":1},"2":{"64":2,"65":2,"67":1,"69":1,"76":1,"142":1,"151":1,"168":1,"176":1,"191":4,"193":1,"203":1,"211":1,"343":1,"385":1,"435":1,"548":1,"574":1,"596":1,"621":1,"663":1,"667":1,"672":1,"686":1,"708":1,"734":1,"744":1,"762":1}}],["construtor",{"2":{"46":1,"257":1,"467":1,"468":1}}],["const",{"2":{"46":2,"49":1,"53":6,"54":4,"60":2,"73":1,"76":2,"113":1,"114":4,"115":4,"116":8,"122":10,"223":2,"224":4,"225":4,"226":4,"227":4,"228":4,"229":4,"230":4,"231":6,"232":5,"233":5,"234":4,"239":1,"242":2,"244":1,"245":1,"257":1,"261":1,"262":1,"263":1,"277":2,"297":2,"298":1,"317":3,"328":2,"344":1,"345":6,"346":1,"347":2,"348":5,"349":9,"362":3,"387":1,"390":23,"398":1,"399":3,"422":1,"427":1,"431":2,"434":5,"442":2,"443":1,"445":2,"457":2,"461":2,"465":1,"466":1,"467":5,"481":2,"485":2,"489":1,"520":8,"562":2,"564":1,"576":3,"577":5,"668":2,"680":5,"690":1,"692":3,"730":4,"731":2,"737":6}}],["conflito",{"2":{"722":1}}],["conflitos",{"0":{"117":1,"722":1},"2":{"720":1,"721":1}}],["conformidade",{"2":{"495":1,"695":1}}],["conforme",{"2":{"48":1,"55":1,"60":1,"63":1,"74":1,"77":1,"95":1,"104":1,"231":1,"265":1,"278":1,"283":1,"287":1,"298":1,"303":1,"306":1,"337":1,"351":1,"404":1,"421":1,"441":1,"445":1,"451":1,"452":1,"461":1,"466":2,"473":1,"485":1,"490":1,"495":1,"497":1,"545":1,"572":1,"651":1,"655":1,"656":1,"670":1,"676":1,"678":2,"681":1,"682":1,"690":1,"742":1,"745":1}}],["confortáveis",{"2":{"249":1}}],["conferir",{"2":{"200":1}}],["confundidas",{"2":{"629":1}}],["confundir",{"2":{"30":1,"533":1}}],["confusos",{"2":{"117":1}}],["conf",{"2":{"68":1,"715":1}}],["confiança",{"2":{"679":1,"682":2}}],["confiará",{"2":{"638":1}}],["confiar",{"2":{"491":1,"638":1,"680":1}}],["confiáveis",{"2":{"638":2}}],["confiável",{"2":{"43":1,"554":1,"638":1}}],["confidencial",{"2":{"632":1}}],["confidenciais",{"0":{"629":1},"1":{"630":1,"631":1,"632":1,"633":1,"634":1},"2":{"628":1,"629":1,"630":1,"631":1,"632":1,"634":2,"635":1}}],["confie",{"2":{"338":1,"638":1}}],["config",{"0":{"577":1},"2":{"68":4,"398":8,"399":6,"577":4,"589":2,"629":1,"667":3,"739":2,"748":1,"751":1}}],["configurou",{"2":{"212":1,"457":1,"481":1,"655":1}}],["configureondemand=true",{"2":{"654":1}}],["configure",{"0":{"267":1,"278":1,"298":1,"308":1,"353":1,"616":1},"2":{"142":2,"168":1,"203":1,"265":1,"287":1,"288":1,"306":1,"351":1,"414":2,"454":1,"466":2,"490":1,"524":1,"566":1,"731":1,"733":1,"739":1,"745":1}}],["configurá",{"2":{"67":1,"209":1,"748":1}}],["configurável",{"2":{"50":1,"591":1,"662":1,"745":1}}],["configuráveis",{"2":{"46":1,"47":1}}],["configuration",{"2":{"398":2,"524":2,"547":1,"548":1}}],["configurations",{"2":{"68":1}}],["configura",{"2":{"74":1,"77":1,"596":5}}],["configuradores",{"0":{"424":1},"2":{"421":1,"434":1}}],["configurado",{"2":{"68":1,"132":1,"142":1,"152":1,"168":1,"177":1,"239":1,"459":1,"580":1,"617":1,"624":1,"665":1,"731":1}}],["configurada",{"2":{"43":1,"417":1,"654":1}}],["configuradas",{"2":{"43":2,"68":1,"560":1,"619":1,"672":1,"708":1}}],["configurar",{"0":{"451":1,"476":1,"547":1,"575":1},"1":{"477":1,"478":1,"479":1,"480":1,"481":1,"482":1,"483":1},"2":{"60":1,"68":1,"70":1,"133":1,"137":1,"140":2,"149":1,"164":1,"182":1,"191":1,"199":1,"201":2,"239":2,"250":1,"266":1,"270":1,"288":1,"290":1,"307":1,"349":2,"352":1,"448":1,"459":1,"470":1,"472":1,"479":1,"483":1,"547":1,"549":1,"575":1,"579":1,"581":1,"595":1,"596":1,"599":1,"605":1,"608":1,"642":1,"653":1,"656":1,"675":1,"685":1,"701":1,"704":1}}],["configurando",{"0":{"47":1,"156":1,"191":1,"270":1,"272":1,"290":1,"292":1,"313":1,"342":1,"358":1,"398":1,"524":1,"581":1,"652":1},"1":{"157":1,"158":1,"159":1,"160":1,"161":1,"162":1,"399":1,"582":1,"583":1,"584":1,"585":1,"586":1,"587":1,"588":1,"589":1,"590":1,"591":1,"592":1,"593":1,"594":1},"2":{"47":1,"156":1,"398":1,"447":1,"577":1,"635":1,"754":1}}],["configuração",{"0":{"68":1,"399":1,"406":1,"447":1,"470":1,"496":1,"653":2,"754":1},"1":{"497":1,"498":1,"499":1,"500":1,"501":1,"502":1,"503":1,"504":1,"505":1,"506":1,"507":1,"508":1,"509":1,"510":1,"511":1},"2":{"9":1,"46":2,"47":1,"56":1,"57":1,"67":2,"68":2,"111":1,"133":1,"141":1,"142":4,"159":1,"167":1,"168":3,"202":1,"203":1,"227":1,"236":1,"266":1,"270":1,"273":1,"288":1,"290":1,"293":1,"307":1,"313":1,"329":1,"349":1,"352":1,"358":1,"398":7,"399":8,"400":1,"406":1,"437":1,"470":1,"493":1,"501":1,"577":1,"581":4,"583":1,"584":1,"585":1,"589":3,"595":1,"652":1,"653":2,"654":1,"657":1,"658":2,"667":1,"672":1,"674":1,"682":1,"708":1,"734":1,"740":1,"762":1,"764":1}}],["configurações",{"2":{"6":1,"38":2,"39":1,"133":1,"358":1,"706":1,"708":3}}],["confirme",{"2":{"742":1}}],["confirmando",{"0":{"742":1},"1":{"743":1,"744":1,"745":1}}],["confirmado",{"2":{"681":1}}],["confirmar",{"2":{"65":1,"454":1,"459":1,"479":1,"483":1}}],["confira",{"2":{"55":1,"155":1,"180":1,"198":1,"215":1,"235":1,"253":1,"386":1,"418":1,"445":1,"447":1,"636":1,"668":1,"694":1}}],["conclui",{"2":{"679":1}}],["concluir",{"2":{"454":1}}],["conclusão",{"2":{"464":1,"488":1,"549":1,"636":1,"700":3}}],["concluído",{"2":{"377":1,"470":1}}],["concluída",{"2":{"120":1,"255":1,"491":1,"692":1}}],["concluídas",{"2":{"20":1,"63":1,"470":1}}],["concise",{"2":{"390":1}}],["concisa",{"2":{"46":1}}],["concebível",{"2":{"534":1}}],["concedida",{"2":{"278":1}}],["concentrar",{"2":{"532":1}}],["concentra",{"2":{"46":1,"417":1}}],["conceitos",{"0":{"265":1,"287":1,"306":1,"351":1},"2":{"343":1,"691":1}}],["conceito",{"2":{"44":1,"90":1,"99":1,"497":1,"521":1}}],["concatenando",{"2":{"3":1}}],["contêm",{"0":{"408":1},"1":{"409":1,"410":1,"411":1,"412":1,"413":1},"2":{"398":1}}],["contêineres",{"2":{"230":1}}],["contêiner",{"2":{"11":2,"34":2,"46":1,"223":1,"224":4,"226":12,"227":10,"228":1,"229":6,"230":2,"231":7,"265":1,"287":1,"306":1,"351":1,"387":2,"562":1,"634":1,"731":1}}],["contínua",{"2":{"665":1}}],["contínuas",{"2":{"112":1,"113":1,"687":1}}],["contínuos",{"2":{"55":1}}],["contornado",{"2":{"78":1}}],["contornar",{"2":{"55":1}}],["contribuir",{"2":{"695":1}}],["contribuídos",{"2":{"386":1}}],["contra",{"2":{"628":1,"637":1,"673":1,"681":1}}],["contras",{"2":{"499":1,"500":1,"501":1,"502":1,"503":1}}],["contraparte",{"2":{"465":1,"489":1}}],["contrário",{"2":{"63":1,"259":2,"331":1,"336":1,"349":1,"407":1,"441":1,"487":1,"520":1,"554":1,"675":1,"730":1,"734":1}}],["controlá",{"2":{"441":1}}],["controlled",{"2":{"116":1}}],["controlada",{"2":{"534":1}}],["controladas",{"2":{"534":1,"545":1}}],["controladores",{"2":{"441":1}}],["controlados",{"2":{"242":1}}],["controlado",{"2":{"77":1,"422":1}}],["controlam",{"2":{"235":1}}],["controla",{"2":{"224":1,"230":1,"279":1,"299":1,"500":1}}],["controlar",{"2":{"46":1,"258":1,"262":1,"427":1,"443":1,"444":1,"668":1}}],["controlando",{"2":{"30":1}}],["controles",{"2":{"13":1,"16":1,"17":1,"18":1,"74":1,"77":2,"252":1,"387":2}}],["controle",{"0":{"334":1},"2":{"11":1,"34":1,"35":1,"45":1,"60":1,"74":4,"77":7,"203":2,"251":1,"279":1,"299":1,"334":1,"428":1,"441":1,"671":1,"682":1,"691":2}}],["contar",{"2":{"751":1}}],["contain",{"2":{"333":1,"426":1}}],["container",{"2":{"30":1,"53":2,"54":2,"60":2,"116":4,"122":6,"223":2,"224":2,"225":2,"226":2,"227":2,"228":2,"229":2,"230":2,"231":3,"232":2,"234":2,"244":2,"245":2,"277":2,"297":2,"317":2,"362":2,"430":2,"562":1,"566":4,"668":2,"730":4,"737":2}}],["contas",{"2":{"203":4,"313":1,"358":1}}],["contanto",{"2":{"90":1,"99":1}}],["conta",{"2":{"67":1,"616":2,"634":1,"639":1}}],["contagem",{"2":{"10":1,"672":1}}],["continuamos",{"2":{"696":1}}],["continuamente",{"2":{"427":1,"443":1,"676":1}}],["continuará",{"2":{"218":2}}],["continuar",{"2":{"130":1,"284":1,"304":1,"326":1,"372":1,"459":1,"470":1,"483":1,"603":1,"612":1,"646":1,"726":1}}],["continue",{"2":{"236":1,"401":1,"560":1,"671":1}}],["contido",{"2":{"110":1}}],["contidos",{"2":{"15":1,"24":1}}],["contiver",{"2":{"14":1,"493":1}}],["context",{"2":{"259":34,"423":4,"427":4,"429":10,"430":1,"452":2}}],["contexto",{"2":{"5":1,"106":1,"441":1,"586":1}}],["contenham",{"2":{"358":1}}],["contenha",{"2":{"279":1,"299":1}}],["contents",{"2":{"166":1,"317":2,"362":2,"651":1,"722":1}}],["content",{"2":{"56":1,"256":2,"259":6,"404":1,"429":2,"519":1,"690":2,"724":1}}],["contentoffset",{"2":{"52":3,"53":1,"56":1}}],["contendo",{"2":{"35":2,"135":1,"402":1,"685":1}}],["conterá",{"2":{"313":1,"318":1,"358":1,"363":1,"431":1,"452":1}}],["conter",{"2":{"35":2,"276":1,"296":1,"316":1,"361":1,"385":1,"387":1,"493":1,"629":1,"680":1,"726":1,"731":1}}],["conteúdo",{"0":{"226":1,"229":1},"2":{"11":1,"34":1,"41":1,"69":2,"74":1,"110":2,"111":8,"233":3,"246":1,"268":1,"279":1,"288":1,"299":1,"309":1,"354":1,"413":1,"419":1,"429":1,"452":1,"456":1,"461":1,"477":1,"485":1,"497":1,"499":1,"517":1,"519":1,"541":1,"558":1,"559":1,"635":1,"724":1,"731":1}}],["contém",{"2":{"11":1,"12":1,"13":2,"14":1,"15":1,"24":1,"34":1,"51":1,"52":1,"101":1,"111":1,"191":1,"328":1,"444":3,"463":1,"487":1,"531":1,"580":1,"608":1,"635":1,"650":1,"682":1}}],["comércio",{"2":{"635":1}}],["comandar",{"2":{"534":1}}],["comandos",{"2":{"134":1,"165":1,"166":1,"183":1,"436":1,"470":1,"534":1,"555":1,"569":1,"587":1,"596":1}}],["comando",{"0":{"144":1,"169":1,"185":1,"188":1,"204":1,"312":1,"357":1,"527":1,"710":1,"721":1},"1":{"528":1,"529":1},"2":{"38":1,"65":2,"67":2,"68":4,"133":1,"134":2,"137":1,"144":2,"145":1,"157":1,"164":1,"169":2,"170":1,"182":1,"185":2,"188":2,"189":1,"190":1,"191":1,"195":1,"199":1,"200":3,"203":1,"204":2,"205":1,"268":1,"281":1,"288":1,"301":1,"309":1,"312":2,"313":2,"324":1,"325":1,"354":1,"357":2,"358":2,"370":1,"371":2,"376":1,"431":2,"434":1,"457":1,"458":1,"481":1,"482":1,"525":1,"529":1,"553":1,"554":1,"559":1,"580":1,"588":1,"592":1,"593":1,"600":1,"602":2,"608":2,"609":1,"611":2,"624":1,"625":1,"626":1,"627":2,"643":1,"645":2,"646":1,"650":1,"651":3,"654":2,"655":1,"666":2,"703":1,"711":1,"715":1,"716":1,"718":1,"720":1,"721":2,"726":1,"734":1,"741":1}}],["coming",{"2":{"431":1}}],["common",{"2":{"431":1,"685":1}}],["commonjs",{"2":{"392":1}}],["commit",{"2":{"404":2,"431":2,"686":1,"690":3,"728":3}}],["comma",{"2":{"390":1}}],["command=",{"2":{"574":2}}],["commandargs",{"2":{"444":2}}],["commands",{"2":{"434":1,"444":1}}],["commandidint",{"2":{"431":2}}],["commandid",{"2":{"431":6,"444":2}}],["command",{"2":{"144":1,"169":1,"188":1,"204":1,"431":8}}],["community",{"2":{"145":1,"170":1,"189":1,"205":1,"271":2,"291":2,"313":2,"358":1,"379":1,"383":1,"531":1}}],["começou",{"2":{"688":1}}],["começando",{"0":{"448":1},"2":{"236":1,"471":1,"516":1,"545":1}}],["começa",{"2":{"48":1,"344":1,"637":1}}],["começará",{"2":{"224":4,"387":1}}],["começar",{"2":{"48":2,"156":2,"159":2,"237":1,"343":1,"377":1,"386":1,"387":1,"451":1,"476":1,"477":1,"525":2,"548":1,"553":1,"608":1,"658":1,"660":1,"672":1,"673":1,"675":1,"683":1,"700":1}}],["começamos",{"2":{"442":1}}],["começam",{"2":{"45":1,"516":2}}],["cometem",{"2":{"671":1}}],["cometer",{"2":{"218":3,"249":1}}],["comece",{"2":{"239":1,"434":1,"449":1,"474":1,"520":1,"673":1}}],["comentários",{"2":{"426":1,"723":1}}],["comentário",{"2":{"74":2,"325":1,"371":1}}],["comum",{"2":{"77":2,"93":1,"102":1,"105":1,"116":1,"227":1,"261":1,"339":1,"471":1,"534":1,"541":1,"566":1,"628":1,"668":1}}],["comumente",{"2":{"47":1,"147":1,"172":1,"207":1,"246":1,"421":1}}],["comunitária",{"2":{"472":1}}],["comunique",{"2":{"448":1}}],["comunidade",{"0":{"514":1},"2":{"374":2,"375":1,"379":1,"386":2,"414":1,"419":3,"463":1,"470":1,"487":1,"508":1,"512":1,"630":1,"682":1}}],["comunicar",{"2":{"448":1,"619":1}}],["comunicando",{"2":{"389":1}}],["comunicação",{"0":{"89":1,"98":1},"1":{"90":1,"91":1,"92":1,"93":1,"94":1,"95":1,"96":1,"97":1,"99":1,"100":1,"101":1,"102":1,"103":1,"104":1,"105":1,"106":1,"107":1,"108":1,"109":1,"110":1,"111":1},"2":{"89":1,"91":1,"95":3,"98":1,"100":1,"104":3,"320":1,"365":1,"488":1,"522":1,"636":1,"678":1,"767":1,"768":1}}],["comunica",{"2":{"11":1,"34":1,"455":1,"480":1}}],["comuns",{"0":{"529":1,"536":1},"1":{"537":1,"538":1,"539":1,"540":1,"541":1,"542":1,"543":1,"544":1,"545":1},"2":{"43":1,"107":1,"243":1,"329":1,"417":1,"421":1,"532":1,"672":1,"701":1,"711":1,"730":1}}],["combina",{"2":{"678":1}}],["combinações",{"2":{"465":1}}],["combinação",{"2":{"11":1,"34":1,"222":1,"243":1,"595":1}}],["combinar",{"2":{"49":1,"387":1,"501":1,"741":1}}],["combinando",{"0":{"49":1}}],["combinadas",{"2":{"48":1,"678":1}}],["combinado",{"2":{"11":1,"34":1}}],["combobox",{"2":{"11":1,"34":1}}],["compensações",{"2":{"682":1}}],["comprovada",{"2":{"687":1}}],["comprometida",{"2":{"651":1,"681":1}}],["comprimento",{"2":{"636":1}}],["compreender",{"2":{"112":1,"681":1}}],["computed",{"2":{"390":1}}],["computador",{"2":{"133":2,"134":1,"147":1,"148":1,"158":1,"172":1,"173":1,"207":1,"208":1,"375":1,"381":1,"547":1,"553":1,"618":1}}],["computacionalmente",{"2":{"113":1,"534":1}}],["computacional",{"2":{"63":1}}],["compileroptions",{"2":{"739":1}}],["compiler",{"2":{"69":1,"722":1}}],["compila",{"0":{"707":1}}],["compilado",{"2":{"493":1,"538":1,"742":1}}],["compiladores",{"2":{"67":2,"68":1}}],["compilador",{"0":{"66":1},"1":{"67":1,"68":1,"69":1},"2":{"66":3,"68":3,"390":1,"593":3,"736":1}}],["compilando",{"2":{"65":2}}],["compilará",{"2":{"744":1}}],["compilar",{"2":{"65":2,"67":1,"143":1,"538":1}}],["compilação",{"0":{"73":1,"76":1},"2":{"43":1,"67":7,"69":1,"70":1,"278":1,"298":1,"331":1,"358":1,"413":2,"595":6,"617":1,"654":1,"660":1,"662":2,"663":1,"685":1,"708":1,"747":1}}],["compilações",{"0":{"665":1},"1":{"666":1,"667":1},"2":{"43":2,"66":1,"67":4,"68":1,"69":1,"70":2,"126":1,"127":1,"166":1,"272":1,"273":2,"278":1,"292":1,"293":2,"298":1,"451":1,"537":1,"653":1,"657":1,"660":1,"662":1,"762":1}}],["company",{"2":{"283":2,"303":2}}],["companion",{"2":{"259":1,"298":1,"422":1,"431":1,"467":1}}],["compatibilidade",{"0":{"380":1},"1":{"381":1,"382":1,"383":1},"2":{"143":1,"382":1,"696":1,"746":1}}],["compatível",{"2":{"57":1,"161":1,"162":1,"383":1,"462":1,"463":1,"486":2,"487":1,"488":1,"741":2}}],["compatíveis",{"2":{"56":1,"379":1,"574":1}}],["compare",{"2":{"700":1,"742":1}}],["compartilhá",{"2":{"419":1}}],["compartilhe",{"0":{"419":1},"2":{"455":1,"480":1}}],["compartilhadas",{"0":{"633":1},"2":{"633":1}}],["compartilhado",{"2":{"262":1,"279":1,"299":1,"491":1,"566":2,"630":1}}],["compartilhar",{"2":{"491":1,"619":1}}],["compartilhando",{"2":{"491":1}}],["compartilham",{"2":{"77":1,"96":1,"97":1,"105":1,"106":1}}],["compartilhamento",{"0":{"566":1},"2":{"44":1,"656":1}}],["compartilha",{"2":{"64":1}}],["comparar",{"2":{"691":1,"742":1}}],["comparado",{"2":{"226":1,"229":1,"740":1}}],["comparação",{"2":{"55":2,"113":1,"166":1,"262":1,"507":1,"540":1,"682":1,"692":1,"693":1,"725":1}}],["complicada",{"2":{"719":1}}],["complicadas",{"2":{"571":1}}],["complicado",{"2":{"55":1,"250":1,"442":1,"456":2,"461":1,"485":1}}],["complicariam",{"2":{"310":1,"355":1}}],["completion",{"2":{"320":1,"365":1}}],["complete",{"2":{"313":1,"358":1}}],["completos",{"2":{"670":1}}],["completo",{"2":{"111":1,"345":1,"441":1,"636":1,"723":1}}],["completa",{"2":{"48":1,"217":1,"235":1,"329":1,"390":1,"399":1,"472":1,"473":1,"519":1,"668":1}}],["completamente",{"2":{"30":1,"117":1,"520":1,"628":2,"655":1,"657":1,"675":1}}],["complexidade",{"2":{"668":1}}],["complexo",{"2":{"424":1,"534":1,"559":1,"565":1}}],["complexos",{"2":{"4":1,"52":1,"424":1,"505":1,"673":1,"693":1}}],["complexas",{"2":{"499":1}}],["complexa",{"2":{"106":1,"442":1}}],["complementares",{"2":{"0":1,"45":1}}],["compor",{"2":{"402":1}}],["comporte",{"2":{"679":1}}],["comportem",{"2":{"110":1}}],["comportamento",{"2":{"30":1,"50":1,"68":1,"77":1,"111":1,"123":1,"131":1,"258":1,"337":2,"384":1,"386":1,"520":1,"581":1,"699":1,"736":1}}],["compose",{"2":{"596":1}}],["composes",{"2":{"426":1}}],["composto",{"2":{"115":1}}],["compostos",{"0":{"114":1},"1":{"115":1},"2":{"51":1,"63":1,"114":1,"119":1,"471":1,"719":1}}],["composição",{"2":{"48":1,"542":1}}],["componentforweb",{"2":{"562":1}}],["componentfornative",{"2":{"562":1}}],["componentandroid",{"2":{"562":1}}],["componentios",{"2":{"562":1}}],["componentwidth",{"2":{"445":2}}],["componentwillupdateprops",{"2":{"92":1}}],["componentwillunmount",{"2":{"74":1,"77":1}}],["componentheight",{"2":{"445":2}}],["components",{"2":{"186":1,"241":1,"402":1,"420":1,"440":1,"446":1,"449":1,"470":1,"474":1,"737":1,"739":4}}],["componentdidmount",{"2":{"74":1,"77":1,"92":1,"534":1}}],["component",{"2":{"60":1,"74":1,"77":1,"92":1,"101":1,"114":1,"244":2,"245":2,"387":1,"390":2,"427":1,"442":1,"443":2,"444":2,"562":4,"573":6,"737":1}}],["componentes",{"0":{"114":1,"346":1,"384":2,"386":1,"387":1,"419":1,"420":1,"440":1,"505":1,"506":1,"679":1,"765":1},"1":{"115":1,"347":1,"385":2,"386":2,"387":2,"421":1,"422":1,"423":1,"424":1,"425":1,"426":1,"427":1,"428":1,"429":1,"430":1,"431":1,"432":1,"433":1,"434":1,"441":1,"442":1,"443":1,"444":1,"445":1},"2":{"10":1,"11":1,"13":1,"16":1,"17":1,"18":1,"30":1,"34":1,"46":2,"57":1,"60":1,"63":4,"74":3,"77":1,"78":1,"79":1,"89":2,"90":2,"91":1,"93":1,"96":1,"98":2,"99":2,"100":1,"102":1,"105":1,"110":1,"112":2,"113":2,"114":1,"115":1,"118":1,"119":3,"141":2,"167":2,"202":2,"216":1,"217":3,"219":3,"220":2,"236":1,"242":1,"243":1,"245":4,"248":2,"261":1,"262":1,"265":2,"279":1,"287":2,"299":1,"306":4,"328":1,"343":1,"344":1,"346":4,"347":1,"348":3,"349":5,"351":4,"374":3,"379":1,"384":2,"386":9,"387":6,"400":2,"402":3,"403":1,"417":1,"419":3,"420":3,"427":1,"440":3,"445":3,"446":1,"449":1,"470":1,"471":1,"474":1,"497":1,"504":1,"505":1,"506":1,"507":2,"509":2,"511":2,"534":3,"539":1,"540":1,"545":1,"561":2,"562":1,"565":1,"567":1,"568":1,"668":2,"673":6,"679":7,"680":6,"681":3,"682":1,"687":1,"693":1,"730":2,"731":1,"753":2,"765":2}}],["componente",{"0":{"108":1,"109":1,"275":1,"295":1,"315":1,"344":1,"360":1},"1":{"110":1,"111":1,"296":1,"297":1,"298":1},"2":{"2":1,"11":4,"12":1,"13":6,"19":1,"30":1,"33":1,"34":4,"35":16,"37":1,"46":1,"63":1,"74":1,"77":2,"89":1,"90":2,"92":1,"93":2,"96":1,"98":1,"99":2,"101":2,"102":3,"105":2,"106":1,"111":2,"112":1,"113":1,"114":4,"115":6,"117":1,"120":2,"217":4,"218":1,"219":4,"220":1,"221":1,"222":1,"233":1,"242":1,"243":1,"244":2,"245":1,"246":1,"252":2,"260":1,"261":2,"262":6,"263":1,"265":1,"276":1,"277":2,"279":1,"287":1,"296":1,"297":2,"299":1,"306":1,"316":1,"317":2,"318":5,"320":2,"325":1,"328":1,"339":2,"340":1,"344":8,"347":5,"349":8,"351":1,"361":1,"362":2,"363":5,"365":2,"371":1,"402":2,"404":1,"406":1,"419":1,"420":2,"424":2,"426":4,"427":1,"428":1,"440":2,"441":4,"442":4,"443":2,"444":4,"445":4,"457":1,"481":1,"497":2,"501":1,"505":2,"510":2,"534":1,"539":1,"540":2,"543":1,"544":1,"562":1,"565":1,"668":3,"673":1,"679":3,"680":4,"681":6,"691":1,"730":5,"731":1,"737":2}}],["compondo",{"0":{"48":1},"2":{"48":1}}],["como",{"0":{"217":1,"237":1,"338":1,"531":1,"707":1,"736":1},"2":{"0":1,"3":3,"9":1,"10":1,"11":8,"12":1,"13":1,"14":2,"15":1,"16":1,"17":1,"18":1,"24":1,"30":1,"34":5,"35":3,"41":1,"42":2,"43":2,"46":3,"48":2,"50":1,"51":3,"52":1,"53":1,"55":2,"56":4,"57":2,"58":1,"62":1,"64":1,"65":1,"68":1,"70":1,"73":1,"74":1,"77":2,"78":1,"79":1,"85":1,"86":1,"89":1,"92":1,"93":2,"94":2,"95":1,"96":2,"98":1,"101":1,"102":1,"103":2,"104":1,"105":2,"108":2,"111":2,"115":2,"122":1,"128":3,"129":1,"131":2,"133":1,"134":1,"145":1,"151":2,"170":1,"176":2,"189":1,"191":1,"193":2,"200":1,"205":1,"211":2,"219":1,"221":1,"223":2,"224":1,"226":3,"227":2,"230":1,"231":1,"234":1,"237":1,"239":1,"241":1,"242":2,"243":2,"255":1,"256":1,"257":1,"262":1,"265":1,"279":2,"283":1,"284":1,"287":1,"299":2,"303":1,"304":1,"306":2,"313":1,"320":3,"321":1,"326":1,"332":1,"333":1,"334":2,"336":1,"338":2,"342":2,"343":1,"344":4,"345":5,"347":2,"348":2,"349":10,"351":2,"358":2,"365":3,"366":1,"372":1,"375":2,"381":2,"382":1,"384":2,"385":1,"386":2,"387":2,"389":1,"400":2,"407":1,"419":1,"420":4,"421":1,"424":5,"427":3,"428":2,"437":2,"440":4,"441":1,"442":1,"443":2,"444":1,"445":3,"446":2,"447":4,"448":2,"451":1,"452":3,"454":2,"455":1,"456":2,"459":2,"461":4,"464":3,"465":1,"466":1,"468":3,"470":2,"471":1,"476":1,"477":3,"478":2,"479":1,"483":3,"485":4,"486":1,"488":1,"492":1,"493":2,"497":1,"499":1,"500":1,"508":1,"510":1,"512":1,"514":1,"516":1,"518":1,"520":1,"521":1,"523":1,"525":3,"529":3,"531":1,"532":2,"533":1,"534":1,"537":1,"538":1,"541":1,"547":1,"553":1,"554":2,"555":4,"556":1,"562":2,"563":2,"567":1,"568":1,"569":3,"574":1,"577":2,"579":1,"580":2,"586":3,"587":1,"588":1,"595":2,"596":1,"617":2,"625":1,"629":2,"634":1,"635":2,"636":2,"648":1,"650":2,"654":3,"656":2,"658":1,"660":1,"662":1,"663":1,"668":3,"669":1,"671":2,"672":2,"675":3,"676":1,"678":1,"679":1,"680":7,"681":2,"685":4,"688":1,"691":5,"692":2,"693":2,"695":1,"697":1,"699":2,"700":2,"705":1,"706":1,"709":2,"710":1,"718":1,"719":1,"721":1,"722":2,"724":1,"725":1,"730":1,"733":1,"734":2,"735":1,"738":1,"739":2,"746":2,"747":1,"748":2,"749":1,"750":1,"751":1}}],["com",{"0":{"53":1,"54":1,"110":1,"111":1,"113":1,"117":1,"222":1,"243":1,"285":1,"333":1,"381":1,"383":1,"400":1,"402":1,"428":1,"444":1,"520":1,"523":1,"525":1,"552":1,"566":1,"568":1,"667":1,"728":1,"739":1},"1":{"223":1,"224":1,"225":1,"226":1,"227":1,"228":1,"229":1,"230":1,"231":1,"244":1,"245":1,"246":1,"247":1,"334":1,"401":1,"402":1,"403":1,"404":1,"405":1,"406":1,"429":1,"430":1,"431":1,"432":1,"433":1,"434":1,"526":1,"527":1,"528":1,"529":1,"530":1,"531":1,"553":1,"554":1,"555":1},"2":{"0":2,"2":1,"9":1,"11":3,"12":1,"14":1,"15":1,"24":1,"30":2,"31":1,"33":1,"34":2,"35":6,"38":6,"39":1,"42":1,"43":1,"44":1,"46":2,"50":1,"51":4,"52":2,"53":1,"55":5,"56":2,"57":6,"62":1,"63":4,"64":2,"65":1,"67":3,"68":1,"71":3,"74":1,"76":2,"77":2,"89":1,"90":2,"92":10,"93":1,"94":2,"96":1,"97":1,"98":2,"99":2,"101":6,"102":1,"103":2,"105":1,"106":1,"110":4,"111":4,"112":2,"113":3,"114":2,"117":1,"120":1,"121":1,"122":2,"128":1,"129":1,"130":4,"131":1,"134":1,"140":1,"142":2,"144":1,"145":1,"146":3,"149":1,"151":1,"153":1,"154":1,"156":2,"166":1,"168":2,"169":1,"170":1,"171":3,"174":1,"176":1,"178":1,"179":1,"186":1,"187":1,"188":1,"189":2,"190":3,"191":1,"193":1,"196":1,"197":1,"200":1,"201":1,"203":2,"204":1,"205":1,"206":3,"209":1,"211":1,"213":1,"214":1,"216":1,"217":1,"218":1,"221":2,"222":2,"223":1,"226":2,"228":1,"231":3,"232":1,"233":1,"234":3,"238":1,"239":1,"240":1,"242":4,"243":2,"244":2,"246":1,"249":1,"251":2,"252":1,"254":1,"256":9,"257":1,"259":6,"261":2,"262":3,"263":1,"268":2,"270":6,"272":1,"278":2,"279":1,"282":1,"283":2,"284":1,"285":1,"288":2,"290":6,"292":1,"298":2,"299":1,"302":1,"303":2,"304":1,"309":2,"313":1,"320":1,"321":1,"326":1,"328":1,"332":1,"334":1,"336":1,"337":2,"338":2,"339":2,"343":1,"344":2,"345":1,"347":3,"348":4,"349":4,"354":2,"358":1,"365":1,"366":1,"372":1,"375":1,"376":1,"378":1,"379":1,"381":3,"383":1,"384":1,"386":3,"387":3,"389":1,"390":1,"398":2,"400":2,"401":1,"402":13,"403":2,"404":10,"407":2,"409":2,"413":1,"417":2,"419":1,"420":2,"424":4,"427":2,"428":1,"429":2,"430":4,"431":15,"432":8,"434":1,"435":2,"437":1,"440":2,"441":3,"442":2,"443":5,"444":1,"445":1,"448":2,"452":15,"454":1,"455":2,"456":19,"457":1,"459":1,"461":2,"462":3,"463":3,"464":7,"465":4,"466":6,"467":1,"470":1,"471":3,"472":1,"478":4,"479":1,"480":2,"481":1,"485":3,"486":3,"487":3,"488":2,"491":1,"492":2,"493":2,"495":1,"497":2,"499":1,"501":2,"505":1,"506":1,"507":1,"508":1,"516":6,"519":2,"520":2,"521":1,"522":1,"523":4,"524":1,"525":1,"526":1,"530":1,"534":1,"538":1,"539":1,"542":1,"545":2,"546":2,"549":2,"553":3,"555":5,"557":1,"559":1,"560":1,"561":1,"562":1,"564":1,"565":1,"570":1,"572":1,"574":1,"580":2,"581":2,"586":1,"593":1,"595":2,"596":2,"603":1,"604":1,"608":1,"612":1,"613":1,"616":1,"619":3,"622":1,"625":1,"627":1,"629":4,"631":1,"632":1,"635":5,"636":3,"637":1,"638":3,"639":2,"646":1,"647":1,"648":4,"651":2,"654":1,"656":1,"660":1,"666":1,"667":2,"668":3,"671":2,"672":1,"673":3,"674":1,"675":3,"677":2,"678":2,"679":2,"680":4,"681":2,"682":2,"683":1,"685":2,"686":2,"687":1,"688":2,"689":2,"690":2,"691":6,"692":4,"693":4,"696":1,"700":1,"706":2,"707":1,"710":2,"718":1,"719":1,"720":2,"721":2,"724":1,"726":2,"730":2,"731":3,"733":1,"735":2,"737":1,"738":1,"739":1,"741":4,"745":2,"747":2,"748":1,"751":1,"754":2,"756":1,"757":1,"762":1}}],["rc",{"2":{"721":2}}],["rcthttprequesthandler",{"2":{"524":1}}],["rctinvalidating",{"2":{"495":1}}],["rctimageview",{"2":{"422":2,"426":1}}],["rctimage",{"2":{"313":2,"358":1,"706":2}}],["rctutils",{"2":{"488":1}}],["rctuimanager",{"2":{"106":1,"113":1,"441":1,"444":2}}],["rctmakeerror",{"2":{"488":1}}],["rctmycustomview",{"2":{"427":2}}],["rctpromiserejectblock",{"2":{"486":1,"489":2}}],["rctpromiseresolveblock",{"2":{"486":1,"489":2}}],["rctcalendarmodule",{"2":{"477":9,"478":1}}],["rctcomponent",{"2":{"443":1}}],["rctconvert+mapkit",{"2":{"442":1,"443":1}}],["rctconvert+corelocation",{"2":{"442":2}}],["rctconvert",{"2":{"442":6,"443":1,"479":1,"486":3}}],["rctdeviceeventemitter",{"2":{"466":3}}],["rctdatepickermanager",{"2":{"445":1}}],["rctdatepickerios",{"2":{"445":1}}],["rctdatepickeriosconsts",{"2":{"445":4}}],["rctdatepicker",{"2":{"445":1}}],["rctloginfo",{"2":{"479":1,"483":1,"488":1}}],["rctlogerror",{"2":{"444":1}}],["rctlog",{"2":{"444":1,"479":2,"483":1}}],["rctlinking",{"2":{"313":1}}],["rctsetcustomnsurlsessionconfigurationprovider",{"2":{"524":5}}],["rctsetimagecachelimits",{"2":{"342":1}}],["rctsettings",{"2":{"313":1}}],["rctbubblingeventblock",{"2":{"443":3}}],["rctbridgedelegate>",{"2":{"492":1}}],["rctbridgedelegate",{"2":{"492":1}}],["rctbridgemodule>",{"2":{"477":1,"490":1}}],["rctbridgemodule",{"2":{"477":3,"490":1,"493":4}}],["rctbridge",{"2":{"320":1,"365":1,"492":3,"524":1}}],["rctblob",{"2":{"313":1}}],["rctwebsocket",{"2":{"313":1,"706":1}}],["rctwebsocketexecutor",{"2":{"134":1,"619":1}}],["rctvibration",{"2":{"313":1}}],["rctviewmanagers",{"2":{"441":1}}],["rctviewmanager",{"2":{"105":1,"441":4,"443":2,"444":1}}],["rctnetwork",{"2":{"313":1,"706":1}}],["rctasynclocalstorage",{"2":{"491":1}}],["rctalertmanager",{"2":{"488":1}}],["rctanimation",{"2":{"313":1}}],["rctactionsheet",{"2":{"313":1}}],["rctresponseerrorblock",{"2":{"486":2,"488":1}}],["rctresponsesenderblock",{"2":{"486":2,"488":7,"491":1}}],["rctrequired",{"2":{"313":2}}],["rctrootviewdelegate",{"2":{"111":1}}],["rctrootviewsizeflexibilityheight",{"2":{"111":4}}],["rctrootviewsizeflexibilitywidthandheight",{"2":{"111":1}}],["rctrootviewsizeflexibilitywidth",{"2":{"111":2}}],["rctrootviewsizeflexibilitynone",{"2":{"111":2}}],["rctrootviewsizeflexibility",{"2":{"111":1}}],["rctrootview",{"0":{"318":1,"363":1},"1":{"319":1,"320":1,"321":1,"364":1,"365":1,"366":1,"367":1},"2":{"101":6,"110":2,"111":7,"318":1,"320":5,"363":1,"365":3,"492":3}}],["rcttypesafety",{"2":{"313":1}}],["rcttext",{"2":{"313":2,"358":1,"706":2}}],["rcttvnavigationeventemitter",{"2":{"77":1}}],["rcttvremotehandler",{"2":{"77":1}}],["rcttvview",{"2":{"77":2}}],["rct",{"2":{"102":1,"441":4,"442":2,"443":4,"444":1,"477":2,"478":10,"479":8,"480":2,"493":4}}],["rcteventemitter",{"2":{"77":1,"427":2,"490":6,"557":1}}],["rsa",{"2":{"650":1,"651":1}}],["rígidas",{"2":{"507":1}}],["rígido",{"2":{"51":1}}],["rk",{"2":{"478":1}}],["rkdatepickerios",{"2":{"445":2}}],["rtl",{"2":{"225":2}}],["rtrrootview",{"2":{"110":1,"306":1,"320":5,"351":1,"365":4}}],["rules",{"2":{"608":2,"657":1,"747":1}}],["rum",{"2":{"345":3}}],["ruim",{"0":{"539":1},"2":{"328":1,"331":1,"337":1,"670":1}}],["ruby",{"2":{"187":2}}],["runafterinteractions",{"2":{"700":3}}],["runtime",{"0":{"763":1},"2":{"299":1,"660":2}}],["runningappprocesses",{"2":{"259":1}}],["runningappprocessinfo",{"2":{"259":4}}],["runningappprocessinfo>",{"2":{"259":1}}],["running",{"2":{"65":2,"73":1,"76":2,"491":1,"563":1}}],["run",{"2":{"65":2,"67":1,"152":1,"177":1,"194":1,"212":1,"259":2,"325":1,"371":1,"377":1,"378":1,"438":1,"457":1,"481":1,"547":1,"549":1,"567":1,"600":1,"609":1,"617":2,"624":1,"625":1,"626":1,"627":1,"643":1,"655":1,"712":1,"716":1,"743":1,"744":1,"747":1,"748":1}}],["r",{"2":{"130":1,"153":1,"178":1,"196":1,"213":1,"404":6,"617":1,"705":2}}],["rngp",{"2":{"579":1}}],["rnpm",{"2":{"516":2}}],["rncmynativeviewmanager",{"2":{"444":2}}],["rncmynativeview",{"2":{"444":1}}],["rnt",{"2":{"441":1}}],["rntmapview",{"2":{"443":9}}],["rntmap",{"2":{"441":4,"442":3,"443":1}}],["rntmapmanager",{"2":{"441":4,"442":3,"443":4}}],["rntester",{"2":{"35":1,"56":1,"59":1}}],["rnhighscore",{"2":{"320":1,"365":1}}],["rnhighscores",{"2":{"317":4,"320":2,"362":4,"365":2}}],["rn",{"2":{"92":1,"94":1,"95":2,"103":1,"104":2,"110":1,"111":2,"320":1,"365":1,"589":1,"720":1,"746":1}}],["rrggbbaa",{"2":{"82":1}}],["rrggbb",{"2":{"82":1}}],["rgb",{"0":{"82":1},"2":{"82":5,"85":1}}],["rgba",{"2":{"53":1,"82":3,"87":1,"730":1}}],["rigorosamente",{"2":{"746":1}}],["right",{"2":{"74":1,"77":1,"234":1}}],["rimraf",{"2":{"381":1}}],["risco",{"2":{"67":1,"499":1,"634":1}}],["rápidas",{"2":{"166":1}}],["rápida",{"0":{"216":1,"221":1},"1":{"217":1,"218":1,"219":1,"220":1,"221":1},"2":{"46":1,"67":1,"130":2,"216":2,"218":3,"220":1,"221":3,"387":1,"533":1,"540":1,"553":1,"560":1,"691":1,"755":1}}],["rápidos",{"2":{"375":1,"504":1,"676":1,"682":1}}],["rápido",{"0":{"157":1,"159":1,"693":1},"1":{"158":1,"160":1,"161":1,"162":1},"2":{"11":1,"34":1,"70":1,"74":1,"120":1,"266":1,"283":1,"288":1,"303":1,"307":1,"352":1,"407":1,"442":1,"456":1,"508":2,"540":1,"665":1,"676":1,"699":1}}],["rate",{"2":{"608":4}}],["random",{"2":{"571":1}}],["ramificação",{"2":{"634":1}}],["ram",{"0":{"571":1,"574":1},"1":{"572":1,"573":1,"574":1,"575":1,"576":1,"577":1,"578":1},"2":{"571":2,"572":1,"573":1,"574":10,"575":1,"577":1,"578":1,"588":2,"762":1}}],["rastro",{"0":{"553":1}}],["rastreada",{"2":{"531":1}}],["rastreado",{"2":{"531":1}}],["rastreamento",{"0":{"52":1,"554":1,"685":1},"1":{"686":1},"2":{"51":1,"130":1,"527":2,"553":4,"554":3,"557":1,"664":1,"685":1,"755":1}}],["rastrear",{"2":{"51":2,"111":1,"349":1,"510":1}}],["rastreando",{"0":{"51":1}}],["razoáveis",{"2":{"581":1}}],["razoável",{"2":{"520":1}}],["razão",{"2":{"115":1,"338":1,"533":1,"535":1,"635":1,"700":1}}],["rapidez",{"2":{"497":1}}],["rapidamente",{"2":{"43":1,"116":1,"451":1,"476":1,"482":1,"540":1,"601":1,"610":1,"618":1,"644":1,"681":1}}],["rac",{"2":{"452":1,"456":1}}],["raio",{"2":{"340":1}}],["raiz",{"2":{"110":6,"111":10,"121":1,"200":1,"218":1,"251":2,"268":1,"276":1,"281":1,"288":1,"296":1,"301":1,"309":1,"316":1,"324":1,"354":1,"361":1,"370":1,"371":1,"407":1,"534":1,"548":1,"549":1,"576":1,"577":1,"582":1,"600":2,"609":2,"638":1,"643":2,"655":1,"666":1,"704":1,"711":1,"734":1,"739":1,"742":1}}],["raízes",{"2":{"134":1}}],["raramente",{"2":{"45":1,"471":1}}],["radiogroup",{"2":{"11":1,"34":1}}],["radio",{"2":{"11":1,"34":1}}],["roda",{"2":{"748":1}}],["rodar",{"2":{"152":1,"194":1,"212":1}}],["rodando",{"2":{"76":1,"280":1,"300":1,"322":1,"368":1,"529":1,"562":1}}],["root",{"0":{"582":1},"2":{"131":1,"313":1,"431":10,"608":8,"699":1,"739":1}}],["rootviewdidchangeintrinsicsize",{"2":{"111":3}}],["rootview",{"2":{"101":2,"110":3,"111":8,"320":2,"365":2,"492":1,"548":1}}],["royalblue",{"2":{"88":1}}],["rosybrown",{"2":{"88":1}}],["rowhaschanged",{"2":{"540":1}}],["rowgap=",{"2":{"232":1}}],["rowgapandcolumngap",{"2":{"232":2}}],["rowgap",{"2":{"232":8}}],["row",{"2":{"53":1,"223":1,"224":7,"225":3,"226":3,"227":3,"228":3,"229":3,"230":3,"231":6,"232":1,"233":4,"234":3,"244":1}}],["rota",{"2":{"534":1}}],["rotatex",{"2":{"58":1}}],["rotatey",{"2":{"58":3}}],["rotação",{"2":{"50":1,"256":1}}],["rotula",{"2":{"25":1,"26":1}}],["roláveis",{"2":{"731":1}}],["rollup",{"2":{"566":1}}],["rolo",{"0":{"336":1},"2":{"336":1}}],["rolando",{"2":{"248":1}}],["rolar",{"0":{"246":1,"542":1},"2":{"243":1,"535":1,"731":1}}],["rolagem",{"0":{"539":1},"2":{"11":1,"34":1,"52":4,"56":1,"78":1,"387":2,"500":1,"503":1,"535":2,"558":1,"730":1,"731":1}}],["role=client",{"2":{"619":1}}],["role",{"0":{"34":1},"2":{"34":1,"246":1,"268":1,"288":1,"309":1,"354":1,"555":1}}],["reescrever",{"2":{"680":1}}],["renomeie",{"2":{"734":1}}],["renomear",{"2":{"680":1}}],["rendersectionheader=",{"2":{"730":1}}],["renders",{"2":{"690":2}}],["renderthread",{"2":{"555":1}}],["rendertohardwaretextureandroid",{"2":{"542":1,"559":1}}],["renderer",{"2":{"113":1,"679":1,"734":2}}],["renderitem=",{"2":{"511":1,"520":1,"730":2}}],["renderitem",{"0":{"511":1},"2":{"511":4,"730":2}}],["renderimage",{"2":{"92":2,"101":2}}],["renderizá",{"2":{"346":1}}],["renderize",{"2":{"279":1,"299":1,"347":1}}],["renderizem",{"2":{"57":1}}],["renderizando",{"0":{"690":1},"1":{"691":1},"2":{"541":1,"556":1,"691":2}}],["renderizações",{"2":{"501":1,"691":2,"692":2}}],["renderização",{"0":{"539":1,"691":1},"2":{"60":1,"77":2,"112":2,"113":1,"117":1,"120":1,"217":1,"325":1,"371":1,"499":1,"502":2,"511":3,"534":1,"539":2,"540":2,"545":1,"552":1,"555":1,"556":3,"559":1,"673":1,"679":2,"681":3,"689":2,"690":3,"691":2,"692":3,"693":1}}],["renderiza",{"2":{"115":1,"217":1,"347":1,"692":1,"730":2}}],["renderizadores",{"2":{"691":1}}],["renderizador",{"2":{"514":1,"679":2,"691":5}}],["renderizados",{"2":{"349":1,"497":1,"500":2,"501":1,"502":1,"505":1,"506":1,"539":1,"691":1,"692":1,"731":1}}],["renderizado",{"2":{"92":1,"101":1,"117":1,"244":1,"344":1,"349":2,"540":1,"680":1,"730":1}}],["renderizada",{"0":{"681":1},"2":{"58":1,"497":1,"540":1,"556":1,"680":1,"681":1,"690":1}}],["renderizadas",{"2":{"58":1}}],["renderizará",{"2":{"217":1,"244":1,"337":2,"403":1,"404":1,"501":1}}],["renderizar",{"0":{"540":1},"2":{"46":1,"63":1,"111":1,"112":1,"113":1,"218":1,"344":1,"347":1,"348":1,"402":1,"429":1,"430":1,"441":1,"497":1,"501":1,"534":1,"556":1,"673":1,"679":2,"680":1,"692":2,"693":1,"730":2}}],["render",{"0":{"117":1},"2":{"60":1,"92":1,"101":1,"244":1,"245":1,"390":1,"427":1,"430":1,"441":2,"442":2,"443":2,"444":1,"445":1,"555":2,"573":2,"680":1,"692":1}}],["revelar",{"2":{"636":1}}],["reversa",{"2":{"636":1}}],["reverse",{"0":{"602":1,"611":1,"645":1},"2":{"133":1,"224":4,"570":1,"599":1,"602":1,"611":1,"645":1}}],["reverter",{"2":{"67":1,"708":1}}],["revisor",{"2":{"681":1}}],["revisada",{"2":{"681":1}}],["revisão",{"2":{"520":1,"681":1}}],["review",{"2":{"549":1}}],["re",{"2":{"515":1,"540":1}}],["reordenação",{"2":{"510":1}}],["reorganizar",{"2":{"111":1}}],["remap",{"2":{"493":2}}],["remontar",{"2":{"220":1}}],["remontará",{"2":{"218":1}}],["remontagem",{"2":{"220":1}}],["removida",{"2":{"424":2,"659":1}}],["removidos",{"2":{"478":1,"720":1}}],["removido",{"2":{"227":1,"478":2,"490":1}}],["removê",{"2":{"272":1,"292":1,"538":1}}],["remova",{"2":{"145":1,"170":1,"189":1,"205":1,"466":2}}],["removelisteners",{"2":{"466":2}}],["removendo",{"2":{"424":1,"657":1}}],["remove",{"2":{"124":1,"466":2,"490":1,"538":3,"693":2}}],["removeclippedsubviews",{"0":{"499":1},"2":{"78":1}}],["removerá",{"2":{"479":1,"538":1,"708":1}}],["remover",{"2":{"65":1,"67":1,"94":1,"103":1,"262":1,"263":1,"381":1,"404":1,"673":1,"728":1}}],["remota",{"2":{"337":1,"517":1,"745":1}}],["remotamente",{"2":{"135":1}}],["remotas",{"2":{"77":1}}],["remotely",{"2":{"134":1}}],["remotos",{"2":{"74":3,"77":3}}],["remoto",{"2":{"74":4,"77":7}}],["rejeitada",{"2":{"465":3}}],["rejeitar",{"2":{"465":2,"467":1}}],["rejecter",{"2":{"489":1}}],["reject",{"2":{"465":4,"467":8,"489":2}}],["reutiliza",{"2":{"505":1}}],["reutilizar",{"2":{"446":1,"561":1}}],["reutilizável",{"2":{"384":1}}],["reutilizáveis",{"2":{"346":1}}],["regenerator",{"2":{"660":1}}],["regex",{"2":{"390":2}}],["regulares",{"2":{"697":1}}],["regular",{"2":{"463":1}}],["regras",{"2":{"507":1,"608":1,"747":1}}],["regra",{"2":{"349":1,"680":1,"681":1,"746":1}}],["regiondidchangeanimated",{"2":{"443":2}}],["region=",{"2":{"442":1,"443":1}}],["region",{"2":{"442":7,"443":12}}],["registercomponent",{"2":{"277":1,"279":2,"297":1,"299":2,"317":1,"362":1,"404":1}}],["registerheadlesstask",{"2":{"255":1}}],["registros",{"2":{"483":1}}],["registrou",{"2":{"456":1}}],["registro",{"2":{"255":1,"379":2,"635":1,"636":1}}],["registrando",{"2":{"635":1}}],["registradas",{"2":{"652":1}}],["registrada",{"2":{"459":1}}],["registrados",{"2":{"492":1}}],["registrado",{"2":{"456":1}}],["registrará",{"2":{"456":1,"493":1,"615":1}}],["registrar",{"2":{"259":1,"320":1,"365":1,"425":1,"456":5,"466":1,"467":1,"468":1,"516":1,"573":1,"615":1}}],["registra",{"2":{"255":1,"478":1}}],["registrem",{"2":{"700":1}}],["registre",{"0":{"433":1,"456":1},"1":{"457":1},"2":{"68":1,"427":1,"616":1}}],["região",{"2":{"27":1,"442":5,"443":2}}],["req",{"2":{"278":3,"298":3}}],["requisições",{"0":{"519":1}}],["requisito",{"2":{"448":1}}],["requisitos",{"0":{"238":1,"266":1,"288":1,"307":1,"352":1,"575":1},"1":{"267":1,"268":1,"308":1,"309":1,"310":1,"353":1,"354":1,"355":1},"2":{"331":1,"421":1,"424":1,"571":1,"576":2,"578":1}}],["requirenotnull",{"2":{"430":1,"431":3}}],["requirenativecomponent",{"2":{"426":3,"427":1,"434":2,"441":3,"442":2}}],["require",{"0":{"571":1,"573":1},"1":{"572":1,"573":1,"574":2,"575":1,"576":1,"577":1,"578":1},"2":{"73":1,"74":1,"76":1,"77":1,"255":1,"296":1,"328":7,"329":1,"337":2,"338":1,"390":1,"392":1,"398":1,"399":1,"407":1,"562":4,"573":1,"575":3,"576":2,"577":5,"762":1}}],["requestnotificationpermission",{"2":{"660":1}}],["request",{"2":{"392":1,"467":6,"519":1,"521":7}}],["requestcode",{"2":{"278":3,"298":3,"467":6}}],["requestanimationframe",{"0":{"62":1},"2":{"62":1,"544":2,"699":2,"700":1}}],["requeira",{"2":{"191":1}}],["requerimento",{"2":{"577":1}}],["requerem",{"2":{"142":1,"168":1,"203":1,"726":1}}],["requer",{"2":{"115":2,"142":1,"156":1,"168":1,"200":1,"203":1,"256":1,"276":1,"316":1,"328":2,"341":1,"361":1,"400":1,"487":1,"493":1,"520":1,"547":1,"574":1,"657":1,"689":1,"709":1,"717":1,"718":1,"730":1,"746":1}}],["reimplementá",{"2":{"446":1}}],["reintroduzido",{"2":{"671":1}}],["reiniciar",{"2":{"328":1}}],["reinstalar",{"2":{"189":1}}],["reivindicar",{"2":{"251":1}}],["rebeccapurple",{"2":{"88":1}}],["rebound",{"2":{"63":1}}],["refinar",{"2":{"696":1}}],["refatorador",{"2":{"694":1}}],["refatoração",{"2":{"680":1,"695":1}}],["refatora",{"2":{"671":1}}],["refatorar",{"2":{"465":1,"489":1,"576":1,"694":1}}],["refletir",{"2":{"654":1}}],["refletida",{"2":{"221":1}}],["refletidas",{"2":{"93":1,"424":1}}],["refresh",{"2":{"216":2,"217":4,"219":1,"220":2,"221":2}}],["ref=",{"2":{"115":2,"116":2,"122":4,"434":1,"444":3,"445":1,"690":2}}],["referimo",{"2":{"533":1}}],["referir",{"2":{"531":1}}],["referenciadas",{"2":{"576":1,"577":1}}],["referenciados",{"2":{"348":1}}],["referenciando",{"2":{"424":1}}],["referenciar",{"2":{"101":1,"424":1}}],["referencie",{"2":{"328":1}}],["refere",{"2":{"225":2,"442":1,"477":1,"687":1}}],["referem",{"2":{"225":1}}],["referências",{"2":{"415":1}}],["referência",{"0":{"79":1,"367":1},"1":{"80":1,"81":1,"82":1,"83":1,"84":1,"85":1,"86":1,"87":1,"88":1},"2":{"4":1,"47":1,"48":1,"80":1,"96":1,"105":1,"106":1,"115":2,"122":2,"227":1,"242":1,"367":2,"422":1,"444":1,"491":1,"540":1,"550":1,"668":1,"675":1,"681":2,"693":2,"739":1,"756":1}}],["ref",{"2":{"74":1,"115":4,"434":3,"444":1}}],["redobrada",{"2":{"681":1}}],["redor",{"2":{"226":2,"229":1,"348":1}}],["redux",{"2":{"538":1,"569":1,"630":1,"634":3,"673":1,"682":1}}],["reduz",{"0":{"543":1},"2":{"499":2,"691":1}}],["reduzidos",{"2":{"685":1}}],["reduzindo",{"2":{"245":1,"566":1}}],["reduzirá",{"2":{"231":1}}],["reduzir",{"0":{"657":1},"2":{"65":1,"230":1,"231":1,"540":1,"629":1,"639":1,"657":2}}],["redbox",{"2":{"442":2}}],["redistributable",{"2":{"746":1}}],["redireciona",{"2":{"636":1}}],["redirecionamentos",{"0":{"636":1}}],["redirecionamento",{"2":{"523":2,"636":1,"686":1}}],["redirecionado",{"2":{"523":1}}],["redirect",{"2":{"523":1}}],["redimensionar",{"2":{"336":1}}],["redigido",{"2":{"113":1}}],["redes",{"2":{"619":1,"730":1}}],["redesenhando",{"2":{"687":1}}],["redesenhar",{"2":{"542":1}}],["redesenho",{"2":{"509":1}}],["rede",{"0":{"331":1,"332":1,"517":1,"521":1,"620":1,"637":1},"1":{"518":1,"519":1,"520":1,"521":1,"522":1,"523":1,"524":1,"638":1},"2":{"158":1,"255":1,"259":5,"273":1,"293":1,"333":1,"334":1,"518":2,"520":1,"524":2,"541":1,"601":1,"603":1,"610":1,"612":1,"618":1,"619":2,"620":1,"628":1,"629":2,"644":1,"646":1,"677":1,"678":1,"758":1}}],["redefinição",{"2":{"220":1}}],["redefinido",{"2":{"219":2}}],["redefinindo",{"2":{"110":1}}],["redefinir",{"2":{"74":1,"442":1,"569":1}}],["redefini",{"2":{"67":1}}],["red",{"2":{"60":1,"88":1,"223":1,"390":1,"562":1,"668":7,"675":2,"737":1}}],["retém",{"2":{"491":1}}],["retido",{"2":{"491":1}}],["retirar",{"2":{"608":1}}],["retirando",{"2":{"461":1,"485":1}}],["retirado",{"2":{"251":1}}],["retangular",{"2":{"385":1}}],["retrypolicy",{"2":{"257":4}}],["retângulo",{"2":{"244":1}}],["retorne",{"2":{"252":1,"431":1,"544":1}}],["retornos",{"2":{"90":1,"94":3,"99":1,"103":3,"279":1,"299":1,"459":1,"464":3,"465":2,"469":1,"479":1,"483":1,"488":5,"489":1,"680":1,"700":1}}],["retorno",{"2":{"55":2,"77":3,"90":1,"99":1,"120":2,"121":2,"424":1,"427":3,"443":4,"464":15,"465":4,"479":1,"480":1,"488":10,"540":1,"689":1,"699":1}}],["retornamos",{"2":{"443":1}}],["retornando",{"2":{"442":1}}],["retornada",{"2":{"456":1}}],["retornadas",{"2":{"120":1,"122":1}}],["retornados",{"2":{"456":2}}],["retornado",{"2":{"219":1,"422":1,"427":1,"456":1,"511":1,"627":1}}],["retornará",{"2":{"463":1,"465":1,"467":1,"488":1,"489":1,"520":1,"699":1,"708":1}}],["retornarem",{"2":{"252":1}}],["retornar",{"2":{"92":1,"251":2,"258":1,"398":1,"424":1,"428":1,"441":1,"464":1,"467":1,"480":1,"562":1,"636":1,"677":1}}],["retorna",{"2":{"48":1,"120":1,"121":1,"344":1,"444":1,"453":2,"456":4,"465":1,"487":1,"489":1,"491":1,"562":1,"730":1}}],["returns",{"2":{"675":1}}],["returned",{"2":{"489":1}}],["returned`",{"2":{"464":2,"488":2}}],["return",{"2":{"46":2,"53":3,"54":1,"60":1,"92":6,"101":2,"113":1,"116":2,"122":2,"223":1,"224":1,"225":1,"226":1,"227":1,"228":1,"229":1,"230":1,"231":1,"232":1,"233":1,"234":1,"239":1,"242":1,"244":1,"245":1,"256":3,"257":2,"259":15,"261":1,"262":1,"263":1,"277":1,"279":2,"297":1,"299":2,"317":1,"344":4,"345":5,"346":1,"347":2,"348":5,"349":5,"362":1,"367":1,"387":1,"390":2,"399":1,"402":4,"404":1,"422":1,"423":1,"425":1,"427":4,"430":2,"431":4,"432":1,"433":1,"434":1,"441":3,"442":4,"443":5,"444":2,"445":2,"453":1,"456":3,"457":1,"463":1,"466":1,"467":3,"480":1,"481":1,"487":1,"491":2,"493":1,"507":1,"511":1,"520":4,"521":1,"524":1,"548":1,"573":2,"577":1,"668":1,"680":1,"690":2,"692":2,"730":2,"737":1}}],["reload",{"2":{"153":1,"178":1,"213":1,"334":1,"603":1,"612":1,"618":1,"646":1}}],["releaseyear",{"2":{"520":2}}],["release",{"0":{"654":1},"2":{"54":1,"547":4,"549":3,"586":1,"595":3,"600":1,"609":2,"643":2,"653":3,"654":2,"655":3,"662":3,"663":2,"685":2,"722":1,"743":2,"744":2}}],["relevantes",{"2":{"531":1,"568":1,"706":1}}],["relevante",{"2":{"33":1,"156":1,"565":1}}],["relação",{"2":{"234":1,"251":4,"552":1,"726":1}}],["relativo",{"0":{"234":1}}],["relativos",{"2":{"68":1}}],["relativelayout",{"2":{"347":1}}],["relative",{"2":{"122":2,"234":6}}],["relativetonativenode",{"2":{"122":1}}],["relativetonativecomponentref",{"0":{"122":1},"2":{"122":1}}],["relativamente",{"2":{"234":1,"493":1}}],["relativas",{"2":{"122":1}}],["relativa",{"2":{"74":1,"122":1,"461":1,"485":1}}],["relatórios",{"2":{"42":1}}],["relacionadas",{"2":{"67":1,"105":1,"142":1,"168":1,"203":1}}],["relacionados",{"2":{"348":1,"455":1,"480":1,"491":1,"676":1,"729":1}}],["relacionado",{"2":{"4":1,"26":1,"113":1}}],["relacionamento",{"2":{"50":1,"531":1}}],["relacionamentos",{"2":{"46":1}}],["reagirá",{"2":{"574":1}}],["reagir",{"2":{"534":1}}],["reage",{"2":{"259":1}}],["reason",{"2":{"522":1}}],["read",{"2":{"660":2}}],["readystate",{"2":{"521":1}}],["readablemap`",{"2":{"424":1}}],["readablemap",{"2":{"424":1,"462":2}}],["readablearray",{"2":{"424":4,"431":4,"462":2}}],["readme",{"2":{"377":1,"382":1,"383":1,"569":1}}],["reatribuível",{"2":{"349":1}}],["reativará",{"2":{"217":1}}],["reativá",{"2":{"134":1,"323":1,"369":1}}],["reação",{"0":{"472":1},"2":{"245":1,"444":1,"445":1}}],["reais",{"2":{"42":1,"338":1,"488":1,"555":1,"674":1,"677":1,"678":1,"699":1}}],["realce",{"2":{"544":1}}],["realista",{"2":{"533":2}}],["realizado",{"2":{"551":1,"560":1}}],["realizadas",{"2":{"92":1,"101":1}}],["realizada",{"2":{"92":1,"101":1}}],["realizar",{"2":{"31":1,"33":2,"35":2,"249":1,"533":1,"549":1,"580":1,"654":1}}],["realmente",{"2":{"63":1,"74":1,"77":1,"328":1,"442":1,"509":1,"557":1,"571":1,"572":1,"573":1,"576":1,"677":1,"681":1}}],["real",{"2":{"42":1,"43":2,"74":1,"77":1,"120":1,"142":1,"168":1,"195":1,"203":1,"275":1,"295":1,"315":1,"360":1,"445":1,"605":1,"682":1,"685":1,"693":1,"745":1}}],["reactotron",{"2":{"569":1}}],["reactshadownode",{"2":{"456":2}}],["reactmethod",{"2":{"452":2,"454":5,"455":2,"464":8,"465":2,"466":4,"467":2}}],["reactcontextbasejavamodule",{"2":{"452":10,"467":2}}],["reactcontext",{"2":{"422":2,"425":4,"427":7,"431":11,"432":4,"452":4,"456":6,"466":9,"467":6}}],["reactcommon",{"2":{"313":9}}],["reactimageview>",{"2":{"422":2}}],["reactimageview",{"2":{"422":2,"423":3,"424":6}}],["reactimagemanager",{"2":{"422":4,"425":2,"427":2}}],["reactinstancemanager",{"2":{"278":1,"279":7,"298":2,"299":16}}],["reactjs",{"2":{"331":2,"332":1,"334":1,"424":1,"566":1}}],["reactfragment",{"2":{"279":1,"299":1,"404":5}}],["reactpackage",{"2":{"402":2,"404":2,"432":4,"456":10}}],["reactpackage>",{"2":{"279":1,"299":1,"402":3,"433":2,"456":3}}],["reactpropgroup",{"0":{"424":1},"2":{"421":1,"424":3,"431":4,"434":1}}],["reactprop",{"0":{"424":1},"2":{"93":1,"421":1,"424":12,"431":1,"434":1}}],["reactnativepath",{"2":{"748":1,"751":1}}],["reactnativedir",{"0":{"583":1},"2":{"583":1}}],["reactnativejs",{"2":{"436":1}}],["reactnativeviewid",{"2":{"431":12}}],["reactnativefragment",{"2":{"403":1,"404":7}}],["reactnativehost",{"2":{"402":7,"404":2,"456":2}}],["reactnative",{"2":{"134":3,"348":1,"387":1,"436":1,"442":1,"444":1,"453":1,"465":1,"478":2,"520":3,"731":1}}],["reactnativerenderer",{"2":{"113":1}}],["reactnativebasecomponent",{"2":{"113":1}}],["reactnativearchitectures=armeabi",{"2":{"65":1}}],["reactnativearchitectures",{"2":{"65":1}}],["reacttag",{"2":{"96":1,"105":1,"444":5}}],["reactrootview",{"0":{"279":1,"299":1},"2":{"92":2,"265":1,"279":4,"287":1,"299":9}}],["reactapplicationcontext",{"2":{"422":3,"425":2,"431":5,"432":4,"452":5,"456":7,"467":2}}],["reactapplication",{"2":{"402":8,"404":2}}],["reactactivity",{"2":{"92":2,"279":1,"299":1}}],["reactactivitydelegate",{"2":{"92":5}}],["reactandroidtvrootviewhelper",{"2":{"74":1}}],["react",{"0":{"89":1,"92":1,"93":1,"96":1,"97":1,"98":1,"101":1,"102":1,"105":1,"106":1,"108":1,"109":1,"110":1,"111":1,"144":1,"150":1,"158":1,"159":1,"169":1,"175":1,"188":1,"192":1,"204":1,"210":1,"269":1,"275":1,"277":1,"289":1,"295":1,"297":1,"311":1,"315":1,"317":1,"343":1,"356":1,"360":1,"362":1,"381":1,"383":1,"401":1,"402":1,"403":1,"404":1,"473":1,"515":1,"567":1,"568":1,"579":1,"658":1,"706":1,"707":1,"711":1,"714":1,"719":1,"720":1,"728":1,"736":1,"737":1,"746":1,"752":1},"1":{"90":1,"91":1,"92":1,"93":1,"94":1,"95":1,"96":1,"97":1,"99":1,"100":1,"101":1,"102":1,"103":1,"104":1,"105":1,"106":1,"107":1,"108":1,"109":1,"110":2,"111":2,"151":1,"152":1,"160":1,"161":1,"162":1,"176":1,"177":1,"178":1,"193":1,"194":1,"211":1,"212":1,"270":1,"290":1,"296":1,"297":1,"298":1,"344":1,"345":1,"346":1,"347":1,"348":1,"349":1,"568":1,"569":1,"570":1,"580":1,"581":1,"582":1,"583":1,"584":1,"585":1,"586":1,"587":1,"588":1,"589":1,"590":1,"591":1,"592":1,"593":1,"594":1,"595":1,"596":1,"707":1,"708":1,"712":1,"713":1,"715":1,"716":1,"721":1,"722":1,"747":1,"748":1,"753":1,"754":1,"755":1,"756":1,"757":1,"758":1,"759":1,"760":1,"761":1,"762":1,"763":1,"764":1,"765":1,"766":1,"767":1,"768":1,"769":1},"2":{"0":2,"2":1,"37":1,"40":1,"43":3,"44":2,"45":1,"46":6,"53":3,"54":3,"56":1,"60":4,"64":3,"65":2,"67":2,"68":1,"71":1,"73":1,"74":1,"75":1,"76":4,"77":1,"79":1,"80":1,"82":1,"83":1,"84":1,"85":1,"86":2,"89":2,"90":5,"91":2,"92":6,"93":2,"95":3,"96":2,"97":1,"98":2,"99":5,"100":2,"101":9,"102":2,"104":3,"105":3,"106":4,"107":1,"108":1,"110":5,"111":10,"112":3,"113":2,"114":6,"115":8,"116":8,"119":1,"121":1,"122":6,"126":1,"128":1,"131":2,"134":2,"137":2,"139":1,"142":2,"144":2,"145":9,"146":3,"147":1,"151":2,"152":1,"154":1,"155":3,"156":5,"157":1,"159":1,"164":2,"168":2,"169":2,"170":9,"171":3,"172":1,"176":2,"179":1,"180":3,"182":2,"188":2,"189":9,"190":5,"191":1,"193":2,"194":1,"197":1,"198":3,"199":2,"200":1,"203":2,"204":2,"205":9,"206":3,"207":1,"211":2,"212":1,"214":1,"215":3,"216":3,"217":6,"218":2,"219":2,"220":1,"221":1,"222":1,"223":3,"224":4,"225":5,"226":4,"227":4,"228":5,"229":4,"230":4,"231":6,"232":4,"233":5,"234":4,"236":4,"237":1,"238":1,"239":3,"240":1,"241":1,"242":4,"243":1,"244":3,"245":4,"247":1,"255":3,"256":6,"259":2,"261":4,"262":3,"263":3,"265":6,"266":2,"267":1,"268":10,"270":12,"271":2,"272":1,"274":1,"275":1,"276":3,"277":3,"278":1,"279":5,"280":1,"281":1,"282":1,"283":4,"284":1,"285":2,"287":6,"288":13,"290":12,"291":2,"292":1,"294":1,"295":1,"296":3,"297":3,"298":1,"299":5,"300":1,"301":1,"302":1,"303":4,"304":1,"306":7,"307":2,"308":1,"309":10,"310":1,"311":1,"313":58,"314":2,"315":1,"316":3,"317":4,"318":2,"319":1,"320":9,"322":1,"324":1,"325":2,"326":1,"328":1,"330":1,"336":1,"337":1,"338":1,"341":1,"342":1,"343":6,"344":11,"345":15,"346":7,"347":4,"348":11,"349":14,"351":7,"352":2,"353":1,"354":10,"355":1,"356":1,"358":11,"359":2,"360":1,"361":3,"362":4,"363":2,"364":1,"365":10,"368":1,"370":1,"371":3,"372":1,"374":3,"375":2,"376":3,"377":2,"378":1,"379":12,"381":4,"382":1,"383":2,"384":6,"386":8,"387":10,"389":4,"390":8,"397":1,"398":5,"399":3,"400":3,"401":1,"402":12,"403":4,"404":12,"405":2,"406":1,"407":1,"409":1,"414":1,"415":1,"416":1,"417":4,"418":1,"419":3,"420":3,"422":4,"426":2,"427":1,"428":1,"429":2,"431":20,"432":6,"434":4,"436":2,"437":1,"438":1,"440":3,"441":5,"442":8,"443":4,"444":5,"445":1,"446":2,"447":4,"448":6,"451":2,"452":12,"455":1,"456":13,"457":7,"458":1,"459":1,"461":3,"462":2,"464":2,"465":4,"466":7,"470":6,"471":6,"472":2,"473":4,"476":2,"477":2,"478":2,"479":5,"480":1,"481":7,"482":1,"483":1,"485":3,"486":2,"487":1,"488":1,"490":2,"491":5,"492":1,"493":4,"497":1,"507":1,"508":1,"510":1,"512":2,"513":4,"514":7,"515":1,"516":11,"518":1,"520":4,"521":1,"522":1,"523":2,"524":4,"525":4,"527":2,"531":1,"532":3,"534":2,"545":2,"546":1,"548":1,"549":1,"552":1,"553":1,"560":1,"561":1,"562":3,"563":1,"564":1,"565":2,"566":3,"567":12,"568":1,"569":1,"570":2,"572":1,"573":6,"574":10,"577":1,"579":2,"580":4,"581":4,"582":1,"583":3,"584":3,"585":3,"593":1,"595":3,"596":8,"599":1,"600":1,"603":1,"604":1,"605":1,"608":1,"609":1,"612":1,"613":1,"622":1,"624":1,"629":2,"630":2,"631":1,"634":4,"636":3,"642":1,"643":1,"646":1,"647":1,"648":1,"654":1,"657":1,"658":1,"662":3,"663":3,"665":2,"666":6,"667":6,"668":4,"669":2,"672":1,"673":3,"674":1,"679":10,"680":2,"681":5,"682":4,"683":1,"684":2,"685":5,"687":5,"688":2,"690":1,"691":8,"692":1,"693":1,"694":1,"695":2,"696":2,"698":1,"700":1,"701":1,"705":1,"706":5,"707":1,"709":7,"711":2,"717":1,"718":3,"719":3,"720":1,"721":3,"722":4,"725":6,"726":4,"728":2,"729":1,"730":8,"731":3,"732":1,"733":1,"734":9,"735":1,"736":1,"737":7,"738":3,"739":3,"740":2,"741":6,"745":1,"746":7,"747":2,"748":2,"749":1,"751":3,"753":1,"760":1,"767":2,"768":1}}],["replacing",{"2":{"748":1}}],["replace",{"2":{"430":2,"431":4,"432":1}}],["repita",{"2":{"616":1}}],["repintura",{"2":{"62":1}}],["repeat",{"2":{"393":1}}],["repetir",{"2":{"347":1}}],["reposiciona",{"2":{"690":1}}],["repositórios",{"2":{"596":1}}],["repositório",{"2":{"407":1,"596":1,"681":1,"695":1,"728":1}}],["repositories",{"2":{"270":3,"290":3}}],["report",{"2":{"621":1}}],["reportada",{"2":{"30":1}}],["repo",{"2":{"596":1}}],["reprovado",{"2":{"675":1}}],["reproduzir",{"2":{"77":1,"254":1}}],["reproduzidas",{"2":{"48":2}}],["representação",{"2":{"85":1,"427":1,"681":1}}],["representações",{"0":{"81":1},"1":{"82":1,"83":1,"84":1,"85":1,"86":1,"87":1,"88":1}}],["representam",{"2":{"35":1,"261":1,"608":1}}],["representar",{"2":{"11":13,"12":1,"21":1,"34":12}}],["representa",{"2":{"11":2,"13":1,"16":1,"17":1,"18":1,"19":1,"34":2,"130":1,"412":1,"453":1,"461":4,"485":4,"608":1}}],["reservadas",{"2":{"390":1}}],["reservados",{"0":{"494":1},"1":{"495":1}}],["reservado",{"2":{"334":1,"341":1}}],["reset",{"2":{"220":1,"656":1}}],["reside",{"2":{"534":1,"535":1,"582":1,"583":1,"584":1}}],["resize",{"2":{"424":2}}],["resizemode",{"2":{"333":1,"424":4,"426":1}}],["resiliente",{"2":{"221":1,"467":1}}],["resiliência",{"0":{"218":1}}],["ressalva",{"2":{"329":1}}],["ressalvas",{"0":{"57":1,"258":1},"2":{"541":1}}],["resolução",{"2":{"325":3,"334":2,"371":3}}],["resolva",{"0":{"722":1}}],["resolvendo",{"0":{"557":1,"558":1},"1":{"559":1,"560":1},"2":{"577":1}}],["resolve",{"2":{"441":1,"465":2,"467":2,"489":2,"577":1}}],["resolvedor",{"2":{"329":1}}],["resolver",{"2":{"112":1,"399":5,"451":1,"465":1,"467":1,"476":1,"489":1,"545":1,"619":1,"635":1,"636":1,"711":1,"715":1,"721":1,"739":4}}],["resolverá",{"2":{"30":1}}],["resolvida",{"2":{"255":1}}],["resolvido",{"2":{"252":1,"328":1}}],["resolvidos",{"2":{"129":1,"217":1,"328":1}}],["resolvê",{"2":{"107":1}}],["res",{"2":{"283":1,"303":1,"403":2}}],["respectivamente",{"2":{"128":1,"233":1,"424":1}}],["respeitar",{"2":{"110":1}}],["responsiva",{"2":{"691":1}}],["responsáveis",{"2":{"679":1}}],["responsável",{"2":{"111":1,"596":2}}],["responsabilidades",{"2":{"596":1}}],["responsabilidade",{"2":{"545":1}}],["responsetext",{"2":{"521":1}}],["response",{"2":{"520":6}}],["responde",{"0":{"544":1}}],["respondedor",{"2":{"251":3,"252":2}}],["respondente",{"0":{"251":1},"1":{"252":1},"2":{"251":4}}],["respondendo",{"0":{"55":1},"2":{"251":3,"544":1}}],["respondem",{"2":{"245":1}}],["responderá",{"2":{"252":1}}],["responder",{"2":{"113":1,"385":1,"487":1,"497":3,"534":2,"552":1}}],["respostas",{"2":{"464":1,"488":1,"541":1,"557":1}}],["resposta",{"0":{"248":1,"520":1,"710":1},"1":{"249":1,"250":1,"251":1,"252":1,"253":1},"2":{"55":1,"113":1,"243":1,"248":2,"250":2,"251":2,"252":1,"256":1,"497":2,"500":1,"501":1,"520":2,"533":1,"534":1,"689":1,"699":1,"757":1}}],["rest",{"2":{"333":1,"390":1,"517":1}}],["restrição",{"2":{"113":1}}],["restante",{"2":{"226":2,"229":2,"231":3,"344":1,"375":1,"465":1}}],["restartgame",{"2":{"74":1,"77":1}}],["restaurar",{"2":{"69":1,"569":1}}],["resto",{"2":{"68":1}}],["resulte",{"2":{"544":1}}],["resultcode",{"2":{"278":2,"298":2,"467":7}}],["result",{"2":{"259":5,"467":4}}],["resulta",{"2":{"113":1,"443":1,"690":1}}],["resultará",{"2":{"226":1,"229":1,"424":1,"503":2,"523":1,"562":1,"740":1}}],["resultar",{"2":{"39":1,"534":3,"746":1}}],["resultados",{"2":{"67":2,"221":1,"313":1,"358":1,"420":1,"440":1,"446":1,"449":1,"467":1,"470":1,"474":1,"551":1,"699":1}}],["resultado",{"0":{"467":1},"2":{"5":1,"67":2,"94":2,"103":2,"219":1,"278":1,"298":1,"337":1,"465":1,"478":1,"479":1,"488":1,"489":1,"523":1,"534":1,"564":1,"636":1,"675":2}}],["resumidamente",{"2":{"648":1}}],["resumir",{"2":{"108":1}}],["resumindo",{"2":{"93":1,"102":1}}],["resumed",{"2":{"279":1,"299":1}}],["resume",{"2":{"89":1,"98":1}}],["resumo",{"0":{"639":1,"683":1},"2":{"11":1,"34":1,"596":1}}],["recrie",{"2":{"511":1}}],["recriado",{"2":{"511":1}}],["recapitulação✨",{"0":{"459":1,"483":1}}],["recarga",{"2":{"217":1}}],["recarregando",{"2":{"135":1}}],["recarregamento",{"2":{"135":1,"495":1,"602":1,"603":1,"611":1,"612":1,"645":1,"646":1}}],["recarregado",{"2":{"135":1,"602":1,"603":1,"611":1,"612":1,"618":1,"645":1,"646":1}}],["recarregar",{"2":{"130":1,"196":1,"218":1,"272":1,"292":1}}],["recém",{"2":{"321":1,"366":1,"577":1,"624":1,"736":1}}],["recálculo",{"2":{"111":1}}],["recursivamente",{"2":{"708":1}}],["recursivo",{"0":{"708":1},"1":{"712":1,"713":1}}],["recursive",{"2":{"413":1}}],["recursos",{"0":{"40":1,"328":1,"329":1,"330":1,"414":1,"691":1},"1":{"415":1,"416":1,"417":1,"418":1,"419":1},"2":{"110":1,"156":1,"249":1,"285":1,"320":1,"323":1,"331":1,"333":1,"335":1,"349":1,"365":1,"369":1,"375":1,"381":1,"384":1,"407":4,"437":1,"490":1,"517":1,"569":1,"571":2,"654":1,"658":1,"671":1,"673":1,"691":3,"695":4,"703":1,"753":1}}],["recurso",{"2":{"9":1,"128":1,"156":1,"216":1,"320":1,"339":1,"365":1,"446":1,"574":1,"596":1,"619":1,"629":2,"658":1}}],["recuperar",{"2":{"106":1}}],["recua",{"2":{"47":1}}],["recortado",{"2":{"543":1}}],["recortada",{"2":{"506":1}}],["recompilação",{"2":{"328":1}}],["recomendar",{"2":{"413":1}}],["recomendado",{"0":{"602":1,"611":1,"645":1},"2":{"333":1,"398":1,"399":1,"413":1,"426":1,"538":1,"729":1}}],["recomendadas",{"2":{"77":1,"628":1}}],["recomenda",{"2":{"139":1,"200":1}}],["recomendamos",{"2":{"64":1,"69":1,"70":1,"131":1,"144":1,"149":1,"165":1,"166":2,"169":1,"183":1,"188":1,"200":2,"204":1,"310":1,"343":1,"355":1,"399":1,"416":1,"441":1,"451":2,"452":1,"455":1,"476":1,"480":1,"658":1,"681":1,"696":2,"736":1}}],["recomendável",{"2":{"42":2,"43":1,"143":1,"165":1,"183":1,"331":1}}],["reconstruí",{"2":{"458":1,"482":1}}],["reconstrução",{"2":{"458":1,"482":1}}],["reconstruir",{"2":{"378":1,"457":1,"458":1,"481":1,"482":1,"726":1}}],["reconstrua",{"2":{"377":1}}],["reconhecido",{"2":{"245":1}}],["reconhecimento",{"2":{"243":1}}],["reconhecer",{"2":{"200":1}}],["reconhecedores",{"2":{"77":1}}],["reconciliação",{"2":{"118":1}}],["reconciliar",{"2":{"112":1}}],["recolhido",{"2":{"12":1,"23":1,"568":1}}],["receba",{"2":{"541":1}}],["recebimento",{"2":{"535":1}}],["recebida",{"2":{"522":1}}],["recebem",{"2":{"681":1}}],["recebe",{"2":{"106":1,"251":1,"552":1}}],["receberá",{"2":{"134":1,"454":1,"490":1}}],["receber",{"2":{"12":1,"21":1,"42":1,"74":2,"358":1,"424":1,"466":1,"619":1}}],["receivecommand",{"2":{"431":4}}],["receivecomponent",{"2":{"113":1}}],["receiveevent",{"2":{"427":2}}],["receiver>",{"2":{"259":1}}],["receiver",{"2":{"259":1}}],["recentes",{"2":{"254":1,"420":1,"440":1,"458":2,"482":2,"550":1,"554":1,"724":1}}],["recentemente",{"2":{"149":1,"174":1,"209":1,"742":1}}],["recente",{"2":{"55":1,"135":1,"138":1,"142":1,"156":1,"165":1,"168":1,"183":1,"184":1,"185":1,"187":1,"200":2,"203":1,"312":1,"357":1,"383":2,"417":1,"457":1,"481":1,"523":1,"529":1,"602":1,"611":1,"645":1,"692":1,"721":1,"726":1,"734":1}}],["receptor",{"2":{"14":1,"28":1,"259":2}}],["rótulo",{"2":{"3":1,"5":1,"6":1,"7":1,"244":1}}],["by",{"2":{"648":1,"658":1,"748":2}}],["bytecode",{"2":{"574":1,"657":2,"685":2,"742":1,"744":1}}],["bônus",{"2":{"555":1}}],["básicas",{"0":{"125":1},"1":{"126":1,"127":1,"128":1,"129":1,"130":1,"131":1,"132":1,"133":1,"134":1,"135":1,"136":1},"2":{"280":1,"300":1,"322":1,"368":1,"473":1,"760":1}}],["básica",{"2":{"90":1,"99":1,"339":1,"457":1,"470":1,"481":1,"507":1,"730":1}}],["básicos",{"0":{"505":1},"2":{"532":1}}],["básico",{"0":{"244":1,"753":1},"2":{"50":1,"51":1,"235":1,"243":1,"244":1,"245":1,"385":1,"467":1,"470":1,"573":1}}],["bc8f8f",{"2":{"88":1}}],["bcp",{"2":{"8":1}}],["b0e0e6",{"2":{"88":1}}],["b0c4de",{"2":{"88":1}}],["b22222",{"2":{"88":1}}],["bdb76b",{"2":{"88":1}}],["b8860b",{"2":{"88":1}}],["brutos",{"2":{"534":1}}],["bruto",{"2":{"427":1,"442":1,"443":2}}],["branco",{"2":{"441":1,"497":2,"500":1,"501":1,"502":1,"503":2,"548":1}}],["brancura",{"0":{"84":1}}],["braces",{"2":{"345":1}}],["bracescurly",{"2":{"345":1}}],["broadcastreceiver",{"2":{"258":1,"259":4}}],["brown",{"2":{"88":1}}],["brisa",{"2":{"673":1}}],["bridging",{"2":{"493":1}}],["bridge",{"2":{"101":1,"110":1,"111":1,"256":2,"431":4,"432":2,"444":1,"452":10,"456":4,"464":2,"465":2,"466":4,"492":2,"524":1,"555":1,"599":1,"608":1,"642":1}}],["brinque",{"2":{"244":1}}],["breve",{"2":{"107":1,"152":1,"177":1,"194":1,"212":1,"454":1,"464":1,"466":1,"479":1,"490":1,"617":1,"624":1,"674":1}}],["brevemente",{"2":{"41":1}}],["brew",{"2":{"67":1,"165":1,"166":2,"183":1,"310":1}}],["break",{"2":{"35":3,"431":1}}],["best",{"2":{"731":1}}],["benchmarks",{"2":{"693":1}}],["benefício",{"2":{"577":1}}],["benefícios",{"2":{"328":1,"694":1,"742":1}}],["beneficiar",{"2":{"66":1}}],["beforeall",{"2":{"675":1}}],["beforeeach",{"2":{"675":1}}],["beginevent",{"2":{"576":1}}],["begintransaction",{"2":{"404":3,"431":2}}],["behavior",{"2":{"564":1}}],["beta",{"2":{"549":1}}],["between",{"2":{"226":2,"229":3,"231":1,"244":1}}],["bela",{"2":{"545":1}}],["be",{"2":{"114":1,"430":1,"680":1}}],["beige",{"2":{"88":1}}],["bem",{"0":{"544":1},"2":{"42":1,"58":1,"65":1,"69":1,"95":1,"104":1,"120":1,"121":1,"159":1,"231":1,"236":1,"243":1,"244":1,"268":1,"285":1,"288":1,"309":1,"344":1,"354":1,"375":1,"384":1,"442":1,"449":1,"474":1,"515":1,"532":1,"534":1,"569":1,"603":1,"612":1,"636":1,"646":1,"648":1,"673":1,"675":1,"700":1,"722":1,"730":1}}],["bigblue",{"2":{"668":6}}],["bigbutton",{"2":{"565":4}}],["bits",{"2":{"349":1,"507":1}}],["biblioteca",{"0":{"376":1,"380":1},"1":{"381":1,"382":1,"383":1},"2":{"106":1,"310":1,"313":2,"343":1,"345":1,"355":1,"358":2,"365":1,"374":1,"375":1,"376":2,"377":2,"378":2,"379":2,"382":2,"383":3,"407":1,"409":1,"411":1,"412":2,"413":5,"417":1,"420":1,"440":1,"470":1,"471":1,"472":1,"473":1,"493":1,"538":1,"545":2,"596":1,"634":1,"636":1,"657":1,"667":2,"679":1,"682":1,"693":1,"695":2,"696":1}}],["bibliotecas",{"0":{"374":1,"379":1,"407":1,"408":1,"521":1,"706":1},"1":{"375":1,"376":1,"377":1,"378":1,"379":1,"380":1,"381":1,"382":1,"383":1,"408":1,"409":2,"410":2,"411":2,"412":2,"413":2,"707":1,"708":1},"2":{"60":1,"106":1,"313":1,"358":1,"375":1,"377":1,"379":8,"381":2,"407":4,"409":1,"417":1,"420":1,"440":1,"446":1,"448":1,"493":1,"521":1,"538":1,"596":1,"634":1,"636":1,"667":1,"679":1,"680":1,"682":1,"706":1,"755":1,"768":1}}],["bisque",{"2":{"88":1}}],["binaries",{"2":{"706":1}}],["binary=node",{"2":{"574":1,"663":1}}],["binary",{"2":{"191":1,"412":1}}],["bind",{"2":{"427":1}}],["binding",{"2":{"390":1}}],["binário",{"2":{"331":1,"377":1,"378":1,"407":1,"648":1,"654":1,"706":1}}],["binários",{"2":{"68":1,"656":1,"706":1}}],["binárias",{"2":{"65":1}}],["bin",{"2":{"67":17,"68":1,"191":1,"650":1,"651":1}}],["blur",{"0":{"124":1}}],["blueviolet",{"2":{"88":1}}],["blue",{"2":{"54":1,"88":1,"562":1,"668":1,"737":1}}],["blanchedalmond",{"2":{"88":1}}],["black",{"2":{"60":1,"88":1}}],["blocklist",{"2":{"577":2}}],["blocking",{"2":{"480":3}}],["block",{"2":{"390":1}}],["blocos",{"2":{"552":1,"691":1,"692":3}}],["bloco",{"2":{"270":1,"385":1,"443":3,"574":1,"581":2,"692":1,"699":1}}],["bloqueada",{"2":{"491":1}}],["bloqueado",{"2":{"56":1,"520":1,"535":1,"545":1}}],["bloqueando",{"2":{"491":1,"500":1}}],["bloqueio",{"0":{"705":1},"2":{"469":1}}],["bloqueou",{"2":{"323":1,"369":1}}],["blob",{"2":{"113":1,"313":1,"576":1}}],["blog",{"2":{"75":1}}],["b",{"2":{"14":3,"15":3,"24":3,"49":1,"390":6,"549":1}}],["bug",{"2":{"671":3,"679":1,"681":1}}],["bugs",{"2":{"117":1,"455":1,"480":1,"499":1,"670":1}}],["buffers",{"2":{"693":1}}],["buffer",{"2":{"559":1}}],["bufferdelay",{"2":{"116":1}}],["bundling=true",{"2":{"548":1}}],["bundling",{"0":{"516":1}}],["bundleassetname",{"0":{"590":1}}],["bundleconfig",{"0":{"589":1}}],["bundlecommand",{"0":{"588":1},"2":{"574":2}}],["bundleurl",{"2":{"365":3}}],["bundlerelease",{"2":{"654":1}}],["bundler",{"2":{"152":1,"189":1,"194":1,"212":1,"328":1,"329":1,"566":1,"655":1,"704":1}}],["bundle",{"2":{"92":7,"189":2,"256":11,"279":2,"280":1,"283":3,"299":2,"300":1,"303":3,"320":5,"322":1,"365":5,"368":1,"404":6,"430":6,"548":3,"574":8,"588":3,"589":1,"590":2,"592":1,"596":1,"654":2,"660":2,"662":3,"663":2,"666":1,"685":2}}],["bubbled",{"2":{"427":2}}],["but",{"2":{"313":1}}],["button>",{"2":{"404":1}}],["buttoncontainer",{"2":{"244":3}}],["buttonbasics",{"2":{"244":1}}],["buttonlabel",{"2":{"224":2,"225":2,"226":2,"227":2,"228":2,"229":2,"230":2,"233":3,"234":2}}],["buttonopacity",{"2":{"113":2}}],["buttontext",{"2":{"3":1,"5":1,"60":2,"245":6}}],["button",{"2":{"3":1,"5":1,"11":1,"34":1,"60":2,"217":1,"224":2,"225":2,"226":2,"227":2,"228":2,"229":2,"230":2,"233":3,"234":2,"244":10,"245":8,"320":1,"328":2,"349":8,"404":9,"444":2,"457":2,"481":2,"680":3,"737":3}}],["burlywood",{"2":{"88":1}}],["buildproductspath",{"2":{"663":2}}],["buildtypes",{"2":{"653":1}}],["buildconfigfields",{"2":{"596":1}}],["buildconfig",{"2":{"279":2,"299":2,"402":2,"404":1}}],["builder",{"2":{"279":1,"299":1,"404":3,"427":1,"710":1}}],["buildsettings",{"2":{"722":1}}],["buildscript",{"2":{"270":1,"290":1}}],["builds",{"2":{"127":1}}],["build",{"2":{"67":1,"68":5,"142":1,"168":1,"203":1,"259":6,"270":4,"271":1,"278":4,"279":2,"290":4,"291":1,"298":4,"299":2,"358":1,"404":2,"412":1,"413":1,"427":1,"547":1,"549":2,"574":1,"581":1,"598":1,"600":1,"607":1,"617":1,"621":1,"641":1,"643":1,"653":1,"654":3,"656":1,"657":1,"658":1,"662":3,"663":2,"685":2,"708":1,"710":1,"742":1}}],["buscá",{"2":{"629":1}}],["busca",{"0":{"523":1},"2":{"520":1,"523":1,"673":1,"691":1,"730":1}}],["buscado",{"2":{"519":1}}],["buscar",{"2":{"43":1,"517":1,"519":1,"520":1}}],["bus",{"2":{"608":13}}],["busy",{"0":{"20":1},"2":{"12":1}}],["bananaelements",{"2":{"680":2}}],["banana",{"2":{"680":3}}],["banda",{"2":{"334":1}}],["bancos",{"2":{"628":1,"693":1}}],["banco",{"2":{"333":1,"379":1,"678":1}}],["banner=",{"2":{"73":1}}],["banner",{"2":{"73":2}}],["babelrc",{"2":{"538":1}}],["babel",{"2":{"151":1,"176":1,"193":1,"211":1,"390":4,"538":2,"736":2,"739":7}}],["bar",{"2":{"135":1,"256":2,"390":3,"461":1,"485":1}}],["barras",{"2":{"13":1,"16":1,"17":1,"18":1}}],["barra",{"2":{"11":3,"34":3,"77":3,"438":1,"439":1,"547":1,"549":1,"615":1,"617":1}}],["ba55d3",{"2":{"88":1}}],["baseurl",{"2":{"739":1}}],["baseenthusiasmlevel",{"2":{"737":3}}],["bases",{"2":{"691":1}}],["baseia",{"2":{"636":1}}],["baseactivityeventlistener",{"2":{"467":3}}],["baseado",{"2":{"166":1,"444":1,"746":1}}],["baseados",{"2":{"13":1,"16":1,"17":1,"18":1,"285":1,"693":1}}],["baseadas",{"2":{"62":1,"532":1,"545":1}}],["baseada",{"0":{"523":1},"2":{"46":1,"523":1,"552":1,"679":1}}],["basejavamodule",{"2":{"452":1}}],["baseconfig",{"2":{"399":2}}],["base64",{"2":{"333":1}}],["baseline",{"2":{"227":2,"228":1}}],["base",{"0":{"231":1},"2":{"74":1,"77":1,"219":1,"227":1,"233":1,"234":2,"241":1,"261":1,"262":1,"337":1,"399":1,"409":1,"424":1,"452":1,"549":1,"565":1,"629":1,"670":1,"671":2,"690":1}}],["bashcd",{"2":{"747":1,"748":1}}],["bashchoco",{"2":{"200":1}}],["bashgit",{"2":{"728":1}}],["bashkill",{"2":{"703":1}}],["bashkeytool",{"2":{"650":1}}],["bash07",{"2":{"685":1}}],["bashtypeerror",{"2":{"660":2}}],["bashsudo",{"2":{"651":1,"703":1,"705":1}}],["bashecho",{"2":{"608":1,"715":1}}],["bashexport",{"2":{"68":1,"168":1,"191":1}}],["bash22b8",{"2":{"608":1}}],["bashbus",{"2":{"608":1}}],["bashbrew",{"2":{"165":1,"166":1,"183":1,"355":1}}],["bashreact",{"2":{"567":1}}],["bashrc",{"2":{"142":1,"168":1}}],["bashpod",{"2":{"313":2,"358":2}}],["bashwarning",{"2":{"268":1}}],["bashyarn",{"2":{"152":1,"157":1,"176":1,"177":1,"193":1,"194":1,"211":1,"212":1,"268":2,"281":1,"288":2,"301":1,"309":2,"324":1,"325":1,"354":2,"370":1,"371":1,"376":1,"377":1,"378":1,"457":1,"470":3,"481":1,"567":1,"600":1,"609":1,"624":1,"625":1,"626":1,"627":1,"643":1,"655":1,"704":1,"713":1,"734":1,"739":1,"743":1,"744":1,"747":1,"748":1}}],["bashnpx",{"2":{"145":1,"146":1,"157":1,"170":1,"171":1,"189":1,"190":1,"205":1,"377":1,"436":2,"470":1,"654":1,"685":1,"711":1,"721":2,"726":1,"733":1}}],["bashnpm",{"2":{"145":1,"151":1,"152":1,"170":1,"176":1,"177":1,"189":1,"193":1,"194":1,"211":1,"212":1,"268":2,"281":1,"288":2,"301":1,"309":2,"324":1,"325":1,"354":2,"370":1,"371":1,"376":1,"377":1,"378":1,"409":1,"457":1,"481":1,"567":1,"600":1,"609":1,"624":1,"625":1,"626":1,"627":1,"643":1,"655":1,"704":1,"712":1,"734":1,"739":1,"743":1,"744":1,"747":1,"748":1}}],["bashadb",{"2":{"133":1,"602":2,"611":2,"645":2,"685":1}}],["bashunlink",{"2":{"67":1}}],["bashln",{"2":{"67":1}}],["bash",{"2":{"65":1,"142":5,"168":4,"548":1,"651":2,"725":1}}],["bash$",{"2":{"65":2,"67":2,"283":1,"303":1,"599":1,"608":3,"642":1}}],["basta",{"2":{"118":1}}],["bastante",{"2":{"60":1,"256":1,"554":1,"719":1}}],["bastidores",{"0":{"596":1},"2":{"46":1,"442":1}}],["baixe",{"2":{"141":1,"167":1,"202":1}}],["baixo",{"2":{"35":1,"60":1,"90":1,"94":2,"99":1,"103":2,"116":1,"224":2,"331":1,"502":1,"535":1,"541":1,"681":2}}],["baixado",{"0":{"530":1},"2":{"525":1}}],["baixados",{"2":{"69":1,"598":1,"607":1,"641":1}}],["baixada",{"2":{"144":1,"169":1,"188":1,"204":1,"341":1}}],["baixar",{"2":{"139":1,"142":1,"168":1,"203":1}}],["baixa",{"2":{"9":1,"334":1,"497":1,"691":1}}],["background",{"2":{"490":1,"491":1,"668":1}}],["background=",{"2":{"245":1}}],["backgroundcolor",{"2":{"30":2,"46":1,"53":2,"54":1,"60":2,"122":2,"223":3,"224":6,"225":6,"226":6,"227":6,"228":6,"229":10,"230":10,"231":5,"232":6,"233":6,"234":6,"245":1,"261":3,"262":3,"263":3,"317":1,"362":1,"441":1,"444":4,"562":3,"668":1,"730":1}}],["backhandler",{"2":{"77":1}}],["back",{"2":{"5":1,"47":1,"520":1}}],["bons",{"2":{"537":1,"681":1}}],["book",{"2":{"555":2}}],["bootstrap",{"2":{"470":1}}],["bool",{"2":{"367":1,"442":5,"443":2,"486":1,"490":1}}],["booleanos",{"2":{"349":1}}],["booleano",{"2":{"14":1,"15":1,"28":1,"258":1,"442":3}}],["booleana",{"2":{"12":1,"21":1}}],["boolean",{"2":{"12":5,"20":1,"21":1,"22":1,"23":1,"24":1,"28":1,"29":1,"259":5,"279":1,"299":1,"402":1,"424":5,"462":5,"486":1,"499":1}}],["body",{"2":{"332":3,"490":1,"519":1}}],["bom",{"2":{"323":1,"328":2,"331":1,"369":1,"461":1,"485":1,"507":1,"725":1}}],["bolha",{"2":{"252":1}}],["bold",{"2":{"53":1,"54":1,"60":1,"668":1,"730":1,"737":1}}],["bobos",{"2":{"555":1}}],["bob",{"2":{"242":1}}],["bobble",{"2":{"55":1}}],["bork",{"2":{"390":1}}],["borda",{"2":{"225":1,"226":2,"340":1}}],["borderbottomrightradius",{"2":{"340":1}}],["borderbottomleftradius",{"2":{"340":1}}],["borderbottomwidth",{"2":{"231":1,"232":1}}],["bordertoprightradius",{"2":{"340":1}}],["bordertopleftradius",{"2":{"340":1}}],["bordercolor",{"2":{"116":2,"346":1,"387":1}}],["borderwidth",{"2":{"116":2,"224":1,"225":1,"226":1,"227":1,"228":1,"229":1,"230":1,"233":1,"234":1,"346":1,"387":1}}],["borderradius",{"2":{"53":3,"54":1,"224":1,"225":1,"226":1,"227":1,"228":1,"229":1,"230":1,"231":1,"233":1,"234":1,"424":6,"426":1}}],["borbulhantes",{"2":{"57":1}}],["bottom",{"2":{"234":1,"551":1}}],["botões",{"2":{"11":2,"34":2,"252":1,"349":1,"526":1,"682":1}}],["botão",{"0":{"244":1},"2":{"11":7,"34":4,"35":3,"39":2,"74":3,"77":5,"116":1,"142":1,"149":1,"168":1,"174":1,"200":1,"203":1,"209":1,"243":2,"244":5,"245":5,"250":1,"279":4,"299":4,"321":1,"349":1,"366":1,"385":1,"404":5,"444":2,"530":1,"617":1,"679":5,"724":1,"745":2}}],["box5",{"2":{"232":2}}],["box4",{"2":{"232":2}}],["box3",{"2":{"232":2}}],["box2",{"2":{"232":2}}],["box1",{"2":{"232":2}}],["boxlabel",{"2":{"231":2}}],["boxinfoprops",{"2":{"231":2}}],["boxinfo",{"2":{"231":4}}],["box",{"2":{"4":1,"54":3,"60":2,"224":4,"225":4,"226":4,"227":4,"228":4,"229":8,"230":8,"231":5,"232":6,"233":4,"234":4}}],["boas",{"2":{"141":1,"167":1,"202":1,"742":1}}],["board",{"2":{"74":8,"77":8}}],["boa",{"2":{"3":1,"218":1,"221":1,"245":1,"541":1,"605":1,"675":1,"738":1}}],["mqt",{"2":{"555":4,"685":1}}],["ms",{"2":{"533":2,"534":2,"552":1,"556":1}}],["mdn",{"2":{"518":1}}],["mdnhttps",{"2":{"415":1}}],["mkcoordinatespan",{"2":{"442":6}}],["mkcoordinateregion",{"2":{"442":7,"443":3}}],["mkcoordenregion",{"2":{"442":2}}],["mkmapviewdelegate",{"2":{"443":1}}],["mkmapviewdelegate>",{"2":{"443":1}}],["mkmapview",{"2":{"441":2,"442":1,"443":5}}],["mcallercontext",{"2":{"422":2,"423":1}}],["mpickerpromise",{"2":{"467":9}}],["mp4",{"2":{"329":1}}],["mp3",{"2":{"329":1}}],["mínima",{"2":{"442":1}}],["mínimo",{"2":{"13":2,"17":1,"244":1,"505":1,"506":1,"523":1,"720":1}}],["mídia",{"2":{"328":1}}],["mreactnativehost",{"2":{"402":2}}],["mreactinstancemanager",{"2":{"278":1,"279":13}}],["mreactrootview",{"2":{"92":2,"279":6}}],["música",{"2":{"254":1}}],["múltiplas",{"0":{"444":1},"2":{"252":1,"279":1,"299":1}}],["mydata",{"2":{"519":1}}],["mywebsite",{"2":{"519":2,"521":1}}],["mycallback",{"2":{"488":2}}],["mycustomview>",{"2":{"427":2}}],["mycustomview",{"2":{"426":1,"427":5}}],["mysuccesscallback",{"2":{"464":2}}],["myscreen",{"2":{"219":1}}],["myfailurecallback",{"2":{"464":2}}],["myfragment",{"2":{"430":3,"431":7}}],["mynativereference2",{"2":{"444":1}}],["mynativereference",{"2":{"444":2}}],["mynativeviewé",{"2":{"444":1}}],["mynativeview",{"2":{"444":12}}],["myapplication",{"2":{"590":1,"591":1}}],["myapppackage",{"2":{"456":8}}],["myapp",{"2":{"441":1,"442":2,"443":2,"652":4,"653":5}}],["myview",{"2":{"434":1}}],["myviewmanager",{"2":{"431":6,"432":2,"434":6}}],["mypackage",{"2":{"429":2,"430":4,"431":2,"432":5,"433":2}}],["mymessage",{"2":{"427":2}}],["my",{"2":{"328":7,"337":3,"338":1,"434":1,"450":1,"464":1,"465":1,"475":1,"489":1,"650":3,"651":2,"652":1}}],["myreactapplication",{"2":{"402":7}}],["myreactactivity",{"2":{"279":4,"299":4}}],["myreactnativepackage",{"2":{"279":1,"299":1,"456":1}}],["myreactnativeapp",{"2":{"268":1,"277":1,"279":2,"288":1,"297":1,"299":2,"309":1,"354":1}}],["mytaskservice",{"2":{"256":5,"259":2}}],["mybutton",{"2":{"114":5,"115":5}}],["mmap",{"2":{"574":1}}],["mm",{"2":{"134":1,"462":2}}],["móvel",{"0":{"385":1},"2":{"156":2,"285":1,"483":1,"679":1}}],["móveis",{"2":{"112":1,"239":1,"243":1,"455":1,"471":1,"480":1,"517":1,"635":1}}],["módulos",{"0":{"95":1,"97":1,"104":1,"106":1,"271":1,"291":1,"406":1,"446":1,"449":1,"470":1,"474":1,"576":1,"764":1},"1":{"96":1,"97":1,"105":1,"106":1,"272":1,"447":1,"448":1,"450":1,"451":1,"452":1,"453":1,"454":1,"455":1,"456":1,"457":1,"458":1,"459":1,"460":1,"461":1,"462":1,"463":1,"464":1,"465":1,"466":1,"467":1,"468":1,"469":1,"475":1,"476":1,"477":1,"478":1,"479":1,"480":1,"481":1,"482":1,"483":1,"484":1,"485":1,"486":1,"487":1,"488":1,"489":1,"490":1,"491":1,"492":1,"493":1,"494":1,"495":1},"2":{"95":1,"97":2,"104":1,"106":4,"217":2,"218":1,"278":1,"298":1,"328":1,"406":1,"419":2,"425":1,"437":1,"448":1,"449":3,"452":2,"453":1,"455":1,"456":5,"461":1,"464":1,"465":1,"466":2,"469":1,"470":3,"474":3,"480":1,"485":1,"488":1,"489":1,"490":1,"491":3,"492":1,"493":2,"495":1,"516":4,"560":1,"573":1,"575":1,"576":4,"577":3,"673":1,"678":1,"735":2,"764":4}}],["módulo",{"0":{"426":1,"434":1,"447":1,"450":1,"452":1,"453":1,"456":1,"460":1,"461":1,"475":1,"477":1,"478":1,"484":1,"485":1,"562":1},"1":{"451":1,"452":1,"457":1,"461":1,"462":1,"463":1,"485":1,"486":1,"487":1,"563":1},"2":{"37":1,"49":1,"50":1,"97":1,"106":3,"217":5,"218":2,"219":2,"317":2,"320":2,"325":1,"362":2,"365":2,"371":1,"419":1,"420":2,"421":1,"426":2,"440":2,"446":1,"447":4,"448":2,"449":1,"450":1,"452":5,"453":3,"454":3,"456":9,"457":8,"458":1,"459":4,"461":10,"462":2,"463":4,"464":6,"465":3,"467":1,"468":2,"469":1,"470":3,"474":1,"475":1,"477":7,"478":9,"479":2,"481":8,"482":1,"483":5,"485":11,"486":3,"487":5,"488":1,"489":1,"490":4,"491":11,"492":1,"493":2,"495":1,"516":2,"555":1,"561":1,"562":1,"563":1,"566":1,"573":1,"574":2,"575":2,"630":1,"677":2,"709":2}}],["m",{"2":{"74":1,"110":1,"126":2,"131":2,"153":1,"178":1,"213":1,"259":2,"278":3,"279":1,"298":3,"299":1,"441":1,"442":3,"443":2,"444":1,"445":1,"477":2,"478":1,"493":1,"548":1,"619":1,"699":2,"728":1}}],["mtime",{"2":{"68":1}}],["m1",{"2":{"68":1,"166":2,"168":1}}],["mbutton",{"2":{"404":3}}],["mb",{"2":{"43":3,"44":2,"342":2,"572":3,"693":1}}],["mutablemap",{"2":{"463":1}}],["mutablelistof",{"2":{"456":1}}],["mutablelist",{"2":{"456":2}}],["multithread",{"2":{"446":1}}],["multiplataforma",{"2":{"414":1,"561":1}}],["multiple",{"2":{"348":1}}],["multiplicação",{"2":{"49":1}}],["munkustrap",{"2":{"349":3}}],["mundos",{"2":{"89":1,"98":1}}],["mundo",{"2":{"43":1}}],["mude",{"2":{"349":1,"750":1}}],["mudança",{"2":{"259":1,"337":1,"485":1,"533":1,"556":1,"681":3,"741":1}}],["mudanças",{"0":{"73":1,"74":1,"77":1},"2":{"10":1,"55":2,"74":1,"77":1,"143":1,"165":1,"183":1,"458":1,"482":1,"681":1}}],["mudado",{"2":{"113":1,"221":1}}],["muda",{"0":{"540":1},"2":{"113":1,"242":1,"349":1,"358":1,"444":1,"680":1}}],["mudará",{"2":{"463":1}}],["mudar",{"2":{"111":1,"117":1,"248":1,"338":1,"377":1,"444":1,"461":1,"463":1,"487":1,"491":1,"507":1,"730":1,"746":1}}],["mudam",{"2":{"10":1,"349":1,"680":1}}],["must",{"2":{"114":1}}],["muitos",{"2":{"51":1,"156":1,"235":1,"236":1,"348":1,"379":1,"387":1,"407":1,"420":1,"440":1,"445":1,"517":1,"520":1,"552":1,"688":1,"740":1}}],["muito",{"0":{"539":1,"541":1,"544":1,"559":1,"708":1},"1":{"712":1,"713":1},"2":{"43":3,"45":1,"46":1,"47":1,"60":2,"67":1,"116":2,"218":1,"227":1,"231":1,"236":1,"240":1,"242":1,"258":1,"279":1,"299":1,"333":1,"336":1,"337":1,"375":1,"379":1,"389":1,"409":1,"414":1,"417":1,"468":1,"491":1,"497":1,"502":1,"505":1,"509":1,"515":1,"537":2,"540":1,"541":1,"543":1,"544":1,"545":1,"556":2,"558":1,"559":1,"573":3,"619":1,"628":1,"666":1,"668":1,"675":1,"678":1,"681":1,"708":1,"745":1}}],["muita",{"2":{"42":1,"505":1}}],["muitas",{"2":{"35":1,"39":1,"50":1,"112":1,"331":1,"344":1,"348":1,"379":2,"385":1,"391":1,"535":1,"552":1,"557":1,"619":1,"629":2,"673":1,"675":3,"676":1,"683":1}}],["mágica",{"0":{"279":1,"299":1,"318":1,"363":1},"1":{"319":1,"320":1,"321":1,"364":1,"365":1,"366":1,"367":1}}],["mágico",{"2":{"33":3}}],["máquinas",{"2":{"665":1}}],["máquina",{"2":{"67":2,"239":1,"527":1,"599":1,"601":1,"602":1,"603":2,"608":2,"610":1,"611":1,"612":3,"621":2,"642":1,"644":1,"645":1,"646":3,"699":1,"745":1}}],["máxima",{"2":{"47":1,"442":1}}],["máximo",{"2":{"13":2,"16":1,"80":1,"257":3,"343":1,"464":1,"465":2,"561":1}}],["motor",{"2":{"673":1}}],["motorola",{"2":{"608":4}}],["motivo",{"2":{"67":1,"491":1,"532":1}}],["motivos",{"2":{"56":1,"219":1,"336":1,"665":1}}],["mobx",{"2":{"417":1,"569":1,"673":1}}],["mobile",{"2":{"259":1}}],["mockando",{"2":{"678":1}}],["mockar",{"2":{"676":1,"677":1}}],["mocks",{"2":{"677":1}}],["mocking",{"2":{"677":1}}],["mock",{"0":{"677":1}}],["mockdata",{"2":{"365":2}}],["moccasin",{"2":{"88":1}}],["most",{"2":{"313":1}}],["mostre",{"2":{"249":1,"506":1,"724":1}}],["mostradas",{"2":{"725":1}}],["mostrada",{"2":{"465":2}}],["mostrados",{"2":{"731":1}}],["mostrado",{"2":{"278":1,"298":1,"452":1,"651":1,"686":1}}],["mostramos",{"2":{"279":1,"299":1}}],["mostram",{"2":{"259":1,"520":1}}],["mostrarão",{"2":{"428":1,"442":1,"724":1}}],["mostrará",{"2":{"420":1,"440":1,"526":1,"635":1}}],["mostrar",{"2":{"135":1,"168":1,"251":1,"673":1,"677":1,"690":1,"692":1}}],["mostra",{"2":{"35":1,"348":1,"677":1,"723":1}}],["mozilla",{"2":{"238":1,"415":1}}],["more",{"2":{"131":1,"168":1,"203":1,"387":1}}],["morta",{"2":{"50":1}}],["mortas",{"2":{"50":1}}],["monorepo",{"2":{"583":1,"584":1,"585":1}}],["montagem",{"2":{"220":1,"337":1}}],["montados",{"2":{"497":1,"503":1}}],["montado",{"2":{"46":1,"673":1}}],["montada",{"2":{"46":1}}],["monitoramento",{"2":{"634":1}}],["monitorar",{"2":{"63":1,"349":1,"715":1}}],["monitor",{"0":{"136":1},"2":{"63":1,"136":1,"533":1,"551":1,"703":1}}],["mola",{"2":{"47":1}}],["mova",{"2":{"511":2}}],["mov",{"2":{"329":1}}],["movida",{"2":{"545":1}}],["movidas",{"2":{"236":1}}],["movie",{"2":{"520":2}}],["movies",{"2":{"520":6}}],["movimentar",{"2":{"246":1}}],["movimentos",{"2":{"45":1}}],["movimento",{"2":{"45":1,"52":1,"55":1,"251":1,"533":2}}],["movendo",{"2":{"251":1}}],["move",{"2":{"74":4,"77":4,"219":1}}],["mover",{"0":{"542":1},"2":{"45":1,"47":1,"191":1,"320":1,"365":1,"542":1}}],["modular",{"2":{"673":1}}],["modulepath",{"2":{"577":3}}],["modulepaths",{"2":{"576":2,"577":4}}],["modulemap",{"2":{"577":4}}],["moduleid",{"2":{"576":8}}],["moduleids",{"2":{"576":3}}],["moduleinitialiser",{"2":{"492":2}}],["module",{"2":{"257":1,"398":1,"399":2,"420":1,"426":1,"440":1,"441":3,"442":1,"443":1,"446":1,"449":1,"457":2,"462":1,"470":5,"474":1,"477":1,"478":7,"481":2,"486":1,"493":2,"516":1,"577":1,"667":1,"739":5}}],["modulenames",{"2":{"576":1}}],["modulename",{"2":{"101":1,"110":1,"111":1,"320":2,"365":2,"492":1}}],["modules",{"2":{"68":1,"268":2,"270":1,"271":4,"288":2,"290":1,"291":4,"309":2,"313":31,"320":1,"354":2,"358":2,"365":1,"390":1,"406":1,"456":3,"466":2,"555":3,"571":1,"574":3,"576":6,"583":2,"584":2,"585":2,"660":2,"663":1,"685":1,"705":1,"706":1,"722":2}}],["modifique",{"2":{"404":1}}],["modificou",{"2":{"154":1,"179":1,"197":1,"214":1}}],["modificá",{"2":{"153":1,"178":1,"196":1,"213":1}}],["modificar",{"2":{"63":1,"112":1,"274":1,"294":1,"314":1,"359":1,"581":1}}],["modificando",{"0":{"153":1,"178":1,"196":1,"213":1},"1":{"180":1},"2":{"50":1}}],["modificados",{"2":{"720":1}}],["modificadores",{"2":{"493":1}}],["modificado",{"2":{"20":1}}],["mod",{"2":{"390":1}}],["mode=release",{"2":{"654":1}}],["mode=",{"2":{"549":1,"608":1,"655":1,"743":1,"744":1}}],["mode",{"2":{"424":2,"549":2,"600":1,"609":1,"643":1,"655":2,"743":1,"744":1}}],["modelos",{"2":{"417":1,"733":2}}],["modelo",{"0":{"146":1,"171":1,"190":1,"206":1},"2":{"146":1,"171":1,"190":1,"206":1,"398":1,"521":2,"608":1,"666":1,"673":1,"674":1,"685":1,"695":1,"726":5}}],["moderação",{"2":{"55":1}}],["modos",{"2":{"111":3}}],["modo",{"0":{"537":1},"2":{"68":1,"79":1,"80":1,"85":2,"111":3,"120":1,"225":1,"255":1,"272":1,"292":1,"483":1,"537":1,"551":1,"568":3,"638":1,"659":1,"662":1,"668":1,"669":1,"676":1,"689":1,"711":1}}],["modal",{"0":{"28":1},"2":{"31":1,"74":1,"217":1,"541":3}}],["momento",{"2":{"7":1,"58":1,"92":1,"101":1,"144":1,"156":1,"169":1,"188":1,"204":1,"251":1,"337":1,"338":1,"455":1,"456":1,"463":1,"469":1,"480":1,"487":1,"488":1,"515":1,"637":1,"708":1,"730":1,"731":1}}],["middle",{"2":{"638":1}}],["midnightblue",{"2":{"88":1}}],["mil",{"2":{"552":1}}],["milissegundos",{"2":{"501":1}}],["milhares",{"2":{"374":1,"419":1,"677":1}}],["milhagem",{"2":{"143":1}}],["milliseconds",{"2":{"256":1}}],["migrando",{"0":{"658":1},"2":{"658":1}}],["migração",{"2":{"463":1,"487":1,"654":1}}],["migrar",{"2":{"217":1,"658":1}}],["migrate",{"2":{"65":1}}],["microsoft",{"2":{"200":1,"513":1,"746":1}}],["mixin",{"2":{"74":1,"77":1}}],["mixed",{"2":{"12":1,"21":1}}],["misses",{"2":{"67":2}}],["misturados",{"2":{"731":1}}],["misturar",{"2":{"493":1}}],["misturamos",{"2":{"89":1,"90":1,"98":1,"99":1}}],["mistyrose",{"2":{"88":1}}],["mistas",{"2":{"12":1,"21":1}}],["mista",{"2":{"12":1,"21":1}}],["misto",{"2":{"11":1,"34":1}}],["mitigar",{"2":{"64":1,"559":1}}],["minimumzoomscale",{"2":{"731":1}}],["minimumvalue=",{"2":{"692":1}}],["minimize",{"2":{"695":1}}],["minimizar",{"2":{"665":1}}],["minimizáveis",{"2":{"129":1}}],["minificado",{"2":{"685":1}}],["minificados",{"2":{"685":1}}],["miniatura",{"2":{"336":1,"506":1}}],["minha",{"0":{"544":1}}],["minhas",{"2":{"203":2}}],["minheight",{"2":{"227":1,"228":1,"234":1}}],["minwidth",{"2":{"224":1,"225":1,"226":1,"227":2,"228":2,"229":1,"230":1,"231":1,"234":1}}],["mintcream",{"2":{"88":1}}],["minúsculas",{"2":{"86":1}}],["minutos",{"2":{"64":1,"67":1,"156":2}}],["min",{"2":{"13":2}}],["métodos",{"0":{"119":1,"455":1,"480":1,"494":1},"1":{"120":1,"121":1,"122":1,"123":1,"124":1,"495":1},"2":{"46":1,"48":2,"74":1,"77":2,"95":1,"104":1,"119":1,"251":2,"402":2,"406":1,"424":1,"428":1,"444":2,"452":1,"454":1,"455":2,"462":1,"464":1,"468":1,"469":1,"479":1,"480":3,"486":2,"488":1,"491":8,"493":2,"680":1,"693":1}}],["método",{"0":{"423":1,"454":1,"479":1,"602":1,"603":1,"611":1,"612":1,"645":1,"646":1},"1":{"455":1},"2":{"10":1,"37":1,"93":1,"111":3,"115":1,"116":1,"122":1,"278":3,"279":2,"298":3,"299":2,"320":1,"321":2,"365":1,"366":2,"399":1,"404":3,"421":1,"423":1,"424":6,"427":2,"430":4,"431":1,"434":1,"441":2,"443":2,"444":5,"450":1,"453":2,"454":4,"455":2,"456":6,"457":4,"459":5,"461":1,"462":4,"463":2,"464":7,"465":5,"467":2,"475":1,"479":7,"480":2,"481":4,"483":5,"485":1,"486":3,"487":1,"488":1,"489":3,"491":4,"495":2,"520":1,"562":1,"602":1,"611":1,"635":1,"636":1,"645":1}}],["maestro",{"2":{"682":1,"684":1}}],["malicioso",{"2":{"628":1,"635":1,"636":1,"638":1}}],["majorversionios",{"2":{"564":2}}],["maven",{"2":{"596":5}}],["mavencentral",{"2":{"270":3,"290":3}}],["maverick",{"2":{"417":1}}],["makekeyandvisible",{"2":{"548":1}}],["makemeasurespec",{"2":{"431":4}}],["make",{"2":{"135":1}}],["magenta",{"2":{"88":1}}],["magictap",{"2":{"35":1}}],["mactivityeventlistener",{"2":{"467":2}}],["mactivityresultlistener",{"2":{"467":1}}],["macs",{"2":{"166":2}}],["mac",{"0":{"597":1,"614":1,"651":1},"1":{"598":1,"599":1,"600":1,"601":1,"602":1,"603":1,"604":1,"615":1,"616":1,"617":1,"618":1,"619":1,"620":1,"621":1,"622":1},"2":{"135":1,"184":1,"608":1,"615":1,"619":2}}],["macro",{"2":{"102":1,"441":1,"442":1,"478":2,"479":5}}],["macros",{"2":{"68":1,"493":1}}],["macos",{"0":{"160":1},"2":{"39":2,"67":1,"69":1,"126":1,"131":1,"187":1,"310":1,"355":1,"513":2,"514":1,"605":2,"651":1,"652":1,"716":1}}],["matrix",{"2":{"520":1}}],["matriz",{"2":{"48":1,"52":2,"65":1,"221":1,"251":2,"488":1,"516":2,"668":2,"708":1}}],["matching",{"2":{"608":4}}],["match",{"2":{"390":2,"403":2,"404":1}}],["matches",{"2":{"68":1}}],["math",{"2":{"390":1}}],["matiz",{"0":{"84":1}}],["mapkit",{"2":{"441":2,"442":4,"443":4}}],["mapview",{"0":{"441":1},"1":{"442":1},"2":{"440":1,"441":5,"442":9,"443":9}}],["mapof",{"2":{"427":3,"431":1}}],["mapbuilder",{"2":{"427":3,"431":2}}],["map",{"2":{"53":2,"92":1,"101":1,"224":1,"225":1,"226":1,"227":1,"228":1,"229":1,"230":1,"233":2,"234":1,"242":1,"317":1,"362":1,"427":2,"431":3,"443":3,"452":1,"463":3,"576":2,"594":2,"596":1,"662":2,"663":2,"680":1,"685":2}}],["mapas",{"0":{"660":1,"661":1,"663":1,"686":1},"1":{"661":1,"662":2,"663":1,"664":1},"2":{"135":1,"528":2,"660":5,"662":3,"663":1,"686":1,"755":1}}],["mapa",{"0":{"528":1},"2":{"52":1,"243":1,"427":1,"441":2,"442":4,"443":2,"662":1,"663":1,"685":1,"686":1}}],["mapeie",{"2":{"431":1}}],["mapeiam",{"2":{"462":1,"486":2}}],["mapeia",{"2":{"50":1}}],["mapear",{"2":{"52":1,"427":1,"660":1}}],["mapeados",{"2":{"52":1}}],["mapeado",{"2":{"50":1}}],["mapeada",{"2":{"46":1}}],["mapeamento",{"2":{"50":2,"52":1,"106":1,"261":1,"563":1}}],["mapeamentos",{"2":{"46":1,"739":1}}],["mainapplication",{"2":{"433":1,"456":2}}],["mainactivity",{"2":{"92":2,"403":1,"404":3}}],["mainreactpackage",{"2":{"404":2}}],["mainbundle",{"2":{"320":1,"365":1}}],["main",{"2":{"283":2,"303":2,"320":1,"365":1,"367":1,"403":1,"404":2,"452":1,"456":2,"491":1,"663":3}}],["maincomponentname",{"2":{"92":1}}],["maiúsculas",{"2":{"86":1}}],["maioria",{"2":{"108":1,"119":2,"216":1,"252":1,"261":1,"348":1,"377":2,"389":1,"407":1,"445":1,"534":1,"559":1,"571":1,"598":1,"607":1,"641":1,"696":1}}],["maiores",{"2":{"44":1,"55":1,"64":1,"70":1,"262":1,"656":1,"670":1,"678":1}}],["maior",{"2":{"43":1,"77":2,"143":1,"262":2,"336":1,"497":1,"500":1,"503":3,"531":1,"575":2,"665":1,"682":2,"687":1}}],["mais",{"0":{"235":1,"414":1,"694":1,"746":1},"1":{"415":1,"416":1,"417":1,"418":1,"419":1,"747":1,"748":1},"2":{"6":1,"33":1,"39":1,"42":2,"44":1,"46":1,"47":3,"55":2,"57":1,"60":2,"64":1,"67":2,"68":1,"76":1,"78":1,"91":1,"95":1,"100":1,"101":1,"104":1,"110":1,"112":1,"120":1,"134":1,"135":1,"138":1,"141":1,"142":1,"143":1,"147":1,"155":1,"156":2,"165":1,"166":1,"167":1,"168":1,"172":1,"180":1,"183":1,"184":2,"185":1,"187":2,"198":1,"200":2,"202":1,"203":1,"207":1,"215":1,"219":2,"221":1,"224":1,"226":1,"227":1,"229":1,"230":1,"231":1,"236":1,"240":1,"242":2,"243":1,"249":1,"252":3,"273":1,"284":1,"293":1,"304":1,"312":1,"313":1,"318":1,"320":1,"321":1,"325":1,"326":1,"328":1,"329":1,"334":1,"336":1,"337":1,"338":1,"339":1,"341":2,"344":1,"345":1,"347":1,"349":1,"357":1,"358":1,"363":1,"365":1,"366":1,"371":1,"372":1,"375":1,"379":1,"381":1,"382":1,"383":3,"384":1,"390":2,"399":2,"403":2,"407":1,"413":1,"414":2,"417":2,"418":1,"420":4,"421":1,"424":1,"426":1,"427":1,"428":1,"440":4,"441":1,"442":4,"444":1,"445":2,"452":1,"455":1,"456":3,"457":1,"458":2,"459":1,"461":1,"463":1,"465":1,"466":1,"467":1,"470":2,"480":1,"481":1,"482":2,"483":1,"487":1,"488":1,"493":2,"500":2,"501":3,"503":1,"505":2,"506":2,"507":1,"508":2,"520":2,"523":1,"525":1,"529":1,"531":3,"534":1,"537":1,"540":2,"541":2,"542":1,"550":1,"551":1,"552":1,"560":1,"562":1,"565":1,"572":1,"577":1,"586":1,"589":1,"602":1,"604":1,"605":1,"611":1,"613":1,"622":1,"628":2,"629":2,"635":2,"636":1,"639":1,"645":1,"646":1,"647":1,"662":1,"665":3,"668":2,"671":3,"673":3,"674":1,"675":1,"680":1,"682":7,"691":4,"692":3,"693":1,"694":1,"699":2,"700":3,"706":1,"711":2,"717":1,"721":1,"724":1,"726":1,"730":2,"734":1,"737":1,"741":1,"746":1,"753":1}}],["manytiles",{"2":{"692":1}}],["man",{"2":{"638":1}}],["manutenção",{"2":{"515":1}}],["manuseio",{"2":{"387":1}}],["manuais",{"2":{"310":1,"355":1,"726":1}}],["manually",{"2":{"549":1,"748":1}}],["manuallylayoutchildren",{"2":{"431":4}}],["manualmente",{"2":{"74":1,"135":2,"270":1,"279":1,"290":1,"299":1,"328":1,"330":1,"331":1,"333":1,"402":3,"404":1,"456":1,"523":1,"706":1,"719":1,"726":1}}],["manual",{"0":{"410":1,"664":1},"1":{"411":1,"412":1,"413":1},"2":{"68":1,"523":1,"532":1,"664":1,"671":1,"726":1,"738":1}}],["manage",{"2":{"278":1,"298":1,"549":2}}],["manager",{"2":{"142":4,"149":2,"168":4,"174":1,"203":4,"209":2,"434":1}}],["manifestação",{"2":{"541":1}}],["manifesto",{"2":{"259":1,"520":1}}],["manipulado",{"2":{"679":1}}],["manipuladora",{"2":{"95":1,"104":1}}],["manipuladores",{"0":{"252":1},"2":{"74":1,"217":1,"251":1,"252":1,"680":1,"691":1}}],["manipulador",{"0":{"320":1,"365":1},"2":{"53":1,"122":1,"252":1,"320":2,"321":1,"365":2,"366":1,"443":4,"544":1}}],["manipuladas",{"2":{"421":1,"441":1}}],["manipula",{"2":{"387":1}}],["manipular",{"2":{"94":1,"103":1,"116":1,"245":1}}],["manipulação",{"0":{"112":1},"1":{"113":1,"114":1,"115":1,"116":1,"117":1,"118":1,"119":1,"120":1,"121":1,"122":1,"123":1,"124":1},"2":{"63":1,"112":1,"426":1,"765":1}}],["mantê",{"2":{"682":1}}],["mantêm",{"2":{"512":1}}],["mantido",{"2":{"630":1}}],["manter",{"2":{"106":1,"111":1,"331":1,"491":1,"540":1,"548":1,"651":1,"673":1,"693":1,"726":1}}],["mantemos",{"2":{"90":1,"99":1}}],["mantém",{"2":{"35":1,"105":1,"245":1,"636":1,"696":1,"733":1}}],["maneiras",{"2":{"89":1,"95":1,"98":1,"104":1,"242":1,"321":1,"344":1,"366":1,"424":1,"447":1,"525":1,"561":1,"601":1,"610":1,"635":1,"644":1,"668":1,"670":1,"671":1,"683":1,"719":1}}],["maneira",{"2":{"43":1,"46":1,"51":1,"55":1,"65":1,"67":1,"77":1,"91":1,"100":1,"107":1,"110":1,"113":1,"134":2,"152":1,"156":1,"177":1,"184":1,"194":1,"212":1,"217":1,"222":1,"231":1,"242":1,"261":1,"313":1,"328":1,"358":1,"381":1,"402":1,"466":1,"490":1,"520":1,"532":1,"551":1,"553":1,"560":1,"565":1,"566":1,"582":1,"583":1,"584":1,"585":1,"586":1,"594":1,"629":1,"636":1,"639":1,"667":1,"670":1}}],["marcar",{"2":{"691":1}}],["marcadores",{"2":{"552":3,"553":2}}],["marcador",{"2":{"441":1}}],["marcados",{"2":{"142":1,"168":1,"203":1,"577":1}}],["marcado",{"2":{"11":2,"34":1,"129":1}}],["marcadas",{"2":{"141":1,"167":1,"202":1,"549":1}}],["marcada",{"2":{"3":1,"11":1,"34":1}}],["marcá",{"2":{"455":1,"692":1}}],["maru",{"2":{"345":1,"348":2}}],["margem",{"2":{"225":2,"247":1,"669":1}}],["margin=",{"2":{"404":1}}],["marginright",{"2":{"233":1}}],["marginbottom",{"2":{"224":2,"225":2,"226":2,"227":2,"228":2,"229":2,"230":2,"231":1,"233":2,"234":2,"245":1,"317":1,"362":1}}],["margintop",{"2":{"60":1,"114":2,"115":2,"224":1,"225":1,"226":1,"227":1,"228":1,"229":1,"230":1,"231":2,"232":1,"234":1,"573":1,"668":1}}],["marginhorizontal",{"2":{"53":2,"116":2,"224":1,"225":1,"226":1,"227":1,"228":1,"229":1,"230":1,"234":1}}],["marginvertical",{"2":{"53":1}}],["margin",{"2":{"46":1,"244":2,"277":1,"297":1,"317":1,"362":1,"737":1}}],["marque",{"2":{"142":2,"168":2,"203":2,"554":1}}],["mark",{"2":{"111":1,"443":1}}],["maroon",{"2":{"88":1}}],["marvin",{"2":{"38":3}}],["mas",{"0":{"728":1,"729":1},"2":{"22":1,"35":1,"39":1,"43":1,"46":1,"50":4,"55":1,"56":1,"57":2,"76":1,"85":1,"90":1,"99":1,"106":1,"111":2,"113":1,"122":2,"129":1,"131":1,"143":1,"151":1,"176":1,"193":1,"211":1,"217":1,"219":1,"227":1,"228":1,"235":1,"243":1,"245":1,"256":1,"263":1,"279":1,"299":1,"310":1,"337":1,"338":1,"348":1,"349":1,"355":1,"379":2,"381":1,"384":1,"403":1,"407":2,"413":1,"420":1,"427":1,"440":1,"441":1,"443":1,"445":2,"456":1,"462":1,"464":1,"465":2,"470":1,"486":1,"488":1,"491":1,"493":1,"531":2,"532":2,"535":1,"541":2,"551":2,"552":1,"566":1,"571":1,"574":1,"576":1,"587":1,"588":1,"603":1,"612":1,"629":2,"633":1,"634":1,"635":2,"636":1,"639":1,"646":1,"659":1,"662":1,"671":1,"672":1,"677":1,"678":1,"679":1,"682":1,"700":1,"717":1,"721":1,"730":1,"732":1,"735":1,"742":1,"745":1,"751":1}}],["maximumzoomscale",{"2":{"731":1}}],["maximumvalue=",{"2":{"692":1}}],["maxtorenderperbatch",{"0":{"500":1},"2":{"501":2}}],["maxheight",{"2":{"229":1,"230":1,"232":1}}],["max",{"2":{"13":2,"390":1,"715":1}}],["mercurial",{"2":{"728":1}}],["mercados",{"2":{"656":2}}],["mergulho",{"0":{"415":1}}],["mergulhar",{"2":{"238":1}}],["mergeconfig",{"2":{"398":2,"399":4,"577":2}}],["membro",{"2":{"425":1}}],["memória",{"0":{"42":1},"1":{"43":1,"44":1},"2":{"42":2,"43":5,"44":1,"349":1,"389":1,"455":1,"480":1,"488":1,"497":2,"499":1,"503":2,"539":1,"542":2,"572":1,"574":1,"636":1,"693":1,"695":1,"740":1}}],["meu",{"0":{"382":1,"383":1,"729":1},"2":{"555":1}}],["meta",{"2":{"687":1,"695":1}}],["metadados",{"2":{"338":1}}],["meteorológico",{"2":{"678":2}}],["meteorológicas",{"2":{"677":1}}],["methodqueue",{"2":{"491":5}}],["method",{"2":{"332":1,"390":2,"430":4,"431":1,"444":1,"479":7,"480":3,"488":4,"489":1,"491":1,"493":2,"519":1}}],["metroconfig",{"2":{"398":1}}],["metro",{"0":{"151":1,"176":1,"193":1,"211":1,"397":1,"398":1,"577":1},"1":{"398":1,"399":2},"2":{"151":4,"152":1,"176":4,"193":4,"194":1,"211":4,"212":1,"273":1,"280":1,"293":1,"300":1,"320":1,"322":1,"329":1,"365":1,"368":1,"397":1,"398":15,"399":5,"405":1,"458":1,"482":1,"516":1,"526":1,"566":1,"577":3,"586":1,"595":1,"596":1,"662":1,"663":1,"685":4,"686":1,"702":1,"739":1,"745":5,"755":1}}],["medo",{"2":{"249":1}}],["mede",{"2":{"122":1}}],["medimos",{"2":{"693":1}}],["medições",{"2":{"689":1}}],["medição",{"2":{"539":1,"690":3}}],["mediumvioletred",{"2":{"88":1}}],["mediumturquoise",{"2":{"88":1,"229":1,"230":1,"232":1}}],["mediumspringgreen",{"2":{"88":1}}],["mediumslateblue",{"2":{"88":1,"229":1,"230":1}}],["mediumseagreen",{"2":{"88":1,"229":1,"230":1,"232":1}}],["mediumpurple",{"2":{"88":1}}],["mediumorchid",{"2":{"88":1}}],["mediumblue",{"2":{"88":1}}],["mediumaquamarine",{"2":{"88":1}}],["medir",{"2":{"60":1,"553":1,"578":1,"689":1,"690":2}}],["medidas",{"2":{"120":2,"635":1,"690":1}}],["medida",{"2":{"45":1,"46":1,"64":1,"219":1,"261":1,"403":1,"458":1,"482":1,"503":1,"548":1,"555":1,"629":1,"668":1,"670":1,"671":1,"676":1}}],["measurespec",{"2":{"431":8}}],["measurement",{"2":{"122":1}}],["measurements",{"2":{"122":2}}],["measurelayout",{"0":{"122":1},"2":{"122":2}}],["measureinwindow",{"0":{"121":1},"2":{"690":2}}],["measure",{"0":{"120":1},"2":{"120":1,"122":11,"431":2}}],["means",{"2":{"68":1}}],["meça",{"0":{"578":1},"2":{"111":1}}],["mecanismos",{"2":{"90":1,"99":1,"107":1,"574":1}}],["mecanismo",{"2":{"65":1,"68":1,"77":1,"94":1,"95":1,"103":1,"104":1,"106":2,"389":3,"409":1,"495":1,"525":1,"740":1,"741":1,"746":1,"747":1,"749":1,"750":1}}],["mesclagem",{"2":{"721":2}}],["mesclado",{"2":{"398":1}}],["message",{"2":{"404":8,"427":3,"465":3,"522":1,"576":2}}],["messenger",{"2":{"51":1}}],["mesmas",{"2":{"228":1,"386":1}}],["mesma",{"2":{"35":2,"113":1,"114":1,"116":1,"158":1,"222":1,"231":1,"233":1,"242":1,"328":3,"333":1,"336":1,"377":1,"387":1,"402":1,"436":1,"452":1,"461":1,"477":2,"485":1,"491":3,"493":1,"509":1,"535":1,"540":1,"545":1,"603":1,"612":1,"618":1,"619":1,"620":1,"629":1,"636":1,"646":1,"668":1,"678":1,"682":1}}],["mesmos",{"2":{"339":1}}],["mesmo",{"0":{"541":1},"2":{"30":2,"47":1,"68":1,"90":1,"95":1,"96":1,"97":1,"99":1,"104":1,"105":1,"106":1,"112":1,"113":1,"115":1,"221":3,"261":1,"262":1,"328":1,"381":1,"385":1,"386":1,"387":1,"399":1,"420":1,"440":1,"443":1,"446":1,"462":2,"493":1,"523":1,"538":1,"544":1,"548":1,"568":1,"573":1,"577":1,"595":1,"616":2,"634":1,"635":1,"636":4,"679":1,"681":1,"690":1,"691":1,"699":1,"731":1}}],["melhorias",{"0":{"578":1},"2":{"539":1,"573":1,"687":1,"688":1,"691":1,"695":1}}],["melhores",{"0":{"249":1},"2":{"671":1}}],["melhorará",{"2":{"744":1}}],["melhorar",{"2":{"64":1,"113":1,"149":1,"498":1,"525":1,"552":1,"672":1,"695":1}}],["melhor",{"0":{"336":1,"461":1,"485":1},"2":{"39":1,"131":1,"143":1,"165":1,"183":1,"235":1,"328":1,"337":1,"379":1,"389":1,"441":1,"508":1,"509":1,"532":2,"535":1,"574":1,"675":1,"677":1,"682":1,"696":2,"731":1,"740":1}}],["mensagens",{"2":{"537":1}}],["mensagem",{"2":{"35":1,"43":1,"65":1,"128":1,"268":1,"288":1,"309":1,"354":1,"459":2,"465":4,"483":1,"522":2,"575":1}}],["mencionando",{"2":{"313":1,"358":1}}],["mencionadas",{"2":{"89":1,"98":1}}],["mencionada",{"2":{"69":1}}],["mencionado",{"2":{"63":1,"404":1,"545":1,"636":1}}],["menores",{"2":{"385":1,"476":1,"675":1,"676":1}}],["menor",{"2":{"110":1,"503":2,"506":1,"740":2}}],["menos",{"2":{"55":1,"60":1,"114":1,"255":1,"333":1,"336":1,"470":1,"479":2,"487":1,"491":2,"500":1,"501":3,"503":2,"540":1,"541":1,"552":1,"560":1,"571":1,"574":1,"662":1,"671":2,"678":1,"691":1,"692":1,"746":1,"747":1}}],["mente",{"0":{"58":1},"2":{"42":1,"55":1,"407":1}}],["menuitem",{"2":{"11":1,"34":1}}],["menus",{"2":{"11":1,"34":1,"241":1}}],["menubar",{"2":{"11":1,"34":1}}],["menu",{"0":{"126":1},"2":{"11":3,"34":3,"63":1,"74":3,"77":4,"126":3,"131":2,"133":1,"134":2,"135":3,"136":1,"153":1,"178":1,"185":2,"213":1,"216":1,"279":3,"299":3,"311":1,"312":2,"319":1,"320":1,"321":1,"356":1,"357":2,"364":1,"365":1,"366":1,"438":1,"439":1,"493":1,"526":3,"533":1,"547":3,"549":1,"551":2,"568":2,"570":1,"598":1,"602":1,"603":3,"607":1,"611":1,"612":3,"615":2,"616":1,"617":1,"618":1,"641":1,"645":1,"646":4,"745":1}}],["meio",{"2":{"35":1,"38":1,"39":2,"49":1,"50":1,"77":1,"105":1,"120":1,"121":1,"126":1,"128":1,"142":1,"168":1,"203":1,"243":1,"249":1,"318":1,"320":1,"328":1,"337":1,"363":1,"365":1,"389":1,"421":1,"423":1,"425":1,"436":1,"441":2,"442":1,"444":1,"448":2,"454":1,"455":1,"480":1,"491":1,"493":1,"529":1,"636":1,"680":1,"699":1,"709":1}}],["me",{"2":{"3":3,"10":1,"60":1,"113":2,"114":2,"115":2,"239":1,"244":3,"346":1,"349":3,"387":1,"444":1,"724":1,"731":1}}],[">react",{"2":{"731":1}}],[">red",{"2":{"668":1}}],[">framework",{"2":{"731":1}}],[">flexgrow",{"2":{"231":1}}],[">flexshrink",{"2":{"231":1}}],[">flexbasis",{"2":{"231":1}}],[">if",{"2":{"731":1}}],[">scrolling",{"2":{"731":1}}],[">scroll",{"2":{"731":1}}],[">bigblue",{"2":{"668":1}}],[">back",{"2":{"5":1}}],[">just",{"2":{"668":2}}],[">>>>>>>",{"2":{"722":1}}],[">>>",{"2":{"456":1}}],[">hello",{"2":{"277":1,"297":1}}],[">height",{"2":{"233":1}}],[">=",{"2":{"259":2,"278":2,"298":2}}],[">touchable",{"2":{"245":1}}],[">touchablewithoutfeedback",{"2":{"245":1}}],[">touchableopacity",{"2":{"245":1}}],[">touchablehighlight",{"2":{"245":1}}],[">what",{"2":{"731":1}}],[">where",{"2":{"122":2}}],[">width",{"2":{"233":1}}],[">drag",{"2":{"54":1}}],[">label",{"2":{"4":1,"26":1}}],[">press",{"2":{"3":1,"60":1}}],[">",{"2":{"2":1,"3":2,"4":1,"5":2,"8":1,"10":3,"26":1,"30":3,"35":1,"46":5,"53":9,"54":3,"56":1,"58":1,"60":4,"73":4,"92":1,"101":1,"113":3,"114":4,"115":5,"116":6,"122":6,"223":4,"224":11,"225":11,"226":11,"227":11,"228":11,"229":15,"230":15,"231":15,"232":14,"233":13,"234":13,"239":1,"242":3,"244":9,"245":12,"256":1,"259":12,"261":3,"262":4,"263":4,"272":2,"273":4,"277":1,"279":1,"292":2,"293":4,"297":1,"299":1,"317":4,"323":1,"328":5,"330":2,"331":2,"332":1,"333":1,"334":1,"338":1,"339":1,"346":1,"347":3,"348":7,"349":16,"362":4,"367":1,"369":1,"387":2,"403":1,"404":1,"427":1,"431":1,"434":1,"441":2,"442":3,"443":2,"444":8,"445":2,"456":1,"457":1,"463":1,"467":3,"481":1,"493":2,"511":2,"520":4,"562":2,"573":3,"668":1,"680":7,"681":1,"690":8,"692":5,"730":7,"731":25,"737":6}}],["nisso",{"2":{"542":1,"636":1}}],["nil",{"2":{"320":2,"365":2,"489":1,"492":2,"548":1}}],["núcleo",{"2":{"504":1,"553":1,"679":1}}],["números",{"2":{"349":1,"531":1}}],["número",{"2":{"51":1,"128":1,"222":1,"257":3,"261":1,"348":1,"349":1,"431":1,"462":1,"486":1,"500":1,"502":1,"503":1,"531":4,"533":1,"539":1,"564":1,"571":1,"575":1,"639":1,"660":1,"672":1,"692":1,"715":1,"730":1,"731":1}}],["n",{"2":{"317":1,"362":1,"486":1}}],["nvm",{"2":{"191":7,"200":1}}],["npm",{"0":{"470":1,"705":1,"712":1},"2":{"205":1,"268":1,"288":1,"328":1,"375":4,"379":3,"381":1,"383":2,"419":1,"447":3,"470":2,"538":1,"549":1,"567":2,"580":1,"605":1,"705":2,"716":1,"764":1}}],["npmyarn",{"2":{"152":1,"157":1,"176":1,"177":1,"193":1,"194":1,"211":1,"212":1,"268":2,"281":1,"288":2,"301":1,"309":2,"324":1,"325":1,"354":2,"370":1,"371":1,"376":1,"377":1,"378":1,"457":1,"481":1,"567":1,"600":1,"609":1,"624":1,"625":1,"626":1,"627":1,"643":1,"655":1,"704":1,"734":1,"739":1,"743":1,"744":1,"747":1,"748":1}}],["npx",{"2":{"144":2,"145":1,"157":1,"169":2,"170":1,"188":2,"190":1,"204":2,"205":1,"206":1,"283":1,"303":1,"377":1,"516":1,"527":1,"580":1,"685":1,"711":1,"726":1,"728":1}}],["nsnotification",{"2":{"490":1}}],["nsnull",{"2":{"488":1}}],["nsnumber",{"2":{"444":4,"480":1,"486":2,"488":4,"493":2}}],["nserror",{"2":{"488":1}}],["nsexception",{"2":{"488":1}}],["nsstring",{"2":{"479":4,"480":1,"488":8,"489":2,"490":1,"491":1,"493":2}}],["nsarray",{"2":{"444":1,"480":1,"486":1}}],["nsobject",{"2":{"365":1,"477":1,"493":2}}],["nsbundle",{"2":{"320":1,"365":1}}],["nslog",{"2":{"320":1,"365":1}}],["nsurlsessionconfiguration",{"2":{"524":4}}],["nsurlsession",{"0":{"524":1},"2":{"524":2}}],["nsurl",{"2":{"320":4,"365":2}}],["nsinteger",{"2":{"111":1,"444":1,"486":1,"488":1,"489":1}}],["ns",{"2":{"111":1}}],["nsdictionary",{"2":{"101":2,"365":1,"442":1,"444":1,"445":1,"480":1,"486":1,"487":1,"524":1}}],["ndk",{"2":{"67":1,"596":1}}],["nuvem",{"2":{"677":1}}],["nuances",{"2":{"464":1}}],["nulos",{"2":{"480":1}}],["nulo",{"2":{"424":1,"442":1,"465":1,"479":1}}],["nullish",{"2":{"390":1}}],["nullable",{"2":{"256":2,"424":2,"431":3,"466":1}}],["null>",{"2":{"122":1}}],["null",{"2":{"53":2,"54":1,"116":2,"122":6,"256":2,"259":4,"279":7,"299":2,"423":2,"424":1,"431":2,"434":1,"464":2,"467":9,"488":1,"573":3,"576":1,"667":1}}],["nunca",{"2":{"247":1,"417":1,"488":1,"571":1,"629":2,"635":1,"639":1,"669":1,"671":2}}],["numchars",{"2":{"737":3}}],["num",{"2":{"390":1}}],["numberwithint",{"2":{"488":2}}],["numbertilegame",{"2":{"313":1}}],["number",{"2":{"122":4,"232":6,"233":2,"342":2,"383":1,"390":2,"426":1,"442":4,"462":6,"486":5,"500":1,"501":1,"502":1,"503":1,"531":3,"598":1,"607":1,"641":1,"737":2}}],["numérico",{"2":{"46":1}}],["numa",{"2":{"24":1}}],["nível",{"0":{"273":1,"293":1},"2":{"52":1,"65":1,"68":1,"92":1,"101":1,"111":1,"149":1,"174":1,"209":1,"236":1,"253":1,"259":2,"270":1,"273":1,"278":2,"290":1,"293":1,"298":2,"477":1,"507":1,"516":1,"520":1,"551":1,"560":1,"573":1,"677":2,"681":1,"688":1}}],["needsexpensive",{"2":{"573":3}}],["needoffscreenalphacompositing",{"2":{"559":1}}],["nelas",{"2":{"347":1}}],["neles",{"2":{"114":1,"442":1,"635":1}}],["nele",{"2":{"32":1,"35":2,"114":1,"221":1,"325":1,"371":1,"483":1,"682":1,"725":1}}],["nexus",{"2":{"328":1,"554":1}}],["next",{"2":{"141":1,"149":2,"167":1,"174":2,"202":1,"209":2,"549":1}}],["netinfo",{"2":{"259":3,"383":1}}],["net",{"2":{"259":7}}],["networkinfo",{"2":{"259":2}}],["networkcapabilities",{"2":{"259":14}}],["networkchangereceiver",{"2":{"259":3}}],["network",{"2":{"238":1,"259":2,"313":1,"603":1}}],["necessidades",{"2":{"257":1,"386":1,"470":1,"518":1,"549":1}}],["necessidade",{"2":{"89":1,"98":1,"328":1,"491":1,"509":1,"552":1,"577":1,"629":2}}],["necessárias",{"2":{"137":1,"164":1,"182":1,"184":1,"199":1,"268":1,"288":1,"309":1,"354":1,"402":1,"404":1,"493":1,"549":1,"550":1,"572":1,"581":1,"596":1,"605":1,"648":1}}],["necessária",{"2":{"71":1,"135":1,"257":1,"463":1,"469":1,"487":1,"495":1,"532":1,"542":1,"681":1,"723":1,"740":1}}],["necessários",{"2":{"37":1,"398":1,"402":2,"534":1,"571":1,"576":1,"577":1,"596":1}}],["necessário",{"2":{"13":1,"48":1,"60":2,"73":1,"112":1,"116":1,"131":1,"140":1,"145":1,"170":1,"189":1,"201":1,"205":1,"230":1,"231":1,"248":1,"272":1,"273":1,"276":2,"278":1,"292":1,"293":1,"296":2,"298":1,"316":2,"328":2,"339":1,"344":1,"361":2,"399":2,"406":1,"407":1,"421":1,"428":1,"441":1,"456":1,"461":1,"466":2,"479":1,"485":1,"490":1,"491":1,"495":1,"524":2,"533":2,"535":1,"554":1,"565":1,"570":1,"573":2,"576":1,"585":1,"595":1,"615":1,"629":1,"652":1,"654":1,"662":1,"663":1,"666":1,"699":1,"721":1}}],["negócio",{"2":{"682":1}}],["negócios",{"2":{"534":1,"670":1,"673":2,"679":1}}],["negligenciada",{"2":{"628":1}}],["negligência",{"2":{"68":1}}],["negociação",{"2":{"251":1}}],["negociem",{"2":{"248":1}}],["negrito",{"2":{"241":1}}],["negada",{"2":{"278":1,"298":1}}],["negativa",{"2":{"247":1,"669":1}}],["negativo",{"2":{"231":1}}],["negação",{"2":{"50":1}}],["nem",{"2":{"57":1,"94":1,"103":1,"407":1,"413":1,"545":1,"678":2,"682":1}}],["nenhuma",{"2":{"71":1,"257":1,"334":1,"341":1,"469":1,"491":1,"538":1,"545":1,"556":1,"580":1,"581":1,"631":1,"708":1,"739":1,"740":1}}],["nenhum",{"2":{"56":1,"111":1,"234":1,"245":2,"328":1,"334":1,"399":1,"404":1,"478":1,"479":1,"493":1,"529":1,"589":1,"672":1,"673":1,"679":1,"689":1}}],["nesses",{"2":{"458":1,"482":1,"635":1}}],["nesse",{"2":{"56":1,"217":2,"218":2,"220":1,"407":1,"421":1,"424":2,"444":1,"533":1,"555":1,"556":2,"662":1,"681":1}}],["neste",{"2":{"15":1,"24":1,"41":1,"46":1,"93":1,"96":1,"97":1,"102":1,"105":1,"106":1,"108":1,"110":1,"149":1,"174":1,"209":1,"225":1,"242":2,"244":1,"284":1,"304":1,"326":1,"338":1,"349":3,"372":1,"421":1,"422":1,"426":1,"444":2,"457":1,"459":1,"477":1,"481":1,"483":1,"493":1,"531":1,"555":3,"556":2,"568":1,"608":2,"619":1,"628":1,"667":1,"670":1,"674":1,"691":1}}],["nesta",{"2":{"10":3,"27":3,"379":1,"404":1,"443":1,"525":1,"532":1,"656":1,"721":1,"741":2}}],["newvalue",{"2":{"692":2}}],["newmodulebutton",{"2":{"457":5,"459":1,"481":5}}],["newdraweecontrollerbuilder",{"2":{"423":2}}],["newtext",{"2":{"242":2}}],["newframe",{"2":{"111":3}}],["new",{"2":{"46":1,"49":1,"53":2,"54":1,"74":1,"77":1,"92":4,"256":3,"257":3,"259":1,"278":1,"279":3,"402":2,"404":4,"423":1,"425":1,"429":1,"430":1,"431":3,"432":1,"433":2,"443":1,"456":5,"462":1,"463":3,"464":1,"465":1,"466":1,"467":2,"487":1,"488":1,"489":1,"493":1,"521":1,"522":1,"576":1,"748":1}}],["nós",{"2":{"156":1,"310":1,"355":1,"531":7,"680":1,"695":1}}],["nó",{"2":{"3":1,"112":2,"224":1,"233":1,"251":1,"252":1,"531":1,"587":1,"619":1}}],["não",{"0":{"129":1,"337":1,"540":1,"544":1,"707":1,"709":1,"714":1,"728":1},"1":{"715":1,"716":1},"2":{"2":1,"5":1,"7":1,"9":1,"10":1,"11":2,"12":8,"13":2,"14":1,"22":1,"27":1,"29":1,"31":2,"33":1,"34":2,"35":2,"36":1,"38":1,"39":1,"42":1,"43":4,"55":1,"57":4,"58":2,"60":1,"62":1,"63":1,"65":3,"67":2,"68":1,"69":2,"74":5,"77":3,"86":1,"92":3,"94":3,"95":1,"96":2,"101":2,"103":3,"104":1,"105":2,"106":1,"110":2,"111":5,"112":2,"113":3,"114":4,"119":2,"120":2,"128":1,"129":1,"130":1,"131":2,"134":1,"135":2,"145":1,"152":1,"156":1,"161":1,"162":1,"170":1,"177":1,"189":1,"194":1,"202":1,"205":1,"209":1,"212":1,"217":3,"218":2,"219":1,"221":4,"227":2,"233":1,"234":2,"245":3,"247":1,"251":2,"255":1,"257":2,"259":4,"261":4,"262":4,"263":3,"270":2,"273":5,"278":1,"279":4,"283":3,"288":1,"290":2,"293":4,"299":4,"303":3,"310":1,"323":1,"328":4,"329":3,"330":1,"331":1,"334":3,"336":2,"337":2,"338":2,"339":1,"341":2,"345":2,"349":1,"355":1,"369":1,"374":2,"377":1,"379":2,"381":2,"382":1,"389":1,"399":2,"402":2,"404":2,"407":1,"413":1,"417":1,"419":1,"420":2,"424":1,"440":2,"441":3,"443":1,"444":1,"446":3,"448":2,"455":2,"456":3,"458":1,"461":1,"462":3,"463":2,"464":2,"465":3,"469":1,"477":1,"478":3,"479":2,"480":2,"482":1,"485":1,"486":1,"487":4,"488":2,"490":1,"491":7,"493":2,"497":2,"499":2,"511":1,"512":1,"515":1,"520":2,"521":1,"523":3,"529":3,"531":1,"532":3,"533":1,"534":3,"535":2,"540":1,"541":1,"542":2,"544":1,"545":2,"547":1,"550":1,"551":1,"552":1,"554":1,"555":1,"556":1,"557":1,"559":1,"560":1,"562":1,"563":1,"566":2,"571":1,"574":3,"575":1,"577":2,"580":1,"581":1,"586":2,"593":1,"595":1,"596":1,"605":2,"616":1,"628":1,"629":6,"630":5,"631":1,"632":1,"633":1,"634":1,"635":6,"636":3,"638":1,"639":1,"651":1,"652":1,"654":2,"656":2,"657":1,"658":1,"662":2,"666":3,"667":2,"669":2,"670":1,"671":1,"672":1,"673":1,"675":3,"677":2,"678":2,"679":3,"680":2,"681":2,"682":5,"685":1,"686":1,"690":1,"695":2,"696":1,"699":4,"701":1,"708":1,"721":1,"726":2,"728":2,"730":1,"731":2,"735":1,"742":2,"745":1,"747":1}}],["naquele",{"2":{"531":1,"545":1}}],["nada",{"2":{"145":1,"170":1,"205":1,"227":1,"635":1,"728":1}}],["natureza",{"2":{"56":1}}],["nativamente",{"2":{"471":1,"574":1}}],["nativa",{"0":{"144":1,"169":1,"188":1,"204":1,"558":1,"693":1},"1":{"559":1,"560":1},"2":{"69":1,"73":1,"74":1,"76":1,"77":3,"94":2,"95":1,"96":1,"103":2,"104":1,"105":1,"106":3,"111":1,"112":1,"114":2,"115":1,"119":1,"121":1,"318":1,"363":1,"422":2,"426":1,"427":1,"428":1,"443":1,"446":2,"458":2,"464":1,"471":1,"482":2,"488":2,"495":1,"499":1,"532":1,"534":1,"558":1,"562":1,"657":1,"693":1,"695":1}}],["nativas",{"0":{"97":1,"106":1,"444":1,"566":1},"2":{"63":1,"66":1,"67":1,"70":2,"95":1,"104":1,"106":2,"108":1,"110":1,"111":1,"334":1,"378":1,"409":1,"421":2,"441":2,"442":1,"445":1,"446":2,"448":3,"458":1,"482":1,"499":1,"556":1,"636":1}}],["nativos",{"0":{"95":1,"96":1,"97":1,"104":1,"105":1,"106":1,"119":1,"271":1,"291":1,"384":1,"386":1,"406":1,"419":1,"420":1,"436":1,"440":1,"446":1,"449":1,"470":1,"474":1,"477":1,"764":1,"765":1},"1":{"96":1,"97":1,"105":1,"106":1,"120":1,"121":1,"122":1,"123":1,"124":1,"272":1,"385":1,"386":1,"387":1,"421":1,"422":1,"423":1,"424":1,"425":1,"426":1,"427":1,"428":1,"429":1,"430":1,"431":1,"432":1,"433":1,"434":1,"441":1,"442":1,"443":1,"444":1,"445":1,"447":1,"448":1,"450":1,"451":1,"452":1,"453":1,"454":1,"455":1,"456":1,"457":1,"458":1,"459":1,"460":1,"461":1,"462":1,"463":1,"464":1,"465":1,"466":1,"467":1,"468":1,"469":1,"475":1,"476":1,"477":1,"478":1,"479":1,"480":1,"481":1,"482":1,"483":1,"484":1,"485":1,"486":1,"487":1,"488":1,"489":1,"490":1,"491":1,"492":1,"493":1,"494":1,"495":1},"2":{"89":2,"90":1,"93":1,"95":1,"97":2,"98":2,"99":1,"102":1,"104":1,"106":4,"236":1,"278":1,"285":1,"298":1,"384":1,"386":3,"400":1,"406":1,"407":1,"419":3,"420":2,"425":1,"431":1,"437":2,"440":2,"441":1,"445":1,"446":1,"448":1,"449":4,"452":2,"453":1,"454":1,"455":1,"456":6,"461":1,"462":1,"464":1,"465":1,"466":1,"469":1,"470":4,"473":1,"474":4,"480":1,"485":1,"486":2,"488":1,"489":1,"490":1,"491":1,"492":1,"493":1,"495":1,"521":1,"545":1,"560":1,"569":1,"691":1,"693":1,"700":1,"753":1,"764":4,"765":2}}],["nativo",{"0":{"56":1,"89":1,"98":1,"108":1,"109":1,"377":1,"378":1,"408":1,"435":1,"437":1,"447":1,"450":1,"452":1,"454":1,"460":1,"461":1,"475":1,"479":1,"484":1,"485":1},"1":{"90":1,"91":1,"92":1,"93":1,"94":1,"95":1,"96":1,"97":1,"99":1,"100":1,"101":1,"102":1,"103":1,"104":1,"105":1,"106":1,"107":1,"108":1,"109":1,"110":2,"111":2,"409":1,"410":1,"411":1,"412":1,"413":1,"436":1,"437":1,"438":2,"439":2,"451":1,"452":1,"455":1,"461":1,"462":1,"463":1,"485":1,"486":1,"487":1},"2":{"2":1,"37":1,"53":1,"55":1,"56":10,"57":1,"63":1,"65":1,"77":3,"89":1,"91":2,"95":2,"98":1,"100":2,"101":2,"102":1,"104":2,"105":2,"106":1,"107":1,"110":1,"111":2,"114":4,"120":1,"142":2,"159":2,"168":2,"203":2,"256":1,"265":1,"274":1,"279":1,"283":3,"287":1,"294":1,"299":1,"303":3,"306":1,"311":1,"314":1,"320":1,"325":2,"342":1,"351":1,"356":1,"359":1,"365":1,"371":2,"376":1,"377":1,"389":1,"400":1,"406":2,"407":1,"409":1,"411":1,"413":2,"419":1,"420":3,"426":1,"427":2,"428":1,"435":2,"437":4,"440":3,"441":1,"442":1,"443":1,"444":3,"445":5,"446":2,"447":4,"448":4,"449":1,"450":1,"451":1,"452":5,"453":3,"454":2,"455":1,"456":7,"457":11,"458":2,"459":5,"461":7,"462":2,"463":6,"464":9,"465":3,"466":1,"469":1,"470":3,"474":1,"475":2,"476":1,"477":6,"478":5,"479":3,"480":1,"481":11,"482":2,"483":6,"485":7,"486":2,"487":3,"488":2,"489":1,"490":1,"491":7,"495":1,"532":1,"534":3,"545":1,"546":1,"552":1,"555":1,"604":1,"613":1,"622":1,"635":1,"636":1,"647":1,"656":2,"677":1,"679":1,"691":2,"693":1,"699":2,"760":1,"767":1,"768":1}}],["nativecall",{"2":{"555":1}}],["nativecalendarmodule",{"2":{"485":4}}],["nativecomponent",{"2":{"444":1}}],["nativecomponente",{"2":{"444":1}}],["nativeview",{"2":{"444":3}}],["nativeviewhierarchymanager",{"2":{"421":1}}],["native`",{"2":{"313":1,"358":1}}],["nativeanimation",{"2":{"313":1}}],["nativeanimationsexample",{"2":{"59":1}}],["nativemodule>",{"2":{"456":3}}],["nativemodule",{"2":{"446":1,"452":3,"456":2,"487":1}}],["nativemodules",{"2":{"60":2,"453":1,"456":1,"457":5,"461":5,"466":2,"478":2,"481":5,"485":5}}],["nativemethodsmixin",{"2":{"113":1}}],["nativeeventemitter",{"2":{"466":3,"490":1}}],["nativeevent",{"2":{"35":1,"52":3,"53":1,"56":1,"251":1,"427":1,"443":1}}],["nativeid=",{"2":{"4":1,"26":1}}],["nativeid",{"2":{"4":2,"26":1}}],["native",{"0":{"89":1,"92":2,"93":2,"96":1,"97":1,"98":1,"101":2,"102":2,"105":1,"106":1,"108":1,"109":1,"110":1,"111":1,"150":1,"158":1,"159":1,"175":1,"192":1,"210":1,"269":1,"275":1,"277":1,"289":1,"295":1,"297":1,"311":1,"315":1,"317":1,"356":1,"360":1,"362":1,"381":1,"383":1,"401":1,"402":1,"403":1,"404":1,"473":1,"515":1,"568":1,"579":1,"658":1,"707":1,"711":1,"714":1,"719":1,"720":1,"728":1,"736":1,"737":1,"746":1,"752":1},"1":{"90":1,"91":1,"92":1,"93":1,"94":1,"95":1,"96":1,"97":1,"99":1,"100":1,"101":1,"102":1,"103":1,"104":1,"105":1,"106":1,"107":1,"108":1,"109":1,"110":2,"111":2,"151":1,"152":1,"160":1,"161":1,"162":1,"176":1,"177":1,"178":1,"193":1,"194":1,"211":1,"212":1,"270":1,"290":1,"296":1,"297":1,"298":1,"580":1,"581":1,"582":1,"583":1,"584":1,"585":1,"586":1,"587":1,"588":1,"589":1,"590":1,"591":1,"592":1,"593":1,"594":1,"595":1,"596":1,"712":1,"713":1,"715":1,"716":1,"721":1,"722":1,"747":1,"748":1,"753":1,"754":1,"755":1,"756":1,"757":1,"758":1,"759":1,"760":1,"761":1,"762":1,"763":1,"764":1,"765":1,"766":1,"767":1,"768":1,"769":1},"2":{"0":2,"2":1,"37":1,"40":1,"43":3,"44":2,"45":1,"46":2,"53":1,"54":1,"56":1,"60":1,"64":3,"65":2,"67":2,"68":1,"71":1,"73":1,"75":1,"76":4,"79":1,"80":1,"82":1,"83":1,"84":1,"85":1,"86":2,"89":2,"90":3,"91":2,"92":3,"93":2,"95":3,"96":2,"97":1,"98":2,"99":3,"100":2,"101":6,"102":2,"104":3,"105":3,"106":4,"107":1,"110":4,"111":9,"112":1,"113":1,"114":4,"115":2,"116":2,"119":1,"122":2,"126":1,"128":1,"131":1,"137":2,"139":1,"142":2,"144":2,"145":9,"146":3,"147":1,"151":2,"152":1,"154":1,"155":3,"156":5,"157":1,"159":1,"164":2,"168":2,"169":2,"170":9,"171":3,"172":1,"176":2,"179":1,"180":3,"182":2,"188":2,"189":9,"190":5,"191":1,"193":2,"194":1,"197":1,"198":3,"199":2,"200":1,"203":2,"204":2,"205":9,"206":3,"207":1,"211":2,"212":1,"214":1,"215":3,"216":2,"222":1,"223":1,"224":1,"225":2,"226":1,"227":1,"228":2,"229":1,"230":1,"231":2,"232":1,"233":2,"234":1,"236":2,"238":1,"239":1,"240":1,"241":2,"242":1,"243":1,"244":1,"245":2,"247":1,"255":2,"261":2,"262":1,"263":1,"265":6,"266":2,"267":1,"268":5,"270":7,"271":4,"274":1,"275":1,"276":3,"277":1,"278":1,"279":4,"280":1,"281":1,"283":4,"284":1,"285":2,"287":6,"288":8,"290":7,"291":4,"294":1,"295":1,"296":3,"297":1,"298":1,"299":4,"300":1,"301":1,"303":4,"304":1,"306":7,"307":2,"308":1,"309":5,"310":1,"311":1,"313":37,"314":2,"315":1,"316":3,"317":2,"318":2,"319":1,"320":8,"322":1,"324":1,"325":2,"326":1,"328":1,"330":1,"336":1,"337":1,"338":1,"341":1,"342":1,"343":2,"344":3,"345":4,"346":3,"347":2,"348":4,"349":3,"351":7,"352":2,"353":1,"354":5,"355":1,"356":1,"358":8,"359":2,"360":1,"361":3,"362":2,"363":2,"364":1,"365":8,"368":1,"370":1,"371":3,"372":1,"374":3,"375":2,"376":3,"377":2,"378":1,"379":12,"381":2,"382":1,"383":2,"384":3,"386":8,"387":4,"389":4,"390":4,"397":1,"398":5,"399":3,"400":3,"401":1,"402":2,"403":4,"404":3,"405":3,"406":1,"407":1,"409":2,"414":1,"416":1,"417":3,"418":1,"419":3,"420":5,"426":1,"428":1,"429":2,"431":3,"434":2,"436":2,"437":1,"438":1,"440":5,"441":3,"442":2,"444":2,"445":1,"446":4,"447":4,"448":6,"449":2,"451":2,"452":2,"455":1,"456":4,"457":6,"458":1,"459":1,"461":3,"462":3,"465":2,"466":1,"470":8,"471":3,"473":3,"474":2,"476":2,"478":2,"479":3,"480":1,"481":6,"482":1,"483":1,"485":4,"486":3,"487":1,"488":1,"491":3,"492":1,"493":2,"497":1,"508":1,"512":2,"513":4,"514":6,"515":1,"516":11,"518":1,"520":2,"521":1,"522":1,"523":2,"524":1,"525":4,"527":2,"531":1,"532":3,"534":1,"546":1,"548":1,"549":1,"552":1,"553":1,"555":3,"560":1,"561":1,"562":5,"563":1,"564":1,"565":2,"566":7,"572":1,"573":2,"574":6,"577":1,"579":2,"580":4,"581":1,"582":1,"583":3,"584":3,"585":3,"593":1,"595":1,"596":5,"599":1,"600":1,"603":1,"604":1,"605":1,"608":1,"609":1,"612":1,"613":1,"622":1,"624":1,"629":2,"630":2,"631":1,"634":4,"636":3,"642":1,"643":1,"646":1,"647":1,"648":1,"654":1,"657":1,"658":1,"660":2,"663":3,"665":2,"666":6,"667":6,"668":2,"669":2,"672":1,"674":1,"679":3,"680":1,"681":1,"682":3,"683":1,"684":1,"685":3,"687":5,"688":2,"691":1,"693":1,"694":1,"695":2,"696":2,"698":1,"700":1,"701":1,"705":1,"706":2,"707":1,"709":3,"711":2,"717":1,"718":2,"719":3,"720":1,"721":3,"722":3,"725":2,"726":4,"728":2,"729":1,"730":4,"731":2,"732":1,"733":1,"734":5,"735":1,"736":1,"737":1,"739":3,"740":2,"741":6,"745":1,"746":7,"747":2,"748":2,"749":1,"751":3,"767":2,"768":1}}],["name>",{"2":{"553":1,"602":1,"611":1,"645":1}}],["name=",{"2":{"73":1,"256":1,"259":2,"272":2,"279":1,"292":2,"299":1,"348":6,"349":6,"402":1}}],["namespaces",{"2":{"477":1}}],["namespace",{"2":{"96":1,"97":1,"105":1,"106":1,"328":1}}],["names",{"2":{"68":1,"431":2}}],["name",{"2":{"35":6,"256":2,"268":1,"279":1,"283":4,"288":1,"299":1,"303":4,"309":1,"313":2,"317":2,"320":2,"345":3,"346":1,"348":3,"349":3,"354":1,"362":2,"365":2,"383":1,"390":6,"402":1,"424":6,"452":5,"454":7,"456":7,"461":3,"463":7,"464":8,"465":2,"479":3,"480":1,"485":3,"487":3,"490":2,"493":2,"529":1,"531":2,"549":1,"553":2,"650":1,"704":1,"722":1,"737":3}}],["navigatorios",{"2":{"535":1}}],["navigator",{"2":{"534":1,"535":1,"541":1,"545":1,"559":1,"616":1,"621":1}}],["navigation",{"0":{"473":1},"2":{"417":1,"471":4,"472":2,"473":3,"545":2}}],["navigates",{"2":{"5":1}}],["navegue",{"2":{"268":1,"288":1,"309":1,"354":1,"376":1,"526":1,"549":1,"615":1,"651":1,"745":1}}],["navegações",{"2":{"473":1}}],["navegação",{"0":{"472":1},"2":{"11":1,"31":1,"34":1,"74":1,"77":2,"279":1,"299":1,"471":7,"472":1,"473":1,"553":1}}],["navegando",{"0":{"471":1},"1":{"472":1,"473":1},"2":{"757":1}}],["navegará",{"2":{"470":1}}],["navegar",{"2":{"189":1,"241":1}}],["navega",{"2":{"77":1}}],["navegadores",{"2":{"239":1,"379":1,"554":1}}],["navegador",{"0":{"392":1,"545":1},"2":{"62":1,"112":1,"156":1,"239":1,"337":2,"471":1,"553":1,"554":2,"698":1,"745":1}}],["navy",{"2":{"88":1}}],["navajowhite",{"2":{"88":1}}],["nas",{"0":{"382":1},"2":{"6":1,"14":1,"28":1,"96":1,"105":1,"191":1,"272":1,"292":1,"345":1,"358":1,"448":2,"531":2,"537":1,"538":1,"546":1,"608":1,"648":1,"706":1,"708":1,"730":1}}],["na",{"0":{"542":1,"546":1,"648":1,"703":1,"708":1},"1":{"547":1,"548":1,"549":1,"550":1,"649":1,"650":1,"651":1,"652":1,"653":1,"654":1,"655":1,"656":1,"657":1,"658":1,"659":1,"712":1,"713":1},"2":{"2":1,"3":1,"10":1,"14":3,"15":2,"24":2,"31":1,"35":1,"38":1,"39":2,"46":1,"47":1,"48":1,"53":1,"56":1,"57":1,"63":1,"65":3,"67":1,"68":1,"71":1,"73":2,"74":1,"76":2,"77":2,"79":1,"90":1,"92":1,"99":1,"110":1,"111":3,"112":1,"115":1,"118":1,"119":1,"120":3,"121":1,"128":2,"142":2,"151":1,"168":2,"176":1,"191":1,"193":1,"200":1,"203":2,"211":1,"218":2,"220":1,"221":1,"222":1,"223":1,"224":3,"225":1,"226":1,"229":2,"231":1,"238":1,"245":2,"250":1,"251":2,"252":1,"255":1,"259":4,"260":1,"261":1,"262":2,"263":1,"268":1,"271":1,"276":1,"278":1,"288":1,"291":1,"296":1,"298":1,"309":1,"313":1,"316":1,"318":1,"321":1,"325":1,"328":2,"330":2,"341":3,"344":2,"345":1,"347":1,"349":1,"354":1,"358":1,"361":1,"363":1,"366":1,"375":1,"377":1,"384":1,"385":1,"387":2,"389":1,"402":1,"403":1,"404":1,"405":1,"407":2,"409":1,"414":1,"420":2,"424":1,"425":1,"436":1,"438":1,"439":2,"440":2,"441":1,"442":1,"443":2,"444":2,"447":1,"457":1,"458":1,"461":1,"466":1,"470":1,"477":2,"479":1,"481":1,"482":1,"483":1,"485":1,"493":1,"497":2,"502":1,"508":1,"514":1,"519":1,"523":1,"528":1,"529":1,"531":5,"533":2,"534":4,"538":1,"547":2,"548":2,"549":6,"551":2,"554":2,"556":1,"558":1,"559":2,"562":1,"563":1,"565":1,"572":2,"575":1,"576":2,"577":3,"589":1,"592":1,"598":2,"599":2,"601":1,"603":1,"604":1,"607":2,"608":2,"609":1,"610":1,"612":1,"613":1,"615":2,"617":1,"618":1,"619":2,"620":1,"622":2,"635":2,"636":6,"641":2,"642":1,"643":1,"644":1,"646":1,"647":1,"648":1,"652":1,"653":1,"654":1,"655":1,"659":1,"660":3,"663":1,"664":1,"667":1,"668":1,"669":1,"671":2,"674":1,"675":1,"679":1,"680":2,"681":2,"682":4,"688":1,"690":1,"693":2,"695":1,"700":2,"702":1,"703":1,"704":1,"715":1,"721":1,"723":1,"724":1,"725":1,"726":2,"730":1,"731":2,"734":1,"739":1,"742":1,"745":4,"746":2,"748":1,"767":1,"768":1}}],["noindex",{"2":{"663":2}}],["nougat",{"2":{"563":1}}],["nonatomic",{"2":{"443":1}}],["nonnull",{"2":{"429":2,"431":2,"444":3,"493":1}}],["none",{"2":{"10":2,"11":1,"34":1}}],["noactionbar",{"2":{"279":2,"299":2}}],["nodeexecutableandargs",{"0":{"587":1}}],["nodehttps",{"2":{"200":1}}],["nodejs",{"0":{"566":1},"2":{"200":2,"566":1}}],["node",{"0":{"138":1,"165":1,"183":1,"200":1},"2":{"134":2,"137":1,"138":1,"144":1,"145":1,"156":1,"164":1,"165":4,"169":1,"170":1,"182":1,"183":4,"188":1,"191":6,"199":1,"200":7,"204":1,"205":1,"268":2,"270":1,"271":2,"288":2,"290":1,"291":2,"309":2,"313":31,"320":1,"354":2,"358":2,"365":1,"375":2,"379":1,"381":1,"464":1,"488":1,"574":4,"583":2,"584":2,"585":2,"587":2,"660":1,"663":2,"679":1,"705":1,"706":1,"722":2}}],["noções",{"0":{"125":1},"1":{"126":1,"127":1,"128":1,"129":1,"130":1,"131":1,"132":1,"133":1,"134":1,"135":1,"136":1},"2":{"760":1}}],["notou",{"2":{"556":1}}],["notifications",{"2":{"660":1}}],["notification",{"2":{"490":2}}],["notificar",{"2":{"424":1}}],["notificação",{"2":{"128":2,"251":1}}],["notificações",{"2":{"77":1,"128":4,"254":1,"490":1}}],["not",{"2":{"129":1,"256":2,"259":2,"298":1,"313":1,"467":6}}],["notation",{"2":{"390":1}}],["notado",{"2":{"115":1,"349":1}}],["nota",{"2":{"92":1,"141":1,"142":1,"167":1,"168":1,"177":1,"190":1,"202":1,"203":1,"209":1,"299":1,"303":1,"310":1,"313":1,"317":1,"320":2,"325":1,"348":1,"358":2,"362":1,"365":1,"652":2,"746":2}}],["notação",{"2":{"82":1,"83":1,"84":1}}],["notaram",{"2":{"535":1}}],["notará",{"2":{"67":1,"113":1,"533":1,"545":1,"692":1}}],["notar",{"2":{"64":1,"452":1,"456":1,"534":1,"691":1}}],["notas",{"0":{"61":1,"240":1,"347":1,"686":1},"1":{"62":1,"63":1},"2":{"630":1,"726":1}}],["normais",{"2":{"56":1,"218":1}}],["normaldot",{"2":{"53":2}}],["normalmente",{"2":{"47":1,"50":1,"97":1,"106":1,"112":1,"113":1,"222":1,"262":1,"282":1,"284":1,"302":1,"304":1,"325":1,"326":1,"328":1,"347":1,"371":1,"372":1,"375":1,"381":1,"383":1,"421":1,"427":1,"441":1,"443":1,"471":1,"666":1,"668":1,"675":1,"681":1,"745":2,"747":1,"748":1}}],["normal",{"2":{"42":1,"55":1,"234":2,"446":1,"571":1}}],["novas",{"0":{"257":1,"560":1,"717":1},"1":{"718":1,"719":1,"720":1,"721":1,"722":1,"723":1,"724":1,"725":1,"726":1,"727":1,"728":1,"729":1},"2":{"77":1,"92":2,"101":2,"221":1,"257":3,"328":1,"443":1,"560":1,"671":1,"691":3,"717":1,"746":1,"755":1}}],["nova",{"0":{"687":1,"688":1,"695":1,"696":1,"697":1},"1":{"688":1,"689":2,"690":1,"691":1,"692":1,"693":1,"694":1,"695":1,"696":1,"697":2},"2":{"55":1,"64":1,"74":1,"77":2,"112":2,"113":1,"131":1,"203":3,"221":1,"257":6,"267":1,"268":1,"275":1,"288":2,"295":1,"308":1,"309":1,"315":1,"318":1,"320":1,"353":1,"354":1,"360":1,"363":1,"365":1,"377":1,"378":1,"390":1,"402":1,"420":2,"426":1,"440":2,"443":1,"446":2,"449":2,"456":1,"470":2,"474":2,"490":1,"508":1,"534":2,"545":3,"558":1,"560":1,"596":4,"658":1,"687":4,"688":2,"689":1,"690":1,"691":2,"693":3,"694":2,"695":4,"696":3,"697":3,"704":1,"718":1,"726":1,"741":1,"748":1,"769":1}}],["novamente",{"0":{"540":1},"2":{"46":1,"63":1,"69":1,"92":1,"101":1,"113":1,"117":1,"203":2,"217":2,"218":2,"221":2,"349":2,"456":1,"491":1,"508":1,"526":1,"540":2,"608":1,"629":1,"671":1,"681":1,"693":1,"711":1,"729":1}}],["novos",{"2":{"76":1,"92":1,"97":1,"106":1,"285":1,"346":1,"493":1,"539":1,"580":1,"595":1,"671":1,"691":1,"695":2,"732":1,"733":1,"734":1,"735":1}}],["novo",{"0":{"145":1,"170":1,"189":1,"205":1},"2":{"46":1,"49":1,"131":1,"135":1,"140":1,"145":2,"146":1,"149":1,"152":2,"155":1,"156":1,"157":1,"170":2,"171":1,"174":1,"177":1,"180":1,"189":2,"190":1,"194":2,"198":1,"201":1,"203":2,"205":2,"206":1,"209":1,"212":2,"215":1,"238":1,"242":1,"268":1,"278":1,"285":1,"288":1,"298":1,"309":1,"318":1,"319":1,"321":2,"354":1,"363":1,"364":1,"366":2,"402":1,"403":1,"404":1,"457":1,"461":1,"464":1,"470":1,"477":1,"481":1,"485":1,"539":1,"545":1,"558":1,"570":1,"624":1,"666":1,"667":1,"726":1,"742":1}}],["nowrap",{"2":{"230":1}}],["now",{"2":{"13":4}}],["nomeie",{"2":{"477":1}}],["nomeados",{"2":{"313":1,"358":1}}],["nomeadas",{"0":{"86":1},"1":{"87":1,"88":1},"2":{"88":1}}],["nomes",{"0":{"494":1},"1":{"495":1},"2":{"68":1,"76":1,"86":3,"96":1,"97":1,"105":1,"106":1,"328":1,"344":1,"349":2,"441":2,"516":1,"555":1,"625":1,"654":1,"668":2,"685":2}}],["nome",{"0":{"453":1,"478":1},"2":{"12":1,"13":1,"35":2,"317":2,"328":2,"330":1,"342":1,"345":1,"348":1,"362":2,"422":1,"424":3,"426":1,"427":1,"441":1,"452":2,"453":2,"454":1,"456":2,"459":1,"461":2,"470":1,"477":3,"478":9,"479":1,"483":1,"485":2,"487":1,"493":1,"516":1,"523":1,"555":9,"588":1,"590":1,"602":1,"611":1,"616":1,"625":1,"645":1,"650":1,"660":1,"663":1,"685":3}}],["nossa",{"2":{"111":1,"259":1,"278":1,"298":1,"320":1,"365":1,"443":1,"652":1,"693":1,"696":1}}],["nossas",{"2":{"108":1,"420":1,"440":1,"445":1,"446":1,"449":1,"470":2,"474":1}}],["nossos",{"2":{"284":1,"304":1,"326":1,"372":1,"512":1,"555":1,"599":1,"608":1,"642":1}}],["nosso",{"2":{"90":1,"95":1,"99":1,"104":1,"239":1,"259":2,"275":1,"276":1,"277":1,"279":1,"295":1,"296":1,"297":1,"299":1,"314":1,"315":1,"316":1,"317":1,"318":1,"320":5,"323":1,"325":1,"347":1,"359":1,"360":1,"361":1,"362":1,"363":1,"365":5,"369":1,"371":1,"376":1,"377":2,"441":3,"442":1,"443":1,"444":1,"459":2,"477":1,"479":1,"532":1,"556":1,"577":1,"652":1,"675":1,"695":1,"697":1}}],["nos",{"0":{"596":1},"2":{"6":1,"46":1,"51":1,"63":1,"90":1,"94":2,"96":2,"99":1,"103":2,"105":2,"111":1,"112":1,"113":1,"131":1,"135":1,"220":1,"234":2,"241":1,"330":1,"338":1,"344":1,"349":2,"419":1,"420":1,"440":1,"442":3,"444":1,"447":1,"461":1,"464":2,"485":1,"505":1,"506":1,"531":2,"533":1,"549":1,"551":1,"553":1,"555":2,"608":1,"655":1,"678":1,"679":1,"680":1,"682":2,"686":2,"690":1,"692":1,"693":1}}],["no",{"0":{"108":1,"109":1,"186":1,"283":1,"303":1,"377":1,"378":1,"524":1,"530":1,"541":1,"560":1,"605":1,"623":1,"661":1,"663":1,"714":1,"745":1},"1":{"110":1,"111":1,"624":1,"625":1,"626":1,"627":1,"662":1,"715":1,"716":1},"2":{"2":2,"3":2,"4":2,"5":1,"6":1,"7":3,"9":1,"10":1,"11":1,"15":1,"30":5,"33":1,"34":1,"35":10,"38":2,"39":1,"41":3,"42":1,"43":1,"46":3,"50":1,"51":2,"52":1,"53":1,"55":2,"56":3,"58":4,"60":2,"63":2,"64":2,"65":5,"67":2,"68":1,"69":8,"71":1,"73":1,"74":7,"77":10,"80":1,"85":3,"86":1,"90":2,"92":3,"93":1,"95":3,"96":1,"99":2,"101":2,"102":1,"104":3,"105":2,"106":2,"110":1,"111":3,"112":1,"113":1,"115":2,"120":1,"126":1,"127":1,"128":2,"131":5,"133":1,"134":3,"135":5,"136":1,"140":1,"141":1,"142":5,"143":1,"144":1,"148":1,"149":2,"152":2,"153":2,"156":2,"158":2,"165":1,"166":1,"167":1,"168":5,"169":1,"173":1,"174":2,"177":2,"178":2,"183":1,"185":2,"186":1,"188":1,"190":1,"194":2,"195":1,"196":2,"201":1,"202":1,"203":7,"204":1,"208":1,"209":2,"212":2,"213":2,"216":1,"218":1,"219":2,"221":1,"222":2,"223":1,"224":3,"225":2,"226":3,"227":2,"229":3,"230":1,"231":2,"233":1,"242":1,"243":1,"244":4,"245":1,"247":1,"248":1,"249":1,"251":3,"252":1,"255":2,"258":1,"259":1,"261":3,"262":2,"263":1,"265":1,"266":1,"270":1,"272":1,"276":1,"277":1,"278":1,"281":1,"283":1,"285":2,"288":1,"290":1,"292":1,"296":1,"297":1,"298":1,"301":1,"303":1,"307":1,"312":2,"313":2,"314":1,"316":1,"317":1,"318":1,"319":1,"320":2,"321":3,"324":1,"328":4,"330":4,"331":1,"332":2,"334":3,"336":1,"337":4,"338":2,"341":1,"342":2,"344":1,"345":1,"346":1,"347":2,"348":1,"349":1,"352":1,"357":2,"358":2,"359":1,"361":1,"362":1,"363":1,"364":1,"365":2,"366":3,"370":1,"374":1,"375":1,"379":1,"381":1,"384":1,"385":1,"386":2,"387":1,"389":2,"398":3,"399":1,"402":1,"403":1,"404":2,"405":1,"411":3,"412":1,"413":1,"417":3,"418":1,"419":1,"420":1,"423":1,"424":3,"426":1,"427":1,"436":1,"437":2,"438":1,"439":1,"440":1,"441":1,"442":1,"443":2,"444":3,"445":1,"446":1,"447":2,"448":1,"449":1,"450":1,"451":2,"452":2,"453":2,"455":2,"456":4,"457":1,"458":1,"459":4,"461":1,"462":1,"463":3,"464":1,"465":4,"466":2,"467":10,"468":1,"469":2,"470":1,"471":2,"474":1,"475":2,"476":1,"478":1,"479":2,"480":2,"481":1,"482":1,"483":2,"485":1,"487":6,"488":3,"489":1,"490":2,"491":4,"492":1,"493":3,"495":2,"497":1,"499":2,"515":1,"516":1,"520":2,"523":3,"524":3,"525":3,"526":1,"529":3,"530":1,"531":3,"532":1,"533":1,"534":5,"535":3,"537":1,"538":1,"541":1,"542":1,"543":1,"544":1,"545":3,"547":2,"548":1,"549":1,"551":6,"553":2,"554":3,"555":3,"556":1,"557":2,"559":2,"560":3,"561":1,"562":2,"563":1,"564":2,"567":1,"568":4,"569":2,"573":2,"574":6,"576":2,"577":1,"598":1,"599":1,"600":2,"602":1,"603":1,"605":1,"607":1,"608":2,"609":2,"611":1,"612":1,"616":2,"617":2,"619":1,"621":1,"624":1,"625":2,"628":1,"629":7,"631":1,"634":4,"635":6,"636":1,"638":7,"641":1,"643":2,"645":1,"646":1,"648":2,"650":1,"651":1,"652":4,"654":4,"655":1,"656":1,"659":1,"662":2,"666":8,"667":2,"668":1,"669":1,"671":1,"676":1,"678":1,"679":5,"680":2,"681":3,"682":2,"683":2,"685":2,"686":2,"688":1,"689":1,"690":1,"691":2,"694":1,"695":1,"699":3,"700":2,"701":1,"703":1,"704":2,"708":2,"711":2,"715":1,"716":1,"724":1,"726":2,"728":1,"730":3,"731":3,"737":1,"738":1,"739":2,"744":1,"745":5,"746":3,"747":1,"751":1,"755":1,"768":1}}],["fn",{"2":{"699":2}}],["f",{"2":{"390":1,"656":1,"685":1}}],["fáceis",{"2":{"321":1,"366":1}}],["fácil",{"2":{"110":1,"156":1,"184":1,"221":1,"313":1,"318":1,"358":1,"363":1,"381":1,"452":1,"461":1,"466":1,"668":1}}],["físicas",{"2":{"261":1}}],["físico",{"0":{"132":1,"148":1,"173":1,"208":1},"2":{"65":1,"131":1,"135":1,"147":1,"148":1,"172":1,"173":1,"195":1,"207":1,"208":1,"261":1,"548":1,"608":1,"745":1}}],["fg",{"2":{"231":3}}],["fs",{"2":{"231":3,"577":3,"715":1}}],["fbreactnativespec",{"2":{"313":2}}],["fblazyvector",{"2":{"313":2}}],["fb",{"2":{"231":3}}],["fb2ec1ea47c53c2e7b873acb1cb46192ac74274e",{"2":{"113":1}}],["f5deb3",{"2":{"88":1}}],["f5f5f5",{"2":{"88":1}}],["f5f5dc",{"2":{"88":1}}],["f5fffa",{"2":{"88":1}}],["f4a460",{"2":{"88":1}}],["fdf5e6",{"2":{"88":1}}],["f08080",{"2":{"88":1}}],["f0e68c",{"2":{"88":1}}],["f0f8ff",{"2":{"88":1}}],["f0fff0",{"2":{"88":1}}],["f0ffff",{"2":{"88":1}}],["f0ff",{"2":{"82":1}}],["f0f",{"2":{"82":1}}],["f8f8ff",{"2":{"88":1}}],["ff6347",{"2":{"88":1}}],["ff69b4",{"2":{"88":1}}],["ff0000",{"2":{"88":1,"92":4,"101":2}}],["ff00ff00",{"2":{"82":1}}],["ff00ff",{"2":{"82":1,"88":2}}],["ffc0cb",{"2":{"88":1}}],["ff4500",{"2":{"88":1}}],["ffa500",{"2":{"88":1}}],["ffa07a",{"2":{"88":1}}],["ffdab9",{"2":{"88":1}}],["ffdead",{"2":{"88":1}}],["ffd700",{"2":{"88":1}}],["ffb6c1",{"2":{"88":1}}],["ff1493",{"2":{"88":1}}],["ff8c00",{"2":{"88":1}}],["ff7f50",{"2":{"88":1}}],["ffefd5",{"2":{"88":1}}],["ffe4b5",{"2":{"88":1}}],["ffe4e1",{"2":{"88":1}}],["ffe4c4",{"2":{"88":1}}],["ffebcd",{"2":{"88":1}}],["fff5ee",{"2":{"88":1}}],["ffff00",{"2":{"88":1}}],["ffffff",{"2":{"88":1,"92":6,"101":3,"317":1,"362":1}}],["fffff0",{"2":{"88":1}}],["ffffe0",{"2":{"88":1}}],["fffafa",{"2":{"88":1}}],["fffaf0",{"2":{"88":1}}],["fffacd",{"2":{"88":1}}],["fff0f5",{"2":{"88":1}}],["fff8dc",{"2":{"88":1}}],["fff",{"2":{"60":1,"231":1}}],["fullrelease",{"2":{"595":1}}],["fullstaging",{"2":{"595":3}}],["fulldebug",{"2":{"595":2}}],["full",{"2":{"349":2,"522":1,"595":1}}],["future",{"2":{"520":1}}],["futuras",{"2":{"452":1,"648":1,"681":1}}],["futura",{"2":{"338":1}}],["futuro",{"2":{"55":1,"338":1,"420":1,"440":1,"446":1,"449":1,"452":1,"461":1,"463":1,"469":1,"470":1,"474":1,"485":1,"487":2,"488":1,"491":1,"671":1,"688":1,"695":1}}],["fuchsia",{"2":{"88":1}}],["fundamentais",{"2":{"688":1}}],["fundamental",{"2":{"552":1}}],["fundamentos",{"0":{"343":1},"1":{"344":1,"345":1,"346":1,"347":1,"348":1,"349":1},"2":{"238":1,"753":1}}],["fundo",{"0":{"235":1,"339":1},"2":{"245":2,"339":1,"421":1,"429":2,"444":1,"542":1,"562":3}}],["fun",{"2":{"92":2,"256":1,"259":3,"298":1,"299":7,"402":4,"404":2,"422":1,"423":1,"424":3,"425":1,"427":2,"430":5,"431":9,"432":1,"433":1,"453":1,"454":2,"456":3,"463":1,"464":4,"465":1,"466":3,"467":4,"468":3}}],["funccolumn",{"2":{"531":1}}],["funcline",{"2":{"531":1}}],["func",{"2":{"365":1,"367":1,"427":1,"443":1,"493":2}}],["functions",{"2":{"390":2,"629":1}}],["function",{"2":{"74":1,"77":1,"129":1,"390":10,"399":1,"445":1,"462":1,"486":3,"692":1}}],["funcionem",{"2":{"71":1,"680":1}}],["funcione",{"2":{"60":1,"65":1,"68":1,"328":1,"445":1,"670":1,"678":1,"721":1}}],["funcionais",{"2":{"511":1}}],["funcional",{"2":{"82":1,"83":1,"84":1,"441":1}}],["funcionalidades",{"2":{"682":1}}],["funcionalidade",{"2":{"41":1,"313":1,"345":1,"358":1,"374":1,"452":1,"461":1,"479":1,"485":1,"648":1,"675":1}}],["funcionamento",{"2":{"156":1,"217":1}}],["funcionam",{"0":{"736":1},"2":{"74":1,"231":1,"375":1,"379":1,"381":1,"384":1,"561":1,"673":2}}],["funcionando",{"2":{"65":1,"523":1,"529":2,"556":1,"671":2,"682":2}}],["funcionarem",{"2":{"739":1}}],["funcionaria",{"2":{"673":1}}],["funcionará",{"2":{"57":1,"74":1,"77":1,"345":2,"402":1,"581":1}}],["funcionarão",{"2":{"57":1,"67":1,"74":1,"77":1,"108":1,"381":1,"445":1}}],["funcionar",{"2":{"43":1,"114":1,"131":1,"152":1,"177":1,"194":1,"212":1,"283":1,"303":1,"638":1,"699":1}}],["funciona",{"0":{"217":1,"381":1,"382":1,"383":1,"531":1},"2":{"42":1,"56":1,"57":2,"58":1,"67":4,"69":1,"77":1,"79":1,"131":1,"222":1,"241":1,"265":1,"285":1,"287":1,"306":1,"344":1,"351":1,"381":1,"387":1,"470":1,"493":1,"520":1,"529":1,"541":1,"546":1,"638":1,"648":1,"668":1,"669":1,"671":1,"675":1,"679":1,"721":1,"730":1,"731":1,"746":1}}],["funções",{"0":{"96":1,"97":1,"105":1,"106":1},"2":{"47":3,"50":2,"51":1,"97":1,"106":1,"391":1,"442":1,"486":1,"493":1,"531":1,"675":1,"676":1,"680":1,"685":2}}],["função",{"0":{"117":1,"399":1,"511":1},"2":{"11":1,"31":3,"32":1,"33":3,"34":3,"35":5,"47":1,"62":2,"92":2,"95":2,"104":2,"106":1,"113":1,"117":1,"219":2,"220":1,"242":2,"244":1,"245":1,"255":1,"259":1,"344":3,"345":1,"349":6,"398":1,"399":3,"425":1,"426":1,"441":1,"442":3,"444":1,"456":2,"457":1,"461":2,"464":4,"465":1,"481":1,"483":1,"485":2,"488":2,"489":1,"511":4,"524":1,"531":11,"540":2,"544":1,"629":1,"672":3,"675":3,"677":1,"680":3,"685":3}}],["fps",{"0":{"540":1,"541":1,"542":1,"543":1},"2":{"55":1,"63":1,"545":1,"556":2}}],["fez",{"2":{"667":1}}],["fechadura",{"2":{"628":1}}],["fechada",{"2":{"522":1}}],["felizmente",{"2":{"420":1,"440":1,"575":1,"635":1}}],["fetch",{"0":{"518":1},"1":{"519":1,"520":1},"2":{"392":1,"518":3,"519":2,"520":4,"706":1}}],["fetching",{"2":{"313":1,"358":1}}],["feedback",{"2":{"216":1,"245":4,"249":1,"676":1}}],["feita",{"2":{"257":1,"334":1,"341":2,"442":1,"538":1,"653":1}}],["feitas",{"2":{"111":1,"398":1,"534":1,"535":1,"726":1}}],["feito",{"2":{"46":1,"50":1,"52":1,"56":1,"336":1,"471":1,"479":1,"534":1,"537":1,"556":1,"657":1,"658":1,"662":1,"663":1,"682":1}}],["ferramenta",{"0":{"690":1},"1":{"691":1},"2":{"38":1,"63":1,"70":1,"112":1,"133":1,"143":1,"151":1,"156":1,"165":1,"176":1,"183":1,"193":1,"211":1,"310":1,"355":1,"470":2,"551":1,"552":2,"554":1,"657":1,"666":1,"681":1,"690":6,"723":1,"734":1}}],["ferramentas",{"0":{"131":1,"135":1,"185":1,"312":1,"357":1,"567":1},"1":{"568":1,"569":1,"570":1},"2":{"11":1,"34":1,"39":1,"134":1,"137":1,"142":2,"156":2,"164":1,"168":2,"182":1,"184":1,"185":3,"199":1,"203":4,"312":3,"313":1,"357":3,"358":1,"375":1,"416":1,"417":2,"419":1,"532":1,"552":1,"617":1,"628":1,"629":1,"672":2,"682":1,"717":1,"745":2,"760":1}}],["flipper=1",{"2":{"666":2}}],["flipper",{"0":{"666":1},"1":{"667":1},"2":{"483":2,"666":8,"667":7}}],["float",{"2":{"424":6,"462":2,"486":1}}],["flow",{"2":{"390":1,"426":1,"732":1}}],["floralwhite",{"2":{"88":1}}],["flutuante",{"2":{"231":2}}],["fluxos",{"2":{"414":1,"417":2}}],["fluxo",{"0":{"107":1},"1":{"108":1,"109":1,"110":1,"111":1},"2":{"65":1,"90":2,"99":2,"234":2,"285":1,"414":1,"435":1,"636":1,"682":1}}],["flamechart",{"2":{"531":1}}],["flags",{"2":{"748":1,"751":2}}],["flag",{"2":{"65":1}}],["flatlistbasics",{"2":{"730":3}}],["flatlist",{"0":{"496":1},"1":{"497":1,"498":1,"499":1,"500":1,"501":1,"502":1,"503":1,"504":1,"505":1,"506":1,"507":1,"508":1,"509":1,"510":1,"511":1},"2":{"11":1,"34":1,"46":1,"497":1,"498":1,"500":1,"509":1,"510":1,"511":1,"520":2,"539":2,"730":9,"731":1,"762":1}}],["flexdimensionsbasics",{"2":{"262":2}}],["flexdirectionbasics",{"2":{"224":2}}],["flexdirection",{"2":{"53":1,"222":2,"223":1,"224":5,"225":1,"226":3,"227":1,"228":1,"229":1,"230":1,"231":6,"232":1,"233":1,"234":1,"244":1}}],["flexíveis",{"0":{"262":1},"2":{"262":1,"263":1}}],["flexível",{"0":{"111":1,"224":1,"231":1},"2":{"111":2,"263":1,"445":1}}],["flexgrow",{"2":{"231":17,"329":1}}],["flexbasis",{"2":{"231":15}}],["flexbox",{"0":{"222":1},"1":{"223":1,"224":1,"225":1,"226":1,"227":1,"228":1,"229":1,"230":1,"231":1},"2":{"57":1,"60":1,"110":1,"111":1,"222":3,"235":1,"347":2,"387":1,"421":1,"756":1}}],["flexaligntype>",{"2":{"228":1}}],["flexaligntype",{"2":{"228":3}}],["flexwraplayout",{"2":{"230":2}}],["flexwrap",{"2":{"224":1,"225":1,"226":1,"227":1,"228":1,"229":3,"230":5,"231":1,"232":2,"233":1,"234":1}}],["flexshrink",{"2":{"222":1,"231":17}}],["flexiblesizeexampleview",{"2":{"111":1}}],["flexibilityexampleapp",{"2":{"111":1}}],["flexibilidade",{"2":{"95":1,"104":1,"111":5,"262":1}}],["flex",{"0":{"223":1,"230":1},"2":{"46":1,"53":2,"54":1,"60":1,"116":2,"122":2,"222":2,"223":12,"224":3,"225":3,"226":8,"227":7,"228":5,"229":8,"230":2,"231":5,"232":3,"233":3,"234":3,"239":1,"244":1,"262":7,"277":1,"297":1,"317":1,"328":1,"362":1,"441":2,"442":2,"520":1,"562":2,"730":2,"737":1}}],["fc",{"2":{"46":1,"737":1}}],["frágil",{"2":{"670":1}}],["frisbee",{"2":{"521":1}}],["fresco",{"2":{"423":2}}],["frente",{"2":{"244":1,"599":1,"608":1,"642":1}}],["frequente",{"2":{"128":1,"501":2}}],["frequentemente",{"2":{"112":1,"488":1,"628":1}}],["frequentes",{"2":{"66":1,"70":1,"501":2,"691":2,"692":1}}],["frequência",{"2":{"42":1,"112":1,"501":1,"557":1}}],["fracos",{"2":{"681":1}}],["fragmentactivity",{"2":{"431":5}}],["fragment",{"2":{"402":2,"403":1,"404":5,"430":6,"431":5}}],["fragments",{"2":{"400":1,"402":1,"428":1,"429":2}}],["fragmento",{"0":{"400":1,"402":1,"403":1,"404":1,"428":1,"430":1},"1":{"401":1,"402":1,"403":1,"404":1,"405":1,"406":1,"429":1,"430":1,"431":1,"432":1,"433":1,"434":1},"2":{"402":2,"403":2,"404":1,"405":1,"431":1,"754":1}}],["fragmentos",{"2":{"279":2,"299":2,"349":2,"400":1,"403":1}}],["frase",{"2":{"242":1}}],["frames",{"0":{"533":1}}],["frametimenanos",{"2":{"431":2}}],["framecallback",{"2":{"431":2}}],["framework",{"2":{"358":1,"687":1,"688":1,"722":1}}],["frameworks",{"2":{"142":2,"168":2,"203":2,"706":1}}],["framelayout>",{"2":{"431":2}}],["framelayout",{"0":{"403":1,"404":1},"2":{"347":1,"403":2,"429":5,"431":13}}],["frame",{"2":{"110":1,"111":5,"404":1,"441":1,"445":2}}],["frombundle",{"2":{"256":2,"257":2}}],["from",{"2":{"37":1,"46":4,"53":2,"54":2,"60":2,"92":2,"101":2,"114":4,"115":4,"116":6,"122":4,"128":1,"223":2,"224":3,"225":3,"226":3,"227":3,"228":4,"229":3,"230":3,"231":3,"232":3,"233":3,"234":3,"239":2,"242":2,"244":2,"245":2,"255":1,"257":1,"261":2,"262":2,"263":2,"271":2,"277":2,"291":2,"297":2,"313":2,"317":2,"344":4,"345":7,"346":2,"347":2,"348":6,"349":5,"358":2,"362":2,"387":2,"390":3,"393":1,"426":1,"431":2,"434":4,"441":2,"442":3,"445":1,"457":3,"461":3,"466":1,"481":3,"485":3,"491":1,"520":2,"562":2,"563":1,"564":1,"565":1,"566":1,"573":4,"574":1,"668":2,"709":3,"730":4,"731":2,"737":2}}],["fatal",{"2":{"685":1}}],["fato",{"2":{"106":1,"113":1,"338":1}}],["fator",{"2":{"65":1}}],["fatores",{"2":{"47":1}}],["failure",{"2":{"486":2,"489":1}}],["failedcallback",{"2":{"464":1}}],["failed",{"2":{"122":1,"467":6,"685":1,"710":1}}],["facilidade",{"2":{"693":1}}],["facilitam",{"2":{"680":1}}],["facilita",{"2":{"656":1}}],["facilitar",{"2":{"515":1}}],["facilitarão",{"2":{"485":1}}],["facebook",{"2":{"101":1,"113":1,"143":1,"165":1,"183":1,"256":6,"259":2,"270":4,"272":1,"279":1,"290":4,"292":1,"299":1,"398":1,"402":12,"404":11,"431":12,"432":6,"452":10,"456":9,"464":2,"465":2,"466":6,"491":1,"523":2,"555":1,"581":1,"595":1,"596":2,"685":1,"747":2}}],["fabricação",{"2":{"673":1}}],["fabricante",{"2":{"608":1}}],["fabric",{"2":{"420":1,"440":1,"446":1,"449":1,"470":1,"474":1,"515":1}}],["familiar",{"2":{"518":1}}],["familiarizados",{"2":{"339":1}}],["familiarizado",{"2":{"62":1,"140":1,"151":1,"156":1,"176":1,"193":1,"201":1,"211":1,"347":1,"387":1,"420":1,"440":1}}],["famintos",{"2":{"349":1}}],["fast",{"2":{"216":2,"217":4,"219":1,"220":1,"221":2,"508":1}}],["fases",{"2":{"191":2,"248":1}}],["fase",{"0":{"64":1},"1":{"65":1,"66":1,"67":1,"68":1,"69":1,"70":1},"2":{"191":1,"252":2,"548":1,"574":1,"663":1,"762":1}}],["farão",{"2":{"534":1}}],["fará",{"2":{"111":1,"252":1,"337":1,"456":1,"458":1,"482":1,"635":1,"654":1,"681":1,"683":1}}],["faria",{"2":{"52":1,"437":1,"682":1,"745":1}}],["fa8072",{"2":{"88":1}}],["faf0e6",{"2":{"88":1}}],["fafad2",{"2":{"88":1}}],["faebd7",{"2":{"88":1}}],["favorito",{"2":{"325":1,"371":1}}],["favor",{"2":{"74":1,"77":1,"486":1}}],["faça",{"2":{"60":1,"276":1,"296":1,"316":1,"361":1,"414":1,"430":3,"443":1,"446":1,"505":1,"561":1,"616":1,"656":1,"660":1,"675":1,"680":1,"728":1,"748":1,"751":1}}],["fading",{"2":{"46":1}}],["fadeanim",{"2":{"46":6,"50":2}}],["fadeinview>",{"2":{"46":1}}],["fadeinview",{"2":{"46":3}}],["fadeinviewprops>",{"2":{"46":1}}],["fadeinviewprops",{"2":{"46":1}}],["falhe",{"2":{"681":1}}],["falha",{"0":{"708":1},"1":{"712":1,"713":1},"2":{"464":2,"465":1,"497":1,"534":1,"671":1,"675":1,"681":1,"682":1,"686":1,"746":1}}],["falhado",{"2":{"334":1}}],["falhará",{"2":{"545":1}}],["falhar",{"2":{"313":1,"358":1,"667":1}}],["falhas",{"2":{"218":1,"413":1,"670":1}}],["falhando",{"2":{"190":1}}],["falham",{"2":{"43":1}}],["faltará",{"2":{"595":1}}],["falaremos",{"2":{"674":1}}],["falar",{"2":{"442":1}}],["falsa",{"2":{"678":1}}],["falso",{"2":{"349":1,"747":1}}],["false",{"2":{"20":1,"21":1,"22":1,"23":1,"24":1,"28":1,"48":1,"53":1,"56":1,"57":1,"78":1,"256":4,"257":2,"259":12,"279":1,"283":1,"299":1,"303":1,"349":5,"402":2,"442":2,"443":1,"499":1,"507":1,"520":1,"551":1,"573":1,"656":2,"748":1,"750":2,"751":2}}],["fazê",{"2":{"219":1,"447":1}}],["fazendo",{"0":{"519":1,"596":1},"2":{"73":1,"76":1,"110":1,"499":1,"680":1}}],["fazemos",{"2":{"90":1,"99":1}}],["fazem",{"2":{"70":1,"420":1,"440":1,"668":1}}],["fazer",{"2":{"35":1,"50":2,"55":2,"57":1,"60":1,"67":2,"69":1,"71":1,"73":1,"77":1,"80":1,"94":1,"103":1,"110":1,"112":1,"114":1,"115":1,"128":1,"142":1,"152":1,"168":1,"177":1,"194":1,"200":1,"203":1,"212":1,"217":1,"220":1,"242":1,"255":2,"257":1,"279":1,"281":1,"299":1,"301":1,"320":1,"321":1,"324":1,"332":1,"336":1,"344":1,"349":1,"365":1,"366":1,"370":1,"377":1,"422":1,"426":1,"428":1,"438":1,"442":1,"456":1,"458":1,"461":1,"465":1,"466":1,"467":1,"470":1,"479":1,"482":1,"485":1,"490":1,"491":1,"492":1,"495":1,"517":1,"519":1,"520":2,"533":1,"540":2,"543":1,"545":1,"553":1,"554":1,"575":1,"576":1,"601":1,"603":1,"610":1,"612":1,"628":1,"629":1,"636":1,"644":1,"646":1,"656":1,"662":1,"663":1,"668":2,"682":1,"689":1,"704":1,"710":1,"721":1,"726":1,"730":1,"742":1,"745":1,"746":1}}],["faz",{"2":{"14":1,"15":1,"24":1,"227":1,"349":1,"387":1,"430":1,"445":1,"674":1,"678":1}}],["fique",{"2":{"675":1,"689":1}}],["fi",{"0":{"603":1,"612":1,"620":1,"646":1},"2":{"548":1,"601":1,"603":2,"610":1,"612":2,"618":1,"619":1,"620":1,"644":1,"646":2}}],["fiz",{"0":{"729":1}}],["fizéssemos",{"2":{"545":1}}],["fizer",{"2":{"544":1}}],["fizermos",{"2":{"544":1}}],["fizesse",{"2":{"221":1,"532":1}}],["fish",{"2":{"348":1}}],["fisicamente",{"2":{"45":1}}],["firebase",{"2":{"709":3}}],["firebrick",{"2":{"88":1}}],["fireevent",{"2":{"679":1,"680":3}}],["firstparam",{"2":{"519":1}}],["firstname",{"2":{"345":4}}],["fica",{"2":{"458":1,"482":1,"545":1}}],["ficam",{"2":{"328":1,"407":1,"665":1}}],["ficaria",{"2":{"666":1,"667":1}}],["ficará",{"2":{"245":1,"508":1,"545":1,"635":1}}],["ficar",{"2":{"74":1,"77":1,"216":1,"677":1,"685":1}}],["fio",{"2":{"158":1,"288":1,"309":1,"603":1,"612":1,"619":1,"646":1}}],["fim",{"2":{"142":1,"168":1,"203":1,"225":2,"270":1,"290":1,"320":1,"365":1,"367":1,"385":1,"552":1,"739":1}}],["fidelidade",{"2":{"113":1}}],["fix",{"2":{"707":1}}],["fixeddimensionsbasics",{"2":{"261":2}}],["fixando",{"2":{"638":1}}],["fixas",{"0":{"261":1},"2":{"261":2,"262":1}}],["fixa",{"2":{"227":1}}],["fixado",{"2":{"51":1,"261":1}}],["fixo",{"0":{"110":1},"2":{"110":3,"111":1,"257":1,"445":2}}],["filmes",{"2":{"533":1}}],["filas",{"2":{"491":1}}],["fila",{"2":{"491":14,"700":1}}],["filter",{"2":{"399":1,"576":2}}],["filter>",{"2":{"73":2,"259":2}}],["filtrar",{"2":{"382":1}}],["file=",{"2":{"663":1}}],["file=my",{"2":{"652":1}}],["files",{"2":{"279":1,"299":1,"358":1,"402":1,"404":1,"650":1}}],["fileclone=true",{"2":{"68":1}}],["file",{"2":{"65":1,"68":3,"271":2,"283":1,"291":2,"303":1,"493":2,"529":1,"582":1,"583":1,"584":1,"585":1,"589":2,"591":1,"653":3,"663":2,"739":1}}],["fill",{"2":{"53":1}}],["filho",{"0":{"115":1},"2":{"113":1,"114":3,"115":2,"226":3,"228":1,"231":3,"248":1,"252":1,"347":1,"531":1}}],["filhos",{"2":{"2":1,"3":1,"30":1,"90":1,"99":1,"113":1,"222":1,"224":5,"225":3,"226":9,"227":7,"228":1,"230":2,"231":9,"233":1,"262":2,"263":1,"339":1,"347":2,"402":2}}],["filhas",{"2":{"223":1}}],["filha",{"2":{"14":1,"115":1,"444":1}}],["finais",{"2":{"531":1}}],["finally",{"2":{"520":1}}],["finalizar",{"2":{"442":1}}],["finalizada",{"2":{"141":1,"167":1,"202":1}}],["finalidade",{"2":{"11":1,"34":1,"37":1}}],["finalmente",{"2":{"111":1,"217":1,"278":1,"279":1,"298":1,"299":1,"349":1,"545":1}}],["final",{"2":{"10":1,"46":1,"47":1,"55":1,"226":3,"227":1,"229":2,"233":1,"251":1,"259":4,"278":1,"313":1,"358":1,"398":1,"399":1,"402":1,"422":1,"425":1,"426":1,"431":3,"450":1,"457":1,"463":1,"467":13,"475":1,"481":1,"534":1,"553":1,"556":1,"566":1,"696":1,"699":1}}],["fingindo",{"2":{"483":1}}],["findviewbyid",{"2":{"404":2,"431":2}}],["findindex",{"2":{"393":1}}],["find",{"2":{"393":1,"444":1}}],["findnodehandle",{"2":{"37":2,"434":2,"444":1}}],["fins",{"2":{"313":1,"320":2,"358":1,"365":2}}],["finish",{"2":{"149":1,"174":1,"209":1}}],["fields",{"2":{"390":1}}],["field",{"2":{"4":2,"26":1}}],["fome",{"2":{"349":1}}],["folly",{"2":{"313":2}}],["follower",{"2":{"51":2}}],["foo💩bar",{"2":{"390":1}}],["food",{"2":{"349":3}}],["food=",{"2":{"348":1}}],["foo",{"2":{"256":2,"390":7,"461":1,"485":1}}],["fosse",{"2":{"93":1,"102":1,"540":1,"745":1}}],["foundation",{"2":{"608":8}}],["found",{"2":{"65":1,"464":2,"467":8,"488":2,"529":1}}],["fontes",{"0":{"536":1},"1":{"537":1,"538":1,"539":1,"540":1,"541":1,"542":1,"543":1,"544":1,"545":1},"2":{"111":1,"131":1,"328":1,"341":1,"532":1}}],["fonte",{"0":{"338":1},"2":{"56":1,"111":1,"135":1,"143":1,"328":1,"334":3,"336":1,"379":1,"399":1,"418":1,"445":1,"635":1,"686":1,"707":1,"730":2}}],["fontweight",{"2":{"53":1,"54":1,"60":1,"224":1,"225":1,"226":1,"227":1,"228":1,"229":1,"230":1,"231":2,"233":1,"234":1,"668":1,"730":1,"737":1}}],["fontsize",{"2":{"46":1,"53":1,"54":1,"224":2,"225":2,"226":2,"227":2,"228":2,"229":2,"230":2,"231":1,"233":2,"234":2,"242":1,"277":1,"297":1,"317":1,"362":1,"668":1,"681":1,"730":3,"731":6,"737":1}}],["foi",{"2":{"31":1,"46":1,"55":1,"56":1,"67":1,"71":1,"73":1,"76":1,"142":1,"151":1,"166":1,"168":1,"176":1,"193":1,"203":1,"211":1,"222":1,"251":1,"259":1,"318":1,"320":1,"341":1,"349":1,"363":1,"365":1,"424":1,"442":1,"454":1,"464":1,"468":1,"476":1,"479":1,"488":1,"522":1,"526":1,"541":2,"554":1,"575":1,"636":2,"671":1,"672":1,"687":1,"708":1,"747":1}}],["foto",{"2":{"9":1}}],["fortes",{"2":{"455":1,"480":1}}],["force",{"2":{"334":1}}],["foreach",{"2":{"577":1}}],["forem",{"2":{"470":1,"505":1,"506":1,"520":1,"550":1,"562":2,"572":1,"699":1,"700":1}}],["foreground",{"2":{"256":2,"259":4}}],["forestgreen",{"2":{"88":1}}],["forçados",{"2":{"230":1}}],["forçar",{"2":{"220":1,"574":1}}],["forçará",{"2":{"30":1}}],["forwardref",{"2":{"115":2}}],["forward",{"2":{"65":1,"114":1}}],["foram",{"2":{"56":1,"89":1,"97":1,"98":1,"106":1,"142":1,"168":1,"236":2,"251":1,"379":1,"424":1,"576":1,"639":1,"687":1,"688":1}}],["fora",{"0":{"341":1,"512":1},"1":{"513":1,"514":1,"515":1,"516":1},"2":{"41":1,"42":1,"74":1,"77":1,"110":2,"217":1,"335":1,"457":1,"481":1,"499":2,"511":2,"545":1,"560":1,"662":1,"754":1}}],["fornecidas",{"2":{"550":1,"680":1,"734":1}}],["fornecida",{"2":{"120":1,"121":1,"123":1,"187":1,"262":1,"321":1,"366":1,"666":1}}],["fornecidos",{"2":{"50":1,"119":1,"245":1,"424":1,"691":1}}],["fornecido",{"2":{"8":1,"68":1,"191":1,"279":1,"299":1,"424":3,"465":1,"589":1}}],["fornecê",{"2":{"111":1}}],["fornecendo",{"2":{"55":1,"92":1,"464":1,"488":1,"723":1}}],["fornece",{"2":{"45":1,"47":1,"48":1,"60":1,"92":1,"101":2,"107":1,"126":1,"243":1,"244":1,"328":1,"334":1,"374":1,"434":2,"465":1,"471":2,"518":1,"522":1,"531":1,"553":3,"562":2,"630":1,"634":1,"677":1,"679":1,"691":1,"692":1,"718":1,"720":1,"730":1}}],["fornecerá",{"2":{"121":1,"491":1,"551":2,"553":1,"737":1}}],["fornecer",{"2":{"5":1,"11":1,"34":1,"41":1,"222":1,"231":1,"245":2,"328":1,"337":1,"402":1,"428":1,"488":1,"491":3,"509":1,"524":2,"537":1,"540":1,"545":1,"638":1,"677":1,"737":1}}],["fornecemos",{"2":{"250":1,"320":1,"365":1,"442":1}}],["fornecem",{"2":{"0":1,"245":1,"330":1,"552":1}}],["forneça",{"2":{"5":1,"491":1}}],["formulário",{"2":{"634":1}}],["formulários",{"2":{"4":1}}],["formatado",{"2":{"730":1}}],["formatação",{"0":{"241":1}}],["format",{"2":{"531":2}}],["formatos",{"2":{"531":1}}],["formato",{"0":{"574":1},"2":{"251":1,"442":1,"488":1,"531":3,"551":1,"552":1,"571":2,"573":1,"574":3,"578":1,"654":1}}],["formação",{"2":{"236":1}}],["formar",{"2":{"230":1}}],["formas",{"0":{"95":1,"104":1},"1":{"96":1,"97":1,"105":1,"106":1}}],["forma",{"2":{"22":1,"31":1,"46":1,"55":2,"60":1,"68":1,"91":1,"100":1,"110":1,"114":1,"118":1,"147":1,"172":1,"207":1,"231":1,"233":1,"234":1,"250":1,"254":1,"261":1,"328":2,"333":1,"338":1,"344":1,"404":1,"425":1,"445":1,"455":2,"456":1,"462":1,"464":1,"480":2,"487":2,"488":1,"491":1,"493":1,"535":1,"540":1,"545":1,"575":1,"589":1,"590":1,"591":1,"592":1,"595":1,"629":1,"631":1,"635":1,"636":1,"654":1,"658":1,"668":1,"673":3,"674":1,"678":1,"681":1,"682":1,"690":1,"730":1,"742":1}}],["formlabel",{"2":{"4":2,"26":2}}],["for",{"2":{"3":1,"4":3,"26":1,"46":1,"48":1,"56":1,"67":2,"68":1,"74":1,"77":1,"92":1,"101":1,"111":1,"113":1,"117":1,"120":1,"121":1,"140":1,"141":2,"144":1,"167":2,"169":1,"188":1,"191":1,"201":1,"202":2,"204":1,"218":1,"219":2,"230":1,"231":3,"255":2,"256":2,"257":2,"259":4,"262":1,"278":1,"298":1,"313":1,"336":1,"349":1,"358":1,"390":2,"399":1,"402":1,"456":1,"464":2,"465":1,"469":1,"488":1,"490":2,"491":3,"499":1,"502":1,"507":1,"511":1,"523":1,"541":2,"548":1,"549":1,"565":1,"570":1,"573":1,"602":1,"603":2,"611":1,"612":2,"615":1,"618":1,"638":1,"645":1,"646":2,"667":1,"691":1,"692":1,"708":1,"710":1,"726":2,"733":1,"745":1}}],["focus",{"0":{"123":1},"2":{"74":1,"124":1}}],["focusable=",{"2":{"2":1}}],["focáveis",{"2":{"74":1}}],["focar",{"2":{"4":1}}],["foco",{"2":{"2":1,"30":1,"35":7,"37":1,"74":6,"77":4,"123":1,"124":1}}],["udid=",{"2":{"627":1}}],["udid",{"0":{"627":1},"2":{"627":3}}],["udev",{"2":{"608":2}}],["uwp",{"2":{"513":1}}],["util",{"2":{"402":1,"431":1,"432":2,"452":2,"454":2,"456":3}}],["utilitários",{"2":{"454":1}}],["utilitário",{"2":{"217":1}}],["utilizá",{"2":{"681":1}}],["utilizável",{"2":{"441":2,"442":1}}],["utilizáveis",{"2":{"39":1}}],["utilizam",{"2":{"659":1}}],["utiliza",{"2":{"112":1,"465":1}}],["utilizado",{"2":{"11":1,"35":1,"566":1,"656":1,"672":1}}],["u",{"2":{"390":4}}],["urls",{"2":{"635":1,"636":1}}],["url",{"2":{"334":3,"365":1,"517":1,"519":2,"520":1,"635":2,"636":1}}],["urlforresource",{"2":{"320":1,"365":1}}],["urlwithstring",{"2":{"320":1}}],["uri",{"0":{"333":1},"1":{"334":1},"2":{"53":1,"92":1,"101":1,"278":1,"298":1,"330":2,"331":2,"332":1,"333":2,"334":1,"337":1,"338":4,"348":1,"387":1,"467":7,"731":1}}],["ux",{"2":{"278":1,"298":1}}],["ultrapassa",{"2":{"247":1,"559":1,"669":1}}],["ultrapassar",{"2":{"43":1}}],["upload",{"0":{"649":1},"1":{"650":1,"651":1},"2":{"549":2,"648":1,"650":2,"651":2,"652":6,"653":6,"656":2,"658":2}}],["upstream",{"2":{"466":4,"490":3}}],["upgrade",{"0":{"721":1},"2":{"313":2,"358":1,"719":1,"720":1,"721":3,"723":1,"726":2,"728":2,"734":1}}],["up",{"2":{"74":1,"77":1,"244":1,"321":1,"366":1,"524":1,"551":1}}],["updatesnapshot",{"2":{"681":1}}],["updatecellsbatchingperiod",{"0":{"501":1},"2":{"501":1}}],["updateview",{"2":{"113":1,"423":1}}],["updatedprops",{"2":{"92":4}}],["update",{"2":{"60":1}}],["unauthorized",{"2":{"599":1}}],["unused",{"2":{"524":1}}],["unnecessary",{"2":{"490":1}}],["unnecessarylocalvariable",{"2":{"456":1}}],["uns",{"2":{"346":1}}],["unsplash",{"2":{"53":1}}],["unmountreactapplication",{"2":{"279":1,"299":1}}],["unmet",{"2":{"268":1,"309":1,"354":1}}],["underlaycolor=",{"2":{"245":2}}],["undefined",{"2":{"129":1,"231":2,"245":1,"328":2,"660":2}}],["universais",{"2":{"635":1}}],["universalapk",{"2":{"656":2}}],["universal",{"2":{"261":1,"513":1,"656":1}}],["unitários",{"0":{"676":1},"2":{"676":2,"678":2}}],["unit",{"2":{"424":1}}],["unicode",{"2":{"390":1,"747":1}}],["unificada",{"2":{"328":1,"634":1}}],["uniformemente",{"2":{"226":3,"229":2}}],["uninstall",{"2":{"170":1,"189":1,"381":1}}],["unidade",{"2":{"261":1,"503":1,"675":1,"677":1,"678":2,"679":1}}],["unidades",{"2":{"50":1,"261":1,"678":1}}],["unidirecional",{"2":{"90":1,"99":1}}],["un",{"2":{"68":1}}],["uncacheable",{"2":{"67":1}}],["unlink",{"2":{"67":5}}],["uidevice",{"2":{"480":1,"564":1}}],["uidatepickermodedateandtime",{"2":{"445":1}}],["uidatepickermodedate",{"2":{"445":1}}],["uidatepickermodetime",{"2":{"445":1}}],["uidatepicker",{"2":{"445":3}}],["uiimageview",{"2":{"387":1}}],["uitableviews",{"2":{"730":1}}],["uitabbar",{"2":{"77":1}}],["uitextfield",{"2":{"387":1}}],["uitextview",{"2":{"387":1}}],["uiapplication",{"2":{"367":2,"524":1}}],["uiapplicationdelegate",{"2":{"367":1}}],["uiwindow",{"2":{"367":1}}],["uiresponder",{"2":{"367":1}}],["uikit",{"2":{"367":1,"487":1}}],["uibutton",{"2":{"365":1}}],["uistoryboard",{"2":{"548":2}}],["uiscrollview",{"2":{"387":1}}],["uis",{"2":{"330":2}}],["uiviewcontroller",{"2":{"320":2,"365":1,"548":1}}],["uiview",{"2":{"101":1,"108":1,"111":1,"112":1,"387":1,"441":6,"443":2,"444":1,"445":1}}],["uimanager",{"2":{"37":4,"60":4,"431":7,"432":2,"434":3,"444":6,"445":2,"456":3,"555":1}}],["ui",{"0":{"440":1,"535":1,"542":1,"558":1,"560":1,"756":1},"1":{"441":1,"442":1,"443":1,"444":1,"445":1,"559":1,"560":1,"757":1,"758":1,"759":1},"2":{"30":1,"37":1,"56":1,"63":1,"89":1,"98":1,"111":1,"131":1,"279":1,"299":1,"384":1,"385":1,"387":1,"420":2,"428":1,"440":2,"533":1,"555":5,"556":2,"558":2,"559":1,"560":2,"568":1,"673":1,"679":2,"680":1,"689":1,"691":2,"765":1}}],["usual",{"2":{"470":1}}],["usuário",{"0":{"543":1,"680":1},"1":{"681":1},"2":{"5":1,"6":1,"10":1,"11":3,"12":1,"20":1,"27":2,"31":2,"33":1,"34":2,"35":9,"45":1,"55":1,"57":1,"77":3,"80":1,"111":1,"116":1,"203":5,"242":4,"245":4,"246":1,"248":1,"249":2,"251":2,"255":1,"258":1,"278":1,"279":1,"285":1,"298":1,"299":1,"337":2,"338":1,"343":1,"349":1,"385":1,"387":1,"427":2,"442":2,"443":2,"444":1,"524":1,"532":1,"533":2,"534":1,"541":1,"556":1,"568":1,"629":3,"632":1,"635":2,"636":1,"638":1,"652":1,"670":1,"679":3,"680":5,"682":2,"691":1,"695":1,"731":2}}],["usuários",{"2":{"0":1,"42":1,"243":1,"249":1,"323":1,"369":1,"426":1,"547":1,"605":1,"628":1,"634":1,"639":1,"656":1,"675":1,"679":2,"680":2,"689":2,"741":2,"746":1}}],["us",{"2":{"415":1,"462":1}}],["usb",{"0":{"598":1,"599":1,"607":1,"608":1,"615":1,"641":1,"642":1},"2":{"133":1,"148":1,"173":1,"208":1,"553":1,"598":3,"599":2,"601":1,"602":2,"603":1,"607":3,"608":4,"610":1,"611":2,"612":1,"615":1,"619":1,"641":3,"642":1,"644":1,"645":2,"646":1}}],["usá",{"2":{"93":1,"96":1,"105":1,"112":1,"148":1,"173":1,"208":1,"338":1,"376":1,"451":1,"462":1,"476":1,"486":1,"491":1,"525":1,"562":1,"567":1}}],["usr",{"2":{"67":17,"68":1,"651":1,"705":1,"722":1}}],["using",{"2":{"65":2,"68":1}}],["usos",{"2":{"730":1}}],["usou",{"2":{"166":1,"518":1,"605":1}}],["uso",{"0":{"42":1,"259":1,"702":1,"728":1,"742":1},"1":{"43":1,"44":1,"703":1,"704":1,"743":1,"744":1,"745":1},"2":{"42":2,"43":2,"56":1,"59":1,"66":1,"70":1,"77":1,"79":1,"95":1,"96":1,"104":1,"105":1,"116":1,"166":1,"261":1,"335":1,"339":1,"344":1,"374":1,"386":1,"399":1,"413":1,"419":1,"420":1,"421":1,"440":1,"441":1,"480":1,"493":1,"539":1,"542":2,"547":1,"571":2,"577":1,"581":1,"629":1,"635":1,"638":1,"652":1,"691":1,"696":1,"699":1,"736":1,"740":2,"742":1,"749":1}}],["useful",{"2":{"724":1}}],["usetransition",{"2":{"692":1}}],["uselayouteffect",{"2":{"690":2}}],["usei",{"2":{"541":1}}],["usescleartexttraffic=",{"2":{"273":1,"293":1}}],["usescleartexttraffic",{"2":{"273":1,"293":1,"520":1}}],["uses",{"2":{"272":1,"292":1}}],["usestate",{"2":{"113":1,"122":4,"221":1,"224":2,"225":2,"226":2,"227":2,"228":2,"229":2,"230":2,"231":4,"232":3,"233":3,"234":2,"242":2,"349":16,"520":3,"680":2,"692":1,"737":1}}],["usememo",{"2":{"221":3}}],["usecallback",{"2":{"113":1,"116":4,"221":1,"511":2,"680":1,"690":1}}],["userinfo",{"2":{"465":3,"490":1}}],["user",{"2":{"390":1,"526":1,"551":1,"680":1,"708":2,"715":1}}],["users",{"2":{"69":1}}],["useref",{"2":{"46":2,"53":2,"54":3,"113":1,"116":4,"122":6,"221":1,"434":2}}],["usewindowdimensions",{"2":{"53":2}}],["usenativedriver",{"2":{"46":1,"47":1,"48":3,"49":1,"51":1,"54":1,"56":4,"63":1,"541":1}}],["useeffect",{"2":{"46":2,"122":4,"221":3,"434":2,"466":1,"520":2}}],["use",{"0":{"66":1,"505":1,"506":1,"508":1,"509":1,"510":1,"702":1},"1":{"67":1,"68":1,"69":1,"703":1,"704":1},"2":{"32":1,"43":1,"55":1,"56":3,"63":1,"65":1,"67":1,"75":1,"102":1,"111":1,"112":1,"158":2,"245":1,"250":1,"262":1,"279":4,"299":4,"320":2,"330":2,"331":1,"334":1,"344":1,"349":2,"365":2,"390":1,"402":1,"452":1,"464":1,"479":1,"488":1,"495":1,"506":2,"539":1,"543":1,"551":1,"554":1,"562":1,"574":1,"630":2,"651":1,"658":1,"675":1,"681":2,"682":1,"706":1,"736":1,"745":1,"747":1,"748":1,"750":1,"751":1}}],["usa",{"0":{"729":1},"2":{"48":1,"60":1,"69":1,"92":1,"101":1,"113":1,"151":1,"176":1,"193":1,"211":1,"223":3,"250":1,"270":1,"290":1,"320":1,"344":1,"347":1,"349":1,"365":1,"377":1,"378":1,"384":1,"386":1,"387":1,"389":2,"397":1,"407":1,"417":1,"420":1,"440":1,"441":1,"442":2,"444":1,"446":1,"449":1,"470":1,"474":1,"478":1,"483":1,"493":1,"519":1,"634":3,"636":1,"654":2,"667":1,"678":1,"680":1,"699":1,"702":1,"708":1,"720":1,"721":1,"728":1}}],["usando",{"0":{"56":1,"69":1,"146":1,"148":1,"149":1,"171":1,"173":1,"174":1,"190":1,"206":1,"208":1,"209":1,"374":1,"399":1,"424":1,"518":1,"521":1,"538":1,"580":1,"595":1,"602":1,"611":1,"645":1,"692":1,"704":1,"730":1,"731":1,"732":1,"735":1,"739":1,"740":1,"745":1},"1":{"375":1,"376":1,"377":1,"378":1,"379":1,"380":1,"381":1,"382":1,"383":1,"519":1,"520":1,"693":1,"694":1,"733":1,"734":1,"735":1,"736":1,"737":1,"738":1,"739":1,"741":1,"742":1,"743":1,"744":1,"745":1,"746":1,"747":1,"748":1,"749":1,"750":1,"751":1},"2":{"43":1,"46":1,"47":1,"50":1,"51":1,"52":2,"63":2,"65":4,"67":1,"68":1,"74":1,"77":2,"79":1,"106":1,"111":1,"115":1,"116":1,"128":1,"131":1,"132":1,"134":1,"135":1,"142":3,"144":1,"145":1,"148":1,"165":1,"166":1,"168":1,"169":1,"170":1,"173":1,"183":1,"186":1,"187":1,"188":1,"190":1,"191":3,"200":2,"202":1,"204":1,"205":1,"208":1,"218":1,"222":1,"229":1,"244":1,"245":1,"252":1,"259":1,"279":3,"283":1,"299":3,"303":1,"306":1,"310":1,"325":2,"338":1,"344":1,"347":1,"351":1,"355":1,"371":2,"375":1,"377":1,"381":1,"383":1,"384":2,"386":1,"402":1,"404":1,"413":2,"421":1,"424":1,"426":1,"434":1,"435":1,"436":2,"437":1,"444":1,"445":1,"453":1,"458":1,"464":1,"478":1,"479":2,"482":1,"483":1,"488":2,"514":2,"525":2,"527":1,"529":1,"531":1,"540":2,"546":1,"547":1,"549":1,"555":1,"559":1,"561":2,"567":1,"569":1,"571":1,"574":1,"578":1,"580":1,"583":1,"584":1,"585":1,"586":1,"588":1,"595":2,"596":1,"603":1,"604":1,"608":1,"612":1,"613":1,"615":3,"618":1,"622":1,"629":1,"646":1,"647":1,"648":1,"649":1,"651":1,"653":1,"655":1,"657":2,"660":1,"667":1,"668":1,"677":1,"680":2,"681":1,"702":1,"703":3,"704":1,"706":3,"719":1,"721":2,"731":2,"739":1,"741":2,"742":3,"747":2,"753":2,"755":2,"763":1}}],["usadas",{"2":{"47":1,"60":1,"80":1,"328":1,"385":1,"420":1,"440":1,"446":1,"449":1,"470":1,"474":1,"745":1}}],["usada",{"2":{"5":1,"11":3,"34":3,"51":1,"106":1,"329":1,"562":1,"635":1,"638":1,"648":1,"679":1,"742":1}}],["usados",{"2":{"68":1,"95":1,"104":1,"106":1,"218":1,"246":1,"252":1,"334":2,"349":1,"375":1,"402":1,"420":1,"440":1,"441":1,"464":2,"488":2,"531":1,"555":1,"571":2,"734":1}}],["usado",{"0":{"707":1},"2":{"4":1,"11":27,"34":25,"46":1,"47":1,"52":1,"90":1,"99":1,"106":1,"134":1,"230":1,"245":1,"254":1,"272":1,"292":1,"317":1,"328":2,"334":1,"362":1,"385":1,"422":1,"424":1,"488":2,"510":1,"524":1,"563":1,"591":1,"596":2,"629":1,"636":1,"668":1,"679":1,"686":1,"715":1,"731":1,"733":1,"735":1,"740":1,"745":1}}],["usarão",{"2":{"733":1}}],["usarem",{"2":{"629":1}}],["usaremos",{"2":{"313":1,"320":1,"358":1,"365":1,"443":1,"470":1,"552":1}}],["usaria",{"2":{"245":1,"250":1,"689":1}}],["usará",{"2":{"47":1,"112":1,"222":1,"245":1,"262":1,"306":1,"336":1,"351":1,"389":2,"465":1,"568":1,"593":1,"650":1,"675":1,"747":1,"748":1,"750":1}}],["usar",{"0":{"237":1,"507":1,"658":1,"696":1},"1":{"697":1},"2":{"3":1,"8":2,"12":1,"30":1,"38":3,"39":3,"46":1,"47":1,"50":1,"53":2,"56":2,"57":2,"58":1,"60":1,"63":1,"65":1,"66":1,"67":3,"68":2,"69":1,"70":2,"74":2,"76":1,"77":1,"86":1,"96":2,"105":2,"110":2,"112":2,"115":1,"116":2,"118":1,"120":2,"131":2,"133":1,"134":1,"135":1,"137":1,"139":1,"142":1,"145":2,"146":1,"147":1,"149":1,"156":1,"164":1,"166":1,"168":1,"170":2,"171":1,"172":1,"174":1,"182":1,"186":1,"189":2,"190":1,"199":1,"200":2,"205":2,"206":1,"207":1,"209":1,"226":2,"229":2,"232":1,"235":1,"243":1,"245":2,"249":1,"250":1,"263":2,"270":1,"271":1,"279":1,"283":2,"290":1,"291":1,"299":1,"303":2,"310":1,"313":1,"320":2,"328":1,"329":1,"330":1,"333":2,"336":1,"339":2,"344":1,"345":1,"348":1,"349":1,"355":1,"358":1,"365":2,"375":1,"377":1,"378":1,"382":1,"386":1,"389":2,"399":2,"400":1,"404":1,"407":2,"416":1,"417":2,"428":1,"435":1,"441":3,"442":2,"444":1,"445":1,"451":1,"452":1,"454":1,"455":1,"456":3,"461":1,"464":3,"465":3,"466":1,"471":1,"476":1,"477":1,"479":2,"480":3,"485":1,"488":1,"489":3,"491":2,"493":2,"507":1,"508":1,"510":1,"518":1,"520":2,"521":2,"527":1,"532":1,"538":2,"541":3,"542":1,"549":1,"551":2,"559":1,"562":1,"566":1,"567":1,"574":4,"577":1,"583":1,"595":1,"600":1,"602":1,"609":1,"611":1,"619":1,"634":2,"635":3,"637":1,"638":1,"643":1,"645":1,"652":1,"658":1,"660":1,"662":1,"668":3,"672":2,"673":1,"674":1,"675":1,"677":2,"680":2,"681":1,"683":1,"686":1,"690":1,"691":1,"697":1,"700":1,"704":1,"705":1,"706":2,"707":1,"711":1,"721":2,"728":2,"730":1,"731":2,"734":1,"736":1,"738":1,"739":1,"745":1,"746":1}}],["usamos",{"2":{"53":1,"95":1,"101":1,"104":1,"105":1,"310":1,"355":1,"442":1,"668":1,"690":1}}],["usam",{"2":{"3":1,"68":1,"236":1,"241":1,"278":1,"298":1,"345":1,"381":1,"441":1,"545":1,"596":1,"692":1}}],["umdelay`",{"2":{"47":1}}],["umas",{"2":{"678":1}}],["uma",{"0":{"65":1,"146":1,"171":1,"190":1,"206":1,"283":1,"303":1,"376":1,"399":1,"540":1,"542":1,"543":1,"626":1,"649":1,"654":1,"688":1,"690":1,"704":1,"729":1},"1":{"650":1,"651":1,"689":1,"691":1},"2":{"2":2,"3":3,"4":1,"5":2,"9":2,"11":14,"12":2,"13":2,"14":2,"15":1,"21":1,"30":1,"31":7,"32":1,"33":5,"34":14,"35":6,"37":4,"38":1,"43":1,"45":1,"46":3,"47":5,"48":4,"49":1,"50":5,"51":4,"52":2,"55":3,"56":3,"57":3,"60":1,"62":1,"65":3,"67":2,"68":4,"69":2,"73":2,"74":2,"77":3,"90":1,"91":1,"92":3,"94":4,"95":2,"96":1,"97":1,"99":1,"100":1,"101":4,"103":4,"104":2,"105":1,"106":5,"107":2,"110":3,"111":7,"112":2,"113":2,"114":2,"115":3,"117":1,"119":1,"124":1,"128":2,"130":1,"131":2,"134":4,"136":1,"143":1,"144":2,"145":2,"146":1,"152":1,"156":3,"165":1,"169":2,"170":2,"171":1,"177":1,"183":1,"187":1,"188":2,"189":1,"190":2,"191":1,"194":1,"200":1,"203":2,"204":2,"205":2,"206":1,"212":1,"217":2,"218":3,"219":1,"220":1,"221":4,"222":1,"225":1,"227":2,"230":1,"231":1,"232":1,"233":1,"236":1,"237":1,"238":1,"240":1,"242":6,"243":2,"245":3,"246":1,"249":1,"250":1,"251":3,"252":3,"254":1,"255":2,"256":1,"257":5,"258":2,"261":2,"263":1,"267":3,"268":2,"278":1,"279":1,"283":2,"285":1,"288":5,"299":2,"303":2,"308":3,"309":2,"310":1,"313":1,"314":1,"317":1,"318":2,"320":3,"321":1,"328":2,"329":3,"333":2,"334":5,"336":2,"337":2,"338":3,"339":1,"341":2,"342":1,"343":1,"344":4,"345":1,"348":1,"349":6,"353":3,"354":2,"355":1,"358":1,"359":1,"362":1,"363":1,"365":3,"366":1,"367":1,"374":2,"376":1,"377":1,"378":1,"379":2,"383":3,"384":1,"385":3,"387":1,"390":1,"398":1,"399":4,"400":2,"402":8,"403":1,"404":2,"409":1,"417":3,"419":1,"420":1,"421":2,"423":1,"424":1,"427":1,"428":1,"429":1,"440":1,"441":3,"442":4,"443":3,"444":6,"445":1,"446":2,"447":1,"448":1,"449":1,"452":1,"453":1,"456":5,"457":1,"458":1,"461":4,"462":1,"463":1,"464":8,"465":9,"467":1,"469":1,"470":2,"471":3,"472":2,"473":2,"474":1,"477":3,"478":1,"481":1,"482":1,"485":4,"486":1,"487":1,"488":3,"489":4,"490":1,"491":9,"492":1,"493":2,"497":1,"498":1,"503":3,"506":1,"508":1,"509":2,"515":2,"516":3,"517":3,"519":3,"520":5,"522":3,"523":2,"524":1,"531":4,"532":2,"533":4,"534":2,"538":1,"540":6,"541":3,"542":2,"543":1,"544":2,"545":2,"548":1,"551":2,"552":2,"553":1,"555":1,"556":2,"557":1,"558":2,"560":4,"561":1,"562":3,"564":1,"565":1,"567":1,"568":1,"575":2,"592":1,"593":1,"595":1,"596":2,"600":1,"601":1,"603":1,"605":1,"609":1,"610":1,"612":1,"616":2,"619":1,"625":1,"628":4,"629":3,"634":4,"635":7,"636":7,"638":3,"639":2,"643":1,"644":1,"646":1,"648":2,"649":1,"650":1,"654":1,"657":1,"663":2,"666":1,"667":2,"668":2,"670":3,"671":2,"672":3,"674":1,"675":4,"677":3,"678":2,"679":2,"680":2,"681":7,"682":1,"685":2,"689":1,"690":2,"691":4,"692":2,"693":4,"695":1,"696":3,"698":1,"700":4,"704":1,"708":2,"710":1,"718":1,"720":2,"721":1,"723":1,"724":1,"730":4,"731":2,"732":1,"734":2,"736":1,"737":1,"738":1,"741":4,"742":3,"745":2,"746":2,"747":1}}],["um",{"0":{"36":1,"66":1,"69":1,"108":1,"109":1,"115":1,"132":1,"145":1,"148":1,"149":1,"170":1,"173":1,"174":1,"186":1,"189":1,"195":1,"205":1,"208":1,"209":1,"244":1,"276":1,"296":1,"316":1,"319":1,"338":1,"361":1,"364":1,"375":1,"400":1,"402":1,"403":1,"404":1,"428":1,"429":1,"430":1,"450":1,"452":1,"454":1,"460":1,"475":1,"479":1,"484":1,"526":1,"553":1,"556":1,"625":1,"627":1,"685":1,"703":1,"731":1,"734":1},"1":{"67":1,"68":1,"69":1,"110":1,"111":1,"196":1,"401":1,"402":1,"403":1,"404":1,"405":1,"406":1,"429":1,"430":1,"431":1,"432":1,"433":1,"434":1,"451":1,"452":1,"455":1,"461":1,"462":1,"463":1,"485":1,"486":1,"487":1,"626":1,"686":1},"2":{"2":5,"3":2,"9":1,"11":30,"12":7,"13":3,"14":1,"15":1,"20":1,"21":1,"23":1,"25":2,"27":1,"29":1,"30":1,"31":1,"32":1,"33":4,"34":26,"35":15,"36":1,"37":4,"38":1,"39":3,"42":1,"43":2,"44":1,"46":3,"47":3,"48":2,"49":3,"50":4,"51":4,"52":2,"53":1,"55":4,"56":4,"60":1,"62":2,"64":1,"65":4,"66":1,"67":1,"68":2,"70":1,"74":5,"77":2,"87":1,"89":1,"90":3,"92":1,"93":2,"96":2,"98":1,"99":3,"101":6,"102":1,"105":4,"106":4,"110":2,"111":7,"112":4,"113":1,"114":6,"115":3,"116":1,"118":1,"120":1,"121":1,"122":2,"126":1,"128":3,"129":1,"130":1,"131":1,"134":4,"135":4,"137":1,"140":1,"142":1,"145":5,"146":3,"147":4,"148":3,"149":2,"152":1,"155":1,"156":3,"157":2,"159":4,"164":1,"165":1,"166":2,"168":1,"170":5,"171":3,"172":4,"173":3,"174":2,"180":1,"183":1,"186":3,"187":1,"189":3,"190":3,"191":4,"194":1,"195":1,"198":1,"199":1,"200":4,"201":1,"203":1,"205":4,"206":3,"207":4,"208":3,"209":2,"212":1,"215":1,"216":2,"217":9,"218":5,"219":4,"220":1,"221":1,"222":3,"224":1,"225":2,"226":6,"227":5,"228":2,"231":10,"232":2,"233":2,"234":4,"237":1,"239":3,"242":2,"243":4,"244":6,"245":8,"248":3,"249":1,"250":1,"251":3,"252":3,"255":1,"257":6,"258":3,"259":2,"260":1,"261":4,"262":6,"263":2,"265":1,"268":2,"270":1,"276":2,"277":2,"279":6,"283":1,"285":1,"287":1,"288":2,"290":1,"296":2,"297":2,"298":1,"299":6,"303":1,"306":1,"309":2,"311":1,"313":2,"316":2,"317":2,"318":3,"319":1,"320":6,"328":2,"330":1,"333":1,"334":1,"335":1,"336":1,"337":2,"338":2,"341":1,"343":1,"344":5,"345":3,"346":1,"347":3,"348":5,"349":12,"351":1,"354":2,"356":1,"358":3,"361":2,"362":2,"363":3,"364":1,"365":6,"374":1,"375":2,"377":1,"379":2,"385":3,"386":2,"387":3,"389":1,"398":3,"399":1,"400":4,"401":1,"402":3,"403":2,"404":5,"407":2,"411":1,"417":1,"418":2,"420":4,"421":1,"424":2,"427":2,"428":1,"430":4,"431":3,"436":5,"437":1,"440":4,"441":6,"442":10,"443":3,"444":3,"445":3,"446":1,"447":7,"448":7,"450":3,"451":2,"452":1,"454":6,"455":2,"456":12,"457":2,"459":2,"461":10,"462":3,"463":3,"464":17,"465":8,"466":2,"467":1,"468":1,"469":2,"470":2,"471":1,"472":1,"475":3,"476":1,"477":5,"478":5,"479":5,"480":1,"481":2,"483":3,"485":10,"486":5,"487":4,"488":13,"489":2,"490":4,"491":7,"492":2,"493":7,"497":2,"500":2,"501":2,"502":2,"503":2,"505":1,"507":2,"509":2,"510":1,"511":1,"515":1,"516":1,"517":1,"519":2,"520":2,"522":2,"523":3,"524":3,"525":3,"526":2,"529":2,"531":7,"532":2,"533":4,"534":4,"535":1,"538":2,"540":1,"541":2,"543":2,"544":3,"545":5,"547":2,"548":1,"551":1,"552":1,"553":2,"554":2,"555":1,"556":3,"557":2,"558":2,"559":1,"560":1,"561":2,"562":6,"563":1,"564":1,"565":1,"566":1,"568":1,"569":2,"570":1,"571":3,"572":3,"573":2,"574":5,"575":2,"576":2,"577":2,"580":2,"583":2,"584":2,"585":2,"586":1,"589":1,"595":1,"596":2,"599":2,"601":2,"602":1,"603":2,"604":2,"605":3,"608":2,"610":2,"611":1,"612":3,"613":2,"615":2,"617":1,"618":1,"619":1,"621":1,"622":1,"625":1,"626":1,"628":4,"629":1,"630":2,"633":1,"634":2,"635":7,"636":9,"638":5,"639":1,"642":2,"644":2,"645":1,"646":2,"647":2,"648":1,"650":2,"654":2,"656":2,"660":5,"662":1,"664":1,"665":2,"666":2,"667":1,"668":8,"671":3,"672":1,"673":3,"675":4,"677":2,"678":4,"679":7,"680":3,"681":9,"682":5,"685":3,"686":2,"688":2,"690":3,"691":1,"692":1,"693":1,"695":1,"697":1,"698":1,"699":2,"700":3,"705":1,"706":1,"707":2,"709":1,"711":2,"716":1,"717":1,"718":1,"719":3,"720":1,"721":1,"726":3,"728":2,"730":8,"731":6,"733":1,"734":3,"737":1,"739":1,"740":1,"741":1,"742":1,"745":5,"746":1,"748":1,"753":1,"754":1,"755":1}}],["é",{"0":{"154":1,"179":1,"197":1,"214":1,"539":2,"714":1,"737":1},"1":{"180":1,"715":1,"716":1},"2":{"2":2,"3":3,"9":1,"10":2,"11":4,"12":1,"13":1,"15":1,"22":2,"26":1,"30":1,"31":1,"33":1,"34":3,"35":7,"37":1,"39":1,"42":3,"43":4,"44":2,"46":9,"47":1,"49":1,"50":2,"51":2,"52":2,"53":1,"55":2,"56":1,"57":2,"60":2,"62":2,"67":1,"74":2,"77":3,"80":1,"87":1,"90":3,"92":1,"93":1,"94":2,"96":1,"97":1,"99":3,"101":3,"102":1,"103":2,"105":2,"106":4,"108":1,"110":3,"111":6,"112":3,"113":5,"114":1,"115":4,"116":1,"117":1,"124":1,"128":2,"131":2,"135":3,"142":1,"143":2,"145":1,"151":2,"152":1,"156":4,"159":1,"165":2,"170":1,"176":2,"177":1,"183":2,"184":1,"187":2,"189":1,"191":4,"193":2,"194":1,"203":2,"205":1,"211":2,"212":1,"216":1,"217":1,"218":1,"219":1,"220":1,"221":1,"224":2,"227":1,"230":1,"231":5,"232":1,"234":5,"238":1,"239":1,"241":1,"242":5,"243":1,"244":2,"245":1,"247":1,"248":2,"251":3,"252":2,"254":1,"255":1,"256":1,"257":1,"259":3,"261":3,"262":1,"270":1,"272":1,"273":2,"275":1,"276":2,"278":1,"279":3,"283":1,"285":1,"290":1,"292":1,"293":2,"295":1,"296":2,"298":1,"299":3,"303":1,"310":2,"311":1,"313":1,"315":1,"316":2,"317":1,"318":1,"320":1,"321":1,"323":1,"328":1,"329":1,"331":1,"333":1,"336":2,"337":4,"338":4,"339":2,"341":4,"342":2,"343":2,"344":2,"345":1,"347":3,"348":2,"349":12,"355":2,"356":1,"358":1,"360":1,"361":2,"362":1,"363":1,"365":1,"366":1,"369":1,"377":1,"379":5,"381":3,"383":1,"384":1,"385":1,"389":2,"399":3,"400":1,"402":1,"403":1,"404":2,"409":2,"413":2,"417":2,"418":1,"420":1,"421":2,"422":2,"424":3,"425":1,"426":3,"427":2,"437":1,"440":1,"441":2,"442":5,"443":3,"444":5,"445":3,"446":1,"451":1,"452":4,"455":1,"456":6,"457":2,"461":1,"462":2,"463":1,"464":8,"465":3,"466":1,"467":2,"468":1,"470":1,"471":2,"472":1,"473":2,"477":3,"478":3,"479":1,"480":1,"481":2,"485":1,"486":2,"487":2,"488":8,"489":2,"490":1,"491":2,"493":1,"495":1,"497":2,"500":2,"503":3,"507":1,"508":1,"509":1,"510":1,"512":1,"515":1,"516":2,"520":2,"521":1,"523":1,"524":1,"525":1,"529":1,"531":4,"532":2,"533":1,"534":5,"535":3,"537":1,"538":1,"541":1,"542":1,"543":2,"544":1,"545":3,"546":1,"548":1,"551":2,"552":5,"553":1,"554":1,"555":4,"556":2,"559":1,"563":1,"564":3,"566":1,"569":1,"571":2,"572":1,"575":1,"576":1,"577":1,"580":2,"581":2,"582":2,"583":2,"584":2,"585":3,"586":2,"587":2,"588":3,"589":2,"590":2,"591":1,"594":1,"595":1,"596":3,"604":1,"605":2,"608":3,"613":1,"622":1,"625":1,"628":7,"629":1,"630":3,"632":1,"634":1,"635":5,"636":9,"637":1,"638":1,"639":2,"647":1,"650":1,"653":1,"657":2,"658":1,"659":2,"660":1,"663":1,"665":2,"666":6,"667":2,"668":5,"669":1,"670":1,"671":2,"672":1,"673":3,"674":2,"675":2,"676":1,"677":3,"678":3,"679":2,"681":13,"682":7,"685":2,"690":1,"693":1,"695":2,"696":2,"697":1,"699":3,"700":1,"702":1,"708":1,"721":2,"723":2,"725":2,"729":1,"730":4,"731":1,"732":1,"736":1,"739":1,"740":3,"741":1,"742":1,"745":3,"746":3,"747":1,"748":1}}],["vulnerável",{"2":{"638":1}}],["vulneráveis",{"2":{"629":1,"638":1}}],["vulnerabilidade",{"2":{"628":1,"635":2}}],["vítima",{"2":{"628":1}}],["vídeos",{"2":{"329":2}}],["vídeo",{"2":{"135":1,"329":1,"533":2}}],["vsyncs",{"2":{"554":1}}],["vsync",{"2":{"554":1}}],["vs",{"2":{"416":1}}],["vjeux",{"2":{"390":1}}],["v8",{"2":{"389":1,"745":1}}],["v8a",{"2":{"65":4,"168":1,"656":2}}],["vc",{"2":{"320":3,"365":3,"548":2}}],["vêm",{"2":{"636":1,"722":1}}],["vê",{"2":{"268":1,"288":1,"309":1,"354":1,"555":1,"560":1,"599":1}}],["v",{"2":{"202":2,"232":4,"390":1,"404":1,"436":2,"650":1,"651":1}}],["vm",{"2":{"149":2,"320":1,"365":1,"455":2,"480":2}}],["v7a",{"2":{"65":2,"656":1}}],["vy",{"2":{"48":1}}],["vx",{"2":{"48":1}}],["válida",{"2":{"650":1}}],["válidas",{"2":{"516":1}}],["válido",{"2":{"638":1}}],["várias",{"2":{"42":1,"47":1,"96":1,"105":1,"126":1,"229":1,"320":1,"347":1,"365":1,"471":1,"537":1,"541":1,"557":1,"601":1,"610":1,"626":1,"644":1,"675":1,"679":1,"682":1,"694":1}}],["vários",{"2":{"11":1,"34":1,"47":1,"48":1,"50":1,"52":1,"59":1,"64":2,"95":1,"104":1,"115":1,"248":1,"336":1,"347":1,"387":1,"417":1,"420":1,"440":1,"471":1,"491":1,"534":1,"574":1,"656":1,"668":1,"673":1,"678":1,"681":1,"686":1,"731":1}}],["vá",{"2":{"38":1,"135":1,"185":1,"244":1,"268":1,"288":1,"309":1,"312":1,"354":1,"357":1,"547":1,"599":1,"603":1,"608":1,"612":1,"615":1,"616":1,"642":1,"646":1,"663":1}}],["vemos",{"2":{"557":1}}],["vem",{"2":{"386":1,"390":1,"417":1,"593":1,"631":1,"672":1,"674":1,"677":1,"687":1,"720":1,"741":1}}],["venha",{"2":{"67":1,"686":1}}],["vejamos",{"2":{"111":1}}],["veja",{"2":{"60":1,"74":1,"202":1,"344":1,"349":1,"399":1,"479":1,"739":1}}],["velocity",{"2":{"48":1}}],["velocidades",{"2":{"619":1}}],["velocidade",{"2":{"47":1,"48":1,"251":1,"533":1,"539":1,"744":1}}],["vezes",{"2":{"32":1,"35":3,"37":1,"39":1,"95":1,"104":1,"112":2,"116":1,"153":1,"166":1,"178":1,"213":1,"219":1,"220":1,"221":1,"252":1,"333":1,"347":1,"349":1,"407":1,"446":1,"532":1,"534":1,"544":1,"549":1,"552":2,"557":2,"598":1,"607":1,"629":2,"641":1,"675":1,"676":1,"677":1,"678":1}}],["vez",{"0":{"735":1},"2":{"11":1,"34":1,"51":1,"63":1,"67":2,"75":1,"92":1,"94":1,"101":1,"103":1,"111":1,"113":1,"116":1,"118":1,"122":1,"144":1,"169":1,"188":1,"204":1,"218":1,"221":1,"222":3,"227":1,"228":1,"234":1,"236":1,"242":1,"262":1,"279":1,"299":1,"320":1,"329":2,"338":1,"349":1,"365":1,"402":1,"409":1,"456":1,"464":2,"465":3,"479":1,"483":1,"488":1,"489":1,"491":1,"497":1,"511":1,"532":2,"540":1,"543":2,"568":1,"573":1,"574":1,"576":1,"577":1,"599":1,"608":1,"615":1,"629":1,"637":1,"642":1,"652":1,"658":1,"666":1,"668":2,"672":1,"673":1,"677":1,"682":1,"730":1,"735":1,"736":1,"745":1,"747":1}}],["vertical",{"2":{"731":2}}],["verticalmente",{"2":{"226":1}}],["veryexpensive",{"2":{"573":9}}],["veremos",{"2":{"544":1}}],["verbose",{"2":{"711":1,"712":1,"713":1}}],["verbosename",{"2":{"576":2}}],["verb",{"2":{"332":1}}],["verbalizará",{"2":{"3":1}}],["vermelha",{"2":{"218":3,"223":3,"562":1,"603":1,"612":1,"619":1,"646":1}}],["vermelho",{"0":{"82":1},"2":{"128":1}}],["versus",{"2":{"629":1}}],["versionamento",{"2":{"728":1}}],["versions",{"2":{"166":1}}],["version",{"2":{"146":2,"171":2,"190":2,"206":1,"259":4,"268":3,"278":4,"288":3,"298":4,"309":3,"354":3,"383":1,"563":2,"564":2,"722":1,"725":4}}],["versões",{"0":{"717":1,"724":1,"746":1},"1":{"718":1,"719":1,"720":1,"721":1,"722":1,"723":1,"724":1,"725":1,"726":1,"727":1,"728":1,"729":1,"747":1,"748":1},"2":{"139":1,"166":1,"191":1,"200":3,"283":2,"303":2,"452":1,"538":1,"563":1,"595":2,"626":1,"635":1,"648":1,"696":1,"717":1,"718":1,"723":1,"724":1,"725":1,"734":2,"741":2,"746":2,"751":1,"755":1}}],["versa",{"2":{"89":1,"95":1,"98":1,"104":1,"672":1,"693":1}}],["versão",{"0":{"146":1,"171":1,"190":1,"206":1,"283":1,"303":1,"383":1,"563":1,"564":1,"626":1,"655":1,"729":1},"2":{"43":1,"65":1,"75":1,"131":1,"135":1,"139":1,"144":3,"146":1,"156":1,"169":3,"171":1,"184":1,"185":1,"186":2,"187":2,"188":3,"190":2,"191":3,"200":4,"204":3,"206":2,"270":2,"273":1,"279":1,"283":2,"290":2,"293":1,"299":1,"303":2,"312":1,"313":3,"357":1,"358":4,"383":5,"506":1,"529":1,"563":3,"564":3,"567":1,"593":1,"596":2,"600":1,"626":1,"648":1,"653":1,"655":2,"656":1,"658":2,"660":1,"687":1,"696":1,"710":1,"718":1,"721":2,"724":1,"726":3,"734":1,"741":6,"742":1,"746":4,"747":1}}],["verdade",{"2":{"115":1,"318":1,"363":1,"399":1,"577":1,"628":1,"636":1,"674":1,"745":1}}],["verdadeira",{"2":{"9":1}}],["verdadeiro",{"2":{"2":1,"15":1,"24":1,"251":1,"252":1,"542":1,"747":1}}],["verde",{"0":{"82":1},"2":{"149":1,"174":1,"209":1,"223":3,"562":1}}],["verifier",{"2":{"636":4}}],["verifique",{"2":{"75":1,"142":1,"168":1,"203":1,"246":1,"265":1,"278":1,"287":1,"298":1,"306":1,"343":1,"351":1,"390":1,"549":1,"554":1,"599":1,"608":2,"619":2,"642":1,"706":1,"708":1}}],["verificados",{"2":{"735":1}}],["verificado",{"2":{"681":1}}],["verifica",{"2":{"636":1,"671":1,"672":1,"682":1}}],["verificações",{"2":{"330":1}}],["verificação",{"2":{"56":1,"507":1,"540":1,"628":1,"636":4,"672":2,"736":1,"737":1}}],["verificará",{"2":{"636":1,"726":1}}],["verificar",{"2":{"67":4,"73":1,"76":1,"111":1,"259":3,"278":1,"298":1,"464":1,"488":1,"507":1,"573":1,"625":1,"681":1,"696":1,"721":1,"726":1,"734":1,"742":1}}],["verificando",{"0":{"36":1},"2":{"507":1}}],["verificável",{"2":{"12":1,"21":1}}],["verá",{"2":{"65":1,"114":1,"325":1,"371":1,"487":1,"533":1,"555":1,"559":1,"560":1,"603":1,"608":1,"612":1,"646":1,"660":1}}],["ver",{"2":{"56":1,"129":1,"149":1,"152":1,"153":1,"174":1,"177":1,"178":1,"194":1,"196":1,"209":1,"212":1,"213":1,"219":1,"235":1,"245":1,"313":1,"325":1,"344":1,"358":1,"371":1,"402":1,"418":2,"442":1,"452":1,"459":1,"464":1,"477":1,"483":1,"488":1,"503":2,"523":1,"548":1,"551":2,"554":2,"555":2,"556":2,"568":1,"569":1,"576":2,"599":1,"608":1,"624":1,"636":1,"642":1,"654":1,"662":1,"663":1,"680":1,"689":1,"734":1,"742":2,"745":1}}],["verossímeis",{"2":{"45":1}}],["vontade",{"2":{"338":1,"387":1}}],["void",{"2":{"110":1,"111":1,"224":1,"225":1,"226":1,"227":1,"228":1,"229":1,"230":1,"232":2,"233":2,"234":1,"259":1,"278":1,"279":6,"402":1,"404":2,"424":4,"427":1,"430":4,"431":6,"443":1,"454":2,"461":1,"464":4,"465":1,"466":3,"467":3,"468":3,"485":1,"490":3,"493":1,"524":1}}],["voiceover",{"0":{"39":1},"2":{"0":1,"3":1,"6":2,"14":3,"15":1,"24":1,"28":1,"35":4,"39":8}}],["voluntários",{"2":{"379":1}}],["volume",{"2":{"35":2,"38":5}}],["volte",{"2":{"149":1,"209":1,"603":1,"612":1,"646":1}}],["voltando",{"0":{"749":1},"1":{"750":1,"751":1}}],["volta",{"2":{"50":2,"105":1,"111":1,"115":1,"279":1,"299":1,"421":2,"441":1,"442":1,"636":1,"660":1,"699":1,"750":1}}],["voltará",{"2":{"217":1}}],["voltar",{"2":{"31":2,"48":1,"279":2,"299":2,"598":1,"607":1,"629":1,"641":1}}],["você",{"0":{"457":1,"458":1,"481":1,"482":1,"533":1},"2":{"9":1,"14":1,"38":3,"39":3,"41":1,"42":1,"43":3,"46":2,"47":2,"48":1,"49":1,"50":7,"52":1,"53":1,"55":2,"56":3,"57":4,"60":2,"62":3,"63":4,"64":1,"65":11,"66":2,"67":16,"68":5,"69":4,"70":1,"73":1,"74":1,"76":3,"80":1,"86":1,"92":4,"94":1,"95":2,"96":4,"101":2,"103":1,"104":2,"105":4,"108":1,"110":2,"111":3,"112":3,"113":2,"114":7,"115":3,"116":2,"117":1,"118":1,"120":2,"126":2,"129":1,"131":4,"132":2,"133":1,"134":3,"135":3,"136":1,"137":3,"139":2,"140":2,"141":1,"142":3,"143":2,"144":1,"145":6,"146":2,"147":3,"148":1,"149":3,"151":1,"152":3,"153":1,"154":1,"155":2,"156":8,"157":1,"159":5,"164":3,"165":1,"166":3,"167":1,"168":2,"169":1,"170":6,"171":2,"172":3,"173":1,"174":3,"176":1,"177":3,"178":1,"179":1,"180":2,"182":3,"183":1,"184":1,"185":1,"186":2,"187":1,"188":1,"189":6,"190":3,"191":5,"193":1,"194":3,"195":1,"196":1,"197":1,"198":2,"199":3,"200":9,"201":2,"202":2,"203":1,"204":1,"205":6,"206":2,"207":3,"208":1,"209":4,"211":1,"212":3,"213":1,"214":1,"215":2,"216":1,"217":5,"218":6,"219":4,"220":3,"221":3,"222":1,"224":1,"226":2,"227":1,"228":1,"229":1,"231":1,"232":1,"235":3,"236":1,"237":3,"238":3,"239":3,"240":1,"241":1,"242":3,"243":1,"244":2,"245":8,"250":1,"255":2,"256":2,"257":4,"258":3,"259":1,"262":2,"263":1,"270":2,"272":2,"278":2,"279":6,"280":1,"281":1,"282":1,"283":6,"284":1,"285":3,"290":2,"292":2,"298":2,"299":6,"300":1,"301":1,"302":1,"303":6,"304":1,"306":1,"313":11,"317":1,"318":1,"319":1,"320":3,"322":1,"324":1,"325":4,"326":1,"328":7,"329":1,"330":4,"331":4,"332":2,"333":3,"334":2,"336":2,"337":1,"338":1,"339":4,"341":1,"343":2,"344":3,"345":5,"346":2,"347":7,"348":6,"349":12,"351":1,"358":12,"362":1,"363":1,"364":1,"365":3,"368":1,"370":1,"371":4,"372":1,"374":3,"375":2,"377":1,"378":1,"379":2,"381":3,"382":1,"383":2,"384":2,"386":5,"387":5,"389":2,"390":1,"398":1,"399":1,"402":7,"403":3,"404":6,"406":1,"407":4,"409":1,"412":1,"413":6,"417":4,"418":1,"419":1,"420":3,"426":2,"428":1,"429":1,"430":1,"434":1,"435":1,"436":3,"437":1,"438":1,"440":3,"441":6,"442":3,"444":1,"445":2,"446":3,"447":3,"448":7,"450":2,"451":4,"452":2,"454":4,"455":2,"456":8,"457":9,"458":5,"459":6,"461":5,"462":4,"463":3,"464":8,"465":3,"466":1,"467":4,"468":2,"470":5,"471":2,"475":2,"476":3,"477":4,"478":1,"479":3,"480":2,"481":9,"482":5,"483":7,"485":5,"486":3,"487":7,"488":6,"489":1,"490":3,"491":6,"492":2,"493":8,"497":2,"499":1,"501":1,"503":2,"505":1,"507":2,"508":1,"509":1,"510":2,"516":3,"517":1,"518":2,"519":2,"520":7,"521":1,"523":1,"525":3,"527":1,"528":1,"529":2,"531":2,"532":2,"533":4,"534":3,"535":1,"538":2,"540":6,"541":3,"542":3,"543":2,"545":1,"546":1,"547":1,"548":4,"549":5,"550":1,"551":2,"552":4,"553":3,"554":3,"555":4,"556":3,"557":2,"558":3,"559":2,"560":3,"561":2,"562":4,"565":2,"566":3,"567":2,"568":1,"569":2,"571":1,"572":2,"573":1,"574":2,"575":1,"576":5,"578":1,"580":2,"581":3,"582":1,"583":3,"584":3,"585":3,"586":4,"588":1,"593":1,"594":1,"595":6,"596":1,"598":3,"599":2,"600":1,"601":2,"602":2,"603":7,"604":1,"605":3,"607":3,"608":6,"609":1,"610":2,"611":2,"612":6,"613":1,"615":1,"617":2,"618":2,"619":6,"622":1,"624":2,"625":2,"626":1,"627":1,"628":3,"629":2,"634":2,"635":6,"636":2,"637":1,"638":1,"641":3,"642":1,"643":1,"644":2,"645":2,"646":6,"647":1,"648":1,"649":1,"650":1,"651":2,"652":3,"654":4,"655":3,"656":3,"657":2,"658":3,"660":2,"662":2,"663":1,"664":1,"665":1,"666":3,"667":1,"668":5,"670":1,"671":3,"672":2,"673":7,"674":4,"675":6,"676":4,"677":8,"678":2,"679":4,"680":3,"681":5,"682":9,"683":3,"685":2,"687":1,"689":1,"691":3,"692":1,"693":2,"695":1,"696":2,"697":2,"699":1,"700":1,"701":2,"702":1,"703":1,"704":3,"705":1,"706":4,"709":2,"710":1,"711":3,"716":1,"717":1,"718":1,"721":4,"722":1,"724":2,"725":1,"726":5,"728":3,"729":1,"730":4,"731":3,"733":1,"734":2,"736":2,"737":2,"739":1,"741":5,"742":4,"745":5,"746":2,"747":6,"748":4,"750":1}}],["vazada",{"2":{"488":1}}],["vazio",{"2":{"276":1,"296":1,"316":1,"361":1,"493":2,"529":2,"589":1,"592":1}}],["vazia",{"2":{"221":1}}],["vantagem",{"2":{"400":1,"638":1,"676":1}}],["vantagens",{"2":{"41":1,"437":1,"682":1,"717":1}}],["var",{"2":{"92":1,"259":1,"299":2,"367":1,"390":1,"404":1,"430":1,"431":2,"466":1,"467":1}}],["variáveis",{"0":{"652":1},"2":{"68":2,"142":1,"168":1,"203":3,"345":1,"629":2,"630":1,"652":3}}],["variável",{"2":{"10":1,"67":1,"68":1,"134":1,"142":1,"166":1,"168":1,"191":4,"203":4,"349":5,"442":1,"663":1,"742":2}}],["variedade",{"2":{"46":1,"94":1,"103":1,"240":1}}],["variant",{"2":{"596":1}}],["variantes",{"0":{"595":1},"2":{"586":5,"595":4}}],["variante",{"2":{"122":1,"596":1}}],["variações",{"2":{"595":3}}],["varia",{"2":{"379":1}}],["variadas",{"2":{"39":1}}],["variaram",{"2":{"699":1}}],["variarem",{"2":{"131":1}}],["variar",{"2":{"0":1,"143":1}}],["vai",{"2":{"50":1,"252":1,"337":1,"557":1,"581":1,"677":1}}],["vamos",{"2":{"46":1,"113":1,"145":1,"153":1,"170":1,"178":1,"189":1,"196":1,"205":1,"213":1,"242":1,"245":1,"270":1,"274":1,"279":2,"290":1,"294":1,"299":2,"343":1,"349":1,"376":1,"384":1,"429":1,"442":1,"444":1,"467":1,"477":1,"478":1,"479":2,"599":1,"608":1,"642":1,"675":1,"731":1}}],["valioso",{"2":{"671":1}}],["validity",{"2":{"650":1,"651":1}}],["validação",{"2":{"537":1}}],["validar",{"2":{"242":1}}],["val",{"2":{"92":2,"256":1,"259":8,"298":2,"299":1,"402":2,"404":1,"422":2,"427":2,"431":9,"462":2,"464":2,"465":1,"466":1,"467":10}}],["valueof",{"2":{"431":1}}],["value=",{"2":{"231":3,"232":2,"680":1,"692":2}}],["values",{"2":{"224":3,"225":3,"226":3,"227":3,"228":3,"229":3,"230":3,"234":3,"395":1}}],["values=",{"2":{"224":1,"225":1,"226":1,"227":1,"228":1,"229":1,"230":1,"234":1}}],["valuexy",{"2":{"51":3,"54":1}}],["valuetext",{"0":{"19":1}}],["valuenow",{"0":{"18":1}}],["valuemin",{"0":{"17":1}}],["valuemax",{"0":{"16":1}}],["value",{"2":{"8":1,"46":2,"49":1,"50":1,"51":2,"52":1,"53":1,"55":1,"113":2,"224":7,"225":7,"226":7,"227":7,"228":7,"229":7,"230":7,"231":6,"233":14,"234":7,"317":1,"320":2,"362":1,"365":2,"431":6,"692":5}}],["valores",{"0":{"49":1,"51":1},"2":{"45":1,"49":1,"50":1,"51":4,"52":2,"56":1,"85":2,"86":1,"120":1,"121":1,"221":1,"231":3,"233":1,"234":2,"259":1,"263":1,"348":1,"399":1,"424":2,"441":1,"442":3,"463":1,"480":1,"487":1,"633":1,"636":2,"668":1}}],["valor",{"0":{"55":1,"116":1},"2":{"4":1,"8":1,"13":6,"14":1,"15":1,"16":1,"17":1,"18":1,"25":1,"26":1,"28":1,"30":1,"46":7,"47":1,"49":3,"50":3,"51":2,"55":5,"56":2,"60":1,"65":1,"111":1,"113":2,"116":2,"117":1,"200":1,"217":1,"224":1,"225":1,"226":1,"227":1,"229":2,"231":4,"233":1,"234":1,"278":1,"298":1,"348":1,"349":4,"402":1,"424":9,"427":1,"442":4,"465":1,"486":1,"503":1,"540":1,"549":1,"562":2,"630":1,"633":1,"671":1,"681":1,"748":1}}],["vitais",{"2":{"682":2}}],["vite",{"2":{"151":1,"176":1,"193":1,"211":1}}],["violação",{"2":{"628":1,"639":1}}],["violet",{"2":{"88":1}}],["vir",{"2":{"745":1}}],["viram",{"2":{"671":1}}],["virão",{"2":{"586":1}}],["virtuais",{"2":{"149":1,"174":1,"209":1}}],["virtual",{"0":{"149":1,"174":1,"209":1},"2":{"141":1,"147":1,"149":1,"167":1,"172":1,"174":1,"202":1,"207":1,"209":1,"497":1}}],["virtualizedlist",{"2":{"11":1,"34":1,"57":1,"497":2,"500":1,"501":1}}],["vibration",{"2":{"313":1}}],["vida",{"0":{"251":1,"468":1},"1":{"252":1},"2":{"248":1,"279":2,"299":2,"428":1,"452":1,"524":1}}],["vinculá",{"2":{"320":1,"365":1,"377":1}}],["vinculadas",{"2":{"427":1}}],["vinculada",{"2":{"424":1,"428":1}}],["vinculado",{"2":{"409":1}}],["vinculador",{"2":{"310":1,"355":1}}],["vinculados",{"2":{"279":1,"299":1,"329":1,"402":2,"456":1,"706":1}}],["vinculação",{"0":{"409":1,"410":1},"1":{"411":1,"412":1,"413":1}}],["vinculando",{"0":{"377":1,"378":1,"407":1},"1":{"408":1,"409":1,"410":1,"411":1,"412":1,"413":1},"2":{"706":1,"768":1}}],["vincula",{"2":{"50":1}}],["vinculará",{"2":{"409":1}}],["vincular",{"0":{"408":1},"1":{"409":1,"410":1,"411":1,"412":1,"413":1},"2":{"46":1,"376":1,"635":1}}],["vindo",{"2":{"236":1,"449":1,"474":1}}],["vindas",{"2":{"141":1,"167":1,"202":1,"742":1}}],["vivo",{"2":{"106":1,"135":1,"602":1,"603":1,"611":1,"612":1,"645":1,"646":1}}],["vice",{"2":{"89":1,"95":1,"98":1,"104":1,"672":1,"693":1}}],["vias",{"2":{"721":2}}],["via",{"0":{"339":1,"598":1,"599":1,"603":1,"607":1,"608":1,"612":1,"615":1,"641":1,"642":1,"646":1},"2":{"60":1,"133":1,"200":2,"320":1,"328":1,"365":1,"553":1,"599":1,"602":1,"608":1,"611":1,"619":1,"642":1,"645":1,"737":1,"745":1}}],["vigor",{"2":{"58":1}}],["viável",{"2":{"44":1}}],["visa",{"2":{"488":1}}],["visuais",{"2":{"385":1,"500":1,"561":1,"689":1}}],["visualmente",{"2":{"691":1}}],["visualizando",{"2":{"459":1}}],["visualizados",{"2":{"552":1}}],["visualizado",{"2":{"244":1}}],["visualizar",{"2":{"128":2,"244":1,"454":1,"459":1,"525":2,"552":1,"569":1}}],["visualizações",{"0":{"385":1,"444":1,"560":1},"2":{"14":2,"15":1,"28":1,"30":1,"31":1,"33":1,"60":1,"63":1,"74":1,"77":2,"105":1,"106":2,"108":1,"110":1,"111":2,"112":2,"223":1,"251":1,"285":1,"320":2,"347":1,"365":2,"385":5,"386":4,"387":1,"421":4,"422":1,"423":1,"427":1,"441":4,"443":1,"445":1,"499":4,"534":2,"545":1,"556":1,"689":1,"717":1,"731":5}}],["visualização",{"0":{"424":1,"429":1,"540":1,"542":1,"544":1},"2":{"2":4,"3":2,"9":1,"10":1,"14":6,"15":2,"27":1,"30":1,"31":1,"33":1,"37":3,"46":1,"74":4,"77":6,"94":2,"96":1,"101":1,"103":2,"105":1,"106":3,"110":8,"111":14,"113":1,"114":2,"115":1,"119":1,"120":2,"121":3,"122":1,"123":2,"124":1,"223":5,"245":2,"247":1,"251":8,"252":1,"262":1,"263":1,"265":1,"279":1,"285":1,"287":1,"299":1,"306":1,"317":1,"318":1,"321":1,"347":1,"351":1,"362":1,"363":1,"366":1,"385":1,"417":1,"421":1,"422":2,"423":1,"424":1,"426":2,"427":1,"428":1,"429":4,"430":2,"431":1,"434":1,"441":4,"442":4,"443":2,"444":5,"445":1,"497":1,"499":1,"502":1,"503":1,"534":1,"541":1,"542":2,"548":1,"669":1,"673":1,"689":1,"690":4,"700":1,"742":1}}],["visual",{"2":{"9":1,"690":2,"746":1}}],["visto",{"2":{"245":1}}],["vista",{"2":{"24":2}}],["vistas",{"2":{"24":1}}],["visível",{"2":{"216":1,"442":1,"443":1,"497":1,"682":1,"689":1}}],["visíveis",{"2":{"110":1,"262":1}}],["visioncamera",{"2":{"693":1}}],["visita",{"2":{"571":1}}],["visite",{"2":{"187":1,"419":1}}],["visibilidade",{"2":{"111":1}}],["visão",{"0":{"532":1},"1":{"533":1,"534":1,"535":1,"536":1,"537":1,"538":1,"539":1,"540":1,"541":1,"542":1,"543":1,"544":1,"545":1},"2":{"9":1,"10":3,"27":2,"39":1,"106":1,"115":1,"122":1,"251":1,"424":2,"441":1,"738":1,"762":1}}],["viewwithtooltip",{"2":{"690":2}}],["viewpager",{"2":{"731":1}}],["viewports",{"2":{"503":1}}],["viewport",{"2":{"497":1,"499":1}}],["viewprops",{"2":{"424":2}}],["viewregistry",{"2":{"444":2}}],["viewref",{"2":{"113":2}}],["viewid",{"2":{"434":5}}],["viewtreeobserver",{"2":{"431":1}}],["viewmanager>aslist",{"2":{"425":1,"432":1}}],["viewmanager>",{"2":{"425":1,"432":1,"456":1}}],["viewmanagers",{"2":{"421":1}}],["viewmanager",{"0":{"422":1,"425":1,"431":1,"432":1},"2":{"421":2,"425":1,"427":1,"428":1,"432":2,"456":3}}],["viewgroup>",{"2":{"431":1}}],["viewgroupmanager",{"2":{"431":4}}],["viewgroup",{"2":{"387":1,"430":4,"431":4}}],["viewcontroller",{"2":{"318":3,"320":1,"363":3,"365":1}}],["views",{"2":{"252":1,"753":1}}],["viewstyle>>",{"2":{"231":1}}],["viewstyle>",{"2":{"231":3}}],["viewstyle",{"2":{"46":2,"231":2}}],["viewdidload",{"2":{"110":1}}],["view>",{"2":{"2":1,"3":1,"4":2,"5":1,"8":1,"10":1,"26":2,"30":3,"46":2,"53":4,"54":2,"60":2,"92":2,"101":2,"113":4,"114":2,"115":2,"116":2,"122":5,"223":1,"224":3,"225":3,"226":3,"227":3,"228":3,"229":3,"230":3,"231":5,"232":5,"233":3,"234":3,"239":1,"242":1,"244":4,"245":6,"261":2,"262":1,"263":1,"277":1,"297":1,"317":1,"346":2,"347":4,"348":10,"349":4,"362":1,"387":2,"444":4,"445":1,"511":1,"520":1,"573":1,"668":1,"690":2,"692":4,"730":2,"737":3}}],["view",{"0":{"730":1},"2":{"2":1,"3":2,"5":2,"8":1,"10":1,"30":3,"35":1,"46":6,"53":6,"54":4,"58":1,"60":4,"92":1,"101":1,"102":1,"110":2,"113":1,"114":4,"115":8,"116":4,"120":1,"122":6,"223":5,"224":7,"225":7,"226":7,"227":7,"228":7,"229":11,"230":11,"231":9,"232":11,"233":7,"234":7,"239":2,"242":2,"244":5,"245":7,"251":9,"252":2,"261":4,"262":5,"263":5,"277":3,"297":3,"313":1,"317":3,"320":1,"346":2,"347":3,"348":4,"349":3,"358":1,"362":3,"365":1,"387":4,"390":2,"404":2,"421":1,"424":12,"427":3,"428":1,"430":18,"431":35,"434":2,"441":3,"442":3,"443":7,"444":4,"445":1,"456":3,"511":1,"520":2,"548":1,"553":3,"573":2,"668":2,"690":2,"693":1,"730":4,"737":2}}],["svn",{"2":{"728":1}}],["svg",{"2":{"88":1,"399":4}}],["símbolos",{"2":{"662":1}}],["síncrona",{"2":{"455":1,"480":1,"690":3,"700":1}}],["síncronos",{"0":{"455":1,"480":1,"689":1},"2":{"455":1,"480":2,"695":1}}],["síncrono",{"2":{"55":1,"455":1,"480":1,"689":1}}],["ssl",{"0":{"638":1},"2":{"637":2,"638":2}}],["sstring",{"2":{"486":1}}],["série",{"2":{"554":1}}],["sbin",{"2":{"612":1}}],["sb",{"2":{"548":2}}],["sfs",{"2":{"531":1}}],["sf",{"2":{"531":7}}],["skip",{"2":{"548":1}}],["skia",{"2":{"514":2}}],["skyblue",{"2":{"88":1,"224":1,"225":1,"226":1,"227":1,"228":1,"231":7,"233":1,"234":1,"261":1,"262":1,"263":1}}],["sdf",{"2":{"462":4}}],["sdk>",{"2":{"553":1}}],["sdks",{"2":{"142":1,"168":1,"203":1}}],["sdk",{"0":{"142":1,"168":1,"203":1},"2":{"141":2,"142":16,"167":2,"168":16,"202":2,"203":18,"259":2,"278":2,"298":2,"420":1,"552":1,"553":1,"636":1,"718":1}}],["srcroot",{"2":{"722":2}}],["src",{"2":{"283":2,"303":2,"338":1,"424":2,"426":1,"452":1,"456":2,"660":1,"739":5}}],["srgb",{"2":{"85":1}}],["sysctl",{"2":{"715":2}}],["systrace",{"0":{"552":1},"1":{"553":1,"554":1,"555":1},"2":{"551":1,"552":2,"553":4,"576":2}}],["systemversion",{"2":{"564":1}}],["system",{"2":{"68":1,"142":2,"168":2,"203":2,"278":2,"298":2,"436":1,"603":2,"659":1}}],["symbolicate",{"2":{"685":4,"686":1}}],["synchronous",{"2":{"480":3}}],["sync",{"2":{"279":1,"299":1,"402":1,"404":1}}],["snapshots",{"2":{"681":2}}],["snapshot",{"2":{"681":3}}],["snack",{"2":{"156":1,"344":1}}],["snow",{"2":{"88":1}}],["slide",{"2":{"559":1}}],["slider",{"2":{"34":1,"691":1,"692":1}}],["slategray",{"2":{"88":1}}],["slateblue",{"2":{"88":1}}],["sloppiness=clang",{"2":{"68":1}}],["swiftimport",{"2":{"367":1}}],["swift",{"0":{"350":1,"493":1},"1":{"351":1,"352":1,"353":1,"354":1,"355":1,"356":1,"357":1,"358":1,"359":1,"360":1,"361":1,"362":1,"363":1,"364":1,"365":1,"366":1,"367":1,"368":1,"369":1,"370":1,"371":1,"372":1},"2":{"285":1,"358":3,"365":1,"367":1,"386":1,"446":1,"486":1,"493":12,"524":1}}],["switch",{"2":{"11":2,"34":2,"35":1,"431":1}}],["swap",{"2":{"68":1}}],["sched",{"2":{"553":3}}],["scheme",{"2":{"547":2}}],["schemas",{"2":{"403":1}}],["scoping",{"2":{"390":1}}],["scores",{"2":{"317":5,"320":1,"325":1,"362":5,"365":1,"371":1}}],["score",{"2":{"275":1,"295":1,"314":1,"315":1,"317":4,"319":1,"320":1,"359":1,"360":1,"362":4,"364":1}}],["sccache",{"2":{"70":2}}],["scale",{"2":{"58":2,"543":1}}],["scripts",{"2":{"268":1,"288":1,"309":1,"320":1,"354":1,"365":1,"567":1,"574":2,"587":1,"663":1}}],["script",{"2":{"191":3,"320":1,"365":1,"470":1,"548":1,"621":1}}],["scrolleventthrottle=",{"2":{"53":1,"56":1}}],["scrollcontainer",{"2":{"53":2}}],["scrollx",{"2":{"52":3,"53":3}}],["scrollviews",{"2":{"731":1}}],["scrollview>",{"2":{"53":1,"56":1,"387":2,"731":2}}],["scrollview",{"0":{"53":1,"731":1},"2":{"11":1,"34":1,"46":1,"52":1,"53":2,"56":2,"57":1,"111":1,"246":1,"387":3,"420":1,"440":1,"535":2,"730":1,"731":6,"753":1}}],["scrollbar",{"2":{"11":1,"34":1}}],["screen",{"2":{"5":1,"402":1}}],["só",{"2":{"55":1,"57":1,"74":1,"77":1,"92":1,"101":1,"105":1,"156":1,"220":1,"229":1,"257":1,"262":1,"272":1,"292":1,"407":1,"441":1,"452":1,"464":4,"465":1,"480":1,"490":1,"529":1,"540":1,"573":1,"598":1,"607":1,"618":1,"636":1,"638":1,"641":1,"655":1,"668":1,"675":1,"726":1}}],["spawnsync",{"0":{"716":1}}],["span",{"2":{"443":2}}],["space",{"2":{"226":6,"229":6,"231":1,"232":1,"244":1}}],["spread",{"2":{"390":2}}],["sprites",{"2":{"338":2}}],["springgreen",{"2":{"88":1}}],["spring",{"2":{"48":2,"49":1,"51":2,"54":1,"55":2,"60":1}}],["spot",{"2":{"348":2,"349":3}}],["splits",{"2":{"656":1}}],["split",{"2":{"242":1}}],["spinbutton",{"2":{"11":1,"34":1}}],["shexport",{"2":{"574":1}}],["shellcommandunresponsiveexception",{"2":{"710":2}}],["shell",{"0":{"710":1},"2":{"38":2,"126":1,"131":1,"142":4,"168":1,"191":2,"404":2,"548":1,"699":1}}],["sha",{"2":{"636":3}}],["shape",{"2":{"442":1}}],["shadowopacity",{"2":{"233":1}}],["shared",{"2":{"633":3,"634":2}}],["sharedeventproperties",{"2":{"531":1}}],["share",{"2":{"44":1}}],["sh",{"2":{"191":2,"320":1,"365":1,"574":2,"663":1}}],["shift",{"2":{"131":1,"617":1}}],["shorthand",{"2":{"390":1}}],["short",{"2":{"390":1}}],["shouldrasterizeios",{"2":{"542":1}}],["should",{"2":{"430":4}}],["shouldsetrespondercapture",{"2":{"252":1}}],["shouldsetresponder",{"2":{"252":1}}],["shouldset",{"0":{"252":1}}],["shouldcomponentupdate",{"0":{"118":1,"507":1},"2":{"63":2,"112":1,"118":1,"507":1,"540":1,"557":1}}],["showcase",{"2":{"418":1}}],["showdevoptionsdialog",{"2":{"279":1,"299":1}}],["show",{"2":{"135":1,"142":2,"168":1,"203":2,"404":1,"467":6,"533":1}}],["showshorizontalscrollindicator=",{"2":{"53":1}}],["somos",{"2":{"671":1}}],["somekey",{"2":{"493":1}}],["somevalue",{"2":{"466":2,"493":1}}],["someviewcontroller",{"2":{"110":1}}],["some",{"2":{"349":3}}],["something",{"2":{"338":1,"522":1}}],["sometaskname",{"2":{"255":3,"256":2,"257":2}}],["somente",{"0":{"65":1,"334":1},"2":{"35":1,"111":1,"219":1,"328":1,"435":1,"491":1,"581":1,"636":1}}],["sort",{"2":{"576":1}}],["sofre",{"2":{"537":1}}],["sofisticado",{"2":{"426":1}}],["software",{"2":{"67":1,"552":1,"598":1,"607":1,"628":1,"641":1,"673":1,"678":1}}],["sob",{"2":{"402":1,"516":1,"540":1,"541":1,"673":1}}],["sobreviver",{"2":{"143":1}}],["sobrecarga",{"2":{"112":1,"113":1,"118":1,"575":1,"695":1}}],["sobreporá",{"2":{"111":1}}],["sobreposição",{"0":{"278":1,"298":1},"2":{"110":1,"136":1,"541":1,"568":1}}],["sobrepostas",{"2":{"30":1}}],["sobrepostos",{"2":{"30":1}}],["sobre",{"0":{"533":1,"686":1,"687":1},"1":{"688":1,"689":1,"690":1,"691":1,"692":1,"693":1,"694":1,"695":1,"696":1,"697":1},"2":{"5":1,"6":1,"20":1,"34":1,"42":2,"47":1,"56":1,"64":1,"68":1,"70":1,"78":1,"79":1,"96":1,"105":1,"128":1,"131":1,"143":1,"155":1,"180":1,"198":1,"215":1,"216":1,"242":1,"248":1,"259":2,"273":1,"284":1,"293":1,"304":1,"326":1,"334":1,"338":2,"339":1,"344":1,"349":1,"372":1,"384":1,"387":1,"390":1,"398":1,"424":1,"428":1,"435":1,"445":1,"448":1,"459":1,"469":1,"470":1,"483":1,"486":1,"491":1,"497":1,"504":1,"518":1,"525":1,"528":1,"531":4,"541":1,"551":1,"553":2,"568":1,"580":1,"586":1,"589":1,"628":1,"635":1,"652":2,"658":1,"664":1,"674":1,"676":1,"678":1,"680":1,"682":1,"693":1,"694":1,"711":1,"718":1,"723":1,"730":1,"731":1,"738":1,"741":1,"769":1}}],["souber",{"2":{"520":1}}],["sou",{"2":{"344":1,"345":1}}],["sourcemaps",{"2":{"662":1,"685":2}}],["sourcemap",{"2":{"662":1,"663":4}}],["sources",{"2":{"424":4}}],["sourceexts",{"2":{"399":7}}],["source",{"2":{"142":2,"168":2,"338":1,"348":1,"390":1,"594":2,"596":1,"662":1}}],["source=",{"2":{"53":1,"92":1,"101":1,"328":5,"330":2,"331":2,"332":1,"333":1,"334":1,"338":1,"339":1,"348":1,"387":1,"731":25}}],["solicitá",{"2":{"709":1}}],["solicitadas",{"2":{"639":1}}],["solicitados",{"2":{"637":1}}],["solicitado",{"2":{"479":1,"636":1}}],["solicitante",{"2":{"636":1}}],["solicitação",{"2":{"332":1,"334":5,"339":1,"517":1,"519":2,"520":1,"573":1,"629":2,"635":1,"636":3}}],["solicitações",{"0":{"332":1},"2":{"35":2,"255":1,"523":1,"524":2,"541":1,"573":1,"629":1,"636":1,"638":1,"677":1}}],["solicitará",{"2":{"635":1,"733":1}}],["solicitar",{"2":{"279":1,"299":1,"629":1}}],["solicita",{"2":{"123":1,"650":1}}],["solucionar",{"2":{"532":1}}],["soluções",{"2":{"111":1,"473":1,"532":1,"631":1,"673":1}}],["solução",{"0":{"570":1,"619":1,"701":1,"727":1},"1":{"620":1,"621":1,"702":1,"703":1,"704":1,"705":1,"706":1,"707":1,"708":1,"709":1,"710":1,"711":1,"712":1,"713":1,"714":1,"715":1,"716":1,"728":1,"729":1},"2":{"95":1,"104":1,"106":1,"152":1,"177":1,"194":1,"212":1,"259":1,"444":1,"471":1,"472":1,"473":1,"493":1,"523":1,"544":1,"545":1,"560":1,"721":2,"753":1}}],["soloader",{"2":{"279":1,"299":1,"402":6,"404":4}}],["sozinho",{"2":{"62":1,"336":1}}],["s",{"2":{"35":1,"65":1,"67":8,"131":1,"191":1,"430":1,"436":1,"602":1,"611":1,"645":1,"678":1,"699":1,"731":1}}],["si",{"2":{"493":1,"574":1,"636":1,"675":1,"681":1}}],["situação",{"2":{"542":1}}],["situações",{"2":{"43":1,"251":1,"677":1}}],["site",{"2":{"398":1,"561":1,"656":1,"658":1}}],["sites",{"2":{"338":1}}],["silenciosamente",{"2":{"520":1}}],["silicon",{"2":{"168":1}}],["silver",{"2":{"53":1,"88":1}}],["sienna",{"2":{"88":1}}],["sizeflexibility",{"2":{"111":1}}],["size",{"2":{"67":1,"111":2}}],["sign",{"2":{"722":1}}],["signingconfig",{"2":{"653":1}}],["signingconfigs",{"2":{"653":2}}],["signing",{"0":{"658":1},"2":{"549":2,"616":1,"648":1,"658":1}}],["significam",{"2":{"500":1,"552":1,"671":1}}],["significativamente",{"2":{"542":1,"639":2}}],["significativas",{"2":{"539":1}}],["significativa",{"2":{"499":1}}],["significa",{"2":{"57":1,"96":1,"105":1,"111":1,"115":1,"122":1,"223":1,"234":1,"252":1,"261":1,"268":1,"288":1,"309":1,"354":1,"413":1,"464":1,"465":2,"480":1,"489":1,"500":1,"516":1,"521":1,"599":1,"608":1,"636":1,"642":1,"671":1,"675":1,"678":1,"689":1,"745":1}}],["significar",{"2":{"31":1}}],["siga",{"2":{"67":1,"138":1,"143":1,"159":1,"195":1,"209":1,"266":1,"288":1,"307":1,"352":1,"401":1,"406":1,"472":1,"473":1,"525":1,"529":1,"549":1,"570":1,"604":1,"613":1,"622":1,"647":1,"651":1,"658":1,"660":1,"749":1}}],["sido",{"2":{"63":1,"67":1,"117":1,"424":1,"651":1,"695":1,"706":1}}],["singleton",{"2":{"279":2,"299":2}}],["singletons",{"2":{"106":1,"421":1,"441":1}}],["sinta",{"2":{"338":1,"387":1}}],["sintaxe",{"0":{"130":1,"390":1},"2":{"52":1,"130":3,"151":1,"176":1,"193":1,"211":1,"218":2,"329":1,"337":1,"344":1,"345":1,"390":2,"451":1,"465":1,"476":1,"489":1,"520":1,"737":1,"739":1}}],["sintético",{"2":{"251":1}}],["sinalizar",{"2":{"466":2,"490":2,"672":1}}],["sinalizador",{"2":{"65":2,"409":1,"625":1,"662":1,"666":3,"667":2,"692":1,"751":1}}],["sinalizadores",{"2":{"60":1,"65":1,"587":1,"588":1,"592":2,"594":1}}],["sinais",{"2":{"241":1}}],["sincronizar",{"2":{"254":1}}],["sincronização",{"2":{"111":1}}],["sincronia",{"2":{"60":1}}],["simbolizar",{"2":{"685":1}}],["simbolizando",{"0":{"685":1},"1":{"686":1},"2":{"755":1}}],["simbolização",{"0":{"664":1},"2":{"664":2,"685":1}}],["simbólico",{"2":{"67":1}}],["simbólicos",{"2":{"67":1,"68":1}}],["simctl",{"2":{"625":1,"627":1}}],["simplifique",{"2":{"560":1}}],["simplifica",{"2":{"520":1}}],["simplificar",{"2":{"320":1,"365":1,"375":1,"443":1,"465":1,"489":1,"539":1}}],["simpledateformat",{"2":{"462":3}}],["simpleviewmanager",{"2":{"421":2,"422":3,"427":2}}],["simples",{"0":{"273":1,"293":1},"2":{"51":1,"399":1,"427":1,"442":1,"471":1,"520":2,"629":1,"637":1,"652":1,"668":1,"717":1}}],["simultâneo",{"2":{"691":1}}],["simultâneos",{"0":{"691":1},"2":{"248":1,"691":1,"695":1}}],["simultânea",{"2":{"691":1}}],["simultaneamente",{"2":{"42":1,"503":1}}],["simulam",{"2":{"680":1}}],["simular",{"2":{"678":1}}],["simulação",{"2":{"677":2,"678":1}}],["simulações",{"2":{"674":2,"678":1}}],["simulada",{"2":{"677":1}}],["simulado",{"2":{"673":1}}],["simulador",{"0":{"186":1,"623":1,"624":1},"1":{"624":1,"625":1,"626":1,"627":1},"2":{"39":1,"42":1,"77":1,"126":1,"135":1,"184":1,"186":3,"196":1,"328":1,"418":1,"567":1,"568":1,"624":1,"625":1,"682":1,"768":1}}],["simulator=",{"2":{"625":1,"626":1}}],["simulator",{"2":{"135":1,"194":1,"195":1,"436":1,"625":2,"626":1}}],["sim",{"2":{"35":1,"256":1,"342":2}}],["sistemas",{"2":{"45":1,"107":1,"187":1,"673":1,"678":1}}],["sistema",{"0":{"248":1,"335":1},"1":{"249":1,"250":1,"251":1,"252":1,"253":1,"336":1},"2":{"31":1,"33":1,"55":1,"80":1,"139":1,"143":1,"149":1,"159":1,"165":2,"166":1,"168":1,"183":2,"184":1,"191":1,"200":2,"243":1,"248":2,"250":2,"251":1,"252":1,"256":1,"278":1,"298":1,"328":1,"381":1,"446":1,"461":1,"485":1,"533":1,"563":1,"564":2,"593":1,"634":1,"635":2,"678":1,"700":1,"711":1,"728":2,"757":1}}],["são",{"2":{"14":1,"28":1,"30":1,"37":2,"41":1,"42":1,"44":2,"45":1,"47":2,"52":1,"55":1,"56":1,"63":1,"67":1,"68":2,"69":1,"77":3,"79":1,"85":1,"86":1,"90":1,"91":1,"94":1,"95":1,"96":2,"97":1,"99":1,"100":1,"103":1,"104":1,"105":2,"106":1,"108":1,"111":1,"114":1,"120":1,"122":1,"127":1,"128":1,"129":1,"159":1,"218":2,"222":1,"223":1,"224":2,"225":4,"226":1,"229":1,"230":2,"241":1,"252":1,"265":1,"285":1,"287":1,"306":1,"313":1,"328":2,"329":2,"337":1,"348":2,"349":2,"351":1,"358":1,"375":2,"379":3,"385":2,"386":2,"402":1,"404":1,"407":1,"417":1,"420":1,"421":3,"423":1,"424":4,"427":1,"440":1,"441":5,"442":3,"445":2,"446":1,"449":2,"452":1,"462":1,"463":1,"464":1,"469":1,"470":2,"471":1,"474":2,"479":1,"486":1,"487":1,"488":2,"493":2,"499":1,"504":1,"534":3,"535":3,"540":1,"541":1,"545":2,"552":2,"553":1,"555":1,"556":1,"557":1,"561":1,"571":2,"574":1,"576":2,"577":3,"595":2,"619":1,"628":1,"629":3,"633":2,"635":2,"636":1,"654":1,"662":1,"668":1,"673":4,"675":1,"676":1,"678":1,"679":3,"680":2,"681":1,"682":2,"685":1,"691":1,"692":1,"698":1,"701":1,"708":1,"709":1,"719":1,"724":1,"725":1,"726":2,"731":1,"732":1,"735":1,"736":1}}],["saem",{"2":{"637":1}}],["sabores",{"0":{"595":1}}],["sabemos",{"2":{"427":1}}],["sabe",{"2":{"241":1,"554":1}}],["saberá",{"2":{"637":1}}],["saberia",{"2":{"444":1}}],["saber",{"0":{"533":1,"694":1},"2":{"42":1,"43":1,"47":1,"56":1,"113":1,"131":1,"155":1,"180":1,"198":1,"215":1,"273":1,"284":1,"293":1,"304":1,"326":1,"337":1,"345":1,"372":1,"382":1,"383":1,"413":1,"531":1,"596":1,"604":1,"613":1,"622":1,"647":1,"690":1,"694":1,"711":1,"745":2,"746":1}}],["satisfeito",{"2":{"576":1}}],["saturação",{"0":{"83":1}}],["sair",{"2":{"568":1,"686":1}}],["saiba",{"2":{"230":1,"442":1,"487":1,"596":1}}],["saibam",{"2":{"3":1}}],["samsung",{"2":{"554":1}}],["samples",{"2":{"531":2}}],["sample",{"2":{"531":1}}],["sampler",{"2":{"526":1}}],["sampling",{"2":{"526":2}}],["save",{"2":{"409":3,"538":1,"549":1,"567":1,"739":1}}],["savedinstancestate",{"2":{"279":2,"299":2,"404":4,"430":10}}],["safer",{"2":{"652":1}}],["safeareaview>",{"2":{"53":1,"233":1}}],["safeareaview",{"2":{"53":2,"233":2}}],["safari",{"0":{"135":1},"2":{"135":4,"389":1}}],["sandybrown",{"2":{"88":1}}],["sandbox",{"2":{"42":1,"630":1}}],["salto",{"2":{"690":2}}],["saltos",{"2":{"689":1}}],["salvo",{"2":{"526":1}}],["salvando",{"2":{"634":1}}],["salva",{"2":{"336":1,"681":1,"728":1}}],["salvar",{"2":{"69":1,"218":1,"526":1,"629":2,"652":1}}],["salve",{"2":{"130":1}}],["salmon",{"2":{"88":1}}],["saddlebrown",{"2":{"88":1}}],["saídas",{"2":{"46":1}}],["saída",{"0":{"681":1},"2":{"11":1,"34":1,"50":3,"134":1,"268":1,"288":1,"309":1,"354":1,"436":1,"576":1,"662":2,"663":2,"679":2,"680":1,"681":3,"685":1}}],["sudo",{"2":{"608":1,"651":1,"705":1,"715":2,"716":1}}],["sujeita",{"2":{"469":1}}],["sujeito",{"2":{"336":1}}],["sutis",{"2":{"413":1}}],["sufixo",{"2":{"516":1}}],["sufixos",{"2":{"328":1,"516":1}}],["suficientes",{"2":{"95":1,"104":1}}],["suficiente",{"2":{"43":1,"115":1,"118":1,"497":1,"507":1,"667":1}}],["surpresa",{"2":{"576":1}}],["surgir",{"2":{"561":1}}],["surja",{"2":{"252":1}}],["sure",{"2":{"135":1}}],["suspense",{"2":{"691":1}}],["suspenso",{"2":{"185":1,"312":1,"357":1,"547":1,"616":1}}],["sustenta",{"2":{"62":1}}],["sucedida",{"2":{"636":1}}],["sucedido",{"2":{"120":1,"121":1}}],["sucessão",{"2":{"691":1}}],["sucesscallback",{"2":{"464":1}}],["sucesso",{"2":{"153":1,"154":1,"178":1,"179":1,"196":1,"197":1,"213":1,"214":1,"456":1,"464":2,"465":1,"488":1,"686":1}}],["successcallback",{"2":{"464":1,"488":3}}],["success",{"2":{"35":3,"486":1,"521":1}}],["sugerido",{"2":{"656":1}}],["sugeridas",{"2":{"532":1}}],["sugerida",{"2":{"191":2}}],["sugerimos",{"2":{"67":1,"92":1,"101":1}}],["sugestões",{"2":{"64":1}}],["suppresswarnings",{"2":{"456":1}}],["supportedevents",{"2":{"490":1}}],["supportfragmentmanager",{"2":{"431":1}}],["support",{"2":{"279":1,"299":1,"358":1}}],["suposição",{"2":{"469":1,"491":1}}],["supor",{"2":{"444":1}}],["suportar",{"2":{"407":1,"552":1}}],["suportando",{"2":{"222":1}}],["suportam",{"2":{"94":1,"103":1,"379":1,"464":1,"488":1,"656":1}}],["suporta",{"2":{"47":1,"50":3,"82":1,"83":1,"84":1,"85":1,"86":1,"111":1,"338":1,"387":1,"417":1,"552":1,"691":1}}],["suportado",{"2":{"531":1,"605":2}}],["suportados",{"2":{"37":1,"47":1,"86":1,"329":1,"391":1,"424":1,"462":3,"486":3}}],["suportada",{"2":{"47":1,"247":1,"669":1}}],["suportadas",{"0":{"382":1},"2":{"35":1,"77":1,"313":1,"358":1,"390":1,"493":1}}],["suportes",{"2":{"441":1}}],["suporte",{"0":{"38":1,"39":1,"522":1,"691":1},"2":{"35":1,"50":1,"63":1,"71":1,"73":1,"74":1,"76":1,"77":5,"114":3,"145":1,"170":1,"189":1,"205":1,"279":1,"299":1,"329":1,"338":1,"379":1,"390":1,"407":1,"417":1,"442":1,"443":1,"461":1,"477":1,"485":1,"493":1,"500":1,"510":1,"514":1,"522":1,"534":1,"629":1,"636":3,"656":1,"668":1,"677":1,"679":1,"697":1,"732":1,"745":1,"749":1}}],["suponha",{"2":{"311":1,"356":1}}],["suprimir",{"2":{"77":1}}],["superficial",{"2":{"507":1}}],["superfície",{"2":{"245":1}}],["super",{"2":{"279":7,"299":7,"402":2,"404":2,"427":1,"429":1,"430":10,"431":2,"452":1,"467":1}}],["superar",{"2":{"45":1,"69":1}}],["superiores",{"2":{"139":1,"166":1,"200":1}}],["superior",{"2":{"38":1,"39":1,"65":1,"92":1,"101":1,"111":1,"186":1,"219":1,"224":1,"234":1,"253":1,"270":1,"278":1,"290":1,"298":1,"439":1,"516":1,"551":1,"554":1,"555":1,"663":1,"724":1}}],["subspecs",{"2":{"706":1}}],["subsystem==",{"2":{"608":1}}],["substring",{"2":{"477":1}}],["substitua",{"2":{"279":1,"299":1,"402":1,"404":1,"429":2,"430":2,"431":2,"432":1,"452":2,"456":2,"491":1,"652":1}}],["substituindo",{"2":{"427":1,"487":1,"658":1,"677":1,"678":1}}],["substituição",{"2":{"367":1,"708":1}}],["substitui",{"2":{"228":1,"677":1,"693":1}}],["substituir",{"2":{"65":1,"92":1,"256":1,"283":1,"303":1,"342":1,"399":1,"445":1,"487":1,"490":1,"608":1}}],["substituirá",{"2":{"13":1,"441":1}}],["substituída",{"2":{"708":1}}],["substituído",{"2":{"117":1,"278":1,"298":1,"487":1,"520":1}}],["substituí",{"2":{"65":1,"726":1}}],["substituto",{"2":{"51":1}}],["submit",{"2":{"549":1}}],["submenus",{"2":{"241":1}}],["subjacente",{"2":{"524":1}}],["subcomponentes",{"2":{"668":1}}],["subconjunto",{"2":{"420":1,"440":1}}],["subclassificar",{"2":{"490":1}}],["subclasses",{"2":{"108":1,"421":1,"441":2,"445":1}}],["subclasse",{"0":{"422":1,"431":1},"2":{"77":1,"421":1,"441":1,"443":2,"490":2}}],["subespecificação",{"2":{"313":3,"358":3}}],["subespecificações",{"2":{"313":3,"358":3,"706":1}}],["subpasta",{"2":{"267":1,"288":1,"308":1,"313":1,"353":1,"358":1}}],["subárvores",{"2":{"118":1,"534":1}}],["subárvore",{"2":{"112":1}}],["subvisualização",{"2":{"111":1}}],["subvisualizações",{"2":{"111":1,"445":1}}],["subvisão",{"2":{"111":1}}],["subir",{"2":{"31":1}}],["summary",{"2":{"11":1,"34":1,"67":1}}],["suaves",{"2":{"700":1}}],["suave",{"2":{"532":1,"533":1,"556":1,"691":1}}],["sua",{"0":{"64":1,"177":1,"280":1,"300":1,"322":1,"368":1,"405":1,"515":1},"1":{"65":1,"66":1,"67":1,"68":1,"69":1,"70":1,"281":1,"282":1,"301":1,"302":1,"323":1,"324":1,"325":1,"369":1,"370":1,"371":1},"2":{"3":1,"5":1,"10":1,"42":2,"43":1,"45":1,"47":2,"57":1,"67":4,"74":1,"80":1,"92":1,"110":1,"111":3,"113":2,"131":1,"137":1,"138":1,"143":1,"153":1,"164":1,"166":1,"178":1,"182":1,"196":1,"199":1,"213":1,"219":1,"221":2,"236":2,"239":1,"255":2,"256":1,"259":1,"278":1,"279":3,"282":1,"298":1,"299":3,"302":1,"313":1,"320":1,"329":1,"331":1,"333":1,"334":2,"337":1,"338":3,"349":2,"358":1,"365":1,"377":1,"378":1,"384":2,"398":1,"402":3,"403":1,"404":5,"411":1,"413":1,"426":1,"428":1,"430":1,"431":1,"441":1,"442":1,"444":1,"452":2,"459":2,"464":1,"467":2,"488":1,"490":2,"491":4,"497":2,"503":1,"504":1,"505":1,"506":2,"507":1,"508":1,"509":3,"516":2,"527":1,"531":1,"534":2,"539":1,"548":1,"555":1,"583":1,"584":1,"585":1,"599":1,"601":1,"602":1,"603":2,"608":2,"610":1,"611":1,"612":3,"616":1,"619":1,"621":2,"629":1,"634":1,"635":1,"639":2,"642":1,"644":1,"645":1,"646":3,"650":1,"658":1,"665":1,"668":1,"670":1,"671":1,"672":1,"673":1,"677":2,"678":2,"679":1,"680":1,"682":1,"683":1,"690":1,"699":1,"710":1,"722":1,"745":1,"762":1}}],["suas",{"0":{"408":1},"1":{"409":1,"410":1,"411":1,"412":1,"413":1},"2":{"0":1,"42":1,"43":1,"63":1,"67":1,"69":1,"70":1,"74":1,"111":1,"113":1,"134":2,"153":1,"166":1,"178":1,"196":1,"213":1,"236":1,"257":1,"270":1,"283":1,"290":1,"303":1,"337":1,"347":1,"390":1,"405":1,"409":1,"416":1,"441":1,"458":1,"482":1,"492":1,"505":1,"518":1,"531":1,"532":1,"549":1,"556":1,"595":1,"637":1,"652":2,"657":1,"678":1,"689":1}}],["stdout",{"2":{"745":1}}],["sticky",{"2":{"390":1}}],["str",{"2":{"390":1}}],["stretch",{"2":{"222":1,"227":5,"228":2,"229":2,"426":1}}],["stringify",{"2":{"122":2,"519":1,"576":1}}],["string>",{"2":{"92":4}}],["strings",{"2":{"50":1,"86":1,"349":1,"454":1,"479":1,"681":1}}],["string",{"2":{"3":2,"5":1,"8":1,"12":1,"21":1,"25":2,"26":1,"35":3,"76":1,"114":1,"115":1,"224":4,"225":4,"226":4,"227":4,"228":2,"229":4,"230":4,"231":4,"232":2,"234":2,"259":2,"279":4,"299":4,"320":1,"338":1,"345":3,"348":2,"349":1,"365":2,"390":4,"393":1,"404":3,"422":2,"424":5,"426":1,"427":1,"431":6,"453":2,"454":8,"456":1,"461":10,"462":3,"463":3,"464":16,"465":7,"466":4,"467":5,"478":1,"485":10,"486":2,"493":3,"520":3,"524":1,"531":12,"564":1,"625":1,"636":1,"672":1,"675":1,"680":1,"681":1,"737":1}}],["step=",{"2":{"692":1}}],["step",{"0":{"177":1}}],["steelblue",{"2":{"88":1,"224":1,"225":1,"226":1,"227":1,"228":1,"231":7,"233":1,"234":1,"261":1,"262":1,"263":1}}],["staging",{"2":{"586":1,"595":2}}],["stack",{"2":{"685":1}}],["stacktrace",{"2":{"660":3,"685":2}}],["stackframedata",{"2":{"531":1}}],["stackframes",{"2":{"531":6}}],["stackoverflow",{"2":{"259":2}}],["star",{"2":{"520":1}}],["starttransition",{"0":{"692":1},"1":{"693":1,"694":1},"2":{"692":4}}],["startobserving",{"2":{"490":2}}],["startdate",{"2":{"462":2}}],["startswith",{"2":{"393":1}}],["startservice",{"2":{"256":2,"259":2}}],["startreactapplication",{"2":{"279":1,"299":1}}],["startactivityforresult",{"0":{"467":1},"2":{"278":2,"298":2,"467":3}}],["start",{"2":{"46":2,"47":1,"48":2,"49":1,"51":2,"54":1,"56":1,"151":2,"157":2,"176":2,"193":2,"211":2,"222":1,"224":1,"225":1,"226":4,"227":3,"228":2,"229":4,"232":1,"233":2,"234":1,"268":2,"281":2,"288":2,"301":2,"309":2,"324":2,"354":2,"370":2,"605":1,"704":2,"745":1}}],["static",{"2":{"259":1,"390":2,"422":1,"431":1,"467":5}}],["stat",{"2":{"68":1}}],["stats",{"2":{"67":1,"313":1,"358":1}}],["status",{"2":{"67":1,"77":1,"521":1}}],["statetsx",{"2":{"349":1}}],["state",{"2":{"47":1,"50":2,"56":2,"58":2,"60":5,"74":4,"77":4,"112":1,"349":2,"417":1,"569":1,"573":2,"737":2}}],["storyboardwithname",{"2":{"548":1}}],["storyboard",{"2":{"321":2,"366":2}}],["storage",{"2":{"67":1,"630":2,"634":2}}],["storepassword",{"2":{"653":1}}],["storefile",{"2":{"653":1}}],["storetype",{"2":{"650":1}}],["stores",{"2":{"546":1,"648":1}}],["store",{"0":{"546":1,"648":1},"1":{"547":1,"548":1,"549":1,"550":1,"649":1,"650":1,"651":1,"652":1,"653":1,"654":1,"655":1,"656":1,"657":1,"658":1,"659":1},"2":{"38":2,"68":1,"184":1,"520":1,"546":1,"547":1,"549":5,"550":1,"604":1,"613":1,"622":2,"634":1,"647":1,"648":2,"652":2,"653":3,"655":1,"767":1,"768":1}}],["stopobserving",{"2":{"490":2}}],["stopanimation",{"2":{"55":1}}],["stoptogether",{"2":{"48":1}}],["stop",{"2":{"46":1,"48":1,"490":1}}],["studio",{"0":{"141":1,"167":1,"202":1,"283":1,"303":1,"438":1},"2":{"38":1,"137":2,"141":2,"142":5,"149":3,"152":1,"156":1,"164":2,"167":2,"168":4,"174":3,"177":1,"199":2,"202":2,"203":5,"209":3,"212":1,"241":1,"279":2,"283":3,"299":2,"303":3,"402":2,"405":1,"417":1,"437":2,"438":1,"451":3,"459":1}}],["style",{"2":{"46":2,"50":1,"218":1,"279":1,"299":1,"348":2,"390":1,"431":2,"445":1,"668":2}}],["stylesheet",{"2":{"53":2,"54":2,"60":2,"116":4,"122":4,"218":1,"223":2,"224":2,"225":2,"226":2,"227":2,"228":2,"229":2,"230":2,"231":2,"232":2,"233":2,"234":2,"244":2,"245":2,"277":2,"297":2,"313":1,"317":2,"358":1,"362":2,"445":1,"562":4,"668":3,"730":4,"737":2}}],["styles",{"2":{"3":2,"5":2,"10":1,"30":3,"53":8,"54":4,"60":5,"116":6,"122":8,"223":2,"224":11,"225":11,"226":11,"227":11,"228":11,"229":15,"230":15,"231":15,"232":18,"233":16,"234":11,"244":5,"245":12,"277":3,"297":3,"317":4,"362":4,"445":2,"562":2,"668":8,"730":7,"737":3}}],["style=",{"2":{"3":2,"5":2,"10":1,"30":3,"46":4,"50":1,"53":8,"54":4,"58":1,"60":4,"113":1,"114":2,"115":2,"116":4,"122":6,"223":4,"224":9,"225":9,"226":9,"227":9,"228":9,"229":13,"230":13,"231":15,"232":12,"233":13,"234":9,"239":1,"242":3,"244":4,"245":11,"261":3,"262":4,"263":4,"277":2,"297":2,"317":3,"330":2,"331":1,"332":1,"333":1,"334":1,"339":1,"346":1,"348":1,"362":3,"387":2,"390":1,"434":1,"441":2,"442":2,"445":2,"520":1,"573":1,"668":5,"681":1,"730":5,"731":6,"737":2}}],["separando",{"2":{"673":1}}],["separadamente",{"2":{"679":1}}],["separada",{"2":{"491":2}}],["separadas",{"2":{"134":1}}],["separado",{"2":{"96":1,"105":1,"111":1,"217":1,"464":1,"488":1,"580":1}}],["separados",{"2":{"3":1,"488":1,"561":1,"565":1}}],["separá",{"2":{"561":1}}],["sessões",{"2":{"571":1,"629":1}}],["session",{"2":{"524":1}}],["sessão",{"2":{"218":3,"523":1}}],["seções",{"2":{"237":1,"448":2,"572":1,"685":1,"730":1}}],["seção",{"2":{"11":1,"34":1,"47":1,"48":1,"63":1,"67":1,"68":1,"107":1,"131":1,"159":1,"236":1,"237":1,"343":1,"384":1,"387":3,"399":1,"401":2,"435":1,"525":1,"532":1,"549":1,"567":1,"586":1,"654":1,"658":1,"706":1,"721":1,"724":1,"730":1,"745":1,"746":1}}],["self",{"2":{"110":2,"111":2,"320":1,"365":1,"442":5,"443":1,"444":1,"490":1,"524":1,"548":1}}],["seletor",{"2":{"467":3}}],["selectablebackground",{"2":{"245":1}}],["select",{"2":{"135":1,"381":1,"562":4}}],["selectedlabel",{"2":{"224":2,"225":2,"226":2,"227":2,"228":2,"229":2,"230":2,"233":3,"234":2}}],["selectedvalue",{"2":{"224":5,"225":5,"226":5,"227":5,"228":4,"229":5,"230":5,"234":4}}],["selectedvalue=",{"2":{"224":1,"225":1,"226":1,"227":1,"228":1,"229":1,"230":1,"234":1}}],["selected",{"0":{"29":1},"2":{"12":1,"224":2,"225":2,"226":2,"227":2,"228":2,"229":2,"230":2,"233":3,"234":2}}],["selecione",{"0":{"724":1},"2":{"131":2,"133":1,"134":1,"135":1,"142":3,"149":2,"153":1,"168":3,"174":2,"178":1,"186":3,"200":1,"203":4,"209":2,"213":1,"321":2,"366":2,"412":1,"439":2,"526":2,"530":1,"547":1,"549":1,"551":1,"603":1,"612":1,"615":1,"616":2,"621":1,"646":1,"708":1}}],["selecionando",{"0":{"375":1},"2":{"136":1,"185":1,"312":1,"357":1,"438":1,"549":1,"551":1,"554":2}}],["selecionadas",{"2":{"724":1}}],["selecionada",{"2":{"74":2,"77":2,"616":1}}],["selecionado",{"2":{"3":1,"12":1,"29":1,"31":1,"32":1,"33":1,"77":1,"142":1,"168":1,"203":1,"328":1}}],["selecionará",{"2":{"565":1}}],["selecionar",{"2":{"11":1,"34":1,"74":1,"77":1,"134":1,"135":1,"244":1,"413":1,"617":1,"724":2}}],["selecionaram",{"2":{"3":1}}],["selecionável",{"2":{"2":1,"12":1,"29":1}}],["seleção",{"2":{"11":1,"12":1,"21":1,"34":1,"141":1,"167":1,"202":1,"549":1,"554":1}}],["seashell",{"2":{"88":1}}],["seagreen",{"2":{"88":1}}],["searchbox",{"2":{"34":1}}],["search",{"2":{"11":1,"358":1,"413":1,"708":4,"722":2}}],["senha",{"2":{"652":2}}],["senhas",{"2":{"632":1,"650":1,"652":1}}],["sentry",{"2":{"634":1}}],["sentirá",{"2":{"534":1}}],["sentinela",{"2":{"442":1}}],["sentido",{"2":{"218":1,"561":1,"576":1,"683":1}}],["sensitive",{"2":{"634":3}}],["sensibilidade",{"2":{"629":1,"639":1}}],["sensíveis",{"2":{"55":1}}],["send",{"2":{"521":1,"522":1}}],["sendeventwithname",{"2":{"490":2}}],["sendevent",{"2":{"466":4}}],["sender",{"2":{"320":1,"365":1}}],["sending",{"2":{"313":1,"358":1}}],["sendaccessibilityevent",{"2":{"37":2}}],["sendo",{"2":{"20":1,"47":1,"73":1,"76":1,"219":1,"231":2,"436":1,"469":1,"483":1,"491":1,"539":1,"551":1,"552":1,"553":1,"555":1,"557":2,"559":1,"562":1,"563":1,"675":1,"676":2,"711":1,"730":1,"736":1}}],["segmentação",{"2":{"656":1}}],["segmentos",{"2":{"50":1}}],["segredo",{"2":{"629":2}}],["segredos",{"2":{"265":1,"287":1,"306":1,"351":1,"629":3,"630":1}}],["seguras",{"0":{"633":1},"2":{"673":1}}],["segura",{"2":{"629":1,"636":2}}],["segurança",{"0":{"323":1,"369":1,"628":1,"637":1},"1":{"629":1,"630":1,"631":1,"632":1,"633":1,"634":1,"635":1,"636":1,"637":1,"638":2,"639":1},"2":{"273":1,"293":1,"330":1,"331":1,"414":1,"442":1,"452":1,"461":3,"485":3,"521":1,"628":4,"632":1,"635":2,"636":2,"639":3,"652":1,"758":1}}],["seguros",{"2":{"635":2}}],["seguro",{"0":{"631":1},"1":{"632":1,"633":1,"634":1},"2":{"219":1,"452":1,"461":1,"485":1,"520":1,"634":2,"636":1,"637":1}}],["segue",{"2":{"88":1,"587":1,"588":1}}],["seguem",{"2":{"56":1,"377":1}}],["segunda",{"2":{"67":1,"534":1}}],["segundo",{"2":{"53":1,"63":1,"254":1,"424":1,"466":4,"487":1,"490":2,"519":1,"532":1,"533":2,"560":1,"675":1,"693":1,"699":1}}],["segundos",{"2":{"38":1,"47":1,"67":1,"216":1,"553":1,"567":1}}],["seguindo",{"2":{"148":1,"173":1,"208":1,"401":1,"603":1,"612":1,"646":1,"745":1}}],["seguinte",{"2":{"52":1,"65":1,"67":1,"151":1,"152":1,"157":1,"176":1,"193":1,"194":1,"200":1,"203":1,"211":1,"212":1,"251":1,"268":2,"271":2,"278":1,"281":1,"283":1,"288":2,"291":2,"298":1,"301":1,"303":1,"309":2,"323":1,"324":1,"328":1,"344":1,"354":2,"369":1,"370":1,"371":1,"404":1,"445":1,"452":1,"456":2,"457":1,"461":1,"462":1,"465":1,"467":1,"477":2,"481":1,"485":1,"487":2,"488":1,"524":1,"548":2,"553":1,"554":1,"565":1,"566":1,"576":1,"582":1,"583":1,"584":1,"585":1,"586":1,"589":1,"590":1,"591":1,"592":1,"594":1,"595":1,"600":1,"602":2,"609":1,"611":2,"624":1,"625":1,"626":1,"627":1,"643":1,"645":2,"651":1,"652":1,"654":1,"655":1,"656":1,"662":1,"675":1,"680":1,"696":1,"700":1,"703":2,"705":1,"711":1,"721":1,"726":1}}],["seguintes",{"2":{"11":1,"12":1,"13":1,"34":1,"35":2,"60":1,"68":1,"73":1,"120":1,"121":1,"142":2,"165":1,"166":1,"168":2,"183":1,"203":1,"233":1,"249":1,"251":2,"340":1,"387":1,"424":2,"436":1,"461":2,"462":1,"465":1,"468":1,"470":1,"485":2,"486":1,"565":1,"566":1,"574":1,"619":1,"745":1}}],["seguimos",{"2":{"70":1}}],["seguido",{"2":{"50":1,"560":1,"621":1,"625":1}}],["seguida",{"2":{"38":1,"46":1,"93":1,"102":1,"111":2,"113":1,"141":1,"142":1,"149":1,"167":1,"168":1,"174":1,"202":1,"203":1,"209":1,"234":1,"256":2,"268":1,"271":1,"272":1,"279":1,"288":1,"291":1,"292":1,"299":1,"309":1,"318":1,"320":2,"337":1,"349":1,"354":1,"363":1,"365":2,"434":1,"443":1,"452":1,"454":1,"456":2,"464":1,"493":1,"527":1,"538":1,"567":1,"608":1,"616":1,"650":1,"658":1,"681":1,"703":1,"706":2}}],["seguir",{"2":{"8":1,"48":1,"52":1,"53":1,"67":2,"68":1,"69":1,"74":1,"77":1,"113":1,"116":1,"135":1,"140":1,"141":1,"149":1,"167":1,"201":1,"202":1,"223":1,"227":1,"239":1,"242":1,"259":1,"349":1,"377":1,"428":1,"435":1,"442":1,"447":1,"448":3,"450":1,"454":1,"459":1,"464":1,"471":1,"475":1,"477":1,"478":1,"488":1,"523":1,"603":1,"612":1,"646":1,"680":1,"731":1,"746":1,"747":1}}],["sequer",{"2":{"682":1}}],["sequestrar",{"2":{"635":1}}],["sequence",{"2":{"48":2}}],["sequenciais",{"2":{"48":1}}],["sequências",{"2":{"387":1}}],["sequência",{"2":{"48":2}}],["setvalue",{"2":{"692":2}}],["setgroceryitem",{"2":{"680":3}}],["setenthusiasmlevel",{"2":{"737":3}}],["sete",{"2":{"598":1,"607":1,"641":1}}],["setdata",{"2":{"520":2}}],["setdirection",{"2":{"225":2}}],["setloading",{"2":{"520":2}}],["setlaunchoptions",{"2":{"404":3}}],["setlayoutanimationenabledexperimental",{"2":{"60":3}}],["setuplayout",{"2":{"431":4}}],["setusedevelopersupport",{"2":{"279":1,"299":1}}],["setpadding",{"2":{"429":2}}],["setposition",{"2":{"234":2}}],["setpowderblue",{"2":{"231":2}}],["setregion",{"2":{"442":1,"443":1}}],["setresizemode",{"2":{"424":2}}],["setrowgap",{"2":{"232":2}}],["setbackgroundcolor",{"2":{"429":2}}],["setborderradius",{"2":{"424":4}}],["setbundleassetname",{"2":{"279":1,"299":1}}],["setbuttonopacity",{"2":{"113":3}}],["setonclicklistener",{"2":{"404":2}}],["setopacityto",{"2":{"113":1}}],["set",{"2":{"392":1,"523":1,"524":2}}],["setimmediate",{"2":{"699":5,"700":1}}],["setinterval",{"2":{"699":1,"700":1}}],["setinitiallifecyclestate",{"2":{"279":1,"299":1}}],["setitems",{"2":{"680":2}}],["setishungry",{"2":{"349":9}}],["setjsmainmodulepath",{"2":{"279":1,"299":1}}],["setjustifycontent",{"2":{"226":2}}],["setcomponentname",{"2":{"404":2}}],["setcontentview",{"2":{"279":1,"299":1,"404":2}}],["setcolumngap",{"2":{"232":2}}],["setcurrentactivity",{"2":{"279":1,"299":1}}],["setheighttype=",{"2":{"233":1}}],["setheighttype",{"2":{"233":5}}],["setwidthtype=",{"2":{"233":1}}],["setwidthtype",{"2":{"233":5}}],["setscaletype",{"2":{"424":2}}],["setsource",{"2":{"424":2}}],["setsrc",{"2":{"424":2}}],["setstyle",{"2":{"231":5,"431":2}}],["setstyle=",{"2":{"231":3}}],["setsteelblue",{"2":{"231":2}}],["setstateaction",{"2":{"231":1}}],["setstate",{"2":{"46":1,"60":1,"63":1,"74":4,"77":4,"112":1,"118":1,"390":1,"534":1,"544":1,"573":1}}],["setskyblue",{"2":{"231":2}}],["setselectedvalue",{"2":{"224":3,"225":3,"226":3,"227":3,"228":3,"229":3,"230":3,"234":3}}],["setselectedvalue=",{"2":{"224":1,"225":1,"226":1,"227":1,"228":1,"229":1,"230":1,"234":1}}],["setflexwrap",{"2":{"230":2}}],["setflexdirection",{"2":{"224":2}}],["setframe",{"2":{"111":1}}],["setmeasure",{"2":{"122":4}}],["settargetrect",{"2":{"690":3}}],["settype",{"2":{"467":1}}],["settimeout",{"2":{"699":2,"700":1}}],["settime",{"2":{"462":1}}],["settimespetted",{"2":{"349":1}}],["setting",{"2":{"358":1}}],["settings",{"2":{"38":2,"68":4,"135":2,"142":2,"168":2,"185":1,"186":2,"203":2,"270":1,"271":2,"278":4,"290":1,"291":2,"298":4,"312":1,"313":2,"357":1,"358":1,"413":1,"598":2,"603":2,"607":2,"612":1,"641":2,"646":1,"708":1}}],["settext",{"2":{"242":2,"429":1}}],["setter",{"2":{"93":1,"349":1,"424":12}}],["setnativeprops",{"0":{"63":1,"113":1,"114":1,"115":1,"116":1,"118":1},"1":{"115":1},"2":{"63":2,"112":3,"113":4,"114":4,"115":5,"116":4,"117":1,"118":1}}],["setapplication",{"2":{"279":1,"299":1}}],["setappproperties",{"2":{"92":1}}],["setaligncontent",{"2":{"229":2}}],["setalignself",{"2":{"228":2}}],["setalignitems",{"2":{"227":2}}],["seta",{"2":{"56":2,"74":1}}],["seis",{"2":{"46":1}}],["section",{"2":{"730":2}}],["sections=",{"2":{"730":1}}],["sectionheader",{"2":{"730":2}}],["sectionlistbasics",{"2":{"730":2}}],["sectionlist",{"2":{"11":1,"34":1,"46":1,"539":1,"730":4}}],["secruity",{"2":{"520":1}}],["secondparam",{"2":{"519":1}}],["secondname",{"2":{"345":4}}],["secundária",{"2":{"461":1,"485":1}}],["secundário",{"2":{"227":1}}],["security",{"2":{"323":1,"369":1}}],["secure",{"2":{"38":2,"634":2}}],["seja",{"0":{"566":1},"2":{"37":1,"56":1,"60":2,"65":1,"74":1,"106":1,"120":1,"140":1,"165":1,"183":1,"184":1,"200":1,"201":1,"203":1,"218":1,"219":1,"227":1,"233":1,"245":2,"249":1,"251":1,"255":1,"311":1,"328":3,"334":1,"336":1,"349":1,"356":1,"424":3,"441":1,"442":1,"479":1,"491":1,"493":1,"495":1,"511":1,"538":1,"540":1,"542":1,"549":1,"561":1,"562":1,"573":1,"574":1,"576":1,"582":1,"615":1,"628":1,"629":1,"636":1,"652":1,"673":1,"681":1,"690":1,"700":1,"739":1,"747":1}}],["sejam",{"2":{"20":1,"39":1,"42":1,"57":1,"63":1,"111":1,"119":1,"128":1,"166":1,"217":1,"329":1,"389":1,"493":1,"545":1,"560":1,"571":1,"576":1,"629":1,"648":1,"652":1,"675":1,"700":1,"731":1}}],["sempre",{"2":{"39":1,"42":1,"43":1,"56":1,"94":1,"103":1,"111":1,"113":1,"117":1,"129":1,"135":1,"218":2,"221":1,"256":1,"259":2,"261":1,"276":1,"296":1,"313":1,"316":1,"358":1,"361":1,"379":1,"407":1,"414":1,"459":1,"461":1,"479":1,"485":1,"493":1,"532":1,"537":1,"548":1,"602":1,"603":1,"605":1,"611":1,"612":1,"618":1,"636":2,"637":1,"645":1,"646":1,"678":2,"741":1,"746":1}}],["sem",{"0":{"329":1,"710":1},"2":{"30":1,"35":2,"56":4,"58":2,"60":1,"63":1,"65":1,"76":1,"96":1,"105":1,"112":1,"113":1,"135":1,"143":1,"145":1,"158":1,"170":1,"205":1,"221":1,"248":1,"249":1,"251":1,"259":1,"311":1,"330":1,"347":1,"349":1,"356":1,"377":1,"387":1,"390":1,"417":1,"446":1,"466":1,"478":2,"490":1,"491":1,"533":1,"560":1,"566":1,"573":1,"595":1,"603":1,"612":1,"619":1,"629":2,"646":1,"660":1,"672":1,"673":1,"674":1,"675":1,"679":2,"681":1,"682":1,"690":1,"692":2,"693":1,"700":1,"739":1}}],["semelhantes",{"2":{"78":1,"389":1,"420":1,"440":1,"441":1,"446":1,"449":1,"470":1,"474":1,"488":1}}],["semelhante",{"2":{"15":1,"70":1,"74":1,"77":1,"85":1,"90":1,"99":1,"151":1,"176":1,"193":1,"211":1,"217":1,"227":1,"231":2,"255":1,"263":1,"268":1,"288":1,"309":1,"313":1,"354":1,"358":1,"367":1,"425":1,"465":1,"468":1,"532":1,"556":1,"673":1,"681":1,"730":2}}],["se",{"0":{"36":1,"228":1,"601":1,"610":1,"618":1,"644":1},"1":{"602":1,"603":1,"604":1,"611":1,"612":1,"645":1,"646":1,"647":1},"2":{"6":1,"9":1,"11":1,"12":4,"13":3,"14":2,"15":1,"23":1,"24":1,"28":1,"29":1,"30":2,"31":1,"33":1,"36":1,"38":2,"43":2,"45":1,"46":1,"47":2,"48":1,"50":1,"55":1,"56":2,"57":1,"58":1,"60":2,"63":2,"64":1,"65":7,"66":2,"67":9,"68":2,"69":1,"73":2,"76":2,"77":1,"90":3,"93":1,"96":1,"99":3,"102":1,"105":1,"110":4,"111":4,"112":1,"113":1,"114":2,"115":1,"117":1,"120":3,"121":2,"131":3,"132":1,"134":2,"139":1,"140":3,"141":2,"142":6,"145":4,"146":1,"148":1,"149":2,"151":1,"152":2,"155":2,"156":5,"158":1,"159":5,"165":2,"166":2,"167":2,"168":5,"170":4,"171":1,"173":1,"174":2,"176":1,"177":2,"180":2,"183":2,"184":2,"186":1,"189":5,"190":2,"191":2,"193":1,"194":1,"195":1,"198":2,"200":7,"201":3,"202":3,"203":3,"205":4,"206":1,"208":1,"209":3,"211":1,"212":2,"215":2,"217":4,"218":5,"219":3,"220":1,"221":1,"224":4,"225":3,"227":1,"230":2,"231":3,"236":1,"238":2,"239":2,"244":1,"245":2,"248":1,"251":8,"252":3,"257":2,"258":3,"259":5,"262":5,"263":1,"265":1,"270":2,"272":3,"273":1,"278":2,"279":5,"283":3,"287":1,"290":2,"292":3,"293":1,"298":2,"299":5,"303":3,"306":1,"309":1,"313":4,"323":1,"325":2,"328":5,"330":1,"332":1,"334":5,"336":2,"337":1,"338":2,"343":2,"345":1,"347":1,"348":1,"349":1,"351":1,"358":6,"369":1,"371":2,"374":1,"375":1,"377":1,"379":1,"381":1,"382":1,"383":1,"387":2,"389":2,"402":4,"404":2,"405":1,"411":1,"413":2,"414":1,"417":3,"426":1,"428":1,"434":1,"435":2,"436":1,"441":3,"442":4,"445":2,"446":1,"447":1,"448":3,"452":1,"455":2,"456":3,"458":1,"461":2,"462":1,"463":2,"464":5,"465":1,"466":1,"467":1,"469":1,"470":1,"471":2,"477":1,"478":1,"479":1,"480":2,"482":1,"483":1,"485":2,"486":1,"487":4,"488":4,"490":2,"491":7,"493":3,"499":2,"502":1,"505":1,"507":2,"509":3,"511":2,"518":1,"520":4,"521":1,"523":2,"524":1,"525":1,"529":2,"531":2,"532":1,"533":1,"534":5,"537":1,"538":1,"539":2,"540":5,"541":2,"542":1,"544":2,"545":4,"546":1,"548":2,"549":4,"550":1,"551":1,"553":1,"554":2,"555":2,"556":2,"557":1,"558":1,"559":1,"562":2,"567":2,"569":1,"570":2,"571":1,"572":1,"574":2,"576":2,"578":1,"580":2,"581":1,"583":1,"584":1,"585":1,"586":1,"588":1,"589":1,"595":2,"596":3,"599":2,"601":2,"602":1,"603":2,"605":1,"608":2,"610":2,"611":1,"612":2,"615":2,"616":2,"617":2,"619":7,"620":1,"621":1,"624":1,"625":4,"626":1,"629":1,"635":3,"636":6,"638":1,"639":1,"642":1,"644":2,"645":1,"646":2,"648":1,"650":1,"651":2,"652":1,"654":4,"655":1,"656":1,"657":2,"658":1,"662":3,"663":1,"667":3,"668":1,"670":2,"671":2,"672":1,"673":1,"674":1,"675":4,"676":1,"677":1,"678":3,"679":7,"681":7,"682":3,"685":1,"686":4,"687":2,"690":3,"692":1,"696":2,"697":1,"699":2,"700":1,"701":1,"702":1,"704":1,"705":1,"706":6,"708":3,"709":2,"710":1,"711":1,"716":1,"721":1,"725":1,"726":5,"728":1,"730":1,"731":1,"736":1,"742":5,"745":4,"746":3,"747":5,"748":1,"750":1}}],["serem",{"2":{"106":1,"218":1,"349":1,"420":1,"440":1,"442":1,"452":1,"454":1,"466":1,"488":1,"490":1,"502":1,"546":1,"575":1,"594":1,"604":1,"613":1,"622":1,"634":1,"647":1,"648":1,"653":1,"665":1}}],["server",{"2":{"65":1,"603":1,"612":1,"646":1}}],["servir",{"2":{"343":1,"671":1}}],["servirá",{"2":{"265":1,"287":1,"306":1,"351":1}}],["servido",{"2":{"320":1,"365":1}}],["servidor",{"0":{"601":1,"610":1,"618":1,"644":1},"1":{"602":1,"603":1,"604":1,"611":1,"612":1,"645":1,"646":1,"647":1},"2":{"133":1,"151":1,"157":1,"176":1,"193":1,"211":1,"265":1,"272":1,"280":1,"281":1,"282":1,"287":1,"292":1,"300":1,"301":1,"302":1,"306":1,"320":1,"322":1,"324":1,"351":1,"365":1,"368":1,"370":1,"405":1,"517":1,"526":1,"601":1,"603":2,"610":1,"612":2,"618":1,"619":1,"629":3,"637":1,"638":3,"644":1,"646":2,"730":1,"745":3}}],["servi",{"2":{"280":1,"300":1,"322":1,"368":1}}],["serviceintent",{"2":{"259":6}}],["service",{"2":{"256":7,"259":4}}],["services",{"2":{"38":2,"632":1}}],["serviço",{"2":{"38":1,"256":2,"258":1,"259":5,"634":1,"665":1,"677":5,"678":2}}],["serviços",{"0":{"632":1},"2":{"10":3,"27":3,"30":3,"156":1,"417":1,"634":1,"677":1}}],["serão",{"2":{"48":1,"56":1,"60":1,"68":1,"96":1,"105":1,"221":1,"230":1,"262":1,"328":1,"334":4,"347":1,"377":1,"420":1,"423":1,"440":1,"444":1,"446":1,"449":1,"454":1,"462":1,"464":1,"470":1,"474":1,"479":1,"486":1,"499":1,"505":1,"506":1,"516":2,"520":1,"550":1,"592":1,"638":2,"652":1,"691":1,"700":1,"726":1,"735":1}}],["ser",{"0":{"707":1},"2":{"5":1,"7":1,"10":1,"11":15,"13":1,"30":1,"32":1,"34":11,"35":3,"43":2,"47":1,"48":4,"50":2,"51":2,"52":2,"55":4,"56":3,"58":1,"60":1,"63":1,"64":2,"65":1,"67":1,"68":2,"70":1,"76":1,"77":2,"78":1,"79":1,"80":1,"90":1,"92":1,"93":2,"94":1,"95":1,"96":1,"99":1,"101":3,"103":1,"104":1,"105":1,"106":2,"111":2,"114":3,"122":1,"128":3,"129":1,"130":2,"131":1,"134":2,"140":1,"142":2,"147":1,"168":2,"172":1,"200":1,"201":1,"203":2,"207":1,"217":1,"218":2,"220":1,"225":1,"227":1,"230":1,"231":3,"233":1,"242":2,"245":2,"249":1,"250":2,"251":3,"252":2,"254":1,"257":1,"259":3,"261":1,"276":1,"278":3,"279":3,"296":1,"298":3,"299":3,"313":1,"316":1,"325":1,"328":4,"329":1,"334":1,"337":2,"340":1,"342":1,"344":1,"348":1,"349":2,"358":1,"361":1,"367":1,"371":1,"379":1,"385":1,"390":1,"398":2,"399":1,"402":7,"403":2,"406":1,"417":1,"423":1,"424":6,"428":1,"429":1,"430":1,"442":2,"443":1,"444":2,"447":2,"453":2,"454":3,"456":4,"459":2,"463":1,"464":4,"465":1,"466":1,"469":1,"470":1,"477":1,"478":2,"479":1,"480":2,"487":3,"488":2,"491":2,"493":1,"495":1,"497":1,"500":1,"502":1,"504":1,"519":1,"520":2,"523":2,"524":3,"529":1,"531":7,"537":1,"540":3,"541":1,"543":1,"547":1,"550":1,"553":2,"554":1,"555":1,"556":2,"562":1,"563":1,"566":1,"570":1,"572":3,"577":3,"586":1,"587":2,"588":2,"589":2,"590":2,"591":1,"592":1,"628":3,"629":4,"635":2,"636":3,"638":2,"648":4,"650":1,"653":1,"654":3,"662":1,"666":1,"667":1,"668":1,"673":1,"674":1,"675":3,"678":1,"679":1,"681":3,"683":1,"686":1,"689":1,"690":1,"692":1,"699":1,"706":1,"719":1,"720":1,"728":1,"731":4,"733":1,"734":1,"735":2,"742":1,"745":2}}],["serial",{"2":{"491":1}}],["serialização",{"2":{"693":3,"695":1}}],["serializador",{"2":{"681":2}}],["serializam",{"2":{"46":1}}],["serializáveis",{"2":{"464":1}}],["serializável",{"2":{"55":1,"56":1,"480":1}}],["seriam",{"2":{"51":1,"673":1}}],["seria",{"2":{"3":1,"42":1,"50":2,"106":1,"221":2,"242":1,"399":1,"573":1,"629":1,"673":1}}],["será",{"2":{"2":1,"27":1,"31":1,"33":1,"58":1,"74":4,"77":4,"92":2,"101":1,"111":3,"112":1,"117":1,"120":1,"121":1,"130":1,"134":1,"144":1,"169":1,"188":1,"204":1,"218":1,"219":1,"221":2,"223":1,"244":1,"257":1,"259":2,"262":1,"275":1,"279":1,"283":1,"295":1,"299":1,"303":1,"315":1,"317":1,"320":2,"328":3,"334":2,"338":1,"349":3,"360":1,"362":1,"365":2,"398":2,"403":1,"404":1,"407":2,"409":1,"422":1,"424":5,"452":1,"461":1,"463":1,"478":1,"479":1,"485":1,"487":1,"488":2,"490":2,"491":2,"520":1,"523":1,"524":1,"532":1,"534":2,"545":1,"553":1,"555":4,"562":2,"573":1,"574":1,"589":2,"595":1,"602":1,"603":1,"611":1,"612":1,"617":2,"618":1,"636":1,"645":1,"646":1,"651":1,"659":1,"665":1,"666":1,"682":1,"695":1,"699":3,"726":3}}],["seus",{"0":{"419":1,"726":1},"2":{"2":1,"30":2,"39":1,"46":2,"76":1,"90":1,"99":1,"110":2,"113":2,"216":1,"221":2,"222":1,"223":1,"227":1,"231":5,"234":1,"248":1,"262":1,"265":1,"287":1,"306":1,"323":1,"328":1,"344":1,"347":1,"349":4,"351":1,"369":1,"386":1,"417":1,"419":1,"447":1,"455":1,"461":1,"462":1,"480":1,"485":1,"486":1,"491":2,"493":1,"497":1,"505":1,"506":1,"507":2,"509":1,"531":1,"532":1,"533":1,"547":1,"605":1,"625":1,"628":1,"638":1,"648":1,"666":3,"673":7,"675":4,"676":1,"677":3,"679":1,"680":1,"683":1,"696":1,"704":1,"708":1,"723":1,"726":1,"734":1,"739":1,"746":1}}],["seu",{"0":{"150":1,"152":1,"153":1,"158":1,"175":1,"178":1,"191":1,"192":1,"194":1,"196":1,"210":1,"212":1,"213":1,"269":1,"277":1,"289":1,"297":1,"311":1,"317":1,"344":1,"356":1,"362":1,"401":1,"402":1,"555":1,"599":1,"600":1,"604":1,"608":1,"609":1,"613":1,"615":1,"617":1,"622":1,"642":1,"643":1,"647":1,"653":1,"655":1},"1":{"151":1,"152":1,"176":1,"177":1,"178":1,"180":1,"193":1,"194":1,"211":1,"212":1,"270":1,"290":1},"2":{"0":1,"38":2,"39":1,"42":1,"43":1,"46":2,"50":1,"62":1,"64":2,"65":6,"67":1,"68":2,"74":1,"90":3,"92":1,"95":1,"96":2,"99":3,"101":1,"102":1,"104":1,"105":2,"111":1,"112":2,"113":1,"115":2,"119":1,"126":2,"127":1,"129":1,"130":1,"133":2,"134":3,"135":3,"137":2,"139":1,"140":1,"142":3,"145":1,"147":2,"149":3,"152":3,"154":1,"156":2,"158":4,"159":3,"164":2,"165":1,"166":1,"168":3,"170":1,"172":2,"174":2,"177":2,"179":1,"182":2,"183":1,"184":2,"189":1,"190":1,"191":6,"194":3,"195":1,"196":1,"197":1,"199":2,"200":3,"201":1,"203":1,"205":1,"207":2,"209":2,"212":3,"214":1,"217":2,"218":3,"221":1,"223":1,"226":1,"227":1,"228":2,"231":2,"233":1,"234":1,"239":3,"244":2,"245":3,"248":1,"249":2,"254":1,"256":2,"257":1,"258":2,"259":1,"260":1,"262":1,"265":5,"266":1,"267":2,"268":4,"270":5,"272":2,"273":2,"276":2,"277":2,"278":1,"279":4,"280":1,"281":2,"282":1,"283":3,"284":1,"287":5,"288":7,"290":5,"292":2,"293":2,"296":2,"297":2,"298":1,"299":4,"300":1,"301":2,"302":1,"303":3,"304":1,"306":6,"307":1,"308":2,"309":4,"310":1,"313":6,"316":2,"317":4,"318":2,"320":2,"322":1,"323":1,"324":2,"325":4,"326":1,"328":4,"329":1,"331":1,"339":1,"342":1,"344":8,"345":3,"347":2,"349":4,"351":6,"352":1,"353":2,"354":4,"355":1,"358":6,"361":2,"362":4,"363":2,"365":2,"367":2,"368":1,"369":1,"370":2,"371":5,"372":1,"374":2,"375":1,"376":2,"379":1,"381":1,"386":2,"389":1,"397":1,"398":1,"399":1,"401":1,"402":2,"403":3,"404":7,"405":2,"406":2,"407":1,"409":2,"411":1,"412":1,"413":1,"414":5,"417":1,"419":2,"420":2,"423":1,"426":1,"427":1,"428":3,"429":2,"430":1,"431":1,"432":1,"437":1,"440":2,"441":2,"446":1,"447":2,"448":1,"451":4,"452":3,"453":1,"454":3,"455":1,"456":8,"457":7,"458":3,"459":6,"461":6,"462":1,"464":1,"465":3,"476":4,"477":2,"478":2,"479":3,"480":1,"481":7,"482":3,"483":8,"485":6,"486":1,"487":3,"488":1,"489":3,"490":2,"491":4,"493":4,"495":1,"501":1,"505":1,"506":1,"508":1,"510":2,"516":2,"525":2,"526":2,"529":3,"531":1,"532":1,"533":1,"534":1,"535":1,"538":2,"540":1,"542":1,"544":1,"546":1,"547":1,"548":2,"549":5,"551":1,"552":1,"553":5,"554":1,"555":5,"557":1,"559":1,"561":1,"565":1,"566":3,"567":4,"570":1,"574":1,"576":2,"578":1,"579":1,"580":1,"581":2,"582":1,"585":1,"588":1,"593":1,"595":1,"596":1,"598":3,"599":2,"600":3,"602":3,"603":6,"605":6,"607":3,"608":3,"609":3,"611":3,"612":6,"615":6,"616":5,"617":4,"618":4,"619":5,"620":1,"624":2,"625":1,"626":1,"627":1,"628":3,"629":8,"630":1,"635":5,"636":1,"639":1,"641":3,"642":2,"643":3,"645":3,"646":6,"648":3,"650":1,"652":1,"653":1,"654":2,"656":1,"657":2,"658":1,"659":2,"662":1,"665":1,"666":2,"667":5,"668":3,"670":2,"671":4,"672":2,"673":7,"674":1,"675":3,"677":2,"678":3,"679":3,"681":6,"682":6,"683":1,"685":1,"691":1,"695":4,"704":1,"706":4,"709":1,"711":3,"715":1,"718":3,"719":1,"725":1,"726":4,"728":3,"729":1,"731":1,"733":1,"734":3,"739":5,"742":2,"744":1,"745":1,"747":4,"748":2,"750":1,"751":1}}],["lsof",{"2":{"703":1}}],["lsusb",{"2":{"608":5}}],["l",{"2":{"555":1}}],["lhe",{"2":{"313":1,"358":1,"675":1,"679":1,"717":1}}],["l5813",{"2":{"113":1}}],["l5793",{"2":{"113":1}}],["lógicos",{"2":{"110":1}}],["lógicas",{"2":{"730":1}}],["lógica",{"2":{"95":1,"104":1,"217":1,"428":1,"430":4,"467":2,"505":2,"534":1,"562":1,"673":4,"679":1,"681":1,"682":1}}],["ltr",{"2":{"225":4}}],["lts",{"2":{"200":2}}],["lt",{"2":{"68":1,"115":1,"144":1,"169":1,"188":1,"204":1,"277":2,"279":1,"297":2,"299":1,"313":2,"317":2,"339":4,"344":3,"345":3,"347":6,"348":2,"349":6,"358":2,"362":2,"383":2,"387":20,"390":3,"402":1,"403":1,"444":1,"553":1,"555":3,"589":1,"596":1,"706":2,"737":1}}],["ldplusplus",{"2":{"68":1}}],["ldplusplus=clang++",{"2":{"68":1}}],["ld",{"2":{"68":1}}],["ld=clang",{"2":{"68":1}}],["ln",{"2":{"67":5}}],["lugares",{"2":{"271":1,"291":1,"347":1}}],["lugar",{"2":{"46":1,"96":1,"105":2,"134":1,"148":1,"173":1,"208":1,"220":1,"245":1,"250":1,"259":1,"328":1,"379":2,"668":1}}],["lá",{"2":{"39":1,"382":1,"413":1,"491":1,"532":1}}],["locking",{"2":{"705":1}}],["location",{"2":{"454":7,"461":3,"464":8,"465":2,"479":5,"485":3,"488":9,"489":2,"493":4}}],["locations",{"2":{"313":1,"358":1}}],["locationy",{"2":{"251":1}}],["locationx",{"2":{"251":1}}],["locais",{"0":{"67":1},"2":{"70":1,"135":1,"185":1,"312":1,"335":1,"357":1}}],["locale",{"2":{"462":1}}],["localizá",{"2":{"651":1}}],["localize",{"2":{"456":1}}],["localizado",{"2":{"457":1,"481":1}}],["localizada",{"2":{"35":1}}],["localização",{"2":{"120":1,"121":1,"130":1,"142":1,"168":1,"203":1,"320":1,"338":1,"365":1,"461":2,"479":1,"485":2}}],["localappdata",{"2":{"203":2}}],["localhost",{"2":{"131":1,"134":1,"280":1,"300":1,"320":1,"322":1,"365":1,"368":1,"619":1,"745":2}}],["local",{"0":{"335":1},"1":{"336":1},"2":{"66":1,"67":16,"68":1,"203":2,"219":3,"220":2,"239":3,"320":1,"334":1,"365":1,"454":1,"457":1,"459":1,"461":2,"481":1,"483":1,"485":2,"526":1,"527":1,"596":1,"603":1,"612":1,"630":1,"632":1,"646":1,"662":1,"663":2,"686":1,"705":1}}],["localmente",{"2":{"65":3,"310":1,"355":1,"547":1}}],["lotsofstyles",{"2":{"668":2}}],["lotes",{"2":{"501":2,"691":1}}],["lote",{"2":{"500":2,"501":4,"691":2,"692":1,"699":1}}],["lollipop",{"2":{"602":1,"611":1,"645":1}}],["loja",{"2":{"595":1}}],["lojas",{"0":{"656":1},"2":{"414":1}}],["loadmodulenames",{"2":{"576":1}}],["loadedmodulenames",{"2":{"576":3}}],["loaded",{"2":{"573":1,"576":1}}],["load",{"2":{"554":1}}],["loadingview",{"2":{"548":1}}],["lodash",{"2":{"381":1}}],["looks",{"2":{"244":1}}],["loop",{"2":{"55":1,"57":1,"456":1,"534":1,"695":1}}],["logger",{"2":{"538":1}}],["logcat",{"2":{"436":1,"685":2}}],["logic",{"2":{"430":4}}],["logo",{"2":{"331":2,"332":1,"334":1,"553":1,"699":1,"731":27}}],["logs",{"0":{"436":1},"2":{"128":3,"436":2,"454":1,"459":2,"551":1,"569":1,"711":1}}],["log",{"0":{"538":1},"2":{"128":4,"244":1,"392":1,"436":3,"454":6,"457":1,"459":2,"463":2,"464":3,"465":1,"466":1,"479":2,"481":1,"487":1,"488":3,"489":1,"521":1,"522":3,"563":1,"564":1,"573":1,"576":2}}],["logbox",{"0":{"127":1},"2":{"127":2,"128":5,"129":1,"130":1}}],["los",{"2":{"60":1,"67":1,"96":2,"105":2,"107":1,"135":1,"257":1,"279":1,"299":1,"346":1,"387":1,"419":1,"436":1,"456":2,"462":1,"486":1,"545":1,"570":1,"595":1,"629":1,"663":1,"679":2,"682":3,"692":1}}],["longitude",{"2":{"442":3,"443":3}}],["longitudedelta",{"2":{"442":3,"443":3}}],["longe",{"2":{"249":1,"470":1,"673":1}}],["long",{"2":{"245":2,"431":2,"491":1}}],["longas",{"2":{"245":1,"730":1}}],["longamente",{"2":{"74":1,"77":1}}],["longa",{"0":{"708":1},"1":{"712":1,"713":1},"2":{"57":1,"491":2,"559":1,"700":2,"731":1}}],["longos",{"2":{"500":1}}],["longo",{"2":{"47":1,"219":1,"223":1,"226":1,"227":3,"229":3,"230":2,"231":3,"349":2,"700":1}}],["longpress",{"2":{"35":1}}],["lo",{"2":{"38":2,"65":1,"67":2,"74":1,"77":1,"90":1,"99":1,"111":1,"112":1,"113":1,"136":1,"145":1,"148":1,"149":1,"152":1,"153":1,"165":1,"170":1,"173":1,"174":1,"177":1,"178":1,"183":1,"194":1,"196":1,"205":1,"208":1,"209":2,"212":1,"213":1,"218":1,"219":1,"257":1,"262":1,"271":1,"272":1,"278":1,"280":1,"291":1,"292":1,"298":1,"300":1,"320":1,"322":1,"323":1,"338":1,"343":1,"347":1,"365":1,"368":1,"369":1,"376":1,"377":1,"404":1,"405":1,"413":1,"441":2,"447":1,"451":1,"454":1,"455":1,"464":1,"465":2,"476":1,"488":1,"525":1,"527":1,"532":1,"538":1,"547":1,"549":2,"555":3,"561":1,"562":1,"566":1,"567":1,"580":1,"582":1,"583":1,"584":1,"585":1,"586":1,"593":1,"594":1,"595":1,"604":1,"605":3,"613":1,"622":1,"638":1,"647":1,"654":1,"667":1,"670":1,"675":1,"679":1,"681":1,"685":1,"703":1,"706":1,"709":2,"711":1,"723":1,"724":1,"725":1,"726":1,"729":1,"740":1,"746":1,"747":1,"748":1}}],["lambda",{"2":{"629":1}}],["laptop",{"2":{"603":1,"612":1,"620":1,"646":1,"745":1}}],["latitude",{"2":{"442":3,"443":4}}],["latitudedelta",{"2":{"442":3,"443":3}}],["lateral",{"2":{"547":1}}],["later",{"2":{"431":1}}],["lateinit",{"2":{"299":2,"404":1,"430":1}}],["latest",{"2":{"145":1,"170":1,"189":1,"205":1,"470":1}}],["lacuna",{"0":{"232":3},"1":{"233":3,"234":3,"235":3},"2":{"232":2}}],["laranja",{"2":{"223":3}}],["largura",{"0":{"233":1,"260":1},"1":{"261":1,"262":1,"263":1},"2":{"110":1,"111":2,"120":3,"233":6,"260":1,"261":1,"328":1,"333":1,"334":1,"339":1,"348":1,"403":1,"434":1,"509":1,"543":1,"756":1}}],["lançá",{"2":{"257":1,"604":1,"613":1,"622":1,"647":1}}],["lançada",{"2":{"452":1}}],["lançados",{"2":{"520":1}}],["lançado",{"2":{"257":1}}],["lançarmos",{"2":{"741":1}}],["lançar",{"2":{"257":2,"323":1,"369":1,"442":1,"685":1}}],["lançamentos",{"2":{"200":1,"746":1}}],["lançamento",{"0":{"283":1,"303":1,"549":1,"655":1},"2":{"43":1,"65":1,"73":1,"126":1,"127":1,"272":1,"283":3,"292":1,"303":3,"367":1,"537":1,"538":1,"549":2,"654":1,"655":1,"657":1,"658":2,"660":2,"682":1,"685":1,"696":1,"725":1,"746":1}}],["languages",{"2":{"142":2,"168":2,"203":2}}],["launchscreen",{"2":{"548":1}}],["launchoptionskey",{"2":{"367":1}}],["launchoptions",{"2":{"320":1,"365":1,"367":1,"492":1,"524":3}}],["launchdebugger",{"2":{"134":2}}],["launcher",{"2":{"73":1}}],["lawngreen",{"2":{"88":1}}],["lavenderblush",{"2":{"88":1}}],["lavender",{"2":{"88":1}}],["las",{"2":{"60":1,"63":1,"93":1,"96":1,"105":1,"134":1,"270":1,"290":1,"446":1,"458":1,"482":1,"538":1,"586":1,"671":1,"706":1,"726":1}}],["la",{"2":{"56":2,"156":1,"217":1,"237":1,"249":1,"251":1,"268":1,"288":1,"309":1,"328":1,"334":1,"336":1,"354":1,"442":1,"446":1,"465":1,"489":1,"491":1,"543":1,"651":1,"681":1,"687":1,"696":1,"717":1}}],["layoutifneeded",{"2":{"445":1}}],["layoutinflater",{"2":{"430":4}}],["layouts`",{"2":{"403":1}}],["layouts",{"2":{"235":1}}],["layoutanimation",{"0":{"60":1},"2":{"45":1,"60":6,"541":4}}],["layout",{"0":{"107":1,"108":1,"109":1,"222":1,"225":1,"234":1,"689":1},"1":{"108":1,"109":1,"110":2,"111":2,"223":1,"224":1,"225":1,"226":1,"227":1,"228":1,"229":1,"230":1,"231":1},"2":{"30":5,"45":1,"57":1,"60":3,"107":2,"110":2,"111":3,"222":3,"225":3,"234":2,"235":1,"263":1,"337":1,"347":2,"348":1,"387":1,"403":4,"404":9,"414":1,"421":1,"431":3,"441":1,"445":1,"509":1,"553":1,"555":1,"689":5,"690":2,"695":3,"756":1}}],["lado",{"2":{"14":1,"95":1,"101":1,"104":1,"110":2,"115":1,"141":1,"142":2,"167":1,"168":2,"202":1,"203":2,"225":2,"338":2,"413":1,"424":1,"463":1,"464":1,"488":1,"503":1,"534":2,"551":2,"555":1,"629":2,"638":1,"675":1,"680":1}}],["label=",{"2":{"26":1,"114":2,"115":2,"224":1,"225":1,"226":1,"227":1,"228":1,"229":1,"230":1,"234":1,"279":1,"299":1}}],["labelledby=",{"2":{"26":1}}],["labelledby",{"0":{"26":1},"2":{"26":1}}],["label",{"0":{"25":1},"2":{"4":1,"8":1,"35":6,"114":3,"115":3,"224":6,"225":6,"226":6,"227":6,"228":5,"229":6,"230":6,"231":4,"233":3,"234":5}}],["like",{"2":{"731":1}}],["likely",{"2":{"313":1,"439":1}}],["lidos",{"2":{"629":1}}],["lidam",{"2":{"680":1}}],["lidamos",{"2":{"427":1,"443":1}}],["lida",{"2":{"259":1,"693":1,"707":1}}],["lidando",{"0":{"243":1,"444":1,"520":1},"1":{"244":1,"245":1,"246":1,"247":1},"2":{"757":1}}],["lidar",{"0":{"667":1},"2":{"35":2,"43":1,"51":1,"94":1,"103":1,"242":1,"243":1,"254":1,"259":1,"278":1,"298":1,"339":1,"349":1,"431":1,"462":2,"629":1,"635":1,"639":1,"667":1,"691":1,"692":1,"718":1}}],["litedebug",{"2":{"586":1}}],["lite",{"2":{"586":1,"595":2}}],["literal",{"2":{"478":1}}],["literals",{"2":{"390":2}}],["lifecycleeventlistener",{"2":{"468":1}}],["lifecycle",{"2":{"468":2}}],["lifecyclestate",{"2":{"279":1,"299":1}}],["livre",{"2":{"508":1,"545":1}}],["livremente",{"2":{"427":1,"443":1}}],["livro",{"2":{"237":1}}],["live",{"0":{"27":1},"2":{"618":1}}],["limpe",{"2":{"747":1}}],["limpeza",{"2":{"495":1}}],["limpo",{"2":{"673":1}}],["limpando",{"2":{"700":1}}],["limpa",{"2":{"69":1,"116":1}}],["limpar",{"2":{"67":1,"116":1,"729":1}}],["limpas",{"2":{"67":1}}],["limegreen",{"2":{"88":1}}],["lime",{"2":{"88":1}}],["limitado",{"2":{"256":1,"374":1,"731":1}}],["limitadas",{"2":{"44":2}}],["limita",{"2":{"106":1}}],["limitação",{"2":{"57":1,"329":1,"700":1}}],["limitações",{"0":{"219":1},"2":{"55":1,"95":1,"104":1,"688":2}}],["limitar",{"2":{"50":1}}],["limite",{"2":{"43":4,"218":1,"342":4,"556":1}}],["limites",{"0":{"94":1,"103":1,"342":1},"2":{"42":1,"43":2,"44":1,"110":3,"218":2,"247":1,"342":1,"553":1,"554":1,"555":1,"556":2,"559":1,"669":1}}],["lib",{"2":{"705":1}}],["libexec",{"2":{"651":1}}],["liberá",{"2":{"251":1,"605":1,"670":1}}],["liberados",{"2":{"699":1}}],["liberando",{"2":{"671":1}}],["liberar",{"2":{"249":1,"251":1}}],["liberação",{"0":{"547":1},"2":{"48":1,"251":1,"687":1}}],["library",{"2":{"69":1,"166":1,"168":1,"383":1,"409":1,"470":2,"651":1,"680":1,"684":1}}],["libraries",{"2":{"65":1,"113":1,"313":13,"407":1,"411":1,"412":1}}],["linting",{"2":{"672":1}}],["linters",{"2":{"672":1}}],["lindo",{"2":{"668":1}}],["linguagem",{"2":{"381":1,"477":1,"732":1}}],["linguagens",{"0":{"104":1},"1":{"105":1,"106":1},"2":{"90":1,"94":2,"99":1,"103":1,"493":1}}],["linux",{"0":{"162":1,"606":1,"714":1},"1":{"607":1,"608":1,"609":1,"610":1,"611":1,"612":1,"613":1,"715":1,"716":1},"2":{"126":1,"131":1,"138":1,"514":1,"605":2,"608":8,"715":1}}],["line",{"2":{"531":1,"571":1,"573":1,"575":1,"577":1,"629":1}}],["linen",{"2":{"88":1}}],["lineheight",{"2":{"54":1}}],["linearlayout",{"2":{"347":1}}],["linearcountingretrypolicy",{"2":{"257":3}}],["linearmente",{"2":{"237":1}}],["linear",{"2":{"50":1}}],["linhas",{"2":{"57":1,"142":1,"153":1,"168":1,"178":1,"196":1,"213":1,"224":1,"229":10,"230":3,"232":2,"259":1,"270":1,"290":1,"472":1,"539":1,"555":1,"574":1,"581":1,"608":1,"652":1,"673":1,"677":1}}],["linha",{"0":{"144":1,"169":1,"185":1,"188":1,"204":1,"232":1,"312":1,"357":1},"1":{"233":1,"234":1,"235":1},"2":{"38":1,"58":1,"60":1,"65":1,"68":3,"133":1,"137":1,"144":1,"145":1,"164":1,"169":1,"170":1,"182":1,"185":2,"188":1,"189":1,"199":1,"204":1,"205":1,"222":1,"224":4,"226":1,"227":1,"229":2,"230":1,"270":2,"290":2,"312":2,"313":1,"325":1,"357":2,"358":1,"371":1,"385":1,"442":1,"457":1,"481":1,"540":1,"555":1,"574":1,"577":1,"598":1,"607":1,"608":4,"641":1,"656":2,"660":1,"678":1,"685":1}}],["linked",{"2":{"706":1}}],["linking",{"2":{"635":1}}],["linkingios",{"2":{"313":1}}],["links",{"0":{"635":1,"684":1},"2":{"67":1,"68":1,"635":4,"724":1}}],["link",{"2":{"11":3,"34":3,"67":1,"245":1,"250":1,"273":1,"293":1,"319":1,"320":1,"321":2,"325":1,"364":1,"365":1,"366":2,"371":1,"412":1,"553":1,"635":6,"745":2}}],["listras",{"2":{"554":1}}],["listeners",{"2":{"490":1}}],["listenercount",{"2":{"466":10}}],["listof",{"2":{"425":1,"432":1,"456":1}}],["listview",{"0":{"539":1},"2":{"78":2,"540":1}}],["list",{"0":{"730":1},"2":{"34":1,"259":1,"279":1,"299":1,"402":4,"425":1,"432":2,"433":2,"456":7,"599":1,"608":1,"625":1,"627":1,"642":1,"680":3,"753":1}}],["listar",{"2":{"595":1}}],["listas",{"0":{"539":1},"2":{"505":1,"730":2}}],["listado",{"2":{"617":1,"701":1}}],["listados",{"2":{"462":1,"726":1}}],["listada",{"2":{"382":1}}],["listadas",{"2":{"379":1,"586":1}}],["lista",{"0":{"504":1,"708":1},"1":{"505":1,"506":1,"507":1,"508":1,"509":1,"510":1,"511":1,"712":1,"713":1},"2":{"11":2,"34":3,"35":2,"48":1,"57":1,"134":1,"149":2,"174":2,"203":1,"209":2,"221":1,"235":1,"243":1,"246":1,"313":1,"321":1,"329":1,"333":1,"358":1,"366":1,"390":1,"439":1,"456":8,"462":1,"486":1,"497":3,"498":1,"504":2,"505":2,"506":2,"507":2,"508":1,"509":2,"519":1,"539":1,"540":1,"545":1,"586":1,"587":1,"592":2,"594":1,"599":1,"608":1,"615":1,"625":1,"628":1,"638":1,"648":1,"668":1,"730":3,"731":2}}],["ligar",{"2":{"538":1}}],["ligações",{"2":{"94":1,"103":1}}],["ligado",{"2":{"11":1,"34":1}}],["lightning",{"2":{"615":1}}],["light",{"2":{"279":2,"299":2}}],["lightyellow",{"2":{"88":1}}],["lightsteelblue",{"2":{"88":1}}],["lightslategrey",{"2":{"88":1}}],["lightskyblue",{"2":{"88":1}}],["lightseagreen",{"2":{"88":1}}],["lightsalmon",{"2":{"88":1}}],["lightpink",{"2":{"88":1}}],["lightgrey",{"2":{"88":1}}],["lightgreen",{"2":{"88":1}}],["lightgray",{"2":{"88":1}}],["lightgoldenrodyellow",{"2":{"88":1}}],["lightcyan",{"2":{"88":1}}],["lightcoral",{"2":{"88":1}}],["lightblue",{"2":{"88":1}}],["ligeiramente",{"2":{"0":1,"47":1,"657":1}}],["lê",{"2":{"10":1,"237":1}}],["legíveis",{"2":{"681":1}}],["legado",{"2":{"691":1}}],["legados",{"2":{"56":1}}],["legada",{"2":{"420":1,"440":1,"446":1,"449":1,"470":1,"474":1,"688":1}}],["let",{"2":{"256":1,"365":5,"390":3,"462":1,"466":1,"467":2,"573":1}}],["letras",{"2":{"86":1,"441":2}}],["length",{"2":{"576":2}}],["lentas",{"0":{"545":1},"2":{"541":1}}],["lenta",{"0":{"539":1},"2":{"258":1,"539":1}}],["lentos",{"2":{"677":1,"682":1}}],["lento",{"2":{"64":1,"491":1,"505":1,"506":1}}],["lendo",{"0":{"554":1},"2":{"236":1,"449":1,"459":1,"474":1,"483":1,"596":1}}],["lembrá",{"2":{"347":1}}],["lembrete",{"2":{"466":1,"490":1}}],["lembre",{"2":{"218":1,"259":1,"279":1,"299":1,"488":1,"524":1,"556":1,"639":1,"650":1,"651":1}}],["lemonchiffon",{"2":{"88":1}}],["leves",{"0":{"506":1}}],["leve",{"2":{"218":1,"237":1,"525":1,"553":1}}],["levando",{"2":{"656":1}}],["levantadas",{"2":{"523":1}}],["levadas",{"2":{"546":1,"604":1,"613":1,"622":1,"647":1}}],["levam",{"2":{"512":1,"670":1,"679":1}}],["leva",{"2":{"111":1,"242":2,"337":1,"426":1,"461":2,"485":2}}],["levarem",{"2":{"665":1}}],["levar",{"2":{"64":1,"67":1,"221":1,"341":1,"534":1,"573":1,"666":1}}],["left",{"2":{"74":1,"77":1,"122":5,"234":4,"338":1}}],["lead",{"2":{"358":1}}],["leader",{"2":{"51":2}}],["leanback",{"2":{"73":1}}],["ler",{"2":{"8":1,"55":1,"237":2,"399":2,"525":1,"528":1,"576":1,"635":1,"664":1,"683":1,"685":1,"693":1,"741":1}}],["lerá",{"2":{"6":1,"7":1}}],["leitura",{"2":{"92":1,"101":1,"637":1,"671":1}}],["leitor",{"0":{"36":1},"2":{"3":1,"4":1,"8":1,"35":1,"36":1,"158":1}}],["leitores",{"2":{"0":1}}],["leia",{"2":{"6":1,"131":1,"419":1,"546":1,"648":1,"675":1}}],["dão",{"2":{"692":1}}],["dígitos",{"2":{"608":1}}],["dúvida",{"2":{"608":1,"681":1}}],["ddmlib",{"2":{"710":1}}],["dd",{"2":{"462":2}}],["dda0dd",{"2":{"88":1}}],["dp",{"2":{"445":4}}],["dpi",{"2":{"434":2}}],["d8bfd8",{"2":{"88":1}}],["d2b48c",{"2":{"88":1}}],["d2691e",{"2":{"88":1}}],["db7093",{"2":{"88":1}}],["d3d3d3",{"2":{"88":2}}],["dcdcdc",{"2":{"88":1}}],["dc143c",{"2":{"88":1}}],["d",{"2":{"77":1,"126":1,"131":1,"454":2,"459":1,"526":2,"608":1,"685":1,"699":1,"730":1,"734":1}}],["droid",{"2":{"656":1}}],["drene",{"2":{"559":1}}],["drawframe",{"2":{"555":1,"559":1}}],["drawable",{"2":{"73":1,"330":1,"654":1}}],["driver",{"0":{"56":1},"2":{"56":8,"57":1}}],["dylanvann",{"2":{"508":1}}],["dynamic",{"2":{"390":1}}],["dynamiccolorios",{"2":{"80":1}}],["dy",{"2":{"53":4,"54":1}}],["dx",{"2":{"53":4,"54":1}}],["dêem",{"2":{"258":1}}],["dê",{"2":{"47":1,"95":1,"104":1,"344":1,"470":1,"519":1,"654":1}}],["dá",{"2":{"35":1,"96":1,"105":1,"349":1,"442":1,"452":1,"501":1,"533":1,"675":1}}],["duplex",{"2":{"522":1}}],["duplas",{"2":{"348":1}}],["duplicá",{"2":{"328":1}}],["duplo",{"2":{"33":1,"35":1}}],["dummyimage",{"2":{"92":8,"101":4}}],["durabilidade",{"2":{"673":1}}],["duração",{"2":{"134":1,"491":1,"700":1}}],["durações",{"2":{"47":1}}],["durante",{"0":{"65":1},"2":{"55":1,"67":1,"68":2,"101":1,"218":2,"221":2,"248":1,"456":1,"500":1,"503":1,"534":2,"541":1,"545":2,"548":1,"551":1,"552":1,"558":2,"571":1,"598":1,"607":1,"629":1,"636":1,"638":1,"641":1,"662":1,"663":1,"681":2,"682":1,"700":1,"724":1,"736":1,"744":1}}],["durationpersonalizada",{"2":{"47":1}}],["duration",{"2":{"46":1,"47":1,"51":1,"56":1}}],["duas",{"2":{"32":1,"35":3,"51":1,"55":1,"67":1,"68":1,"111":1,"153":1,"166":1,"178":1,"213":1,"231":1,"349":1,"427":1,"441":1,"447":1,"464":1,"488":1,"493":1,"533":1,"549":1,"561":1,"652":1,"672":1,"679":1,"708":1,"719":1,"723":1,"736":1}}],["dan",{"2":{"730":2}}],["danos",{"2":{"639":1}}],["dada",{"2":{"674":1}}],["dado",{"2":{"334":1,"675":1}}],["dados",{"0":{"333":1},"1":{"334":1},"2":{"43":1,"90":1,"94":1,"99":1,"103":1,"254":1,"320":2,"333":2,"334":7,"338":1,"349":4,"365":2,"379":1,"442":1,"443":1,"464":3,"467":1,"488":1,"540":2,"629":7,"630":2,"631":1,"633":2,"634":1,"635":2,"637":1,"638":1,"639":1,"673":1,"677":1,"678":1,"691":1,"693":3,"695":1,"730":7}}],["daí",{"2":{"469":1}}],["daemon",{"2":{"451":1}}],["dateformat",{"2":{"462":4}}],["datetime",{"2":{"445":1}}],["datepickermodes",{"2":{"445":1}}],["datepicker",{"2":{"445":1}}],["datepickerios",{"2":{"445":2}}],["date",{"2":{"131":2,"445":1,"462":1,"465":2,"493":4,"675":1,"699":2}}],["data=",{"2":{"511":1,"520":1,"730":1}}],["data",{"2":{"69":1,"278":2,"298":2,"333":2,"334":2,"462":1,"467":9,"493":1,"520":2,"522":1,"526":1,"531":5,"660":2,"730":4}}],["daqui",{"2":{"131":1,"414":1,"706":1}}],["da70d6",{"2":{"88":1}}],["daa520",{"2":{"88":1}}],["dará",{"2":{"313":1,"349":1,"358":1,"717":1}}],["darkviolet",{"2":{"88":1}}],["darkturquoise",{"2":{"88":1}}],["darkslategrey",{"2":{"88":1}}],["darkslateblue",{"2":{"88":1}}],["darkseagreen",{"2":{"88":1}}],["darksalmon",{"2":{"88":1}}],["darkred",{"2":{"88":1}}],["darkorchid",{"2":{"88":1}}],["darkorange",{"2":{"88":1,"223":1}}],["darkolivegreen",{"2":{"88":1}}],["darkmagenta",{"2":{"88":1}}],["darkkhaki",{"2":{"88":1}}],["darkgrey",{"2":{"88":1}}],["darkgreen",{"2":{"88":1}}],["darkgray",{"2":{"88":1}}],["darkgoldenrod",{"2":{"88":1}}],["darkcyan",{"2":{"88":1}}],["darkblue",{"2":{"88":1}}],["dar",{"2":{"56":1,"557":1,"679":1}}],["daltonismo",{"2":{"9":1}}],["dashboard",{"2":{"549":1}}],["das",{"0":{"88":1},"2":{"9":1,"11":1,"34":2,"39":1,"41":1,"43":1,"47":1,"50":1,"65":1,"74":1,"92":1,"94":1,"101":1,"103":1,"111":1,"120":1,"134":1,"216":1,"221":1,"229":1,"242":1,"251":1,"313":1,"321":1,"331":1,"334":1,"341":1,"344":1,"358":1,"366":1,"377":1,"379":2,"385":1,"390":1,"407":1,"421":3,"424":1,"441":3,"499":1,"523":1,"535":1,"556":1,"571":1,"596":1,"628":1,"666":1,"667":2,"671":1,"680":1,"691":1,"708":2,"718":1,"746":1}}],["da",{"0":{"55":1,"256":1,"336":1,"367":1,"380":1,"467":1,"496":1,"512":1,"514":1,"527":1,"535":1,"539":1,"542":1,"543":1,"552":1,"560":1,"561":1,"565":1},"1":{"381":1,"382":1,"383":1,"497":1,"498":1,"499":1,"500":1,"501":1,"502":1,"503":1,"504":1,"505":1,"506":1,"507":1,"508":1,"509":1,"510":1,"511":1,"513":1,"514":1,"515":1,"516":1,"528":1,"529":1,"553":1,"554":1,"555":1,"562":1,"563":1,"564":1,"565":1,"566":1},"2":{"5":1,"8":1,"9":1,"10":1,"11":1,"14":1,"27":1,"34":1,"35":3,"38":6,"42":1,"46":1,"47":3,"48":4,"56":2,"57":1,"62":1,"63":1,"65":2,"67":4,"68":1,"70":1,"74":2,"75":1,"76":1,"77":10,"80":2,"90":1,"94":1,"96":2,"99":1,"101":1,"103":1,"105":3,"106":2,"110":4,"111":8,"113":2,"114":1,"116":1,"120":1,"121":1,"122":1,"123":1,"135":1,"137":1,"138":1,"144":2,"145":1,"149":1,"152":1,"164":1,"169":2,"170":1,"174":1,"184":1,"188":2,"189":1,"191":1,"194":1,"199":1,"204":2,"205":1,"209":1,"212":1,"217":1,"218":1,"219":2,"222":1,"224":2,"225":3,"229":2,"231":1,"232":2,"233":4,"235":1,"242":1,"245":1,"247":1,"251":1,"256":1,"259":1,"261":1,"263":1,"270":1,"278":1,"279":2,"285":1,"290":1,"298":1,"299":2,"310":1,"313":4,"320":1,"328":8,"330":3,"331":1,"333":3,"334":3,"336":1,"337":4,"338":2,"341":1,"342":1,"344":2,"347":1,"348":1,"349":2,"355":1,"358":5,"365":1,"371":1,"374":1,"379":2,"381":1,"382":1,"383":2,"384":3,"385":1,"390":1,"399":1,"402":1,"403":1,"404":4,"412":2,"413":2,"415":1,"420":1,"421":1,"424":4,"425":1,"426":1,"427":1,"430":1,"435":1,"440":1,"441":1,"442":2,"443":2,"444":1,"445":2,"452":1,"455":1,"456":2,"457":1,"462":2,"463":1,"464":1,"465":3,"467":2,"468":2,"470":1,"471":2,"475":1,"477":2,"478":3,"479":1,"480":1,"481":1,"486":1,"487":4,"488":1,"491":1,"493":2,"499":4,"503":1,"504":2,"505":1,"506":1,"507":1,"508":1,"509":1,"511":1,"513":1,"515":1,"520":4,"521":1,"525":1,"531":5,"532":1,"534":1,"535":1,"539":1,"540":2,"541":1,"543":1,"545":5,"548":1,"549":1,"552":2,"553":2,"554":1,"555":1,"560":1,"561":1,"562":3,"563":2,"564":1,"565":2,"566":2,"567":1,"568":1,"574":1,"582":1,"583":1,"584":1,"585":1,"586":1,"589":2,"590":1,"591":1,"592":2,"594":1,"595":1,"596":1,"599":1,"600":2,"603":2,"608":3,"609":1,"612":3,"617":1,"621":2,"629":2,"630":1,"636":1,"642":1,"643":1,"646":3,"648":1,"650":1,"652":1,"656":1,"658":3,"660":2,"662":1,"663":1,"666":1,"668":2,"669":1,"672":1,"673":1,"675":1,"678":1,"680":3,"681":1,"682":2,"685":1,"687":2,"690":4,"691":3,"693":2,"694":1,"695":1,"697":3,"700":2,"704":2,"710":1,"723":1,"730":2,"742":1,"745":1,"746":1,"747":1,"753":1,"754":1,"762":1}}],["diligência",{"2":{"639":1}}],["dias",{"2":{"650":1}}],["dia",{"2":{"636":1}}],["diante",{"2":{"67":1,"255":1,"595":1,"682":1,"706":1}}],["didpress",{"2":{"573":2}}],["didfinishlaunchingwithoptions",{"2":{"342":1,"367":1,"524":1}}],["dizer",{"2":{"678":1,"681":1}}],["dizendo",{"2":{"619":1}}],["diz",{"2":{"262":1}}],["dirname",{"2":{"398":1,"399":2,"577":1}}],["dirigidas",{"2":{"379":1}}],["dir",{"2":{"191":2,"722":2}}],["dir=",{"2":{"191":1}}],["direção",{"0":{"224":1,"225":1},"2":{"224":1,"225":4}}],["direito",{"2":{"142":1,"168":1,"200":1,"203":1,"225":1,"234":1,"244":1,"321":1,"366":1,"530":1,"554":1}}],["direita",{"2":{"35":1,"224":5,"225":3,"545":2,"555":2,"599":1,"608":1,"642":1}}],["direciona",{"2":{"548":1}}],["direcionando",{"2":{"279":1,"299":1}}],["direcionados",{"2":{"732":1}}],["direcionado",{"2":{"278":1,"298":1,"746":1}}],["direcional",{"2":{"74":1}}],["direcioná",{"2":{"90":1,"99":1}}],["directory=ios",{"2":{"666":1}}],["directory",{"2":{"313":1,"379":2,"382":1,"386":1,"419":1,"529":1}}],["direction",{"2":{"225":3}}],["directionlayout",{"2":{"225":2}}],["direct",{"2":{"67":2}}],["direto",{"2":{"533":1,"635":3}}],["diretoriodestino",{"2":{"527":1}}],["diretos",{"0":{"635":1},"2":{"57":1,"635":3}}],["diretório",{"2":{"268":2,"281":1,"288":2,"301":1,"309":2,"324":1,"354":2,"370":1,"371":1,"376":1,"377":2,"379":1,"529":1,"538":1,"624":1,"651":2,"652":2,"706":1,"708":1,"711":1,"728":1}}],["diretórios",{"0":{"267":1,"308":1,"353":1},"2":{"142":1,"168":1,"265":1,"287":1,"288":1,"306":1,"351":1,"715":1}}],["diretiva",{"2":{"220":1}}],["direta",{"0":{"112":1},"1":{"113":1,"114":1,"115":1,"116":1,"117":1,"118":1,"119":1,"120":1,"121":1,"122":1,"123":1,"124":1},"2":{"63":1,"68":1,"91":1,"100":1,"112":1,"765":1}}],["diretamente",{"2":{"50":1,"52":1,"60":1,"63":1,"65":1,"95":1,"104":1,"112":3,"114":1,"116":1,"119":1,"152":1,"156":1,"177":1,"194":1,"212":1,"329":1,"447":2,"448":1,"463":1,"466":1,"487":1,"490":1,"521":1,"531":1,"532":1,"635":1,"679":1,"685":1,"693":1,"745":1}}],["diretrizes",{"2":{"6":1}}],["diálogo",{"2":{"142":2,"168":2,"203":2,"635":1}}],["diário",{"2":{"65":1}}],["dito",{"2":{"106":1,"681":1}}],["digite",{"2":{"142":1,"549":1,"600":1,"603":1,"609":1,"612":2,"646":2}}],["digitalmente",{"2":{"648":1}}],["digitalizando",{"2":{"605":1}}],["digitando",{"2":{"218":1}}],["digita",{"2":{"116":1,"242":2}}],["digitação",{"2":{"56":1}}],["digamos",{"2":{"106":1,"111":1,"242":1,"441":1,"442":1,"493":1,"545":1,"565":1,"566":1}}],["dict>",{"2":{"323":6,"369":6}}],["dicionário",{"2":{"101":1,"487":1,"488":1}}],["dicas",{"0":{"220":1,"548":1},"2":{"6":1,"7":1,"344":1,"399":1,"504":1}}],["dica",{"0":{"690":1},"1":{"691":1},"2":{"5":1,"6":1,"7":1,"131":1,"279":1,"283":1,"293":1,"313":1,"320":1,"321":1,"323":1,"355":1,"358":1,"366":1,"369":1,"375":1,"398":1,"399":1,"441":1,"485":1,"554":1,"566":1,"570":1,"600":1,"609":1,"617":1,"619":2,"643":1,"690":6,"721":1,"724":1}}],["diminua",{"2":{"262":1}}],["diminuam",{"2":{"231":1}}],["diminuir",{"2":{"35":1,"256":1,"442":2,"731":1}}],["diminui",{"2":{"35":1}}],["dimensionado",{"2":{"543":1}}],["dimensionadas",{"2":{"337":1}}],["dimensionar",{"0":{"337":1},"2":{"328":1}}],["dimension>",{"2":{"233":2}}],["dimension",{"2":{"233":7}}],["dimensões",{"0":{"261":1,"262":1,"263":1},"2":{"111":1,"261":4,"262":3,"263":3,"328":1,"330":1,"331":1,"333":1,"337":2}}],["dimensão",{"2":{"111":1,"227":1,"233":1,"338":1}}],["dimgrey",{"2":{"88":1}}],["dimgray",{"2":{"88":1}}],["dificultar",{"2":{"634":1}}],["diff",{"2":{"681":1,"720":1}}],["diffapply",{"2":{"595":1}}],["different",{"2":{"68":1}}],["difícil",{"2":{"112":1,"628":1,"639":1,"680":1,"681":1,"683":1,"685":1}}],["difíceis",{"2":{"96":1,"105":1,"681":1}}],["diferenças",{"2":{"566":1,"686":1,"707":1}}],["diferença",{"2":{"261":1}}],["diferente",{"0":{"704":1},"2":{"47":1,"77":1,"159":1,"191":1,"242":1,"270":1,"290":1,"341":1,"344":1,"348":2,"441":1,"491":1,"521":1,"554":1,"561":1,"576":1,"583":1,"584":1,"585":1,"704":1,"726":1,"739":1,"745":1}}],["diferentes",{"2":{"41":1,"65":1,"68":1,"69":1,"95":1,"104":1,"107":1,"111":2,"159":1,"200":1,"222":2,"236":1,"261":1,"285":1,"320":1,"328":1,"348":1,"365":1,"387":1,"424":1,"442":1,"465":1,"533":1,"552":1,"557":1,"595":1,"635":1,"670":1,"677":1}}],["diferem",{"2":{"0":1,"92":1,"101":1}}],["dinheiro",{"2":{"666":1}}],["dinner",{"2":{"450":1,"475":1}}],["dinâmico",{"2":{"509":1}}],["dinâmicos",{"0":{"51":1}}],["dinâmicas",{"2":{"333":1}}],["dinamicamente",{"2":{"10":1,"110":1,"111":2,"262":1,"328":1,"331":1,"399":1}}],["diversos",{"2":{"390":1}}],["diversas",{"2":{"11":1,"34":1,"35":1,"80":1,"230":1,"240":1,"248":1}}],["div",{"2":{"347":1,"387":2}}],["dividi",{"2":{"675":1}}],["dividir",{"2":{"565":1}}],["divididos",{"2":{"730":1}}],["dividido",{"2":{"223":1}}],["divide",{"2":{"49":1}}],["divisão",{"2":{"49":1,"658":1}}],["disciplina",{"2":{"681":1}}],["disco",{"2":{"320":1,"365":1,"491":1,"629":2}}],["discussões",{"2":{"695":1}}],["discussão",{"2":{"78":1}}],["discutir",{"2":{"532":1}}],["discurso",{"2":{"10":1,"27":1}}],["distintos",{"2":{"656":1}}],["distinção",{"2":{"635":1}}],["distinguished",{"2":{"650":1}}],["distingui",{"2":{"96":1,"105":1}}],["distraído",{"2":{"545":1}}],["distribute",{"2":{"549":1}}],["distributionurl",{"2":{"200":1}}],["distribua",{"2":{"226":1}}],["distribuir",{"2":{"549":1,"648":1}}],["distribuirá",{"2":{"231":2}}],["distribuindo",{"2":{"226":2,"229":2}}],["distribuição",{"2":{"138":1,"166":2,"226":1,"229":2,"547":1}}],["distribuídas",{"2":{"328":1}}],["distribuída",{"2":{"70":1}}],["distribuído",{"2":{"70":1,"231":1,"447":1,"580":1}}],["distribuídos",{"0":{"70":1},"2":{"66":1,"469":1,"470":1}}],["distância",{"2":{"442":1}}],["disabletveventhandler",{"2":{"74":2,"77":2}}],["disable",{"2":{"65":1,"74":1,"77":1,"526":1,"748":1}}],["disabled=",{"2":{"349":3}}],["disabled",{"0":{"22":1},"2":{"12":1,"349":1,"748":1}}],["dissociar",{"2":{"191":1}}],["disso",{"2":{"38":1,"50":1,"75":1,"77":1,"94":1,"103":1,"116":1,"120":1,"128":1,"191":1,"234":1,"235":1,"270":1,"278":1,"290":1,"298":1,"330":1,"400":1,"428":1,"455":1,"464":1,"479":1,"480":1,"511":1,"541":1,"542":1,"543":1,"568":1,"638":1,"675":1,"678":1,"682":1,"747":1}}],["display",{"2":{"390":1}}],["dispare",{"2":{"541":1}}],["disparar",{"2":{"542":1}}],["disparando",{"2":{"252":1}}],["disparado",{"2":{"251":1}}],["dispara",{"2":{"30":1,"74":1,"77":2}}],["dispatchui",{"2":{"555":1}}],["dispatchviewmanagercommand",{"2":{"434":1,"444":2}}],["dispatchongloballayout",{"2":{"431":2}}],["dispatch",{"2":{"231":1,"491":10}}],["dispensáveis",{"2":{"129":1}}],["disponha",{"2":{"431":1}}],["disponíveis",{"0":{"709":1},"2":{"38":1,"39":1,"89":1,"95":1,"97":1,"98":1,"104":1,"106":1,"119":2,"120":1,"149":1,"174":1,"187":1,"209":1,"270":1,"290":1,"330":1,"331":1,"337":1,"391":1,"398":1,"420":1,"440":1,"459":1,"471":1,"531":1,"592":1,"625":2,"682":1}}],["disponível",{"2":{"2":1,"9":1,"39":1,"111":1,"113":1,"223":1,"262":3,"270":1,"290":1,"313":1,"334":1,"358":1,"420":1,"440":1,"446":1,"456":1,"457":2,"463":1,"481":2,"524":1,"562":1,"586":1,"655":1,"687":1,"728":1,"739":1,"742":2}}],["dispor",{"2":{"231":1}}],["disposto",{"2":{"334":1,"628":1}}],["dispostos",{"2":{"224":1,"225":3}}],["dispostas",{"2":{"224":1}}],["dispositivos",{"0":{"71":1},"1":{"72":1,"73":1,"74":1,"75":1,"76":1,"77":1,"78":1},"2":{"39":1,"42":1,"71":1,"76":2,"126":1,"133":1,"134":1,"149":1,"174":1,"209":1,"246":1,"261":1,"455":1,"480":1,"512":1,"514":1,"533":1,"550":2,"598":1,"607":1,"608":1,"617":1,"619":2,"625":3,"641":1,"656":1,"699":1}}],["dispositivo",{"0":{"132":1,"147":1,"148":1,"149":1,"172":1,"173":1,"174":1,"195":1,"207":1,"208":1,"209":1,"599":1,"605":1,"608":1,"615":1,"625":1,"626":1,"642":1},"1":{"148":1,"149":1,"173":1,"174":1,"196":1,"208":1,"209":1,"626":1},"2":{"6":1,"38":1,"39":2,"42":1,"43":1,"65":1,"74":2,"77":2,"126":2,"131":2,"133":2,"135":1,"147":5,"148":1,"167":1,"172":5,"173":1,"195":1,"202":1,"207":5,"208":1,"279":1,"299":1,"328":1,"418":1,"436":1,"502":1,"529":4,"547":1,"548":1,"549":2,"553":1,"554":1,"555":1,"598":2,"599":6,"600":1,"601":1,"602":2,"603":2,"605":4,"607":2,"608":7,"609":1,"610":1,"611":2,"612":2,"615":5,"617":3,"618":2,"619":4,"625":2,"627":1,"629":2,"634":1,"638":1,"641":2,"642":6,"643":1,"644":1,"645":2,"646":2,"655":1,"656":2,"682":1,"699":1,"704":1,"744":1,"745":2,"755":1}}],["dogfood",{"2":{"697":1}}],["dobrando",{"2":{"673":1}}],["dotenv",{"2":{"629":1}}],["doexpensiveaction",{"2":{"544":1}}],["doesn",{"2":{"467":2}}],["does",{"2":{"467":6}}],["doframe",{"2":{"431":2}}],["double",{"2":{"424":2,"462":4,"486":1}}],["doubleconversion",{"2":{"313":2}}],["dootherstuffasync",{"2":{"390":1}}],["docs",{"2":{"348":1,"387":1,"398":1,"415":1,"684":1}}],["documento",{"2":{"531":1,"605":1}}],["documentos",{"0":{"237":1},"2":{"6":1,"131":1,"236":1,"237":1,"284":1,"304":1,"326":1,"329":1,"372":1,"415":1,"424":1,"617":1}}],["documentá",{"2":{"442":1}}],["documente",{"2":{"426":1}}],["documentaremos",{"2":{"442":1}}],["documentar",{"2":{"442":1}}],["documentado",{"2":{"442":1,"515":1,"745":1}}],["documentados",{"2":{"387":1}}],["documentada",{"2":{"235":1}}],["documentação",{"0":{"752":1},"1":{"753":1,"754":1,"755":1,"756":1,"757":1,"758":1,"759":1,"760":1,"761":1,"762":1,"763":1,"764":1,"765":1,"766":1,"767":1,"768":1,"769":1},"2":{"36":1,"77":1,"236":1,"242":2,"339":1,"343":1,"345":1,"349":1,"390":1,"398":1,"413":1,"415":1,"442":1,"519":1,"520":1,"589":1,"592":1,"648":1,"656":1,"671":1,"694":1,"738":1,"747":1}}],["doreact",{"2":{"313":1}}],["dores",{"2":{"143":1}}],["dominic",{"2":{"730":2}}],["domínios",{"2":{"520":3}}],["dom",{"2":{"112":3,"381":1,"514":1,"679":1}}],["dodgerblue",{"2":{"88":1}}],["downgrade",{"2":{"710":1}}],["downloading",{"2":{"313":1,"358":1}}],["download",{"2":{"200":1,"337":1}}],["downloads",{"2":{"200":1}}],["down",{"2":{"74":1,"77":1,"731":1}}],["dose",{"2":{"681":1}}],["dosomethingexpensive",{"2":{"491":1}}],["dosomethingwhichdoesnotcareaboutthevaluethrown",{"2":{"390":1}}],["dostuffasync",{"2":{"390":1}}],["dos",{"0":{"330":1},"2":{"11":1,"35":1,"48":1,"50":1,"63":1,"64":1,"71":1,"74":2,"106":1,"107":1,"108":1,"110":2,"115":1,"119":2,"187":1,"226":1,"227":1,"231":3,"235":1,"241":1,"245":2,"248":1,"252":1,"261":1,"331":1,"346":1,"348":1,"349":1,"377":1,"379":1,"387":2,"389":1,"420":1,"424":1,"437":1,"440":1,"445":3,"459":1,"462":2,"465":2,"470":1,"483":1,"486":2,"491":2,"504":1,"507":1,"515":1,"533":2,"534":1,"539":1,"545":1,"550":1,"556":1,"559":1,"572":2,"575":1,"598":1,"607":1,"625":1,"628":1,"637":1,"638":1,"639":1,"641":1,"660":1,"667":1,"668":2,"673":1,"676":1,"682":1,"692":1,"696":1,"708":1,"718":1,"730":1}}],["dois",{"2":{"2":2,"30":1,"31":1,"33":1,"35":2,"37":1,"45":1,"49":1,"66":1,"89":1,"98":1,"107":1,"216":1,"251":1,"349":1,"407":1,"464":1,"488":1,"558":1,"595":1,"635":1,"636":1,"681":1,"730":1}}],["do",{"0":{"38":1,"39":1,"66":1,"68":1,"93":1,"97":1,"102":1,"106":1,"128":1,"131":1,"139":1,"144":1,"166":1,"169":1,"188":1,"204":1,"225":1,"240":1,"251":1,"313":1,"330":1,"335":1,"336":1,"340":1,"341":1,"342":1,"343":1,"347":1,"358":1,"383":1,"420":1,"440":1,"447":1,"449":1,"453":1,"468":1,"470":1,"478":1,"532":1,"539":1,"541":1,"542":1,"543":2,"545":1,"552":1,"563":1,"564":1,"569":1,"626":1,"653":1,"655":1,"657":1,"658":2,"680":1,"708":1,"710":1,"711":1,"737":1,"745":1,"746":1,"752":1,"754":1},"1":{"67":1,"68":1,"69":1,"167":1,"168":1,"252":1,"336":1,"344":1,"345":1,"346":1,"347":1,"348":1,"349":1,"421":1,"422":1,"423":1,"424":1,"425":1,"426":1,"427":1,"428":1,"429":1,"430":1,"431":1,"432":1,"433":1,"434":1,"441":1,"442":1,"443":1,"444":1,"445":1,"450":1,"451":1,"452":1,"453":1,"454":1,"455":1,"456":1,"457":1,"458":1,"459":1,"460":1,"461":1,"462":1,"463":1,"464":1,"465":1,"466":1,"467":1,"468":1,"469":1,"533":1,"534":1,"535":1,"536":1,"537":1,"538":1,"539":1,"540":1,"541":1,"542":1,"543":1,"544":1,"545":1,"553":1,"554":1,"555":1,"681":1,"712":2,"713":2,"747":1,"748":1,"753":1,"754":1,"755":1,"756":1,"757":1,"758":1,"759":1,"760":1,"761":1,"762":1,"763":1,"764":1,"765":1,"766":1,"767":1,"768":1,"769":1},"2":{"0":1,"3":1,"4":1,"6":3,"11":2,"13":5,"14":1,"19":1,"26":1,"28":1,"31":1,"33":1,"34":2,"35":3,"36":1,"39":3,"41":1,"42":1,"43":4,"45":1,"46":2,"47":3,"48":2,"50":1,"51":2,"53":2,"55":2,"56":3,"58":1,"60":3,"62":1,"63":3,"64":1,"65":3,"66":2,"67":7,"68":11,"69":5,"70":1,"73":2,"74":5,"75":1,"77":9,"79":1,"80":1,"85":1,"90":2,"92":1,"95":3,"96":4,"99":2,"104":3,"105":5,"106":2,"110":5,"111":15,"112":1,"116":2,"120":3,"121":1,"123":1,"127":1,"128":2,"129":2,"130":1,"131":1,"133":3,"134":5,"135":3,"137":2,"139":4,"141":1,"142":9,"143":3,"146":1,"151":1,"152":2,"156":2,"158":3,"159":3,"164":3,"165":1,"166":1,"167":1,"168":8,"171":1,"176":1,"177":1,"183":1,"184":1,"185":1,"186":1,"187":3,"189":2,"190":2,"191":9,"193":1,"194":1,"199":2,"200":9,"202":1,"203":8,"206":1,"211":1,"212":2,"216":1,"217":2,"218":4,"220":3,"221":2,"223":4,"224":6,"225":3,"226":14,"227":10,"229":14,"230":3,"231":5,"232":1,"233":3,"234":3,"236":2,"238":1,"241":1,"242":1,"243":1,"244":1,"245":3,"248":1,"249":1,"251":8,"252":1,"255":1,"256":1,"258":1,"259":2,"263":1,"265":2,"266":2,"268":2,"270":3,"271":2,"272":1,"273":1,"276":2,"278":1,"279":13,"281":1,"282":2,"283":3,"285":1,"287":2,"288":5,"290":3,"291":2,"292":1,"293":1,"296":2,"298":1,"299":13,"301":1,"302":2,"303":3,"306":3,"307":2,"309":2,"311":2,"312":1,"313":6,"316":2,"317":3,"319":2,"320":5,"323":1,"324":1,"325":4,"328":5,"329":1,"330":3,"334":2,"337":3,"338":3,"339":1,"340":1,"341":2,"342":4,"343":2,"344":4,"345":3,"346":2,"348":3,"349":12,"351":3,"352":2,"354":2,"356":2,"358":5,"361":2,"362":3,"364":2,"365":5,"367":1,"369":1,"370":1,"371":6,"375":1,"376":1,"377":1,"378":1,"379":3,"381":1,"383":1,"384":1,"385":1,"386":3,"387":2,"389":1,"390":1,"398":6,"399":3,"402":2,"404":4,"405":1,"406":1,"407":1,"412":1,"413":2,"414":1,"415":2,"418":2,"420":4,"421":1,"422":2,"424":7,"425":1,"426":1,"427":3,"428":2,"430":4,"431":1,"436":3,"437":1,"440":3,"441":7,"442":10,"443":7,"444":2,"445":3,"446":1,"447":1,"448":3,"450":2,"452":5,"453":1,"454":5,"455":2,"456":4,"457":3,"458":3,"459":2,"461":6,"462":1,"463":2,"464":4,"465":1,"466":2,"467":1,"468":1,"469":1,"470":4,"472":1,"473":1,"475":1,"477":4,"478":3,"479":6,"480":3,"481":3,"482":3,"483":3,"485":6,"487":1,"488":3,"489":1,"490":4,"491":3,"493":6,"495":1,"497":5,"498":1,"506":1,"507":1,"509":1,"511":1,"515":1,"516":4,"518":1,"519":1,"520":2,"521":1,"523":1,"524":3,"525":3,"526":1,"527":2,"529":5,"531":3,"532":1,"533":1,"534":4,"535":2,"537":1,"538":2,"541":4,"544":1,"545":1,"546":1,"547":1,"548":3,"549":4,"551":4,"552":3,"553":4,"554":4,"555":12,"556":4,"557":4,"559":3,"560":2,"563":3,"564":2,"566":1,"567":4,"568":1,"569":1,"570":1,"571":4,"572":1,"573":2,"577":1,"581":1,"582":1,"585":1,"586":1,"587":1,"588":1,"590":2,"593":1,"595":4,"596":3,"598":1,"600":2,"602":1,"603":3,"607":2,"608":5,"609":2,"611":1,"612":3,"615":1,"616":2,"617":1,"618":1,"619":3,"624":2,"625":1,"626":1,"627":2,"628":1,"629":13,"630":2,"634":1,"635":4,"636":3,"637":1,"638":3,"641":2,"643":2,"645":1,"646":2,"648":1,"651":2,"652":6,"653":1,"654":5,"655":4,"656":2,"657":2,"658":3,"660":2,"662":3,"663":3,"666":4,"667":2,"668":2,"670":1,"671":2,"672":2,"673":7,"674":2,"675":2,"676":1,"677":3,"678":3,"679":9,"680":2,"681":5,"682":6,"685":2,"686":1,"687":4,"688":2,"689":3,"690":1,"692":3,"695":3,"696":1,"698":1,"699":2,"700":1,"703":1,"704":2,"706":2,"707":1,"708":2,"709":2,"710":1,"711":2,"715":1,"716":1,"717":1,"718":2,"719":1,"721":2,"722":1,"726":3,"729":1,"730":1,"734":1,"736":1,"737":1,"738":1,"739":2,"740":2,"741":9,"742":4,"744":1,"745":9,"746":7,"747":1,"751":2,"753":1,"762":1,"764":2,"765":2}}],["dedicado",{"2":{"695":1,"697":2}}],["dedicados",{"2":{"673":1}}],["dedicatedworker",{"2":{"551":1}}],["dedo",{"2":{"35":1,"249":1,"251":1}}],["dedos",{"2":{"31":1,"33":1,"35":2}}],["degradê",{"2":{"551":1}}],["demanda",{"2":{"541":1}}],["demorar",{"2":{"491":1,"534":1}}],["demonstrar",{"2":{"467":1}}],["demonstrações",{"2":{"128":1}}],["demonstra",{"2":{"116":1}}],["dealloc",{"2":{"490":1}}],["denativecomponent`",{"2":{"444":1}}],["denotados",{"2":{"348":1}}],["denominado",{"2":{"338":1,"402":1,"477":1}}],["densidades",{"2":{"328":1}}],["densidade",{"2":{"261":1,"328":2}}],["dentro",{"2":{"11":1,"34":1,"35":2,"67":2,"74":2,"90":1,"99":1,"111":1,"115":1,"127":1,"152":1,"194":1,"212":1,"218":1,"226":2,"228":2,"231":1,"256":1,"257":1,"270":1,"277":1,"279":1,"282":1,"290":1,"297":1,"299":1,"302":1,"317":2,"320":2,"342":2,"345":2,"346":2,"347":1,"349":2,"362":2,"365":2,"398":1,"411":1,"412":1,"442":1,"446":1,"452":1,"455":1,"456":3,"457":1,"462":1,"465":1,"479":1,"480":1,"481":1,"489":1,"491":1,"493":1,"533":1,"544":1,"573":1,"581":1,"615":1,"624":1,"663":1,"689":1,"699":1}}],["deixá",{"2":{"638":1}}],["deixa",{"2":{"692":1}}],["deixarão",{"2":{"638":1}}],["deixar",{"2":{"638":1,"668":1,"734":1}}],["deixamos",{"2":{"751":1}}],["deixam",{"2":{"249":1,"722":1}}],["deixe",{"2":{"152":1,"194":1,"212":1}}],["debugging",{"0":{"760":1},"2":{"598":1,"607":1}}],["debuggablevariants",{"0":{"586":1},"2":{"586":2,"595":4}}],["debugger=",{"2":{"134":1}}],["debugger",{"2":{"131":2,"134":2,"619":1}}],["debug",{"0":{"435":1},"1":{"436":1,"437":1,"438":1,"439":1},"2":{"134":1,"273":1,"279":1,"293":1,"299":1,"358":2,"392":1,"402":2,"436":1,"439":1,"548":2,"551":1,"586":1,"595":3,"599":1,"603":1,"608":1,"612":1,"642":1,"646":1,"760":1}}],["deb887",{"2":{"88":1}}],["deep",{"2":{"635":1}}],["deepskyblue",{"2":{"88":1,"229":1,"230":1,"232":1}}],["deeppink",{"2":{"88":1}}],["delimitadores",{"2":{"722":1}}],["delas",{"2":{"539":1,"678":1}}],["delay",{"2":{"48":1}}],["deles",{"2":{"407":2,"418":1,"420":1,"440":1,"491":1,"572":1}}],["delega",{"2":{"421":1,"441":1}}],["delegate",{"2":{"111":1,"443":1}}],["delegados",{"2":{"421":1,"441":1,"488":1}}],["delegado",{"2":{"105":1,"111":7,"443":2,"492":1}}],["delete",{"2":{"74":1,"77":1}}],["dele",{"2":{"35":2,"242":1,"279":1,"299":1,"345":1,"456":1,"521":1,"615":1}}],["def",{"2":{"657":1}}],["defaultview",{"2":{"442":2,"443":1}}],["defaultvalue=",{"2":{"242":1,"346":1,"387":1}}],["defaultfloat",{"2":{"424":4}}],["defaultint",{"2":{"424":1}}],["defaultboolean",{"2":{"424":2}}],["defaultsessionconfiguration",{"2":{"524":1}}],["defaults",{"2":{"402":2}}],["defaultreactnativehost",{"2":{"402":4}}],["defaultconfig",{"2":{"399":6,"653":1}}],["defaulthardwarebackbtnhandler",{"2":{"279":1,"299":1}}],["default",{"2":{"46":1,"53":1,"54":1,"60":1,"92":1,"101":1,"114":2,"115":2,"116":2,"122":2,"223":1,"224":1,"225":1,"226":1,"227":1,"228":1,"229":1,"230":1,"231":1,"232":1,"233":1,"234":1,"239":1,"242":1,"244":1,"245":1,"256":2,"261":1,"262":1,"263":1,"334":1,"344":3,"345":3,"346":1,"347":1,"348":3,"349":2,"387":1,"390":3,"424":2,"431":1,"457":1,"461":2,"463":7,"481":1,"485":2,"487":3,"491":1,"520":1,"562":3,"573":3,"668":1,"730":2,"731":1,"737":1,"748":1,"751":1}}],["deficiência",{"2":{"9":1}}],["defined",{"2":{"358":1}}],["defines",{"2":{"68":1,"256":2}}],["define",{"2":{"25":1,"35":1,"37":1,"229":1,"232":3,"233":2,"234":1,"279":1,"299":1,"349":1,"426":1}}],["definições",{"2":{"732":1}}],["definição",{"2":{"12":1,"77":1,"421":1,"441":1}}],["defini",{"2":{"465":1}}],["definitiva",{"2":{"379":1}}],["definimos",{"2":{"111":4,"442":1}}],["definindo",{"2":{"50":1,"51":1,"56":1,"78":1,"332":1,"520":1,"731":1,"751":1}}],["definidas",{"2":{"270":1,"290":1,"423":1,"424":1}}],["definida",{"2":{"46":1,"48":1,"114":1,"227":1,"228":1,"230":1,"349":1,"442":1,"563":1}}],["definidos",{"2":{"119":1,"220":1,"233":1,"441":1,"708":1}}],["definido",{"2":{"10":1,"13":3,"30":1,"77":1,"92":1,"101":1,"111":1,"117":1,"223":1,"226":2,"263":1,"342":2,"424":1,"444":2,"523":1,"636":1,"662":2,"666":1,"747":1,"750":1}}],["definirmos",{"2":{"442":1}}],["definirá",{"2":{"223":1}}],["definir",{"2":{"3":1,"14":2,"15":1,"24":1,"46":1,"50":2,"60":1,"101":1,"110":1,"111":1,"112":1,"114":2,"134":1,"135":1,"223":1,"231":3,"261":2,"279":1,"299":1,"328":1,"332":1,"344":1,"347":1,"348":1,"349":1,"399":1,"429":2,"441":1,"500":1,"502":1,"510":1,"524":1,"531":1,"662":1,"663":1,"668":1,"739":1}}],["defina",{"2":{"3":1,"9":1,"12":1,"35":1,"134":1,"502":1,"541":1,"547":1,"739":1}}],["decrease",{"2":{"737":1}}],["decrement",{"2":{"35":1,"737":1}}],["decolar",{"2":{"673":1}}],["decodificada",{"2":{"341":1}}],["decodificação",{"0":{"341":1},"2":{"341":3}}],["declare",{"2":{"443":1}}],["declara",{"2":{"349":1}}],["declarando",{"2":{"345":1}}],["declaração",{"2":{"344":1,"424":1}}],["declarado",{"2":{"95":1,"104":1}}],["declarativa",{"2":{"46":1,"250":1}}],["declarativos",{"2":{"46":1}}],["decida",{"2":{"682":1}}],["decidir",{"2":{"259":1,"313":1,"358":1,"683":1}}],["decifrável",{"2":{"660":1}}],["decisão",{"2":{"338":1}}],["deceleration",{"2":{"48":1}}],["decadência",{"2":{"48":1}}],["decay",{"2":{"48":1}}],["decair",{"2":{"48":1}}],["decaimento",{"2":{"47":1}}],["depurável",{"2":{"596":1}}],["depuráveis",{"2":{"595":1}}],["depure",{"2":{"414":1}}],["depuradas",{"2":{"586":1}}],["depuradora",{"2":{"699":1}}],["depurador",{"2":{"131":1,"134":7,"135":1,"437":1,"455":2,"480":2,"483":1,"699":1,"745":2}}],["depurando",{"0":{"437":1,"569":1,"745":1},"1":{"438":1,"439":1},"2":{"711":1}}],["depurar",{"2":{"96":1,"105":1,"131":1,"135":2,"136":1,"552":1,"567":1,"576":1,"603":1,"612":1,"646":1,"666":2,"685":1,"699":1,"745":1}}],["depuração",{"0":{"125":1,"132":1,"598":1,"607":1,"641":1},"1":{"126":1,"127":1,"128":1,"129":1,"130":1,"131":1,"132":1,"133":1,"134":1,"135":1,"136":1},"2":{"43":1,"126":1,"131":1,"133":1,"134":2,"273":1,"284":1,"293":1,"304":1,"320":1,"326":1,"358":1,"365":1,"372":1,"389":1,"437":1,"454":1,"483":1,"538":1,"548":1,"551":1,"569":1,"598":2,"599":1,"602":1,"607":2,"611":1,"641":3,"645":1,"659":1,"660":1,"666":1,"745":3,"760":1}}],["dependa",{"2":{"479":1}}],["dependência",{"0":{"492":1},"2":{"128":1,"221":1,"288":1,"447":1,"567":1,"596":1,"667":2,"676":1,"677":2,"678":1,"734":1}}],["dependências",{"0":{"137":1,"164":1,"182":1,"199":1,"268":1,"309":1,"313":1,"354":1,"358":1,"667":1,"725":1},"1":{"138":1,"139":1,"140":1,"141":1,"142":1,"143":1,"144":1,"145":1,"146":1,"147":1,"148":1,"149":1,"150":1,"151":1,"152":1,"153":1,"154":1,"155":1,"200":1,"201":1,"202":1,"203":1,"204":1,"205":1,"206":1,"207":1,"208":1,"209":1,"210":1,"211":1,"212":1,"213":1,"214":1,"215":1},"2":{"96":1,"105":1,"187":1,"189":2,"221":4,"265":1,"268":1,"270":4,"287":1,"288":2,"290":4,"306":2,"309":1,"351":2,"354":1,"377":1,"378":2,"405":1,"409":1,"492":1,"596":1,"657":1,"666":1,"667":2,"671":1,"677":1,"706":3,"707":1,"718":1,"725":1}}],["depend=true",{"2":{"68":1}}],["dependem",{"2":{"279":1,"299":1,"379":1,"407":1,"521":1,"667":1}}],["dependerão",{"2":{"557":1}}],["dependerá",{"2":{"123":1,"245":1,"313":2,"358":2}}],["depender",{"2":{"115":1,"389":1,"673":1,"678":1,"679":1}}],["depende",{"2":{"65":1,"69":2,"90":2,"99":2,"540":1,"667":1,"677":1}}],["dependencies>",{"2":{"409":1}}],["dependencies",{"2":{"270":2,"290":2,"313":3,"358":3,"409":1,"667":1}}],["dependency",{"2":{"268":1,"309":1,"354":1}}],["dependente",{"2":{"111":1}}],["dependentes",{"2":{"46":1}}],["dependendo",{"2":{"47":1,"95":1,"104":1,"159":1,"233":1,"285":1,"313":1,"344":1,"358":1,"555":1,"601":1,"610":1,"644":1,"672":1,"693":1}}],["depois",{"2":{"35":1,"38":1,"48":1,"50":2,"56":1,"65":1,"67":1,"77":1,"92":1,"101":1,"141":1,"149":2,"166":1,"167":1,"174":1,"202":1,"209":1,"218":1,"231":1,"244":1,"262":1,"313":1,"358":1,"378":1,"379":1,"454":1,"456":1,"466":1,"470":1,"548":1,"549":1,"554":1,"560":2,"562":1,"570":1,"578":1,"603":1,"612":1,"624":1,"646":1,"674":1,"681":1,"682":1,"688":1,"699":1,"728":1,"742":1,"745":1,"746":1,"748":1}}],["detox",{"2":{"682":1,"684":1}}],["details",{"2":{"142":2,"168":1,"203":2}}],["detalhe",{"2":{"464":1,"491":2}}],["detalhes",{"2":{"36":1,"74":1,"75":1,"93":1,"96":1,"97":1,"102":1,"106":1,"168":1,"390":1,"465":1,"486":1,"506":1,"551":1,"635":1,"648":1,"680":3}}],["detalhando",{"2":{"569":1}}],["detalha",{"2":{"400":1}}],["detalhado",{"2":{"711":1,"742":1}}],["detalhados",{"2":{"242":1}}],["detalhada",{"2":{"711":1}}],["detalhadas",{"2":{"551":1,"706":1}}],["detalhadamente",{"2":{"105":1,"673":1}}],["detecção",{"2":{"562":1}}],["detectou",{"2":{"621":1}}],["detectando",{"0":{"563":1,"564":1}}],["detecta",{"2":{"562":1}}],["detectadas",{"2":{"96":1,"105":1}}],["detectará",{"2":{"565":1}}],["detectar",{"2":{"74":1,"76":1,"77":1,"245":1,"563":1,"564":1,"672":1}}],["detected",{"2":{"65":2}}],["determinando",{"0":{"380":1},"1":{"381":1,"382":1,"383":1},"2":{"540":1}}],["determinam",{"2":{"260":1}}],["determinada",{"2":{"234":1,"263":1}}],["determinado",{"2":{"35":1,"245":1,"424":1,"682":1}}],["determina",{"2":{"120":1,"121":1,"248":1,"442":2}}],["determinar",{"2":{"36":1,"111":1,"248":1,"532":1,"690":1}}],["devo",{"0":{"696":1},"1":{"697":1}}],["dev=true",{"0":{"537":1}}],["devmode",{"2":{"495":1}}],["deva",{"2":{"430":1}}],["devdependencies",{"2":{"409":1}}],["devserver",{"2":{"596":1}}],["devsettingsactivity",{"2":{"272":2,"292":2}}],["devsupport",{"2":{"272":1,"292":1,"313":1}}],["devin",{"2":{"730":2}}],["devidamente",{"2":{"689":1}}],["devido",{"2":{"10":1,"55":1,"56":1,"278":1,"298":1,"389":1,"677":1,"681":1,"707":1}}],["deviceexception",{"2":{"710":1}}],["deviceeventmanagermodule",{"2":{"466":4}}],["devices",{"2":{"529":1,"599":3,"602":1,"608":3,"611":1,"625":1,"627":1,"642":3,"645":1}}],["device",{"2":{"135":1,"141":1,"149":1,"174":1,"209":1,"529":1,"599":3,"602":1,"603":1,"608":16,"611":1,"612":1,"642":2,"645":1,"646":1}}],["devtools",{"0":{"530":1,"745":1},"2":{"131":2,"525":2,"530":2,"531":2,"567":13,"568":3,"570":2}}],["dev",{"2":{"74":2,"77":2,"126":2,"131":1,"133":1,"134":2,"136":1,"153":1,"178":1,"213":1,"216":1,"283":1,"303":1,"348":1,"387":1,"396":1,"409":1,"520":3,"526":3,"533":1,"538":1,"547":1,"551":1,"567":1,"568":1,"602":1,"603":3,"611":1,"612":3,"618":1,"645":1,"646":4,"731":1,"734":1,"739":2}}],["deverão",{"2":{"572":1}}],["deveria",{"2":{"430":3,"444":2}}],["deveriam",{"2":{"250":1}}],["deverá",{"2":{"152":1,"156":1,"177":1,"194":1,"212":1,"252":1,"282":1,"283":1,"302":1,"303":1,"313":1,"325":1,"358":1,"371":1,"398":1,"402":1,"405":1,"426":1,"459":1,"469":1,"483":1,"491":1,"540":1,"551":1,"554":2,"574":1,"624":1,"648":1,"662":1,"663":1,"675":1,"742":1}}],["development",{"2":{"139":1,"200":3}}],["develop",{"2":{"135":2}}],["developer",{"2":{"131":2,"238":1,"415":1,"549":1,"567":1,"598":2,"607":1,"641":1,"722":2}}],["devem",{"2":{"10":3,"27":3,"45":1,"80":1,"92":1,"93":1,"94":1,"101":1,"103":1,"129":1,"134":2,"218":2,"225":1,"227":1,"278":1,"298":1,"329":1,"349":1,"424":2,"443":1,"454":1,"469":1,"497":1,"555":1,"577":2,"587":1,"629":1,"637":1,"673":1,"675":1,"706":1}}],["deve",{"2":{"4":1,"8":1,"11":7,"14":1,"26":1,"28":1,"31":1,"33":1,"34":4,"35":7,"62":1,"65":1,"67":2,"68":1,"69":1,"90":1,"92":1,"99":1,"101":1,"114":2,"115":1,"130":1,"135":1,"191":1,"216":1,"231":1,"249":2,"251":1,"259":1,"261":1,"278":1,"279":1,"298":1,"299":1,"313":2,"328":1,"330":1,"334":1,"339":1,"342":1,"348":1,"349":1,"358":2,"367":1,"383":1,"398":1,"411":1,"413":2,"423":1,"424":3,"427":1,"444":2,"456":2,"459":1,"467":1,"468":1,"480":1,"483":1,"487":2,"488":1,"491":2,"493":1,"516":2,"524":1,"531":1,"549":1,"551":1,"556":1,"559":1,"567":1,"572":1,"578":1,"581":1,"590":1,"599":1,"608":4,"616":1,"621":1,"625":1,"635":1,"636":1,"638":1,"642":1,"650":1,"675":1,"680":1,"685":1,"690":1,"708":1,"731":1,"734":1,"745":1,"747":1,"748":1}}],["desbloqueia",{"2":{"688":1,"690":1,"695":1}}],["desvantagens",{"2":{"682":1}}],["desvantagem",{"2":{"94":1,"103":1,"656":1}}],["desktop",{"2":{"569":1,"745":1}}],["despenca",{"0":{"540":1}}],["despacho",{"2":{"491":1}}],["despachados",{"2":{"535":1}}],["despachado",{"2":{"469":1}}],["desnecessariamente",{"2":{"490":1,"656":1}}],["desnecessário",{"2":{"349":1}}],["desnecessárias",{"2":{"466":2}}],["desnecessária",{"2":{"118":1}}],["desmontado",{"2":{"466":1}}],["desmarcada",{"2":{"11":1,"34":1}}],["desfoque",{"2":{"336":1}}],["deslocamentos",{"2":{"545":1,"685":1,"686":1}}],["deslocamento",{"2":{"234":1,"545":3,"685":1}}],["deslocado",{"2":{"234":1}}],["deslizando",{"2":{"248":1,"541":1}}],["deslizantes",{"2":{"13":1,"16":1,"17":1,"18":1,"77":1}}],["deslizante",{"2":{"11":1,"34":1,"35":1,"691":2}}],["deslizar",{"0":{"246":1},"2":{"246":1,"731":2}}],["desliza",{"2":{"35":2}}],["desligado",{"2":{"11":1,"34":1,"551":1}}],["desinstale",{"2":{"655":1}}],["desinstalar",{"2":{"145":1,"190":1,"205":1}}],["designs",{"2":{"417":1}}],["design",{"2":{"80":1,"348":1,"506":1,"509":1,"688":1}}],["dessa",{"2":{"94":1,"103":1,"134":1,"349":1,"441":1,"545":1,"673":2,"674":1}}],["dessas",{"2":{"42":1,"55":1,"156":1,"279":1,"299":1,"313":1,"358":1,"533":1,"672":1,"718":1}}],["desses",{"2":{"349":1,"386":1,"407":2,"656":1}}],["desse",{"2":{"74":1,"113":1,"231":2,"491":1,"556":1}}],["destination",{"2":{"615":1}}],["destinados",{"2":{"454":1}}],["destino",{"2":{"76":1,"616":2,"617":1,"690":1}}],["destructuring",{"2":{"390":1}}],["dest",{"2":{"283":1,"303":1}}],["destacar",{"2":{"251":1,"464":1,"488":1,"554":1}}],["destacará",{"2":{"110":1}}],["destaque",{"2":{"249":1}}],["desta",{"2":{"159":1,"261":1,"328":1,"344":1,"349":1,"401":1,"413":1,"429":1,"673":1}}],["destas",{"2":{"68":1}}],["destes",{"2":{"516":1}}],["deste",{"2":{"13":4,"279":1,"299":1,"375":1,"465":1,"480":1,"489":1,"490":2,"553":1,"568":1,"619":1}}],["desde",{"2":{"67":1,"221":1,"236":1,"240":1,"251":1,"255":1,"387":1,"648":1,"670":1,"677":1,"687":1,"748":1}}],["descarregadas",{"2":{"545":1}}],["descartando",{"0":{"541":1}}],["descartados",{"2":{"520":1}}],["descartado",{"2":{"130":1,"534":1}}],["descartará",{"2":{"533":1}}],["descartar",{"2":{"31":1,"116":1,"130":2}}],["descomente",{"2":{"581":1}}],["descobrirá",{"2":{"542":1}}],["descobrir",{"2":{"381":2,"386":1,"419":1,"671":1,"720":1}}],["descobrem",{"2":{"42":1}}],["desconectar",{"2":{"608":1}}],["desconhecido",{"2":{"111":1}}],["descontinuados",{"2":{"420":1,"440":1,"446":1,"449":1,"470":1,"474":1}}],["descontinuado",{"2":{"75":1,"554":1}}],["desce",{"2":{"48":1}}],["descendente",{"2":{"90":2,"99":2}}],["descendentes",{"2":{"30":1}}],["descendants",{"2":{"15":1,"30":2}}],["descrições",{"2":{"675":1}}],["descrição",{"2":{"12":1,"13":3,"19":1,"35":1,"107":1,"342":1,"387":1,"675":2}}],["describe",{"2":{"675":2}}],["descritas",{"2":{"679":1}}],["descrita",{"2":{"329":1,"581":1}}],["descrito",{"2":{"283":1,"303":1,"655":1,"675":1,"676":1,"678":1,"681":1,"741":1,"745":1}}],["descritos",{"2":{"94":1,"96":1,"103":1,"105":1,"119":1}}],["descrever",{"2":{"344":1,"384":1}}],["descreve",{"2":{"12":1,"27":1,"226":1,"227":1,"231":2,"579":1,"648":1}}],["desambiguação",{"2":{"635":1}}],["desapareceu",{"2":{"608":1}}],["desaparecendo",{"2":{"541":1}}],["desaparecerá",{"2":{"218":2}}],["desalocadas",{"2":{"499":1}}],["desanexadas",{"2":{"499":2}}],["desatualizada",{"2":{"334":1}}],["desative",{"0":{"666":1},"1":{"667":1},"2":{"487":1,"542":1,"548":1,"751":1}}],["desativarão",{"2":{"547":1}}],["desativar",{"2":{"442":1,"520":2,"529":1,"741":1,"747":1,"748":1,"750":1}}],["desativado",{"2":{"11":1,"273":1,"293":1,"389":1,"551":1}}],["desativadas",{"2":{"7":1,"77":1}}],["desativá",{"2":{"38":1}}],["desacoplar",{"2":{"191":1}}],["desacelerando",{"2":{"47":1}}],["desaceleração",{"2":{"47":1}}],["desabilitada",{"2":{"130":1}}],["desabilitados",{"2":{"663":1}}],["desabilitado",{"2":{"12":1,"22":1,"38":1,"126":1,"127":1,"559":1}}],["desabilitar",{"2":{"48":1,"134":1,"442":2,"667":1}}],["desenhar",{"2":{"553":1,"555":1,"558":1}}],["desenho",{"2":{"499":1,"555":1}}],["desencorajamos",{"2":{"479":1}}],["desenvolvidos",{"2":{"547":1}}],["desenvolvido",{"2":{"381":2,"451":1,"476":1,"679":1}}],["desenvolvidas",{"2":{"320":1,"365":1}}],["desenvolvimento",{"0":{"65":1,"126":1,"139":1,"140":1,"156":1,"166":1,"201":1,"278":1,"298":1,"385":1,"537":1,"601":1,"610":1,"618":1,"644":1},"1":{"141":1,"142":1,"157":1,"158":1,"159":1,"160":1,"161":1,"162":1,"167":1,"168":1,"202":1,"203":1,"602":1,"603":1,"604":1,"611":1,"612":1,"645":1,"646":1,"647":1},"2":{"63":1,"65":1,"127":1,"140":3,"147":1,"148":1,"151":2,"156":2,"157":1,"159":1,"172":1,"173":1,"176":2,"193":2,"201":3,"207":1,"208":1,"211":2,"239":1,"240":1,"266":1,"272":2,"278":3,"279":1,"281":1,"282":1,"288":1,"292":2,"298":3,"299":1,"301":1,"302":1,"307":1,"310":1,"324":1,"347":2,"352":1,"355":1,"370":1,"385":1,"386":2,"405":1,"414":1,"417":2,"446":1,"451":1,"476":1,"537":1,"551":2,"598":1,"599":1,"601":2,"602":1,"603":4,"607":1,"608":1,"610":2,"611":1,"612":4,"615":2,"618":1,"619":1,"638":1,"641":1,"642":1,"644":2,"645":1,"646":3,"662":2,"665":1,"674":1,"685":1,"691":1,"722":1,"726":1,"739":1,"745":2,"754":1}}],["desenvolva",{"2":{"265":1,"287":1,"306":1,"351":1}}],["desenvolvendo",{"2":{"284":1,"304":1,"326":1,"372":1,"695":1}}],["desenvolver",{"2":{"42":2,"135":1,"137":1,"159":2,"164":1,"182":1,"199":1,"479":1,"747":1,"748":1}}],["desenvolvedores",{"0":{"131":1,"135":1},"2":{"42":1,"64":2,"116":1,"236":1,"240":1,"258":1,"339":1,"374":1,"375":1,"414":1,"419":1,"472":1,"648":1,"666":1,"675":1,"687":1,"688":1,"692":1}}],["desenvolvedor",{"0":{"240":1,"347":1,"567":1},"1":{"568":1,"569":1,"570":1},"2":{"6":1,"126":1,"134":1,"239":1,"337":1,"442":1,"570":1,"607":1,"616":2,"630":1,"635":1,"641":1,"681":2,"717":1,"760":1}}],["desejável",{"2":{"252":1,"509":1}}],["desejados",{"2":{"576":1}}],["desejada",{"2":{"434":2}}],["desejadas",{"2":{"92":1}}],["desejará",{"2":{"279":1,"299":1,"313":2,"331":1,"349":1,"358":2,"471":1,"520":1,"561":1,"675":1,"730":1}}],["desejar",{"2":{"65":1,"239":1,"244":1,"257":1,"442":1,"491":1,"492":1,"625":1,"748":1}}],["deseja",{"2":{"9":1,"60":1,"65":4,"94":1,"103":1,"111":1,"155":1,"159":2,"180":1,"186":1,"195":1,"198":1,"215":1,"245":1,"251":4,"313":1,"344":1,"358":1,"398":1,"402":1,"430":1,"434":1,"441":1,"448":1,"464":1,"488":2,"507":1,"553":2,"652":1,"677":1,"679":1,"680":1,"721":1,"724":1,"730":1}}],["desempenho",{"0":{"136":1,"532":1,"536":1,"539":1,"552":1},"1":{"533":1,"534":1,"535":1,"536":1,"537":2,"538":2,"539":2,"540":2,"541":2,"542":2,"543":2,"544":2,"545":2,"553":1,"554":1,"555":1},"2":{"46":1,"55":2,"63":1,"64":1,"112":1,"118":1,"136":2,"143":1,"149":1,"165":1,"183":1,"336":1,"386":1,"446":1,"455":1,"480":1,"498":1,"502":1,"507":1,"508":1,"509":2,"525":4,"532":3,"535":1,"537":2,"539":1,"542":1,"551":2,"574":1,"577":1,"693":1,"695":2,"762":1}}],["de",{"0":{"1":1,"35":1,"36":1,"37":2,"41":1,"42":1,"44":1,"52":1,"53":1,"54":1,"64":1,"71":1,"73":1,"74":1,"76":1,"77":1,"79":1,"80":1,"81":1,"85":1,"92":1,"94":1,"95":1,"96":1,"101":1,"103":1,"104":1,"105":1,"107":2,"108":1,"109":1,"125":1,"126":1,"130":1,"136":1,"139":1,"140":1,"144":2,"156":1,"166":1,"169":2,"185":2,"188":2,"201":1,"204":2,"232":2,"242":2,"248":1,"251":1,"259":1,"267":1,"271":1,"273":2,"274":1,"278":2,"283":1,"291":1,"293":2,"294":1,"298":2,"303":1,"308":1,"312":2,"314":1,"319":1,"320":1,"323":3,"328":1,"331":1,"332":1,"334":1,"335":1,"339":1,"342":2,"353":1,"357":2,"359":1,"364":1,"365":1,"369":3,"375":1,"389":1,"390":1,"399":1,"418":1,"420":1,"421":1,"424":2,"428":1,"429":1,"440":1,"441":1,"450":1,"452":1,"460":2,"461":1,"462":1,"467":1,"468":1,"470":1,"472":1,"475":1,"477":1,"484":2,"485":1,"486":1,"492":1,"494":1,"504":1,"513":1,"521":1,"526":1,"528":1,"531":1,"534":1,"535":1,"536":2,"537":1,"541":1,"543":1,"547":1,"550":1,"552":2,"557":1,"558":1,"559":1,"562":1,"566":1,"567":1,"570":1,"571":1,"595":1,"601":1,"610":1,"616":1,"618":1,"619":1,"632":1,"634":1,"637":1,"644":1,"649":1,"653":1,"655":1,"660":1,"661":1,"663":1,"665":1,"678":1,"679":1,"685":1,"686":1,"690":1,"700":1,"701":1,"704":1,"705":1,"708":1,"714":1,"718":1,"723":1,"726":1,"727":1,"735":1,"739":1},"1":{"2":1,"3":1,"4":1,"5":1,"6":1,"7":1,"8":1,"9":1,"10":1,"11":1,"12":1,"13":1,"14":1,"15":1,"16":1,"17":1,"18":1,"19":1,"20":1,"21":1,"22":1,"23":1,"24":1,"25":1,"26":1,"27":1,"28":1,"29":1,"30":1,"31":1,"32":1,"33":1,"34":1,"42":1,"43":2,"44":2,"65":1,"66":1,"67":1,"68":1,"69":1,"70":1,"72":1,"73":1,"74":1,"75":1,"76":1,"77":1,"78":1,"80":1,"81":1,"82":2,"83":2,"84":2,"85":2,"86":2,"87":2,"88":2,"96":1,"97":1,"105":1,"106":1,"108":2,"109":2,"110":3,"111":3,"126":1,"127":1,"128":1,"129":1,"130":1,"131":1,"132":1,"133":1,"134":1,"135":1,"136":1,"141":1,"142":1,"157":1,"158":1,"159":1,"160":1,"161":1,"162":1,"167":1,"168":1,"202":1,"203":1,"233":2,"234":2,"235":2,"249":1,"250":1,"251":1,"252":2,"253":1,"272":1,"275":1,"276":1,"277":1,"278":1,"295":1,"296":1,"297":1,"298":1,"299":1,"315":1,"316":1,"317":1,"336":1,"360":1,"361":1,"362":1,"421":1,"422":2,"423":2,"424":2,"425":2,"426":2,"427":1,"428":1,"429":2,"430":2,"431":2,"432":2,"433":2,"434":2,"441":1,"442":2,"443":1,"444":1,"445":1,"451":1,"452":1,"461":2,"462":2,"463":2,"485":2,"486":2,"487":2,"495":1,"505":1,"506":1,"507":1,"508":1,"509":1,"510":1,"511":1,"537":2,"538":2,"539":2,"540":2,"541":2,"542":2,"543":2,"544":2,"545":2,"553":2,"554":2,"555":2,"559":1,"560":1,"563":1,"568":1,"569":1,"570":1,"572":1,"573":1,"574":1,"575":1,"576":1,"577":1,"578":1,"602":1,"603":1,"604":1,"611":1,"612":1,"620":1,"621":1,"638":1,"645":1,"646":1,"647":1,"650":1,"651":1,"661":1,"662":2,"663":1,"664":1,"666":1,"667":1,"686":1,"691":1,"702":1,"703":1,"704":1,"705":1,"706":1,"707":1,"708":1,"709":1,"710":1,"711":1,"712":2,"713":2,"714":1,"715":2,"716":2,"724":1,"725":1,"726":1,"728":1,"729":1},"2":{"0":3,"2":3,"3":1,"4":2,"5":2,"8":1,"9":1,"10":4,"11":26,"12":4,"13":4,"15":2,"16":1,"17":1,"18":1,"20":1,"21":2,"22":1,"24":2,"25":1,"26":1,"27":5,"30":7,"31":6,"33":3,"34":24,"35":21,"36":1,"37":6,"38":8,"39":3,"41":7,"42":10,"43":15,"44":8,"45":3,"46":12,"47":15,"48":4,"49":1,"50":14,"51":6,"52":7,"53":1,"55":12,"56":5,"57":2,"58":3,"59":1,"60":5,"62":3,"63":6,"64":2,"65":10,"66":4,"67":10,"68":14,"69":4,"70":1,"71":2,"73":3,"74":16,"76":1,"77":28,"79":2,"80":2,"85":3,"86":4,"88":1,"89":5,"90":9,"91":5,"92":4,"93":3,"94":9,"95":8,"96":6,"97":2,"98":5,"99":9,"100":5,"101":3,"102":3,"103":9,"104":8,"105":8,"106":6,"107":4,"108":3,"110":7,"111":23,"112":6,"113":9,"114":3,"115":5,"116":3,"117":1,"118":5,"120":6,"121":3,"122":1,"123":1,"124":2,"126":5,"127":2,"128":6,"129":1,"130":6,"131":2,"133":4,"134":8,"135":2,"136":2,"137":4,"138":1,"139":1,"140":2,"141":6,"142":13,"143":3,"144":4,"145":3,"147":2,"148":1,"149":5,"151":3,"152":2,"153":2,"155":1,"156":6,"157":1,"158":1,"159":1,"164":4,"165":2,"166":3,"167":6,"168":12,"169":4,"170":3,"172":2,"173":1,"174":2,"176":3,"177":2,"178":2,"180":1,"182":4,"183":2,"184":2,"185":4,"187":3,"188":4,"189":3,"191":11,"193":3,"194":2,"196":2,"198":1,"199":4,"200":7,"201":2,"202":6,"203":24,"204":4,"205":3,"207":2,"208":1,"209":2,"211":3,"212":2,"213":2,"215":1,"217":4,"218":15,"219":8,"220":2,"221":3,"222":6,"223":3,"224":4,"225":2,"226":6,"227":10,"228":3,"229":1,"231":13,"232":3,"233":5,"234":6,"235":2,"236":4,"237":1,"238":1,"239":3,"240":4,"241":2,"242":4,"243":4,"244":3,"245":7,"246":2,"247":1,"248":3,"249":3,"250":5,"251":15,"252":5,"253":2,"254":1,"255":2,"257":5,"258":4,"259":10,"260":1,"261":8,"262":6,"265":1,"266":2,"268":1,"270":3,"272":5,"273":9,"276":1,"277":1,"278":8,"279":11,"281":1,"282":1,"283":7,"284":1,"285":1,"287":1,"288":6,"290":3,"292":5,"293":9,"296":1,"297":1,"298":8,"299":10,"301":1,"302":1,"303":7,"304":1,"306":1,"307":2,"309":4,"310":3,"311":1,"312":4,"313":12,"314":1,"316":1,"317":2,"318":2,"320":8,"321":2,"323":3,"324":1,"325":5,"326":1,"328":10,"329":6,"330":3,"331":4,"332":2,"333":5,"334":17,"335":3,"336":5,"337":4,"338":4,"339":8,"340":5,"341":4,"342":10,"343":4,"344":12,"345":3,"346":1,"347":6,"348":6,"349":18,"351":1,"352":2,"354":1,"355":3,"356":1,"357":4,"358":15,"359":1,"361":1,"362":2,"363":2,"365":8,"366":2,"367":3,"369":3,"370":1,"371":5,"372":1,"374":3,"375":2,"376":2,"377":1,"378":2,"379":3,"381":2,"382":2,"383":1,"384":3,"385":5,"386":3,"387":8,"389":6,"390":3,"391":1,"398":7,"399":8,"400":1,"401":2,"402":2,"404":1,"405":2,"407":1,"411":1,"413":3,"414":5,"415":1,"416":1,"417":9,"418":2,"419":3,"420":5,"421":9,"422":3,"423":2,"424":14,"425":2,"426":3,"427":6,"428":4,"429":5,"431":3,"434":2,"435":1,"436":2,"437":4,"438":1,"439":2,"440":5,"441":20,"442":17,"443":12,"444":9,"445":5,"446":8,"447":2,"448":7,"450":3,"451":3,"452":7,"453":1,"454":10,"455":4,"456":17,"457":5,"458":1,"459":7,"461":9,"462":5,"463":2,"464":36,"465":19,"466":6,"467":4,"469":3,"470":5,"471":6,"472":3,"473":1,"475":3,"476":2,"477":7,"479":13,"480":6,"481":5,"482":1,"483":6,"485":10,"486":6,"487":7,"488":30,"489":5,"490":7,"491":15,"492":1,"493":13,"497":8,"498":1,"499":6,"500":7,"501":4,"502":5,"503":7,"505":3,"506":2,"507":2,"508":2,"509":5,"510":2,"511":4,"515":3,"516":5,"517":3,"518":2,"519":2,"520":9,"521":3,"522":1,"523":2,"524":6,"525":5,"526":3,"527":2,"528":3,"529":4,"531":24,"532":6,"533":7,"534":13,"535":2,"537":6,"538":5,"539":6,"540":10,"541":4,"542":3,"543":4,"544":1,"545":6,"546":3,"548":5,"549":8,"550":3,"551":9,"552":15,"553":4,"554":8,"555":9,"556":5,"557":1,"558":1,"559":6,"560":6,"561":3,"562":5,"563":1,"564":2,"565":2,"566":1,"567":2,"569":5,"570":2,"571":4,"572":2,"573":2,"574":6,"575":3,"576":3,"577":4,"578":2,"579":1,"581":2,"583":1,"584":1,"585":4,"586":2,"587":1,"588":1,"589":4,"591":2,"592":2,"594":1,"595":10,"596":4,"599":1,"600":1,"601":3,"602":2,"603":7,"604":1,"605":1,"608":3,"609":1,"610":3,"611":2,"612":7,"613":1,"615":1,"616":4,"617":2,"618":1,"619":4,"620":1,"621":3,"622":2,"624":1,"625":1,"628":11,"629":17,"630":5,"631":1,"632":1,"633":2,"634":6,"635":19,"636":23,"637":2,"638":5,"639":4,"642":1,"643":1,"644":3,"645":2,"646":8,"647":1,"648":6,"649":1,"650":1,"651":3,"652":2,"653":4,"654":7,"655":2,"656":4,"657":2,"658":10,"659":1,"660":13,"662":8,"663":5,"664":3,"665":6,"666":5,"667":1,"668":5,"669":1,"670":5,"671":5,"672":6,"673":18,"674":4,"675":6,"676":2,"677":8,"678":12,"679":16,"680":15,"681":21,"682":8,"683":2,"685":12,"686":8,"687":5,"688":4,"689":8,"690":13,"691":13,"692":4,"693":16,"694":1,"695":9,"696":4,"697":2,"698":1,"699":8,"700":10,"703":2,"704":2,"706":3,"707":1,"708":4,"709":1,"715":1,"717":2,"718":3,"719":2,"720":3,"721":4,"722":2,"723":2,"724":1,"725":1,"726":3,"728":2,"729":1,"730":15,"731":9,"732":1,"734":6,"735":1,"736":2,"737":2,"739":7,"740":3,"742":2,"744":2,"745":8,"746":6,"747":1,"748":1,"749":1,"750":1,"751":1,"753":3,"754":1,"755":2,"756":1,"757":1,"760":2,"762":3,"764":1,"765":2,"768":1}}],["pós",{"2":{"707":1}}],["pbxproj",{"2":{"704":1}}],["pássaros",{"2":{"673":1}}],["pára",{"2":{"673":1}}],["páginas",{"2":{"246":1}}],["página",{"2":{"64":1,"152":1,"156":1,"177":1,"194":1,"200":1,"212":1,"319":1,"364":1,"528":1,"580":1,"635":1,"648":1,"656":1,"664":1,"680":1,"721":1,"726":2,"741":2}}],["pwd",{"2":{"663":1}}],["pkcs12",{"2":{"650":1}}],["pkce",{"2":{"636":5}}],["py",{"2":{"553":1}}],["px",{"2":{"434":2}}],["público",{"2":{"424":1}}],["physical",{"2":{"599":1,"642":1}}],["phone",{"2":{"598":1,"607":1,"641":1}}],["photo",{"2":{"53":1}}],["phasedregistrationnames",{"2":{"427":2}}],["phases",{"2":{"412":1}}],["p",{"2":{"347":1,"348":1,"387":2,"660":2,"685":4,"715":1}}],["pdf",{"2":{"329":1}}],["pé",{"2":{"258":1}}],["pcs",{"2":{"608":3}}],["pc",{"2":{"190":1}}],["pch",{"2":{"68":1}}],["png",{"2":{"92":8,"101":4,"328":12,"330":1,"331":2,"332":1,"333":1,"334":1,"337":3,"338":1,"348":1,"387":1,"731":1}}],["puder",{"2":{"638":1}}],["publicá",{"2":{"595":1}}],["publica",{"2":{"697":1}}],["publicar",{"2":{"549":2}}],["publicação",{"0":{"546":1,"648":1,"656":1},"1":{"547":1,"548":1,"549":1,"550":1,"649":1,"650":1,"651":1,"652":1,"653":1,"654":1,"655":1,"656":1,"657":1,"658":1,"659":1},"2":{"546":1,"622":1,"767":1,"768":1}}],["public",{"2":{"256":1,"259":3,"279":3,"402":3,"404":1,"422":3,"423":1,"424":3,"425":1,"427":2,"429":2,"430":6,"431":13,"432":2,"452":1,"453":1,"454":2,"456":3,"463":1,"464":4,"465":1,"466":2,"467":4,"468":3}}],["push",{"2":{"254":1,"722":1}}],["pular",{"2":{"237":1,"337":1,"652":1}}],["purge",{"2":{"720":1}}],["purecomponent",{"2":{"507":1,"540":1}}],["puros",{"2":{"540":1,"679":1}}],["puro",{"2":{"407":1}}],["pura",{"2":{"95":1,"104":1}}],["purple",{"2":{"88":1,"229":1,"230":1}}],["putextra",{"2":{"259":3}}],["putextras",{"2":{"256":2}}],["putstring",{"2":{"256":2,"404":2,"427":2,"466":2}}],["putstringarraylist",{"2":{"92":3}}],["put",{"2":{"38":2,"427":1,"463":1}}],["plz",{"2":{"731":1}}],["please",{"2":{"349":3}}],["plist",{"2":{"323":1,"369":1}}],["plugdev",{"2":{"608":1}}],["plug",{"0":{"579":1},"1":{"580":1,"581":1,"582":1,"583":1,"584":1,"585":1,"586":1,"587":1,"588":1,"589":1,"590":1,"591":1,"592":1,"593":1,"594":1,"595":1,"596":1},"2":{"585":1,"734":1,"767":1}}],["plugins",{"2":{"538":1,"739":1}}],["plugin",{"0":{"580":1,"581":1,"596":1},"1":{"582":1,"583":1,"584":1,"585":1,"586":1,"587":1,"588":1,"589":1,"590":1,"591":1,"592":1,"593":1,"594":1},"2":{"270":8,"283":2,"290":8,"303":2,"538":3,"579":1,"580":3,"581":3,"586":1,"593":1,"595":3,"596":3,"707":1,"739":3}}],["plus",{"2":{"328":1}}],["plum",{"2":{"88":1}}],["planeja",{"2":{"542":1,"696":1}}],["plano",{"2":{"254":1,"255":1,"258":1,"259":4,"466":4,"487":1,"490":2}}],["placeholder=",{"2":{"242":1,"680":1}}],["player",{"2":{"344":1}}],["playground",{"2":{"235":1,"737":1}}],["playpause",{"2":{"74":1,"77":1}}],["play",{"0":{"648":1,"658":1},"1":{"649":1,"650":1,"651":1,"652":1,"653":1,"654":1,"655":1,"656":1,"657":1,"658":1,"659":1},"2":{"38":2,"244":1,"598":1,"604":1,"607":1,"613":1,"641":1,"647":1,"648":5,"654":5,"655":1,"658":3,"767":1}}],["platform=ios",{"2":{"320":1,"365":1}}],["platforms",{"2":{"142":1,"186":2,"203":1,"516":2,"667":1}}],["platformcolor",{"2":{"80":1}}],["platform",{"2":{"37":2,"73":4,"76":5,"141":1,"142":2,"168":1,"203":1,"245":3,"271":2,"283":1,"291":2,"303":1,"516":1,"553":1,"561":2,"562":8,"563":3,"564":2}}],["plataformas",{"0":{"382":1,"417":1,"512":1},"1":{"513":1,"514":1,"515":1,"516":1},"2":{"168":1,"244":1,"334":1,"381":1,"471":1,"512":1,"516":1,"562":3,"631":1,"754":1}}],["plataforma",{"0":{"256":1,"515":1,"561":1,"562":1,"565":1},"1":{"562":1,"563":2,"564":1,"565":1,"566":1},"2":{"0":1,"79":1,"80":2,"123":1,"167":1,"168":1,"202":1,"203":3,"244":1,"285":1,"330":1,"382":1,"384":2,"386":1,"415":1,"420":2,"440":2,"444":1,"446":1,"470":1,"513":1,"515":2,"516":3,"552":1,"561":3,"562":5,"563":1,"565":3,"679":1,"753":1}}],["pior",{"2":{"746":1}}],["pipe",{"2":{"686":1}}],["pilloxa",{"2":{"652":1}}],["pilha",{"0":{"685":1},"1":{"686":1},"2":{"130":1,"417":1,"465":1,"471":1,"531":5,"664":1,"685":1,"755":1}}],["pixy",{"2":{"636":1}}],["pixelratio",{"2":{"434":3}}],["pixels",{"2":{"110":1,"233":2,"261":1,"497":1}}],["pistas",{"2":{"557":1}}],["piscando",{"2":{"548":1}}],["piscar",{"2":{"31":1}}],["pid>",{"2":{"703":1}}],["pid",{"2":{"531":1,"685":1}}],["pick",{"2":{"467":4}}],["pickerpromise",{"2":{"467":6}}],["picker",{"2":{"467":20}}],["pickimage",{"2":{"467":3}}],["pinturas",{"2":{"690":1}}],["pintar",{"2":{"689":1}}],["pinnig",{"2":{"638":1}}],["pinning",{"0":{"638":1},"2":{"638":1}}],["pinça",{"2":{"441":1,"442":1}}],["pinçar",{"2":{"427":1,"442":1,"443":1,"731":1}}],["pink",{"2":{"88":1}}],["pizzatranslator",{"2":{"242":2}}],["pizza",{"2":{"8":1}}],["pega",{"2":{"730":1}}],["pegamos",{"2":{"690":1}}],["pegue",{"2":{"576":1}}],["peças",{"2":{"673":2}}],["pedaços",{"2":{"632":1}}],["pedaço",{"2":{"500":1,"517":1}}],["pense",{"2":{"675":1}}],["pensa",{"2":{"560":1,"682":1}}],["pensado",{"2":{"231":1}}],["pensar",{"2":{"50":1,"114":1,"344":1,"345":1,"347":1,"349":2,"509":1,"635":1,"722":1}}],["penúltimo",{"2":{"464":1}}],["penalidades",{"2":{"455":1,"480":1}}],["peer",{"2":{"268":1,"288":1,"309":1,"354":1}}],["pequeno",{"2":{"276":1,"296":1,"316":1,"361":1,"385":1,"502":1,"525":1,"561":1,"731":1}}],["pequenos",{"2":{"42":1,"451":1,"632":1,"670":1,"673":1,"681":1}}],["pequenas",{"2":{"333":1,"562":1,"686":1}}],["pequena",{"2":{"94":1,"103":1}}],["peachpuff",{"2":{"88":1}}],["pelos",{"2":{"219":1,"231":2,"283":1,"303":1,"462":1,"486":1,"629":1}}],["pelo",{"0":{"382":1},"2":{"51":1,"68":1,"77":1,"90":1,"99":1,"110":1,"119":1,"189":1,"191":1,"218":1,"228":1,"245":1,"251":1,"279":1,"299":1,"320":2,"333":1,"336":1,"340":1,"365":2,"390":1,"422":1,"424":1,"429":2,"430":1,"431":1,"432":1,"442":1,"452":4,"456":2,"471":1,"478":1,"491":1,"524":1,"531":1,"534":1,"545":1,"566":1,"608":1,"625":1,"629":1,"636":1,"638":1,"679":2,"681":1,"686":1,"695":1,"696":1,"708":1,"715":2,"728":1,"734":2,"736":1,"740":1,"746":1,"747":1}}],["pelas",{"2":{"47":1,"77":1,"242":1,"386":1,"442":1,"605":1}}],["pela",{"2":{"11":1,"34":1,"56":1,"68":1,"77":2,"117":1,"236":1,"279":1,"299":1,"379":2,"386":2,"404":1,"420":1,"421":1,"430":1,"440":1,"441":2,"442":2,"446":1,"449":1,"470":1,"474":1,"520":1,"533":1,"573":1,"575":1,"630":1,"635":1,"648":1,"652":1,"675":2,"677":1,"693":1,"700":1,"726":1,"733":1}}],["pesadas",{"2":{"506":1}}],["pesados",{"2":{"506":1}}],["pesado",{"2":{"469":1}}],["pesquise",{"2":{"621":1}}],["pesquisável",{"2":{"379":1}}],["pesquisando",{"2":{"695":1}}],["pesquisará",{"2":{"516":1}}],["pesquisar",{"2":{"459":1,"516":1,"701":1,"708":1}}],["pesquisa",{"2":{"11":1,"34":1,"358":1,"516":1}}],["pessoa",{"2":{"629":1}}],["pessoais",{"2":{"349":1,"634":1}}],["pessoas",{"2":{"3":1,"9":1,"39":1,"236":2,"240":1,"249":1,"419":1,"479":1,"535":1,"671":2}}],["pertencem",{"2":{"675":1}}],["pertença",{"2":{"632":1}}],["perto",{"2":{"55":1,"344":1}}],["perguntas",{"2":{"557":1}}],["perguntar",{"2":{"251":2}}],["pergunte",{"2":{"509":1}}],["pergaminho",{"2":{"500":1}}],["perder",{"2":{"545":1}}],["perdas",{"2":{"670":1}}],["perda",{"2":{"499":1}}],["perdida",{"2":{"101":1}}],["perdidos",{"2":{"544":1}}],["perdido",{"2":{"56":1,"651":1}}],["periódica",{"2":{"256":1}}],["períodos",{"2":{"500":1}}],["período",{"2":{"245":1,"534":1,"553":1,"556":1}}],["perpendicular",{"2":{"224":1}}],["perfis",{"2":{"762":1}}],["perfilados",{"2":{"552":1}}],["perfil",{"0":{"525":1,"526":1,"530":1,"531":1,"551":1,"552":1},"1":{"526":1,"527":1,"528":1,"529":1,"530":1,"531":1,"552":1,"553":2,"554":2,"555":2,"556":1,"557":1,"558":1,"559":1,"560":1},"2":{"525":5,"526":2,"527":2,"529":3,"530":2,"531":3,"551":4,"552":2,"553":1,"554":1,"555":1,"571":1,"666":1,"762":1}}],["perfeita",{"2":{"420":1,"440":1}}],["perfeito",{"2":{"417":1}}],["performance",{"0":{"762":1},"2":{"202":1,"530":1}}],["perf",{"2":{"136":1,"533":1,"551":1}}],["peru",{"2":{"88":1}}],["persistindo",{"2":{"634":1}}],["persist",{"2":{"634":1}}],["persistência",{"2":{"630":1}}],["persistente",{"2":{"629":2,"630":2,"633":1}}],["persistentes",{"2":{"629":3}}],["personal",{"2":{"619":1}}],["personalizá",{"2":{"582":1,"583":1,"584":1,"585":1,"586":1,"593":1,"594":1}}],["personalização",{"2":{"367":1}}],["personalizar",{"2":{"60":1,"347":1,"348":1,"398":1,"399":1,"519":1,"581":2,"668":1}}],["personalizado",{"0":{"452":1},"2":{"44":1,"74":1,"77":1,"95":1,"102":1,"104":1,"115":2,"134":4,"146":1,"171":1,"190":1,"206":1,"339":1,"431":1,"434":1,"442":1,"444":1,"477":2,"524":1,"587":1,"588":1,"589":1,"590":1,"591":1,"592":1,"681":1}}],["personalizados",{"0":{"346":1,"477":1,"739":1},"1":{"347":1},"2":{"41":1,"417":1,"426":1,"445":2,"569":2,"595":1,"739":2}}],["personalizadas",{"2":{"35":2,"47":1,"398":1,"595":4}}],["personalizada",{"0":{"429":1},"2":{"3":1,"5":1,"31":1,"32":1,"33":1,"37":1,"73":1,"92":1,"348":1,"428":1,"434":1,"441":1,"524":1,"581":1,"667":1,"708":1}}],["perspective",{"2":{"58":1}}],["perspectiva",{"2":{"58":1,"96":1,"105":1,"680":1,"682":1}}],["permission",{"2":{"272":2,"278":5,"292":2,"298":6,"660":1}}],["permissão",{"2":{"272":1,"278":3,"292":1,"298":2,"651":1,"659":2}}],["permissões",{"0":{"272":1,"278":1,"292":1,"298":1,"659":1},"2":{"278":1,"298":1}}],["permitam",{"2":{"90":1,"99":1}}],["permita",{"2":{"68":1,"739":1}}],["permitido",{"2":{"230":1}}],["permitirá",{"2":{"404":1,"450":1,"456":1,"475":1,"560":1,"635":1}}],["permitiria",{"2":{"94":1,"103":1}}],["permitir",{"2":{"52":1,"80":1,"243":1,"248":1,"421":1,"545":1,"596":1,"599":1,"687":1,"731":2}}],["permitirem",{"2":{"39":1}}],["permitindo",{"2":{"50":1,"56":1,"231":1,"245":1,"390":1,"444":1,"446":1,"560":1,"690":1}}],["permite",{"2":{"11":1,"34":1,"36":1,"51":1,"60":1,"63":1,"74":1,"80":2,"94":1,"95":1,"101":1,"103":1,"104":1,"111":1,"113":1,"147":1,"172":1,"191":1,"207":1,"216":1,"239":1,"242":1,"250":1,"251":1,"257":1,"279":1,"299":1,"338":2,"345":1,"346":1,"349":2,"382":1,"386":1,"387":1,"400":1,"444":1,"472":1,"519":1,"524":1,"568":1,"569":1,"629":1,"632":1,"634":1,"660":1,"681":1,"690":1,"693":2,"700":1}}],["permitem",{"2":{"0":1,"35":1,"41":1,"45":1,"96":1,"105":1,"111":1,"246":1,"249":1,"273":1,"293":1,"344":1,"348":1,"349":1,"406":1,"660":1,"682":1,"691":1}}],["permanece",{"2":{"50":1}}],["percorra",{"2":{"246":1}}],["percorre",{"2":{"57":1}}],["percorrerá",{"2":{"33":1}}],["percorrer",{"2":{"31":1,"730":1}}],["percentuais",{"0":{"263":1},"2":{"263":2}}],["percentagedimensionsbasics",{"2":{"263":2}}],["percentage",{"2":{"233":1}}],["perceber",{"2":{"55":1}}],["perceptível",{"2":{"22":1}}],["prático",{"2":{"418":1}}],["práticas",{"0":{"249":1},"2":{"628":1}}],["prática",{"2":{"3":1,"51":1,"221":1,"341":1}}],["prévia",{"2":{"628":1}}],["pré",{"0":{"238":1,"266":1,"288":1,"307":1,"352":1,"575":1},"1":{"267":1,"268":1,"308":1,"309":1,"310":1,"353":1,"354":1,"355":1},"2":{"320":2,"365":2,"417":1,"435":1,"448":1,"575":1,"577":2,"631":1,"638":1,"675":1,"742":1}}],["praticamente",{"2":{"635":1,"659":1}}],["prazo",{"2":{"219":1,"534":1}}],["pragma",{"2":{"111":1,"332":1,"443":1}}],["pr",{"2":{"78":1}}],["prós",{"2":{"499":1,"500":1,"501":1,"502":1,"503":1}}],["próspero",{"2":{"386":1}}],["próximo",{"2":{"60":1,"149":1,"174":1,"209":1,"336":2,"349":1,"379":1,"500":1,"556":1,"561":1,"663":1,"668":1,"676":1,"679":1}}],["próximas",{"2":{"140":1,"201":1,"556":1,"751":1}}],["próxima",{"2":{"43":1,"62":1,"141":1,"149":1,"167":1,"174":1,"202":1,"203":1,"209":1,"218":1,"224":4,"262":1,"328":1,"384":1,"387":2,"409":1,"515":1,"696":1,"745":1}}],["próprias",{"2":{"441":1,"492":1}}],["própria",{"0":{"515":1},"2":{"47":1,"236":1,"491":4,"677":1}}],["próprios",{"0":{"419":1},"2":{"386":1,"419":1,"673":1}}],["próprio",{"2":{"46":1,"90":1,"92":1,"99":1,"101":1,"115":1,"119":1,"152":1,"191":2,"194":1,"212":1,"245":1,"257":1,"258":1,"279":1,"299":1,"339":1,"343":1,"389":1,"419":2,"420":1,"440":1,"630":1}}],["privada",{"2":{"649":1}}],["privado",{"2":{"493":1,"651":1}}],["private",{"2":{"259":2,"268":1,"279":2,"288":1,"299":2,"309":1,"354":1,"402":2,"422":1,"430":1,"431":8,"466":4,"467":9}}],["priority",{"2":{"491":1}}],["prioridade",{"2":{"46":1,"691":3}}],["princípio",{"2":{"635":1}}],["princípios",{"2":{"532":1}}],["principais",{"0":{"384":1},"1":{"385":1,"386":1,"387":1},"2":{"313":1,"341":1,"343":1,"346":1,"348":2,"349":2,"358":1,"374":2,"379":1,"386":1,"387":3,"419":1,"545":1,"668":1,"682":1,"687":1,"693":1,"724":2}}],["principalmente",{"2":{"243":1,"387":1,"499":1,"673":1}}],["principal",{"0":{"535":1},"2":{"41":1,"57":1,"92":2,"94":2,"101":1,"103":2,"111":1,"223":1,"224":2,"226":9,"227":1,"230":2,"231":4,"242":1,"279":1,"299":1,"311":1,"319":1,"320":2,"321":1,"341":1,"344":1,"349":1,"356":1,"364":1,"365":2,"366":1,"402":3,"412":1,"420":1,"440":1,"477":1,"487":1,"491":1,"493":1,"499":1,"534":1,"535":2,"539":1,"541":1,"545":3,"551":1,"560":1,"564":1,"568":1,"571":1,"616":2,"660":1}}],["printed",{"2":{"268":2,"288":2,"309":2,"354":2}}],["primitivos",{"2":{"424":2}}],["primary",{"2":{"67":1}}],["primeiros",{"2":{"187":1,"472":1,"473":1,"608":1}}],["primeiro",{"0":{"344":1},"2":{"50":1,"52":1,"67":3,"154":1,"156":1,"179":1,"197":1,"214":1,"224":4,"226":2,"252":1,"255":1,"258":1,"259":5,"270":1,"271":1,"275":1,"276":1,"279":1,"281":1,"290":1,"291":1,"295":1,"296":1,"299":1,"301":1,"315":1,"316":1,"320":1,"324":1,"344":2,"349":1,"360":1,"361":1,"365":1,"370":1,"379":1,"384":1,"403":1,"404":1,"424":1,"429":1,"447":1,"456":1,"457":1,"464":4,"467":1,"481":1,"488":2,"490":1,"520":1,"538":1,"551":1,"552":1,"553":1,"559":1,"560":1,"598":1,"603":1,"607":1,"608":1,"612":1,"641":1,"646":1,"655":1,"672":1,"673":1,"674":1,"675":2,"681":1,"699":1,"724":1,"725":1,"746":2}}],["primeira",{"2":{"11":1,"34":1,"53":1,"67":1,"229":1,"236":1,"336":1,"442":1,"452":1,"464":1,"477":1,"488":1,"573":1,"576":2,"615":1,"636":1}}],["proibições",{"2":{"672":1}}],["proibido",{"2":{"589":1}}],["proguard",{"0":{"657":1},"2":{"657":6,"747":2}}],["program",{"2":{"650":1}}],["programado",{"2":{"700":1}}],["programadas",{"2":{"689":1}}],["programa",{"2":{"673":1}}],["programar",{"2":{"236":1}}],["programação",{"2":{"41":1,"379":1,"420":1,"440":1,"670":1}}],["programaticamente",{"2":{"35":1}}],["progressivamente",{"2":{"572":1}}],["progresso",{"2":{"11":1,"13":1,"16":1,"17":1,"18":1,"34":1}}],["progressbar",{"2":{"11":1,"34":1}}],["proof",{"2":{"636":1}}],["pronunciado",{"2":{"636":1}}],["prontas",{"2":{"691":1}}],["prontamente",{"2":{"524":1}}],["pronta",{"2":{"279":1,"299":1,"493":1}}],["prontos",{"2":{"374":1,"386":1,"420":1,"440":1}}],["pronto",{"2":{"67":1,"283":1,"303":1,"313":1,"358":1,"413":1,"549":1,"578":1,"581":1,"654":1,"736":1}}],["pro",{"2":{"626":3,"657":1,"747":1}}],["proxy",{"2":{"444":1,"619":2}}],["protege",{"2":{"637":1}}],["proteger",{"2":{"628":3,"681":1}}],["protected",{"2":{"92":2,"256":1,"278":1,"279":4,"402":1,"404":1,"433":1,"456":1}}],["protocolo",{"2":{"477":2,"492":1,"495":1,"522":1,"636":3,"745":1}}],["prototype",{"2":{"393":2,"394":1}}],["promises",{"0":{"465":1,"489":1},"1":{"466":1}}],["promise",{"2":{"390":1,"462":3,"465":13,"467":14,"486":1,"489":1,"520":1,"699":1}}],["promessas",{"2":{"459":1,"483":1}}],["promessa",{"2":{"255":1,"465":5,"467":1,"489":3}}],["prompt",{"2":{"200":2,"203":1,"268":1,"288":1,"309":1,"354":1,"600":1,"602":1,"609":1,"611":1,"643":1,"645":1,"646":1}}],["prosseguir",{"2":{"149":1,"174":1,"203":1,"209":1,"283":1,"303":1,"413":1}}],["prossiga",{"2":{"141":1,"167":1,"202":1}}],["profissional",{"2":{"566":1}}],["profissionais",{"0":{"548":1}}],["profiler",{"2":{"526":3}}],["profile",{"2":{"142":3,"168":2,"527":1,"529":1,"531":3}}],["profunda",{"2":{"540":1}}],["profundamente",{"2":{"63":1}}],["profundo",{"0":{"415":1},"2":{"252":3}}],["proceda",{"2":{"456":1}}],["processe",{"2":{"693":1}}],["processados",{"2":{"534":1}}],["processamento",{"2":{"446":1,"500":1}}],["processamos",{"2":{"427":1,"443":1}}],["processar",{"2":{"442":1,"443":1,"534":1}}],["process",{"2":{"438":1,"439":1,"667":1,"685":1}}],["processo",{"0":{"555":1,"703":1},"2":{"309":1,"310":1,"355":1,"437":1,"446":1,"515":1,"546":2,"604":1,"613":1,"622":1,"647":1,"648":2,"673":1,"686":1,"702":2,"703":3,"711":1,"721":1,"751":1}}],["processos",{"2":{"134":1}}],["processname",{"2":{"259":2}}],["procurar",{"2":{"379":1,"413":1,"591":1,"708":2}}],["procurará",{"2":{"328":1,"516":2}}],["procura",{"2":{"374":1,"419":1}}],["procurando",{"2":{"236":1,"417":1,"418":1,"471":1,"687":1}}],["procure",{"2":{"142":2,"149":1,"168":2,"174":1,"203":2,"209":1,"555":3,"557":1,"615":1,"616":1}}],["proddebug",{"2":{"586":1}}],["produtivo",{"2":{"674":1}}],["produto",{"2":{"549":2,"557":1,"635":1}}],["produtos",{"2":{"128":1}}],["produzem",{"2":{"662":1}}],["produzir",{"2":{"134":1,"636":1}}],["produzidos",{"2":{"56":1}}],["product",{"2":{"547":1,"615":1,"617":1}}],["production",{"2":{"538":1}}],["products",{"2":{"412":1,"635":2}}],["produção",{"0":{"604":1,"613":1,"622":1,"647":1},"2":{"126":1,"127":1,"218":2,"320":1,"323":1,"365":1,"369":1,"538":1,"547":1,"566":1,"596":1,"605":1,"659":1,"687":1,"696":1,"734":1}}],["prod",{"2":{"113":1}}],["project",{"2":{"68":1,"271":1,"279":1,"291":1,"299":1,"313":4,"358":2,"402":1,"404":1,"574":2,"616":1,"653":1,"666":1,"704":1,"722":3,"729":1}}],["projete",{"2":{"414":1}}],["projetados",{"2":{"218":1}}],["projetado",{"2":{"55":1,"151":1,"176":1,"193":1,"211":1,"222":1}}],["projetadas",{"2":{"80":1,"442":1}}],["projetada",{"2":{"46":1,"56":1,"672":1}}],["projetos",{"0":{"718":1,"719":1},"2":{"76":3,"344":1,"377":1,"378":1,"379":1,"435":2,"447":1,"512":1,"566":1,"580":1,"599":1,"608":1,"642":1,"719":1,"732":1,"733":1}}],["projeto",{"0":{"726":1,"734":1},"2":{"43":1,"64":1,"65":1,"73":1,"96":1,"105":1,"134":1,"145":3,"146":2,"151":1,"152":1,"157":1,"158":1,"159":2,"170":3,"171":2,"176":1,"189":3,"190":2,"191":1,"193":1,"194":1,"200":2,"205":3,"206":2,"211":1,"212":1,"267":2,"268":2,"270":2,"276":1,"281":1,"288":4,"290":2,"296":1,"301":1,"308":2,"309":2,"310":1,"313":1,"316":1,"323":1,"324":1,"328":1,"329":1,"353":2,"354":2,"355":1,"358":1,"361":1,"369":1,"370":1,"371":1,"376":2,"377":1,"398":2,"402":1,"403":1,"404":1,"411":1,"412":1,"413":1,"451":3,"470":2,"476":3,"493":4,"538":3,"549":1,"565":1,"566":1,"567":3,"574":1,"577":1,"580":1,"582":1,"595":1,"600":2,"605":2,"609":2,"615":1,"616":3,"624":2,"643":2,"652":1,"653":1,"654":1,"655":1,"666":1,"671":1,"685":1,"704":1,"706":3,"708":1,"711":1,"718":2,"719":4,"720":1,"721":1,"725":1,"726":3,"728":2,"729":1,"733":1,"734":3,"739":1,"742":1}}],["probably",{"2":{"313":1}}],["probabilidade",{"2":{"43":1,"628":2,"639":1}}],["problems",{"2":{"358":1}}],["problemática",{"2":{"134":1,"570":1}}],["problemáticos",{"2":{"576":1}}],["problemático",{"2":{"64":1}}],["problematicmodule",{"2":{"576":1}}],["problemas",{"0":{"78":1,"247":1,"523":1,"536":1,"557":1,"558":1,"570":1,"619":1,"669":1,"701":1,"727":1},"1":{"537":1,"538":1,"539":1,"540":1,"541":1,"542":1,"543":1,"544":1,"545":1,"559":1,"560":1,"620":1,"621":1,"702":1,"703":1,"704":1,"705":1,"706":1,"707":1,"708":1,"709":1,"710":1,"711":1,"712":1,"713":1,"714":1,"715":1,"716":1,"728":1,"729":1},"2":{"69":1,"74":1,"107":1,"136":1,"139":1,"145":1,"152":1,"166":1,"170":1,"177":1,"189":2,"194":1,"200":1,"205":1,"212":1,"325":1,"371":1,"451":1,"501":1,"532":2,"554":1,"560":1,"574":1,"660":2,"701":1,"711":1,"721":1,"734":1,"741":1,"753":1}}],["problema",{"2":{"57":1,"78":1,"92":1,"93":1,"94":1,"101":2,"102":1,"103":1,"110":1,"111":3,"112":1,"134":1,"325":1,"337":1,"371":1,"442":1,"444":1,"545":1,"556":2,"557":1,"558":1,"617":1,"619":2,"635":1,"675":1,"685":1,"689":1,"701":1,"711":1,"715":1,"716":1,"741":1}}],["propósito",{"2":{"682":1}}],["propósitos",{"2":{"555":1}}],["propensos",{"2":{"680":1,"682":1}}],["properly",{"2":{"431":1}}],["property",{"2":{"102":1,"442":2,"443":4,"660":2}}],["properties",{"2":{"65":1,"200":1,"390":2,"652":6,"654":1,"747":2,"750":1}}],["propheight",{"2":{"431":8}}],["propwidth",{"2":{"431":8}}],["proptypes",{"2":{"427":2,"442":12,"443":2,"537":1}}],["proporcional",{"2":{"628":1,"639":1}}],["proporção",{"2":{"262":1,"337":1}}],["propostas",{"2":{"695":1}}],["proposta",{"2":{"390":1}}],["proprietário",{"2":{"111":2}}],["propriedade",{"2":{"2":2,"3":1,"5":1,"8":1,"9":1,"10":2,"15":1,"30":1,"31":1,"32":1,"33":1,"34":1,"35":2,"46":1,"50":1,"56":1,"65":2,"92":1,"101":1,"110":1,"111":1,"116":2,"117":2,"120":2,"223":1,"226":1,"228":1,"230":1,"233":2,"242":2,"334":1,"348":1,"349":2,"402":1,"424":7,"427":1,"442":4,"443":1,"487":1,"501":1,"509":1,"531":1,"542":1,"543":1,"668":1,"731":1,"747":2,"750":1}}],["propriedades",{"0":{"1":1,"91":1,"92":1,"93":1,"94":1,"100":1,"101":1,"102":1,"103":1,"424":1,"442":1},"1":{"2":1,"3":1,"4":1,"5":1,"6":1,"7":1,"8":1,"9":1,"10":1,"11":1,"12":1,"13":1,"14":1,"15":1,"16":1,"17":1,"18":1,"19":1,"20":1,"21":1,"22":1,"23":1,"24":1,"25":1,"26":1,"27":1,"28":1,"29":1,"30":1,"31":1,"32":1,"33":1,"34":1,"92":1,"93":1,"94":1,"101":1,"102":1,"103":1},"2":{"57":2,"60":1,"63":1,"77":1,"79":1,"90":2,"91":2,"92":6,"93":2,"94":2,"95":2,"99":2,"100":2,"101":5,"102":2,"103":2,"104":2,"112":1,"113":1,"231":1,"320":1,"332":1,"340":1,"348":1,"365":1,"421":3,"423":1,"424":2,"434":1,"441":2,"442":2,"443":1,"519":1,"531":1,"561":1,"730":1}}],["prop",{"2":{"92":1,"348":1,"442":1,"510":1,"668":1}}],["props>",{"2":{"737":1}}],["propsmultiple",{"2":{"348":1}}],["props",{"0":{"498":1},"1":{"499":1,"500":1,"501":1,"502":1,"503":1},"2":{"46":3,"92":1,"101":3,"110":1,"112":1,"114":4,"115":7,"251":8,"252":2,"320":1,"328":2,"348":6,"349":7,"365":1,"390":1,"404":1,"427":5,"431":1,"442":1,"443":3,"445":1,"507":2,"561":1,"730":1,"731":2,"737":3}}],["propswithchildren",{"2":{"46":2,"224":2,"225":2,"226":2,"227":2,"228":2,"229":2,"230":2,"232":2,"233":2,"234":2}}],["provedor",{"2":{"636":1}}],["provedores",{"2":{"636":1}}],["provenientes",{"2":{"111":1,"349":1,"431":1,"524":1}}],["providesmodulenodemodules",{"2":{"516":2}}],["provavelmente",{"2":{"65":1,"69":1,"96":1,"105":1,"149":1,"166":1,"174":1,"209":1,"243":1,"402":1,"471":1,"545":1,"557":1,"575":1,"675":1}}],["prova",{"2":{"44":1,"338":1}}],["provável",{"2":{"42":1,"43":1,"658":1}}],["predefinição",{"2":{"674":1}}],["predefinido",{"2":{"60":1}}],["predefinidas",{"2":{"47":2}}],["prejudicial",{"2":{"635":1}}],["prejudicando",{"2":{"500":1}}],["preloadedmodules",{"2":{"577":2}}],["pretending",{"2":{"479":1,"488":1}}],["preencha",{"2":{"549":1}}],["preenchimento",{"2":{"225":2,"429":2,"500":1,"737":1}}],["preencher",{"2":{"223":1,"262":2,"263":1}}],["previewcontainer",{"2":{"231":2,"232":2}}],["previewlayoutprops",{"2":{"224":2,"225":2,"226":2,"227":2,"228":2,"229":2,"230":2,"232":2,"233":2,"234":2}}],["previewlayout>",{"2":{"224":1,"225":1,"226":1,"227":1,"228":1,"229":1,"230":1,"232":1,"233":1,"234":1}}],["previewlayout",{"2":{"224":2,"225":2,"226":2,"227":2,"228":2,"229":2,"230":2,"232":2,"233":2,"234":2}}],["previous",{"2":{"5":1}}],["prebuild",{"2":{"159":1}}],["prepare",{"2":{"728":1}}],["prepará",{"2":{"605":1}}],["preparar",{"2":{"147":1,"172":1,"207":1,"259":1}}],["preparando",{"0":{"147":1,"172":1,"207":1},"1":{"148":1,"149":1,"173":1,"174":1,"208":1,"209":1}}],["preprocessed",{"2":{"67":2}}],["preocupamos",{"2":{"553":1,"555":2,"608":1}}],["preocupação",{"2":{"113":1,"635":1}}],["preocupar",{"2":{"60":1,"328":1,"336":1}}],["prefira",{"2":{"680":2,"681":1}}],["prefixo",{"2":{"441":2}}],["prefixos",{"2":{"441":2,"478":1}}],["prefixados",{"2":{"443":1}}],["prefixadas",{"2":{"68":1}}],["prefixamos",{"2":{"441":1}}],["preferida",{"2":{"490":1}}],["preferidos",{"2":{"663":1}}],["preferido",{"2":{"467":1}}],["preferir",{"2":{"38":1,"521":1,"567":1}}],["preferência",{"2":{"153":1,"178":1,"196":1,"213":1,"554":1,"562":1}}],["preferências",{"0":{"633":1},"2":{"80":1,"633":1}}],["preference",{"2":{"241":1}}],["preferences",{"2":{"135":1,"185":1,"186":1,"312":1,"313":1,"357":1,"358":1,"603":1,"633":3,"634":2}}],["preferem",{"2":{"116":1,"375":1}}],["preactnativearchitectures=x86",{"2":{"65":2}}],["precisos",{"2":{"551":1,"699":1}}],["preciso",{"2":{"413":1,"502":1}}],["precisem",{"2":{"461":1,"485":1,"629":1}}],["precise",{"2":{"191":1,"666":1,"721":1,"728":1}}],["precisam",{"2":{"93":1,"344":1,"424":1,"452":2,"453":1,"504":1,"517":1,"678":1,"720":1}}],["precisamos",{"2":{"90":1,"91":1,"94":1,"95":1,"99":1,"100":1,"103":1,"104":1,"107":1,"110":2,"259":2,"268":1,"278":1,"279":4,"288":1,"298":1,"299":4,"309":1,"320":1,"323":1,"354":1,"365":1,"369":1,"376":1,"441":1,"442":1,"577":1}}],["precisarão",{"2":{"638":1}}],["precisaremos",{"2":{"413":1}}],["precisaria",{"2":{"114":1,"706":1}}],["precisariam",{"2":{"94":1,"103":1}}],["precisaríamos",{"2":{"106":1}}],["precisará",{"2":{"65":1,"69":2,"96":1,"105":1,"137":2,"142":1,"147":2,"149":1,"156":1,"159":1,"164":2,"172":2,"174":1,"182":2,"185":1,"199":2,"200":1,"207":2,"209":1,"218":1,"238":1,"245":1,"257":1,"313":2,"331":1,"333":1,"348":1,"358":2,"378":1,"387":1,"402":2,"413":1,"428":1,"448":1,"454":1,"458":2,"462":1,"467":1,"482":2,"491":1,"493":2,"520":2,"540":1,"541":1,"575":1,"586":2,"593":1,"595":1,"598":1,"599":1,"603":2,"607":1,"608":1,"612":2,"626":1,"641":1,"646":2,"676":1,"678":2,"704":1,"726":1,"728":2,"730":1,"747":1}}],["precisar",{"2":{"55":1,"57":1,"67":1,"96":1,"105":1,"120":3,"135":1,"159":1,"235":1,"245":1,"272":1,"279":1,"292":1,"299":1,"328":1,"404":1,"407":1,"413":1,"426":1,"441":1,"445":1,"464":2,"491":1,"517":1,"520":1,"581":1,"629":1,"654":1,"675":1,"695":1,"734":1}}],["precisa",{"0":{"533":1},"2":{"49":1,"55":1,"60":1,"62":1,"68":2,"74":1,"77":1,"112":1,"113":1,"237":1,"238":1,"248":1,"256":1,"257":1,"259":1,"270":1,"278":1,"281":1,"283":1,"290":1,"298":1,"301":1,"303":1,"318":1,"324":1,"328":1,"336":1,"341":1,"363":1,"370":1,"404":2,"407":1,"413":1,"441":1,"442":1,"444":1,"446":2,"456":2,"457":1,"462":1,"467":1,"468":1,"481":1,"486":1,"487":1,"507":1,"509":1,"534":1,"537":1,"538":1,"540":1,"545":1,"556":1,"566":1,"572":1,"575":1,"580":1,"581":1,"585":1,"595":1,"598":1,"607":1,"618":1,"641":1,"648":2,"653":1,"654":1,"658":1,"667":1,"673":1,"677":1,"681":2,"690":1,"711":1,"724":1,"739":1,"745":1}}],["precedência",{"2":{"34":1,"668":1}}],["presença",{"2":{"523":1}}],["presentes",{"2":{"531":2}}],["presente",{"2":{"523":1}}],["present",{"2":{"365":1}}],["presentviewcontroller",{"2":{"320":1}}],["presentation",{"2":{"34":1}}],["presets",{"2":{"739":1}}],["preset",{"2":{"390":1,"739":1}}],["preserva",{"2":{"220":1}}],["preservam",{"2":{"219":1,"221":1}}],["preservado",{"2":{"219":2}}],["preservar",{"2":{"219":1,"221":1}}],["pressupõe",{"2":{"420":1,"440":1,"461":1,"485":1}}],["pressed",{"2":{"245":1,"320":1,"390":1}}],["pressões",{"2":{"245":1}}],["pressione",{"2":{"38":1,"74":2,"77":1,"153":1,"178":1,"196":1,"213":1,"349":1,"526":2}}],["pressionar",{"2":{"244":1,"245":1,"599":1,"617":1}}],["pressionamento",{"2":{"74":1,"279":1,"299":1}}],["pressionando",{"2":{"74":1,"77":1,"459":1,"526":1}}],["pressiona",{"2":{"35":2,"245":2,"279":2,"299":2,"349":1,"679":1,"680":1}}],["press",{"2":{"3":1,"114":2,"115":2,"244":3,"245":1,"680":2}}],["pay",{"2":{"446":1}}],["packager",{"2":{"337":1,"576":2,"577":1,"662":1}}],["packagelist",{"2":{"279":1,"299":1,"402":4,"433":2,"456":2}}],["packages",{"2":{"279":2,"299":4,"402":4,"433":4,"456":5}}],["packagename",{"2":{"259":4}}],["package",{"0":{"433":1},"2":{"142":2,"168":1,"203":2,"268":2,"278":1,"283":2,"288":2,"298":1,"303":2,"309":2,"354":2,"390":3,"409":1,"429":2,"430":3,"431":3,"432":3,"452":4,"516":1,"553":3,"567":1,"582":1,"596":1,"718":1,"725":1,"726":1}}],["pacotes",{"0":{"375":1,"571":1,"714":1},"1":{"572":1,"573":1,"574":1,"575":1,"576":1,"577":1,"578":1,"715":1,"716":1},"2":{"200":1,"268":1,"279":2,"288":1,"299":1,"309":2,"310":1,"328":1,"354":1,"355":1,"375":1,"381":1,"384":1,"398":1,"402":2,"456":5,"470":2,"508":1,"548":1,"572":1,"574":2,"583":1,"584":1,"585":1,"588":1,"718":1,"734":1,"762":1}}],["pacote",{"0":{"470":1,"741":1},"2":{"65":1,"145":1,"168":1,"170":1,"189":1,"205":1,"259":1,"279":3,"280":1,"283":1,"288":1,"299":3,"300":1,"303":1,"322":1,"337":1,"368":1,"375":1,"404":2,"421":1,"425":1,"429":2,"430":1,"431":1,"432":1,"447":3,"452":2,"454":1,"456":3,"482":1,"516":1,"548":1,"549":1,"552":1,"555":3,"566":2,"567":2,"571":2,"572":3,"575":1,"577":2,"580":1,"583":1,"584":1,"586":1,"588":1,"590":1,"591":1,"595":1,"629":1,"648":1,"654":1,"662":1,"685":1,"704":1,"739":1,"742":1,"764":1}}],["paths`",{"2":{"708":1}}],["pathseheader",{"2":{"708":1}}],["paths",{"2":{"358":1,"413":1,"708":2,"722":2,"739":1}}],["path`",{"2":{"313":1}}],["path=$path",{"2":{"142":2,"168":2}}],["path",{"2":{"134":3,"203":2,"313":25,"522":1,"553":1,"577":3,"651":1,"706":1,"728":1,"748":1,"751":1}}],["pausa",{"2":{"745":1}}],["pausando",{"2":{"490":1}}],["pausado",{"2":{"255":1}}],["pausar",{"2":{"77":1}}],["pause",{"2":{"131":1}}],["pagamentos",{"2":{"682":1}}],["paginação",{"2":{"731":1}}],["paginar",{"2":{"128":1}}],["pagingenabled",{"2":{"53":1,"731":1}}],["pagey",{"2":{"120":2,"251":1}}],["pagex",{"2":{"120":2,"251":1}}],["papayawhip",{"2":{"88":1}}],["palavra",{"2":{"242":1,"465":1,"489":1}}],["palavras",{"0":{"88":1},"2":{"110":1,"242":1,"390":1}}],["palevioletred",{"2":{"88":1}}],["paleturquoise",{"2":{"88":1}}],["palegreen",{"2":{"88":1}}],["palegoldenrod",{"2":{"88":1}}],["palestra",{"2":{"42":1}}],["paddingbottom",{"2":{"730":1}}],["paddingright",{"2":{"730":1}}],["paddingleft",{"2":{"730":1}}],["paddingtop",{"2":{"245":1,"730":3}}],["padding",{"2":{"122":4,"223":1,"224":1,"225":1,"226":1,"227":1,"228":1,"229":1,"230":1,"231":1,"232":1,"233":3,"234":1,"242":2,"245":1,"520":1,"730":2}}],["paddingvertical",{"2":{"53":1,"60":1,"224":1,"225":1,"226":1,"227":1,"228":1,"229":1,"230":1,"231":1,"232":1,"234":1}}],["paddinghorizontal",{"2":{"53":1,"60":1,"224":1,"225":1,"226":1,"227":1,"228":1,"229":1,"230":1,"231":1,"234":1}}],["padroniza",{"2":{"735":1}}],["padronizando",{"2":{"222":3}}],["padronizadas",{"2":{"56":1}}],["padronizado",{"2":{"3":1}}],["padrões",{"2":{"46":1,"222":1,"329":1,"398":3,"399":1,"417":1,"471":1,"516":1,"581":1,"708":2}}],["padrão",{"0":{"659":1},"2":{"2":1,"20":1,"21":1,"22":1,"23":1,"24":1,"27":1,"28":1,"30":1,"35":5,"38":1,"47":1,"50":2,"65":1,"67":2,"68":2,"105":1,"111":1,"119":1,"135":1,"142":1,"158":1,"168":1,"191":1,"195":1,"203":3,"216":1,"220":1,"224":1,"225":2,"226":1,"227":1,"229":2,"230":1,"231":5,"233":1,"234":2,"245":1,"252":1,"257":1,"258":1,"273":1,"279":2,"293":1,"299":2,"313":1,"334":1,"336":1,"342":1,"349":1,"358":1,"391":1,"398":1,"399":4,"402":1,"423":1,"424":2,"429":2,"437":1,"442":2,"445":3,"446":1,"465":1,"487":1,"488":1,"499":1,"500":1,"501":1,"502":1,"503":2,"520":2,"532":1,"552":3,"555":1,"559":1,"562":1,"572":1,"574":1,"581":2,"582":1,"583":1,"584":1,"585":1,"586":1,"587":1,"588":1,"589":1,"590":1,"591":1,"592":1,"593":1,"594":1,"595":1,"598":1,"607":1,"625":1,"633":1,"634":1,"636":1,"641":1,"654":1,"656":2,"659":1,"662":2,"663":1,"666":3,"668":1,"674":1,"685":1,"687":1,"696":1,"708":1,"724":1,"732":1,"733":1,"736":1,"740":1,"742":1,"746":1,"748":1,"751":1}}],["panhandlers",{"2":{"54":1}}],["panresponder",{"0":{"54":1,"253":1},"2":{"53":2,"54":4,"57":1,"253":1}}],["panorâmico",{"2":{"52":1,"55":1}}],["panorâmica",{"2":{"51":1,"427":1,"443":1}}],["pan",{"2":{"51":1,"53":4,"54":6}}],["password",{"2":{"653":2}}],["passwords",{"2":{"652":1}}],["password=",{"2":{"652":2}}],["passo",{"0":{"411":1,"412":1},"2":{"407":1,"552":1,"668":1,"672":1,"718":2}}],["passos",{"2":{"187":1,"472":1,"473":1}}],["passes",{"2":{"553":1}}],["passe",{"2":{"111":1,"404":1}}],["passá",{"2":{"96":1,"105":1}}],["passada",{"2":{"675":1}}],["passadas",{"2":{"257":1,"445":1}}],["passados",{"2":{"90":1,"94":1,"99":1,"103":1,"488":1,"592":1,"594":1}}],["passado",{"2":{"53":1,"424":1,"442":1,"464":2,"478":1,"488":1,"500":1,"503":1,"589":1}}],["passa",{"2":{"115":1,"348":2,"488":1,"682":1}}],["passamos",{"2":{"115":1,"690":1}}],["passar",{"2":{"56":1,"90":1,"91":1,"92":1,"99":1,"100":1,"101":1,"114":1,"248":1,"258":1,"278":1,"279":2,"298":1,"299":2,"348":1,"404":1,"444":1,"455":1,"464":3,"478":1,"479":1,"488":3,"516":1,"519":1,"628":1,"668":1,"671":1,"672":1}}],["passando",{"0":{"92":1,"93":1,"101":1,"102":1},"2":{"47":1,"245":1,"348":1,"672":1,"685":1,"721":1}}],["past",{"2":{"675":1}}],["pastas",{"2":{"654":1,"708":3}}],["pasta",{"2":{"65":1,"67":1,"69":2,"151":1,"152":1,"176":1,"189":1,"193":1,"194":1,"200":1,"203":1,"211":1,"212":1,"267":1,"268":2,"270":1,"283":1,"288":3,"290":1,"303":1,"308":1,"309":2,"328":2,"329":1,"330":2,"353":1,"354":2,"402":2,"403":1,"407":1,"411":1,"412":1,"452":2,"456":1,"470":1,"477":2,"549":1,"567":1,"582":1,"583":1,"584":1,"615":1,"651":1,"652":1,"653":1,"666":1}}],["paste",{"2":{"35":4}}],["parceiros",{"0":{"513":1},"2":{"512":1}}],["parcelados",{"2":{"259":1}}],["parsing",{"2":{"465":2}}],["parsecolor",{"2":{"429":2}}],["parse",{"2":{"278":1,"298":1,"462":2}}],["parseint",{"2":{"231":6,"431":1,"564":1}}],["parentview",{"2":{"431":4}}],["parent",{"2":{"403":2,"404":1,"430":2,"531":1}}],["pares",{"2":{"348":1,"531":1}}],["parecem",{"2":{"700":1}}],["parece",{"2":{"553":1,"557":1,"635":1}}],["pareceriam",{"2":{"534":1}}],["parecerá",{"2":{"518":1,"533":1}}],["parecer",{"2":{"55":1,"85":1,"245":1}}],["parecia",{"2":{"325":1,"371":1}}],["parecidos",{"2":{"555":1}}],["parecido",{"2":{"149":1,"174":1,"209":1,"559":1,"560":1,"651":1}}],["par",{"2":{"226":1,"348":1}}],["party",{"2":{"313":3,"450":1,"464":1,"465":1,"475":1,"488":1,"489":1}}],["partida",{"2":{"276":1,"296":1,"316":1,"361":1}}],["participa",{"2":{"234":1}}],["particular",{"2":{"74":1,"77":1,"110":1,"142":1,"168":1,"203":1,"221":1}}],["partir",{"0":{"96":1,"105":1},"2":{"77":2,"131":1,"143":1,"191":1,"258":1,"259":1,"273":1,"293":1,"371":1,"375":1,"399":1,"414":1,"427":1,"441":2,"443":2,"448":1,"450":1,"454":1,"457":1,"459":1,"469":1,"475":1,"479":1,"481":1,"483":1,"516":1,"520":2,"531":1,"543":1,"554":1,"595":1,"666":1,"687":1}}],["partes",{"2":{"313":1,"320":1,"358":1,"365":1,"562":1,"636":1,"657":1,"676":1,"678":1,"682":2,"694":1}}],["parte",{"2":{"38":1,"39":2,"46":1,"77":2,"95":1,"104":1,"224":2,"259":3,"263":1,"271":1,"276":1,"291":1,"296":1,"316":1,"361":1,"420":1,"440":1,"446":1,"458":1,"482":1,"497":1,"531":1,"555":1,"572":1,"575":1,"598":1,"607":1,"641":1,"663":1,"673":1,"679":1,"682":1,"698":1,"709":1,"724":1}}],["parágrafo",{"2":{"69":1,"676":1,"679":1,"681":1}}],["parâmetroviewregistrye",{"2":{"444":1}}],["parâmetros",{"2":{"47":1,"342":1,"444":1,"461":2,"465":1,"485":2,"488":1}}],["parâmetro",{"2":{"47":1,"101":1,"222":1,"444":1,"464":1,"465":1,"488":1,"489":1,"704":1}}],["paradigma",{"2":{"346":1}}],["parada",{"2":{"48":1}}],["parabéns",{"2":{"154":1,"179":1,"197":1,"214":1}}],["paralaxe",{"2":{"77":1}}],["paralelizar",{"2":{"65":1,"69":1}}],["paralelo",{"2":{"48":3}}],["parallel",{"2":{"48":2}}],["parar",{"2":{"47":1,"48":1}}],["params",{"2":{"390":1,"466":9}}],["parameters",{"2":{"390":1}}],["param",{"2":{"45":1,"491":1}}],["para",{"0":{"71":1,"92":1,"93":1,"101":1,"102":1,"115":1,"116":1,"131":1,"135":1,"278":1,"298":1,"312":1,"332":1,"357":1,"403":1,"408":1,"417":1,"441":1,"454":1,"456":1,"466":1,"479":1,"490":1,"539":1,"549":1,"604":1,"613":1,"622":1,"647":1,"657":1,"658":1,"666":1,"691":1,"706":1,"717":1,"749":1},"1":{"72":1,"73":1,"74":1,"75":1,"76":1,"77":1,"78":1,"409":1,"410":1,"411":1,"412":1,"413":1,"442":1,"455":1,"457":1,"667":1,"707":1,"708":1,"718":1,"719":1,"720":1,"721":1,"722":1,"723":1,"724":1,"725":1,"726":1,"727":1,"728":1,"729":1,"750":1,"751":1},"2":{"0":1,"2":2,"3":2,"4":1,"5":1,"6":1,"9":1,"10":1,"11":16,"12":3,"13":1,"16":1,"17":1,"18":1,"21":1,"27":1,"30":1,"31":1,"32":1,"34":15,"35":11,"36":1,"37":2,"38":7,"39":5,"42":2,"43":5,"45":3,"46":6,"47":3,"48":4,"49":2,"50":12,"51":2,"52":5,"53":2,"55":4,"56":6,"57":1,"60":7,"62":2,"63":2,"64":2,"65":5,"67":8,"68":4,"69":5,"70":3,"73":4,"74":6,"75":1,"76":1,"77":12,"78":1,"80":2,"87":1,"90":3,"91":2,"92":2,"94":2,"95":5,"97":1,"99":3,"100":2,"101":3,"103":2,"104":5,"105":1,"106":3,"107":1,"108":1,"110":1,"111":3,"112":4,"113":1,"114":3,"115":6,"116":2,"123":1,"126":1,"128":4,"129":1,"130":3,"131":4,"132":1,"133":4,"134":4,"135":4,"136":1,"137":4,"138":1,"141":2,"142":5,"143":3,"145":2,"147":4,"148":1,"149":6,"151":4,"153":1,"155":1,"156":2,"157":2,"158":2,"159":4,"164":4,"165":2,"166":3,"167":2,"168":6,"170":2,"172":4,"173":1,"174":4,"176":4,"178":1,"180":1,"182":4,"183":2,"184":1,"185":1,"186":2,"187":2,"189":5,"191":5,"193":4,"196":1,"198":1,"199":4,"200":4,"202":3,"203":10,"205":2,"207":4,"208":1,"209":6,"211":4,"213":1,"215":1,"217":3,"218":1,"219":2,"220":2,"221":2,"222":5,"224":4,"225":2,"226":2,"227":3,"228":1,"229":1,"230":1,"232":1,"235":2,"236":3,"237":2,"238":1,"239":2,"240":1,"241":1,"242":3,"243":2,"244":3,"245":4,"246":1,"248":1,"249":2,"250":1,"251":5,"252":1,"253":1,"254":1,"257":2,"258":1,"259":3,"261":2,"262":3,"265":2,"266":3,"267":3,"268":4,"270":2,"271":1,"273":2,"274":1,"275":1,"276":2,"278":5,"279":10,"280":3,"281":2,"283":3,"284":1,"285":1,"287":2,"288":10,"290":2,"291":1,"293":2,"294":1,"295":1,"296":2,"298":5,"299":10,"300":3,"301":2,"303":3,"304":1,"306":2,"307":3,"308":3,"309":4,"310":2,"311":1,"312":1,"313":6,"314":2,"315":1,"316":2,"318":1,"319":2,"320":13,"321":1,"322":3,"323":2,"324":2,"325":2,"326":1,"328":4,"329":6,"330":2,"331":2,"333":3,"334":5,"335":1,"336":3,"337":2,"338":3,"339":2,"341":1,"342":1,"343":2,"344":4,"345":4,"346":1,"347":2,"348":5,"349":8,"351":2,"352":3,"353":3,"354":4,"355":2,"356":1,"357":1,"358":7,"359":2,"360":1,"361":2,"363":1,"364":2,"365":13,"366":1,"367":1,"368":3,"369":2,"370":2,"371":2,"372":1,"374":2,"375":2,"376":1,"377":6,"378":2,"379":6,"381":3,"382":1,"383":1,"384":3,"385":1,"386":6,"387":4,"389":1,"390":2,"397":1,"398":2,"399":4,"400":1,"402":4,"403":1,"404":7,"405":2,"407":2,"409":1,"411":1,"412":1,"413":3,"414":3,"417":7,"418":1,"419":3,"420":4,"421":3,"422":1,"423":1,"424":9,"426":1,"427":4,"428":2,"431":1,"435":1,"436":1,"440":4,"441":11,"442":15,"443":5,"444":3,"445":2,"446":4,"447":1,"448":5,"449":3,"451":4,"452":6,"454":3,"455":3,"456":9,"457":3,"458":3,"459":3,"461":5,"462":4,"463":2,"464":14,"465":4,"466":3,"467":3,"469":1,"470":8,"471":1,"472":2,"473":3,"474":3,"476":3,"477":2,"478":1,"479":4,"480":3,"481":3,"482":3,"483":1,"485":5,"486":5,"487":4,"488":16,"489":2,"490":4,"491":8,"492":1,"493":11,"495":2,"497":1,"502":2,"503":2,"505":1,"506":1,"507":1,"508":1,"509":2,"510":3,"511":6,"512":2,"513":2,"514":1,"516":2,"517":1,"518":2,"519":2,"520":4,"521":1,"524":5,"525":2,"526":3,"527":2,"529":2,"530":1,"531":4,"532":5,"533":4,"534":7,"535":5,"537":1,"538":1,"539":2,"540":3,"541":6,"542":2,"543":3,"544":1,"545":8,"546":4,"547":6,"548":1,"549":7,"550":3,"551":3,"552":4,"553":1,"554":3,"555":5,"556":2,"559":2,"560":1,"561":1,"562":3,"563":2,"564":1,"566":4,"567":4,"568":1,"569":1,"570":1,"571":3,"573":1,"574":1,"575":3,"576":3,"577":1,"578":1,"579":1,"580":2,"581":3,"583":1,"585":2,"586":2,"587":2,"588":2,"589":2,"591":1,"593":2,"595":5,"596":10,"598":4,"599":1,"600":2,"602":1,"603":1,"604":3,"605":6,"607":4,"608":2,"609":2,"611":1,"612":2,"613":3,"615":4,"616":4,"618":1,"619":4,"622":2,"626":1,"627":1,"628":2,"629":7,"630":2,"631":1,"632":2,"633":2,"634":7,"635":8,"636":13,"638":2,"641":4,"642":1,"643":2,"645":1,"646":2,"647":3,"648":7,"650":2,"651":1,"652":1,"653":1,"654":7,"655":1,"656":8,"657":3,"658":4,"660":1,"662":3,"663":4,"665":2,"666":5,"667":2,"668":6,"671":2,"672":9,"673":4,"674":2,"675":6,"677":1,"678":4,"679":5,"680":4,"681":5,"682":6,"685":1,"687":7,"688":1,"689":2,"690":5,"691":5,"692":6,"693":1,"694":2,"695":4,"696":2,"697":2,"699":1,"700":4,"703":2,"704":3,"706":1,"708":4,"709":1,"710":1,"711":3,"715":1,"716":1,"717":2,"718":4,"720":2,"721":5,"723":2,"724":2,"726":4,"728":1,"729":1,"730":4,"731":4,"734":4,"735":1,"736":4,"737":1,"739":4,"740":3,"741":2,"742":3,"745":5,"746":7,"747":1,"748":2,"749":1,"750":2,"751":1,"754":1,"755":1}}],["pais",{"2":{"227":1}}],["painel",{"2":{"185":1,"203":2,"312":1,"357":1,"617":1,"708":1}}],["pai",{"2":{"2":1,"30":2,"60":1,"90":2,"94":1,"99":2,"103":1,"106":3,"228":2,"231":2,"233":1,"234":2,"247":1,"248":1,"252":2,"262":6,"263":3,"347":2,"531":4,"669":1}}],["potencializa",{"2":{"687":1}}],["potencialmente",{"2":{"491":1,"500":1}}],["pop",{"2":{"244":1}}],["populares",{"2":{"417":1,"733":1}}],["popular",{"2":{"200":1,"343":1,"636":1,"682":2,"693":1}}],["ponderados",{"2":{"231":1}}],["ponderado",{"2":{"231":1}}],["pontuação",{"2":{"320":1,"325":1,"365":1,"371":1}}],["ponta",{"0":{"682":2},"2":{"151":2,"176":2,"193":2,"211":2,"682":2}}],["pontos",{"2":{"135":1,"261":2,"437":1,"619":1,"681":1}}],["ponto",{"2":{"118":1,"149":1,"174":1,"209":1,"225":1,"231":2,"276":1,"284":1,"296":1,"304":1,"316":1,"326":1,"361":1,"367":1,"372":1,"457":1,"459":1,"481":1,"483":1,"531":1,"553":1,"556":1,"585":2,"673":1,"681":1,"734":1,"745":1}}],["ponte",{"2":{"56":1,"97":1,"101":1,"105":1,"106":1,"320":1,"365":1,"421":2,"441":2,"442":1,"445":1,"492":1,"493":4,"495":1,"575":1,"634":1,"693":2}}],["powershell",{"2":{"203":2}}],["powderblue",{"2":{"46":1,"88":1,"224":1,"225":1,"226":1,"227":1,"228":1,"231":7,"233":1,"234":1,"261":1,"262":1,"263":1}}],["poucas",{"2":{"71":1}}],["pouco",{"2":{"55":1,"159":2,"245":1,"375":1,"441":1,"456":2,"461":1,"485":1,"493":1,"497":1,"533":1,"560":1,"711":1,"717":1}}],["podspecs",{"2":{"313":3}}],["podspec",{"2":{"313":8,"358":2}}],["pods",{"2":{"68":1,"313":1,"358":4,"666":1,"667":1,"706":1,"708":1,"748":2}}],["pod",{"2":{"68":1,"189":1,"313":31,"358":3,"377":3,"666":1,"706":2,"748":1}}],["podfile`",{"2":{"313":1}}],["podfilemuda",{"2":{"313":1}}],["podfile",{"2":{"68":1,"313":6,"358":9,"666":1,"706":2,"748":1,"751":1}}],["poderosa",{"2":{"681":1}}],["poderosos",{"2":{"96":1,"105":1}}],["poderoso",{"2":{"60":1}}],["poder",{"2":{"271":1,"291":1,"445":1,"501":1,"692":1,"706":1,"726":1}}],["poderão",{"2":{"131":1,"251":1,"262":1,"263":1,"491":1}}],["poderíamos",{"2":{"63":1,"110":1,"545":1}}],["poderia",{"2":{"50":2,"51":1,"538":1,"629":1,"635":1,"673":1,"677":1}}],["poderá",{"2":{"50":1,"56":1,"65":1,"66":1,"69":1,"117":1,"148":1,"149":2,"156":1,"173":1,"174":2,"208":1,"209":2,"218":1,"245":1,"330":1,"374":1,"402":1,"446":1,"450":1,"454":1,"455":1,"456":1,"461":1,"470":2,"475":1,"480":1,"485":1,"487":1,"491":2,"493":1,"520":1,"534":1,"540":1,"544":1,"545":1,"549":1,"556":1,"603":1,"612":1,"619":1,"636":1,"646":1,"679":1,"685":1,"702":1,"725":1,"731":1,"734":1}}],["poderemos",{"2":{"46":1,"652":1}}],["pode",{"2":{"5":1,"10":1,"11":7,"12":1,"13":1,"21":1,"30":2,"31":1,"33":1,"34":6,"38":3,"39":3,"41":1,"43":3,"46":3,"47":2,"48":2,"49":1,"50":5,"53":1,"55":3,"56":3,"57":4,"60":1,"63":4,"64":2,"65":4,"66":1,"67":10,"68":3,"69":1,"70":2,"73":1,"74":5,"76":2,"77":2,"78":1,"85":1,"86":1,"92":2,"95":1,"96":3,"101":2,"104":1,"105":3,"111":5,"113":1,"114":2,"115":1,"116":2,"118":1,"122":1,"126":2,"128":1,"130":1,"131":4,"133":1,"134":2,"135":2,"136":1,"139":2,"140":1,"142":2,"143":3,"145":4,"146":2,"147":2,"152":1,"156":3,"159":1,"166":1,"168":2,"170":4,"171":2,"172":2,"177":1,"187":1,"189":3,"190":3,"191":2,"194":1,"200":6,"201":1,"203":2,"205":4,"206":2,"207":2,"212":1,"216":1,"217":2,"218":1,"219":3,"220":3,"221":1,"222":1,"224":1,"226":2,"227":2,"228":1,"229":1,"230":2,"231":2,"232":1,"233":1,"235":3,"237":3,"238":1,"239":1,"240":1,"242":2,"244":2,"245":4,"248":3,"250":1,"251":3,"252":1,"254":1,"255":1,"257":2,"258":1,"259":2,"261":1,"262":1,"263":1,"272":1,"276":2,"278":2,"279":1,"283":1,"284":1,"285":1,"292":1,"296":2,"298":2,"299":1,"303":1,"304":1,"313":1,"316":2,"319":1,"320":3,"325":1,"326":1,"328":3,"329":2,"332":1,"333":2,"334":1,"337":1,"338":1,"339":1,"341":1,"343":1,"344":4,"345":3,"346":1,"347":5,"348":2,"349":5,"358":1,"361":2,"364":1,"365":3,"371":1,"372":1,"381":1,"383":1,"384":1,"385":1,"386":2,"387":2,"389":1,"390":1,"398":1,"399":1,"402":2,"403":1,"404":1,"406":1,"413":1,"417":1,"418":1,"424":2,"428":1,"429":1,"430":1,"436":2,"437":1,"438":1,"441":1,"442":4,"444":2,"445":1,"447":2,"448":3,"451":2,"452":1,"453":2,"454":3,"455":2,"456":3,"457":4,"459":3,"461":2,"462":1,"463":3,"464":11,"465":8,"466":2,"467":1,"468":1,"470":2,"476":2,"477":3,"478":2,"479":3,"480":3,"481":4,"483":2,"485":2,"486":1,"487":3,"488":6,"489":2,"490":3,"491":1,"492":2,"493":1,"495":1,"497":2,"499":1,"500":1,"502":2,"507":1,"508":1,"510":2,"516":2,"517":2,"518":1,"519":2,"520":3,"521":2,"523":4,"524":2,"525":2,"527":1,"528":1,"529":4,"531":6,"532":1,"534":3,"535":1,"538":1,"540":3,"541":3,"542":2,"543":2,"548":2,"549":3,"550":1,"552":2,"553":2,"554":2,"556":1,"561":1,"562":2,"563":1,"565":1,"566":2,"567":2,"568":1,"569":1,"570":1,"572":1,"573":1,"574":3,"576":5,"581":1,"582":1,"583":2,"584":2,"585":2,"586":1,"587":1,"588":1,"589":1,"590":1,"591":1,"592":1,"594":1,"598":2,"600":1,"601":1,"602":2,"603":3,"605":1,"607":2,"609":1,"610":1,"611":2,"612":2,"617":1,"618":1,"619":2,"624":1,"625":2,"627":1,"629":3,"634":2,"635":4,"636":4,"638":4,"639":1,"641":2,"643":1,"644":1,"645":2,"646":2,"648":1,"649":1,"652":2,"654":2,"655":1,"656":1,"657":1,"662":1,"664":1,"666":3,"667":3,"668":5,"671":1,"673":1,"674":1,"675":1,"677":2,"678":1,"679":2,"681":2,"682":2,"683":1,"685":1,"691":3,"692":1,"693":3,"695":4,"696":1,"697":1,"700":2,"701":1,"703":1,"704":2,"711":1,"715":1,"719":1,"721":3,"722":1,"724":1,"726":3,"728":2,"729":1,"730":1,"731":5,"733":1,"734":1,"735":1,"737":2,"741":2,"742":1,"745":3,"746":1,"748":2}}],["podemos",{"2":{"30":1,"67":1,"90":1,"99":1,"110":1,"259":1,"338":2,"420":1,"427":1,"440":1,"441":2,"442":1,"443":3,"444":1,"571":1,"575":1,"689":1,"690":1,"692":1}}],["podem",{"2":{"0":1,"7":1,"20":1,"27":1,"43":1,"47":1,"48":3,"51":2,"52":1,"58":1,"60":1,"74":1,"77":1,"79":1,"95":1,"96":2,"97":1,"104":1,"105":2,"106":2,"128":2,"142":1,"168":1,"203":1,"217":1,"233":1,"243":1,"245":2,"257":1,"279":2,"299":2,"328":1,"337":1,"340":1,"347":1,"379":1,"385":1,"398":2,"402":6,"403":1,"420":1,"440":1,"456":2,"464":1,"465":1,"466":2,"488":1,"489":1,"490":1,"495":1,"498":1,"501":2,"507":1,"509":1,"531":4,"538":1,"551":1,"561":2,"562":1,"573":1,"586":1,"589":1,"629":2,"665":1,"670":1,"671":1,"673":1,"675":1,"677":1,"679":3,"680":1,"681":1,"686":2,"689":2,"692":1,"699":2,"700":1,"731":1,"734":1,"735":1,"745":1,"751":1}}],["polimento",{"2":{"688":1}}],["polifills",{"0":{"391":1},"1":{"392":1,"393":1,"394":1,"395":1,"396":1}}],["polite",{"2":{"10":4,"27":2}}],["política",{"2":{"273":1,"293":1}}],["políticas",{"2":{"257":1}}],["polyfills",{"2":{"709":1}}],["polyfill",{"2":{"62":1,"709":1}}],["posts",{"2":{"652":1}}],["posteriores",{"2":{"635":1}}],["posterior",{"2":{"493":1,"520":1}}],["posteriormente",{"2":{"221":1,"431":1,"456":1,"464":1,"465":1,"650":1,"652":1,"700":1}}],["postframecallback",{"2":{"431":4}}],["postagem",{"2":{"75":1}}],["post",{"2":{"68":5,"332":1,"344":1,"517":1,"519":2}}],["posicione",{"2":{"690":1}}],["posicionar",{"2":{"690":1}}],["posicionado",{"2":{"234":4,"542":1}}],["posicionamento",{"2":{"110":1,"329":1,"499":1,"679":1,"690":1}}],["posições",{"2":{"53":1}}],["posição",{"2":{"47":1,"50":1,"52":1,"53":1,"56":1,"57":1,"74":1,"111":1,"234":3,"251":4,"689":1,"690":1}}],["positionlayout",{"2":{"234":2}}],["position",{"2":{"48":2,"234":7}}],["posso",{"0":{"695":1}}],["possuem",{"2":{"561":1,"566":1,"571":2,"662":1}}],["possuir",{"2":{"411":1}}],["possui",{"2":{"0":1,"50":1,"59":1,"65":1,"77":1,"80":1,"101":1,"144":1,"145":1,"169":1,"170":1,"188":1,"200":1,"204":1,"205":1,"209":1,"223":1,"339":1,"387":1,"417":1,"424":1,"445":1,"531":2,"619":1,"630":1,"656":1,"679":1,"746":1}}],["possibly",{"2":{"68":1}}],["possivelmente",{"2":{"9":1}}],["possa",{"2":{"60":1,"110":1,"129":1,"137":1,"164":1,"182":1,"199":1,"200":1,"349":1,"420":1,"440":1,"442":1,"457":1,"458":1,"479":1,"481":1,"482":1,"534":1,"547":1,"572":2,"596":1,"628":1,"635":1,"674":1,"726":1}}],["possam",{"2":{"52":1,"55":1,"135":1,"252":1,"520":1,"619":1,"680":1}}],["possível",{"0":{"714":1},"1":{"715":1,"716":1},"2":{"10":1,"31":1,"43":1,"74":1,"120":1,"191":2,"221":1,"310":1,"325":2,"336":1,"355":1,"371":2,"379":1,"417":1,"442":1,"463":1,"487":1,"505":1,"506":2,"532":2,"561":1,"595":1,"639":1,"677":1,"682":1,"699":1,"707":1,"742":1}}],["pois",{"2":{"39":1,"43":1,"53":1,"55":1,"56":1,"65":1,"69":1,"94":1,"96":1,"103":1,"105":1,"111":1,"145":1,"170":1,"189":1,"205":1,"242":1,"249":1,"270":1,"290":1,"338":1,"339":1,"413":1,"455":1,"469":1,"477":1,"480":1,"521":1,"531":2,"551":1,"559":1,"595":1,"654":1,"659":1}}],["porcentagem",{"2":{"233":1}}],["português",{"0":{"752":1},"1":{"753":1,"754":1,"755":1,"756":1,"757":1,"758":1,"759":1,"760":1,"761":1,"762":1,"763":1,"764":1,"765":1,"766":1,"767":1,"768":1,"769":1}}],["port=8088",{"2":{"704":1}}],["portfólio",{"2":{"420":1,"440":1}}],["port",{"0":{"702":1},"1":{"703":1,"704":1},"2":{"134":2,"603":1,"612":1,"646":1,"704":2}}],["portado",{"2":{"736":1}}],["portais",{"2":{"619":1}}],["portal",{"2":{"345":1}}],["porta",{"0":{"702":1,"703":1,"704":1},"1":{"703":1,"704":1},"2":{"133":1,"596":2,"603":1,"612":1,"646":1,"702":3,"703":2,"704":3}}],["portanto",{"2":{"0":1,"22":1,"56":1,"60":1,"65":1,"68":1,"69":1,"91":1,"100":1,"114":1,"115":1,"217":1,"218":1,"242":1,"245":1,"250":1,"252":1,"262":1,"263":1,"270":1,"272":1,"290":1,"292":1,"320":1,"323":1,"341":1,"348":1,"365":1,"369":1,"443":1,"456":1,"458":1,"463":1,"479":1,"482":1,"487":1,"491":1,"499":1,"532":1,"535":1,"538":1,"545":1,"629":1,"636":1,"638":1,"650":1,"662":1,"665":1,"666":1,"668":1,"676":1,"677":1,"681":1,"721":1}}],["porque",{"2":{"43":1,"55":2,"96":1,"105":1,"114":1,"117":1,"130":1,"252":1,"278":1,"279":1,"298":1,"299":1,"337":1,"341":1,"421":1,"455":1,"458":1,"467":1,"480":1,"482":1,"499":1,"507":1,"529":1,"534":2,"535":1,"545":1,"573":1,"574":1,"575":1,"585":1,"595":1,"635":1,"636":2,"637":1,"671":1,"677":1,"682":1,"692":1}}],["por",{"0":{"248":1,"337":1,"541":1,"671":1,"688":1},"1":{"249":1,"250":1,"251":1,"252":1,"253":1,"689":1},"2":{"2":1,"3":1,"11":2,"14":2,"15":1,"24":1,"34":3,"35":2,"38":3,"39":2,"44":1,"46":1,"47":2,"48":1,"49":1,"50":6,"51":1,"52":1,"55":1,"56":1,"60":1,"63":2,"65":1,"67":3,"68":1,"74":3,"77":5,"92":1,"95":1,"97":1,"101":1,"104":1,"105":1,"106":1,"110":2,"111":3,"112":1,"114":2,"115":2,"116":1,"119":1,"120":2,"121":1,"126":1,"128":4,"134":3,"135":1,"142":3,"151":1,"159":1,"168":3,"176":1,"193":1,"195":1,"203":4,"211":1,"216":1,"217":3,"218":1,"220":2,"221":2,"225":1,"226":1,"230":1,"231":1,"234":1,"242":2,"243":1,"245":1,"246":1,"248":4,"251":1,"252":1,"254":1,"255":1,"256":2,"257":2,"258":1,"259":2,"270":1,"273":1,"279":7,"290":1,"293":1,"299":7,"313":4,"318":1,"320":3,"328":2,"336":2,"337":2,"338":2,"342":1,"343":1,"346":1,"348":2,"349":2,"358":4,"363":1,"365":3,"367":1,"379":1,"382":1,"383":1,"389":1,"399":1,"402":2,"403":1,"404":1,"413":1,"421":1,"422":1,"423":1,"425":1,"426":2,"430":4,"431":1,"436":1,"441":3,"442":2,"444":3,"445":1,"446":2,"447":1,"448":2,"453":1,"454":2,"455":2,"456":2,"461":1,"462":2,"463":1,"466":2,"470":1,"478":1,"479":2,"480":3,"485":1,"486":2,"487":1,"490":2,"491":5,"492":1,"493":1,"497":2,"500":3,"501":2,"503":1,"504":1,"520":2,"524":2,"529":4,"532":2,"533":2,"534":3,"535":1,"541":1,"549":1,"552":1,"555":2,"557":2,"558":1,"559":3,"560":1,"561":2,"562":1,"564":1,"565":1,"566":2,"571":2,"572":1,"574":2,"581":2,"586":1,"587":1,"588":1,"591":1,"593":1,"594":1,"595":4,"596":2,"598":1,"599":1,"600":1,"603":2,"607":1,"608":1,"609":1,"612":2,"621":1,"626":1,"627":1,"629":2,"633":1,"634":3,"635":2,"636":4,"638":1,"641":1,"642":1,"643":1,"646":2,"650":1,"654":1,"656":2,"659":1,"662":1,"663":1,"665":1,"666":3,"667":1,"668":2,"669":1,"671":1,"672":1,"673":1,"675":3,"677":1,"678":2,"679":5,"680":4,"681":3,"682":2,"685":1,"693":1,"695":2,"696":1,"699":1,"706":2,"709":1,"721":1,"722":1,"723":1,"724":1,"725":1,"726":1,"732":1,"733":1,"735":1,"739":1,"740":1,"742":1,"745":1,"748":1,"751":1,"757":1}}],["eram",{"2":{"688":1}}],["errno",{"0":{"715":1}}],["errada",{"2":{"681":1}}],["errorcallback",{"2":{"488":3}}],["error",{"0":{"716":1},"2":{"122":1,"257":2,"392":1,"464":7,"465":7,"488":7,"489":1,"520":9,"521":1,"576":1,"705":1}}],["erros",{"0":{"128":1,"129":1,"130":1,"218":1,"278":1,"298":1,"529":1},"2":{"67":1,"127":1,"128":2,"129":3,"130":1,"218":1,"249":1,"257":1,"278":1,"298":1,"313":1,"336":1,"358":1,"442":3,"451":1,"464":1,"476":1,"488":2,"520":1,"670":1,"671":2,"672":2,"729":1}}],["erro",{"0":{"705":1,"715":1},"2":{"56":1,"114":1,"128":1,"129":2,"130":5,"218":9,"257":2,"407":1,"464":3,"465":5,"488":6,"522":1,"529":1,"537":1,"603":1,"612":1,"619":1,"646":1,"660":1,"705":1,"708":1,"711":1,"716":1}}],["e2e",{"2":{"682":8}}],["eu",{"2":{"555":1}}],["efêmero",{"2":{"524":1}}],["efeitos",{"0":{"689":1},"2":{"217":1,"228":1,"506":1,"695":1}}],["efeito",{"2":{"111":1,"115":1,"227":1,"229":1,"544":1}}],["efetivamente",{"2":{"67":1,"677":1}}],["ecmascript",{"0":{"393":1,"394":1,"395":1},"2":{"390":7}}],["economizando",{"2":{"503":1}}],["economiza",{"2":{"499":1}}],["economizar",{"2":{"320":1,"334":1,"365":1,"548":1,"666":2}}],["ecossistema",{"2":{"386":1,"419":1,"687":1,"695":1}}],["echo",{"2":{"142":2,"168":2}}],["equals",{"2":{"259":1}}],["equivale",{"2":{"693":1}}],["equivalentes",{"2":{"462":1,"486":1}}],["equivalente",{"2":{"112":1,"323":1,"369":1,"503":1,"630":1,"633":1}}],["equipe",{"2":{"111":1,"506":1,"509":1,"560":1,"616":2,"671":1,"687":2,"688":1,"695":1,"696":1,"697":1,"722":2}}],["eixo",{"2":{"223":1,"224":5,"226":7,"227":8,"229":7,"230":2,"231":5}}],["either",{"2":{"114":1}}],["ee82ee",{"2":{"88":1}}],["eee8aa",{"2":{"88":1}}],["e0ffff",{"2":{"88":1}}],["e6e6fa",{"2":{"88":1}}],["e9967a",{"2":{"88":1}}],["ethernet",{"2":{"259":3,"619":1}}],["etc",{"2":{"77":1,"112":1,"285":1,"347":1,"424":1,"437":1,"443":1,"468":1,"526":1,"534":1,"555":1,"586":1,"595":1,"596":1,"608":1,"681":1,"682":1,"693":1,"699":1,"715":1}}],["etapa",{"0":{"151":1,"152":1,"176":1,"193":1,"194":1,"211":1,"212":1,"413":1},"2":{"68":1,"135":1,"141":1,"149":1,"167":1,"174":1,"202":1,"203":1,"209":1,"262":1,"283":1,"303":1,"390":1,"401":2,"409":1,"413":1,"425":1,"426":1,"452":1,"457":1,"477":1,"481":1,"580":1,"616":1,"636":1,"653":1,"720":1}}],["etapas",{"0":{"408":1},"1":{"409":1,"410":1,"411":1,"412":1,"413":1},"2":{"68":1,"140":1,"166":1,"201":1,"280":1,"285":2,"300":1,"322":1,"368":1,"428":1,"448":1,"454":1,"459":1,"470":1,"556":1,"603":1,"605":1,"612":1,"646":1,"648":1,"675":2,"706":1,"745":1}}],["eacces",{"0":{"716":1},"2":{"705":1}}],["each",{"2":{"68":2}}],["easing",{"2":{"47":3,"50":1}}],["easyinout",{"2":{"47":1}}],["evidência",{"2":{"681":1}}],["evite",{"0":{"511":1},"2":{"462":1,"486":1,"506":1,"680":1}}],["evitam",{"2":{"700":1}}],["evita",{"2":{"135":1,"258":1,"273":1,"293":1}}],["evitando",{"0":{"117":1},"2":{"672":1,"690":1}}],["evitar",{"2":{"50":1,"57":1,"69":1,"77":1,"112":1,"118":1,"143":1,"252":1,"336":1,"389":1,"441":2,"461":1,"463":1,"485":1,"487":1,"490":1,"505":1,"511":1,"566":1,"567":1,"638":1,"670":1,"672":1,"680":2,"689":1}}],["evenly",{"2":{"226":2}}],["eventualidade",{"2":{"628":1}}],["eventualmente",{"2":{"89":1,"98":1}}],["eventlistener",{"2":{"466":2}}],["eventemitter",{"2":{"466":2}}],["eventreminder",{"2":{"466":3,"490":1}}],["eventproperty",{"2":{"466":3}}],["eventname",{"2":{"466":6,"490":2}}],["eventid",{"2":{"464":14,"465":6,"488":12,"489":5}}],["eventtype",{"2":{"74":5,"77":5}}],["event",{"2":{"35":2,"52":4,"53":2,"54":1,"56":2,"57":1,"279":2,"299":2,"427":7,"443":4,"454":2,"463":9,"464":1,"465":5,"466":2,"479":1,"487":4,"488":2,"489":3,"531":1,"690":1}}],["evento",{"0":{"53":1,"54":1,"319":1,"364":1},"2":{"35":1,"37":2,"53":1,"56":1,"74":3,"77":2,"96":2,"105":2,"251":3,"256":1,"318":1,"321":1,"363":1,"366":1,"404":1,"427":4,"443":2,"450":1,"459":1,"461":4,"464":1,"466":1,"475":1,"483":1,"485":4,"487":1,"488":1,"490":2,"689":1}}],["eventos",{"0":{"37":1,"95":1,"96":1,"104":1,"105":1,"320":1,"365":1,"427":1,"443":1,"466":1,"468":1,"490":1},"1":{"96":1,"97":1,"105":1,"106":1},"2":{"30":1,"37":1,"52":2,"55":1,"57":2,"74":5,"77":4,"95":1,"96":6,"104":1,"105":8,"131":1,"217":1,"251":2,"279":1,"299":1,"320":2,"321":1,"365":2,"366":1,"387":1,"421":1,"426":1,"427":1,"441":1,"443":6,"448":1,"454":1,"466":2,"468":2,"479":1,"490":3,"500":1,"531":3,"534":4,"535":1,"555":1,"557":1,"680":3,"691":1,"695":1,"699":1}}],["evt",{"2":{"74":11,"77":11,"251":9,"252":2}}],["enospc",{"0":{"715":2}}],["enorme",{"2":{"673":1}}],["enfileiradas",{"2":{"700":1}}],["engenharia",{"2":{"636":1}}],["engenheiros",{"2":{"235":1}}],["engine",{"2":{"574":1,"685":1}}],["ensinar",{"2":{"532":1}}],["en",{"2":{"200":1,"415":1}}],["enquadrar",{"2":{"679":1}}],["enquadra",{"2":{"110":1,"678":1}}],["enquanto",{"0":{"458":1,"482":1},"2":{"32":1,"35":2,"43":1,"48":1,"55":1,"57":1,"58":1,"74":1,"77":1,"95":1,"104":1,"111":2,"221":1,"242":2,"245":1,"248":1,"254":1,"258":1,"328":1,"341":1,"436":2,"454":1,"478":1,"479":1,"490":1,"501":1,"531":1,"541":2,"547":1,"554":1,"575":1,"586":1,"672":1,"699":1}}],["enablehermes",{"2":{"662":1}}],["enableproguardinreleasebuilds",{"2":{"657":1}}],["enable",{"2":{"74":1,"77":1,"216":1,"526":1,"656":1,"748":2}}],["enabletveventhandler",{"2":{"74":2,"77":2}}],["enabled",{"2":{"38":2,"748":5,"751":3}}],["env",{"2":{"191":3,"203":1,"538":1,"667":1}}],["envolva",{"2":{"414":1}}],["envolvidas",{"2":{"677":1}}],["envolvida",{"2":{"118":1}}],["envolvemos",{"2":{"692":1}}],["envolvente",{"2":{"349":1}}],["envolver",{"2":{"348":1}}],["envolve",{"2":{"77":1,"558":1,"571":1,"634":1,"636":1}}],["envenenado",{"2":{"69":1}}],["enviá",{"2":{"527":1,"545":1,"549":1}}],["enviada",{"2":{"695":1}}],["enviadas",{"2":{"534":1}}],["enviado",{"2":{"242":1,"424":1}}],["enviados",{"2":{"96":1,"105":1,"534":1}}],["envia",{"2":{"490":1,"522":1,"534":1,"636":2}}],["enviam",{"2":{"421":1}}],["enviamos",{"2":{"56":1,"407":1}}],["enviará",{"2":{"636":1}}],["enviar",{"2":{"417":1,"421":1,"442":1,"534":1,"545":1,"546":1,"575":1,"596":1,"634":1,"635":4,"648":1,"655":1,"658":1,"699":1}}],["enviaremos",{"2":{"259":2}}],["enviando",{"0":{"466":1,"490":1},"2":{"105":1,"421":1,"441":1}}],["envio",{"0":{"37":1},"2":{"414":1}}],["endpoints",{"2":{"629":1,"638":1}}],["endpoint",{"2":{"519":1,"521":1,"637":1}}],["endswith",{"2":{"393":1}}],["endereço",{"0":{"621":1},"2":{"133":1,"134":1,"603":3,"612":3,"619":1,"621":4,"646":3,"745":2}}],["end",{"2":{"68":3,"226":2,"227":2,"228":1,"229":2,"313":1,"441":2,"442":2,"443":4,"477":2,"490":1,"493":1}}],["encryptedsharedpreferences",{"2":{"634":1}}],["encrypted",{"2":{"633":1,"634":1}}],["encorajamos",{"2":{"463":1,"487":1}}],["encolher",{"0":{"231":1}}],["encontrá",{"2":{"387":1,"549":1,"747":1}}],["encontre",{"0":{"419":1,"555":1},"2":{"191":1,"457":1,"481":1,"682":1}}],["encontra",{"2":{"680":1}}],["encontradas",{"2":{"531":3,"589":1}}],["encontrada",{"2":{"390":1,"523":1,"550":1}}],["encontrados",{"2":{"79":1,"442":1}}],["encontrado",{"2":{"68":1,"142":1,"168":1,"203":1,"456":1,"553":1,"654":1}}],["encontrando",{"0":{"379":1},"2":{"389":1}}],["encontrarão",{"2":{"679":1}}],["encontraremos",{"2":{"89":1,"98":1}}],["encontrará",{"2":{"39":1,"379":1,"403":1,"444":2,"629":1}}],["encontrar",{"0":{"738":1},"2":{"31":2,"33":1,"48":1,"63":1,"96":1,"105":1,"134":1,"139":1,"142":1,"166":1,"168":1,"200":2,"203":1,"374":1,"379":1,"402":1,"419":1,"451":2,"465":1,"476":2,"529":1,"531":1,"563":1,"575":1,"602":1,"603":1,"611":1,"612":1,"645":1,"646":1,"660":1,"696":1,"697":1,"701":2,"703":2,"705":1,"710":1}}],["encadeamento",{"2":{"555":1}}],["encaminhe",{"2":{"443":1}}],["encaminhamento",{"2":{"133":1}}],["encaminha",{"0":{"115":1}}],["encaminharemos",{"2":{"114":1}}],["encaminhar",{"2":{"114":1,"115":1,"629":1}}],["encapsulamento",{"2":{"349":1}}],["encapsulado",{"2":{"115":1,"511":1}}],["encaixar",{"2":{"55":1}}],["encerrando",{"0":{"703":1}}],["encerrar",{"2":{"655":1,"702":1,"703":1}}],["encerra",{"2":{"33":1,"279":1,"299":1}}],["enum",{"2":{"27":1,"111":1}}],["enthusiasm",{"2":{"737":2}}],["enthusiasmlevel",{"2":{"737":5}}],["entenda",{"2":{"306":1,"351":1}}],["entender",{"2":{"235":1,"238":1,"343":1,"387":1,"470":1,"671":1,"723":1}}],["entenderá",{"2":{"8":1,"381":1}}],["enter",{"2":{"279":1,"299":1,"402":1,"680":2}}],["entediante",{"2":{"140":1,"201":1}}],["entanto",{"2":{"65":1,"69":1,"74":1,"92":2,"96":1,"101":1,"105":1,"135":1,"142":1,"168":1,"203":1,"218":1,"221":1,"252":1,"261":1,"285":1,"344":1,"348":1,"387":1,"399":1,"447":1,"448":1,"452":1,"488":1,"491":1,"492":1,"493":1,"556":1,"568":1,"628":1,"631":1,"634":1,"635":1,"648":1,"656":1,"666":1,"683":1,"689":1}}],["então",{"2":{"46":1,"48":1,"55":1,"67":2,"74":1,"77":1,"90":1,"99":1,"111":1,"134":2,"142":1,"168":1,"255":1,"259":1,"270":1,"279":1,"290":1,"299":1,"336":1,"349":1,"375":1,"381":1,"441":1,"442":1,"443":2,"448":1,"453":2,"457":1,"459":1,"462":1,"463":1,"464":2,"466":1,"467":1,"468":1,"478":2,"481":1,"487":2,"488":3,"491":1,"493":1,"531":1,"565":1,"586":1,"593":1,"598":1,"607":1,"635":1,"636":1,"641":1,"652":1,"671":1,"675":1,"681":1,"683":1,"688":1,"690":1,"729":1,"730":1,"731":1,"745":1}}],["entries",{"2":{"395":1}}],["entryfile",{"0":{"591":1}}],["entry",{"2":{"283":1,"303":1}}],["entra",{"2":{"320":1,"365":1}}],["entrará",{"2":{"255":1,"568":1}}],["entrar",{"2":{"74":1,"77":1}}],["entradas",{"2":{"46":1}}],["entrada",{"0":{"242":1},"2":{"11":1,"34":1,"50":1,"74":2,"77":2,"116":2,"123":1,"124":1,"142":2,"168":2,"203":2,"242":3,"271":2,"291":2,"385":1,"486":1,"516":1,"577":2,"585":2,"591":1,"636":3,"663":1,"686":1,"708":1,"734":1,"753":1}}],["entregar",{"2":{"679":1}}],["entretanto",{"2":{"119":1,"464":1,"465":1,"520":1}}],["entre",{"0":{"89":1,"95":1,"98":1,"104":1,"471":1},"1":{"90":1,"91":1,"92":1,"93":1,"94":1,"95":1,"96":2,"97":2,"99":1,"100":1,"101":1,"102":1,"103":1,"104":1,"105":2,"106":2,"107":1,"108":1,"109":1,"110":1,"111":1,"472":1,"473":1},"2":{"11":1,"34":1,"46":2,"52":1,"60":1,"89":1,"90":2,"91":1,"94":2,"95":2,"98":1,"99":2,"100":1,"101":1,"103":2,"104":2,"111":1,"131":1,"191":1,"200":1,"221":1,"226":3,"229":1,"231":2,"232":4,"257":3,"262":1,"320":1,"345":1,"365":1,"379":1,"426":1,"442":1,"471":1,"491":2,"501":1,"548":1,"549":1,"566":2,"574":1,"629":2,"630":1,"636":1,"637":1,"678":1,"681":1,"689":1,"691":1,"693":1,"695":1,"699":1,"723":1,"731":1,"757":1,"767":1,"768":1}}],["ex",{"2":{"399":1}}],["exactly",{"2":{"431":4}}],["examinando",{"2":{"349":1}}],["examinaremos",{"2":{"421":1}}],["examinar",{"2":{"242":1}}],["example",{"2":{"68":1,"256":1,"470":2,"516":7,"553":1}}],["exatas",{"2":{"540":1}}],["exata",{"2":{"336":1}}],["exatamente",{"2":{"113":1,"226":1,"549":1}}],["exato",{"2":{"123":1,"686":1}}],["ext",{"2":{"399":2,"574":3,"662":1}}],["extrema",{"2":{"673":1}}],["extremos",{"2":{"143":1,"670":1}}],["extração",{"2":{"634":1}}],["extrapackagerargs",{"0":{"592":1},"2":{"574":1}}],["extrapolateright",{"2":{"50":1}}],["extrapolateleft",{"2":{"50":1}}],["extrapolate",{"2":{"50":1,"53":1}}],["extrapolação",{"2":{"50":1}}],["extrapolar",{"2":{"50":1}}],["extrapolará",{"2":{"50":1}}],["extra",{"2":{"257":1,"349":1,"445":1,"580":1}}],["extras",{"2":{"68":1,"256":4,"257":2,"259":2,"587":1,"588":1,"592":1}}],["extraia",{"2":{"53":1}}],["extrair",{"2":{"53":1}}],["extraídos",{"2":{"52":1}}],["extraído",{"2":{"46":1}}],["externo",{"2":{"677":1,"678":1}}],["extern",{"2":{"493":4}}],["externas",{"2":{"677":1}}],["externa",{"2":{"95":1,"104":1,"635":1}}],["extended",{"2":{"390":1}}],["extends",{"2":{"60":1,"74":1,"77":1,"92":2,"101":1,"244":1,"245":1,"256":1,"259":1,"279":1,"390":1,"402":2,"422":1,"427":3,"429":1,"430":1,"431":1,"442":1,"443":2,"444":1,"452":1,"467":1,"573":2,"734":1,"739":2}}],["extend",{"2":{"50":1}}],["extensions",{"2":{"739":1}}],["extension",{"2":{"44":1}}],["extensão",{"2":{"42":2,"131":1,"134":1,"330":1,"442":1,"565":1,"566":2,"636":1,"735":1}}],["extensões",{"0":{"41":1,"42":1,"44":1,"565":1,"566":1},"1":{"42":1,"43":2,"44":2},"2":{"41":4,"42":6,"43":1,"44":4,"134":2,"561":1,"566":1,"768":1}}],["existssync",{"2":{"577":1}}],["existir",{"2":{"531":1}}],["exist",{"2":{"467":8}}],["exista",{"2":{"283":1,"303":1,"446":1}}],["existente",{"0":{"734":1},"2":{"145":2,"155":1,"159":1,"170":2,"180":1,"189":2,"198":1,"205":2,"215":1,"267":1,"283":1,"288":1,"303":1,"308":1,"318":2,"334":1,"353":1,"363":2,"400":2,"402":1,"406":1,"420":1,"440":1,"442":1,"580":1,"654":1,"671":1,"688":1,"736":1}}],["existentes",{"0":{"285":1},"2":{"71":1,"74":1,"77":1,"89":1,"98":2,"106":1,"145":1,"170":1,"189":1,"205":1,"285":1,"334":4,"338":1,"400":1,"401":1,"420":1,"428":1,"440":1,"446":1,"631":1,"671":1,"734":1,"754":1}}],["existe",{"2":{"115":1,"261":1,"320":1,"365":1,"634":1,"635":2,"636":2,"639":1,"682":1,"707":1}}],["existem",{"2":{"41":1,"49":1,"55":1,"96":1,"105":1,"235":1,"251":1,"420":1,"440":1,"447":1,"464":2,"488":1,"533":1,"555":1,"601":1,"610":1,"631":1,"644":1,"668":1,"679":1,"682":1,"719":1}}],["exige",{"2":{"550":1,"573":1,"648":1}}],["exigem",{"2":{"263":1,"455":1,"480":1,"488":1}}],["exigindo",{"2":{"556":1,"571":1}}],["exigida",{"2":{"452":1}}],["exigidas",{"2":{"328":1}}],["exigirá",{"2":{"520":1}}],["exigir",{"2":{"441":1,"726":1}}],["exigiria",{"2":{"60":1,"310":1,"355":1,"540":1}}],["exiba",{"2":{"553":1}}],["exibem",{"2":{"533":1}}],["exibe",{"2":{"244":1,"387":2,"730":1}}],["exibição",{"2":{"548":1,"550":1,"730":1}}],["exibi",{"2":{"334":1,"405":1}}],["exibindo",{"0":{"244":1},"2":{"442":1}}],["exibido",{"2":{"245":1,"531":1,"605":1}}],["exibidos",{"2":{"127":1,"128":1,"278":1,"298":1,"533":1,"730":1}}],["exibidas",{"2":{"442":1}}],["exibida",{"2":{"141":1,"167":1,"202":1,"338":1,"442":2,"548":1}}],["exibirá",{"2":{"328":1,"331":1,"568":1}}],["exibir",{"2":{"43":1,"73":1,"244":1,"245":2,"282":1,"302":1,"334":1,"336":1,"341":1,"385":1,"436":1,"554":1,"556":1,"730":1}}],["exija",{"2":{"113":1}}],["exchange",{"2":{"636":1}}],["exception",{"2":{"465":1,"467":1,"685":1}}],["exceptions",{"2":{"131":1}}],["exceto",{"2":{"424":1,"470":1,"668":1}}],["exceção",{"0":{"323":1,"369":1,"710":1},"2":{"520":1,"685":1,"710":1}}],["exceções",{"2":{"222":1,"520":1}}],["excessivamente",{"2":{"310":1,"355":1}}],["exceda",{"2":{"50":1}}],["excedente",{"2":{"231":1}}],["excedendo",{"2":{"43":1}}],["excede",{"2":{"231":1}}],["excedem",{"2":{"230":1}}],["exceder",{"2":{"43":1}}],["excluí",{"2":{"667":1}}],["exclua",{"2":{"667":1}}],["exclusivos",{"2":{"636":1}}],["exclusiva",{"2":{"636":1}}],["exclusivas",{"2":{"386":1}}],["exclusivamente",{"2":{"90":1,"99":1,"673":1}}],["excluindo",{"2":{"499":1}}],["excluir",{"2":{"35":1,"67":1,"708":1}}],["expirou",{"2":{"619":1}}],["expiram",{"2":{"638":1}}],["expirada",{"2":{"523":1}}],["expiração",{"2":{"334":2,"638":1}}],["expectativas",{"2":{"675":1,"681":1}}],["expect",{"2":{"675":1,"680":2}}],["expensive",{"2":{"573":1}}],["experimental",{"0":{"769":1},"2":{"687":1,"696":1}}],["experimentar",{"0":{"417":1},"2":{"43":1,"156":2}}],["experimente",{"2":{"418":1}}],["experimentem",{"2":{"249":1}}],["experiência",{"2":{"45":1,"131":1,"236":1,"240":1,"267":1,"288":1,"308":1,"337":2,"353":1,"541":1,"670":1,"687":1,"691":1,"695":1,"696":2,"697":1}}],["experiências",{"2":{"39":1,"687":1,"688":1,"689":1}}],["expusemos",{"2":{"407":1}}],["expulso",{"2":{"218":1}}],["expulsou",{"2":{"145":1,"170":1,"189":1,"205":1}}],["expressão",{"2":{"345":1}}],["expressar",{"2":{"46":1,"691":1}}],["exploração",{"2":{"695":1}}],["explorar",{"2":{"673":1,"737":1}}],["explorada",{"2":{"635":1}}],["explícito",{"2":{"442":1,"751":1}}],["explícitas",{"2":{"681":1}}],["explícita",{"2":{"60":1}}],["explica",{"2":{"746":1}}],["explicação",{"2":{"375":1}}],["explicitamente",{"2":{"110":1,"442":1,"479":1,"487":1,"491":1,"667":1}}],["exponha",{"0":{"424":1},"2":{"671":1}}],["exponentiation",{"2":{"390":1}}],["expomos",{"2":{"342":1}}],["expo",{"0":{"157":1,"718":1},"1":{"158":1},"2":{"132":1,"145":1,"156":2,"157":4,"158":2,"159":1,"170":1,"189":1,"205":1,"379":2,"398":1,"417":3,"435":1,"436":1,"546":2,"569":2,"605":3,"634":1,"648":2,"718":4,"733":2}}],["exporá",{"2":{"479":1}}],["expor",{"2":{"106":1,"421":1,"427":1,"434":1,"441":2,"467":1,"493":2,"693":1}}],["exportá",{"2":{"446":1}}],["exports",{"2":{"255":1,"257":1,"398":1,"399":2,"426":1,"441":1,"442":1,"576":1,"577":1,"667":1}}],["exporte",{"2":{"102":1,"217":1}}],["export",{"2":{"46":1,"53":1,"54":1,"60":1,"68":3,"92":1,"101":1,"114":2,"115":2,"116":2,"122":2,"142":3,"168":2,"223":1,"224":1,"225":1,"226":1,"227":1,"228":1,"229":1,"230":1,"231":1,"232":1,"233":1,"234":1,"239":1,"242":1,"244":1,"245":1,"261":1,"262":1,"263":1,"344":3,"345":3,"346":1,"347":1,"348":3,"349":2,"387":1,"390":3,"434":2,"441":2,"442":1,"443":3,"444":1,"457":1,"461":2,"477":1,"478":7,"479":8,"480":3,"481":1,"485":2,"488":4,"489":1,"491":1,"520":1,"548":1,"573":2,"574":2,"663":2,"668":1,"730":2,"731":1,"737":2}}],["exportando",{"0":{"463":1,"487":1,"493":1},"2":{"493":1}}],["exportado",{"2":{"457":1,"481":1}}],["exportados",{"2":{"95":1,"104":1}}],["exportadas",{"2":{"445":1,"463":2,"487":2,"493":1}}],["exportada",{"2":{"444":1}}],["exportação",{"0":{"461":1,"485":1},"2":{"344":1}}],["exportações",{"2":{"217":1,"219":1,"344":1,"663":1}}],["exportará",{"2":{"478":1}}],["exportaria",{"2":{"219":1}}],["exportaríamos",{"2":{"106":1}}],["exportar",{"0":{"454":1,"479":1},"1":{"455":1},"2":{"97":1,"106":1,"191":1,"344":2,"398":1,"399":1,"446":1,"463":1,"477":1,"478":1,"487":1}}],["exporta",{"2":{"46":1,"217":2,"478":1}}],["exposto",{"2":{"435":1,"444":1,"478":1,"628":1}}],["expostas",{"2":{"93":1,"424":1}}],["exposição",{"2":{"93":1,"102":1,"634":1}}],["expõem",{"2":{"441":1}}],["expõe",{"2":{"37":1,"441":1,"443":1,"444":1,"446":1,"448":1,"461":2,"485":2,"525":1}}],["expansão",{"0":{"708":1},"1":{"712":1,"713":1},"2":{"60":1}}],["expansível",{"2":{"12":1,"23":1}}],["expande",{"2":{"670":1}}],["expanded",{"0":{"23":1},"2":{"12":1}}],["expandir",{"2":{"262":2,"263":1,"419":1,"731":1}}],["expandido",{"2":{"12":1,"23":1}}],["expanda",{"2":{"142":2,"168":2,"203":2,"262":1}}],["exec",{"2":{"189":1,"666":1}}],["execuções",{"2":{"630":1}}],["execução",{"0":{"389":1},"2":{"46":1,"55":2,"57":1,"65":1,"69":1,"95":1,"96":1,"104":1,"105":1,"130":1,"144":1,"152":1,"169":1,"177":1,"188":1,"194":1,"204":1,"212":1,"218":2,"221":1,"255":1,"279":1,"320":1,"365":1,"386":1,"389":1,"391":1,"436":1,"438":1,"463":1,"487":2,"491":2,"493":1,"500":1,"520":1,"524":1,"525":1,"526":1,"531":3,"537":1,"556":1,"565":1,"568":1,"570":1,"596":1,"601":1,"610":1,"624":1,"644":1,"655":1,"665":1,"681":1,"699":1,"700":3,"704":1,"711":1,"716":1,"745":3}}],["execution",{"2":{"710":1}}],["executáveis",{"2":{"716":1}}],["executável",{"2":{"151":1,"176":1,"191":2,"193":1,"211":1,"389":1,"675":1}}],["executá",{"2":{"152":1,"177":1,"194":1,"212":1,"586":1,"595":1,"682":1,"711":1,"729":1}}],["executejscall",{"2":{"555":1}}],["execute",{"0":{"281":1,"282":1,"301":1,"302":1,"324":1,"325":1,"370":1,"371":1,"527":1,"600":1,"609":1,"617":1,"643":1,"721":1},"1":{"528":1,"529":1},"2":{"56":1,"95":1,"104":1,"115":1,"151":1,"152":1,"157":1,"165":1,"166":1,"168":1,"176":1,"183":1,"190":1,"193":1,"194":1,"200":1,"211":1,"212":1,"265":1,"268":1,"279":1,"281":1,"282":1,"287":1,"288":1,"299":1,"301":1,"302":1,"306":1,"309":1,"324":1,"325":1,"351":1,"354":1,"370":1,"371":1,"376":1,"377":1,"402":1,"404":1,"405":1,"406":1,"446":1,"457":1,"481":1,"525":1,"526":1,"551":1,"553":2,"567":2,"602":2,"611":2,"625":1,"626":1,"627":1,"643":1,"645":2,"651":1,"654":1,"657":1,"700":1,"703":2,"711":1,"715":1,"721":2,"734":1}}],["executa",{"2":{"111":1,"525":1,"605":1,"615":1,"671":1,"677":1,"681":1,"700":1,"726":1,"745":1}}],["executados",{"2":{"134":1,"218":1,"469":1,"656":1,"665":1,"679":1}}],["executado",{"2":{"48":1,"55":1,"73":1,"74":3,"76":1,"77":3,"111":1,"144":1,"169":1,"188":1,"204":1,"221":2,"231":1,"343":1,"389":1,"436":1,"455":1,"480":1,"491":1,"537":1,"551":1,"553":1,"555":1,"562":3,"563":1,"572":1,"573":1,"577":1,"650":1,"699":2,"702":1,"706":1,"745":2}}],["executadas",{"2":{"55":1,"545":1,"555":1,"700":1}}],["executada",{"2":{"35":1,"50":1,"111":1,"144":1,"169":1,"188":1,"204":1,"349":1,"534":1,"675":1,"690":1}}],["executam",{"2":{"46":1}}],["executando",{"0":{"150":1,"158":1,"175":1,"192":1,"195":1,"210":1,"537":1,"605":1,"623":1},"1":{"151":1,"152":1,"176":1,"177":1,"178":1,"193":1,"194":1,"196":1,"211":1,"212":1,"624":1,"625":1,"626":1,"627":1},"2":{"43":1,"56":1,"66":1,"67":1,"131":1,"142":2,"168":2,"189":1,"313":1,"358":1,"383":1,"436":1,"470":2,"555":1,"557":1,"562":1,"599":1,"602":1,"608":1,"611":1,"619":2,"625":1,"642":1,"645":1,"652":1,"682":1,"699":1,"704":1,"725":1,"726":1,"755":1,"768":1}}],["executaremos",{"2":{"470":1}}],["executará",{"2":{"56":1,"195":1,"217":1,"257":1,"389":1,"726":1}}],["executar",{"2":{"33":1,"55":1,"57":1,"63":1,"67":2,"73":2,"74":1,"77":1,"95":1,"104":1,"113":1,"114":1,"126":1,"147":2,"152":1,"172":2,"177":1,"191":1,"194":1,"195":1,"200":1,"207":2,"212":1,"254":1,"256":1,"258":1,"279":1,"281":1,"283":3,"299":1,"301":1,"303":3,"324":1,"325":2,"370":1,"371":2,"377":1,"398":1,"405":2,"418":1,"437":1,"464":1,"488":1,"491":2,"525":1,"529":1,"538":1,"545":1,"569":1,"570":2,"572":1,"576":1,"596":1,"598":1,"599":2,"600":1,"605":3,"607":1,"608":2,"609":1,"624":1,"625":2,"626":1,"627":1,"641":1,"642":1,"643":1,"654":1,"672":1,"675":2,"676":2,"677":1,"700":1,"705":1,"716":1,"745":1}}],["executou",{"2":{"35":1,"153":1,"154":1,"159":1,"178":1,"179":1,"196":1,"197":1,"213":1,"214":1,"280":1,"300":1,"322":1,"368":1}}],["exemplos",{"0":{"59":1,"239":1},"2":{"56":1,"59":1,"235":1,"239":2,"242":1,"344":1,"381":1,"520":1,"686":1,"692":1}}],["exemplo",{"0":{"53":1,"54":1,"259":1,"418":1,"421":1,"428":1,"429":1,"441":1,"690":1,"692":1},"1":{"422":1,"423":1,"424":1,"425":1,"426":1,"429":1,"430":1,"431":1,"432":1,"433":1,"434":1,"442":1,"691":1,"693":1,"694":1},"2":{"2":1,"3":1,"4":1,"6":1,"7":1,"10":1,"11":2,"14":1,"15":1,"24":1,"30":1,"34":3,"35":1,"43":1,"44":2,"46":1,"47":1,"48":1,"49":1,"50":4,"51":2,"52":2,"55":1,"56":1,"58":1,"60":2,"63":1,"67":1,"77":1,"106":1,"110":2,"111":5,"112":1,"113":1,"114":1,"116":1,"128":1,"134":1,"151":1,"159":1,"176":1,"193":1,"211":1,"217":1,"218":1,"220":1,"221":2,"223":1,"226":1,"227":1,"241":1,"242":3,"244":2,"248":1,"254":1,"256":3,"257":2,"259":3,"277":1,"279":4,"297":1,"299":4,"313":3,"317":1,"325":1,"328":2,"335":1,"337":1,"338":2,"342":2,"346":1,"348":2,"349":4,"358":3,"362":1,"371":1,"383":1,"402":2,"403":1,"404":1,"418":1,"421":1,"422":1,"426":3,"430":4,"434":1,"441":1,"444":4,"445":1,"446":1,"453":1,"454":1,"456":2,"457":1,"459":2,"461":2,"462":2,"465":1,"466":1,"470":2,"477":1,"478":2,"480":1,"481":1,"485":2,"486":1,"488":1,"490":2,"491":2,"492":1,"497":1,"501":1,"524":2,"534":3,"543":1,"545":1,"549":1,"555":1,"558":1,"559":1,"561":1,"562":1,"564":2,"565":1,"566":1,"571":1,"573":1,"595":2,"600":1,"603":1,"609":1,"612":1,"621":1,"626":1,"627":1,"629":1,"634":1,"635":1,"636":1,"643":1,"646":1,"654":1,"667":1,"668":3,"669":1,"672":1,"673":1,"675":1,"677":1,"678":1,"679":3,"680":4,"682":1,"691":1,"692":1,"695":2,"706":1,"721":1,"722":1,"725":1,"726":1,"730":1,"731":1,"742":1,"745":1}}],["edições",{"2":{"216":1,"221":1}}],["edição",{"2":{"116":1,"217":1,"218":1,"219":1,"220":1,"221":1,"441":1}}],["editing",{"2":{"239":1}}],["edita",{"2":{"221":1}}],["editando",{"2":{"219":2,"220":1,"574":2,"676":1}}],["editar",{"0":{"116":1},"2":{"116":1,"142":1,"203":1,"217":4,"270":1,"290":1,"399":1,"538":1}}],["edite",{"2":{"153":1,"178":1,"196":1,"213":1,"652":1,"653":1,"657":1,"739":1,"747":1,"748":1,"750":1,"751":1}}],["edited",{"2":{"116":2}}],["editor",{"2":{"137":1,"153":1,"164":1,"178":1,"182":1,"196":1,"199":1,"213":1,"325":1,"371":1,"416":1,"737":1}}],["edittext",{"2":{"116":4,"387":1}}],["editável",{"2":{"22":1}}],["edit",{"2":{"4":1,"547":1}}],["educados",{"2":{"10":1}}],["eslint",{"2":{"672":1,"734":1}}],["esforço",{"2":{"628":2,"639":1,"717":1}}],["esfregar",{"2":{"35":1}}],["es2016",{"2":{"465":1,"489":1}}],["es6",{"0":{"393":1}}],["esm",{"2":{"390":1}}],["esmaecidas",{"2":{"141":1,"167":1,"202":1}}],["es13",{"2":{"390":1}}],["es11",{"2":{"390":1}}],["es10",{"2":{"390":1}}],["es9",{"2":{"390":1}}],["es8",{"0":{"395":1},"2":{"390":1}}],["es7",{"0":{"394":1},"2":{"390":1}}],["esquecido",{"2":{"529":1}}],["esquerdo",{"2":{"225":1,"234":1,"551":1,"555":1}}],["esquerda",{"2":{"35":2,"224":3,"225":3,"545":1}}],["esquemas",{"2":{"635":1,"636":1}}],["esquema",{"0":{"547":1},"2":{"74":1,"330":1,"333":1,"547":2,"635":3}}],["esqueça",{"2":{"65":1,"283":1,"303":1,"441":1,"520":1,"541":1}}],["essenciais",{"2":{"386":1,"398":1}}],["essencialmente",{"2":{"421":1,"441":1,"719":1}}],["essencial",{"2":{"62":1,"446":1,"679":1}}],["esses",{"0":{"237":1},"2":{"56":1,"65":1,"74":1,"77":1,"89":1,"94":1,"98":1,"103":1,"129":2,"130":1,"141":2,"167":2,"202":2,"236":1,"237":1,"245":1,"249":1,"306":1,"320":1,"346":2,"349":1,"351":1,"365":1,"379":1,"386":2,"387":1,"389":1,"398":1,"399":2,"402":1,"407":2,"420":1,"424":1,"440":1,"490":1,"520":1,"542":1,"561":1,"571":1,"574":1,"577":2,"629":1,"671":1,"680":1,"695":1,"709":1,"726":1,"729":1}}],["esse",{"2":{"42":1,"46":1,"57":1,"64":1,"65":1,"67":2,"94":1,"103":1,"113":1,"217":2,"310":1,"318":2,"320":1,"337":2,"339":1,"355":1,"363":2,"365":1,"427":1,"443":1,"445":1,"446":1,"448":1,"478":1,"479":1,"488":1,"505":1,"520":1,"531":1,"533":1,"534":1,"544":1,"548":1,"572":1,"573":1,"608":1,"635":1,"636":1,"638":1,"651":1,"666":1,"667":2,"674":1,"677":1,"682":1,"689":1,"702":1,"737":1,"741":1}}],["essas",{"2":{"42":2,"43":1,"44":1,"55":1,"120":1,"128":1,"149":1,"231":1,"245":1,"248":1,"257":1,"270":3,"290":3,"330":2,"333":1,"386":1,"417":1,"421":1,"441":1,"442":1,"485":2,"538":1,"557":1,"572":1,"652":1,"654":1,"688":1,"706":2}}],["essa",{"2":{"35":4,"52":1,"62":1,"65":1,"111":1,"113":2,"117":1,"152":1,"177":1,"212":1,"226":1,"228":1,"234":1,"237":1,"251":1,"261":1,"329":1,"470":1,"542":1,"552":1,"556":1,"635":1,"636":1,"654":1,"681":1,"693":2,"702":1,"708":1,"723":1}}],["escopos",{"2":{"516":1}}],["escopo",{"2":{"516":1}}],["escolhida",{"2":{"704":1}}],["escolhê",{"2":{"336":1}}],["escolha",{"2":{"137":1,"149":1,"164":1,"174":1,"182":1,"185":1,"199":1,"209":1,"278":1,"298":1,"312":1,"357":1,"530":1,"549":1,"568":1,"629":1,"635":3,"680":1}}],["escolher",{"2":{"38":1,"135":1,"159":1,"336":1,"568":1,"635":1}}],["escrevê",{"2":{"682":1}}],["escrevendo",{"0":{"673":1,"674":1},"1":{"675":1},"2":{"458":1,"482":1,"677":1}}],["escreve",{"2":{"386":1,"672":1,"673":1,"674":1}}],["escreveremos",{"2":{"275":1,"295":1,"315":1,"360":1}}],["escrever",{"2":{"113":1,"156":1,"221":1,"240":1,"320":1,"336":1,"345":1,"365":1,"437":1,"442":1,"446":1,"447":1,"448":1,"451":1,"456":1,"476":1,"486":1,"532":1,"540":1,"634":1,"671":1,"673":4,"674":3,"675":1,"676":1,"678":1}}],["escritas",{"2":{"379":1}}],["escrita",{"2":{"242":1,"344":1,"390":1,"520":1,"680":1}}],["escritos",{"2":{"236":1,"241":1,"452":1,"479":1,"668":1}}],["escrito",{"2":{"77":1,"420":1,"440":1,"456":1,"675":1,"677":1}}],["escutando",{"2":{"703":1,"745":1}}],["escutar",{"2":{"74":1,"77":1}}],["escurecido",{"2":{"245":1}}],["escuridão",{"0":{"84":1}}],["escuro",{"2":{"80":1}}],["escanear",{"2":{"158":1}}],["escala",{"2":{"49":1,"63":1,"687":1}}],["escape",{"2":{"31":2,"35":1}}],["espaça",{"2":{"229":1}}],["espaçamento",{"2":{"226":1,"232":1}}],["espaçar",{"2":{"226":1,"229":1}}],["espaço",{"2":{"68":1,"134":1,"223":5,"226":5,"229":3,"231":4,"262":4,"334":1,"341":1,"497":1,"682":1,"697":1}}],["espaços",{"2":{"3":1,"503":1,"672":1}}],["espaguete",{"2":{"96":1,"105":1}}],["esperemos",{"2":{"446":1}}],["esperada",{"2":{"681":1}}],["esperados",{"2":{"106":1,"681":1}}],["esperado",{"2":{"74":1,"77":1,"265":1,"287":1,"306":1,"351":1,"445":1,"497":1,"670":1,"675":1,"678":1,"682":1}}],["esperamos",{"2":{"349":1,"683":1}}],["esperando",{"2":{"349":1,"559":1,"576":1,"683":1}}],["espera",{"2":{"349":1,"497":1,"576":1,"670":1,"672":1}}],["esperaria",{"2":{"108":1,"114":1,"445":1}}],["esperar",{"0":{"695":1},"2":{"20":1,"27":1,"42":1,"219":1,"390":1,"696":1}}],["específico",{"0":{"146":1,"171":1,"190":1,"206":1,"396":1,"456":1,"561":1},"1":{"457":1,"562":1,"563":1,"564":1,"565":1,"566":1},"2":{"76":1,"80":1,"142":2,"191":2,"257":2,"381":1,"444":1,"491":1,"531":3,"557":1,"562":1,"565":1,"726":1,"753":1}}],["específicos",{"2":{"45":1,"90":1,"99":1,"553":1,"562":1,"723":1}}],["específicas",{"0":{"565":1,"566":1},"2":{"35":1,"60":1,"77":1,"237":1,"285":1,"340":1,"561":1,"562":1,"580":1,"629":1,"708":1}}],["específica",{"0":{"68":1},"2":{"12":1,"67":1,"144":1,"146":1,"169":1,"171":1,"188":1,"190":1,"204":1,"206":1,"313":1,"358":1,"379":1,"383":1,"444":2,"657":1,"708":1,"741":1,"746":1}}],["especificando",{"0":{"625":1,"626":1,"627":1},"1":{"626":1},"2":{"595":1}}],["especificadas",{"2":{"562":1}}],["especificados",{"2":{"68":1,"231":1,"708":1}}],["especificado",{"2":{"48":1,"122":1,"424":1,"491":1}}],["especificações",{"2":{"389":1,"452":1}}],["especificação",{"2":{"8":1,"88":1,"636":1}}],["especificam",{"2":{"708":1}}],["especificamos",{"2":{"270":1,"290":1,"442":1}}],["especificamente",{"2":{"66":1,"70":1,"379":1,"381":1,"553":1}}],["especifica",{"2":{"225":1,"233":2,"478":1,"691":1}}],["especificar",{"2":{"47":1,"65":2,"80":1,"222":1,"230":1,"244":1,"257":1,"270":1,"290":1,"313":2,"330":1,"331":1,"333":1,"339":1,"358":2,"442":1,"478":1,"491":2,"519":1,"625":1,"626":1,"627":1,"666":1,"721":1,"748":1}}],["especialista",{"2":{"668":1}}],["especial",{"2":{"46":1}}],["especialmente",{"2":{"43":1,"56":1,"60":1,"413":1,"465":1,"489":1,"499":1,"502":1,"542":1,"543":1,"566":1,"570":1,"680":1,"681":1}}],["estratégia",{"2":{"334":1}}],["estruturados",{"2":{"730":1}}],["estruturada",{"2":{"52":1}}],["estruturar",{"2":{"675":1}}],["estruturando",{"0":{"675":1}}],["estruturas",{"2":{"441":2,"540":2}}],["estrutura",{"0":{"267":1,"308":1,"353":1},"2":{"74":1,"90":1,"99":1,"265":1,"287":1,"288":1,"306":1,"310":1,"313":1,"328":1,"338":1,"344":1,"351":1,"355":1,"358":2,"384":1,"387":1,"417":1,"457":1,"470":1,"481":1,"552":2,"553":1,"654":1,"655":1,"666":1,"674":1,"682":1}}],["estivesse",{"2":{"635":1,"706":1}}],["estiverem",{"2":{"110":1,"141":1,"156":1,"167":1,"202":1}}],["estiver",{"2":{"5":1,"9":1,"13":2,"32":1,"55":1,"63":1,"65":3,"66":1,"67":2,"111":1,"121":1,"131":1,"132":1,"140":1,"142":2,"145":2,"151":1,"152":1,"155":1,"159":1,"168":1,"170":2,"176":1,"177":1,"180":1,"186":1,"189":3,"190":1,"191":1,"193":1,"198":1,"200":1,"201":1,"202":1,"205":2,"211":1,"215":1,"220":1,"221":1,"224":4,"236":1,"251":1,"258":1,"259":1,"279":4,"283":1,"299":4,"303":1,"325":2,"330":1,"334":1,"338":1,"348":1,"371":2,"377":1,"382":1,"383":1,"387":1,"389":1,"402":1,"404":1,"413":1,"420":1,"435":1,"436":1,"440":1,"446":1,"447":1,"449":1,"470":2,"471":1,"474":1,"490":1,"499":1,"523":1,"531":1,"534":1,"539":1,"540":2,"545":1,"546":1,"547":1,"549":1,"554":1,"555":2,"562":1,"568":1,"569":1,"574":1,"576":1,"580":1,"583":1,"584":1,"585":1,"588":1,"595":1,"596":1,"602":2,"611":2,"615":1,"617":1,"619":1,"624":1,"645":2,"648":1,"652":1,"654":1,"658":1,"662":1,"667":1,"697":1,"702":1,"704":1,"706":1,"742":1,"747":1,"748":1}}],["esticar",{"2":{"441":1}}],["estica",{"2":{"229":1}}],["estiliza",{"2":{"387":1,"668":1}}],["estilizado",{"2":{"277":1,"297":1}}],["estilizados",{"2":{"79":1}}],["estilizar",{"2":{"74":1,"77":1,"441":1,"668":1}}],["estilo",{"0":{"340":1,"668":1},"1":{"669":1},"2":{"58":1,"108":1,"114":2,"245":1,"261":1,"262":1,"263":1,"317":1,"328":1,"339":1,"340":1,"362":1,"387":1,"445":6,"543":1,"668":4,"672":1,"695":1,"756":1}}],["estilos",{"0":{"445":1},"2":{"58":1,"217":1,"233":1,"235":1,"668":5,"681":1}}],["estendem",{"2":{"452":1}}],["estende",{"2":{"422":1,"429":1,"452":2,"732":1}}],["estendendo",{"2":{"421":1}}],["estender",{"2":{"43":1,"256":1,"398":1,"452":1,"467":1}}],["estes",{"2":{"246":1,"386":1,"701":1}}],["estejam",{"2":{"141":1,"142":1,"167":1,"168":1,"202":1,"203":1,"313":1,"330":1,"358":1,"531":1,"549":1,"603":1,"612":1,"619":1,"620":1,"646":1}}],["estejamos",{"2":{"90":1,"99":1}}],["esteja",{"2":{"43":1,"58":1,"114":1,"134":1,"142":1,"168":1,"191":1,"203":1,"270":1,"290":1,"334":1,"420":1,"440":1,"461":1,"499":1,"511":1,"524":1,"529":2,"551":1,"616":1,"634":1,"662":2,"679":2,"681":2,"701":1,"741":1,"742":2,"745":1}}],["este",{"2":{"12":1,"21":1,"35":2,"60":1,"65":2,"74":3,"77":1,"78":2,"87":1,"89":1,"95":1,"98":1,"104":1,"108":1,"111":2,"114":2,"122":1,"124":1,"130":1,"135":1,"149":1,"155":1,"174":1,"180":1,"198":1,"209":1,"215":1,"239":1,"241":1,"251":1,"258":1,"259":1,"273":1,"293":1,"325":2,"338":1,"344":2,"347":1,"358":1,"371":2,"379":1,"399":1,"402":1,"403":1,"411":1,"418":1,"420":2,"430":1,"440":2,"441":2,"442":1,"444":2,"445":1,"447":1,"452":1,"453":1,"456":1,"461":1,"464":1,"470":1,"471":1,"478":1,"485":1,"488":2,"491":2,"493":1,"495":2,"510":1,"532":1,"538":1,"546":1,"548":1,"549":1,"556":1,"559":2,"576":1,"579":1,"580":1,"581":2,"585":1,"588":1,"589":1,"590":1,"602":1,"605":1,"611":1,"619":1,"632":1,"636":1,"645":1,"648":2,"650":1,"654":1,"666":1,"678":1,"680":1,"681":1,"683":1,"691":1,"715":1,"730":1,"731":1,"734":1,"736":1,"751":1}}],["estabelecendo",{"2":{"545":1}}],["estas",{"2":{"159":1,"209":1,"332":1,"402":1,"404":1,"454":1,"459":1,"603":1,"608":1,"612":1,"646":1,"651":1,"747":1,"749":1}}],["estava",{"2":{"113":1,"555":1,"570":1}}],["estaticamente",{"2":{"96":1,"105":1,"328":1,"329":1}}],["estatísticas",{"2":{"67":1}}],["estaremos",{"2":{"741":1}}],["estarem",{"2":{"576":1}}],["estartdate",{"2":{"462":4}}],["estarão",{"2":{"120":1,"331":1}}],["estará",{"2":{"111":1,"166":1,"243":1,"283":1,"303":1,"313":1,"320":1,"358":1,"365":1,"441":1,"456":1,"478":1,"742":1,"745":1}}],["estar",{"2":{"62":1,"67":1,"69":1,"110":1,"135":1,"420":1,"440":1,"495":1,"551":1,"578":1,"618":1,"638":1,"667":1,"728":1,"739":1}}],["estamos",{"2":{"53":1,"63":1,"434":1,"544":1,"556":1}}],["estacionários",{"2":{"45":1}}],["estados",{"2":{"680":1,"681":1,"689":1,"692":2}}],["estado",{"0":{"349":1,"569":1},"2":{"10":1,"11":1,"12":2,"21":1,"34":1,"46":1,"55":2,"74":1,"90":2,"99":2,"112":1,"113":1,"129":1,"219":6,"220":2,"221":1,"242":1,"343":1,"348":1,"349":14,"417":1,"423":1,"540":1,"569":3,"630":2,"634":2,"673":2,"680":3,"689":2,"690":2,"691":4,"692":4}}],["esta",{"0":{"69":1},"2":{"3":1,"9":2,"31":1,"32":1,"33":1,"35":2,"37":1,"46":1,"58":2,"64":1,"65":1,"67":1,"70":1,"74":1,"77":2,"92":1,"106":1,"107":1,"113":1,"116":1,"122":1,"131":1,"135":1,"156":1,"191":3,"194":1,"203":1,"220":1,"233":1,"239":1,"251":2,"259":2,"265":1,"268":1,"270":2,"287":1,"288":1,"290":2,"306":1,"309":1,"311":1,"341":1,"343":1,"344":1,"351":1,"354":1,"356":1,"377":1,"402":1,"403":1,"404":1,"409":1,"413":2,"422":1,"435":1,"442":2,"444":1,"456":1,"499":1,"501":1,"509":1,"531":1,"545":2,"549":1,"554":1,"555":1,"556":1,"562":1,"582":1,"583":1,"584":1,"586":1,"587":1,"608":1,"615":1,"616":1,"628":1,"629":1,"636":1,"687":2,"690":1,"721":1,"741":1,"746":1,"747":2,"750":1}}],["estáveis",{"2":{"420":1,"440":1,"446":1,"449":1,"470":1,"474":1}}],["estável",{"2":{"144":1,"169":1,"188":1,"204":1,"420":1,"440":1,"446":1,"449":1,"470":1,"474":1}}],["estáticas",{"2":{"337":1,"407":1,"493":1,"533":1,"541":1,"670":1}}],["estática",{"0":{"328":1,"672":1},"2":{"328":1,"412":1,"493":1,"533":1,"672":2}}],["estáticos",{"0":{"329":1},"2":{"331":1}}],["estático",{"2":{"11":1,"517":1,"548":1,"559":1}}],["está",{"0":{"36":1,"596":1,"742":1},"1":{"743":1,"744":1,"745":1},"2":{"2":1,"11":1,"12":4,"20":1,"23":1,"29":1,"35":2,"36":1,"39":1,"42":1,"43":2,"46":1,"57":1,"65":2,"67":2,"73":1,"76":1,"111":1,"116":1,"122":1,"126":1,"127":1,"132":1,"156":1,"216":1,"219":2,"220":1,"235":1,"248":1,"249":1,"251":4,"254":1,"259":4,"279":1,"285":1,"299":1,"313":1,"325":2,"334":2,"344":2,"345":2,"347":1,"349":1,"358":1,"371":2,"374":1,"377":1,"386":1,"398":1,"404":1,"412":1,"413":2,"417":1,"419":1,"424":1,"436":2,"442":2,"446":1,"454":1,"457":2,"458":1,"461":2,"462":1,"463":1,"465":1,"469":1,"471":1,"477":2,"481":2,"482":1,"483":2,"485":3,"486":1,"491":1,"493":2,"497":1,"498":1,"515":1,"521":1,"529":3,"534":1,"535":1,"544":1,"545":1,"551":2,"552":1,"553":1,"555":1,"556":6,"557":3,"558":2,"559":2,"560":2,"562":2,"563":1,"569":1,"573":1,"580":1,"592":2,"596":1,"599":2,"604":1,"608":2,"613":1,"616":1,"619":1,"622":1,"628":1,"642":2,"647":1,"651":1,"654":1,"655":1,"657":2,"666":1,"668":1,"671":1,"672":1,"673":1,"675":4,"676":2,"677":3,"680":1,"682":3,"683":1,"687":3,"690":1,"695":1,"703":1,"706":1,"711":2,"734":1,"741":1,"742":3,"745":2,"747":1,"751":1}}],["estão",{"0":{"408":1},"1":{"409":1,"410":1,"411":1,"412":1,"413":1},"2":{"2":1,"15":1,"24":1,"38":1,"50":1,"119":2,"219":1,"236":1,"240":1,"270":1,"290":1,"320":1,"328":1,"330":1,"335":1,"337":1,"349":1,"365":1,"391":1,"420":1,"440":1,"469":1,"499":1,"504":1,"523":1,"531":1,"551":1,"576":2,"596":1,"655":1,"663":1,"676":1,"682":1,"696":1,"700":1,"706":1,"725":1,"729":1,"730":1}}],["eliminação",{"2":{"534":1}}],["elimina",{"0":{"542":1},"2":{"509":1,"741":1}}],["eliminadas",{"2":{"464":1}}],["else",{"2":{"74":4,"77":4,"259":3,"279":1,"467":2,"489":1,"521":1}}],["eletrônico",{"2":{"635":1}}],["electron",{"2":{"379":1}}],["eles",{"2":{"38":1,"65":1,"68":1,"74":1,"90":1,"94":1,"95":1,"96":2,"97":2,"99":1,"103":1,"104":1,"105":2,"106":2,"119":1,"156":1,"218":2,"243":1,"245":1,"246":1,"313":1,"358":1,"379":1,"420":2,"421":2,"440":2,"441":2,"446":1,"449":1,"462":1,"464":1,"470":2,"474":1,"486":1,"488":1,"504":1,"505":1,"506":1,"509":1,"520":1,"538":1,"561":1,"577":1,"629":1,"676":1,"677":1,"679":3,"680":2,"681":1,"682":3,"687":1}}],["ele",{"2":{"11":1,"12":1,"13":1,"34":1,"47":1,"50":1,"57":2,"58":1,"60":1,"62":1,"101":1,"115":2,"200":1,"221":1,"233":1,"234":1,"242":2,"249":1,"252":2,"254":1,"259":2,"276":1,"279":1,"282":1,"296":1,"299":1,"302":1,"316":1,"339":1,"345":1,"348":1,"349":3,"361":1,"381":1,"405":1,"442":1,"446":1,"454":1,"456":3,"458":1,"477":1,"479":1,"482":1,"488":1,"491":3,"497":1,"508":1,"511":1,"516":3,"525":1,"534":1,"543":1,"545":2,"547":1,"567":1,"568":1,"635":1,"636":3,"638":1,"648":2,"650":1,"651":1,"671":1,"674":1,"675":1,"680":1,"681":1,"682":1,"691":1,"692":2,"694":1,"699":1,"720":1,"723":1,"726":2}}],["elementos",{"2":{"2":1,"14":3,"15":2,"24":2,"28":1,"74":1,"230":1,"313":2,"344":2,"345":1,"349":1,"358":2,"385":1,"428":1,"682":1,"730":2,"731":1}}],["elemento",{"2":{"2":2,"3":3,"4":2,"11":14,"12":5,"15":1,"20":1,"21":1,"22":1,"23":1,"24":1,"25":1,"26":3,"27":1,"29":1,"31":1,"32":1,"33":1,"34":12,"62":1,"223":1,"225":2,"232":2,"233":3,"234":5,"251":5,"337":1,"344":2,"347":1,"349":1,"385":1,"531":1,"568":1,"682":1}}],["elas",{"2":{"41":1,"46":1,"94":1,"103":1,"236":1,"442":1,"652":1,"665":1}}],["ela",{"2":{"2":1,"57":1,"106":1,"251":1,"252":1,"283":1,"303":1,"334":1,"338":1,"341":1,"511":1,"580":1,"651":1,"676":1,"690":1}}],["emitindo",{"2":{"490":1}}],["emitir",{"2":{"427":1,"479":1}}],["emitirão",{"2":{"56":1}}],["emit",{"2":{"466":2}}],["emreacttag`",{"2":{"444":1}}],["emrc5utvaaaaabjru5erkjggg==",{"2":{"333":1}}],["emmynativeview",{"2":{"444":1}}],["emular",{"2":{"147":1,"172":1,"207":1}}],["emulators",{"2":{"529":1}}],["emulator",{"2":{"142":1,"168":1,"599":2,"608":2,"642":2}}],["emuladores",{"2":{"38":1,"126":2,"279":1,"299":1}}],["emulador",{"2":{"38":3,"65":2,"74":2,"152":1,"156":1,"177":1,"212":1,"279":1,"299":1,"436":1,"529":2,"570":1,"682":1,"745":1}}],["empty",{"2":{"680":1}}],["emptylist",{"2":{"456":1}}],["empresa",{"2":{"665":1}}],["empresas",{"2":{"379":1}}],["empacotar",{"2":{"648":1}}],["empacotada",{"2":{"662":1}}],["empacotadas",{"2":{"328":1}}],["empacotados",{"2":{"420":1,"440":1}}],["empacotado",{"2":{"320":2,"365":2}}],["empacotadores",{"2":{"151":1,"176":1,"193":1,"211":1}}],["empacotador",{"0":{"281":1,"301":1,"324":1,"370":1},"2":{"139":1,"273":1,"280":1,"293":1,"300":1,"320":1,"322":1,"328":3,"365":1,"368":1,"405":1,"436":1,"458":1,"482":1,"516":1,"566":2,"619":1,"702":2}}],["empacotamento",{"2":{"224":4,"595":1,"736":1}}],["empurrar",{"2":{"545":1}}],["empurra",{"2":{"60":1}}],["embutidos",{"0":{"575":1},"2":{"578":1}}],["emblema",{"2":{"128":1,"561":1}}],["embora",{"2":{"60":1,"94":1,"103":1,"106":1,"135":1,"137":1,"156":1,"164":1,"182":1,"199":1,"349":2,"389":1,"446":1,"458":1,"461":1,"482":1,"485":1,"628":1,"635":1,"680":1,"695":2,"728":1}}],["embeddedframework",{"2":{"722":2}}],["embedded",{"2":{"10":1}}],["email",{"2":{"35":1}}],["em",{"0":{"42":1,"58":1,"69":1,"132":1,"195":1,"508":1,"511":1,"523":1,"537":1,"656":1,"702":1,"735":1,"742":1,"746":1,"752":1},"1":{"43":1,"44":1,"196":1,"703":1,"704":1,"743":1,"744":1,"745":1,"747":1,"748":1,"753":1,"754":1,"755":1,"756":1,"757":1,"758":1,"759":1,"760":1,"761":1,"762":1,"763":1,"764":1,"765":1,"766":1,"767":1,"768":1,"769":1},"2":{"0":1,"2":2,"3":1,"5":1,"10":1,"13":1,"14":1,"15":1,"16":1,"17":1,"18":1,"27":1,"31":2,"33":1,"35":1,"37":2,"38":4,"39":6,"42":4,"43":3,"45":2,"46":6,"47":1,"48":4,"49":1,"50":7,"51":3,"55":6,"56":3,"57":2,"58":1,"59":1,"60":2,"62":2,"63":1,"64":1,"65":5,"67":4,"68":4,"69":1,"70":1,"73":1,"74":4,"75":1,"76":1,"77":4,"78":1,"79":1,"82":1,"83":1,"84":1,"86":2,"89":3,"92":4,"93":3,"94":2,"95":3,"96":3,"97":2,"98":3,"101":6,"102":3,"103":2,"104":3,"105":3,"106":4,"110":4,"111":9,"112":3,"113":6,"115":3,"116":2,"117":1,"118":1,"119":2,"121":1,"122":1,"126":2,"127":2,"128":2,"129":1,"130":1,"131":1,"133":1,"134":1,"135":1,"140":1,"141":2,"142":6,"143":1,"144":3,"145":1,"147":1,"149":5,"151":1,"152":3,"156":5,"158":1,"159":2,"165":2,"166":6,"167":2,"168":5,"169":3,"170":1,"172":1,"174":4,"176":1,"177":2,"183":2,"184":1,"188":3,"189":1,"193":1,"194":3,"195":1,"200":3,"201":1,"202":2,"203":14,"204":3,"205":1,"207":1,"209":5,"211":1,"212":3,"216":2,"218":3,"219":1,"220":2,"221":1,"222":4,"225":1,"226":2,"227":1,"228":1,"229":1,"230":2,"231":1,"233":3,"234":4,"236":2,"238":1,"239":3,"241":1,"243":1,"244":4,"245":4,"246":1,"248":1,"250":1,"251":4,"252":2,"254":2,"255":4,"256":3,"258":2,"259":4,"261":2,"262":2,"265":2,"268":1,"270":2,"271":3,"272":2,"273":1,"275":1,"276":1,"277":1,"278":1,"279":7,"280":1,"283":1,"287":2,"288":1,"290":2,"291":3,"292":2,"293":1,"295":1,"296":1,"297":1,"298":1,"299":7,"300":1,"303":1,"306":3,"309":1,"313":3,"315":1,"316":1,"317":1,"318":1,"320":7,"322":1,"323":1,"325":1,"328":7,"329":3,"331":2,"333":1,"334":3,"336":1,"337":1,"338":4,"339":2,"341":1,"343":1,"344":2,"345":1,"347":3,"348":3,"349":5,"351":3,"354":1,"358":3,"360":1,"361":1,"362":1,"363":1,"365":7,"368":1,"369":1,"371":1,"374":1,"375":1,"376":2,"377":1,"379":2,"381":1,"385":1,"386":2,"389":2,"390":1,"391":1,"398":1,"399":2,"400":4,"402":7,"403":1,"404":3,"405":1,"406":1,"407":1,"409":2,"413":3,"417":2,"418":1,"419":1,"420":2,"421":2,"423":1,"424":7,"426":1,"427":2,"430":4,"434":3,"436":4,"438":2,"439":1,"440":2,"441":6,"442":2,"443":3,"445":1,"446":2,"447":2,"448":4,"451":2,"452":2,"453":2,"454":5,"455":1,"456":7,"457":3,"458":1,"459":4,"462":4,"463":5,"464":7,"465":3,"466":5,"469":2,"470":1,"471":2,"473":1,"476":3,"477":1,"478":3,"479":5,"480":1,"481":3,"482":1,"483":6,"486":4,"487":5,"488":7,"489":1,"490":5,"491":5,"493":4,"495":1,"497":5,"500":2,"501":6,"502":1,"503":4,"505":1,"506":1,"507":2,"509":1,"510":2,"511":1,"516":3,"520":3,"521":1,"522":1,"523":2,"524":2,"525":3,"526":3,"527":2,"531":11,"532":3,"533":2,"534":2,"535":1,"537":1,"538":2,"541":4,"542":2,"543":2,"544":3,"545":3,"546":1,"547":2,"548":1,"549":11,"551":4,"552":3,"553":3,"554":3,"555":1,"556":3,"557":1,"560":1,"561":2,"562":7,"565":3,"566":2,"567":3,"568":5,"570":2,"576":3,"577":1,"580":1,"583":1,"584":1,"585":1,"595":2,"596":3,"598":1,"599":1,"601":2,"602":1,"603":3,"604":1,"605":4,"607":1,"608":3,"610":2,"611":1,"612":2,"613":1,"615":2,"616":2,"617":3,"618":1,"619":1,"622":1,"624":2,"625":1,"626":1,"628":1,"629":2,"630":2,"633":1,"634":2,"635":2,"636":2,"637":3,"638":2,"639":3,"641":1,"642":1,"644":2,"645":1,"646":2,"647":1,"648":2,"650":2,"652":5,"654":3,"655":1,"656":3,"657":1,"658":3,"665":1,"666":2,"668":5,"669":1,"670":2,"671":2,"672":2,"673":4,"674":1,"675":3,"677":6,"678":4,"679":2,"681":8,"682":6,"685":2,"687":3,"690":4,"691":2,"692":5,"693":4,"695":2,"696":1,"697":2,"699":4,"703":1,"706":5,"708":2,"709":1,"710":1,"711":2,"716":2,"718":1,"721":1,"722":2,"725":1,"726":2,"728":2,"730":2,"735":1,"736":1,"737":1,"740":1,"742":2,"744":1,"745":10,"746":2,"747":2,"748":1}}],["e",{"0":{"89":1,"95":1,"98":1,"104":1,"114":1,"118":1,"128":1,"155":1,"180":1,"183":1,"198":1,"215":1,"221":1,"231":1,"232":1,"233":1,"234":1,"246":1,"260":1,"284":1,"304":1,"326":1,"372":1,"384":1,"385":1,"419":2,"523":1,"566":1,"571":1,"575":1,"578":1,"595":1,"617":1,"635":1,"636":1,"689":1,"691":1,"736":1,"766":1},"1":{"90":1,"91":1,"92":1,"93":1,"94":1,"95":1,"96":2,"97":2,"99":1,"100":1,"101":1,"102":1,"103":1,"104":1,"105":2,"106":2,"107":1,"108":1,"109":1,"110":1,"111":1,"115":1,"233":1,"234":1,"235":1,"261":1,"262":1,"263":1,"385":1,"386":1,"387":1,"572":1,"573":1,"574":1,"575":1,"576":1,"577":1,"578":1,"767":1,"768":1},"2":{"0":3,"2":2,"8":1,"9":1,"10":1,"11":2,"13":3,"14":2,"15":1,"16":1,"17":1,"18":1,"20":1,"24":1,"27":2,"30":5,"34":2,"35":10,"37":2,"38":2,"39":2,"41":2,"44":1,"45":3,"46":8,"47":4,"48":6,"50":4,"51":4,"52":3,"53":3,"55":1,"56":2,"57":3,"58":1,"60":5,"62":1,"63":1,"64":2,"65":5,"66":1,"67":7,"68":3,"69":2,"70":1,"71":1,"74":5,"76":1,"77":8,"78":1,"80":2,"82":2,"83":1,"89":3,"90":3,"92":1,"93":1,"94":1,"95":4,"96":2,"97":1,"98":3,"99":3,"101":2,"102":1,"103":1,"104":4,"105":2,"106":2,"107":2,"108":1,"110":2,"111":11,"112":5,"113":4,"114":1,"115":2,"116":2,"117":3,"120":6,"121":1,"123":1,"126":2,"127":1,"128":4,"129":1,"130":2,"131":4,"133":1,"134":4,"135":2,"137":1,"139":1,"141":2,"142":10,"143":2,"144":2,"148":1,"149":4,"151":1,"153":1,"154":1,"156":5,"158":1,"159":2,"164":1,"165":1,"166":1,"167":2,"168":10,"169":2,"173":1,"174":4,"176":1,"178":1,"179":1,"182":1,"183":1,"184":1,"185":2,"186":2,"188":2,"190":1,"191":3,"193":1,"196":2,"197":1,"199":1,"200":3,"202":2,"203":13,"204":2,"208":1,"209":5,"211":1,"213":1,"214":1,"216":1,"217":5,"218":3,"219":2,"220":3,"221":2,"222":1,"223":3,"225":7,"226":4,"228":1,"229":1,"230":1,"231":3,"232":3,"234":3,"236":1,"237":1,"239":1,"240":1,"241":1,"242":2,"244":3,"245":2,"246":1,"247":1,"249":2,"250":1,"251":3,"252":2,"255":1,"256":2,"257":3,"258":1,"259":4,"260":1,"261":4,"262":4,"265":2,"267":1,"268":3,"270":2,"273":1,"276":1,"279":7,"280":1,"282":2,"283":2,"284":1,"287":2,"288":4,"290":2,"293":1,"296":1,"299":7,"300":1,"302":2,"303":2,"304":1,"306":2,"308":1,"309":3,"310":2,"312":1,"313":1,"316":1,"318":1,"320":3,"321":2,"322":1,"325":3,"326":1,"328":8,"329":1,"333":2,"334":2,"336":1,"337":1,"338":3,"339":3,"342":1,"344":3,"345":2,"346":3,"347":4,"348":4,"349":7,"351":2,"353":1,"354":3,"355":2,"357":1,"358":2,"361":1,"363":1,"365":3,"366":2,"368":1,"371":3,"372":1,"374":4,"375":2,"376":2,"377":1,"379":6,"381":4,"382":1,"384":4,"385":2,"386":5,"387":4,"397":1,"398":2,"399":1,"401":1,"402":4,"403":3,"404":5,"405":3,"406":1,"407":2,"409":1,"412":1,"413":1,"414":2,"415":2,"416":1,"417":8,"419":5,"420":5,"421":3,"424":4,"426":1,"427":1,"429":2,"430":4,"431":2,"437":2,"438":1,"439":1,"440":5,"441":5,"442":11,"443":1,"444":1,"445":2,"446":2,"448":1,"449":2,"451":1,"452":3,"454":4,"455":2,"456":6,"457":1,"458":2,"459":5,"461":1,"462":1,"463":2,"464":8,"465":12,"467":26,"469":1,"470":4,"471":3,"473":1,"474":2,"476":1,"477":3,"478":2,"479":4,"480":3,"481":1,"482":2,"483":4,"485":1,"486":2,"487":1,"488":7,"489":4,"490":4,"491":4,"492":3,"493":7,"497":1,"499":3,"503":1,"505":3,"506":1,"509":1,"510":1,"512":2,"513":1,"514":2,"516":2,"521":1,"522":7,"525":3,"526":1,"527":1,"529":1,"530":1,"531":7,"532":5,"533":4,"534":6,"535":2,"537":2,"538":1,"540":3,"541":6,"542":1,"543":2,"544":1,"545":5,"546":1,"547":2,"548":2,"549":7,"551":4,"552":4,"553":5,"554":1,"555":6,"556":2,"557":1,"559":2,"560":1,"561":3,"562":4,"563":1,"565":1,"566":3,"567":2,"568":3,"569":2,"571":3,"572":3,"573":1,"574":2,"576":5,"578":2,"581":1,"585":1,"587":1,"595":6,"596":2,"598":2,"599":2,"600":2,"602":1,"603":3,"604":1,"605":1,"607":2,"608":2,"609":2,"611":1,"612":4,"613":1,"615":3,"616":3,"617":1,"618":1,"619":3,"620":1,"621":1,"622":1,"628":2,"629":3,"630":2,"631":1,"632":1,"633":2,"634":5,"635":5,"636":6,"637":1,"638":3,"639":3,"641":2,"642":1,"643":2,"645":1,"646":4,"647":1,"648":1,"650":1,"651":1,"652":3,"653":1,"654":3,"655":1,"656":2,"657":1,"658":1,"660":2,"662":1,"663":1,"666":5,"668":2,"669":1,"670":2,"671":3,"672":2,"673":4,"674":1,"675":2,"676":1,"677":3,"678":3,"679":7,"680":5,"681":8,"682":9,"683":1,"685":14,"686":1,"687":1,"688":1,"689":5,"690":7,"691":6,"693":6,"694":1,"695":7,"696":2,"697":2,"698":1,"699":1,"700":3,"703":1,"706":2,"708":5,"711":2,"717":1,"718":2,"719":1,"722":1,"725":2,"726":3,"728":1,"729":1,"730":4,"731":9,"732":1,"733":1,"734":1,"735":1,"737":2,"739":1,"740":2,"741":1,"742":1,"745":1,"747":2,"748":2,"750":1,"751":1,"753":1,"756":1,"762":1,"767":1,"768":1}}],["típicos",{"2":{"693":1,"719":1}}],["título",{"2":{"11":1,"34":1}}],["txt",{"2":{"685":1}}],["túnel",{"2":{"619":1}}],["t",{"2":{"467":4,"491":3}}],["tsc",{"2":{"734":1,"736":1}}],["tsconfig",{"2":{"734":5,"739":6}}],["ts",{"2":{"399":1,"531":1,"733":1,"739":1}}],["tsxmynativeview",{"2":{"444":1}}],["tsxmapview",{"2":{"443":1}}],["tsxmodule",{"2":{"255":1}}],["tsxconst",{"2":{"113":2,"344":3,"349":2,"464":3,"465":1,"481":2,"488":3,"489":1}}],["tsximport",{"2":{"46":1,"92":1,"101":1,"114":1,"115":1,"116":1,"122":1,"225":1,"226":1,"227":1,"228":1,"229":1,"230":1,"231":1,"232":1,"233":1,"234":1,"255":1,"257":1,"344":1,"345":1,"348":1,"349":2,"434":1,"461":1,"466":1,"481":2}}],["tsx",{"2":{"2":1,"3":1,"8":1,"10":1,"113":1,"153":1,"178":1,"196":1,"213":1,"244":1,"349":2,"399":1,"426":2,"427":2,"434":2,"441":6,"442":8,"443":3,"444":3,"445":2,"461":1,"573":2,"733":1,"734":1,"737":2,"739":2}}],["tão",{"2":{"283":1,"303":1,"407":1,"673":1,"700":1}}],["tê",{"2":{"270":1,"290":1}}],["têm",{"2":{"38":1,"42":1,"43":1,"44":1,"45":1,"76":1,"261":1,"386":1,"509":1,"555":1,"556":1,"635":1,"677":1,"681":1,"693":1}}],["tcp",{"2":{"133":2,"522":1,"570":2,"599":2,"602":2,"611":2,"645":2}}],["técnica",{"2":{"509":1,"638":1,"741":1}}],["técnicas",{"2":{"89":1,"95":1,"98":1,"104":1}}],["término",{"2":{"48":1,"531":2}}],["tutoriais",{"2":{"415":1,"419":1}}],["tugger",{"2":{"345":3}}],["tum",{"2":{"345":3}}],["turboreactpackages",{"2":{"456":1}}],["turboreactpackage",{"2":{"456":4}}],["turbo",{"2":{"420":1,"440":1,"446":1,"449":1,"470":1,"474":1}}],["turbomodules",{"0":{"419":1},"2":{"462":1,"463":3,"464":1,"479":1,"486":1,"487":1,"488":1}}],["turbomodule",{"2":{"313":1}}],["turned",{"2":{"135":1}}],["turquoise",{"2":{"88":1}}],["tudo",{"0":{"337":1},"2":{"50":1,"56":1,"57":1,"152":1,"159":1,"177":1,"212":2,"245":1,"268":1,"276":1,"283":1,"288":1,"296":1,"303":1,"309":1,"316":1,"336":1,"344":1,"354":1,"361":1,"387":1,"534":1,"603":1,"612":1,"617":1,"624":1,"646":1,"679":1,"683":1,"746":1}}],["tvos",{"0":{"75":1},"1":{"76":1,"77":1,"78":1},"2":{"75":1,"76":2,"77":6,"379":1,"514":1}}],["tveventhandler",{"2":{"74":11,"77":11}}],["tv",{"0":{"71":1,"72":1},"1":{"72":1,"73":2,"74":2,"75":1,"76":1,"77":1,"78":1},"2":{"71":3,"73":7,"74":10,"76":6,"77":17,"514":2,"754":1}}],["twirl",{"2":{"48":1}}],["tópicos",{"2":{"555":1}}],["tópico",{"2":{"42":1,"387":1,"555":2,"648":1,"673":1}}],["that",{"2":{"430":5,"690":2}}],["thank",{"2":{"349":3}}],["thirdname",{"2":{"345":4}}],["third",{"2":{"313":3}}],["thistle",{"2":{"88":1}}],["this",{"2":{"37":1,"47":1,"50":2,"54":1,"56":2,"58":2,"60":6,"74":8,"77":8,"92":4,"101":2,"244":5,"245":6,"278":4,"279":7,"298":4,"299":7,"320":1,"328":2,"358":1,"365":1,"390":2,"402":6,"427":7,"429":3,"430":2,"431":3,"433":2,"442":1,"443":5,"444":4,"445":1,"456":2,"468":2,"534":1,"544":1,"573":3}}],["throwable",{"2":{"465":5,"467":1}}],["throw",{"2":{"257":1,"390":1,"576":1}}],["threads",{"2":{"555":2,"556":1}}],["threading",{"0":{"469":1,"491":1},"1":{"492":1,"493":1},"2":{"455":1,"480":1}}],["thread",{"0":{"341":1,"534":1,"535":1,"541":2,"542":1,"543":1,"560":1},"2":{"46":1,"56":2,"63":2,"92":2,"96":1,"101":2,"105":1,"111":2,"341":2,"469":3,"487":2,"491":4,"499":1,"508":1,"534":7,"535":5,"537":1,"538":1,"541":3,"545":8,"551":3,"555":12,"556":2,"557":1,"559":2,"560":4,"700":1}}],["theirs",{"2":{"722":2}}],["then",{"2":{"520":2,"548":1,"668":2,"748":1}}],["there",{"2":{"313":1,"358":1,"529":1}}],["themedreactcontext",{"2":{"423":2,"431":4}}],["theme=",{"2":{"279":1,"299":1}}],["theme",{"2":{"217":2,"279":2,"299":2}}],["the",{"2":{"5":1,"60":1,"65":1,"68":1,"122":2,"244":2,"245":2,"256":4,"313":5,"358":4,"431":2,"457":1,"481":1,"520":2,"524":1,"529":1,"638":1,"675":1,"680":3,"731":1}}],["type=",{"2":{"387":1}}],["types",{"2":{"442":1,"734":6}}],["typesafety",{"2":{"313":1}}],["typescript",{"0":{"732":1,"733":1,"734":1,"735":1,"736":1,"737":1,"739":1},"1":{"733":1,"734":1,"735":1,"736":1,"737":1,"738":1,"739":1},"2":{"56":1,"379":1,"390":1,"426":1,"461":1,"485":1,"672":1,"732":2,"733":4,"734":5,"735":3,"736":4,"737":1,"738":4,"739":2,"755":1}}],["type",{"2":{"46":3,"122":1,"134":2,"224":2,"225":2,"226":2,"227":2,"228":3,"229":2,"230":2,"231":2,"232":2,"233":3,"234":2,"242":1,"259":4,"348":1,"349":1,"387":1,"390":1,"398":1,"467":1,"519":1,"520":1,"737":1}}],["typeviewclicked",{"2":{"37":1}}],["typeviewfocused",{"2":{"37":2}}],["typewindowstatechanged",{"2":{"37":1}}],["tiny",{"2":{"731":1}}],["tiles",{"2":{"692":3}}],["tileslider",{"2":{"692":2}}],["tid",{"2":{"531":1}}],["tivemos",{"2":{"442":1,"741":1}}],["tiverem",{"2":{"374":1,"509":1}}],["tiver",{"2":{"6":1,"31":1,"33":1,"63":1,"67":1,"134":1,"148":1,"156":1,"173":1,"208":1,"218":1,"262":2,"328":1,"345":1,"375":1,"377":1,"448":1,"540":1,"565":1,"571":1,"580":1,"586":1,"602":1,"611":1,"617":1,"619":1,"626":1,"635":1,"645":1,"651":1,"675":1,"676":1,"679":1,"711":1,"716":1,"731":1,"736":1}}],["tirar",{"2":{"638":1}}],["tiramisu",{"2":{"142":2,"149":1,"168":2,"174":1,"203":2,"209":1}}],["tiro",{"2":{"258":1}}],["title",{"2":{"349":1,"488":5,"489":1,"511":1,"520":2,"730":3}}],["title=",{"2":{"244":5,"349":3,"457":1,"481":1,"680":1,"737":2}}],["titletext",{"2":{"54":2}}],["timing",{"2":{"46":1,"47":2,"48":1,"51":2,"56":1,"551":1}}],["time=10",{"2":{"553":1}}],["timeout",{"2":{"256":2,"392":1}}],["time",{"2":{"68":1,"445":1,"462":1,"553":1}}],["timers",{"2":{"763":1}}],["timer",{"2":{"11":2,"34":2}}],["timespetted",{"2":{"349":1}}],["timestamp",{"2":{"251":1}}],["times",{"2":{"10":1}}],["tipos",{"0":{"462":1,"486":1},"2":{"27":1,"37":1,"41":1,"44":1,"46":1,"47":1,"66":1,"236":1,"243":1,"329":2,"349":1,"385":2,"387":1,"424":5,"442":2,"452":1,"459":1,"461":1,"462":3,"479":1,"483":1,"485":1,"486":2,"595":4,"635":1,"674":1,"682":1,"693":1,"729":1,"734":1}}],["tipo",{"2":{"12":1,"13":1,"20":1,"21":1,"22":1,"23":1,"24":1,"25":1,"26":1,"27":1,"28":1,"29":1,"35":1,"37":1,"47":1,"96":1,"105":1,"123":1,"234":1,"242":1,"245":1,"342":1,"344":2,"349":2,"422":3,"424":7,"442":2,"452":1,"454":1,"461":5,"462":1,"464":2,"479":2,"480":2,"485":6,"486":2,"488":3,"499":1,"500":1,"501":1,"502":1,"503":1,"541":1,"629":1,"672":2,"678":1,"681":1,"732":1,"734":1,"736":1,"737":1}}],["triagem",{"2":{"660":1}}],["triângulo",{"2":{"149":1,"174":1,"209":1}}],["trocar",{"2":{"636":1}}],["troca",{"2":{"636":1}}],["trocado",{"2":{"636":1}}],["trecho",{"2":{"453":1,"466":1}}],["tree",{"2":{"417":1,"569":1}}],["try",{"2":{"390":1,"462":2,"465":3,"467":2,"488":1,"489":1,"520":2}}],["trás",{"2":{"343":1,"497":1,"572":1}}],["tráfego",{"0":{"273":1,"293":1},"2":{"273":3,"293":3,"520":1}}],["truques",{"2":{"50":1}}],["true",{"2":{"2":3,"3":1,"5":1,"8":1,"14":2,"35":1,"46":1,"47":1,"48":3,"49":1,"51":1,"53":1,"54":2,"56":5,"60":2,"251":4,"252":3,"259":9,"268":1,"273":1,"279":1,"288":1,"293":1,"299":1,"309":1,"323":1,"337":1,"349":5,"354":1,"365":1,"367":1,"369":1,"390":2,"455":3,"499":1,"520":1,"541":1,"573":1,"577":1,"656":2,"657":1,"662":1,"748":2}}],["três",{"2":{"39":1,"111":1,"389":1,"441":1}}],["traz",{"2":{"691":1,"694":1}}],["trazê",{"2":{"687":1}}],["tracing",{"2":{"554":1}}],["traceevents",{"2":{"531":1}}],["trace",{"2":{"392":1,"531":1,"553":1,"559":1}}],["travada",{"0":{"711":1},"1":{"712":1,"713":1}}],["trava",{"2":{"675":1,"711":1}}],["travar",{"2":{"259":2}}],["travará",{"2":{"258":1}}],["travessia",{"2":{"560":1}}],["travessias",{"2":{"499":1}}],["traversals",{"2":{"555":1}}],["trailing",{"2":{"390":1}}],["tranquila",{"2":{"267":1,"288":1,"308":1,"353":1}}],["transitiva",{"2":{"667":2}}],["transitivas",{"0":{"667":1}}],["transição",{"2":{"471":1,"534":2,"545":4,"548":1,"692":3}}],["transições",{"0":{"545":1},"2":{"55":1,"534":1,"535":1,"541":1,"691":2,"692":4}}],["transferidos",{"2":{"687":1}}],["transferência",{"2":{"619":1}}],["transformer",{"2":{"531":2,"577":1}}],["transformados",{"2":{"736":1}}],["transformado",{"2":{"559":1,"660":1}}],["transformador",{"0":{"531":1}}],["transformadores",{"0":{"390":1},"2":{"390":1}}],["transformará",{"2":{"685":1}}],["transformar",{"2":{"151":1,"176":1,"193":1,"211":1,"670":1}}],["transformação",{"2":{"58":2,"390":1}}],["transformações",{"2":{"46":1,"390":2,"499":1}}],["transformation",{"2":{"57":1}}],["transform",{"2":{"50":1,"54":1,"58":1,"538":2,"543":1,"577":1}}],["translúcida",{"2":{"541":1}}],["translate",{"2":{"242":1}}],["translatex",{"2":{"54":1}}],["translatey",{"2":{"50":1,"54":1}}],["transportes",{"0":{"709":1}}],["transporte",{"0":{"323":1,"369":1},"2":{"331":1}}],["transport",{"2":{"259":6,"323":1,"369":1,"520":1}}],["transparente",{"2":{"338":1,"542":1,"741":1}}],["transparent",{"0":{"87":1}}],["transmissão",{"2":{"256":1,"259":2,"636":1}}],["transmitido",{"2":{"464":1,"488":1}}],["transmitidas",{"2":{"329":1}}],["transmitida",{"2":{"259":1}}],["transmitir",{"2":{"45":1,"47":1,"90":1,"99":1}}],["transmite",{"2":{"47":1}}],["transversal",{"2":{"224":1,"227":3,"229":2}}],["transações",{"2":{"45":1}}],["traduza",{"2":{"681":1}}],["traduzi",{"2":{"685":1}}],["traduzir",{"0":{"542":1}}],["traduzida",{"2":{"2":1,"242":1}}],["traduz",{"2":{"242":1}}],["tradução",{"2":{"143":1,"675":1}}],["trabalha",{"2":{"458":1,"482":1,"676":1}}],["trabalhando",{"2":{"111":1,"534":1,"560":1,"687":1}}],["trabalhamos",{"2":{"95":1,"104":1}}],["trabalhará",{"2":{"387":1}}],["trabalhar",{"2":{"52":1,"238":1,"245":1,"258":1,"284":1,"304":1,"326":1,"344":1,"372":1,"437":1,"442":1,"448":1,"608":1,"737":1}}],["trabalhos",{"2":{"665":1}}],["trabalhoso",{"2":{"337":1}}],["trabalho",{"0":{"541":1,"559":1},"2":{"63":1,"65":1,"68":1,"414":2,"417":2,"435":1,"469":2,"490":1,"533":2,"534":2,"537":1,"540":1,"541":1,"544":1,"551":1,"556":3,"558":1,"560":1,"673":1,"687":2,"693":1,"694":1,"697":2,"700":1,"726":1}}],["tratar",{"2":{"464":1,"488":1}}],["tratada",{"2":{"685":1}}],["tratadas",{"2":{"245":1}}],["tratados",{"0":{"129":1},"2":{"129":1,"735":1}}],["tratado",{"2":{"11":6,"34":4,"96":1,"105":1,"444":1,"464":2,"523":1}}],["tratamento",{"0":{"242":1},"2":{"74":1,"77":1,"115":1,"464":1,"488":1,"700":1,"753":1}}],["trata",{"2":{"35":1}}],["tohavelength",{"2":{"680":1}}],["tobe",{"2":{"675":1}}],["tokens",{"2":{"630":1,"632":1,"634":1,"635":1,"636":1}}],["token",{"2":{"629":1,"636":2}}],["toggle",{"2":{"568":2}}],["togglebutton",{"2":{"11":1}}],["toast",{"2":{"526":1}}],["toastexample",{"2":{"466":1}}],["tostring",{"2":{"431":1,"434":1,"467":2}}],["toscaletype",{"2":{"424":2}}],["toint",{"2":{"431":1}}],["tomar",{"2":{"681":1}}],["tomato",{"2":{"88":1}}],["tome",{"2":{"675":1}}],["tomou",{"2":{"635":1}}],["tomutablelist",{"2":{"402":1,"456":1}}],["totalcostlimit",{"2":{"342":1}}],["total",{"2":{"231":1,"313":1,"336":1,"342":2,"358":1}}],["totalmente",{"2":{"55":2,"68":1,"69":1,"116":1,"441":1,"673":1,"689":1,"741":3}}],["toolchains",{"2":{"722":1}}],["tooltip",{"2":{"690":6}}],["tools",{"2":{"131":3,"142":3,"168":3,"203":3,"270":1,"273":1,"290":1,"293":1,"553":1,"567":1}}],["toolbar",{"2":{"11":1,"34":1}}],["topchange",{"2":{"427":5}}],["topo",{"2":{"345":1,"404":1,"465":1,"479":1,"542":1}}],["top",{"2":{"122":5,"234":4,"338":1}}],["torná",{"2":{"441":1,"717":1}}],["torno",{"2":{"113":1,"156":1,"490":1}}],["torne",{"2":{"111":3,"252":1,"414":1,"443":1}}],["tornam",{"2":{"390":1}}],["tornamos",{"2":{"111":1}}],["tornará",{"2":{"252":1,"452":1,"461":1,"463":1}}],["tornar",{"2":{"105":1,"111":1,"251":5,"258":1,"441":1,"442":1,"452":1,"629":1,"668":1,"673":1,"677":1,"681":1,"687":1,"716":1}}],["torna",{"2":{"96":1,"105":1,"111":1,"112":1,"221":1,"337":1,"344":1,"417":1,"461":1,"485":1,"680":1,"681":1,"692":1}}],["tornando",{"2":{"40":1,"51":1}}],["tonalidade",{"0":{"83":1}}],["touches",{"2":{"251":1}}],["touchup",{"2":{"251":1}}],["touch",{"2":{"74":1,"77":1,"321":1,"366":1}}],["touchs",{"2":{"74":1}}],["touchablex",{"0":{"544":1}}],["touchables",{"2":{"245":1}}],["touchablenativefeedback>",{"2":{"245":1}}],["touchablenativefeedback",{"2":{"74":1,"245":5}}],["touchablehighlight>",{"2":{"245":2}}],["touchablehighlight",{"0":{"250":1},"2":{"74":1,"77":1,"110":1,"115":1,"245":4,"250":1}}],["touchablewithoutfeedback>",{"2":{"10":1,"245":1}}],["touchablewithoutfeedback",{"2":{"10":2,"74":2,"77":1,"245":3}}],["touchableopacity>",{"2":{"3":1,"5":1,"60":1,"113":2,"114":4,"115":4,"116":2,"224":1,"225":1,"226":1,"227":1,"228":1,"229":1,"230":1,"233":2,"234":1,"245":1,"573":1}}],["touchableopacity",{"0":{"113":1},"2":{"3":2,"5":1,"60":2,"74":1,"77":1,"113":3,"114":2,"115":5,"116":4,"224":2,"225":2,"226":2,"227":2,"228":2,"229":2,"230":2,"233":3,"234":2,"245":3,"534":2,"573":2}}],["touchable",{"0":{"250":1},"2":{"3":1,"5":1,"74":1,"77":1,"114":1,"250":1}}],["tovalue",{"2":{"46":1,"47":1,"48":2,"49":1,"51":3,"54":1,"56":1}}],["todo",{"2":{"262":1,"276":1,"296":1,"316":1,"344":1,"361":1,"389":1,"407":1,"461":1,"485":1,"533":1,"540":1,"556":2,"630":1,"654":1,"673":1,"729":1}}],["todos",{"2":{"0":1,"2":1,"3":1,"30":2,"46":1,"47":1,"60":1,"65":1,"76":1,"97":1,"106":1,"115":1,"128":1,"141":2,"167":2,"202":2,"226":1,"236":1,"243":1,"251":2,"252":1,"257":1,"338":1,"349":1,"379":1,"387":1,"390":1,"391":1,"407":2,"420":1,"440":1,"442":1,"443":1,"453":1,"454":1,"456":3,"469":1,"491":1,"507":1,"509":1,"516":2,"531":1,"534":1,"545":1,"561":1,"572":1,"587":1,"595":2,"638":2,"648":1,"656":1,"659":1,"668":1,"673":1,"674":1,"675":2,"699":1,"700":2,"728":1,"730":2,"731":1}}],["toda",{"2":{"46":1,"111":1,"112":1,"191":1,"242":1,"413":1,"442":1,"577":1,"634":1,"655":1,"666":1,"673":1,"677":1,"693":1}}],["today",{"0":{"43":1},"2":{"43":5,"44":1}}],["todas",{"0":{"729":1},"2":{"41":1,"48":1,"60":1,"62":1,"65":2,"67":2,"77":1,"106":1,"108":1,"128":1,"134":2,"184":1,"223":1,"240":1,"244":1,"261":1,"268":1,"278":1,"279":1,"280":1,"288":1,"298":1,"299":1,"300":1,"309":1,"322":1,"354":1,"368":1,"379":2,"398":1,"402":1,"404":1,"407":1,"431":1,"443":1,"445":1,"470":1,"486":1,"524":1,"531":3,"538":2,"549":1,"562":1,"595":1,"596":1,"648":1,"706":1}}],["toques",{"0":{"243":1},"1":{"244":1,"245":1,"246":1,"247":1},"2":{"110":1,"113":1,"242":1,"248":1,"251":1,"534":1,"700":2,"757":1}}],["toque",{"2":{"33":4,"35":1,"38":1,"39":2,"115":1,"128":1,"243":1,"245":3,"247":1,"248":5,"249":2,"250":1,"251":15,"252":1,"255":1,"387":2,"534":3,"544":1,"669":1,"679":1,"700":1}}],["tocável",{"2":{"74":3,"77":3,"114":1,"245":1}}],["tocáveis",{"0":{"245":1},"2":{"2":1,"245":3,"246":1,"250":1}}],["tocar",{"2":{"243":1,"417":1,"543":1,"568":1,"682":1}}],["toca",{"2":{"35":2,"116":1,"497":1}}],["tocando",{"2":{"32":1,"248":1,"549":1,"598":1,"607":1,"641":1}}],["to",{"2":{"5":1,"65":3,"114":1,"122":2,"134":3,"242":1,"244":1,"358":1,"390":1,"427":3,"429":2,"430":1,"431":2,"438":1,"439":1,"457":1,"463":1,"467":6,"479":1,"481":1,"485":1,"488":1,"520":1,"553":1,"662":2,"663":2,"680":4,"681":1,"748":2}}],["tais",{"2":{"550":1}}],["tasks",{"2":{"490":1}}],["task",{"2":{"256":4,"710":1}}],["taskdata",{"2":{"255":1,"257":1}}],["task>",{"2":{"65":1}}],["tanta",{"2":{"557":1}}],["tanto",{"2":{"0":1,"91":1,"100":1,"140":1,"201":1,"233":1,"552":1,"687":1,"739":1}}],["tan",{"2":{"88":1}}],["tarde",{"2":{"141":1,"143":1,"167":1,"202":1,"488":1,"700":2}}],["targetrect",{"2":{"690":2}}],["targetrect=",{"2":{"690":2}}],["targetref",{"2":{"690":4}}],["targetapi=",{"2":{"273":1,"293":1}}],["target",{"2":{"68":1,"77":1,"251":1,"313":2,"358":2,"390":1}}],["targets",{"2":{"68":1,"439":1}}],["tarefas",{"2":{"254":1,"255":1,"466":4,"490":2,"700":3,"703":1}}],["tarefa",{"2":{"11":1,"34":1,"128":1,"255":3,"256":2,"257":2,"258":2,"596":1,"700":1}}],["taxas",{"2":{"533":1}}],["taxa",{"0":{"534":1,"535":1},"2":{"63":1,"67":2,"500":1,"693":1}}],["tal",{"2":{"524":1,"628":1}}],["talvez",{"2":{"60":1,"140":1,"201":1,"217":1,"239":1,"328":1,"339":1,"441":1,"446":1,"541":1,"571":1,"576":1,"595":1,"615":1,"652":1,"671":1,"730":1}}],["talkbackservice",{"2":{"38":2}}],["talkback",{"0":{"38":1},"2":{"0":1,"3":1,"7":1,"10":2,"30":2,"35":2,"38":10}}],["tamanhos",{"2":{"111":1,"222":1,"261":1,"336":1,"550":2}}],["tamanho",{"0":{"110":1,"111":1,"543":1,"657":1},"2":{"60":1,"108":1,"110":4,"111":10,"120":1,"230":1,"231":6,"232":3,"260":1,"261":3,"262":1,"263":1,"328":1,"329":1,"331":1,"336":1,"337":2,"338":2,"342":2,"407":1,"445":1,"503":2,"509":1,"543":1,"548":1,"566":1,"636":1,"657":1,"668":1,"689":1,"731":1,"740":1}}],["também",{"2":{"11":2,"34":1,"46":1,"47":1,"48":1,"50":7,"51":2,"56":3,"60":1,"63":1,"65":2,"67":1,"69":1,"77":1,"85":1,"86":1,"101":2,"106":2,"107":1,"111":1,"115":1,"117":1,"122":1,"142":2,"145":1,"146":1,"152":1,"168":2,"170":1,"171":1,"177":1,"184":1,"185":1,"189":1,"190":1,"191":1,"194":1,"200":2,"203":2,"205":1,"206":1,"212":1,"217":2,"218":1,"224":1,"225":1,"231":1,"248":1,"268":1,"279":2,"283":1,"285":1,"288":1,"299":2,"303":1,"309":1,"329":1,"331":1,"338":1,"348":2,"349":1,"354":1,"386":2,"391":1,"407":1,"417":2,"420":1,"421":1,"424":1,"436":1,"440":1,"441":2,"442":1,"445":1,"451":1,"452":1,"456":1,"461":2,"464":3,"465":1,"478":1,"485":2,"486":1,"487":1,"488":3,"489":1,"493":2,"499":1,"510":1,"516":1,"519":1,"520":2,"522":1,"525":1,"538":2,"539":1,"547":1,"549":1,"555":2,"556":1,"562":2,"563":1,"566":1,"577":1,"596":1,"600":1,"601":1,"603":1,"609":1,"610":1,"612":1,"617":1,"618":1,"619":1,"626":1,"629":1,"635":1,"636":3,"638":1,"643":1,"644":1,"646":1,"652":1,"656":1,"668":1,"671":1,"675":1,"680":1,"682":1,"691":1,"692":1,"700":1,"704":1,"723":1,"728":1,"731":1,"732":1,"733":1,"742":1,"748":1,"749":1}}],["tags",{"2":{"347":1,"553":1}}],["tag",{"2":{"37":1,"256":1,"349":1,"402":1,"444":1}}],["tabulações",{"2":{"672":1}}],["tabular",{"2":{"551":1}}],["table",{"2":{"392":1}}],["tablist",{"2":{"11":1,"34":1}}],["tabbarios",{"2":{"77":2}}],["tab",{"2":{"11":1,"34":1}}],["tapped",{"2":{"244":2,"245":1}}],["tap",{"2":{"3":1,"166":1,"244":1}}],["teve",{"2":{"694":1}}],["teoricamente",{"2":{"673":1}}],["tee",{"2":{"608":1,"715":1}}],["tedioso",{"2":{"336":1}}],["te",{"2":{"156":1}}],["teal",{"2":{"88":1}}],["testing",{"2":{"680":1,"684":2,"710":1}}],["testid",{"2":{"680":1}}],["tests",{"2":{"616":1,"739":5}}],["testflight",{"2":{"549":1}}],["testável",{"0":{"673":1},"2":{"673":4,"674":1}}],["testá",{"2":{"547":1,"679":1}}],["testlocation",{"2":{"457":1,"459":1,"464":2,"481":1,"488":2}}],["testname",{"2":{"457":1,"459":1,"464":2,"481":1,"488":2}}],["test",{"2":{"390":1,"404":2,"679":1,"734":2}}],["testes",{"0":{"674":1,"675":1,"676":1,"678":1,"679":1,"682":1},"1":{"675":1},"2":{"239":1,"417":1,"549":1,"616":2,"670":1,"671":3,"673":2,"674":4,"675":6,"676":4,"677":4,"678":3,"679":7,"680":2,"682":10,"683":1}}],["teste",{"0":{"280":1,"300":1,"322":1,"368":1,"405":1,"457":1,"481":1,"578":1,"670":1},"1":{"281":1,"282":1,"301":1,"302":1,"323":1,"324":1,"325":1,"369":1,"370":1,"371":1,"671":1,"672":1,"673":1,"674":1,"675":1,"676":1,"677":1,"678":1,"679":1,"680":1,"681":1,"682":1,"683":1,"684":1},"2":{"43":1,"457":1,"481":1,"655":1,"671":4,"674":1,"675":8,"677":2,"678":5,"679":1,"680":2,"681":9,"682":4,"739":1}}],["testa",{"2":{"680":1}}],["testabilidade",{"2":{"674":1}}],["testasse",{"2":{"673":1}}],["testados",{"2":{"673":1,"677":1}}],["testado",{"2":{"673":1,"675":1,"676":1}}],["testadores",{"2":{"549":1}}],["testadas",{"2":{"673":3,"678":1}}],["testar",{"0":{"671":1},"2":{"39":1,"42":1,"458":1,"482":1,"537":1,"605":1,"657":1,"665":1,"670":1,"671":1,"675":1,"679":3,"680":4,"681":1,"683":1}}],["testando",{"0":{"38":1,"39":1,"655":1,"680":1,"681":1,"761":1},"1":{"681":1},"2":{"65":1,"675":2,"680":1,"761":1}}],["telefones",{"2":{"552":1}}],["telefone",{"2":{"33":1,"65":1,"149":1,"156":1,"158":1,"174":1,"209":1,"553":1,"603":1,"608":4,"612":1,"620":1,"646":1}}],["telas",{"0":{"471":1},"1":{"472":1,"473":1},"2":{"246":1,"285":1,"417":1,"471":1,"472":1,"553":1,"571":3,"757":1}}],["tela",{"0":{"36":1,"542":1,"550":1},"2":{"0":1,"3":1,"4":1,"8":1,"9":1,"35":2,"36":1,"37":1,"110":1,"120":1,"128":2,"129":1,"130":1,"141":1,"167":1,"202":1,"218":1,"221":1,"222":1,"251":1,"260":1,"261":2,"262":1,"263":1,"275":1,"295":1,"314":1,"315":1,"320":1,"325":2,"328":3,"344":1,"347":1,"359":1,"360":1,"365":1,"371":2,"385":1,"400":1,"402":1,"441":1,"471":1,"502":1,"533":1,"543":1,"545":1,"548":3,"550":2,"554":1,"571":1,"576":1,"603":1,"612":1,"619":1,"646":1,"682":2,"730":1,"731":2}}],["tendo",{"2":{"189":1,"325":1,"334":1,"371":1}}],["tendem",{"2":{"680":1}}],["tende",{"2":{"43":1}}],["tentador",{"2":{"681":1}}],["tentando",{"2":{"556":1,"558":1}}],["tentativa",{"2":{"257":7,"334":1}}],["tentativas",{"0":{"257":1},"2":{"257":3}}],["tentamos",{"2":{"240":1,"532":1,"717":1}}],["tenta",{"2":{"219":1,"221":1}}],["tentar",{"2":{"251":1,"258":1,"376":1,"381":1,"407":1,"619":1,"665":1,"746":1}}],["tentarão",{"2":{"218":1}}],["tentará",{"2":{"31":1,"708":1}}],["tente",{"2":{"43":1,"112":1,"134":1,"189":1,"190":1,"223":1,"262":1,"263":1,"418":1,"441":1,"505":1,"554":1,"570":1,"608":1,"682":1,"701":1,"705":1,"710":1,"711":1,"716":1,"742":1}}],["tenham",{"2":{"113":1,"245":1,"700":1}}],["tenhamos",{"2":{"94":1,"103":1}}],["tenha",{"0":{"58":1},"2":{"31":1,"33":1,"42":1,"55":1,"113":1,"117":1,"135":1,"156":1,"221":1,"227":1,"239":1,"279":1,"299":1,"404":1,"424":1,"456":1,"493":1,"542":1,"550":1,"555":1,"565":1,"566":1,"616":1,"651":2,"679":1,"683":1,"706":1}}],["temas",{"2":{"417":1}}],["tema",{"2":{"279":2,"299":2}}],["template",{"2":{"146":1,"171":1,"190":1,"191":1,"206":1,"358":1,"390":3,"733":1}}],["temporária",{"2":{"523":1}}],["temporárias",{"2":{"111":1}}],["temporizadores",{"0":{"698":1,"699":1},"1":{"699":1,"700":1},"2":{"255":1,"698":2}}],["tempos",{"2":{"131":1,"375":1,"391":1,"578":1,"699":1}}],["tempo",{"0":{"389":1,"541":1},"2":{"46":1,"47":2,"55":1,"64":3,"65":1,"96":1,"105":1,"144":1,"169":1,"188":1,"204":1,"218":2,"242":1,"245":1,"251":1,"279":1,"320":1,"331":1,"349":3,"365":1,"381":1,"386":1,"389":1,"413":1,"456":2,"463":1,"487":1,"493":1,"499":1,"520":1,"537":1,"548":1,"552":1,"553":1,"555":1,"556":1,"559":2,"571":1,"573":1,"577":1,"596":1,"665":3,"666":3,"671":2,"682":2,"693":1,"700":1,"730":1,"740":1,"744":1}}],["temos",{"2":{"106":1,"110":2,"111":2,"271":1,"291":1,"320":1,"365":1,"386":1,"442":3,"443":2,"575":1,"628":1,"700":1}}],["tem",{"2":{"11":1,"34":3,"35":2,"48":1,"74":1,"77":1,"94":1,"103":1,"111":1,"228":1,"229":1,"242":1,"278":1,"288":1,"298":1,"345":1,"348":1,"374":1,"375":1,"381":1,"419":1,"420":1,"440":1,"444":1,"457":1,"461":2,"477":1,"481":1,"485":2,"493":1,"531":2,"532":1,"533":1,"542":1,"554":1,"555":1,"559":1,"566":1,"601":1,"610":1,"630":1,"636":1,"644":1,"656":1,"668":1,"676":1,"726":1,"738":1}}],["tecnicamente",{"2":{"310":1,"355":1,"452":1,"463":1,"487":1}}],["tecnologia",{"2":{"11":1,"12":1,"35":3,"417":1}}],["tecnologias",{"2":{"0":1,"20":1,"27":1,"35":1,"240":1,"420":1,"440":1,"446":1,"449":1,"470":1,"474":1}}],["teclas",{"2":{"38":1,"74":1,"554":1,"562":1}}],["teclado",{"2":{"11":1,"44":1,"74":3,"77":2,"126":1}}],["tecla",{"2":{"11":1,"38":4,"74":1,"153":1,"178":1,"213":1}}],["terceirizada",{"2":{"538":1}}],["terceiro",{"2":{"407":1,"636":1}}],["terceiros",{"2":{"128":1,"145":1,"170":1,"189":1,"205":1,"420":1,"440":1,"470":1,"493":1,"521":1,"596":1,"636":1,"677":1}}],["termo",{"2":{"687":1}}],["termos",{"0":{"497":1},"2":{"375":1,"531":1}}],["terminologia",{"2":{"678":1}}],["terminado",{"2":{"700":1}}],["terminar",{"2":{"549":1,"721":1,"728":1}}],["terminal",{"2":{"126":1,"152":2,"158":1,"165":1,"166":1,"183":1,"194":2,"212":2,"268":1,"288":1,"309":1,"354":1,"376":1,"436":3,"526":1,"549":1,"567":1,"570":1,"612":1,"654":1,"686":1,"715":1}}],["terminando",{"2":{"76":1}}],["termina",{"2":{"47":1,"616":1}}],["termômetros",{"2":{"677":1}}],["terá",{"2":{"113":1,"115":1,"141":1,"167":1,"202":1,"262":2,"263":1,"270":1,"283":1,"290":1,"303":1,"407":1,"503":2,"555":1,"556":1,"575":1,"595":1,"656":1,"746":1}}],["terão",{"2":{"76":1,"562":1,"662":1}}],["ter",{"2":{"11":1,"30":1,"34":1,"46":1,"55":1,"56":1,"63":1,"115":1,"118":1,"190":1,"217":1,"218":1,"219":1,"227":1,"240":1,"249":1,"252":2,"261":1,"272":1,"279":1,"292":1,"299":1,"309":1,"320":1,"349":1,"365":1,"390":1,"404":1,"420":1,"440":1,"444":1,"446":1,"455":1,"457":1,"464":1,"469":1,"481":1,"499":1,"509":1,"516":1,"523":1,"529":1,"539":1,"561":1,"574":2,"595":1,"599":1,"608":1,"616":1,"642":1,"665":1,"695":1,"706":2,"734":1,"739":1}}],["text=",{"2":{"404":1}}],["textview",{"2":{"387":1,"429":5}}],["textref",{"2":{"122":8}}],["textcontainerref",{"2":{"122":8}}],["textcontainer",{"2":{"53":2,"122":4}}],["textalign",{"2":{"46":1,"122":2,"224":2,"225":2,"226":2,"227":2,"228":2,"229":2,"230":2,"231":2,"232":1,"233":1,"234":2,"245":1,"277":1,"297":1,"317":2,"362":2,"681":1}}],["textual",{"2":{"13":2,"19":1,"681":1}}],["textinputs",{"2":{"682":1}}],["textinput>",{"2":{"116":1}}],["textinput",{"0":{"116":1},"2":{"4":2,"26":1,"74":1,"116":8,"231":4,"232":3,"242":4,"346":3,"349":1,"387":3,"420":1,"440":1,"680":3}}],["text",{"2":{"3":3,"4":1,"5":2,"10":1,"11":1,"13":1,"26":1,"46":3,"53":2,"54":2,"60":2,"114":2,"115":2,"116":8,"122":8,"224":3,"225":3,"226":3,"227":3,"228":3,"229":3,"230":3,"231":5,"232":1,"233":5,"234":3,"239":1,"242":5,"245":6,"277":3,"297":3,"313":3,"317":5,"344":6,"345":6,"346":2,"347":2,"348":4,"349":2,"358":2,"362":5,"387":5,"429":4,"520":1,"573":2,"668":5,"680":4,"681":1,"693":1,"706":1,"730":7,"731":7,"737":2}}],["texto",{"0":{"242":1,"273":1,"293":1},"2":{"2":2,"10":2,"11":3,"34":2,"116":1,"153":1,"178":1,"196":1,"213":1,"225":3,"233":1,"242":7,"244":1,"273":4,"293":3,"323":1,"369":1,"385":2,"387":2,"429":2,"520":2,"542":1,"576":1,"629":1,"636":1,"637":1,"652":1,"668":3,"680":2,"682":2,"731":1,"753":1}}],["text>load",{"2":{"573":1}}],["text>very",{"2":{"573":1}}],["text>some",{"2":{"387":2,"690":2}}],["text>second",{"2":{"30":1}}],["text>welcome",{"2":{"347":1}}],["text>i",{"2":{"347":1}}],["text>inside",{"2":{"339":1}}],["text>hello",{"2":{"344":3,"345":3,"346":1,"348":3}}],["text>try",{"2":{"239":1}}],["text>texto",{"2":{"2":2}}],["text>column",{"2":{"232":1}}],["text>click",{"2":{"10":1}}],["text>row",{"2":{"232":1}}],["text>edit",{"2":{"116":2}}],["text>press",{"2":{"113":2}}],["text>first",{"2":{"30":1}}],["text>🍕",{"2":{"8":1}}],["text>",{"2":{"2":2,"3":1,"4":1,"5":1,"8":1,"10":2,"26":1,"30":2,"46":1,"53":1,"54":1,"60":1,"113":2,"114":4,"115":4,"116":2,"122":5,"224":2,"225":2,"226":2,"227":2,"228":2,"229":2,"230":2,"231":4,"232":2,"233":4,"234":2,"239":1,"242":1,"245":5,"277":1,"297":1,"317":3,"339":1,"344":3,"345":3,"346":1,"347":2,"348":3,"349":4,"362":3,"387":2,"511":2,"520":2,"573":2,"668":4,"680":1,"681":1,"690":2,"692":2,"730":3,"731":6,"737":1}}],["ii",{"2":{"434":1}}],["ibaction",{"2":{"320":1,"365":1}}],["ilusão",{"2":{"533":1}}],["ilustrada",{"2":{"748":1,"751":1}}],["ilustrado",{"2":{"426":1}}],["ilustrativos",{"2":{"320":1,"365":1}}],["iluminação",{"0":{"83":1}}],["io",{"2":{"313":2,"358":1,"398":1,"652":1}}],["ioga",{"2":{"235":1}}],["ios|android",{"2":{"576":1}}],["ios",{"0":{"6":1,"8":1,"9":1,"14":1,"15":1,"28":1,"31":1,"33":1,"39":1,"134":1,"181":1,"186":1,"305":1,"334":1,"340":1,"342":1,"350":1,"377":1,"440":1,"441":1,"474":1,"524":1,"564":1,"614":1,"632":1,"663":1,"666":1,"744":1,"748":1,"751":1,"766":1,"768":1},"1":{"182":1,"183":1,"184":1,"185":1,"186":1,"187":1,"188":1,"189":1,"190":1,"191":1,"192":1,"193":1,"194":1,"195":1,"196":1,"197":1,"198":1,"306":1,"307":1,"308":1,"309":1,"310":1,"311":1,"312":1,"313":1,"314":1,"315":1,"316":1,"317":1,"318":1,"319":1,"320":1,"321":1,"322":1,"323":1,"324":1,"325":1,"326":1,"351":1,"352":1,"353":1,"354":1,"355":1,"356":1,"357":1,"358":1,"359":1,"360":1,"361":1,"362":1,"363":1,"364":1,"365":1,"366":1,"367":1,"368":1,"369":1,"370":1,"371":1,"372":1,"441":1,"442":2,"443":1,"444":1,"445":1,"475":1,"476":1,"477":1,"478":1,"479":1,"480":1,"481":1,"482":1,"483":1,"484":1,"485":1,"486":1,"487":1,"488":1,"489":1,"490":1,"491":1,"492":1,"493":1,"494":1,"495":1,"615":1,"616":1,"617":1,"618":1,"619":1,"620":1,"621":1,"622":1,"667":1,"767":1,"768":1},"2":{"0":3,"6":1,"9":1,"35":4,"39":1,"41":2,"42":1,"44":1,"58":1,"67":2,"68":2,"76":1,"77":3,"79":1,"80":1,"126":1,"134":1,"135":1,"158":3,"159":2,"160":1,"161":1,"162":1,"182":1,"184":2,"186":2,"187":1,"189":5,"194":3,"195":2,"196":1,"236":1,"240":1,"244":1,"251":1,"285":2,"306":2,"307":1,"308":2,"310":1,"313":1,"314":1,"317":1,"325":3,"328":2,"331":1,"336":1,"340":1,"342":1,"351":2,"352":1,"353":2,"355":1,"358":1,"359":1,"362":1,"371":3,"377":6,"379":2,"382":1,"384":1,"385":2,"386":4,"387":1,"389":2,"415":1,"419":2,"436":4,"440":1,"444":4,"445":1,"447":1,"448":2,"470":2,"471":1,"474":1,"476":4,"481":3,"483":2,"486":1,"487":1,"488":2,"490":1,"491":1,"493":2,"495":1,"499":1,"512":1,"520":1,"523":1,"524":1,"533":1,"543":1,"546":1,"549":4,"551":1,"552":1,"561":1,"562":8,"564":2,"565":2,"566":2,"574":2,"605":1,"615":3,"622":1,"624":3,"625":2,"626":3,"627":2,"631":1,"634":3,"635":5,"636":1,"666":2,"667":1,"679":2,"682":1,"704":1,"719":1,"722":2,"730":1,"731":1,"739":1,"744":2,"746":1,"748":7,"751":1,"764":1,"765":1}}],["i",{"2":{"122":2,"131":2,"344":3,"345":3,"346":1,"348":3,"349":4,"434":1,"538":1,"703":1}}],["iu",{"0":{"420":1},"1":{"421":1,"422":1,"423":1,"424":1,"425":1,"426":1,"427":1,"428":1,"429":1,"430":1,"431":1,"432":1,"433":1,"434":1},"2":{"111":2,"337":1,"533":1,"558":1,"560":2,"691":1,"765":1}}],["iremos",{"2":{"314":1,"320":1,"359":1,"365":1,"679":1}}],["irá",{"2":{"251":1,"256":1,"259":2,"336":1,"344":1,"346":1,"441":1,"465":1,"467":1,"516":1,"531":1,"595":1,"605":1,"706":1}}],["irão",{"2":{"223":1,"445":1,"680":1}}],["ir",{"2":{"94":1,"103":1,"319":1,"364":1,"413":1,"414":1,"470":1,"673":1}}],["irmão",{"2":{"234":1}}],["irmãos",{"2":{"14":1,"28":1,"234":1,"262":1}}],["irmãs",{"2":{"14":1,"15":1,"24":1}}],["ivborw0kggoaaaansuheugaaadmaaaazcayaaaa6otaqaaaaexrfwhrtb2z0d2fyzqbwbmdjcnvzaeb1sfmaaabqsurbvgje7dsxcqbacarb+2",{"2":{"333":1}}],["ivory",{"2":{"88":1}}],["ivfsoverlay",{"2":{"68":1}}],["iguais",{"2":{"226":1}}],["igualdade",{"2":{"540":1}}],["igual",{"2":{"87":1,"546":1,"549":1,"604":1,"613":1,"622":1,"647":1}}],["igualmente",{"2":{"77":1,"262":1}}],["ignite",{"2":{"145":1,"170":1,"189":1,"205":1,"417":4,"733":1}}],["ignoradas",{"2":{"340":1}}],["ignorada",{"2":{"221":1}}],["ignorados",{"2":{"128":1}}],["ignorado",{"2":{"117":1,"726":1}}],["ignorando",{"2":{"67":1,"539":1}}],["ignora",{"2":{"14":1,"53":1}}],["ignorar",{"2":{"14":1,"28":1,"30":1,"116":1,"128":1,"566":1,"595":1,"666":1}}],["ignorelogs",{"2":{"128":2}}],["ignorealllogs",{"2":{"128":2}}],["ignore",{"2":{"14":1,"15":1,"24":1,"128":2,"654":1}}],["icon",{"2":{"328":11,"330":2,"337":3,"338":1}}],["ic",{"0":{"69":1}}],["ishermes",{"2":{"742":1}}],["ishungry",{"2":{"349":17}}],["ispending",{"2":{"692":3}}],["isinitialized",{"2":{"576":2}}],["isinteraction",{"2":{"57":1}}],["isloading",{"2":{"520":2}}],["isblockingsynchronousmethod",{"2":{"455":4}}],["iskindofclass",{"2":{"444":1}}],["isrequired",{"2":{"442":4}}],["isa",{"2":{"722":1}}],["isactive",{"2":{"390":1}}],["isapponforeground",{"2":{"259":4}}],["isconnected",{"2":{"259":1}}],["isnetworkavailable",{"2":{"259":4}}],["isnan",{"2":{"231":3}}],["is",{"2":{"129":1,"135":1,"256":4,"259":2,"313":2,"529":1,"748":1}}],["issuecomment",{"2":{"523":1}}],["issues",{"2":{"101":1,"523":2}}],["issue",{"2":{"77":1}}],["isso",{"0":{"154":1,"179":1,"197":1,"214":1},"1":{"180":1},"2":{"5":1,"10":1,"15":1,"30":1,"31":1,"39":1,"42":1,"43":1,"46":1,"48":1,"50":1,"51":1,"55":4,"56":3,"57":1,"60":1,"62":1,"63":2,"64":1,"65":2,"67":3,"68":1,"69":2,"70":2,"74":2,"77":2,"85":1,"89":1,"90":1,"94":1,"98":1,"99":1,"103":1,"105":1,"110":1,"111":4,"113":2,"114":3,"115":3,"119":1,"121":1,"122":1,"128":1,"131":2,"132":1,"142":1,"143":2,"145":1,"152":1,"157":1,"166":1,"168":1,"170":1,"177":1,"189":1,"191":1,"194":1,"200":1,"203":1,"205":1,"212":1,"217":1,"220":2,"221":3,"224":1,"229":1,"234":1,"244":1,"245":1,"248":1,"250":1,"252":3,"256":1,"257":2,"258":1,"261":1,"268":1,"270":1,"272":1,"273":2,"278":3,"279":6,"281":1,"288":1,"290":1,"292":1,"293":2,"298":3,"299":6,"301":1,"309":1,"310":1,"313":2,"320":2,"321":1,"324":1,"328":1,"332":1,"333":1,"336":2,"337":2,"338":2,"342":1,"344":1,"348":1,"349":2,"354":1,"355":1,"358":2,"365":2,"366":1,"370":1,"376":1,"377":2,"379":1,"381":1,"398":1,"404":1,"407":2,"409":1,"413":3,"424":1,"425":1,"426":1,"428":1,"438":1,"442":1,"445":1,"455":2,"456":1,"457":1,"458":2,"459":2,"461":5,"463":4,"464":1,"465":3,"466":1,"467":2,"470":1,"478":1,"479":2,"480":2,"481":1,"482":2,"485":4,"487":3,"488":1,"489":1,"490":2,"491":1,"492":1,"499":2,"500":1,"502":1,"504":1,"507":1,"516":1,"521":1,"523":1,"529":3,"531":1,"532":1,"534":4,"535":1,"537":1,"538":2,"540":3,"541":2,"542":1,"543":1,"544":2,"545":3,"551":1,"552":1,"554":1,"557":1,"559":1,"560":2,"562":1,"566":1,"568":1,"571":1,"573":1,"575":2,"586":1,"588":1,"595":1,"601":1,"603":2,"608":1,"610":1,"612":2,"629":2,"634":1,"636":4,"638":1,"644":1,"646":2,"654":1,"656":2,"657":1,"658":2,"660":1,"662":2,"663":1,"667":2,"668":3,"675":3,"677":1,"678":1,"681":1,"682":1,"685":2,"689":1,"690":1,"693":1,"694":1,"699":1,"700":2,"704":1,"708":1,"715":1,"721":2,"726":2,"730":1,"741":2,"744":1,"745":3,"746":1,"747":1,"748":1,"751":1}}],["istvos",{"2":{"76":1}}],["istv",{"2":{"73":1,"76":1}}],["isto",{"2":{"52":1,"55":1,"60":1,"74":1,"106":1,"128":1,"313":1,"367":1,"461":2,"485":2,"543":1,"555":1,"560":1,"651":1}}],["ifconfig",{"2":{"612":1}}],["if",{"2":{"37":1,"74":6,"77":6,"122":2,"256":1,"257":1,"259":10,"278":5,"279":6,"298":5,"299":1,"313":1,"334":2,"427":1,"431":4,"443":2,"444":1,"464":1,"466":4,"467":8,"488":1,"489":1,"490":1,"521":2,"548":1,"563":1,"564":1,"573":1,"576":1,"577":1,"653":1}}],["ipconfig",{"2":{"646":1}}],["ip=",{"2":{"621":1}}],["ip",{"0":{"621":1},"2":{"133":1,"134":1,"603":3,"612":3,"619":1,"621":4,"646":3}}],["iphoneos",{"2":{"663":2}}],["iphone",{"2":{"33":1,"328":2,"625":4,"626":3,"699":1,"722":1}}],["ipados",{"2":{"9":1,"39":1}}],["idêntico",{"2":{"726":1}}],["idp",{"2":{"636":1}}],["idvendor",{"2":{"608":1}}],["id=",{"2":{"403":1,"404":1}}],["id`",{"2":{"403":1}}],["idade",{"2":{"334":2}}],["id",{"2":{"251":2,"320":1,"404":4,"427":1,"442":4,"444":3,"464":4,"465":1,"480":1,"488":4,"489":2,"520":3,"608":15,"635":1,"703":1}}],["identity",{"2":{"722":1}}],["identidade",{"2":{"636":1}}],["identificou",{"2":{"557":1,"558":1,"688":1}}],["identificá",{"2":{"555":3}}],["identificando",{"0":{"556":1}}],["identificador",{"2":{"96":1,"105":1,"106":2,"251":1,"549":1,"608":2,"700":1}}],["identificadores",{"2":{"96":1,"105":1,"106":1,"549":1,"700":1}}],["identificar",{"2":{"34":1,"726":1}}],["identifica",{"2":{"26":1}}],["identifier",{"2":{"251":1}}],["idealmente",{"2":{"675":1}}],["ideal",{"2":{"632":1}}],["ide",{"2":{"437":1,"451":1}}],["ides",{"0":{"416":1}}],["ideia",{"2":{"90":1,"99":1,"106":1,"218":1,"551":1,"605":1}}],["idiomas",{"0":{"95":1},"1":{"96":1,"97":1},"2":{"95":1,"103":1,"104":1}}],["idioma",{"2":{"8":1,"242":2}}],["imutáveis",{"2":{"540":2}}],["immediate",{"2":{"392":1}}],["imagina",{"2":{"671":1}}],["imaginar",{"2":{"113":1}}],["imagine",{"2":{"94":1,"103":1,"448":1,"545":1,"677":1}}],["imagepickermodule",{"2":{"467":5}}],["imageresizemode",{"2":{"424":2}}],["imageviews",{"2":{"421":1}}],["imageview",{"0":{"421":1},"1":{"422":1,"423":1,"424":1,"425":1,"426":1},"2":{"387":1,"420":1,"426":1,"429":1,"434":1}}],["imagens",{"0":{"327":1,"330":1,"331":1,"332":1,"335":1,"342":1,"508":1},"1":{"328":1,"329":1,"330":1,"331":1,"332":1,"333":1,"334":1,"335":1,"336":2,"337":1,"338":1,"339":1,"340":1,"341":1,"342":1},"2":{"313":1,"328":7,"330":4,"331":1,"333":2,"337":2,"341":1,"358":1,"385":1,"387":1,"446":1,"467":2,"506":1,"508":1,"533":3,"543":1,"693":1,"731":1,"756":1}}],["imagelist",{"2":{"92":7,"101":4}}],["imageindex",{"2":{"53":8}}],["imagesizelimit",{"2":{"342":1}}],["images",{"2":{"53":4,"92":4,"101":3,"335":1,"548":1,"574":1,"663":1}}],["imagebrowserapp",{"2":{"92":1,"101":2}}],["imagebackground>",{"2":{"53":1,"339":1}}],["imagebackground",{"2":{"53":2,"339":4}}],["imagebutton",{"2":{"11":1}}],["imagem",{"0":{"328":1,"329":1,"336":1,"339":1,"543":1},"2":{"11":2,"34":1,"73":1,"149":1,"168":1,"174":1,"209":1,"233":1,"328":9,"329":1,"330":2,"331":1,"332":1,"333":2,"334":2,"336":2,"337":4,"338":2,"339":1,"340":1,"341":2,"342":3,"348":1,"451":1,"452":1,"459":1,"465":1,"467":1,"476":1,"477":1,"483":1,"508":1,"533":1,"542":1,"543":3,"554":1,"677":1}}],["image",{"2":{"11":1,"46":1,"53":4,"92":2,"101":2,"142":2,"168":2,"203":2,"313":2,"328":5,"330":2,"331":2,"332":1,"333":2,"334":1,"338":1,"339":1,"348":5,"358":1,"387":3,"467":20,"508":2,"706":1,"731":26}}],["imediato",{"2":{"51":1}}],["imediatamente",{"2":{"10":1,"27":1,"43":1,"45":1,"48":1,"108":1,"114":1,"239":1,"337":1,"417":1,"445":1,"462":1,"464":1,"488":1,"497":1,"577":1,"672":1,"674":1,"686":1,"695":1,"699":1}}],["imguri",{"2":{"92":2,"101":2}}],["img",{"2":{"34":1,"328":2,"387":1,"731":1}}],["impossíveis",{"2":{"688":1}}],["impossível",{"2":{"628":1}}],["importname",{"2":{"390":1}}],["imports",{"2":{"390":1}}],["importá",{"2":{"217":1,"566":1}}],["importe",{"2":{"217":1,"464":1,"573":1}}],["importação",{"2":{"430":1,"461":1,"485":1,"524":1,"575":1}}],["importações",{"2":{"279":1,"299":1,"344":1,"402":2,"404":2,"576":2,"577":1}}],["importa",{"2":{"334":1,"349":1,"456":1}}],["importando",{"2":{"412":1,"461":1,"485":1}}],["importance",{"2":{"259":4}}],["importantforaccessibility",{"0":{"30":1},"2":{"30":1}}],["importantforaccessibility=",{"2":{"15":1,"30":2}}],["importantes",{"2":{"45":1,"74":1,"671":1}}],["importante",{"2":{"11":1,"34":1,"336":1,"409":1,"424":1,"445":1,"452":1,"456":1,"464":2,"488":1,"493":2,"657":1,"665":2,"671":3,"691":1,"698":1}}],["importar",{"2":{"257":1,"344":1,"349":1,"454":1,"457":1,"461":1,"479":1,"481":1,"485":1,"490":1,"493":1,"565":1}}],["importarem",{"2":{"217":1}}],["importados",{"2":{"735":1}}],["importado",{"2":{"217":2}}],["importam",{"2":{"217":1}}],["import",{"2":{"46":3,"53":1,"54":1,"60":1,"92":1,"101":1,"114":2,"115":2,"116":4,"122":2,"223":1,"224":2,"225":2,"226":2,"227":2,"228":3,"229":2,"230":2,"231":2,"232":2,"233":2,"234":2,"239":2,"242":1,"244":1,"245":1,"256":10,"259":17,"261":1,"262":1,"263":1,"277":1,"297":1,"317":1,"320":2,"344":3,"345":4,"346":1,"347":1,"348":3,"349":2,"362":1,"365":1,"387":1,"390":2,"398":1,"402":13,"404":10,"426":1,"429":10,"430":13,"431":25,"432":8,"434":3,"441":4,"442":8,"443":7,"444":3,"445":1,"452":12,"456":13,"457":1,"461":2,"466":6,"477":2,"479":1,"481":1,"485":2,"490":2,"493":2,"520":1,"524":1,"573":4,"668":1,"708":1,"709":2,"730":2,"731":1,"737":2}}],["improvável",{"2":{"666":1}}],["imprimirá",{"2":{"268":1,"288":1,"309":1,"354":1}}],["imprevisíveis",{"2":{"117":1}}],["imprevisível",{"2":{"30":1}}],["impede",{"2":{"652":1}}],["impediam",{"2":{"688":1}}],["impedidos",{"2":{"218":1}}],["impedirá",{"2":{"547":1}}],["impedir",{"2":{"57":1,"218":1,"619":1}}],["impeça",{"2":{"635":1}}],["impenetrável",{"2":{"628":2}}],["imperceptível",{"2":{"261":1}}],["imperativo",{"2":{"112":1}}],["impacto",{"2":{"64":1,"533":1,"575":1,"673":1}}],["implantar",{"2":{"747":1,"748":1}}],["implantação",{"2":{"284":1,"304":1,"326":1,"372":1,"417":1,"546":2,"648":2,"742":1}}],["implícito",{"2":{"323":1,"369":1}}],["implicações",{"2":{"55":1}}],["implements",{"2":{"279":1,"402":2,"432":1,"456":1}}],["implementá",{"2":{"113":1}}],["implementam",{"2":{"452":1}}],["implementation",{"2":{"270":3,"290":3,"441":1,"442":1,"443":2,"477":1,"490":1}}],["implementations",{"2":{"68":1}}],["implementando",{"2":{"251":1,"463":1,"467":1,"468":1,"495":1,"745":1}}],["implementação",{"2":{"88":1,"92":2,"113":2,"250":1,"257":1,"339":1,"420":1,"421":1,"440":1,"442":2,"447":1,"454":1,"477":2,"491":2,"493":1,"497":1,"499":1,"677":2,"680":3,"699":2,"741":1}}],["implementações",{"2":{"0":1,"43":2}}],["implementa",{"2":{"52":1,"77":1,"456":2,"477":2,"507":1,"681":1,"698":1,"709":1}}],["implementado",{"2":{"71":1,"337":1,"468":1,"539":1,"731":1}}],["implementados",{"2":{"51":1,"445":1,"488":1}}],["implementada",{"2":{"51":1}}],["implementadas",{"2":{"50":1}}],["implementará",{"2":{"463":1}}],["implementar",{"0":{"423":1},"2":{"35":1,"44":1,"46":1,"74":1,"77":1,"257":1,"259":1,"279":1,"299":1,"402":2,"421":1,"452":1,"453":1,"456":3,"467":2,"468":1,"477":1,"487":1,"490":1,"540":1,"561":1,"562":1,"575":1}}],["implementemos",{"2":{"115":1}}],["implemente",{"0":{"426":1,"434":1},"2":{"35":1,"402":1,"421":1,"434":1,"441":1,"492":1,"507":1}}],["impulso",{"2":{"45":1}}],["iteração",{"2":{"534":1}}],["itera",{"0":{"458":1,"482":1},"2":{"451":1,"458":1,"482":1}}],["iterar",{"2":{"417":1,"601":1,"610":1,"618":1,"644":1}}],["itens",{"0":{"227":1,"504":1},"1":{"505":1,"506":1,"507":1,"508":1,"509":1,"510":1,"511":1},"2":{"34":1,"141":1,"142":1,"167":1,"168":1,"202":1,"203":1,"223":1,"226":1,"229":1,"230":1,"232":1,"246":1,"497":2,"500":3,"501":4,"502":2,"503":1,"504":1,"505":1,"506":1,"507":1,"510":1,"539":1,"730":1,"731":2}}],["itemscenter",{"2":{"232":3}}],["items",{"2":{"68":1,"511":1,"680":4}}],["item",{"2":{"11":1,"34":1,"77":1,"224":4,"226":2,"231":4,"505":1,"506":1,"509":1,"510":1,"511":3,"520":3,"680":8,"730":12,"731":1}}],["it",{"2":{"8":2,"65":1,"256":1,"462":1,"675":1,"680":1,"748":1}}],["inotify",{"2":{"715":2}}],["inodecache=true",{"2":{"68":1}}],["ingressando",{"2":{"671":1}}],["inútil",{"2":{"636":1}}],["inlinerequires",{"2":{"577":1}}],["inline",{"0":{"571":1,"573":1},"1":{"572":1,"573":1,"574":2,"575":1,"576":1,"577":1,"578":1},"2":{"571":1,"573":1,"576":1,"577":1,"762":1}}],["inestimável",{"2":{"551":1}}],["inesperados",{"2":{"145":1,"170":1,"189":1,"205":1,"221":1}}],["inesperadas",{"2":{"681":1}}],["inesperada",{"2":{"110":1,"134":1}}],["inevitável",{"2":{"537":1}}],["inerentemente",{"2":{"520":1}}],["injetar",{"2":{"492":1}}],["injeção",{"0":{"492":1}}],["inherited",{"2":{"358":1,"722":2}}],["inadvertidamente",{"2":{"547":1}}],["inactive",{"2":{"328":2}}],["inalteradas",{"2":{"118":1}}],["intrinsiccontentsize",{"2":{"111":1}}],["introduzimos",{"2":{"666":1}}],["introduzido",{"2":{"278":1,"298":1}}],["introduzir",{"2":{"96":2,"105":2,"221":1,"455":1,"480":1}}],["introdução",{"0":{"90":1,"99":1,"236":1,"373":1,"446":1,"733":1},"1":{"237":1,"238":1,"239":1,"240":1,"241":1,"447":1,"448":1},"2":{"155":1,"180":1,"198":1,"215":1,"236":1,"239":1,"344":1,"387":1,"449":2,"472":1,"473":1,"474":2,"753":1,"764":1}}],["int",{"2":{"85":1,"259":2,"278":5,"279":1,"298":4,"299":1,"424":4,"431":14,"462":1,"466":2,"467":9}}],["inteiro",{"2":{"431":1,"574":1,"673":1,"708":1}}],["inteiramente",{"2":{"535":1,"540":1}}],["inteira",{"2":{"110":1,"129":1,"400":1,"402":1,"543":1}}],["intel",{"2":{"142":2,"166":2,"168":2,"202":1,"203":2,"608":4}}],["inteligente",{"2":{"118":1}}],["intencional",{"2":{"681":1}}],["intencionalmente",{"2":{"218":1,"270":1,"290":1,"337":1}}],["intensamente",{"2":{"299":1}}],["intensivo",{"2":{"63":1,"113":1}}],["intent",{"2":{"73":3,"256":10,"259":11,"278":5,"298":4,"467":18}}],["intenção",{"2":{"71":1,"73":1,"248":1,"259":2,"635":1}}],["integre",{"2":{"400":1}}],["integrated",{"2":{"608":4}}],["integrating",{"2":{"313":1,"358":1}}],["integra",{"2":{"403":1}}],["integrados",{"2":{"374":1,"553":1}}],["integrado",{"2":{"158":1,"267":1,"288":1,"308":1,"353":1,"551":1,"681":1}}],["integrada",{"2":{"144":1,"145":1,"169":1,"170":1,"188":1,"189":1,"204":1,"205":1,"275":1,"295":1,"315":1,"360":1,"521":1,"741":1}}],["integradas",{"2":{"47":1}}],["integrando",{"0":{"402":1},"2":{"145":1,"159":1,"170":1,"189":1,"205":1,"471":1,"580":1}}],["integrar",{"2":{"107":1,"265":1,"274":1,"278":1,"280":1,"287":1,"294":1,"298":1,"300":1,"306":1,"313":2,"314":1,"322":1,"351":1,"358":2,"359":1,"368":1,"400":1,"428":1}}],["integração",{"0":{"274":1,"280":1,"285":1,"294":1,"300":1,"314":1,"322":1,"359":1,"368":1,"400":1,"405":1,"428":1,"568":1,"678":1},"1":{"275":1,"276":1,"277":1,"278":1,"281":1,"282":1,"295":1,"296":1,"297":1,"298":1,"299":1,"301":1,"302":1,"315":1,"316":1,"317":1,"323":1,"324":1,"325":1,"360":1,"361":1,"362":1,"369":1,"370":1,"371":1,"401":1,"402":1,"403":1,"404":1,"405":1,"406":1,"429":1,"430":1,"431":1,"432":1,"433":1,"434":1},"2":{"0":1,"89":1,"98":2,"145":1,"155":1,"170":1,"180":1,"189":1,"198":1,"205":1,"215":1,"311":1,"313":1,"356":1,"358":1,"400":1,"401":2,"420":1,"440":1,"665":1,"678":4,"679":1,"754":2}}],["integer>",{"2":{"431":1}}],["integer",{"2":{"13":4,"424":1,"431":3,"462":1,"464":2,"465":1,"466":1}}],["interoperabilidade",{"2":{"693":1}}],["interligado",{"2":{"673":1}}],["intermediates",{"2":{"662":1,"663":2}}],["intermediárias",{"2":{"690":1,"691":1}}],["intermediária",{"2":{"503":1}}],["intermediários",{"2":{"689":1,"692":2}}],["intermediário",{"2":{"67":1,"689":1}}],["interceptação",{"2":{"638":1}}],["intercalação",{"2":{"241":1}}],["interesse",{"2":{"553":1}}],["interessante",{"2":{"338":1}}],["interessantes",{"2":{"46":1}}],["interessado",{"2":{"243":1,"419":1,"447":1,"697":1}}],["interessados",{"2":{"53":1}}],["intervenção",{"2":{"532":1}}],["interval",{"2":{"392":1}}],["intervalos",{"2":{"50":3}}],["intervalo",{"2":{"13":5,"16":1,"17":1,"18":1,"50":3,"232":1,"533":1}}],["interstellar",{"2":{"520":1}}],["interpretadores",{"2":{"390":1}}],["interpretação",{"2":{"253":1}}],["interpolações",{"2":{"51":1}}],["interpolação",{"0":{"50":1},"2":{"50":3}}],["interpolate",{"2":{"50":8,"51":1,"53":1}}],["internet",{"2":{"272":2,"292":2,"619":1,"659":1,"677":1}}],["internacionalização",{"2":{"414":1}}],["internamente",{"2":{"101":1,"113":1,"469":1,"635":1,"720":1}}],["interna",{"2":{"95":1,"104":1,"106":1,"398":2}}],["internos",{"2":{"680":1,"687":1}}],["interno",{"2":{"90":1,"99":1,"242":1,"399":1,"445":1,"680":1}}],["interrupção",{"2":{"135":1,"437":1,"745":1}}],["interruptores",{"2":{"77":1}}],["interrompê",{"2":{"703":1}}],["interrompível",{"2":{"541":1}}],["interrompa",{"2":{"466":2}}],["interrompidas",{"2":{"48":1,"535":1}}],["interrompida",{"2":{"48":1,"692":1}}],["interromperá",{"2":{"55":1}}],["interromper",{"2":{"10":1,"27":1,"526":1,"691":1,"692":2}}],["interajam",{"2":{"249":1}}],["interagido",{"2":{"679":1,"680":1}}],["interagirão",{"2":{"679":1}}],["interagir",{"2":{"678":1,"680":1}}],["interagindo",{"2":{"134":1,"680":1}}],["interagem",{"2":{"243":1}}],["interage",{"2":{"242":1,"334":1,"381":1,"444":1}}],["interactionmanager",{"2":{"63":1,"541":1,"700":4}}],["interações",{"0":{"680":1},"1":{"681":1},"2":{"51":1,"248":1,"250":1,"497":1,"506":1,"680":1,"700":3}}],["interação",{"0":{"95":1,"104":1,"700":1,"756":1,"757":1},"1":{"96":1,"97":1,"105":1,"106":1,"757":1,"758":1,"759":1},"2":{"46":1,"349":1,"553":1,"558":1,"560":2,"679":1,"700":2}}],["interativos",{"0":{"239":1},"2":{"239":1}}],["interativo",{"2":{"25":1,"45":1,"235":1,"348":1,"441":1}}],["interfaces",{"2":{"65":1,"343":1}}],["interface",{"0":{"144":1,"169":1,"188":1,"204":1,"543":1,"552":1,"693":1},"1":{"553":1,"554":1,"555":1},"2":{"31":2,"45":1,"101":1,"111":1,"137":1,"144":1,"145":1,"164":1,"169":1,"170":1,"182":1,"188":1,"189":1,"199":1,"204":1,"205":1,"255":1,"258":1,"402":1,"426":2,"441":1,"442":2,"443":2,"452":1,"461":1,"464":1,"465":1,"477":1,"485":1,"490":1,"493":1,"531":3,"532":1,"533":1,"556":1,"568":1,"693":3,"737":1}}],["initializemap",{"2":{"685":2}}],["initialnumtorender",{"0":{"502":1},"2":{"502":1}}],["initialvalue",{"2":{"349":1}}],["initialproperties",{"2":{"92":5,"101":2,"110":1,"111":1,"320":2,"365":2,"404":3,"492":1}}],["initwithdelegate",{"2":{"492":1,"524":1}}],["initwithurl",{"2":{"320":2}}],["initwithbundleurl",{"2":{"320":2,"365":1}}],["initwithbridge",{"2":{"101":1,"110":1,"111":1,"320":1,"365":1,"492":1}}],["initwithframe",{"2":{"111":1}}],["init",{"2":{"76":2,"145":1,"146":1,"170":1,"171":1,"189":1,"190":1,"205":1,"206":1,"279":1,"299":1,"313":2,"320":1,"358":2,"402":2,"429":1,"441":1,"445":1,"467":1,"492":1,"580":1,"711":2,"726":1,"728":1}}],["inicie",{"0":{"152":1,"177":1,"194":1,"212":1},"2":{"265":1,"287":1,"306":1,"351":1,"549":1}}],["iniciá",{"2":{"56":2,"149":1,"174":1,"209":1}}],["iniciando",{"0":{"624":1}}],["iniciantes",{"2":{"236":1}}],["iniciamos",{"2":{"545":1}}],["iniciais",{"2":{"320":1,"365":1,"531":1,"576":1}}],["inicia",{"2":{"279":1,"285":1,"299":1,"320":1,"365":1}}],["iniciada",{"2":{"46":1,"56":1,"467":1}}],["iniciador",{"2":{"73":1}}],["iniciado",{"2":{"11":1,"34":1,"259":4,"456":1,"617":1}}],["inicialize",{"2":{"728":2}}],["inicializo",{"2":{"541":1}}],["inicializando",{"2":{"492":2}}],["inicializar",{"2":{"492":1,"624":1,"693":1}}],["inicializará",{"2":{"470":1,"492":1}}],["inicializada",{"2":{"423":1,"492":1}}],["inicializados",{"2":{"709":1}}],["inicializador",{"2":{"101":1}}],["inicializado",{"2":{"46":1,"487":2,"491":1}}],["inicializa",{"2":{"191":1,"456":1}}],["inicializamos",{"2":{"111":1}}],["inicialização",{"0":{"711":1},"1":{"712":1,"713":1},"2":{"101":1,"218":1,"252":1,"442":1,"456":3,"463":1,"487":1,"571":1,"572":1,"573":1,"575":1,"576":1,"578":1,"629":1,"740":1,"744":1,"745":1}}],["inicialmente",{"2":{"111":2}}],["inicial",{"0":{"539":1},"2":{"46":1,"77":1,"226":1,"279":1,"299":1,"325":1,"349":2,"371":1,"404":1,"417":1,"502":3,"548":2,"575":1,"636":2,"652":1,"689":1}}],["iniciaremos",{"2":{"259":2,"280":1,"300":1,"322":1,"368":1}}],["iniciará",{"2":{"134":1,"157":1,"691":1}}],["iniciar",{"0":{"151":1,"176":1,"193":1,"211":1,"714":1},"1":{"715":1,"716":1},"2":{"38":1,"48":1,"56":1,"74":1,"77":1,"134":2,"145":1,"146":2,"151":1,"170":1,"171":2,"176":1,"189":1,"190":2,"193":1,"205":1,"206":2,"211":1,"256":1,"258":1,"279":1,"281":1,"299":1,"301":1,"324":1,"370":1,"405":1,"437":1,"470":1,"549":1,"567":1,"600":1,"609":1,"617":1,"643":1,"721":1}}],["independentes",{"2":{"261":1,"328":1,"407":1,"673":1,"675":1}}],["independente",{"2":{"131":1,"231":1,"234":1,"472":1,"567":1,"673":1}}],["independentemente",{"2":{"55":1,"236":1,"334":2,"636":1,"673":1}}],["indefinido",{"2":{"111":1}}],["indexed",{"2":{"574":1}}],["indexado",{"2":{"574":2}}],["index",{"0":{"276":1,"296":1,"316":1,"361":1},"2":{"68":1,"276":3,"277":1,"279":4,"280":1,"283":2,"296":3,"297":1,"299":4,"300":1,"303":2,"316":3,"317":1,"318":1,"320":5,"322":1,"361":3,"362":1,"363":1,"365":5,"368":1,"401":1,"404":2,"431":6,"576":1,"590":1,"591":2,"660":2,"662":2,"685":2,"734":1}}],["indo",{"0":{"235":1},"2":{"50":1}}],["individuais",{"2":{"673":1,"676":1,"678":2}}],["individualmente",{"2":{"2":1}}],["indivíduos",{"2":{"379":1}}],["indistintamente",{"2":{"375":1}}],["indigo",{"2":{"88":1}}],["indianred",{"2":{"88":1}}],["indicatorcontainer",{"2":{"53":2}}],["indicadores",{"2":{"52":1,"387":1}}],["indicar",{"2":{"11":1,"31":1,"540":1,"692":1}}],["indica",{"2":{"2":1,"11":1,"12":5,"14":1,"15":1,"20":1,"21":1,"22":1,"23":1,"24":1,"27":1,"28":1,"29":1,"34":1,"577":2}}],["in",{"0":{"579":1,"702":1},"1":{"580":1,"581":1,"582":1,"583":1,"584":1,"585":1,"586":1,"587":1,"588":1,"589":1,"590":1,"591":1,"592":1,"593":1,"594":1,"595":1,"596":1,"703":1,"704":1},"2":{"46":1,"68":1,"113":1,"135":1,"256":3,"259":3,"313":1,"358":1,"387":1,"430":4,"529":1,"531":1,"564":1,"571":1,"573":1,"575":1,"577":1,"585":1,"638":1,"652":1,"675":1,"767":1}}],["inércia",{"2":{"45":1}}],["ins",{"2":{"734":1}}],["insira",{"2":{"387":1,"629":1}}],["inside",{"2":{"321":1,"366":1}}],["inserir",{"2":{"242":1,"445":1,"497":1,"608":1,"682":1}}],["inspetor",{"2":{"745":1}}],["inspetores",{"2":{"135":1}}],["inspect",{"2":{"745":2}}],["inspector",{"0":{"568":1},"2":{"39":1,"135":2,"568":3}}],["inspecione",{"2":{"629":1}}],["inspecionar",{"2":{"569":1,"745":1}}],["inspirado",{"2":{"90":1,"99":1}}],["instáveis",{"2":{"677":1}}],["instável",{"2":{"77":1,"523":1,"682":1}}],["instituiu",{"2":{"635":1}}],["instabilidade",{"2":{"534":1,"552":1,"682":1}}],["instantânea",{"2":{"746":1}}],["instantâneos",{"2":{"569":1,"681":3}}],["instantâneo",{"2":{"216":1,"531":1,"681":11}}],["instantiateinitialviewcontroller",{"2":{"548":1}}],["instantaneamente",{"2":{"458":1}}],["instanciá",{"2":{"456":1}}],["instancia",{"2":{"456":2}}],["instanciados",{"2":{"456":1}}],["instanciado",{"2":{"456":1}}],["instanciar",{"2":{"404":1,"456":1}}],["instancetype",{"2":{"111":1}}],["instalou",{"2":{"145":1,"149":1,"165":1,"166":1,"170":1,"174":1,"183":1,"184":1,"189":1,"200":1,"205":1,"209":1,"655":1}}],["instale",{"0":{"141":1,"142":1,"167":1,"168":1,"202":1,"203":1,"268":1,"309":1,"310":1,"354":1,"355":1},"2":{"141":1,"143":1,"158":1,"167":1,"185":1,"202":1,"268":1,"288":2,"309":1,"312":2,"354":1,"357":2,"409":1,"567":1,"655":1,"733":1}}],["installdebug",{"2":{"710":1}}],["installed",{"2":{"313":1,"358":1}}],["installer",{"2":{"68":3}}],["installation",{"2":{"313":1,"358":2}}],["install",{"2":{"67":1,"68":5,"165":2,"166":1,"183":2,"189":2,"200":1,"209":1,"268":2,"288":2,"309":2,"310":1,"313":1,"354":2,"355":1,"358":1,"376":1,"377":3,"383":2,"409":1,"567":2,"666":1,"706":1,"734":1,"739":1,"748":2}}],["installing",{"2":{"65":1,"313":1,"358":1}}],["instalá",{"2":{"67":1,"165":1,"183":1,"538":1,"580":1,"725":1}}],["instalações",{"2":{"567":1}}],["instalação",{"2":{"67":1,"68":1,"138":1,"141":1,"143":1,"167":1,"184":1,"200":1,"202":1,"309":1,"375":1,"376":1,"569":1,"666":1}}],["instalamos",{"2":{"376":1}}],["instala",{"2":{"142":1,"168":1,"203":1,"552":1}}],["instalando",{"0":{"137":1,"164":1,"182":1,"186":1,"199":1,"376":1},"1":{"138":1,"139":1,"140":1,"141":1,"142":1,"143":1,"144":1,"145":1,"146":1,"147":1,"148":1,"149":1,"150":1,"151":1,"152":1,"153":1,"154":1,"155":1,"200":1,"201":1,"202":1,"203":1,"204":1,"205":1,"206":1,"207":1,"208":1,"209":1,"210":1,"211":1,"212":1,"213":1,"214":1,"215":1},"2":{"156":1,"638":1}}],["instaladas",{"2":{"375":1,"626":1,"706":1}}],["instalada",{"2":{"38":1,"156":1,"190":1,"375":1,"552":1,"638":1}}],["instalador",{"2":{"166":1}}],["instalados",{"2":{"68":1,"142":1,"156":1,"168":1,"203":1,"648":1}}],["instalado",{"2":{"38":1,"67":1,"166":1,"200":1,"203":1,"209":1,"309":1,"375":1,"447":1,"580":1,"685":1,"706":1}}],["instalará",{"2":{"184":1}}],["instalar",{"2":{"38":1,"67":2,"137":1,"138":1,"139":1,"141":2,"142":1,"143":3,"144":1,"145":1,"156":2,"164":1,"165":2,"166":3,"167":2,"168":1,"169":1,"170":1,"182":1,"183":2,"184":1,"185":1,"186":2,"187":1,"188":1,"189":2,"191":1,"199":1,"200":2,"202":2,"203":1,"204":1,"205":1,"268":1,"288":1,"309":1,"310":1,"313":1,"354":1,"355":1,"358":1,"374":1,"376":1,"378":1,"383":2,"405":1,"569":1,"580":1,"598":2,"600":1,"603":1,"607":2,"608":1,"609":1,"612":1,"641":2,"643":1,"646":1,"666":2,"667":1,"728":1,"729":1,"748":1}}],["instância",{"2":{"74":1,"77":1,"97":1,"101":1,"106":1,"278":1,"298":1,"421":1,"441":3,"442":1,"443":1,"444":1,"490":1,"491":1,"508":1,"655":1,"745":1}}],["instâncias",{"2":{"51":1,"74":1,"77":1,"96":1,"105":1,"446":1,"492":1,"693":1}}],["instruí",{"2":{"706":1}}],["instruments",{"2":{"551":1}}],["instrumentos",{"2":{"43":1}}],["instruindo",{"2":{"667":1}}],["instruir",{"2":{"595":1,"666":1}}],["instrui",{"2":{"220":1}}],["instruções",{"0":{"538":1},"2":{"67":3,"70":1,"138":1,"148":1,"149":1,"159":2,"173":1,"195":1,"208":1,"209":1,"236":1,"377":2,"525":1,"529":1,"538":1,"569":1,"570":1,"580":1,"603":1,"612":1,"646":1,"651":1,"658":1,"660":1,"696":1,"697":1,"749":1}}],["início",{"0":{"157":1,"159":1},"1":{"158":1,"160":1,"161":1,"162":1},"2":{"39":1,"47":1,"70":1,"225":4,"226":2,"227":1,"229":2,"236":1,"251":1,"266":1,"288":1,"307":1,"352":1,"524":1,"531":2,"552":1,"683":1,"700":1}}],["infalível",{"2":{"639":1}}],["infinitas",{"2":{"523":1}}],["infranome",{"2":{"477":1}}],["infraestrutura",{"2":{"191":1,"338":1,"560":1,"694":1}}],["inflater",{"2":{"430":4}}],["influenciar",{"2":{"675":1}}],["influencia",{"2":{"55":1}}],["infelizmente",{"2":{"95":1,"104":1,"552":1}}],["inferior",{"2":{"39":1,"142":1,"168":1,"203":1,"224":1,"234":1,"244":1,"271":1,"291":1,"598":1,"607":1,"641":1}}],["info",{"2":{"65":5,"166":1,"323":1,"369":1,"392":1,"634":2}}],["infotext",{"2":{"53":2}}],["information",{"2":{"598":1,"607":1,"641":1}}],["informa",{"2":{"501":2,"691":1}}],["informação",{"2":{"111":1,"279":1,"365":1,"497":1,"632":1,"636":1,"638":1,"648":1,"654":1,"673":1,"677":2,"685":1}}],["informações",{"0":{"85":1,"629":1},"1":{"630":1,"631":1,"632":1,"633":1,"634":1},"2":{"0":1,"13":1,"60":1,"64":1,"67":1,"86":1,"90":2,"94":1,"99":2,"101":1,"103":1,"128":2,"131":1,"132":1,"187":1,"189":1,"191":1,"227":1,"259":4,"262":1,"270":1,"290":1,"325":1,"328":1,"329":1,"333":1,"338":2,"339":1,"371":1,"399":1,"409":1,"420":1,"424":1,"436":1,"440":1,"446":1,"449":1,"452":1,"456":1,"461":1,"462":1,"463":1,"465":1,"470":2,"474":1,"479":1,"486":1,"487":1,"488":1,"493":4,"506":1,"518":1,"520":1,"528":1,"531":7,"541":1,"546":1,"549":2,"551":1,"553":3,"556":1,"567":1,"568":1,"570":1,"574":1,"589":1,"605":2,"628":1,"632":1,"634":3,"635":1,"636":1,"639":1,"646":1,"662":1,"664":1,"677":1,"678":1,"679":1,"680":1,"687":1,"689":2,"690":1,"711":1,"718":1,"726":1,"730":1,"745":1}}],["informar",{"2":{"20":1,"677":1,"692":1}}],["incentivamos",{"2":{"673":1}}],["inception",{"2":{"520":1}}],["increase",{"2":{"737":1}}],["incrementa",{"2":{"35":1}}],["increment",{"2":{"35":1,"737":1}}],["incrível",{"2":{"683":1}}],["incrivelmente",{"2":{"636":1}}],["incompatibilidade",{"2":{"746":1}}],["inconsciente",{"2":{"635":1}}],["inconsistências",{"2":{"111":1,"389":1}}],["incorretos",{"2":{"442":1}}],["incorporando",{"2":{"345":1,"638":1}}],["incorporada",{"2":{"121":1}}],["incorporado",{"0":{"108":1,"109":1},"1":{"110":1,"111":1},"2":{"106":1,"621":1,"638":1}}],["incorporação",{"2":{"106":1}}],["incorporar",{"2":{"89":1,"98":1,"101":1,"105":1}}],["inclusion",{"0":{"759":1}}],["inclua",{"2":{"333":1,"477":1,"654":1}}],["incluída",{"2":{"493":1,"629":1}}],["incluídas",{"2":{"330":2}}],["incluído",{"2":{"283":1,"303":1,"345":1,"666":1,"706":1}}],["incluídos",{"2":{"0":1,"374":1}}],["incluí",{"2":{"279":1,"299":1}}],["incluem",{"2":{"246":1,"328":1,"381":1,"682":1,"722":1}}],["incluirão",{"2":{"470":1}}],["incluir",{"2":{"270":1,"290":1,"329":1,"402":1,"404":1,"407":1,"413":1}}],["incluirá",{"2":{"119":1,"660":1}}],["inclui",{"2":{"77":1,"376":1,"379":1,"478":1,"538":1,"571":1,"674":1,"693":1,"709":1}}],["incluindo",{"2":{"39":1,"111":1,"217":1,"329":1,"345":1,"348":1,"379":1,"531":2}}],["includes",{"2":{"393":1,"394":1,"576":1}}],["includebuild",{"2":{"270":1,"290":1}}],["include",{"2":{"68":2,"656":1,"722":1}}],["invista",{"2":{"639":1}}],["invisíveis",{"2":{"30":1}}],["invasor",{"2":{"638":2}}],["invasores",{"2":{"629":1}}],["invalidada",{"2":{"495":1}}],["invalidate",{"0":{"495":1},"2":{"495":1}}],["investimento",{"2":{"688":1}}],["investido",{"2":{"628":1}}],["investigação",{"2":{"660":1,"693":1}}],["investigando",{"0":{"576":1}}],["investigar",{"2":{"553":1,"576":1,"681":1}}],["investigue",{"2":{"559":1}}],["inventar",{"2":{"628":1}}],["inverso",{"2":{"735":1}}],["inversamente",{"2":{"628":1}}],["inversão",{"2":{"9":1}}],["inverter",{"2":{"9":1,"49":2}}],["inválida",{"2":{"130":1}}],["involuntária",{"2":{"634":1}}],["invocá",{"2":{"464":1,"465":1,"488":1}}],["invocou",{"2":{"459":1,"483":1}}],["invocação",{"2":{"463":1}}],["invoca",{"2":{"456":1,"483":1,"596":1}}],["invocando",{"2":{"450":1,"457":1,"463":1,"475":1,"481":1,"487":1}}],["invocar",{"2":{"386":1,"448":1,"457":2,"459":2,"461":1,"464":2,"481":2,"483":1,"485":1,"488":2,"585":1,"596":1,"693":1}}],["invocará",{"2":{"55":2,"491":1}}],["invocados",{"2":{"454":1,"466":1,"490":1,"576":1,"587":1}}],["invocado",{"2":{"320":1,"365":1,"427":1,"443":1,"454":3,"462":1,"464":2,"465":1,"479":1,"483":1,"486":1,"488":2,"495":1,"588":1}}],["invocadefaultonbackpressed",{"2":{"279":1,"299":1}}],["invoke",{"2":{"457":2,"464":4,"481":2,"491":1}}],["invokedefaultonbackpressed",{"2":{"279":1,"299":1}}],["invoque",{"2":{"35":1}}],["inputcontainer",{"2":{"232":2}}],["inputref",{"2":{"74":1,"116":6}}],["inputrange",{"2":{"50":4,"51":1,"53":1}}],["input",{"2":{"4":4,"26":2,"50":1,"116":4,"126":1,"231":4,"232":3,"387":1}}],["aeronave",{"2":{"673":1}}],["aaa",{"2":{"675":1}}],["aaaa",{"2":{"627":9}}],["aaaaaaaaaaaa",{"2":{"627":3}}],["aaaaaaaa",{"2":{"627":3}}],["aab",{"0":{"654":1},"2":{"654":4}}],["axios",{"2":{"521":1}}],["aws",{"2":{"629":1}}],["awesome",{"2":{"470":3}}],["awesomeproject",{"2":{"145":2,"146":1,"149":1,"157":5,"170":2,"171":1,"174":1,"189":2,"190":1,"205":2,"206":1,"209":1,"685":3}}],["await",{"2":{"390":2,"465":3,"489":3,"520":5}}],["afirmações",{"2":{"680":2,"682":1}}],["afirmar",{"2":{"675":1}}],["afirmado",{"2":{"473":1}}],["afinal",{"2":{"628":1}}],["afaste",{"2":{"226":1}}],["afete",{"2":{"675":1}}],["afetado",{"2":{"541":1}}],["afeta",{"2":{"225":1,"234":1}}],["afetaria",{"2":{"407":1}}],["afetará",{"2":{"67":1,"463":1,"487":1}}],["afetar",{"2":{"56":1,"60":1,"228":1,"491":1}}],["afeeee",{"2":{"88":1}}],["a0522d",{"2":{"88":1}}],["a9a9a9",{"2":{"88":2}}],["a52a2a",{"2":{"88":1}}],["azure",{"2":{"88":1}}],["azul",{"0":{"82":1},"2":{"166":1,"244":2,"562":1}}],["ajudante",{"0":{"723":1},"1":{"724":1,"725":1,"726":1}}],["ajudasse",{"2":{"532":1}}],["ajuda",{"2":{"152":1,"191":1,"194":1,"212":1,"419":1,"428":1,"525":1,"658":1,"671":1}}],["ajudarão",{"2":{"628":1}}],["ajudará",{"2":{"156":1,"451":1,"476":1,"628":1}}],["ajudar",{"2":{"77":1,"191":1,"344":1,"417":1,"498":1,"542":1,"576":1,"660":1,"666":1,"672":1,"675":1,"723":1}}],["ajudá",{"2":{"136":1,"343":1,"532":1,"671":1,"679":1,"723":1,"724":1}}],["ajuste",{"2":{"111":1,"583":1}}],["ajustes",{"2":{"39":1,"689":1}}],["ajustável",{"2":{"35":4}}],["ajusta",{"2":{"543":1}}],["ajustando",{"2":{"220":1,"544":1}}],["ajustada",{"2":{"417":1}}],["ajustadas",{"2":{"77":1}}],["ajustados",{"2":{"47":1}}],["ajustado",{"2":{"11":1,"34":1}}],["ajustará",{"2":{"313":1,"358":1}}],["ajustar",{"2":{"35":1,"534":1,"584":1,"585":1,"586":1,"674":1,"689":1}}],["avós",{"2":{"533":1}}],["avisado",{"2":{"726":1}}],["avisos",{"0":{"128":1},"2":{"127":1,"128":3,"537":1}}],["aviso",{"2":{"56":1,"97":1,"128":1,"358":1,"487":1,"490":1,"551":1}}],["avidamente",{"2":{"456":1}}],["avds",{"2":{"149":1,"174":1,"209":1}}],["avd",{"2":{"148":1,"149":5,"173":1,"174":4,"208":1,"209":5}}],["avançadas",{"2":{"473":1}}],["avançados",{"2":{"236":1,"375":1,"399":1}}],["avançado",{"0":{"399":1},"2":{"134":1,"243":1,"420":1,"440":1,"681":1}}],["avançar",{"2":{"387":1}}],["avanço",{"2":{"74":1}}],["aquele",{"2":{"279":1,"299":1,"336":1,"412":1,"686":1}}],["aqueles",{"2":{"128":1,"420":1,"440":1,"493":1,"553":1}}],["aquelas",{"2":{"67":1}}],["aquela",{"2":{"65":1}}],["aquamarine",{"2":{"88":1}}],["aqua",{"2":{"88":1}}],["aqui",{"0":{"408":1},"1":{"409":1,"410":1,"411":1,"412":1,"413":1},"2":{"46":1,"56":1,"94":1,"103":1,"111":1,"119":1,"142":1,"148":1,"168":1,"173":1,"195":1,"200":1,"202":1,"203":1,"208":1,"219":1,"224":1,"226":1,"227":1,"229":1,"230":1,"231":1,"235":1,"237":1,"259":1,"270":1,"277":1,"279":2,"290":1,"297":1,"299":2,"317":1,"320":2,"325":2,"328":1,"344":2,"345":1,"347":1,"348":1,"362":1,"365":2,"371":2,"402":2,"406":1,"441":2,"442":2,"444":1,"448":1,"451":1,"456":3,"461":1,"465":1,"467":2,"476":1,"485":1,"491":1,"498":1,"503":1,"507":1,"523":2,"525":1,"534":2,"550":1,"555":3,"557":1,"569":1,"581":1,"586":1,"596":1,"635":1,"668":1,"678":1,"696":1,"701":1,"706":1,"751":1}}],["amazon",{"2":{"656":1}}],["amarraremos",{"2":{"318":1,"363":1}}],["amarelo",{"2":{"128":1}}],["amigáveis",{"2":{"344":1}}],["amostras",{"2":{"531":2,"693":1}}],["amostragem",{"0":{"526":1},"2":{"525":1,"526":2}}],["amostra",{"2":{"314":1,"359":1,"385":1,"531":7}}],["amd",{"2":{"202":1}}],["ampliar",{"2":{"243":1,"554":1,"731":1}}],["ampla",{"2":{"46":1,"110":1}}],["amp",{"0":{"165":1,"756":1},"1":{"757":1,"758":1,"759":1},"2":{"142":2,"168":2,"203":2,"603":1,"612":1,"646":1}}],["am",{"2":{"122":2,"344":3,"345":3,"346":1,"347":1,"348":3,"349":4}}],["ambos",{"2":{"140":1,"201":1,"217":2,"464":1,"465":2,"692":1}}],["ambientes",{"2":{"379":2,"389":2}}],["ambiente",{"0":{"140":1,"156":1,"191":1,"201":1,"388":1,"754":1},"1":{"141":1,"142":1,"157":1,"158":1,"159":1,"160":1,"161":1,"162":1,"202":1,"203":1,"389":1,"390":1,"391":1,"392":1,"393":1,"394":1,"395":1,"396":1},"2":{"68":2,"134":1,"140":1,"142":2,"166":1,"168":2,"191":5,"201":1,"203":5,"236":1,"239":3,"266":2,"288":2,"307":2,"352":2,"381":1,"414":1,"463":1,"487":1,"629":2,"630":1,"663":1,"665":2,"666":2,"674":1,"679":2,"685":1,"754":1,"763":1}}],["ambas",{"2":{"38":1,"375":1,"471":1,"656":1}}],["ainda",{"0":{"729":1},"2":{"42":1,"111":1,"202":1,"221":1,"256":1,"279":1,"299":1,"330":1,"341":1,"345":1,"402":2,"407":1,"420":1,"440":1,"441":1,"445":2,"448":1,"456":1,"461":1,"485":1,"532":1,"566":1,"575":1,"616":1,"628":4,"635":1,"638":2,"667":1,"671":1,"673":1,"676":1,"678":1,"679":1,"691":1,"692":3,"721":1,"728":1,"735":2,"741":1}}],["arbitrário",{"2":{"446":1,"519":1}}],["arbitrária",{"2":{"111":1}}],["arbitrárias",{"2":{"50":1,"97":1,"101":1,"106":1}}],["args",{"2":{"390":2,"431":6,"444":1}}],["arguments",{"2":{"256":4,"257":2,"427":2,"466":4}}],["argumentos",{"0":{"708":1},"1":{"712":1,"713":1},"2":{"37":1,"52":1,"106":1,"120":1,"121":1,"221":1,"349":1,"424":3,"459":1,"462":3,"464":2,"465":1,"479":3,"486":2,"587":1}}],["argumento",{"0":{"462":1,"486":1},"2":{"35":1,"53":1,"62":1,"146":2,"171":2,"190":2,"206":2,"257":1,"258":1,"279":1,"299":1,"404":1,"424":4,"454":1,"464":5,"465":1,"478":3,"479":2,"483":1,"486":1,"488":6,"492":1,"519":1,"721":1}}],["are",{"2":{"313":1,"358":1}}],["arrombado",{"2":{"628":1}}],["arrombados",{"2":{"628":1}}],["arrow",{"2":{"390":1}}],["arredondado",{"0":{"340":1},"2":{"244":1}}],["arrange",{"2":{"675":1}}],["arraste",{"2":{"321":1,"366":1,"411":1,"412":1}}],["arrastar",{"2":{"407":1,"691":1}}],["arrastando",{"2":{"249":1}}],["arrasta",{"2":{"55":1,"427":1,"443":1}}],["arrastamento",{"2":{"51":1}}],["arrays",{"2":{"92":2,"349":1,"425":1,"432":2}}],["arraylistof",{"2":{"92":2}}],["arraylist",{"2":{"92":4,"456":2}}],["array",{"2":{"53":2,"234":1,"348":1,"390":1,"393":2,"394":1,"462":1,"486":2,"488":2,"531":1,"737":1}}],["around",{"2":{"226":2,"229":3,"232":1,"564":1,"731":1}}],["artigo",{"2":{"89":1,"93":1,"96":1,"97":1,"98":1,"102":1,"105":1,"106":1,"108":1,"569":1}}],["arquivos",{"0":{"335":1,"477":1,"726":1},"1":{"336":1},"2":{"69":1,"143":1,"165":1,"183":1,"217":1,"328":1,"329":1,"344":1,"381":1,"407":2,"461":1,"477":1,"485":1,"493":1,"516":1,"565":2,"566":1,"574":2,"589":1,"654":1,"656":1,"708":1,"716":1,"720":2,"722":1,"723":1,"726":3,"728":2,"734":1,"735":1}}],["arquivo",{"0":{"276":1,"296":1,"316":1,"361":1,"452":1},"2":{"65":1,"68":1,"69":1,"134":1,"142":2,"168":1,"191":4,"217":4,"218":1,"219":1,"220":3,"239":1,"256":1,"259":1,"268":3,"270":3,"276":3,"279":1,"288":3,"290":3,"296":3,"299":1,"309":3,"313":1,"316":3,"320":2,"323":1,"329":1,"345":1,"354":3,"358":1,"361":3,"365":2,"367":1,"369":1,"398":2,"399":1,"401":1,"402":1,"404":1,"409":1,"411":2,"412":1,"413":1,"444":1,"452":2,"456":2,"461":2,"477":3,"479":1,"485":2,"493":6,"520":1,"524":1,"529":2,"538":1,"549":3,"554":3,"561":1,"565":3,"573":3,"574":5,"576":3,"577":1,"582":1,"585":2,"589":2,"590":1,"591":1,"615":1,"636":2,"650":1,"651":1,"652":3,"653":1,"656":1,"660":4,"662":1,"663":1,"667":1,"673":1,"678":1,"681":2,"685":3,"704":1,"706":1,"718":1,"725":1,"726":5,"733":1,"734":3,"739":1,"742":1,"747":2,"748":1,"750":1,"751":1}}],["arquiteturas",{"2":{"65":1,"656":1}}],["arquitetura",{"0":{"687":1,"688":1,"695":1,"696":1,"697":1},"1":{"688":1,"689":2,"690":1,"691":1,"692":1,"693":1,"694":1,"695":1,"696":1,"697":2},"2":{"64":1,"65":1,"420":3,"440":3,"446":3,"449":3,"470":3,"474":3,"515":1,"552":1,"596":4,"687":4,"688":3,"689":1,"690":2,"691":2,"693":3,"694":2,"695":4,"696":3,"697":3,"748":1,"769":1}}],["architecture",{"2":{"748":2}}],["architectures",{"2":{"65":2}}],["archiveintermediates",{"2":{"663":2}}],["arch",{"2":{"65":2}}],["armv7a",{"2":{"656":1}}],["armário",{"2":{"628":1}}],["arm",{"2":{"168":1}}],["armazene",{"2":{"467":1,"629":1}}],["armazenada",{"2":{"349":1,"497":1}}],["armazenados",{"2":{"85":1,"639":1}}],["armazenado",{"2":{"67":1,"681":1}}],["armazenamento",{"0":{"630":1,"631":1,"634":1},"1":{"632":1,"633":1,"634":1},"2":{"349":1,"510":1,"628":1,"629":1,"630":6,"632":1,"633":1,"634":2}}],["armazenamos",{"2":{"242":1}}],["armazena",{"2":{"112":1,"268":1,"288":1,"309":1,"354":1}}],["armazenando",{"0":{"629":1},"1":{"630":1,"631":1,"632":1,"633":1,"634":1},"2":{"67":1,"630":1}}],["armazenar",{"2":{"67":2,"69":1,"113":1,"338":1,"464":1,"465":1,"488":1,"569":1,"631":1,"632":2,"634":1,"652":2}}],["armadilhas",{"2":{"96":1,"105":1,"672":1}}],["arm64",{"2":{"65":4,"549":1,"656":2}}],["armeabi",{"2":{"65":1,"656":1}}],["aria",{"0":{"16":1,"17":1,"18":1,"19":1,"20":1,"21":1,"22":1,"23":1,"24":1,"25":1,"26":1,"27":1,"28":1,"29":1},"2":{"24":1,"26":3}}],["auxiliar",{"2":{"751":1}}],["auxiliares",{"2":{"51":1,"486":1,"680":1}}],["auth",{"2":{"636":3}}],["authorize",{"2":{"636":2}}],["autenticar",{"2":{"629":1,"636":1}}],["autenticação",{"0":{"523":1,"635":1},"2":{"523":1,"628":1,"636":2,"682":1}}],["autônoma",{"2":{"567":1}}],["autoassinados",{"2":{"638":1}}],["autoridade",{"2":{"638":1}}],["autorização",{"2":{"636":2}}],["automáticos",{"2":{"691":1}}],["automático",{"2":{"691":1,"692":1,"737":1}}],["automática",{"0":{"409":1},"2":{"658":1}}],["automatizados",{"2":{"671":1}}],["automatizadas",{"2":{"670":1}}],["automatizar",{"2":{"417":1,"546":1,"648":1}}],["automatically",{"2":{"549":1}}],["automaticamente",{"0":{"337":1},"2":{"48":1,"74":2,"76":1,"129":1,"130":2,"135":1,"195":1,"279":1,"299":1,"337":1,"402":2,"424":1,"441":1,"456":1,"488":1,"492":1,"538":1,"547":1,"565":1,"580":1,"633":1,"648":1,"656":1,"726":1,"733":1}}],["autolinking",{"0":{"271":1,"291":1},"1":{"272":1},"2":{"271":1,"291":1,"409":1}}],["auto",{"2":{"30":1,"227":1,"228":1,"231":2,"233":6}}],["aumente",{"2":{"683":1}}],["aumentá",{"2":{"543":1}}],["aumento",{"2":{"502":1}}],["aumenta",{"2":{"60":1,"456":1,"500":1,"548":1,"559":1}}],["aumentar",{"2":{"35":1,"442":2,"731":1}}],["ausente",{"2":{"499":1}}],["ausentes",{"0":{"706":1},"1":{"707":1,"708":1},"2":{"279":1,"299":1,"402":1,"404":1,"442":1,"531":2}}],["ausência",{"2":{"389":1}}],["ações",{"0":{"35":1},"2":{"35":12,"74":1,"77":1}}],["ação",{"2":{"5":1,"11":1,"33":1,"34":1,"35":14,"56":1,"94":3,"103":3,"111":1,"245":1,"249":2,"320":1,"365":1,"544":2,"636":1,"675":1,"745":1}}],["agir",{"2":{"675":1}}],["agitar",{"2":{"126":1}}],["agitando",{"2":{"126":1,"279":1,"299":1}}],["agite",{"2":{"74":1,"77":1,"618":1}}],["aguardando",{"2":{"491":1,"576":2}}],["aguardar",{"2":{"465":1,"489":1}}],["age=",{"2":{"348":1}}],["agendamento",{"2":{"700":1}}],["agendará",{"2":{"111":1}}],["agendar",{"2":{"95":1,"104":1,"700":1}}],["agente",{"2":{"524":1}}],["agentes",{"2":{"27":1}}],["agora",{"0":{"155":1,"180":1,"198":1,"215":1,"284":1,"304":1,"326":1,"372":1},"2":{"76":1,"77":1,"115":1,"143":1,"153":1,"178":1,"196":1,"213":1,"241":1,"251":2,"256":1,"274":1,"279":1,"280":2,"282":1,"283":1,"294":1,"299":1,"300":2,"302":1,"303":1,"314":1,"318":1,"320":1,"322":2,"344":1,"349":2,"359":1,"363":1,"365":1,"368":2,"403":1,"404":1,"427":1,"441":1,"442":3,"443":2,"444":2,"456":1,"457":1,"459":1,"467":1,"468":1,"481":1,"483":1,"516":1,"531":1,"533":1,"545":1,"549":4,"567":1,"575":2,"577":1,"578":1,"599":2,"602":1,"603":1,"604":1,"608":2,"611":1,"612":1,"613":1,"617":1,"622":1,"636":1,"642":2,"645":1,"646":1,"647":1,"668":1,"687":1,"691":2,"745":2,"747":1,"748":1,"751":1}}],["agradável",{"2":{"390":1}}],["agrega",{"2":{"67":1}}],["agrupam",{"2":{"633":1}}],["agrupamento",{"2":{"230":1,"589":1,"654":1}}],["agrupados",{"2":{"229":1,"230":1,"349":1,"654":1,"655":1}}],["agrupadas",{"2":{"77":1,"229":1,"259":1,"534":1,"691":1}}],["agrupar",{"2":{"74":1,"111":1,"230":1,"420":1,"426":1,"440":1,"441":1,"488":1,"544":1,"585":1,"675":1,"692":1,"734":1}}],["agrupará",{"2":{"67":1,"328":1,"547":1}}],["agrupando",{"2":{"67":1,"114":1,"445":1}}],["agrupa",{"2":{"2":1,"634":1,"636":1,"654":1}}],["abusar",{"2":{"542":1}}],["abertura",{"2":{"554":1}}],["abertas",{"2":{"571":1,"619":1}}],["aberta",{"2":{"522":1}}],["aberto",{"2":{"130":1,"343":1,"384":1,"389":1,"541":1,"569":1,"636":1,"687":2,"695":1,"740":1}}],["abc",{"2":{"390":1}}],["ab8beeqnhfi6wsyzylyuddqygbgygbgygbgygbgygbgzmcvdqygbgmhivgqygbgygbgygbgygbgygbgbmqw+p",{"2":{"333":1}}],["about",{"2":{"598":1,"607":1,"641":1}}],["above",{"2":{"268":2,"288":2,"309":2,"354":2,"690":2}}],["abordá",{"2":{"679":1}}],["abordou",{"2":{"445":1}}],["abordar",{"2":{"384":1}}],["abordaremos",{"2":{"41":1,"670":1}}],["abordamos",{"2":{"235":1}}],["aborda",{"2":{"107":1,"648":1}}],["abordados",{"2":{"97":1,"106":1,"479":1}}],["abordado",{"2":{"93":1,"102":1,"108":1}}],["abordadas",{"2":{"41":1,"454":1,"479":1}}],["abordagem",{"0":{"69":1},"2":{"60":1,"65":1,"69":1,"116":1,"191":2,"463":1,"487":1,"541":1,"545":1}}],["abordagens",{"2":{"0":1,"55":1,"330":1,"464":1,"488":1}}],["abortá",{"2":{"249":1}}],["abstrata",{"2":{"250":1,"452":1}}],["absoluta",{"2":{"234":1}}],["absolutas",{"2":{"121":1}}],["absolute",{"2":{"234":5}}],["absolutos",{"2":{"233":1}}],["absoluto",{"0":{"234":1},"2":{"110":1,"329":1,"499":1}}],["aba",{"2":{"186":1,"554":1,"616":1,"621":1}}],["abaixo",{"2":{"35":1,"58":1,"60":1,"63":1,"67":1,"79":1,"244":1,"273":1,"278":1,"293":1,"298":1,"346":1,"398":1,"399":1,"426":1,"444":1,"453":1,"454":1,"456":1,"457":2,"461":1,"462":1,"463":1,"464":1,"465":1,"466":1,"477":1,"478":2,"479":2,"481":2,"485":1,"486":1,"487":1,"488":2,"503":1,"504":1,"525":1,"551":1,"562":1,"581":1,"616":1,"651":1,"660":1,"663":1,"742":1,"748":1,"751":1}}],["abrindo",{"2":{"149":1,"174":1,"209":1,"554":1}}],["abrirão",{"2":{"129":1}}],["abrir",{"2":{"74":1,"131":1,"135":1,"149":1,"158":1,"174":1,"209":1,"270":1,"290":1,"321":1,"366":1,"526":1,"530":1,"553":1,"554":2,"567":1,"570":2,"618":1,"635":3,"745":1}}],["abrirá",{"2":{"74":1,"77":1,"131":1,"568":1}}],["abrangente",{"2":{"243":1}}],["abra",{"0":{"530":1},"2":{"134":1,"142":1,"152":1,"153":1,"168":1,"178":1,"185":1,"186":2,"194":1,"196":1,"200":1,"203":5,"212":1,"213":1,"268":1,"288":1,"309":1,"354":1,"451":1,"456":1,"476":1,"525":1,"526":1,"530":1,"533":1,"568":1,"603":2,"612":3,"615":3,"621":1,"646":3}}],["abreviatura",{"2":{"477":1}}],["abreviação",{"2":{"232":1,"348":1}}],["abre",{"2":{"11":1,"34":1}}],["abis",{"2":{"65":2,"69":1}}],["abi",{"0":{"65":1},"2":{"65":2,"656":1}}],["ataque",{"2":{"628":1,"638":2}}],["atalhos",{"2":{"126":1}}],["atalho",{"2":{"38":4,"39":1,"87":1,"131":1,"377":1}}],["attr",{"2":{"608":1}}],["attached",{"2":{"599":1,"608":1,"642":1}}],["attach",{"2":{"438":1,"439":1}}],["ats",{"2":{"520":5}}],["at",{"2":{"479":1,"488":1,"660":6}}],["atingirá",{"2":{"463":1}}],["atingir",{"2":{"282":1,"302":1,"508":1,"532":1}}],["atividades",{"2":{"279":2,"299":2}}],["atividade",{"0":{"467":1},"2":{"92":1,"278":1,"279":3,"282":1,"299":2,"302":1,"387":1,"452":1,"467":1,"468":2}}],["ative",{"2":{"38":1,"135":1,"618":1}}],["ativá",{"2":{"38":1}}],["ativou",{"2":{"657":1}}],["ativos",{"2":{"283":1,"303":1,"328":1,"329":1,"330":2,"397":1,"531":1,"654":1,"655":1,"700":1}}],["ativo",{"2":{"36":1}}],["ativas",{"2":{"700":1}}],["ativamente",{"2":{"695":1}}],["ativando",{"2":{"483":1}}],["ativar",{"0":{"695":1},"2":{"32":1,"38":2,"39":2,"135":1,"136":1,"451":1,"455":1,"525":1,"529":1,"542":1,"554":1,"598":3,"602":1,"603":1,"607":3,"611":1,"612":1,"641":3,"645":1,"646":1,"657":1,"696":1,"747":1,"748":1,"750":1}}],["ativa",{"2":{"27":1,"35":1,"695":1}}],["ativado",{"0":{"36":1},"2":{"11":1,"35":1,"224":4,"279":1,"299":1,"574":1,"667":1,"742":1}}],["ativadas",{"2":{"551":1}}],["ativada",{"2":{"9":1,"216":1,"278":1,"298":1,"602":1,"611":1,"645":1}}],["atom",{"2":{"142":2,"168":2,"203":2}}],["atento",{"2":{"634":1,"638":1}}],["atenuar",{"2":{"560":1}}],["atenuação",{"2":{"46":1,"47":4,"50":2}}],["atendida",{"2":{"288":1}}],["atender",{"2":{"257":1,"331":1,"334":3,"386":1}}],["atende",{"2":{"33":1}}],["atenção",{"2":{"112":1,"145":1,"168":1,"170":1,"189":1,"205":1,"288":1,"651":1,"681":1,"734":1}}],["atrás",{"2":{"56":1}}],["atrasará",{"2":{"700":1}}],["atrasar",{"2":{"541":1,"573":1,"700":2}}],["atraso",{"2":{"48":1,"55":1,"257":3,"501":1,"534":1}}],["atrasos",{"2":{"47":1}}],["atrapalha",{"2":{"417":1}}],["através",{"2":{"38":1,"74":1,"184":1,"523":1,"619":1,"731":1}}],["atribuído",{"2":{"424":1}}],["atribuídas",{"2":{"313":1,"358":1}}],["atribuição",{"2":{"469":1}}],["atribui",{"2":{"349":1}}],["atribuir",{"2":{"32":1}}],["atributo",{"2":{"328":1,"338":2}}],["atributos",{"2":{"108":1,"249":1,"338":1,"339":1,"445":1}}],["atribua",{"2":{"31":1,"33":1}}],["até",{"2":{"20":1,"31":1,"33":1,"47":2,"48":1,"63":1,"111":2,"120":1,"134":1,"189":1,"227":1,"236":2,"240":1,"248":1,"268":1,"288":1,"309":1,"334":1,"354":1,"376":1,"381":1,"385":1,"387":2,"389":1,"401":1,"443":1,"469":1,"470":1,"507":1,"520":1,"526":1,"531":1,"544":1,"549":1,"555":1,"556":1,"560":1,"573":1,"615":1,"651":1,"670":1,"677":1,"696":1,"700":1}}],["atualizá",{"2":{"654":1,"681":1,"726":1,"746":1}}],["atualize",{"0":{"726":1},"2":{"133":1,"166":1,"404":1,"461":1,"485":1,"490":1}}],["atualiza",{"2":{"671":1}}],["atualizada",{"2":{"106":1,"113":1,"424":1}}],["atualizadas",{"2":{"92":1,"101":1,"718":1}}],["atualizados",{"2":{"221":1,"638":1}}],["atualizado",{"2":{"27":1,"111":1,"218":2,"638":1,"721":1}}],["atualizando",{"0":{"577":1,"717":1},"1":{"718":1,"719":1,"720":1,"721":1,"722":1,"723":1,"724":1,"725":1,"726":1,"727":1,"728":1,"729":1},"2":{"63":1,"541":1,"654":1,"704":1,"746":1,"755":1}}],["atualizar",{"0":{"725":1,"728":1},"2":{"60":1,"63":1,"64":1,"90":1,"92":2,"99":1,"101":2,"106":1,"110":1,"113":2,"117":1,"200":1,"238":1,"328":1,"424":2,"577":1,"681":1,"690":1,"704":1,"718":2,"719":1,"720":1,"721":1,"724":2,"725":1,"726":1,"746":1}}],["atualizará",{"2":{"46":1,"217":2,"349":1}}],["atualizações",{"2":{"27":1,"60":1,"62":1,"92":1,"101":1,"111":4,"534":1,"571":1,"648":1,"689":2,"690":1,"691":7,"692":1,"695":1,"697":1,"724":1,"726":2}}],["atualização",{"0":{"216":1,"221":1,"723":1},"1":{"217":1,"218":1,"219":1,"220":1,"221":1,"724":1,"725":1,"726":1},"2":{"20":1,"92":2,"101":1,"130":2,"216":2,"218":3,"220":1,"221":3,"237":1,"238":1,"343":1,"387":1,"421":1,"441":1,"507":1,"545":1,"690":2,"691":2,"692":2,"717":2,"718":4,"719":1,"721":1,"723":1,"724":1,"726":1,"728":1,"751":1,"755":1}}],["atualmente",{"2":{"12":1,"23":1,"57":1,"92":1,"101":1,"139":1,"329":1,"424":1,"456":1,"462":1,"463":1,"486":1,"491":2,"514":1,"523":2,"531":1,"541":1,"562":1,"608":1,"700":1,"719":1}}],["atual",{"0":{"55":1},"2":{"12":1,"13":3,"18":1,"33":1,"55":2,"116":1,"142":1,"144":2,"168":1,"169":2,"188":2,"204":2,"280":1,"300":1,"310":1,"322":1,"355":1,"368":1,"424":1,"469":1,"531":2,"564":1,"603":1,"612":1,"646":1,"677":1,"690":1,"699":1}}],["atuais",{"2":{"11":1,"34":1,"251":1,"728":2}}],["atua",{"2":{"11":2,"34":1}}],["advertências",{"2":{"736":1}}],["advanced",{"2":{"135":2}}],["adoção",{"2":{"693":1,"696":1,"697":1}}],["adoptopenjdk",{"2":{"139":1}}],["adaptando",{"2":{"691":1}}],["adaptada",{"2":{"674":1,"682":1}}],["adaptáveis",{"2":{"689":1}}],["adsmanager",{"2":{"555":3}}],["adquirido",{"2":{"259":1}}],["adjust",{"2":{"313":1}}],["adjustable",{"2":{"11":1}}],["adjacentes",{"2":{"226":1,"349":1}}],["administrador",{"2":{"200":2,"650":1}}],["adequada",{"2":{"596":1}}],["adequadas",{"2":{"74":1,"77":1}}],["adequados",{"2":{"596":1}}],["adequado",{"2":{"245":1,"562":1}}],["adereço",{"2":{"244":1}}],["adereços",{"0":{"348":1},"2":{"92":1,"94":1,"103":1,"115":2,"235":1,"245":1,"339":1,"343":1,"347":1,"348":4,"431":1,"441":1,"540":1,"680":3}}],["adff2f",{"2":{"88":1}}],["addnewitemtoshoppinglist",{"2":{"680":2}}],["addevent",{"2":{"493":3}}],["addlifecycleeventlistener",{"2":{"468":2}}],["addlistener",{"2":{"55":2,"466":4}}],["addactivityeventlistener",{"2":{"467":3}}],["adduiblockque",{"2":{"444":1}}],["adduiblock",{"2":{"444":1}}],["addview",{"2":{"429":2}}],["addpackages",{"2":{"279":1,"299":1}}],["add",{"2":{"268":2,"279":1,"288":2,"299":1,"309":2,"354":2,"376":1,"404":3,"433":2,"456":4,"567":1,"680":3,"725":3,"728":1,"734":1,"739":1}}],["addsubview",{"2":{"110":1}}],["add8e6",{"2":{"88":1}}],["addone",{"2":{"10":2}}],["adições",{"2":{"310":1,"355":1}}],["adição",{"2":{"49":1,"407":1,"461":1,"485":1}}],["adicionou",{"2":{"706":2}}],["adicioná",{"2":{"404":1,"456":1,"706":1}}],["adicione",{"0":{"277":1,"297":1,"317":1,"362":1,"401":1,"403":1},"2":{"73":1,"111":1,"142":1,"168":1,"203":2,"256":1,"265":1,"268":1,"270":1,"271":2,"272":1,"287":1,"288":1,"290":1,"291":2,"292":1,"306":2,"309":1,"351":2,"354":1,"367":1,"401":1,"403":2,"404":4,"441":1,"452":1,"454":1,"456":2,"464":1,"467":1,"477":1,"479":1,"567":2,"574":2,"652":1,"653":1,"663":1,"666":1,"734":2,"739":1}}],["adicionada",{"2":{"636":1,"659":2,"747":1}}],["adicionados",{"2":{"142":1,"168":1,"279":1,"299":1,"402":2,"403":1,"456":1,"516":2}}],["adicionado",{"2":{"73":1,"74":1,"76":1,"77":1,"203":1,"320":1,"321":1,"365":1,"366":1,"456":1,"457":1,"481":1,"488":1,"490":1,"733":1}}],["adicionamos",{"2":{"338":1,"442":1}}],["adicionando",{"0":{"269":1,"289":1,"311":1,"356":1,"653":1,"734":1},"1":{"270":1,"290":1},"2":{"145":1,"170":1,"189":1,"205":1,"261":1,"270":1,"278":1,"290":1,"298":1,"329":1,"442":1,"548":1,"635":1,"656":1,"658":1,"732":1}}],["adicionais",{"0":{"40":1,"59":1,"61":1},"1":{"62":1,"63":1},"2":{"46":1,"77":1,"142":1,"168":1,"200":1,"203":1,"259":1,"375":1,"377":1,"518":1,"519":1,"546":1,"604":1,"613":1,"622":1,"647":1}}],["adicionará",{"2":{"403":1}}],["adicionaremos",{"2":{"277":1,"297":1,"314":1,"317":1,"320":1,"359":1,"362":1,"365":1,"442":1}}],["adicionar",{"0":{"323":1,"369":1,"404":1},"2":{"35":1,"65":1,"155":1,"180":1,"191":1,"198":1,"215":1,"220":1,"232":1,"262":1,"279":2,"285":2,"299":2,"310":1,"313":1,"317":1,"318":2,"319":1,"323":1,"328":3,"329":1,"339":1,"349":2,"355":1,"358":1,"362":1,"363":2,"364":1,"367":1,"369":1,"374":1,"402":1,"404":3,"407":1,"428":1,"429":2,"441":1,"442":1,"443":2,"452":1,"453":2,"454":1,"456":4,"457":2,"461":2,"464":1,"470":1,"479":1,"481":2,"485":2,"488":1,"493":1,"520":2,"524":1,"548":1,"567":1,"576":1,"587":1,"588":1,"629":1,"636":1,"652":1,"667":1,"682":1,"683":1,"745":1,"747":1}}],["adiciona",{"2":{"11":1,"34":1,"349":1,"404":1,"596":1,"671":1,"679":1,"734":1}}],["adicional",{"0":{"406":1},"2":{"5":1,"248":1,"283":1,"303":1,"400":1,"493":1,"534":1,"636":2,"667":1,"740":1}}],["adiar",{"2":{"63":1,"560":1}}],["adb",{"0":{"602":1,"611":1,"645":1},"2":{"38":2,"126":1,"131":1,"133":1,"436":1,"459":2,"529":4,"570":1,"599":4,"602":1,"608":3,"611":1,"642":3,"645":1,"685":1,"699":1}}],["alcancem",{"2":{"619":1}}],["alcançamos",{"2":{"95":1,"104":1}}],["alfa",{"2":{"542":1,"559":1}}],["alocados",{"2":{"533":1}}],["alonga",{"2":{"227":1}}],["all",{"2":{"431":1}}],["allowed",{"2":{"256":2}}],["alloc",{"2":{"101":1,"110":1,"111":1,"320":3,"441":1,"445":1,"492":3,"524":1}}],["alvo",{"2":{"381":1,"616":2,"745":1}}],["alvos",{"2":{"76":1,"552":1}}],["also",{"2":{"347":1}}],["aleatoriamente",{"2":{"682":1}}],["aleatória",{"2":{"636":1}}],["alex",{"2":{"320":1,"365":1}}],["alerta",{"2":{"244":1}}],["alert",{"2":{"11":1,"34":1,"35":9,"244":3,"245":5,"278":2,"298":2,"659":1}}],["alerte",{"2":{"10":1}}],["almejando",{"2":{"285":1}}],["alunos",{"2":{"236":1}}],["aliases",{"0":{"739":1},"2":{"739":2}}],["alias=my",{"2":{"652":1}}],["alias",{"2":{"650":4,"651":2,"652":2,"653":1,"739":1}}],["alimenta",{"2":{"389":1}}],["alimentar",{"2":{"349":1}}],["alimentados",{"2":{"349":1}}],["alinhamento",{"2":{"226":1,"228":1,"695":1}}],["alinhar",{"0":{"227":1,"228":1,"229":1},"2":{"226":1,"227":1}}],["alinha",{"2":{"224":1,"226":3,"227":3,"229":1}}],["alinhe",{"2":{"224":3,"227":1,"229":2}}],["alignselflayout",{"2":{"228":2}}],["alignself",{"2":{"224":1,"225":1,"226":1,"227":1,"228":7,"229":1,"233":2,"234":1}}],["aligncontentlayout",{"2":{"229":2}}],["aligncontent",{"2":{"222":1,"229":4,"230":1,"231":1,"232":2}}],["alignitemslayout",{"2":{"227":2}}],["alignitems",{"2":{"46":1,"53":4,"54":1,"60":1,"116":2,"122":2,"222":1,"227":6,"228":2,"231":1,"232":1,"239":1,"245":2,"317":1,"362":1,"737":1}}],["aliceblue",{"2":{"88":1,"224":1,"225":1,"226":1,"227":1,"228":1,"229":1,"230":1,"231":1,"232":1,"233":1,"234":1}}],["already",{"0":{"702":1},"1":{"703":1,"704":1},"2":{"65":1}}],["algoritmo",{"2":{"222":1,"445":1,"636":1}}],["algo",{"2":{"55":1,"320":1,"321":1,"348":2,"365":1,"366":1,"367":1,"418":1,"426":1,"520":1,"534":1,"554":1,"556":2,"560":1,"568":1,"608":1,"635":1,"675":1,"683":1,"701":1}}],["algumvalor",{"2":{"466":1}}],["alguma",{"2":{"400":1,"488":1,"575":1,"576":1,"675":2,"676":1,"677":1}}],["algumas",{"0":{"408":1},"1":{"409":1,"410":1,"411":1,"412":1,"413":1},"2":{"51":1,"55":1,"58":1,"64":1,"68":1,"69":1,"89":1,"92":1,"95":1,"96":2,"98":1,"101":1,"104":1,"105":2,"111":1,"140":1,"142":1,"153":1,"168":1,"178":1,"196":1,"201":1,"203":1,"213":1,"222":1,"285":1,"330":2,"331":1,"389":1,"442":1,"446":1,"464":1,"472":1,"504":1,"523":1,"546":1,"556":1,"604":1,"613":1,"622":1,"634":1,"647":1,"667":1,"680":2,"726":1}}],["algum",{"2":{"134":1,"191":1,"256":2,"279":2,"299":2,"328":1,"338":1,"387":1,"407":1,"424":1,"446":1,"470":2,"491":1,"560":1,"617":1,"619":1,"629":1,"656":1,"666":1,"675":1,"677":1,"708":1,"745":1}}],["alguns",{"2":{"49":1,"55":1,"90":1,"99":1,"110":1,"111":1,"116":1,"117":1,"156":1,"219":1,"235":1,"245":1,"271":1,"279":2,"291":1,"299":2,"320":1,"328":1,"334":1,"339":2,"341":1,"349":1,"365":1,"375":1,"385":1,"407":1,"420":1,"440":1,"445":2,"524":1,"531":1,"532":1,"534":1,"544":1,"545":1,"550":1,"555":1,"567":1,"573":1,"669":1,"674":1,"677":1,"680":1,"701":1,"721":1}}],["alguém",{"2":{"31":1,"32":1,"33":1,"349":1,"490":1}}],["alt",{"2":{"279":1,"299":1,"402":1}}],["altura",{"0":{"233":1,"260":1},"1":{"261":1,"262":1,"263":1},"2":{"110":1,"111":4,"120":3,"227":1,"229":1,"233":6,"260":1,"261":1,"328":1,"333":1,"339":1,"348":1,"403":1,"434":1,"503":1,"509":1,"543":1,"756":1}}],["altas",{"2":{"619":1}}],["alta",{"2":{"46":1,"320":1,"325":1,"334":1,"365":1,"371":1,"679":1,"691":1}}],["altamente",{"2":{"42":3,"43":1,"47":1,"143":1,"165":1,"183":1,"331":1,"742":1}}],["alto",{"2":{"43":1,"55":1,"446":1,"541":1,"688":1}}],["alterou",{"2":{"654":1}}],["altere",{"2":{"111":1,"134":1,"221":1,"444":1,"574":1,"656":1}}],["alternativelayoutbuttoncontainer",{"2":{"244":2}}],["alternativas",{"2":{"700":1}}],["alternativa",{"2":{"133":1,"399":1,"456":1,"471":1,"493":1}}],["alternativamente",{"2":{"126":1,"131":1,"325":1,"371":1,"402":1,"404":1}}],["alternar",{"2":{"38":2,"39":1,"191":1,"200":1,"216":1}}],["alterne",{"2":{"38":1,"39":1,"533":1}}],["alternância",{"2":{"11":1,"244":1}}],["alteradas",{"2":{"734":1}}],["alterada",{"2":{"259":2,"424":1}}],["alterados",{"2":{"251":1,"730":1}}],["alterado",{"2":{"11":1,"111":1,"242":1,"602":1,"603":1,"611":1,"612":1,"618":1,"645":1,"646":1}}],["alterando",{"2":{"200":1}}],["alteração",{"2":{"71":1,"101":1,"341":1,"654":1,"681":1,"682":1,"723":1,"748":1,"751":1}}],["alterações",{"0":{"76":1,"729":1},"2":{"10":2,"20":1,"27":3,"60":1,"73":1,"77":3,"112":1,"113":1,"153":1,"178":1,"196":1,"213":1,"216":1,"273":1,"293":1,"458":2,"467":1,"469":1,"482":2,"654":1,"681":1,"686":1,"722":1,"723":1,"725":1,"726":4}}],["alterarão",{"2":{"681":1}}],["alterar",{"2":{"68":1,"96":1,"105":1,"111":2,"200":1,"203":2,"228":1,"244":1,"328":1,"349":1,"443":1,"444":1,"463":1,"487":1,"493":1,"576":1,"654":1,"702":1}}],["altera",{"2":{"10":1,"68":1,"444":1,"680":1}}],["além",{"0":{"460":1,"484":1},"1":{"461":1,"462":1,"463":1,"485":1,"486":1,"487":1},"2":{"38":1,"50":2,"115":1,"120":1,"128":1,"191":1,"219":1,"235":1,"278":1,"298":1,"330":1,"455":1,"456":1,"464":1,"470":1,"480":1,"511":1,"539":1,"556":1,"595":1,"675":1,"678":1,"680":1,"691":1,"747":1}}],["anonymous",{"2":{"660":2,"685":1}}],["anos",{"2":{"638":1,"688":1}}],["anotações",{"2":{"461":1,"485":3}}],["anotação",{"0":{"424":1},"2":{"421":1,"424":5,"434":1}}],["anotar",{"2":{"338":1,"650":1}}],["anotados",{"2":{"424":1,"454":1,"561":1}}],["anotado",{"2":{"93":1,"424":1}}],["ansioso",{"2":{"604":1,"613":1,"622":1,"647":1}}],["answer",{"2":{"390":1}}],["anônima",{"0":{"511":1}}],["análises",{"2":{"670":1}}],["análise",{"0":{"672":1},"2":{"479":1,"553":1,"670":1,"672":2}}],["análogos",{"2":{"462":1,"486":1}}],["análogo",{"2":{"387":1}}],["an",{"2":{"430":4,"431":1,"467":2,"479":1,"488":1,"680":1}}],["anexar",{"2":{"338":1,"437":1}}],["analise",{"2":{"542":1}}],["analisam",{"2":{"672":1}}],["analisados",{"2":{"572":1}}],["analisado",{"2":{"572":1}}],["analisa",{"2":{"452":1}}],["analisar",{"2":{"43":1,"46":1,"525":1}}],["analyzing",{"2":{"313":1,"358":1}}],["annotations",{"2":{"431":3}}],["annotation",{"2":{"256":1,"429":1,"431":2}}],["andamento",{"2":{"692":3}}],["and",{"0":{"250":1},"2":{"313":1,"349":2,"358":1,"431":2,"454":2,"548":1,"574":1,"617":1,"663":1,"706":1,"748":2}}],["androidruntime",{"2":{"685":7}}],["androidpara",{"2":{"436":1}}],["android=",{"2":{"403":1}}],["androidmanifest",{"2":{"73":1,"256":1,"272":2,"273":1,"292":2,"293":1,"402":1,"553":1}}],["androidx",{"2":{"65":1,"429":1,"430":2,"431":4}}],["android",{"0":{"4":1,"7":1,"10":1,"26":1,"27":1,"30":1,"37":2,"38":1,"65":1,"72":1,"133":1,"140":1,"141":1,"142":1,"147":1,"163":1,"167":1,"168":1,"172":1,"201":1,"202":1,"203":1,"207":1,"264":1,"283":1,"286":1,"303":1,"378":1,"400":1,"420":1,"428":1,"438":1,"449":1,"456":1,"552":1,"563":1,"597":1,"606":1,"633":1,"634":1,"640":1,"658":1,"661":1,"743":1,"747":1,"750":1,"766":1,"767":1},"1":{"73":1,"74":1,"141":1,"142":1,"148":1,"149":1,"164":1,"165":1,"166":1,"167":1,"168":1,"169":1,"170":1,"171":1,"172":1,"173":2,"174":2,"175":1,"176":1,"177":1,"178":1,"179":1,"180":1,"202":1,"203":1,"208":1,"209":1,"265":1,"266":1,"267":1,"268":1,"269":1,"270":1,"271":1,"272":1,"273":1,"274":1,"275":1,"276":1,"277":1,"278":1,"279":1,"280":1,"281":1,"282":1,"283":1,"284":1,"287":1,"288":1,"289":1,"290":1,"291":1,"292":1,"293":1,"294":1,"295":1,"296":1,"297":1,"298":1,"299":1,"300":1,"301":1,"302":1,"303":1,"304":1,"401":1,"402":1,"403":1,"404":1,"405":1,"406":1,"421":1,"422":1,"423":1,"424":1,"425":1,"426":1,"427":1,"428":1,"429":2,"430":2,"431":2,"432":2,"433":2,"434":2,"450":1,"451":1,"452":1,"453":1,"454":1,"455":1,"456":1,"457":2,"458":1,"459":1,"460":1,"461":1,"462":1,"463":1,"464":1,"465":1,"466":1,"467":1,"468":1,"469":1,"553":1,"554":1,"555":1,"598":1,"599":1,"600":1,"601":1,"602":1,"603":1,"604":1,"607":1,"608":1,"609":1,"610":1,"611":1,"612":1,"613":1,"641":1,"642":1,"643":1,"644":1,"645":1,"646":1,"647":1,"662":1,"767":1,"768":1},"2":{"0":3,"2":1,"7":1,"11":1,"15":1,"34":1,"35":3,"37":1,"38":7,"51":1,"58":2,"60":1,"64":1,"65":4,"67":5,"71":1,"73":10,"74":6,"76":1,"77":1,"79":1,"85":2,"126":2,"131":1,"133":1,"137":3,"140":2,"141":5,"142":20,"145":1,"147":6,"148":1,"149":5,"152":4,"156":1,"158":2,"159":2,"160":1,"161":1,"162":1,"164":3,"167":5,"168":18,"170":1,"172":6,"173":1,"174":5,"177":4,"199":3,"200":1,"201":2,"202":5,"203":20,"205":1,"207":6,"208":1,"209":5,"212":4,"240":1,"241":1,"244":1,"245":4,"247":1,"256":4,"259":23,"265":2,"266":1,"267":2,"270":4,"271":2,"272":3,"273":2,"274":1,"278":3,"279":9,"282":1,"283":9,"285":2,"287":2,"288":3,"290":4,"291":2,"292":3,"293":2,"294":1,"298":3,"299":8,"302":1,"303":9,"328":2,"329":1,"330":2,"347":2,"378":3,"379":2,"382":1,"384":1,"385":2,"386":4,"387":1,"400":1,"401":1,"402":7,"403":5,"404":8,"405":2,"406":1,"415":1,"417":1,"419":2,"420":1,"428":1,"429":11,"430":8,"431":8,"436":3,"437":2,"438":1,"447":1,"448":2,"449":1,"450":1,"451":7,"452":2,"453":1,"454":3,"456":5,"457":3,"459":2,"462":1,"466":1,"469":1,"470":3,"471":1,"512":1,"514":1,"520":2,"523":1,"529":1,"551":1,"552":5,"553":2,"555":3,"561":1,"562":7,"563":5,"565":2,"566":2,"570":1,"574":5,"579":1,"581":2,"590":2,"591":2,"595":2,"596":3,"598":1,"599":2,"600":3,"602":1,"604":1,"605":1,"607":1,"608":3,"609":3,"611":1,"613":1,"631":1,"633":2,"634":6,"635":2,"636":1,"641":1,"642":2,"643":3,"645":1,"647":1,"648":3,"652":3,"653":2,"654":4,"655":2,"656":4,"657":1,"658":1,"659":2,"660":2,"662":5,"669":1,"679":2,"682":1,"685":4,"699":1,"710":3,"712":1,"713":1,"716":3,"719":1,"731":1,"739":1,"743":2,"746":1,"747":4,"750":1,"754":1,"764":1,"765":1}}],["ancestral",{"2":{"90":2,"99":2,"122":2}}],["ancestrais",{"2":{"60":1}}],["antigo",{"2":{"638":1,"668":1}}],["antigos",{"0":{"658":1},"2":{"426":1}}],["antigas",{"0":{"746":1},"1":{"747":1,"748":1},"2":{"746":1}}],["antiga",{"0":{"729":1},"2":{"190":1,"383":1,"658":1}}],["antiquewhite",{"2":{"88":1}}],["antecipadamente",{"2":{"337":1,"520":1}}],["anteriormente",{"2":{"117":1,"145":1,"170":1,"189":1,"205":1,"424":1,"636":1}}],["anteriores",{"2":{"92":1,"101":1,"221":1,"696":1}}],["anterior",{"2":{"48":1,"69":1,"95":1,"104":1,"420":1,"440":1,"464":1,"488":1,"531":2,"554":1,"559":1,"655":1,"658":1,"681":1,"689":1,"692":1,"739":1,"746":1}}],["antes",{"2":{"20":1,"47":2,"56":1,"62":1,"67":1,"112":1,"130":1,"156":1,"203":1,"231":1,"252":1,"258":1,"283":1,"303":1,"313":1,"323":1,"358":1,"369":1,"376":1,"442":1,"479":1,"487":1,"518":1,"525":1,"534":1,"538":1,"548":1,"553":1,"570":1,"572":2,"574":2,"577":1,"578":1,"603":1,"605":1,"612":1,"637":1,"646":1,"648":2,"652":1,"655":1,"670":1,"671":1,"673":1,"675":1,"699":1,"742":1,"746":1}}],["any>",{"2":{"427":1,"463":1}}],["anyobject",{"2":{"365":1}}],["any",{"2":{"74":1,"77":1,"367":1,"430":5,"491":1,"493":1}}],["aninhadas",{"2":{"675":1}}],["aninhado",{"2":{"63":1,"384":1}}],["aninhados",{"2":{"52":1,"346":1}}],["aninha",{"2":{"387":1}}],["aninhar",{"2":{"346":2,"349":1}}],["aninhamento",{"0":{"339":1},"2":{"505":2}}],["animá",{"2":{"60":2}}],["animável",{"2":{"46":1}}],["animáveis",{"2":{"46":1}}],["anime",{"2":{"50":1}}],["anima",{"2":{"700":1}}],["animating=",{"2":{"692":1}}],["animation",{"2":{"541":1}}],["animationframe",{"2":{"392":1}}],["animate",{"2":{"60":1}}],["animatedgratuitousapp",{"2":{"59":1}}],["animatedvalue",{"2":{"56":2}}],["animated",{"0":{"46":1},"2":{"45":1,"46":10,"47":2,"48":7,"49":3,"50":1,"51":3,"52":4,"53":5,"54":6,"55":2,"56":5,"57":2,"58":1,"59":1,"60":1,"320":1,"365":1,"442":1,"443":2,"541":2,"545":1}}],["animar",{"0":{"543":1},"2":{"50":2,"57":1,"541":1,"543":1}}],["animada",{"2":{"47":1,"442":1}}],["animadas",{"2":{"45":1}}],["animados",{"0":{"49":1},"2":{"49":1,"51":2,"52":2,"56":1}}],["animado",{"0":{"53":1,"54":1},"2":{"46":4,"49":3,"51":2,"56":2,"559":1}}],["animação",{"0":{"55":1},"2":{"45":1,"46":4,"47":6,"48":3,"51":2,"55":3,"56":8,"57":3,"58":1,"60":1,"62":2,"113":1,"220":1,"541":1,"545":1,"553":2,"556":1,"558":1,"699":1,"700":3}}],["animações",{"0":{"45":1,"47":1,"48":1},"1":{"46":1,"47":1,"48":1,"49":1,"50":1,"51":1,"52":1,"53":1,"54":1,"55":1,"56":1,"57":1,"58":1,"59":1,"60":1,"61":1,"62":1,"63":1},"2":{"45":2,"47":3,"48":5,"55":1,"56":3,"58":1,"60":2,"62":1,"63":3,"77":3,"112":1,"113":2,"131":1,"534":1,"535":1,"541":3,"545":3,"559":1,"700":5,"757":1}}],["anúncios",{"2":{"11":1,"34":1}}],["anunciar",{"2":{"10":3,"27":3}}],["anuncia",{"2":{"4":1}}],["aos",{"0":{"446":1},"1":{"447":1,"448":1},"2":{"30":1,"70":1,"113":1,"331":1,"349":3,"374":1,"425":1,"441":2,"449":2,"465":1,"472":1,"474":2,"531":1,"534":1,"630":1,"635":1,"639":1,"679":1,"692":1,"708":1,"734":1,"741":1,"764":1}}],["ao",{"0":{"55":1,"269":1,"289":1,"311":1,"356":1,"401":1,"404":1,"540":1,"541":1,"601":1,"610":1,"618":1,"644":1,"695":1,"707":1,"733":1},"1":{"270":1,"290":1,"602":1,"603":1,"604":1,"611":1,"612":1,"645":1,"646":1,"647":1},"2":{"4":2,"5":1,"8":2,"11":4,"26":2,"34":3,"35":2,"42":2,"43":1,"46":1,"47":1,"52":1,"53":1,"55":2,"56":3,"57":1,"58":1,"63":1,"65":2,"67":2,"73":1,"74":3,"77":5,"79":1,"80":2,"87":1,"90":1,"96":1,"97":1,"99":1,"101":1,"105":3,"106":2,"107":1,"111":2,"112":1,"113":1,"118":1,"128":1,"133":1,"135":1,"139":1,"141":1,"142":4,"148":1,"149":1,"155":1,"166":1,"167":1,"168":4,"173":1,"174":1,"180":1,"189":1,"198":1,"200":1,"202":1,"203":3,"208":1,"209":1,"215":1,"223":1,"224":1,"225":2,"226":6,"227":7,"229":8,"230":3,"231":4,"236":1,"242":1,"245":2,"248":1,"249":3,"251":7,"255":1,"256":1,"258":1,"261":1,"265":1,"268":1,"270":1,"272":2,"273":2,"278":2,"279":2,"280":1,"283":1,"287":1,"288":1,"290":1,"292":2,"293":2,"298":2,"299":2,"300":1,"303":1,"306":1,"309":1,"310":1,"313":1,"317":1,"320":5,"321":1,"322":1,"325":2,"328":2,"329":1,"331":1,"336":2,"343":1,"344":1,"348":2,"349":3,"351":1,"354":1,"355":1,"358":1,"362":1,"365":5,"366":1,"367":1,"368":1,"371":2,"374":1,"376":1,"377":1,"389":2,"399":1,"403":1,"404":6,"407":1,"409":1,"413":1,"421":1,"422":1,"424":1,"427":1,"428":1,"437":3,"441":4,"442":3,"443":1,"445":1,"449":1,"450":1,"452":1,"453":2,"454":2,"456":1,"457":3,"461":1,"464":1,"465":1,"471":1,"472":1,"473":1,"474":1,"477":3,"478":2,"479":1,"481":3,"485":1,"487":1,"488":1,"489":1,"491":1,"493":4,"501":1,"516":1,"521":1,"524":1,"533":1,"534":1,"538":1,"542":1,"546":1,"547":1,"548":1,"549":1,"552":1,"553":2,"556":1,"561":1,"567":2,"574":1,"576":1,"577":1,"579":1,"588":1,"595":1,"599":1,"601":1,"602":1,"603":3,"604":1,"608":1,"610":1,"611":1,"612":3,"613":1,"615":1,"619":3,"621":1,"622":1,"628":2,"629":3,"632":1,"634":1,"635":2,"636":2,"637":1,"638":2,"639":2,"642":1,"644":1,"645":1,"646":3,"647":1,"650":1,"658":2,"659":2,"660":2,"663":1,"666":1,"668":1,"669":1,"672":1,"675":2,"676":1,"678":1,"680":1,"681":2,"683":1,"685":1,"686":1,"687":1,"691":2,"693":1,"699":3,"700":1,"701":1,"705":1,"706":3,"707":1,"726":3,"729":1,"730":2,"731":1,"732":1,"733":1,"734":2,"736":1,"737":1,"739":1,"740":1,"741":1,"745":4,"748":1,"749":1}}],["a",{"0":{"96":1,"105":1,"117":1,"218":1,"255":1,"256":1,"267":1,"279":1,"299":1,"308":1,"318":1,"353":1,"363":1,"380":1,"383":1,"422":1,"424":1,"431":1,"496":1,"520":1,"539":1,"563":1,"564":1,"598":1,"607":1,"616":1,"641":1,"655":1,"682":1,"687":1,"695":1,"696":1,"697":1,"734":1,"737":1},"1":{"319":1,"320":1,"321":1,"364":1,"365":1,"366":1,"367":1,"381":1,"382":1,"383":1,"497":1,"498":1,"499":1,"500":1,"501":1,"502":1,"503":1,"504":1,"505":1,"506":1,"507":1,"508":1,"509":1,"510":1,"511":1,"688":1,"689":1,"690":1,"691":1,"692":1,"693":1,"694":1,"695":1,"696":1,"697":2},"2":{"0":1,"2":3,"3":1,"4":1,"6":1,"7":1,"8":2,"9":1,"10":1,"11":2,"14":4,"15":1,"19":1,"20":1,"24":1,"30":2,"31":2,"32":1,"33":4,"34":4,"35":10,"36":2,"38":2,"43":2,"44":2,"45":2,"46":9,"47":4,"48":4,"49":3,"50":7,"51":1,"52":1,"53":1,"55":7,"56":7,"57":1,"58":1,"60":1,"63":5,"64":1,"65":4,"67":9,"68":2,"69":6,"71":2,"73":1,"74":7,"75":1,"76":1,"77":14,"88":2,"89":1,"90":2,"91":1,"92":3,"94":1,"95":3,"96":1,"98":1,"99":2,"100":1,"101":4,"102":1,"103":1,"104":3,"105":1,"106":3,"108":1,"110":1,"111":16,"112":6,"113":10,"114":2,"115":3,"116":4,"118":2,"119":1,"120":8,"121":2,"122":3,"123":1,"129":2,"130":1,"131":2,"133":2,"134":3,"135":1,"136":1,"139":1,"141":5,"142":10,"143":1,"144":2,"145":1,"149":4,"151":3,"152":1,"153":1,"155":2,"156":2,"159":2,"166":2,"167":5,"168":10,"169":2,"170":1,"174":3,"176":3,"177":1,"178":1,"180":2,"184":3,"185":1,"186":3,"187":2,"188":2,"189":3,"191":7,"193":3,"194":1,"198":2,"200":3,"202":5,"203":12,"204":2,"205":1,"209":3,"211":3,"212":1,"213":1,"215":2,"216":3,"217":4,"218":7,"219":1,"220":4,"221":7,"223":8,"224":7,"225":9,"226":2,"227":3,"228":1,"229":1,"230":2,"231":1,"233":10,"234":3,"235":1,"236":1,"241":1,"242":7,"243":1,"244":2,"245":2,"247":2,"248":1,"251":10,"252":1,"255":2,"256":2,"257":1,"258":2,"259":5,"260":2,"261":1,"262":4,"265":1,"270":2,"271":2,"273":4,"275":1,"278":2,"279":8,"283":1,"285":1,"287":1,"288":1,"290":2,"291":2,"293":4,"295":1,"298":2,"299":7,"303":1,"306":1,"311":1,"312":1,"313":8,"315":1,"318":4,"319":1,"320":4,"321":1,"323":1,"325":4,"328":6,"329":2,"330":2,"332":1,"334":8,"336":4,"337":3,"338":4,"339":4,"341":4,"343":2,"344":1,"345":3,"347":1,"348":3,"349":8,"351":1,"356":1,"357":1,"358":8,"360":1,"363":3,"364":1,"365":5,"366":1,"367":1,"369":1,"371":5,"374":1,"375":3,"376":1,"377":3,"379":2,"381":3,"382":1,"383":2,"384":1,"386":2,"387":3,"389":1,"390":10,"399":5,"400":1,"401":3,"402":4,"403":2,"404":2,"406":1,"407":2,"411":1,"412":1,"414":1,"417":3,"419":3,"420":3,"421":4,"422":2,"423":1,"424":7,"425":1,"426":4,"427":3,"428":2,"431":2,"434":4,"435":3,"437":1,"438":1,"439":1,"440":3,"441":10,"442":18,"443":5,"444":3,"445":1,"446":2,"447":1,"448":3,"449":3,"450":2,"451":1,"452":8,"454":4,"455":2,"456":3,"457":3,"459":1,"461":3,"462":3,"463":5,"464":6,"465":7,"466":1,"467":1,"468":1,"469":3,"470":5,"471":5,"472":1,"474":3,"475":2,"476":1,"477":7,"478":1,"479":8,"480":2,"481":3,"483":1,"485":4,"486":1,"487":7,"488":7,"489":4,"490":3,"491":6,"492":1,"493":2,"495":2,"497":4,"498":1,"500":4,"501":3,"502":5,"503":1,"507":1,"509":3,"510":1,"511":4,"512":1,"513":1,"514":1,"515":1,"516":2,"518":1,"519":2,"520":9,"521":2,"522":1,"523":2,"524":2,"525":3,"526":1,"527":1,"529":2,"530":1,"531":7,"532":5,"533":7,"534":8,"535":2,"539":4,"540":1,"541":4,"542":2,"543":4,"544":3,"545":12,"546":2,"547":1,"548":6,"549":5,"550":2,"551":3,"552":3,"553":4,"554":3,"555":2,"556":5,"557":1,"558":2,"559":3,"560":5,"561":1,"562":5,"563":4,"564":3,"566":2,"567":2,"570":1,"571":3,"572":2,"573":2,"574":2,"576":3,"577":3,"580":1,"581":1,"582":1,"583":1,"584":1,"585":1,"586":2,"587":1,"588":1,"592":1,"594":2,"595":3,"596":9,"598":4,"601":2,"602":1,"603":2,"604":1,"607":4,"608":5,"610":2,"611":1,"612":2,"613":1,"615":2,"616":1,"619":1,"621":1,"622":1,"626":1,"628":6,"629":6,"633":1,"634":3,"635":5,"636":9,"637":2,"638":3,"639":2,"641":4,"644":2,"645":1,"646":2,"647":1,"648":3,"650":1,"651":2,"653":3,"654":6,"655":5,"656":4,"658":3,"659":3,"660":2,"662":3,"663":2,"664":1,"666":5,"667":5,"668":2,"669":2,"670":2,"671":3,"672":7,"673":7,"674":5,"675":6,"676":2,"677":1,"678":7,"679":5,"680":4,"681":7,"682":3,"683":1,"685":1,"686":1,"687":5,"688":3,"689":5,"690":9,"691":5,"692":4,"693":6,"694":2,"695":9,"696":9,"697":3,"699":2,"700":2,"702":1,"703":1,"704":1,"706":2,"707":1,"708":2,"711":2,"715":1,"716":1,"717":3,"718":3,"719":1,"721":1,"722":1,"723":1,"724":1,"726":3,"728":1,"730":2,"731":3,"732":1,"734":1,"737":1,"739":1,"741":3,"742":1,"744":1,"746":4,"747":3,"748":1,"751":1,"762":1,"769":1}}],["asas",{"2":{"673":1}}],["aspectos",{"2":{"445":1}}],["aspecto",{"2":{"265":1,"287":1,"306":1,"351":1}}],["asynclocalstoragequeue",{"2":{"491":1}}],["async",{"2":{"255":1,"257":1,"390":2,"465":2,"489":2,"491":2,"520":3,"630":2}}],["aslist",{"2":{"92":2}}],["assync",{"2":{"630":1}}],["associadas",{"2":{"320":1,"365":1}}],["associado",{"2":{"3":1}}],["assumiremos",{"2":{"375":1}}],["assumir",{"2":{"233":1}}],["assunto",{"2":{"78":1,"533":1}}],["assíncronos",{"2":{"464":1,"469":1,"479":1,"488":1,"509":1}}],["assíncrono",{"0":{"630":1},"2":{"120":1,"121":1,"630":2,"632":1,"634":1}}],["assíncronas",{"2":{"491":1}}],["assíncrona",{"2":{"55":1,"56":1,"255":1,"455":1,"464":1,"465":1,"480":1,"488":2,"489":1,"520":2,"690":1,"693":1}}],["assert",{"2":{"675":1}}],["assertive",{"2":{"10":2,"27":2}}],["asserções",{"2":{"537":1}}],["assetcatalog",{"2":{"722":1}}],["assetexts",{"2":{"399":3}}],["asset",{"2":{"330":1,"337":1}}],["assetsexts",{"2":{"329":1}}],["assets",{"2":{"283":2,"303":2,"329":1,"330":1,"348":1,"387":1,"662":1}}],["assembledebug",{"2":{"65":1}}],["assincronicidade",{"2":{"699":1}}],["assincrono",{"2":{"630":1}}],["assinando",{"2":{"648":1}}],["assinadas",{"2":{"638":1,"653":1}}],["assinados",{"2":{"638":1,"648":1}}],["assinado",{"2":{"604":1,"613":1,"638":1,"647":1,"648":2}}],["assinatura",{"0":{"616":1,"653":1},"2":{"490":1,"636":1,"648":1,"649":1,"653":1,"654":2,"655":1,"658":3}}],["assinar",{"2":{"490":1,"650":1,"652":1}}],["assign",{"2":{"390":2,"393":1}}],["assistente",{"2":{"141":1,"167":1,"202":1}}],["assista",{"2":{"42":1}}],["assistiva",{"2":{"11":1,"12":1,"35":3}}],["assistivas",{"2":{"0":1,"20":1,"27":1,"35":1}}],["assim",{"2":{"30":1,"50":2,"67":1,"111":1,"114":1,"244":1,"255":2,"282":1,"302":1,"328":1,"349":1,"407":1,"420":1,"440":1,"442":1,"446":1,"453":1,"461":1,"465":1,"467":1,"478":2,"485":1,"489":1,"516":1,"538":1,"553":1,"554":1,"556":2,"566":1,"573":1,"608":1,"638":1,"666":2,"667":1,"681":1,"682":1,"692":2}}],["as",{"0":{"665":1,"724":1,"729":1},"1":{"666":1,"667":1},"2":{"0":1,"3":1,"6":2,"7":1,"20":2,"27":1,"35":2,"38":1,"39":1,"41":2,"43":3,"44":2,"45":2,"47":2,"48":3,"50":1,"51":1,"53":1,"55":1,"60":2,"62":3,"63":2,"65":2,"67":7,"68":3,"73":1,"74":1,"77":2,"79":1,"80":1,"89":1,"91":1,"92":3,"93":1,"94":1,"95":1,"96":2,"98":1,"100":1,"101":2,"102":1,"103":1,"104":1,"105":4,"106":2,"108":1,"111":3,"121":1,"122":1,"128":3,"131":1,"134":2,"137":1,"138":1,"140":1,"141":2,"142":2,"148":1,"159":1,"164":1,"166":1,"167":2,"168":2,"173":1,"182":1,"184":1,"185":2,"189":2,"191":1,"195":1,"199":1,"201":1,"202":2,"203":1,"208":1,"221":1,"223":1,"224":1,"227":1,"228":1,"229":7,"230":1,"231":1,"232":2,"237":1,"240":1,"242":1,"244":1,"249":1,"259":3,"261":2,"263":1,"265":1,"268":1,"273":1,"278":1,"279":1,"280":1,"285":1,"287":1,"288":2,"293":1,"298":1,"299":1,"300":1,"306":1,"309":1,"312":2,"313":1,"320":1,"322":1,"328":5,"329":1,"330":1,"331":1,"333":1,"337":2,"340":1,"347":1,"348":1,"351":1,"354":1,"357":2,"358":1,"365":2,"368":1,"374":1,"375":2,"377":1,"379":3,"384":1,"386":1,"387":1,"398":3,"402":2,"404":2,"407":1,"421":1,"423":1,"424":2,"427":2,"428":1,"431":2,"437":1,"441":3,"442":2,"443":1,"445":2,"446":1,"448":3,"451":1,"452":2,"454":1,"458":1,"461":1,"463":1,"470":1,"471":1,"472":1,"479":3,"482":1,"485":1,"486":1,"487":1,"491":2,"493":3,"499":2,"501":1,"505":1,"507":1,"523":1,"524":1,"525":1,"529":1,"531":6,"534":4,"535":1,"538":2,"540":2,"541":1,"545":2,"549":2,"550":1,"551":1,"553":3,"554":1,"555":1,"556":1,"557":1,"562":3,"569":1,"570":1,"573":1,"574":1,"576":2,"577":1,"581":1,"586":1,"595":1,"596":1,"603":1,"612":1,"628":1,"635":1,"636":2,"638":1,"646":1,"648":2,"652":3,"653":1,"656":2,"658":1,"660":1,"662":1,"665":1,"673":3,"674":1,"675":1,"676":1,"678":1,"680":1,"682":5,"685":1,"689":2,"690":2,"691":2,"692":3,"696":1,"700":3,"704":1,"706":3,"708":1,"722":1,"724":2,"725":2,"726":2,"731":1,"734":2,"745":3,"751":1,"762":1}}],["acrescentado",{"2":{"681":1}}],["acrescentar",{"2":{"477":1}}],["acreditamos",{"2":{"337":1,"683":1}}],["acariciado",{"2":{"349":1}}],["acabará",{"2":{"678":1}}],["acabar",{"2":{"117":1,"389":1,"491":1}}],["accept",{"2":{"519":1}}],["access",{"2":{"571":1,"652":1}}],["accessrole",{"2":{"34":1}}],["accesslabel",{"2":{"3":1}}],["accessibility",{"2":{"38":2,"39":1}}],["accessibilityeventtypes",{"2":{"37":1}}],["accessibilityelementshidden",{"0":{"15":1},"2":{"15":1}}],["accessibilityinfo",{"2":{"36":2}}],["accessibilityactions=",{"2":{"35":1}}],["accessibilityactions",{"2":{"35":2}}],["accessibilityviewismodal",{"0":{"14":1},"2":{"14":2}}],["accessibilityvalue",{"0":{"13":1},"2":{"13":1}}],["accessibilitystate",{"0":{"12":1},"2":{"12":1}}],["accessibilityrole",{"0":{"11":1},"2":{"11":2}}],["accessibilityliveregion=",{"2":{"10":2}}],["accessibilityliveregion",{"0":{"10":1},"2":{"10":1}}],["accessibilitylanguage=",{"2":{"8":1}}],["accessibilitylanguage",{"0":{"8":1},"2":{"8":1}}],["accessibilitylabelledby=",{"2":{"4":1}}],["accessibilitylabelledby",{"0":{"4":1}}],["accessibilitylabel=",{"2":{"3":1,"4":1,"5":1,"8":1,"737":2}}],["accessibilitylabel",{"0":{"3":1},"2":{"3":2}}],["accessibilityhint=",{"2":{"5":1}}],["accessibilityhint",{"0":{"5":1},"1":{"6":1,"7":1}}],["accessible=",{"2":{"2":1,"3":1,"5":1,"8":1,"35":1}}],["accessible",{"0":{"2":1}}],["access=",{"2":{"2":1}}],["accordingly",{"2":{"313":1}}],["act",{"2":{"675":1}}],["actnw",{"2":{"259":9}}],["activityindicator",{"2":{"520":2,"692":1}}],["activityeventlistener",{"2":{"467":4,"468":1}}],["activity>",{"2":{"279":1,"299":1}}],["activity",{"2":{"259":2,"272":1,"279":4,"292":1,"298":1,"299":5,"400":2,"402":2,"403":6,"404":9,"405":1,"431":4,"467":24,"468":6}}],["activitymanager",{"2":{"259":13}}],["activenetworkinfo",{"2":{"259":1}}],["activenetwork",{"2":{"259":1}}],["active",{"2":{"65":2,"328":4}}],["activate",{"2":{"35":1}}],["actionsheetios",{"2":{"313":1}}],["actions",{"2":{"168":1,"203":1}}],["action",{"2":{"35":3,"259":1,"278":1,"298":1,"467":2}}],["actionname",{"2":{"35":1}}],["acquirewakelocknow",{"2":{"258":1,"259":2}}],["aceitos",{"2":{"638":1}}],["aceite",{"2":{"479":1,"654":1,"668":1}}],["aceitação",{"2":{"687":1}}],["aceitar",{"2":{"672":1}}],["aceitas",{"2":{"638":1}}],["aceitam",{"2":{"442":1,"486":1,"668":1}}],["aceita",{"2":{"62":1,"231":2,"278":1,"298":1,"338":1,"348":1,"462":1,"486":1,"488":2,"562":1}}],["acertos",{"2":{"67":2}}],["acelerar",{"2":{"69":1,"256":1,"451":1}}],["acelerando",{"0":{"64":1,"665":1},"1":{"65":1,"66":1,"67":1,"68":1,"69":1,"70":1,"666":1,"667":1},"2":{"762":2}}],["aceleração",{"2":{"47":2,"149":2}}],["acessórios",{"2":{"348":1,"404":1,"498":1,"542":1,"681":1}}],["acessada",{"2":{"463":1,"487":1,"629":1}}],["acessados",{"2":{"629":1}}],["acessado",{"2":{"453":2,"464":1,"478":2,"488":1,"739":1}}],["acessando",{"0":{"126":1,"436":1},"2":{"200":1,"438":1,"457":1,"481":1,"598":1,"607":1,"641":1}}],["acessar",{"2":{"92":1,"126":1,"272":1,"292":1,"384":1,"399":1,"446":2,"448":1,"450":1,"457":2,"458":1,"461":2,"463":2,"475":1,"481":2,"482":1,"485":2,"487":2,"520":1,"529":2,"629":2,"639":1}}],["acessá",{"2":{"74":1,"77":1,"145":1,"170":1,"205":1,"436":1}}],["acesso",{"2":{"74":1,"77":1,"131":1,"320":1,"365":1,"442":1,"452":1,"487":1,"491":1,"601":1,"610":1,"629":2,"630":1,"635":1,"636":2,"639":1,"644":1,"689":1,"699":1,"717":1}}],["acessem",{"2":{"547":1}}],["acesse",{"2":{"38":1,"39":1,"144":1,"169":1,"188":1,"204":1,"551":1}}],["acessível",{"2":{"2":1,"3":1,"32":1,"478":1}}],["acessíveis",{"2":{"2":1,"40":1,"344":1,"682":1}}],["acessibilidadestate",{"2":{"11":1,"12":1}}],["acessibilidadeignoresinvertcolors",{"0":{"9":1}}],["acessibilidadehint",{"2":{"5":1,"6":1}}],["acessibilidadelabelledby",{"2":{"4":1}}],["acessibilidade",{"0":{"0":1,"1":1,"35":1,"37":1},"1":{"1":1,"2":2,"3":2,"4":2,"5":2,"6":2,"7":2,"8":2,"9":2,"10":2,"11":2,"12":2,"13":2,"14":2,"15":2,"16":2,"17":2,"18":2,"19":2,"20":2,"21":2,"22":2,"23":2,"24":2,"25":2,"26":2,"27":2,"28":2,"29":2,"30":2,"31":2,"32":2,"33":2,"34":2,"35":1,"36":1,"37":1,"38":1,"39":1,"40":1},"2":{"2":3,"5":2,"9":1,"10":3,"15":2,"24":2,"27":3,"30":5,"35":5,"37":2,"38":3,"39":3,"387":1,"680":1,"759":1}}],["acione",{"2":{"745":1}}],["acionou",{"2":{"636":1}}],["acionar",{"2":{"37":1,"55":1,"74":2,"94":1,"103":1,"112":1}}],["acionado",{"2":{"10":1,"113":1,"123":1,"349":1,"699":2}}],["acidentalmente",{"2":{"634":1}}],["acima",{"2":{"2":1,"3":1,"4":1,"6":1,"7":1,"10":1,"30":1,"50":1,"51":1,"166":1,"190":1,"195":1,"257":1,"278":1,"283":1,"298":1,"303":1,"320":1,"328":1,"329":1,"342":1,"349":1,"365":1,"399":1,"404":1,"434":1,"441":1,"444":1,"452":1,"458":1,"461":1,"462":1,"463":1,"465":1,"470":1,"473":1,"482":1,"485":1,"487":1,"489":1,"503":1,"520":1,"545":2,"554":1,"557":2,"608":2,"652":1,"655":1,"662":1,"678":1,"685":1,"690":1,"708":1,"716":1,"745":1}}],["aconselhável",{"2":{"681":1}}],["aconteça",{"2":{"678":1}}],["aconteceu",{"2":{"522":1}}],["acontecerá",{"2":{"249":1,"251":1}}],["acontecer",{"2":{"74":1,"430":4,"541":1,"634":1,"638":1,"721":1}}],["acontecendo",{"2":{"46":1,"221":1,"249":1,"251":1,"349":1,"573":1}}],["acontece",{"2":{"43":1,"220":1,"230":1,"251":1,"279":1,"299":1,"425":1,"529":3,"534":1,"555":1,"675":1,"680":1,"690":1}}],["acompanhamento",{"2":{"423":1}}],["acompanhar",{"2":{"349":1,"695":1}}],["acompanha",{"2":{"144":1,"145":1,"169":1,"170":1,"188":1,"204":1,"205":1}}],["acomode",{"2":{"0":1}}],["acordo",{"2":{"0":1,"223":1,"231":1,"234":1,"259":1,"586":1}}],["apagados",{"2":{"700":1}}],["aparentemente",{"2":{"349":1}}],["aparecendo",{"2":{"725":1}}],["aparecerem",{"2":{"725":1}}],["aparecerá",{"2":{"551":1,"617":1}}],["aparecerão",{"2":{"436":1}}],["aparecem",{"2":{"497":1}}],["aparece",{"2":{"37":1,"39":1,"46":1,"555":1,"679":1,"725":1}}],["aparência",{"0":{"737":1},"2":{"46":1,"245":1,"311":1,"356":1,"384":1,"386":1,"532":1,"533":1,"679":1}}],["aplique",{"2":{"273":1,"293":1}}],["aplicá",{"2":{"271":1,"291":1}}],["aplicações",{"2":{"421":1,"425":1}}],["aplicação",{"0":{"177":1},"2":{"320":1,"365":1,"425":1,"639":1}}],["aplicadas",{"2":{"377":1,"689":1}}],["aplicados",{"2":{"225":4}}],["aplicado",{"2":{"26":1}}],["aplicar",{"2":{"118":1,"227":1,"228":1,"581":1,"690":1}}],["aplicará",{"2":{"74":1,"399":1}}],["aplica",{"2":{"77":1,"90":1,"99":1,"112":1,"227":1,"421":1,"435":1,"520":1}}],["aplicativo",{"0":{"145":1,"150":1,"152":1,"153":1,"158":1,"170":1,"175":1,"178":1,"189":1,"192":1,"194":1,"196":1,"205":1,"210":1,"212":1,"213":1,"269":1,"282":1,"289":1,"302":1,"311":1,"325":1,"330":1,"356":1,"371":1,"382":1,"383":1,"401":1,"402":1,"549":1,"569":1,"600":1,"604":1,"609":1,"613":1,"617":1,"622":1,"643":1,"647":1,"653":1,"655":1,"729":1},"1":{"151":1,"152":1,"176":1,"177":1,"178":1,"180":1,"193":1,"194":1,"211":1,"212":1,"270":1,"290":1},"2":{"0":1,"11":1,"33":1,"34":1,"38":2,"39":2,"41":2,"42":5,"43":1,"44":2,"56":1,"59":1,"63":1,"64":1,"65":4,"74":1,"77":1,"90":1,"92":2,"95":2,"99":1,"101":4,"104":2,"110":2,"111":1,"119":1,"126":1,"127":1,"129":1,"130":1,"135":3,"137":2,"142":1,"145":2,"147":1,"152":2,"153":1,"154":1,"155":1,"156":2,"158":3,"159":1,"164":2,"168":1,"170":2,"172":1,"177":2,"178":1,"179":1,"180":1,"182":2,"184":1,"189":2,"194":2,"195":2,"196":2,"197":1,"198":1,"199":2,"203":1,"205":2,"207":1,"212":2,"213":1,"214":1,"215":1,"218":4,"242":1,"244":2,"245":2,"248":2,"249":2,"254":1,"255":1,"258":2,"259":4,"265":4,"270":2,"273":1,"274":1,"275":1,"276":1,"278":1,"279":1,"280":1,"281":1,"282":2,"283":4,"284":1,"285":1,"287":4,"290":2,"293":1,"294":1,"295":1,"296":1,"298":1,"299":1,"300":1,"301":1,"302":2,"303":4,"304":1,"306":5,"311":2,"313":3,"314":2,"315":1,"316":1,"317":1,"320":3,"322":1,"323":1,"324":1,"325":5,"326":1,"328":3,"330":3,"331":1,"344":2,"351":5,"356":2,"358":3,"359":2,"360":1,"361":1,"362":1,"365":3,"367":1,"368":1,"369":1,"370":1,"371":5,"372":1,"374":2,"376":1,"377":1,"378":1,"379":1,"385":1,"386":3,"400":4,"402":1,"403":1,"405":1,"406":1,"407":3,"409":1,"414":3,"417":1,"420":2,"428":1,"436":3,"437":3,"438":1,"439":1,"440":2,"441":1,"446":2,"447":3,"448":5,"451":2,"452":2,"454":2,"455":2,"456":5,"457":4,"458":2,"459":3,"465":1,"466":1,"470":1,"471":1,"472":1,"476":2,"477":1,"479":1,"480":2,"481":4,"482":2,"483":3,"490":1,"493":3,"497":2,"505":1,"520":2,"524":3,"525":4,"526":1,"529":3,"532":1,"533":1,"534":2,"538":1,"546":3,"547":4,"548":1,"549":4,"551":1,"553":2,"555":1,"556":2,"561":1,"562":1,"563":1,"567":1,"569":2,"570":1,"571":4,"575":1,"576":2,"578":1,"579":1,"580":1,"581":1,"585":1,"588":1,"595":1,"596":3,"598":1,"600":1,"602":1,"603":4,"604":2,"605":3,"607":1,"609":1,"611":1,"612":4,"613":2,"615":1,"617":2,"618":1,"621":1,"622":2,"624":1,"625":1,"626":1,"627":1,"628":3,"629":9,"630":2,"635":7,"636":3,"638":1,"639":1,"641":1,"643":1,"645":1,"646":3,"647":2,"648":4,"650":1,"652":2,"654":4,"655":1,"656":1,"657":2,"658":1,"659":1,"662":1,"665":1,"666":2,"667":4,"668":1,"670":1,"673":5,"677":1,"678":3,"679":2,"682":7,"683":1,"685":1,"686":1,"695":3,"698":1,"706":1,"709":1,"740":1,"742":2,"744":1,"745":2,"746":2,"747":2,"748":1}}],["aplicativos",{"0":{"41":1,"44":1,"285":1,"323":1,"369":1,"418":1,"658":1},"1":{"42":1,"43":1,"44":1},"2":{"0":1,"40":1,"41":3,"67":2,"71":2,"89":1,"98":2,"112":1,"142":1,"145":1,"147":1,"168":1,"170":1,"172":1,"189":1,"203":1,"205":1,"207":1,"243":1,"255":1,"266":1,"276":1,"285":1,"288":1,"296":1,"307":1,"316":1,"328":1,"331":1,"337":1,"347":1,"352":1,"361":1,"384":2,"385":1,"386":1,"389":1,"398":1,"400":1,"401":1,"414":1,"417":1,"418":2,"420":1,"440":1,"447":1,"471":1,"473":1,"517":1,"521":1,"524":1,"532":1,"534":1,"547":1,"569":1,"571":2,"595":2,"596":2,"598":1,"607":1,"628":1,"629":1,"630":3,"634":1,"635":3,"636":1,"638":1,"641":1,"648":2,"654":2,"658":1,"659":1,"666":2,"682":2,"683":1,"687":1,"696":1,"700":3,"704":1,"723":1,"735":1,"736":1,"740":1,"746":1,"754":1,"768":1}}],["apoio",{"2":{"534":1}}],["apoiado",{"2":{"114":1,"115":1}}],["apoiados",{"2":{"63":1,"114":1,"119":1,"386":2}}],["apoiar",{"2":{"35":1}}],["apontar",{"2":{"320":2,"365":2}}],["aponta",{"2":{"203":1,"471":1}}],["apkfiles",{"2":{"656":1}}],["apks",{"2":{"656":3}}],["apk",{"0":{"657":1},"2":{"65":1,"403":1,"604":1,"613":1,"647":1,"655":1,"656":4,"657":1,"659":1}}],["appicon",{"2":{"722":2}}],["appium",{"2":{"682":1,"684":1}}],["appauth",{"2":{"636":2}}],["appstore",{"2":{"656":1}}],["apps",{"2":{"452":4}}],["appdelegate",{"2":{"342":1,"367":3,"477":1,"548":1}}],["appcompat",{"2":{"279":3,"299":3}}],["appcompatactivity",{"2":{"279":1,"299":1}}],["appprocess",{"2":{"259":6}}],["appprocesses",{"2":{"259":5}}],["appproperties",{"2":{"92":2,"101":4}}],["appregistry",{"2":{"255":3,"277":2,"279":2,"297":2,"299":2,"313":1,"317":2,"358":1,"362":2,"404":1}}],["appname",{"2":{"110":1,"526":1}}],["applications",{"2":{"722":1}}],["applicationcontext",{"2":{"256":2}}],["application>",{"2":{"73":1,"273":1,"293":1}}],["application",{"2":{"73":1,"256":3,"259":2,"270":1,"273":1,"290":1,"293":1,"299":2,"367":2,"402":8,"404":2,"519":2,"524":2,"663":2}}],["appletv",{"2":{"76":1}}],["apple",{"0":{"546":1},"1":{"547":1,"548":1,"549":1,"550":1},"2":{"71":1,"76":4,"77":7,"168":1,"323":1,"369":1,"441":1,"446":1,"475":1,"514":1,"520":2,"546":1,"549":1,"550":1,"616":2,"617":1,"622":1,"635":1,"768":1}}],["applynativemodulesappbuildgradle",{"2":{"271":1,"291":1}}],["applynativemodulessettingsgradle",{"2":{"271":1,"291":1}}],["apply",{"2":{"68":1,"92":1,"142":1,"168":1,"203":1,"270":2,"271":2,"290":2,"291":2,"404":1,"427":1,"429":1,"433":1,"456":1,"466":1,"467":1,"574":1,"721":2}}],["app",{"0":{"546":1,"658":1},"1":{"547":1,"548":1,"549":1,"550":1},"2":{"53":2,"54":2,"60":1,"65":3,"67":1,"114":4,"115":4,"116":4,"122":4,"134":1,"153":1,"157":2,"178":1,"184":1,"196":1,"213":1,"231":2,"239":1,"248":1,"259":3,"271":1,"279":1,"283":2,"291":1,"299":1,"303":2,"323":1,"330":2,"369":1,"387":2,"402":2,"404":2,"430":2,"431":2,"452":2,"456":8,"520":4,"546":2,"547":1,"548":1,"549":7,"553":1,"574":1,"581":1,"605":1,"622":2,"635":4,"636":3,"648":2,"652":1,"653":1,"654":4,"656":1,"657":2,"658":2,"660":2,"662":3,"685":4,"704":1,"710":1,"722":1,"731":2,"733":1,"768":1}}],["aprimorados",{"2":{"693":1}}],["aprendido",{"2":{"683":1}}],["aprendizagem",{"2":{"673":1}}],["aprendendo",{"2":{"240":1}}],["aprenderá",{"2":{"525":1,"628":1}}],["aprender",{"2":{"131":1,"224":1,"226":1,"227":1,"229":1,"231":1,"242":1,"262":1,"347":1,"349":1,"384":1,"387":1,"414":1,"459":1,"483":1,"551":1,"654":1,"668":1,"730":1,"731":1}}],["aprendemos",{"2":{"89":1,"98":1}}],["apresentam",{"2":{"539":1}}],["apresentar",{"2":{"471":1,"730":1,"731":1}}],["apresentação",{"2":{"471":1}}],["apresenta",{"2":{"95":1,"104":1,"225":1}}],["apresentada",{"2":{"35":1}}],["apresentados",{"2":{"674":1}}],["apresentado",{"2":{"11":1,"34":1,"234":1}}],["apropriada",{"2":{"626":1}}],["apropriados",{"2":{"142":1,"168":1,"534":1}}],["apropriado",{"2":{"142":1,"524":1,"656":1}}],["aprofundar",{"2":{"343":1,"349":1,"445":1,"470":1}}],["aprovado",{"2":{"681":1}}],["aprovados",{"2":{"676":1}}],["aprová",{"2":{"278":1,"298":1}}],["aproveita",{"2":{"541":1}}],["aproveitar",{"2":{"41":1,"343":1,"437":1,"540":1,"658":1,"692":1,"695":1}}],["aproveite",{"2":{"80":1}}],["aproximadamente",{"2":{"65":1,"693":1}}],["api",{"0":{"46":1,"60":1,"255":1,"256":1,"273":1,"293":1},"2":{"36":1,"43":1,"46":1,"47":1,"48":2,"55":1,"56":1,"77":1,"149":1,"174":1,"209":1,"259":3,"273":1,"278":2,"293":1,"298":2,"333":1,"342":1,"387":2,"427":1,"435":1,"443":1,"446":2,"448":1,"467":1,"491":1,"517":1,"518":1,"520":1,"521":2,"534":1,"539":1,"541":1,"563":1,"629":6,"634":1,"675":1,"678":1,"710":1}}],["apis",{"0":{"80":1},"2":{"0":2,"62":2,"77":1,"80":1,"142":1,"168":2,"203":1,"374":3,"379":1,"384":1,"387":1,"446":1,"448":2,"450":1,"475":1,"479":1,"488":1,"518":1,"637":1,"679":1,"680":1,"682":1,"691":1,"695":1,"706":1,"717":1}}],["após",{"2":{"6":1,"7":1,"48":3,"74":1,"92":1,"165":1,"166":1,"183":1,"218":2,"251":1,"367":1,"464":1,"488":1,"549":1,"571":1,"576":1,"608":1,"635":1,"636":2,"689":1,"700":3,"709":1,"721":1,"724":1,"726":1}}],["apenas",{"0":{"65":1},"2":{"2":1,"5":1,"35":2,"42":1,"46":1,"53":1,"56":1,"57":1,"65":1,"67":2,"76":1,"86":1,"90":1,"92":1,"99":1,"101":1,"106":1,"112":1,"115":1,"217":2,"219":1,"222":1,"259":1,"333":1,"334":1,"358":1,"381":1,"385":1,"413":2,"421":1,"424":1,"435":1,"441":1,"443":1,"444":1,"463":1,"470":1,"478":1,"487":1,"488":3,"491":1,"493":1,"499":1,"505":1,"507":1,"512":1,"520":1,"523":1,"541":1,"561":1,"562":1,"571":1,"572":1,"576":2,"581":1,"586":1,"599":1,"608":1,"636":2,"638":2,"642":1,"675":1,"679":1,"681":2,"700":1,"730":1,"736":1}}],["oauth",{"2":{"636":2}}],["oauth2",{"0":{"636":1},"2":{"636":3}}],["omit",{"2":{"523":1}}],["o+",{"2":{"390":1}}],["og",{"2":{"331":2,"332":1,"334":1}}],["ok",{"2":{"244":1,"442":1,"467":2}}],["overview",{"2":{"684":1}}],["overlay",{"2":{"278":4,"298":4}}],["overrides",{"2":{"358":1}}],["override",{"2":{"92":4,"256":2,"259":2,"278":1,"279":7,"299":4,"402":7,"404":1,"422":2,"423":2,"424":1,"425":2,"427":1,"430":10,"431":10,"432":2,"433":1,"453":2,"456":5,"463":1,"467":5,"468":5}}],["overflow",{"2":{"53":1}}],["old",{"2":{"748":1}}],["oldlace",{"2":{"88":1,"224":1,"225":1,"226":1,"227":1,"228":1,"229":1,"230":1,"233":1,"234":1}}],["olá",{"2":{"242":1,"344":1,"345":1}}],["olivedrab",{"2":{"88":1}}],["olive",{"2":{"88":1}}],["olhar",{"2":{"576":1}}],["olhando",{"2":{"441":1}}],["olhada",{"2":{"47":1,"56":1,"344":1,"470":1,"519":1,"557":1,"654":1}}],["olho",{"2":{"77":1}}],["other",{"2":{"68":1,"135":1}}],["otimizá",{"2":{"63":1}}],["otimização",{"2":{"509":1,"532":1,"572":1}}],["otimizações",{"2":{"46":1,"55":1,"551":1}}],["otimizando",{"0":{"496":1},"1":{"497":1,"498":1,"499":1,"500":1,"501":1,"502":1,"503":1,"504":1,"505":1,"506":1,"507":1,"508":1,"509":1,"510":1,"511":1},"2":{"762":1}}],["otimizar",{"2":{"113":1,"490":1,"532":1,"539":1,"571":1}}],["otimizado",{"2":{"63":1,"389":1,"525":1,"740":1,"742":1}}],["otimizadas",{"0":{"508":1}}],["otimizada",{"2":{"46":1,"545":1}}],["orquestração",{"2":{"629":1}}],["orientação",{"2":{"696":1}}],["orientados",{"2":{"680":1}}],["orientado",{"2":{"674":1}}],["orientar",{"2":{"556":1}}],["orientaremos",{"2":{"448":1}}],["orientará",{"2":{"447":1}}],["orientando",{"2":{"420":1,"440":1}}],["origens",{"2":{"240":2}}],["origem",{"0":{"528":1,"660":1,"661":1,"663":1,"686":1},"1":{"661":1,"662":2,"663":1,"664":1},"2":{"122":1,"129":1,"135":1,"332":1,"334":4,"528":2,"660":7,"662":4,"663":2,"685":1,"686":2,"720":1,"755":1}}],["originar",{"2":{"191":1}}],["original",{"2":{"67":1,"113":1,"543":1,"636":1,"658":1,"660":2}}],["originalmente",{"2":{"67":1,"77":1}}],["ordem",{"2":{"219":1,"221":1,"635":1}}],["organizar",{"2":{"445":1,"561":1,"675":1}}],["organização",{"2":{"379":1}}],["organizações",{"2":{"64":1,"70":1}}],["organizados",{"2":{"347":1}}],["organizá",{"2":{"262":1}}],["org",{"2":{"200":1,"331":2,"332":1,"334":1,"415":1,"516":1,"654":1}}],["or",{"2":{"114":1,"135":2,"256":2,"259":2,"313":1,"357":1,"358":1,"748":1}}],["orchid",{"2":{"88":1}}],["orangered",{"2":{"88":1,"229":1,"230":1,"232":1}}],["orange",{"2":{"88":1,"229":1,"230":1,"232":1}}],["ocasiões",{"2":{"541":1}}],["ocasional",{"2":{"221":1}}],["ocorra",{"2":{"535":1}}],["ocorrência",{"2":{"69":1}}],["ocorrências",{"2":{"68":1,"704":1}}],["ocorrer",{"2":{"544":1}}],["ocorrerá",{"2":{"466":1,"490":1,"545":1,"575":1}}],["ocorrem",{"2":{"74":1,"77":1,"129":1,"523":1,"723":1}}],["ocorre",{"2":{"55":1,"114":1,"130":1,"329":1,"349":1,"427":1,"455":1,"458":1,"459":1,"480":1,"482":1,"497":1,"534":1}}],["ocupe",{"2":{"534":1}}],["ocupada",{"2":{"534":1}}],["ocupado",{"2":{"12":1}}],["ocupará",{"2":{"262":1}}],["ocultadas",{"2":{"128":2}}],["oculta",{"2":{"111":1}}],["ocultar",{"2":{"111":1}}],["ocultos",{"2":{"15":1,"24":1}}],["ofuscada",{"2":{"685":1}}],["ofereça",{"2":{"461":1,"485":1}}],["oferecem",{"2":{"245":1,"379":1,"656":1,"682":1,"732":1}}],["oferecerá",{"2":{"493":1,"696":1}}],["oferecer",{"2":{"77":2,"338":1,"407":1,"532":1,"629":1,"636":3}}],["oferece",{"2":{"50":1,"77":1,"126":1,"166":1,"473":1,"514":1,"522":1,"561":1,"675":1,"741":1,"745":1,"749":1}}],["of",{"2":{"313":2,"390":2,"427":2,"431":1,"599":1,"608":1,"636":1,"642":1,"660":2}}],["oficial",{"2":{"68":1,"343":1,"595":1,"656":1,"696":1}}],["oficiais",{"2":{"67":1}}],["offline",{"2":{"529":1,"599":1,"608":1,"642":1,"677":1}}],["off",{"2":{"27":3,"629":1}}],["onincrement",{"2":{"737":2}}],["onvaluechange=",{"2":{"692":2}}],["onvaluechange",{"2":{"692":2}}],["onviewcreated",{"2":{"428":1,"430":4}}],["onerror",{"2":{"522":1}}],["onopen",{"2":{"522":1}}],["onkeyup",{"2":{"279":2,"299":2}}],["onhostdestroy",{"2":{"279":1,"299":1,"468":2}}],["onhostresume",{"2":{"279":1,"299":1,"468":2}}],["onhostpause",{"2":{"279":1,"299":1,"468":2}}],["onbatchcomplete",{"2":{"555":1}}],["onbackpressed",{"2":{"279":4,"299":4}}],["onblur",{"2":{"74":1,"77":1}}],["onactivityresult",{"2":{"278":4,"298":4,"467":6}}],["onaccessibilityaction=",{"2":{"35":1}}],["onaccessibilityaction",{"2":{"35":2}}],["onaccessibilitytap",{"0":{"32":1}}],["onaccessibilityescape",{"0":{"31":1},"2":{"31":1}}],["onclose",{"2":{"522":1}}],["onclick",{"2":{"404":1}}],["onclicklistener",{"2":{"404":2}}],["onchange=",{"2":{"427":1}}],["onchangemessage",{"2":{"427":3}}],["onchange",{"2":{"427":7}}],["onchangetext",{"2":{"242":1,"680":1}}],["onchangetext=",{"2":{"231":3,"232":2,"242":1,"680":1}}],["oncreateview",{"2":{"430":4}}],["oncreate",{"2":{"278":1,"279":2,"298":1,"299":2,"402":4,"404":5,"430":2}}],["onreadystatechange",{"2":{"521":1}}],["onregionchange=",{"2":{"443":2}}],["onregionchange",{"2":{"443":13}}],["onresume",{"2":{"279":2,"299":2,"428":1,"430":6,"468":1}}],["onresponderterminate",{"2":{"251":1}}],["onresponderterminationrequest",{"2":{"251":2}}],["onresponderrelease",{"2":{"251":1}}],["onresponderreject",{"2":{"251":1}}],["onrespondermove",{"2":{"251":1}}],["onrespondergrant",{"2":{"251":1}}],["onreceivenativeevent",{"2":{"427":2}}],["onreceive",{"2":{"258":1,"259":3}}],["ondulações",{"2":{"245":1}}],["ondecrement",{"2":{"737":2}}],["ondestroy",{"2":{"279":2,"299":2,"430":6}}],["onde",{"0":{"738":1},"2":{"52":1,"166":1,"245":1,"250":1,"252":1,"349":1,"414":1,"451":1,"457":2,"470":1,"476":1,"481":2,"503":1,"526":1,"531":1,"532":2,"540":1,"541":1,"551":1,"552":1,"562":1,"575":1,"582":1,"583":1,"584":1,"635":2,"651":1,"690":2,"691":1,"697":1,"708":1,"722":1,"730":1,"745":2}}],["onfailure",{"2":{"464":1,"488":1}}],["onfail",{"0":{"122":1}}],["onfocus",{"2":{"74":2,"77":1}}],["onstartshouldsetrespondercapture",{"2":{"252":2}}],["onstartshouldsetresponder",{"2":{"251":1,"252":1}}],["onsubmit",{"2":{"465":1,"488":1,"489":1}}],["onsubmitediting",{"2":{"242":1}}],["onsuccess",{"0":{"122":1},"2":{"464":1,"488":1}}],["onscroll",{"2":{"57":1}}],["onscroll=",{"2":{"52":1,"53":1,"56":1}}],["onlongpress=",{"2":{"245":1}}],["onlongpressbutton",{"2":{"245":2}}],["onlongpress",{"2":{"245":1}}],["onlayout=",{"2":{"690":1}}],["onlayout",{"2":{"120":2,"689":2,"690":3}}],["only",{"2":{"65":2,"245":1,"334":2}}],["on",{"2":{"73":1,"76":2,"131":1,"135":1,"443":1,"491":1,"563":1,"680":1,"748":3}}],["onpause",{"2":{"279":2,"299":2,"428":1,"430":6,"468":1}}],["onpanresponderrelease",{"2":{"54":1}}],["onpanrespondermove",{"2":{"54":1}}],["onpressbutton",{"2":{"244":5,"245":6}}],["onpressout=",{"2":{"113":1}}],["onpressin=",{"2":{"113":1}}],["onpress",{"2":{"3":1,"5":1,"60":2,"74":1,"77":1,"113":1,"244":1,"349":2,"457":5,"464":3,"481":5,"488":2,"544":3,"679":1,"680":1}}],["onpress=",{"2":{"3":1,"5":1,"10":1,"60":1,"113":1,"116":2,"224":1,"225":1,"226":1,"227":1,"228":1,"229":1,"230":1,"233":2,"234":1,"244":5,"245":5,"349":3,"390":1,"444":1,"457":1,"481":1,"573":1,"680":1,"737":2}}],["onmessage",{"2":{"522":1}}],["onmoveshouldsetrespondercapture",{"2":{"252":1}}],["onmoveshouldsetresponder",{"2":{"251":1,"252":1}}],["onmoveshouldsetpanresponder",{"2":{"54":1}}],["onmagictap",{"0":{"33":1},"2":{"33":1}}],["oportunidade",{"2":{"675":1}}],["oposto",{"2":{"124":1}}],["opinativa",{"2":{"470":1}}],["optimized",{"2":{"573":2}}],["options",{"2":{"598":2,"607":1,"641":1}}],["optional",{"2":{"256":2,"390":2}}],["option",{"2":{"131":1}}],["optar",{"2":{"455":1,"456":1,"480":1,"695":1}}],["openid",{"2":{"636":1}}],["opengl",{"2":{"555":1}}],["openjdk17",{"2":{"200":1}}],["openjdk",{"2":{"139":1,"166":2}}],["open",{"2":{"131":1,"134":1,"436":1,"521":1,"549":1}}],["operator",{"2":{"390":2}}],["operação",{"2":{"279":1,"299":1,"402":1,"404":1,"491":1,"520":1,"549":1,"720":1}}],["operações",{"2":{"43":1,"491":2,"700":1}}],["operacional",{"2":{"159":1,"251":1,"563":1,"564":1,"635":2}}],["operável",{"2":{"22":1}}],["opcionais",{"2":{"77":1,"424":1}}],["opcionalmente",{"2":{"239":1,"318":1,"363":1}}],["opcional",{"0":{"146":1,"171":1,"190":1,"191":1,"206":1,"657":1},"2":{"35":2,"404":1,"478":1,"519":1}}],["opacity",{"2":{"46":1,"50":1,"51":1,"57":1,"113":2}}],["opacidade",{"2":{"46":6,"50":1,"113":4,"114":1,"245":1,"421":1,"534":1,"544":1}}],["opção",{"2":{"11":2,"34":2,"38":1,"48":1,"55":1,"63":1,"69":1,"186":1,"228":1,"273":1,"293":1,"328":1,"329":1,"399":1,"437":1,"438":1,"439":1,"464":1,"488":1,"493":1,"549":1,"562":1,"676":1,"681":1,"711":1}}],["opções",{"2":{"11":3,"34":3,"50":1,"68":1,"126":1,"200":1,"228":1,"398":3,"399":1,"454":1,"479":1,"523":1,"607":1,"628":1,"641":1,"726":1}}],["objc",{"2":{"477":1,"493":4}}],["obj",{"2":{"390":5}}],["objetivos",{"2":{"515":1,"545":1}}],["objetivo",{"2":{"95":1,"104":1,"532":1,"660":1}}],["objetos",{"2":{"35":1,"45":2,"47":1,"52":2,"348":1,"349":1,"446":1,"456":1,"462":2,"486":2,"488":2,"531":1,"540":1,"675":1,"677":2,"679":1}}],["objeto",{"0":{"338":1},"2":{"12":2,"13":1,"35":1,"47":1,"74":1,"77":1,"101":1,"332":1,"338":3,"348":3,"398":3,"399":1,"422":1,"456":1,"463":1,"464":2,"465":1,"480":1,"487":1,"488":1,"489":1,"531":4,"562":1,"576":1,"668":1,"676":1,"693":1}}],["object>",{"2":{"463":2}}],["object",{"2":{"92":1,"259":1,"298":1,"390":6,"393":1,"395":1,"402":1,"422":1,"431":2,"462":1,"467":2,"486":2,"488":1,"554":1,"576":1,"681":1}}],["objective",{"0":{"305":1},"1":{"306":1,"307":1,"308":1,"309":1,"310":1,"311":1,"312":1,"313":1,"314":1,"315":1,"316":1,"317":1,"318":1,"319":1,"320":1,"321":1,"322":1,"323":1,"324":1,"325":1,"326":1},"2":{"66":1,"77":1,"101":2,"106":1,"110":1,"111":2,"285":1,"320":2,"386":1,"446":2,"477":1,"478":3,"486":4,"488":1,"493":3,"548":1,"677":1}}],["obsoleto",{"2":{"259":2,"692":2}}],["obsoleta",{"2":{"122":1}}],["observando",{"2":{"483":1}}],["observado",{"2":{"464":1,"499":1}}],["observar",{"2":{"113":1,"143":1,"165":1,"183":1,"458":1,"482":1}}],["observação",{"2":{"101":1,"111":2,"122":1,"126":1,"127":1,"134":2,"151":1,"176":1,"193":1,"211":1,"407":1,"441":2,"549":1,"563":1,"599":1,"699":1,"734":1,"747":1}}],["observe",{"2":{"39":1,"60":2,"67":2,"96":1,"105":1,"111":1,"119":1,"120":1,"320":2,"328":1,"339":1,"340":1,"348":1,"365":2,"389":1,"424":2,"426":1,"442":1,"443":1,"455":1,"464":1,"479":1,"480":1,"485":1,"487":1,"488":2,"491":1,"499":1,"520":1,"550":1,"554":1,"556":2,"559":1,"560":1,"576":2,"655":1,"656":1,"678":1,"699":1,"700":1,"739":1,"745":1}}],["obtém",{"2":{"328":1,"676":1}}],["obtido",{"2":{"251":2,"466":1,"566":2,"608":1}}],["obtida",{"2":{"65":1,"531":1}}],["obtendo",{"0":{"467":1},"2":{"635":1}}],["obtenha",{"2":{"166":1,"636":1}}],["obterão",{"2":{"656":1}}],["obterá",{"2":{"110":1,"223":1,"691":1}}],["obter",{"2":{"36":1,"50":1,"60":1,"70":1,"74":1,"75":1,"101":1,"143":1,"187":1,"216":1,"222":1,"236":1,"320":1,"325":1,"329":1,"333":1,"335":1,"339":1,"365":1,"371":1,"377":1,"390":1,"398":1,"420":1,"424":1,"440":1,"441":1,"446":1,"449":2,"456":1,"467":1,"470":1,"474":2,"486":1,"488":1,"493":1,"508":1,"518":1,"519":1,"520":1,"541":1,"551":1,"586":1,"605":1,"608":1,"616":1,"639":1,"689":1,"690":1,"718":1}}],["obrigatório",{"2":{"12":1,"13":2,"35":2,"342":1,"424":1}}],["ours",{"2":{"722":2}}],["ouvindo",{"0":{"468":1},"2":{"490":1,"745":1}}],["ouvintes",{"2":{"466":4,"490":2}}],["ouvinte",{"2":{"404":1,"466":1,"467":2,"468":1,"490":2,"679":1}}],["ouvir",{"2":{"467":2,"468":2,"680":1}}],["outputs",{"2":{"654":1}}],["output",{"2":{"50":1,"283":1,"303":1,"594":2,"662":3,"663":2}}],["outputrange",{"2":{"50":6,"51":1,"53":1}}],["outras",{"0":{"44":1,"95":1,"104":1,"521":1,"656":1},"1":{"96":1,"97":1,"105":1,"106":1},"2":{"48":1,"60":1,"95":1,"104":1,"110":1,"111":1,"113":1,"219":1,"251":1,"255":1,"270":1,"278":1,"290":1,"298":1,"313":1,"358":1,"381":2,"385":1,"407":1,"417":1,"419":1,"441":1,"512":1,"518":1,"532":1,"537":1,"541":1,"562":2,"663":1,"673":1,"675":1,"678":1,"680":1,"691":1,"700":1,"717":1,"718":1,"726":1}}],["outra",{"2":{"22":1,"60":2,"121":1,"191":1,"251":2,"437":1,"464":1,"473":1,"488":1,"491":1,"542":1,"551":1,"586":1,"629":1,"632":1,"677":1,"678":1,"681":1,"682":1}}],["outros",{"0":{"119":1},"1":{"120":1,"121":1,"122":1,"123":1,"124":1},"2":{"30":1,"44":1,"50":1,"51":1,"52":1,"58":1,"89":1,"98":1,"111":1,"217":2,"233":2,"235":1,"262":1,"328":1,"329":1,"334":1,"346":1,"347":1,"349":1,"420":1,"440":1,"441":1,"442":1,"447":1,"461":1,"485":1,"491":3,"500":1,"550":1,"565":1,"569":1,"619":1,"630":1,"656":1,"667":1,"673":1,"682":1,"693":1,"694":1,"726":1}}],["outro",{"2":{"4":1,"14":1,"49":1,"51":2,"67":1,"68":1,"115":1,"116":1,"142":2,"242":1,"276":1,"296":1,"316":1,"348":1,"361":1,"386":1,"426":1,"441":1,"464":1,"503":1,"517":1,"534":1,"546":1,"566":1,"604":1,"613":1,"622":1,"647":1,"675":3,"678":1,"679":1,"680":1,"702":1,"709":1}}],["ou",{"0":{"146":1,"171":1,"190":1,"206":1,"424":1,"510":1,"539":1,"566":1},"2":{"3":2,"5":1,"9":1,"11":5,"12":6,"13":1,"21":1,"22":1,"23":1,"29":1,"31":3,"33":1,"34":4,"35":6,"36":1,"37":2,"38":2,"39":1,"47":2,"48":3,"49":1,"50":1,"51":2,"52":1,"57":1,"60":1,"63":2,"65":2,"66":1,"68":1,"71":1,"74":2,"77":2,"80":1,"113":1,"114":1,"123":1,"124":1,"126":3,"128":3,"130":1,"135":2,"138":1,"139":1,"142":4,"145":1,"147":1,"151":1,"153":1,"156":2,"158":1,"159":2,"165":1,"168":5,"170":1,"172":1,"178":1,"183":1,"184":1,"185":1,"186":3,"189":1,"190":1,"191":1,"200":1,"202":1,"203":1,"205":1,"207":1,"209":1,"213":1,"216":1,"217":1,"221":1,"224":1,"226":1,"231":1,"233":4,"234":1,"236":1,"237":2,"238":2,"242":1,"243":1,"245":1,"246":1,"248":2,"250":1,"251":2,"254":1,"255":2,"256":1,"259":2,"262":1,"268":1,"276":2,"278":2,"279":3,"285":1,"288":1,"296":2,"298":2,"299":3,"309":1,"312":1,"316":2,"318":1,"323":1,"325":1,"328":3,"329":2,"330":1,"331":1,"332":1,"334":3,"337":1,"343":1,"348":1,"349":1,"354":1,"361":2,"363":1,"369":1,"371":1,"375":1,"379":1,"385":2,"386":2,"387":1,"398":1,"399":1,"402":2,"404":2,"409":1,"413":1,"417":1,"418":1,"419":1,"421":2,"424":3,"426":1,"427":1,"434":1,"436":3,"437":2,"441":1,"442":1,"443":1,"446":3,"452":2,"456":2,"464":1,"465":2,"466":2,"467":1,"470":1,"471":1,"477":2,"478":1,"479":1,"480":1,"483":1,"486":1,"490":3,"491":1,"493":1,"495":1,"499":1,"501":1,"506":1,"509":1,"517":1,"518":1,"519":1,"520":1,"521":2,"524":1,"529":2,"531":1,"533":1,"539":1,"540":1,"542":3,"543":1,"544":1,"549":2,"553":1,"555":5,"558":1,"559":1,"560":1,"562":1,"565":1,"566":1,"569":1,"571":1,"573":1,"574":1,"582":1,"583":1,"584":1,"585":1,"591":1,"595":1,"596":2,"601":1,"602":1,"603":1,"610":1,"611":1,"615":1,"616":1,"617":1,"628":1,"629":5,"634":5,"635":2,"636":2,"638":1,"644":1,"645":1,"651":1,"652":1,"654":2,"656":1,"665":1,"666":1,"671":1,"672":1,"673":1,"675":2,"676":1,"677":2,"678":1,"679":3,"680":7,"681":2,"682":6,"686":1,"689":1,"695":4,"699":1,"700":2,"702":1,"711":1,"716":1,"719":1,"720":1,"726":3,"728":1,"730":1,"733":3,"736":1,"745":2,"746":1,"747":1,"748":1,"750":1}}],["oss",{"2":{"113":1}}],["os",{"0":{"424":1,"576":1,"597":1,"614":1,"651":1,"722":1},"1":{"598":1,"599":1,"600":1,"601":1,"602":1,"603":1,"604":1,"615":1,"616":1,"617":1,"618":1,"619":1,"620":1,"621":1,"622":1},"2":{"0":2,"2":1,"3":1,"10":3,"12":1,"13":1,"14":3,"15":2,"24":2,"27":5,"28":1,"30":3,"34":1,"35":1,"37":2,"38":1,"42":1,"43":2,"46":1,"47":1,"51":3,"52":2,"56":1,"57":1,"60":2,"67":4,"68":3,"69":1,"71":1,"74":2,"76":1,"77":2,"79":1,"85":1,"90":1,"92":1,"96":6,"97":1,"99":1,"105":6,"106":3,"110":1,"111":2,"114":1,"115":1,"119":1,"120":2,"121":2,"128":3,"131":1,"134":1,"135":1,"140":1,"141":1,"142":2,"156":2,"165":1,"166":1,"167":1,"168":2,"183":1,"200":1,"201":1,"202":1,"203":1,"217":3,"218":1,"220":1,"222":1,"224":5,"225":3,"226":7,"227":5,"228":1,"229":1,"230":4,"231":2,"232":1,"233":1,"236":1,"238":1,"239":1,"241":1,"243":2,"245":4,"246":1,"247":1,"248":1,"249":2,"251":4,"252":1,"256":1,"257":1,"258":1,"259":2,"262":2,"263":1,"265":1,"268":1,"278":2,"279":1,"283":1,"287":1,"288":1,"298":2,"299":1,"303":1,"306":1,"309":1,"328":3,"329":3,"333":1,"334":5,"338":1,"339":1,"342":1,"343":1,"344":1,"347":1,"348":4,"349":6,"351":1,"354":1,"358":1,"374":1,"375":1,"379":1,"381":1,"384":2,"385":1,"386":3,"387":1,"390":2,"391":1,"398":2,"402":3,"406":1,"407":1,"413":1,"418":1,"419":1,"421":3,"424":6,"426":1,"430":2,"436":3,"441":4,"442":1,"443":2,"449":1,"452":1,"453":1,"454":2,"455":2,"456":4,"459":1,"461":3,"462":4,"463":1,"464":1,"466":1,"468":3,"469":2,"470":2,"471":2,"474":1,"479":2,"480":2,"485":3,"486":4,"487":1,"488":2,"491":2,"493":2,"495":1,"497":1,"501":1,"504":1,"506":2,"507":3,"508":1,"509":1,"516":2,"520":2,"531":6,"533":2,"534":5,"535":1,"539":1,"545":1,"547":1,"549":1,"551":1,"552":1,"554":1,"555":3,"556":2,"559":1,"562":2,"565":1,"566":1,"568":1,"572":1,"576":5,"578":2,"587":1,"595":3,"596":2,"608":2,"617":1,"619":1,"625":1,"628":1,"629":6,"633":1,"634":2,"635":2,"636":2,"638":3,"648":1,"650":1,"654":2,"656":2,"659":1,"660":4,"662":2,"663":1,"665":1,"666":1,"668":4,"669":1,"671":3,"672":1,"673":2,"674":2,"675":5,"676":1,"677":1,"679":6,"680":4,"681":4,"682":3,"687":3,"688":1,"689":2,"691":2,"692":1,"693":3,"698":2,"699":3,"700":4,"706":1,"708":1,"716":1,"719":1,"720":1,"722":1,"728":2,"730":3,"731":4,"736":1,"739":1,"741":1,"742":1,"746":1,"748":1}}],["o",{"0":{"38":1,"39":1,"56":1,"65":1,"116":1,"126":1,"141":1,"142":1,"147":1,"151":1,"156":1,"167":1,"168":1,"172":1,"176":1,"193":1,"202":1,"203":1,"207":1,"211":1,"226":1,"270":1,"275":1,"281":1,"282":1,"290":1,"295":1,"301":1,"302":1,"315":1,"324":1,"325":1,"360":1,"370":1,"371":1,"403":1,"423":1,"425":1,"426":1,"432":1,"433":1,"434":1,"456":1,"457":1,"467":1,"481":1,"518":1,"527":1,"530":1,"531":1,"533":1,"539":1,"541":1,"542":1,"543":2,"554":1,"555":1,"569":1,"574":1,"580":1,"581":1,"596":2,"624":1,"657":2,"658":1,"666":1,"695":1,"714":1,"721":1,"736":2,"740":1},"1":{"148":1,"149":1,"157":1,"158":1,"159":1,"160":1,"161":1,"162":1,"173":1,"174":1,"208":1,"209":1,"296":1,"297":1,"298":1,"457":1,"519":1,"520":1,"528":1,"529":1,"582":1,"583":1,"584":1,"585":1,"586":1,"587":1,"588":1,"589":1,"590":1,"591":1,"592":1,"593":1,"594":1,"667":1,"715":1,"716":1,"741":1,"742":1,"743":1,"744":1,"745":1,"746":1,"747":1,"748":1,"749":1,"750":1,"751":1},"2":{"0":2,"2":1,"3":5,"4":2,"5":1,"6":3,"7":2,"8":5,"10":6,"11":11,"12":4,"13":4,"14":3,"15":1,"16":1,"17":1,"18":1,"20":1,"21":1,"22":1,"24":1,"26":3,"27":2,"28":1,"30":8,"31":3,"33":3,"34":9,"35":30,"37":2,"38":11,"39":9,"43":7,"44":1,"46":6,"47":2,"48":3,"50":7,"52":5,"53":5,"55":9,"56":13,"57":4,"59":1,"60":6,"62":1,"63":2,"64":2,"65":5,"67":16,"68":8,"69":2,"70":2,"71":1,"73":2,"74":14,"76":2,"77":16,"78":1,"79":2,"80":1,"89":1,"90":4,"92":4,"93":2,"94":4,"95":2,"96":6,"97":1,"98":1,"99":4,"101":9,"102":2,"103":4,"104":2,"105":8,"106":5,"107":2,"110":5,"111":25,"112":5,"113":4,"114":2,"115":5,"116":8,"117":1,"120":2,"121":1,"123":1,"124":2,"126":2,"128":2,"129":1,"130":3,"131":6,"133":2,"134":5,"135":6,"137":1,"138":1,"139":2,"140":1,"141":1,"142":8,"143":4,"144":2,"145":4,"146":2,"147":1,"148":1,"149":5,"151":3,"152":2,"153":1,"155":2,"156":6,"157":1,"158":4,"159":3,"164":1,"165":6,"166":8,"167":1,"168":7,"169":2,"170":4,"171":2,"172":1,"173":1,"174":3,"176":3,"178":1,"180":2,"182":1,"183":6,"184":3,"185":2,"186":1,"187":1,"188":2,"189":5,"190":5,"191":10,"193":3,"194":2,"195":2,"196":2,"198":2,"199":1,"200":9,"201":1,"202":1,"203":13,"204":2,"205":5,"206":2,"207":1,"208":1,"209":5,"211":3,"212":2,"213":1,"215":2,"217":6,"218":7,"219":10,"220":3,"221":4,"222":5,"223":3,"224":7,"225":10,"226":8,"227":1,"229":3,"230":4,"231":12,"232":3,"234":3,"235":4,"237":1,"242":8,"243":3,"244":5,"245":7,"246":2,"248":6,"249":5,"250":2,"251":15,"252":4,"255":1,"256":2,"257":3,"258":1,"259":10,"261":1,"262":8,"263":2,"265":3,"266":1,"268":4,"270":4,"271":1,"272":1,"273":1,"274":2,"275":2,"276":2,"278":6,"279":20,"280":4,"281":2,"282":1,"283":5,"287":3,"288":6,"290":4,"291":1,"292":1,"293":1,"294":2,"295":2,"296":2,"298":6,"299":20,"300":4,"301":2,"302":1,"303":5,"306":3,"307":1,"309":6,"310":2,"311":2,"312":1,"313":6,"314":2,"315":2,"316":2,"317":1,"318":2,"320":10,"321":6,"322":4,"323":3,"324":2,"325":3,"328":9,"330":2,"331":1,"333":1,"334":2,"336":4,"337":6,"338":3,"339":1,"341":1,"342":2,"343":2,"344":8,"345":2,"346":2,"347":2,"348":1,"349":15,"351":3,"352":1,"354":4,"355":2,"356":2,"357":1,"358":6,"359":2,"360":2,"361":2,"362":1,"363":2,"365":9,"366":6,"367":1,"368":4,"369":3,"370":2,"371":4,"374":1,"375":3,"376":2,"377":3,"378":1,"379":5,"381":3,"382":1,"383":1,"384":2,"385":2,"386":3,"387":5,"389":10,"390":4,"398":2,"399":3,"400":1,"401":1,"402":3,"403":2,"404":13,"405":4,"406":1,"407":5,"409":2,"411":1,"412":1,"413":4,"414":1,"416":1,"417":3,"418":2,"419":3,"420":1,"421":7,"422":2,"424":18,"425":1,"426":4,"427":7,"429":1,"431":4,"434":4,"435":2,"436":3,"437":2,"438":1,"439":1,"440":1,"441":5,"442":16,"443":6,"444":10,"445":7,"446":2,"447":2,"451":3,"452":6,"453":4,"454":2,"455":4,"456":17,"457":8,"458":4,"459":2,"461":11,"462":4,"463":3,"464":9,"465":8,"466":3,"467":8,"468":1,"469":2,"470":6,"471":3,"472":1,"473":1,"476":3,"477":6,"478":12,"479":8,"480":7,"481":8,"482":5,"483":4,"485":11,"486":5,"487":4,"488":12,"489":3,"490":5,"491":10,"492":3,"493":8,"495":2,"497":3,"498":1,"499":2,"500":2,"501":2,"502":1,"503":2,"504":1,"505":1,"506":2,"507":2,"508":1,"510":2,"512":1,"515":1,"516":5,"518":2,"519":1,"520":8,"521":1,"523":5,"524":1,"525":9,"526":6,"527":1,"529":7,"530":3,"531":8,"532":3,"533":8,"534":7,"535":5,"537":2,"538":2,"539":2,"540":4,"541":10,"542":3,"543":1,"545":6,"546":4,"547":8,"548":5,"549":5,"551":10,"552":4,"553":11,"554":5,"555":14,"556":6,"559":3,"560":1,"561":3,"562":2,"563":3,"564":1,"565":7,"566":1,"567":4,"568":4,"569":2,"570":4,"571":6,"572":2,"573":2,"574":11,"575":3,"576":3,"577":3,"578":1,"579":1,"580":4,"581":5,"582":2,"583":3,"584":2,"585":6,"586":1,"588":2,"589":3,"590":2,"591":2,"592":2,"593":7,"594":2,"595":5,"596":9,"598":2,"599":4,"600":2,"602":6,"603":5,"604":2,"605":2,"607":2,"608":12,"609":2,"611":6,"612":5,"613":2,"615":4,"616":4,"617":1,"618":3,"619":4,"621":4,"622":2,"624":1,"625":5,"626":1,"627":2,"629":7,"630":3,"631":1,"632":3,"633":1,"634":2,"635":10,"636":21,"637":2,"638":7,"641":2,"642":4,"643":2,"645":6,"646":6,"647":2,"648":8,"650":5,"651":5,"652":6,"653":1,"654":8,"655":3,"656":5,"657":6,"658":2,"660":4,"662":3,"663":1,"665":4,"666":11,"667":7,"668":6,"669":2,"670":1,"671":7,"672":3,"673":4,"674":3,"675":9,"676":1,"677":5,"678":4,"679":8,"680":11,"681":13,"682":3,"683":2,"685":4,"686":2,"687":4,"688":1,"689":3,"690":5,"691":7,"692":3,"693":2,"694":1,"695":6,"696":1,"697":1,"698":1,"699":7,"700":8,"701":2,"702":2,"703":7,"704":3,"705":2,"706":2,"708":4,"709":1,"710":1,"711":2,"715":1,"716":2,"718":1,"720":3,"721":6,"723":2,"725":2,"726":6,"728":7,"729":2,"730":7,"731":5,"733":3,"734":3,"735":2,"736":3,"740":1,"741":2,"742":6,"744":3,"745":14,"746":6,"747":2,"748":4,"749":1,"750":1,"754":1,"763":1}}]],"serializationVersion":2}';export{e as default}; diff --git a/vitepress/docs/.vitepress/dist/assets/chunks/VPLocalSearchBox.B0G8URRa.js b/vitepress/docs/.vitepress/dist/assets/chunks/VPLocalSearchBox.B0G8URRa.js new file mode 100644 index 0000000..e25d15c --- /dev/null +++ b/vitepress/docs/.vitepress/dist/assets/chunks/VPLocalSearchBox.B0G8URRa.js @@ -0,0 +1,13 @@ +function __vite__mapDeps(indexes) { + if (!__vite__mapDeps.viteFileDeps) { + __vite__mapDeps.viteFileDeps = [] + } + return indexes.map((i) => __vite__mapDeps.viteFileDeps[i]) +} +var It=Object.defineProperty;var Dt=(o,e,t)=>e in o?It(o,e,{enumerable:!0,configurable:!0,writable:!0,value:t}):o[e]=t;var Oe=(o,e,t)=>(Dt(o,typeof e!="symbol"?e+"":e,t),t);import{Y as yt,h as oe,y as $e,aj as kt,ak as Ot,d as _t,H as xe,al as tt,k as Fe,am as Rt,an as Mt,z as Lt,ao as Pt,l as _e,U as de,S as Ee,ap as zt,aq as Vt,Z as Bt,j as $t,ar as Wt,o as ee,b as Kt,m as k,a2 as Jt,p as j,as as Ut,at as jt,au as Gt,c as re,n as rt,e as Se,G as at,F as nt,a as ve,t as pe,av as qt,q as Ht,s as Qt,aw as it,ax as Yt,a8 as Zt,ae as Xt,ay as er,_ as tr}from"./framework.nQaBHiNx.js";import{u as rr,c as ar}from"./theme.Dx0ZSJLU.js";const nr={root:()=>yt(()=>import("./@localSearchIndexroot.BSIqPQjv.js"),__vite__mapDeps([]))};/*! +* tabbable 6.2.0 +* @license MIT, https://github.com/focus-trap/tabbable/blob/master/LICENSE +*/var mt=["input:not([inert])","select:not([inert])","textarea:not([inert])","a[href]:not([inert])","button:not([inert])","[tabindex]:not(slot):not([inert])","audio[controls]:not([inert])","video[controls]:not([inert])",'[contenteditable]:not([contenteditable="false"]):not([inert])',"details>summary:first-of-type:not([inert])","details:not([inert])"],Ne=mt.join(","),gt=typeof Element>"u",ue=gt?function(){}:Element.prototype.matches||Element.prototype.msMatchesSelector||Element.prototype.webkitMatchesSelector,Ce=!gt&&Element.prototype.getRootNode?function(o){var e;return o==null||(e=o.getRootNode)===null||e===void 0?void 0:e.call(o)}:function(o){return o==null?void 0:o.ownerDocument},Ie=function o(e,t){var r;t===void 0&&(t=!0);var n=e==null||(r=e.getAttribute)===null||r===void 0?void 0:r.call(e,"inert"),a=n===""||n==="true",i=a||t&&e&&o(e.parentNode);return i},ir=function(e){var t,r=e==null||(t=e.getAttribute)===null||t===void 0?void 0:t.call(e,"contenteditable");return r===""||r==="true"},bt=function(e,t,r){if(Ie(e))return[];var n=Array.prototype.slice.apply(e.querySelectorAll(Ne));return t&&ue.call(e,Ne)&&n.unshift(e),n=n.filter(r),n},wt=function o(e,t,r){for(var n=[],a=Array.from(e);a.length;){var i=a.shift();if(!Ie(i,!1))if(i.tagName==="SLOT"){var s=i.assignedElements(),u=s.length?s:i.children,l=o(u,!0,r);r.flatten?n.push.apply(n,l):n.push({scopeParent:i,candidates:l})}else{var h=ue.call(i,Ne);h&&r.filter(i)&&(t||!e.includes(i))&&n.push(i);var d=i.shadowRoot||typeof r.getShadowRoot=="function"&&r.getShadowRoot(i),v=!Ie(d,!1)&&(!r.shadowRootFilter||r.shadowRootFilter(i));if(d&&v){var y=o(d===!0?i.children:d.children,!0,r);r.flatten?n.push.apply(n,y):n.push({scopeParent:i,candidates:y})}else a.unshift.apply(a,i.children)}}return n},xt=function(e){return!isNaN(parseInt(e.getAttribute("tabindex"),10))},se=function(e){if(!e)throw new Error("No node provided");return e.tabIndex<0&&(/^(AUDIO|VIDEO|DETAILS)$/.test(e.tagName)||ir(e))&&!xt(e)?0:e.tabIndex},or=function(e,t){var r=se(e);return r<0&&t&&!xt(e)?0:r},sr=function(e,t){return e.tabIndex===t.tabIndex?e.documentOrder-t.documentOrder:e.tabIndex-t.tabIndex},Ft=function(e){return e.tagName==="INPUT"},ur=function(e){return Ft(e)&&e.type==="hidden"},lr=function(e){var t=e.tagName==="DETAILS"&&Array.prototype.slice.apply(e.children).some(function(r){return r.tagName==="SUMMARY"});return t},cr=function(e,t){for(var r=0;rsummary:first-of-type"),i=a?e.parentElement:e;if(ue.call(i,"details:not([open]) *"))return!0;if(!r||r==="full"||r==="legacy-full"){if(typeof n=="function"){for(var s=e;e;){var u=e.parentElement,l=Ce(e);if(u&&!u.shadowRoot&&n(u)===!0)return ot(e);e.assignedSlot?e=e.assignedSlot:!u&&l!==e.ownerDocument?e=l.host:e=u}e=s}if(vr(e))return!e.getClientRects().length;if(r!=="legacy-full")return!0}else if(r==="non-zero-area")return ot(e);return!1},yr=function(e){if(/^(INPUT|BUTTON|SELECT|TEXTAREA)$/.test(e.tagName))for(var t=e.parentElement;t;){if(t.tagName==="FIELDSET"&&t.disabled){for(var r=0;r=0)},gr=function o(e){var t=[],r=[];return e.forEach(function(n,a){var i=!!n.scopeParent,s=i?n.scopeParent:n,u=or(s,i),l=i?o(n.candidates):s;u===0?i?t.push.apply(t,l):t.push(s):r.push({documentOrder:a,tabIndex:u,item:n,isScope:i,content:l})}),r.sort(sr).reduce(function(n,a){return a.isScope?n.push.apply(n,a.content):n.push(a.content),n},[]).concat(t)},br=function(e,t){t=t||{};var r;return t.getShadowRoot?r=wt([e],t.includeContainer,{filter:We.bind(null,t),flatten:!1,getShadowRoot:t.getShadowRoot,shadowRootFilter:mr}):r=bt(e,t.includeContainer,We.bind(null,t)),gr(r)},wr=function(e,t){t=t||{};var r;return t.getShadowRoot?r=wt([e],t.includeContainer,{filter:De.bind(null,t),flatten:!0,getShadowRoot:t.getShadowRoot}):r=bt(e,t.includeContainer,De.bind(null,t)),r},le=function(e,t){if(t=t||{},!e)throw new Error("No node provided");return ue.call(e,Ne)===!1?!1:We(t,e)},xr=mt.concat("iframe").join(","),Re=function(e,t){if(t=t||{},!e)throw new Error("No node provided");return ue.call(e,xr)===!1?!1:De(t,e)};/*! +* focus-trap 7.5.4 +* @license MIT, https://github.com/focus-trap/focus-trap/blob/master/LICENSE +*/function st(o,e){var t=Object.keys(o);if(Object.getOwnPropertySymbols){var r=Object.getOwnPropertySymbols(o);e&&(r=r.filter(function(n){return Object.getOwnPropertyDescriptor(o,n).enumerable})),t.push.apply(t,r)}return t}function ut(o){for(var e=1;e0){var r=e[e.length-1];r!==t&&r.pause()}var n=e.indexOf(t);n===-1||e.splice(n,1),e.push(t)},deactivateTrap:function(e,t){var r=e.indexOf(t);r!==-1&&e.splice(r,1),e.length>0&&e[e.length-1].unpause()}},Ar=function(e){return e.tagName&&e.tagName.toLowerCase()==="input"&&typeof e.select=="function"},Tr=function(e){return(e==null?void 0:e.key)==="Escape"||(e==null?void 0:e.key)==="Esc"||(e==null?void 0:e.keyCode)===27},ge=function(e){return(e==null?void 0:e.key)==="Tab"||(e==null?void 0:e.keyCode)===9},Nr=function(e){return ge(e)&&!e.shiftKey},Cr=function(e){return ge(e)&&e.shiftKey},ct=function(e){return setTimeout(e,0)},ft=function(e,t){var r=-1;return e.every(function(n,a){return t(n)?(r=a,!1):!0}),r},ye=function(e){for(var t=arguments.length,r=new Array(t>1?t-1:0),n=1;n1?p-1:0),I=1;I=0)c=r.activeElement;else{var f=i.tabbableGroups[0],p=f&&f.firstTabbableNode;c=p||h("fallbackFocus")}if(!c)throw new Error("Your focus-trap needs to have at least one focusable element");return c},v=function(){if(i.containerGroups=i.containers.map(function(c){var f=br(c,a.tabbableOptions),p=wr(c,a.tabbableOptions),C=f.length>0?f[0]:void 0,I=f.length>0?f[f.length-1]:void 0,M=p.find(function(m){return le(m)}),P=p.slice().reverse().find(function(m){return le(m)}),z=!!f.find(function(m){return se(m)>0});return{container:c,tabbableNodes:f,focusableNodes:p,posTabIndexesFound:z,firstTabbableNode:C,lastTabbableNode:I,firstDomTabbableNode:M,lastDomTabbableNode:P,nextTabbableNode:function(x){var $=arguments.length>1&&arguments[1]!==void 0?arguments[1]:!0,K=f.indexOf(x);return K<0?$?p.slice(p.indexOf(x)+1).find(function(q){return le(q)}):p.slice(0,p.indexOf(x)).reverse().find(function(q){return le(q)}):f[K+($?1:-1)]}}}),i.tabbableGroups=i.containerGroups.filter(function(c){return c.tabbableNodes.length>0}),i.tabbableGroups.length<=0&&!h("fallbackFocus"))throw new Error("Your focus-trap must have at least one container with at least one tabbable node in it at all times");if(i.containerGroups.find(function(c){return c.posTabIndexesFound})&&i.containerGroups.length>1)throw new Error("At least one node with a positive tabindex was found in one of your focus-trap's multiple containers. Positive tabindexes are only supported in single-container focus-traps.")},y=function w(c){var f=c.activeElement;if(f)return f.shadowRoot&&f.shadowRoot.activeElement!==null?w(f.shadowRoot):f},b=function w(c){if(c!==!1&&c!==y(document)){if(!c||!c.focus){w(d());return}c.focus({preventScroll:!!a.preventScroll}),i.mostRecentlyFocusedNode=c,Ar(c)&&c.select()}},E=function(c){var f=h("setReturnFocus",c);return f||(f===!1?!1:c)},g=function(c){var f=c.target,p=c.event,C=c.isBackward,I=C===void 0?!1:C;f=f||Ae(p),v();var M=null;if(i.tabbableGroups.length>0){var P=l(f,p),z=P>=0?i.containerGroups[P]:void 0;if(P<0)I?M=i.tabbableGroups[i.tabbableGroups.length-1].lastTabbableNode:M=i.tabbableGroups[0].firstTabbableNode;else if(I){var m=ft(i.tabbableGroups,function(V){var U=V.firstTabbableNode;return f===U});if(m<0&&(z.container===f||Re(f,a.tabbableOptions)&&!le(f,a.tabbableOptions)&&!z.nextTabbableNode(f,!1))&&(m=P),m>=0){var x=m===0?i.tabbableGroups.length-1:m-1,$=i.tabbableGroups[x];M=se(f)>=0?$.lastTabbableNode:$.lastDomTabbableNode}else ge(p)||(M=z.nextTabbableNode(f,!1))}else{var K=ft(i.tabbableGroups,function(V){var U=V.lastTabbableNode;return f===U});if(K<0&&(z.container===f||Re(f,a.tabbableOptions)&&!le(f,a.tabbableOptions)&&!z.nextTabbableNode(f))&&(K=P),K>=0){var q=K===i.tabbableGroups.length-1?0:K+1,H=i.tabbableGroups[q];M=se(f)>=0?H.firstTabbableNode:H.firstDomTabbableNode}else ge(p)||(M=z.nextTabbableNode(f))}}else M=h("fallbackFocus");return M},S=function(c){var f=Ae(c);if(!(l(f,c)>=0)){if(ye(a.clickOutsideDeactivates,c)){s.deactivate({returnFocus:a.returnFocusOnDeactivate});return}ye(a.allowOutsideClick,c)||c.preventDefault()}},T=function(c){var f=Ae(c),p=l(f,c)>=0;if(p||f instanceof Document)p&&(i.mostRecentlyFocusedNode=f);else{c.stopImmediatePropagation();var C,I=!0;if(i.mostRecentlyFocusedNode)if(se(i.mostRecentlyFocusedNode)>0){var M=l(i.mostRecentlyFocusedNode),P=i.containerGroups[M].tabbableNodes;if(P.length>0){var z=P.findIndex(function(m){return m===i.mostRecentlyFocusedNode});z>=0&&(a.isKeyForward(i.recentNavEvent)?z+1=0&&(C=P[z-1],I=!1))}}else i.containerGroups.some(function(m){return m.tabbableNodes.some(function(x){return se(x)>0})})||(I=!1);else I=!1;I&&(C=g({target:i.mostRecentlyFocusedNode,isBackward:a.isKeyBackward(i.recentNavEvent)})),b(C||i.mostRecentlyFocusedNode||d())}i.recentNavEvent=void 0},F=function(c){var f=arguments.length>1&&arguments[1]!==void 0?arguments[1]:!1;i.recentNavEvent=c;var p=g({event:c,isBackward:f});p&&(ge(c)&&c.preventDefault(),b(p))},L=function(c){if(Tr(c)&&ye(a.escapeDeactivates,c)!==!1){c.preventDefault(),s.deactivate();return}(a.isKeyForward(c)||a.isKeyBackward(c))&&F(c,a.isKeyBackward(c))},R=function(c){var f=Ae(c);l(f,c)>=0||ye(a.clickOutsideDeactivates,c)||ye(a.allowOutsideClick,c)||(c.preventDefault(),c.stopImmediatePropagation())},B=function(){if(i.active)return lt.activateTrap(n,s),i.delayInitialFocusTimer=a.delayInitialFocus?ct(function(){b(d())}):b(d()),r.addEventListener("focusin",T,!0),r.addEventListener("mousedown",S,{capture:!0,passive:!1}),r.addEventListener("touchstart",S,{capture:!0,passive:!1}),r.addEventListener("click",R,{capture:!0,passive:!1}),r.addEventListener("keydown",L,{capture:!0,passive:!1}),s},N=function(){if(i.active)return r.removeEventListener("focusin",T,!0),r.removeEventListener("mousedown",S,!0),r.removeEventListener("touchstart",S,!0),r.removeEventListener("click",R,!0),r.removeEventListener("keydown",L,!0),s},_=function(c){var f=c.some(function(p){var C=Array.from(p.removedNodes);return C.some(function(I){return I===i.mostRecentlyFocusedNode})});f&&b(d())},A=typeof window<"u"&&"MutationObserver"in window?new MutationObserver(_):void 0,O=function(){A&&(A.disconnect(),i.active&&!i.paused&&i.containers.map(function(c){A.observe(c,{subtree:!0,childList:!0})}))};return s={get active(){return i.active},get paused(){return i.paused},activate:function(c){if(i.active)return this;var f=u(c,"onActivate"),p=u(c,"onPostActivate"),C=u(c,"checkCanFocusTrap");C||v(),i.active=!0,i.paused=!1,i.nodeFocusedBeforeActivation=r.activeElement,f==null||f();var I=function(){C&&v(),B(),O(),p==null||p()};return C?(C(i.containers.concat()).then(I,I),this):(I(),this)},deactivate:function(c){if(!i.active)return this;var f=ut({onDeactivate:a.onDeactivate,onPostDeactivate:a.onPostDeactivate,checkCanReturnFocus:a.checkCanReturnFocus},c);clearTimeout(i.delayInitialFocusTimer),i.delayInitialFocusTimer=void 0,N(),i.active=!1,i.paused=!1,O(),lt.deactivateTrap(n,s);var p=u(f,"onDeactivate"),C=u(f,"onPostDeactivate"),I=u(f,"checkCanReturnFocus"),M=u(f,"returnFocus","returnFocusOnDeactivate");p==null||p();var P=function(){ct(function(){M&&b(E(i.nodeFocusedBeforeActivation)),C==null||C()})};return M&&I?(I(E(i.nodeFocusedBeforeActivation)).then(P,P),this):(P(),this)},pause:function(c){if(i.paused||!i.active)return this;var f=u(c,"onPause"),p=u(c,"onPostPause");return i.paused=!0,f==null||f(),N(),O(),p==null||p(),this},unpause:function(c){if(!i.paused||!i.active)return this;var f=u(c,"onUnpause"),p=u(c,"onPostUnpause");return i.paused=!1,f==null||f(),v(),B(),O(),p==null||p(),this},updateContainerElements:function(c){var f=[].concat(c).filter(Boolean);return i.containers=f.map(function(p){return typeof p=="string"?r.querySelector(p):p}),i.active&&v(),O(),this}},s.updateContainerElements(e),s};function kr(o,e={}){let t;const{immediate:r,...n}=e,a=oe(!1),i=oe(!1),s=d=>t&&t.activate(d),u=d=>t&&t.deactivate(d),l=()=>{t&&(t.pause(),i.value=!0)},h=()=>{t&&(t.unpause(),i.value=!1)};return $e(()=>kt(o),d=>{d&&(t=Dr(d,{...n,onActivate(){a.value=!0,e.onActivate&&e.onActivate()},onDeactivate(){a.value=!1,e.onDeactivate&&e.onDeactivate()}}),r&&s())},{flush:"post"}),Ot(()=>u()),{hasFocus:a,isPaused:i,activate:s,deactivate:u,pause:l,unpause:h}}class fe{constructor(e,t=!0,r=[],n=5e3){this.ctx=e,this.iframes=t,this.exclude=r,this.iframesTimeout=n}static matches(e,t){const r=typeof t=="string"?[t]:t,n=e.matches||e.matchesSelector||e.msMatchesSelector||e.mozMatchesSelector||e.oMatchesSelector||e.webkitMatchesSelector;if(n){let a=!1;return r.every(i=>n.call(e,i)?(a=!0,!1):!0),a}else return!1}getContexts(){let e,t=[];return typeof this.ctx>"u"||!this.ctx?e=[]:NodeList.prototype.isPrototypeOf(this.ctx)?e=Array.prototype.slice.call(this.ctx):Array.isArray(this.ctx)?e=this.ctx:typeof this.ctx=="string"?e=Array.prototype.slice.call(document.querySelectorAll(this.ctx)):e=[this.ctx],e.forEach(r=>{const n=t.filter(a=>a.contains(r)).length>0;t.indexOf(r)===-1&&!n&&t.push(r)}),t}getIframeContents(e,t,r=()=>{}){let n;try{const a=e.contentWindow;if(n=a.document,!a||!n)throw new Error("iframe inaccessible")}catch{r()}n&&t(n)}isIframeBlank(e){const t="about:blank",r=e.getAttribute("src").trim();return e.contentWindow.location.href===t&&r!==t&&r}observeIframeLoad(e,t,r){let n=!1,a=null;const i=()=>{if(!n){n=!0,clearTimeout(a);try{this.isIframeBlank(e)||(e.removeEventListener("load",i),this.getIframeContents(e,t,r))}catch{r()}}};e.addEventListener("load",i),a=setTimeout(i,this.iframesTimeout)}onIframeReady(e,t,r){try{e.contentWindow.document.readyState==="complete"?this.isIframeBlank(e)?this.observeIframeLoad(e,t,r):this.getIframeContents(e,t,r):this.observeIframeLoad(e,t,r)}catch{r()}}waitForIframes(e,t){let r=0;this.forEachIframe(e,()=>!0,n=>{r++,this.waitForIframes(n.querySelector("html"),()=>{--r||t()})},n=>{n||t()})}forEachIframe(e,t,r,n=()=>{}){let a=e.querySelectorAll("iframe"),i=a.length,s=0;a=Array.prototype.slice.call(a);const u=()=>{--i<=0&&n(s)};i||u(),a.forEach(l=>{fe.matches(l,this.exclude)?u():this.onIframeReady(l,h=>{t(l)&&(s++,r(h)),u()},u)})}createIterator(e,t,r){return document.createNodeIterator(e,t,r,!1)}createInstanceOnIframe(e){return new fe(e.querySelector("html"),this.iframes)}compareNodeIframe(e,t,r){const n=e.compareDocumentPosition(r),a=Node.DOCUMENT_POSITION_PRECEDING;if(n&a)if(t!==null){const i=t.compareDocumentPosition(r),s=Node.DOCUMENT_POSITION_FOLLOWING;if(i&s)return!0}else return!0;return!1}getIteratorNode(e){const t=e.previousNode();let r;return t===null?r=e.nextNode():r=e.nextNode()&&e.nextNode(),{prevNode:t,node:r}}checkIframeFilter(e,t,r,n){let a=!1,i=!1;return n.forEach((s,u)=>{s.val===r&&(a=u,i=s.handled)}),this.compareNodeIframe(e,t,r)?(a===!1&&!i?n.push({val:r,handled:!0}):a!==!1&&!i&&(n[a].handled=!0),!0):(a===!1&&n.push({val:r,handled:!1}),!1)}handleOpenIframes(e,t,r,n){e.forEach(a=>{a.handled||this.getIframeContents(a.val,i=>{this.createInstanceOnIframe(i).forEachNode(t,r,n)})})}iterateThroughNodes(e,t,r,n,a){const i=this.createIterator(t,e,n);let s=[],u=[],l,h,d=()=>({prevNode:h,node:l}=this.getIteratorNode(i),l);for(;d();)this.iframes&&this.forEachIframe(t,v=>this.checkIframeFilter(l,h,v,s),v=>{this.createInstanceOnIframe(v).forEachNode(e,y=>u.push(y),n)}),u.push(l);u.forEach(v=>{r(v)}),this.iframes&&this.handleOpenIframes(s,e,r,n),a()}forEachNode(e,t,r,n=()=>{}){const a=this.getContexts();let i=a.length;i||n(),a.forEach(s=>{const u=()=>{this.iterateThroughNodes(e,s,t,r,()=>{--i<=0&&n()})};this.iframes?this.waitForIframes(s,u):u()})}}let Or=class{constructor(e){this.ctx=e,this.ie=!1;const t=window.navigator.userAgent;(t.indexOf("MSIE")>-1||t.indexOf("Trident")>-1)&&(this.ie=!0)}set opt(e){this._opt=Object.assign({},{element:"",className:"",exclude:[],iframes:!1,iframesTimeout:5e3,separateWordSearch:!0,diacritics:!0,synonyms:{},accuracy:"partially",acrossElements:!1,caseSensitive:!1,ignoreJoiners:!1,ignoreGroups:0,ignorePunctuation:[],wildcards:"disabled",each:()=>{},noMatch:()=>{},filter:()=>!0,done:()=>{},debug:!1,log:window.console},e)}get opt(){return this._opt}get iterator(){return new fe(this.ctx,this.opt.iframes,this.opt.exclude,this.opt.iframesTimeout)}log(e,t="debug"){const r=this.opt.log;this.opt.debug&&typeof r=="object"&&typeof r[t]=="function"&&r[t](`mark.js: ${e}`)}escapeStr(e){return e.replace(/[\-\[\]\/\{\}\(\)\*\+\?\.\\\^\$\|]/g,"\\$&")}createRegExp(e){return this.opt.wildcards!=="disabled"&&(e=this.setupWildcardsRegExp(e)),e=this.escapeStr(e),Object.keys(this.opt.synonyms).length&&(e=this.createSynonymsRegExp(e)),(this.opt.ignoreJoiners||this.opt.ignorePunctuation.length)&&(e=this.setupIgnoreJoinersRegExp(e)),this.opt.diacritics&&(e=this.createDiacriticsRegExp(e)),e=this.createMergedBlanksRegExp(e),(this.opt.ignoreJoiners||this.opt.ignorePunctuation.length)&&(e=this.createJoinersRegExp(e)),this.opt.wildcards!=="disabled"&&(e=this.createWildcardsRegExp(e)),e=this.createAccuracyRegExp(e),e}createSynonymsRegExp(e){const t=this.opt.synonyms,r=this.opt.caseSensitive?"":"i",n=this.opt.ignoreJoiners||this.opt.ignorePunctuation.length?"\0":"";for(let a in t)if(t.hasOwnProperty(a)){const i=t[a],s=this.opt.wildcards!=="disabled"?this.setupWildcardsRegExp(a):this.escapeStr(a),u=this.opt.wildcards!=="disabled"?this.setupWildcardsRegExp(i):this.escapeStr(i);s!==""&&u!==""&&(e=e.replace(new RegExp(`(${this.escapeStr(s)}|${this.escapeStr(u)})`,`gm${r}`),n+`(${this.processSynomyms(s)}|${this.processSynomyms(u)})`+n))}return e}processSynomyms(e){return(this.opt.ignoreJoiners||this.opt.ignorePunctuation.length)&&(e=this.setupIgnoreJoinersRegExp(e)),e}setupWildcardsRegExp(e){return e=e.replace(/(?:\\)*\?/g,t=>t.charAt(0)==="\\"?"?":""),e.replace(/(?:\\)*\*/g,t=>t.charAt(0)==="\\"?"*":"")}createWildcardsRegExp(e){let t=this.opt.wildcards==="withSpaces";return e.replace(/\u0001/g,t?"[\\S\\s]?":"\\S?").replace(/\u0002/g,t?"[\\S\\s]*?":"\\S*")}setupIgnoreJoinersRegExp(e){return e.replace(/[^(|)\\]/g,(t,r,n)=>{let a=n.charAt(r+1);return/[(|)\\]/.test(a)||a===""?t:t+"\0"})}createJoinersRegExp(e){let t=[];const r=this.opt.ignorePunctuation;return Array.isArray(r)&&r.length&&t.push(this.escapeStr(r.join(""))),this.opt.ignoreJoiners&&t.push("\\u00ad\\u200b\\u200c\\u200d"),t.length?e.split(/\u0000+/).join(`[${t.join("")}]*`):e}createDiacriticsRegExp(e){const t=this.opt.caseSensitive?"":"i",r=this.opt.caseSensitive?["aàáảãạăằắẳẵặâầấẩẫậäåāą","AÀÁẢÃẠĂẰẮẲẴẶÂẦẤẨẪẬÄÅĀĄ","cçćč","CÇĆČ","dđď","DĐĎ","eèéẻẽẹêềếểễệëěēę","EÈÉẺẼẸÊỀẾỂỄỆËĚĒĘ","iìíỉĩịîïī","IÌÍỈĨỊÎÏĪ","lł","LŁ","nñňń","NÑŇŃ","oòóỏõọôồốổỗộơởỡớờợöøō","OÒÓỎÕỌÔỒỐỔỖỘƠỞỠỚỜỢÖØŌ","rř","RŘ","sšśșş","SŠŚȘŞ","tťțţ","TŤȚŢ","uùúủũụưừứửữựûüůū","UÙÚỦŨỤƯỪỨỬỮỰÛÜŮŪ","yýỳỷỹỵÿ","YÝỲỶỸỴŸ","zžżź","ZŽŻŹ"]:["aàáảãạăằắẳẵặâầấẩẫậäåāąAÀÁẢÃẠĂẰẮẲẴẶÂẦẤẨẪẬÄÅĀĄ","cçćčCÇĆČ","dđďDĐĎ","eèéẻẽẹêềếểễệëěēęEÈÉẺẼẸÊỀẾỂỄỆËĚĒĘ","iìíỉĩịîïīIÌÍỈĨỊÎÏĪ","lłLŁ","nñňńNÑŇŃ","oòóỏõọôồốổỗộơởỡớờợöøōOÒÓỎÕỌÔỒỐỔỖỘƠỞỠỚỜỢÖØŌ","rřRŘ","sšśșşSŠŚȘŞ","tťțţTŤȚŢ","uùúủũụưừứửữựûüůūUÙÚỦŨỤƯỪỨỬỮỰÛÜŮŪ","yýỳỷỹỵÿYÝỲỶỸỴŸ","zžżźZŽŻŹ"];let n=[];return e.split("").forEach(a=>{r.every(i=>{if(i.indexOf(a)!==-1){if(n.indexOf(i)>-1)return!1;e=e.replace(new RegExp(`[${i}]`,`gm${t}`),`[${i}]`),n.push(i)}return!0})}),e}createMergedBlanksRegExp(e){return e.replace(/[\s]+/gmi,"[\\s]+")}createAccuracyRegExp(e){const t="!\"#$%&'()*+,-./:;<=>?@[\\]^_`{|}~¡¿";let r=this.opt.accuracy,n=typeof r=="string"?r:r.value,a=typeof r=="string"?[]:r.limiters,i="";switch(a.forEach(s=>{i+=`|${this.escapeStr(s)}`}),n){case"partially":default:return`()(${e})`;case"complementary":return i="\\s"+(i||this.escapeStr(t)),`()([^${i}]*${e}[^${i}]*)`;case"exactly":return`(^|\\s${i})(${e})(?=$|\\s${i})`}}getSeparatedKeywords(e){let t=[];return e.forEach(r=>{this.opt.separateWordSearch?r.split(" ").forEach(n=>{n.trim()&&t.indexOf(n)===-1&&t.push(n)}):r.trim()&&t.indexOf(r)===-1&&t.push(r)}),{keywords:t.sort((r,n)=>n.length-r.length),length:t.length}}isNumeric(e){return Number(parseFloat(e))==e}checkRanges(e){if(!Array.isArray(e)||Object.prototype.toString.call(e[0])!=="[object Object]")return this.log("markRanges() will only accept an array of objects"),this.opt.noMatch(e),[];const t=[];let r=0;return e.sort((n,a)=>n.start-a.start).forEach(n=>{let{start:a,end:i,valid:s}=this.callNoMatchOnInvalidRanges(n,r);s&&(n.start=a,n.length=i-a,t.push(n),r=i)}),t}callNoMatchOnInvalidRanges(e,t){let r,n,a=!1;return e&&typeof e.start<"u"?(r=parseInt(e.start,10),n=r+parseInt(e.length,10),this.isNumeric(e.start)&&this.isNumeric(e.length)&&n-t>0&&n-r>0?a=!0:(this.log(`Ignoring invalid or overlapping range: ${JSON.stringify(e)}`),this.opt.noMatch(e))):(this.log(`Ignoring invalid range: ${JSON.stringify(e)}`),this.opt.noMatch(e)),{start:r,end:n,valid:a}}checkWhitespaceRanges(e,t,r){let n,a=!0,i=r.length,s=t-i,u=parseInt(e.start,10)-s;return u=u>i?i:u,n=u+parseInt(e.length,10),n>i&&(n=i,this.log(`End range automatically set to the max value of ${i}`)),u<0||n-u<0||u>i||n>i?(a=!1,this.log(`Invalid range: ${JSON.stringify(e)}`),this.opt.noMatch(e)):r.substring(u,n).replace(/\s+/g,"")===""&&(a=!1,this.log("Skipping whitespace only range: "+JSON.stringify(e)),this.opt.noMatch(e)),{start:u,end:n,valid:a}}getTextNodes(e){let t="",r=[];this.iterator.forEachNode(NodeFilter.SHOW_TEXT,n=>{r.push({start:t.length,end:(t+=n.textContent).length,node:n})},n=>this.matchesExclude(n.parentNode)?NodeFilter.FILTER_REJECT:NodeFilter.FILTER_ACCEPT,()=>{e({value:t,nodes:r})})}matchesExclude(e){return fe.matches(e,this.opt.exclude.concat(["script","style","title","head","html"]))}wrapRangeInTextNode(e,t,r){const n=this.opt.element?this.opt.element:"mark",a=e.splitText(t),i=a.splitText(r-t);let s=document.createElement(n);return s.setAttribute("data-markjs","true"),this.opt.className&&s.setAttribute("class",this.opt.className),s.textContent=a.textContent,a.parentNode.replaceChild(s,a),i}wrapRangeInMappedTextNode(e,t,r,n,a){e.nodes.every((i,s)=>{const u=e.nodes[s+1];if(typeof u>"u"||u.start>t){if(!n(i.node))return!1;const l=t-i.start,h=(r>i.end?i.end:r)-i.start,d=e.value.substr(0,i.start),v=e.value.substr(h+i.start);if(i.node=this.wrapRangeInTextNode(i.node,l,h),e.value=d+v,e.nodes.forEach((y,b)=>{b>=s&&(e.nodes[b].start>0&&b!==s&&(e.nodes[b].start-=h),e.nodes[b].end-=h)}),r-=h,a(i.node.previousSibling,i.start),r>i.end)t=i.end;else return!1}return!0})}wrapMatches(e,t,r,n,a){const i=t===0?0:t+1;this.getTextNodes(s=>{s.nodes.forEach(u=>{u=u.node;let l;for(;(l=e.exec(u.textContent))!==null&&l[i]!=="";){if(!r(l[i],u))continue;let h=l.index;if(i!==0)for(let d=1;d{let u;for(;(u=e.exec(s.value))!==null&&u[i]!=="";){let l=u.index;if(i!==0)for(let d=1;dr(u[i],d),(d,v)=>{e.lastIndex=v,n(d)})}a()})}wrapRangeFromIndex(e,t,r,n){this.getTextNodes(a=>{const i=a.value.length;e.forEach((s,u)=>{let{start:l,end:h,valid:d}=this.checkWhitespaceRanges(s,i,a.value);d&&this.wrapRangeInMappedTextNode(a,l,h,v=>t(v,s,a.value.substring(l,h),u),v=>{r(v,s)})}),n()})}unwrapMatches(e){const t=e.parentNode;let r=document.createDocumentFragment();for(;e.firstChild;)r.appendChild(e.removeChild(e.firstChild));t.replaceChild(r,e),this.ie?this.normalizeTextNode(t):t.normalize()}normalizeTextNode(e){if(e){if(e.nodeType===3)for(;e.nextSibling&&e.nextSibling.nodeType===3;)e.nodeValue+=e.nextSibling.nodeValue,e.parentNode.removeChild(e.nextSibling);else this.normalizeTextNode(e.firstChild);this.normalizeTextNode(e.nextSibling)}}markRegExp(e,t){this.opt=t,this.log(`Searching with expression "${e}"`);let r=0,n="wrapMatches";const a=i=>{r++,this.opt.each(i)};this.opt.acrossElements&&(n="wrapMatchesAcrossElements"),this[n](e,this.opt.ignoreGroups,(i,s)=>this.opt.filter(s,i,r),a,()=>{r===0&&this.opt.noMatch(e),this.opt.done(r)})}mark(e,t){this.opt=t;let r=0,n="wrapMatches";const{keywords:a,length:i}=this.getSeparatedKeywords(typeof e=="string"?[e]:e),s=this.opt.caseSensitive?"":"i",u=l=>{let h=new RegExp(this.createRegExp(l),`gm${s}`),d=0;this.log(`Searching with expression "${h}"`),this[n](h,1,(v,y)=>this.opt.filter(y,l,r,d),v=>{d++,r++,this.opt.each(v)},()=>{d===0&&this.opt.noMatch(l),a[i-1]===l?this.opt.done(r):u(a[a.indexOf(l)+1])})};this.opt.acrossElements&&(n="wrapMatchesAcrossElements"),i===0?this.opt.done(r):u(a[0])}markRanges(e,t){this.opt=t;let r=0,n=this.checkRanges(e);n&&n.length?(this.log("Starting to mark with the following ranges: "+JSON.stringify(n)),this.wrapRangeFromIndex(n,(a,i,s,u)=>this.opt.filter(a,i,s,u),(a,i)=>{r++,this.opt.each(a,i)},()=>{this.opt.done(r)})):this.opt.done(r)}unmark(e){this.opt=e;let t=this.opt.element?this.opt.element:"*";t+="[data-markjs]",this.opt.className&&(t+=`.${this.opt.className}`),this.log(`Removal selector "${t}"`),this.iterator.forEachNode(NodeFilter.SHOW_ELEMENT,r=>{this.unwrapMatches(r)},r=>{const n=fe.matches(r,t),a=this.matchesExclude(r);return!n||a?NodeFilter.FILTER_REJECT:NodeFilter.FILTER_ACCEPT},this.opt.done)}};function _r(o){const e=new Or(o);return this.mark=(t,r)=>(e.mark(t,r),this),this.markRegExp=(t,r)=>(e.markRegExp(t,r),this),this.markRanges=(t,r)=>(e.markRanges(t,r),this),this.unmark=t=>(e.unmark(t),this),this}var W=function(){return W=Object.assign||function(e){for(var t,r=1,n=arguments.length;r0&&a[a.length-1])&&(l[0]===6||l[0]===2)){t=0;continue}if(l[0]===3&&(!a||l[1]>a[0]&&l[1]=o.length&&(o=void 0),{value:o&&o[r++],done:!o}}};throw new TypeError(e?"Object is not iterable.":"Symbol.iterator is not defined.")}function J(o,e){var t=typeof Symbol=="function"&&o[Symbol.iterator];if(!t)return o;var r=t.call(o),n,a=[],i;try{for(;(e===void 0||e-- >0)&&!(n=r.next()).done;)a.push(n.value)}catch(s){i={error:s}}finally{try{n&&!n.done&&(t=r.return)&&t.call(r)}finally{if(i)throw i.error}}return a}var Lr="ENTRIES",Et="KEYS",St="VALUES",G="",Me=function(){function o(e,t){var r=e._tree,n=Array.from(r.keys());this.set=e,this._type=t,this._path=n.length>0?[{node:r,keys:n}]:[]}return o.prototype.next=function(){var e=this.dive();return this.backtrack(),e},o.prototype.dive=function(){if(this._path.length===0)return{done:!0,value:void 0};var e=ce(this._path),t=e.node,r=e.keys;if(ce(r)===G)return{done:!1,value:this.result()};var n=t.get(ce(r));return this._path.push({node:n,keys:Array.from(n.keys())}),this.dive()},o.prototype.backtrack=function(){if(this._path.length!==0){var e=ce(this._path).keys;e.pop(),!(e.length>0)&&(this._path.pop(),this.backtrack())}},o.prototype.key=function(){return this.set._prefix+this._path.map(function(e){var t=e.keys;return ce(t)}).filter(function(e){return e!==G}).join("")},o.prototype.value=function(){return ce(this._path).node.get(G)},o.prototype.result=function(){switch(this._type){case St:return this.value();case Et:return this.key();default:return[this.key(),this.value()]}},o.prototype[Symbol.iterator]=function(){return this},o}(),ce=function(o){return o[o.length-1]},Pr=function(o,e,t){var r=new Map;if(e===void 0)return r;for(var n=e.length+1,a=n+t,i=new Uint8Array(a*n).fill(t+1),s=0;st)continue e}At(o.get(y),e,t,r,n,E,i,s+y)}}}catch(f){u={error:f}}finally{try{v&&!v.done&&(l=d.return)&&l.call(d)}finally{if(u)throw u.error}}},Le=function(){function o(e,t){e===void 0&&(e=new Map),t===void 0&&(t=""),this._size=void 0,this._tree=e,this._prefix=t}return o.prototype.atPrefix=function(e){var t,r;if(!e.startsWith(this._prefix))throw new Error("Mismatched prefix");var n=J(ke(this._tree,e.slice(this._prefix.length)),2),a=n[0],i=n[1];if(a===void 0){var s=J(je(i),2),u=s[0],l=s[1];try{for(var h=D(u.keys()),d=h.next();!d.done;d=h.next()){var v=d.value;if(v!==G&&v.startsWith(l)){var y=new Map;return y.set(v.slice(l.length),u.get(v)),new o(y,e)}}}catch(b){t={error:b}}finally{try{d&&!d.done&&(r=h.return)&&r.call(h)}finally{if(t)throw t.error}}}return new o(a,e)},o.prototype.clear=function(){this._size=void 0,this._tree.clear()},o.prototype.delete=function(e){return this._size=void 0,zr(this._tree,e)},o.prototype.entries=function(){return new Me(this,Lr)},o.prototype.forEach=function(e){var t,r;try{for(var n=D(this),a=n.next();!a.done;a=n.next()){var i=J(a.value,2),s=i[0],u=i[1];e(s,u,this)}}catch(l){t={error:l}}finally{try{a&&!a.done&&(r=n.return)&&r.call(n)}finally{if(t)throw t.error}}},o.prototype.fuzzyGet=function(e,t){return Pr(this._tree,e,t)},o.prototype.get=function(e){var t=Ke(this._tree,e);return t!==void 0?t.get(G):void 0},o.prototype.has=function(e){var t=Ke(this._tree,e);return t!==void 0&&t.has(G)},o.prototype.keys=function(){return new Me(this,Et)},o.prototype.set=function(e,t){if(typeof e!="string")throw new Error("key must be a string");this._size=void 0;var r=Pe(this._tree,e);return r.set(G,t),this},Object.defineProperty(o.prototype,"size",{get:function(){if(this._size)return this._size;this._size=0;for(var e=this.entries();!e.next().done;)this._size+=1;return this._size},enumerable:!1,configurable:!0}),o.prototype.update=function(e,t){if(typeof e!="string")throw new Error("key must be a string");this._size=void 0;var r=Pe(this._tree,e);return r.set(G,t(r.get(G))),this},o.prototype.fetch=function(e,t){if(typeof e!="string")throw new Error("key must be a string");this._size=void 0;var r=Pe(this._tree,e),n=r.get(G);return n===void 0&&r.set(G,n=t()),n},o.prototype.values=function(){return new Me(this,St)},o.prototype[Symbol.iterator]=function(){return this.entries()},o.from=function(e){var t,r,n=new o;try{for(var a=D(e),i=a.next();!i.done;i=a.next()){var s=J(i.value,2),u=s[0],l=s[1];n.set(u,l)}}catch(h){t={error:h}}finally{try{i&&!i.done&&(r=a.return)&&r.call(a)}finally{if(t)throw t.error}}return n},o.fromObject=function(e){return o.from(Object.entries(e))},o}(),ke=function(o,e,t){var r,n;if(t===void 0&&(t=[]),e.length===0||o==null)return[o,t];try{for(var a=D(o.keys()),i=a.next();!i.done;i=a.next()){var s=i.value;if(s!==G&&e.startsWith(s))return t.push([o,s]),ke(o.get(s),e.slice(s.length),t)}}catch(u){r={error:u}}finally{try{i&&!i.done&&(n=a.return)&&n.call(a)}finally{if(r)throw r.error}}return t.push([o,e]),ke(void 0,"",t)},Ke=function(o,e){var t,r;if(e.length===0||o==null)return o;try{for(var n=D(o.keys()),a=n.next();!a.done;a=n.next()){var i=a.value;if(i!==G&&e.startsWith(i))return Ke(o.get(i),e.slice(i.length))}}catch(s){t={error:s}}finally{try{a&&!a.done&&(r=n.return)&&r.call(n)}finally{if(t)throw t.error}}},Pe=function(o,e){var t,r,n=e.length;e:for(var a=0;o&&a0)throw new Error("Expected documents to be present. Omit the argument to remove all documents.");this._index=new Le,this._documentCount=0,this._documentIds=new Map,this._idToShortId=new Map,this._fieldLength=new Map,this._avgFieldLength=[],this._storedFields=new Map,this._nextId=0}},o.prototype.discard=function(e){var t=this,r=this._idToShortId.get(e);if(r==null)throw new Error("MiniSearch: cannot discard document with ID ".concat(e,": it is not in the index"));this._idToShortId.delete(e),this._documentIds.delete(r),this._storedFields.delete(r),(this._fieldLength.get(r)||[]).forEach(function(n,a){t.removeFieldLength(r,a,t._documentCount,n)}),this._fieldLength.delete(r),this._documentCount-=1,this._dirtCount+=1,this.maybeAutoVacuum()},o.prototype.maybeAutoVacuum=function(){if(this._options.autoVacuum!==!1){var e=this._options.autoVacuum,t=e.minDirtFactor,r=e.minDirtCount,n=e.batchSize,a=e.batchWait;this.conditionalVacuum({batchSize:n,batchWait:a},{minDirtCount:r,minDirtFactor:t})}},o.prototype.discardAll=function(e){var t,r,n=this._options.autoVacuum;try{this._options.autoVacuum=!1;try{for(var a=D(e),i=a.next();!i.done;i=a.next()){var s=i.value;this.discard(s)}}catch(u){t={error:u}}finally{try{i&&!i.done&&(r=a.return)&&r.call(a)}finally{if(t)throw t.error}}}finally{this._options.autoVacuum=n}this.maybeAutoVacuum()},o.prototype.replace=function(e){var t=this._options,r=t.idField,n=t.extractField,a=n(e,r);this.discard(a),this.add(e)},o.prototype.vacuum=function(e){return e===void 0&&(e={}),this.conditionalVacuum(e)},o.prototype.conditionalVacuum=function(e,t){var r=this;return this._currentVacuum?(this._enqueuedVacuumConditions=this._enqueuedVacuumConditions&&t,this._enqueuedVacuum!=null?this._enqueuedVacuum:(this._enqueuedVacuum=this._currentVacuum.then(function(){var n=r._enqueuedVacuumConditions;return r._enqueuedVacuumConditions=Ue,r.performVacuuming(e,n)}),this._enqueuedVacuum)):this.vacuumConditionsMet(t)===!1?Promise.resolve():(this._currentVacuum=this.performVacuuming(e),this._currentVacuum)},o.prototype.performVacuuming=function(e,t){return Rr(this,void 0,void 0,function(){var r,n,a,i,s,u,l,h,d,v,y,b,E,g,S,T,F,L,R,B,N,_,A,O,w;return Mr(this,function(c){switch(c.label){case 0:if(r=this._dirtCount,!this.vacuumConditionsMet(t))return[3,10];n=e.batchSize||Je.batchSize,a=e.batchWait||Je.batchWait,i=1,c.label=1;case 1:c.trys.push([1,7,8,9]),s=D(this._index),u=s.next(),c.label=2;case 2:if(u.done)return[3,6];l=J(u.value,2),h=l[0],d=l[1];try{for(v=(_=void 0,D(d)),y=v.next();!y.done;y=v.next()){b=J(y.value,2),E=b[0],g=b[1];try{for(S=(O=void 0,D(g)),T=S.next();!T.done;T=S.next())F=J(T.value,1),L=F[0],!this._documentIds.has(L)&&(g.size<=1?d.delete(E):g.delete(L))}catch(f){O={error:f}}finally{try{T&&!T.done&&(w=S.return)&&w.call(S)}finally{if(O)throw O.error}}}}catch(f){_={error:f}}finally{try{y&&!y.done&&(A=v.return)&&A.call(v)}finally{if(_)throw _.error}}return this._index.get(h).size===0&&this._index.delete(h),i%n!==0?[3,4]:[4,new Promise(function(f){return setTimeout(f,a)})];case 3:c.sent(),c.label=4;case 4:i+=1,c.label=5;case 5:return u=s.next(),[3,2];case 6:return[3,9];case 7:return R=c.sent(),B={error:R},[3,9];case 8:try{u&&!u.done&&(N=s.return)&&N.call(s)}finally{if(B)throw B.error}return[7];case 9:this._dirtCount-=r,c.label=10;case 10:return[4,null];case 11:return c.sent(),this._currentVacuum=this._enqueuedVacuum,this._enqueuedVacuum=null,[2]}})})},o.prototype.vacuumConditionsMet=function(e){if(e==null)return!0;var t=e.minDirtCount,r=e.minDirtFactor;return t=t||Be.minDirtCount,r=r||Be.minDirtFactor,this.dirtCount>=t&&this.dirtFactor>=r},Object.defineProperty(o.prototype,"isVacuuming",{get:function(){return this._currentVacuum!=null},enumerable:!1,configurable:!0}),Object.defineProperty(o.prototype,"dirtCount",{get:function(){return this._dirtCount},enumerable:!1,configurable:!0}),Object.defineProperty(o.prototype,"dirtFactor",{get:function(){return this._dirtCount/(1+this._documentCount+this._dirtCount)},enumerable:!1,configurable:!0}),o.prototype.has=function(e){return this._idToShortId.has(e)},o.prototype.getStoredFields=function(e){var t=this._idToShortId.get(e);if(t!=null)return this._storedFields.get(t)},o.prototype.search=function(e,t){var r,n;t===void 0&&(t={});var a=this.executeQuery(e,t),i=[];try{for(var s=D(a),u=s.next();!u.done;u=s.next()){var l=J(u.value,2),h=l[0],d=l[1],v=d.score,y=d.terms,b=d.match,E=y.length||1,g={id:this._documentIds.get(h),score:v*E,terms:Object.keys(b),queryTerms:y,match:b};Object.assign(g,this._storedFields.get(h)),(t.filter==null||t.filter(g))&&i.push(g)}}catch(S){r={error:S}}finally{try{u&&!u.done&&(n=s.return)&&n.call(s)}finally{if(r)throw r.error}}return e===o.wildcard&&t.boostDocument==null&&this._options.searchOptions.boostDocument==null||i.sort(vt),i},o.prototype.autoSuggest=function(e,t){var r,n,a,i;t===void 0&&(t={}),t=W(W({},this._options.autoSuggestOptions),t);var s=new Map;try{for(var u=D(this.search(e,t)),l=u.next();!l.done;l=u.next()){var h=l.value,d=h.score,v=h.terms,y=v.join(" "),b=s.get(y);b!=null?(b.score+=d,b.count+=1):s.set(y,{score:d,terms:v,count:1})}}catch(R){r={error:R}}finally{try{l&&!l.done&&(n=u.return)&&n.call(u)}finally{if(r)throw r.error}}var E=[];try{for(var g=D(s),S=g.next();!S.done;S=g.next()){var T=J(S.value,2),b=T[0],F=T[1],d=F.score,v=F.terms,L=F.count;E.push({suggestion:b,terms:v,score:d/L})}}catch(R){a={error:R}}finally{try{S&&!S.done&&(i=g.return)&&i.call(g)}finally{if(a)throw a.error}}return E.sort(vt),E},Object.defineProperty(o.prototype,"documentCount",{get:function(){return this._documentCount},enumerable:!1,configurable:!0}),Object.defineProperty(o.prototype,"termCount",{get:function(){return this._index.size},enumerable:!1,configurable:!0}),o.loadJSON=function(e,t){if(t==null)throw new Error("MiniSearch: loadJSON should be given the same options used when serializing the index");return this.loadJS(JSON.parse(e),t)},o.getDefault=function(e){if(Ve.hasOwnProperty(e))return ze(Ve,e);throw new Error('MiniSearch: unknown option "'.concat(e,'"'))},o.loadJS=function(e,t){var r,n,a,i,s,u,l=e.index,h=e.documentCount,d=e.nextId,v=e.documentIds,y=e.fieldIds,b=e.fieldLength,E=e.averageFieldLength,g=e.storedFields,S=e.dirtCount,T=e.serializationVersion;if(T!==1&&T!==2)throw new Error("MiniSearch: cannot deserialize an index created with an incompatible version");var F=new o(t);F._documentCount=h,F._nextId=d,F._documentIds=Te(v),F._idToShortId=new Map,F._fieldIds=y,F._fieldLength=Te(b),F._avgFieldLength=E,F._storedFields=Te(g),F._dirtCount=S||0,F._index=new Le;try{for(var L=D(F._documentIds),R=L.next();!R.done;R=L.next()){var B=J(R.value,2),N=B[0],_=B[1];F._idToShortId.set(_,N)}}catch(z){r={error:z}}finally{try{R&&!R.done&&(n=L.return)&&n.call(L)}finally{if(r)throw r.error}}try{for(var A=D(l),O=A.next();!O.done;O=A.next()){var w=J(O.value,2),c=w[0],f=w[1],p=new Map;try{for(var C=(s=void 0,D(Object.keys(f))),I=C.next();!I.done;I=C.next()){var M=I.value,P=f[M];T===1&&(P=P.ds),p.set(parseInt(M,10),Te(P))}}catch(z){s={error:z}}finally{try{I&&!I.done&&(u=C.return)&&u.call(C)}finally{if(s)throw s.error}}F._index.set(c,p)}}catch(z){a={error:z}}finally{try{O&&!O.done&&(i=A.return)&&i.call(A)}finally{if(a)throw a.error}}return F},o.prototype.executeQuery=function(e,t){var r=this;if(t===void 0&&(t={}),e===o.wildcard)return this.executeWildcardQuery(t);if(typeof e!="string"){var n=W(W(W({},t),e),{queries:void 0}),a=e.queries.map(function(g){return r.executeQuery(g,n)});return this.combineResults(a,n.combineWith)}var i=this._options,s=i.tokenize,u=i.processTerm,l=i.searchOptions,h=W(W({tokenize:s,processTerm:u},l),t),d=h.tokenize,v=h.processTerm,y=d(e).flatMap(function(g){return v(g)}).filter(function(g){return!!g}),b=y.map(Jr(h)),E=b.map(function(g){return r.executeQuerySpec(g,h)});return this.combineResults(E,h.combineWith)},o.prototype.executeQuerySpec=function(e,t){var r,n,a,i,s=W(W({},this._options.searchOptions),t),u=(s.fields||this._options.fields).reduce(function(M,P){var z;return W(W({},M),(z={},z[P]=ze(s.boost,P)||1,z))},{}),l=s.boostDocument,h=s.weights,d=s.maxFuzzy,v=s.bm25,y=W(W({},ht.weights),h),b=y.fuzzy,E=y.prefix,g=this._index.get(e.term),S=this.termResults(e.term,e.term,1,g,u,l,v),T,F;if(e.prefix&&(T=this._index.atPrefix(e.term)),e.fuzzy){var L=e.fuzzy===!0?.2:e.fuzzy,R=L<1?Math.min(d,Math.round(e.term.length*L)):L;R&&(F=this._index.fuzzyGet(e.term,R))}if(T)try{for(var B=D(T),N=B.next();!N.done;N=B.next()){var _=J(N.value,2),A=_[0],O=_[1],w=A.length-e.term.length;if(w){F==null||F.delete(A);var c=E*A.length/(A.length+.3*w);this.termResults(e.term,A,c,O,u,l,v,S)}}}catch(M){r={error:M}}finally{try{N&&!N.done&&(n=B.return)&&n.call(B)}finally{if(r)throw r.error}}if(F)try{for(var f=D(F.keys()),p=f.next();!p.done;p=f.next()){var A=p.value,C=J(F.get(A),2),I=C[0],w=C[1];if(w){var c=b*A.length/(A.length+w);this.termResults(e.term,A,c,I,u,l,v,S)}}}catch(M){a={error:M}}finally{try{p&&!p.done&&(i=f.return)&&i.call(f)}finally{if(a)throw a.error}}return S},o.prototype.executeWildcardQuery=function(e){var t,r,n=new Map,a=W(W({},this._options.searchOptions),e);try{for(var i=D(this._documentIds),s=i.next();!s.done;s=i.next()){var u=J(s.value,2),l=u[0],h=u[1],d=a.boostDocument?a.boostDocument(h,"",this._storedFields.get(l)):1;n.set(l,{score:d,terms:[],match:{}})}}catch(v){t={error:v}}finally{try{s&&!s.done&&(r=i.return)&&r.call(i)}finally{if(t)throw t.error}}return n},o.prototype.combineResults=function(e,t){if(t===void 0&&(t=Ge),e.length===0)return new Map;var r=t.toLowerCase();return e.reduce($r[r])||new Map},o.prototype.toJSON=function(){var e,t,r,n,a=[];try{for(var i=D(this._index),s=i.next();!s.done;s=i.next()){var u=J(s.value,2),l=u[0],h=u[1],d={};try{for(var v=(r=void 0,D(h)),y=v.next();!y.done;y=v.next()){var b=J(y.value,2),E=b[0],g=b[1];d[E]=Object.fromEntries(g)}}catch(S){r={error:S}}finally{try{y&&!y.done&&(n=v.return)&&n.call(v)}finally{if(r)throw r.error}}a.push([l,d])}}catch(S){e={error:S}}finally{try{s&&!s.done&&(t=i.return)&&t.call(i)}finally{if(e)throw e.error}}return{documentCount:this._documentCount,nextId:this._nextId,documentIds:Object.fromEntries(this._documentIds),fieldIds:this._fieldIds,fieldLength:Object.fromEntries(this._fieldLength),averageFieldLength:this._avgFieldLength,storedFields:Object.fromEntries(this._storedFields),dirtCount:this._dirtCount,index:a,serializationVersion:2}},o.prototype.termResults=function(e,t,r,n,a,i,s,u){var l,h,d,v,y;if(u===void 0&&(u=new Map),n==null)return u;try{for(var b=D(Object.keys(a)),E=b.next();!E.done;E=b.next()){var g=E.value,S=a[g],T=this._fieldIds[g],F=n.get(T);if(F!=null){var L=F.size,R=this._avgFieldLength[T];try{for(var B=(d=void 0,D(F.keys())),N=B.next();!N.done;N=B.next()){var _=N.value;if(!this._documentIds.has(_)){this.removeTerm(T,_,t),L-=1;continue}var A=i?i(this._documentIds.get(_),t,this._storedFields.get(_)):1;if(A){var O=F.get(_),w=this._fieldLength.get(_)[T],c=Kr(O,L,this._documentCount,w,R,s),f=r*S*A*c,p=u.get(_);if(p){p.score+=f,jr(p.terms,e);var C=ze(p.match,t);C?C.push(g):p.match[t]=[g]}else u.set(_,{score:f,terms:[e],match:(y={},y[t]=[g],y)})}}}catch(I){d={error:I}}finally{try{N&&!N.done&&(v=B.return)&&v.call(B)}finally{if(d)throw d.error}}}}}catch(I){l={error:I}}finally{try{E&&!E.done&&(h=b.return)&&h.call(b)}finally{if(l)throw l.error}}return u},o.prototype.addTerm=function(e,t,r){var n=this._index.fetch(r,pt),a=n.get(e);if(a==null)a=new Map,a.set(t,1),n.set(e,a);else{var i=a.get(t);a.set(t,(i||0)+1)}},o.prototype.removeTerm=function(e,t,r){if(!this._index.has(r)){this.warnDocumentChanged(t,e,r);return}var n=this._index.fetch(r,pt),a=n.get(e);a==null||a.get(t)==null?this.warnDocumentChanged(t,e,r):a.get(t)<=1?a.size<=1?n.delete(e):a.delete(t):a.set(t,a.get(t)-1),this._index.get(r).size===0&&this._index.delete(r)},o.prototype.warnDocumentChanged=function(e,t,r){var n,a;try{for(var i=D(Object.keys(this._fieldIds)),s=i.next();!s.done;s=i.next()){var u=s.value;if(this._fieldIds[u]===t){this._options.logger("warn","MiniSearch: document with ID ".concat(this._documentIds.get(e),' has changed before removal: term "').concat(r,'" was not present in field "').concat(u,'". Removing a document after it has changed can corrupt the index!'),"version_conflict");return}}}catch(l){n={error:l}}finally{try{s&&!s.done&&(a=i.return)&&a.call(i)}finally{if(n)throw n.error}}},o.prototype.addDocumentId=function(e){var t=this._nextId;return this._idToShortId.set(e,t),this._documentIds.set(t,e),this._documentCount+=1,this._nextId+=1,t},o.prototype.addFields=function(e){for(var t=0;t(Ht("data-v-43c4f204"),o=o(),Qt(),o),Hr=["aria-owns"],Qr={class:"shell"},Yr=["title"],Zr=Y(()=>k("span",{"aria-hidden":"true",class:"vpi-search search-icon local-search-icon"},null,-1)),Xr=[Zr],ea={class:"search-actions before"},ta=["title"],ra=Y(()=>k("span",{class:"vpi-arrow-left local-search-icon"},null,-1)),aa=[ra],na=["placeholder"],ia={class:"search-actions"},oa=["title"],sa=Y(()=>k("span",{class:"vpi-layout-list local-search-icon"},null,-1)),ua=[sa],la=["disabled","title"],ca=Y(()=>k("span",{class:"vpi-delete local-search-icon"},null,-1)),fa=[ca],ha=["id","role","aria-labelledby"],da=["aria-selected"],va=["href","aria-label","onMouseenter","onFocusin"],pa={class:"titles"},ya=Y(()=>k("span",{class:"title-icon"},"#",-1)),ma=["innerHTML"],ga=Y(()=>k("span",{class:"vpi-chevron-right local-search-icon"},null,-1)),ba={class:"title main"},wa=["innerHTML"],xa={key:0,class:"excerpt-wrapper"},Fa={key:0,class:"excerpt",inert:""},Ea=["innerHTML"],Sa=Y(()=>k("div",{class:"excerpt-gradient-bottom"},null,-1)),Aa=Y(()=>k("div",{class:"excerpt-gradient-top"},null,-1)),Ta={key:0,class:"no-results"},Na={class:"search-keyboard-shortcuts"},Ca=["aria-label"],Ia=Y(()=>k("span",{class:"vpi-arrow-up navigate-icon"},null,-1)),Da=[Ia],ka=["aria-label"],Oa=Y(()=>k("span",{class:"vpi-arrow-down navigate-icon"},null,-1)),_a=[Oa],Ra=["aria-label"],Ma=Y(()=>k("span",{class:"vpi-corner-down-left navigate-icon"},null,-1)),La=[Ma],Pa=["aria-label"],za=_t({__name:"VPLocalSearchBox",emits:["close"],setup(o,{emit:e}){var P,z;const t=e,r=xe(),n=xe(),a=xe(nr),i=rr(),{activate:s}=kr(r,{immediate:!0,allowOutsideClick:!0,clickOutsideDeactivates:!0,escapeDeactivates:!0}),{localeIndex:u,theme:l}=i,h=tt(async()=>{var m,x,$,K,q,H,V,U,Z;return it(Br.loadJSON(($=await((x=(m=a.value)[u.value])==null?void 0:x.call(m)))==null?void 0:$.default,{fields:["title","titles","text"],storeFields:["title","titles"],searchOptions:{fuzzy:.2,prefix:!0,boost:{title:4,text:2,titles:1},...((K=l.value.search)==null?void 0:K.provider)==="local"&&((H=(q=l.value.search.options)==null?void 0:q.miniSearch)==null?void 0:H.searchOptions)},...((V=l.value.search)==null?void 0:V.provider)==="local"&&((Z=(U=l.value.search.options)==null?void 0:U.miniSearch)==null?void 0:Z.options)}))}),v=Fe(()=>{var m,x;return((m=l.value.search)==null?void 0:m.provider)==="local"&&((x=l.value.search.options)==null?void 0:x.disableQueryPersistence)===!0}).value?oe(""):Rt("vitepress:local-search-filter",""),y=Mt("vitepress:local-search-detailed-list",((P=l.value.search)==null?void 0:P.provider)==="local"&&((z=l.value.search.options)==null?void 0:z.detailedView)===!0),b=Fe(()=>{var m,x,$;return((m=l.value.search)==null?void 0:m.provider)==="local"&&(((x=l.value.search.options)==null?void 0:x.disableDetailedView)===!0||(($=l.value.search.options)==null?void 0:$.detailedView)===!1)}),E=Fe(()=>{var x,$,K,q,H,V,U;const m=((x=l.value.search)==null?void 0:x.options)??l.value.algolia;return((H=(q=(K=($=m==null?void 0:m.locales)==null?void 0:$[u.value])==null?void 0:K.translations)==null?void 0:q.button)==null?void 0:H.buttonText)||((U=(V=m==null?void 0:m.translations)==null?void 0:V.button)==null?void 0:U.buttonText)||"Search"});Lt(()=>{b.value&&(y.value=!1)});const g=xe([]),S=oe(!1);$e(v,()=>{S.value=!1});const T=tt(async()=>{if(n.value)return it(new _r(n.value))},null),F=new qr(16);Pt(()=>[h.value,v.value,y.value],async([m,x,$],K,q)=>{var be,qe,He,Qe;(K==null?void 0:K[0])!==m&&F.clear();let H=!1;if(q(()=>{H=!0}),!m)return;g.value=m.search(x).slice(0,16),S.value=!0;const V=$?await Promise.all(g.value.map(Q=>L(Q.id))):[];if(H)return;for(const{id:Q,mod:ae}of V){const ne=Q.slice(0,Q.indexOf("#"));let te=F.get(ne);if(te)continue;te=new Map,F.set(ne,te);const X=ae.default??ae;if(X!=null&&X.render||X!=null&&X.setup){const ie=Yt(X);ie.config.warnHandler=()=>{},ie.provide(Zt,i),Object.defineProperties(ie.config.globalProperties,{$frontmatter:{get(){return i.frontmatter.value}},$params:{get(){return i.page.value.params}}});const Ye=document.createElement("div");ie.mount(Ye),Ye.querySelectorAll("h1, h2, h3, h4, h5, h6").forEach(he=>{var et;const we=(et=he.querySelector("a"))==null?void 0:et.getAttribute("href"),Ze=(we==null?void 0:we.startsWith("#"))&&we.slice(1);if(!Ze)return;let Xe="";for(;(he=he.nextElementSibling)&&!/^h[1-6]$/i.test(he.tagName);)Xe+=he.outerHTML;te.set(Ze,Xe)}),ie.unmount()}if(H)return}const U=new Set;if(g.value=g.value.map(Q=>{const[ae,ne]=Q.id.split("#"),te=F.get(ae),X=(te==null?void 0:te.get(ne))??"";for(const ie in Q.match)U.add(ie);return{...Q,text:X}}),await de(),H)return;await new Promise(Q=>{var ae;(ae=T.value)==null||ae.unmark({done:()=>{var ne;(ne=T.value)==null||ne.markRegExp(M(U),{done:Q})}})});const Z=((be=r.value)==null?void 0:be.querySelectorAll(".result .excerpt"))??[];for(const Q of Z)(qe=Q.querySelector('mark[data-markjs="true"]'))==null||qe.scrollIntoView({block:"center"});(Qe=(He=n.value)==null?void 0:He.firstElementChild)==null||Qe.scrollIntoView({block:"start"})},{debounce:200,immediate:!0});async function L(m){const x=Xt(m.slice(0,m.indexOf("#")));try{if(!x)throw new Error(`Cannot find file for id: ${m}`);return{id:m,mod:await yt(()=>import(x),__vite__mapDeps([]))}}catch($){return console.error($),{id:m,mod:{}}}}const R=oe(),B=Fe(()=>{var m;return((m=v.value)==null?void 0:m.length)<=0});function N(m=!0){var x,$;(x=R.value)==null||x.focus(),m&&(($=R.value)==null||$.select())}_e(()=>{N()});function _(m){m.pointerType==="mouse"&&N()}const A=oe(-1),O=oe(!1);$e(g,m=>{A.value=m.length?0:-1,w()});function w(){de(()=>{const m=document.querySelector(".result.selected");m&&m.scrollIntoView({block:"nearest"})})}Ee("ArrowUp",m=>{m.preventDefault(),A.value--,A.value<0&&(A.value=g.value.length-1),O.value=!0,w()}),Ee("ArrowDown",m=>{m.preventDefault(),A.value++,A.value>=g.value.length&&(A.value=0),O.value=!0,w()});const c=zt();Ee("Enter",m=>{if(m.isComposing||m.target instanceof HTMLButtonElement&&m.target.type!=="submit")return;const x=g.value[A.value];if(m.target instanceof HTMLInputElement&&!x){m.preventDefault();return}x&&(c.go(x.id),t("close"))}),Ee("Escape",()=>{t("close")});const p=ar({modal:{displayDetails:"Display detailed list",resetButtonTitle:"Reset search",backButtonTitle:"Close search",noResultsText:"No results for",footer:{selectText:"to select",selectKeyAriaLabel:"enter",navigateText:"to navigate",navigateUpKeyAriaLabel:"up arrow",navigateDownKeyAriaLabel:"down arrow",closeText:"to close",closeKeyAriaLabel:"escape"}}});_e(()=>{window.history.pushState(null,"",null)}),Vt("popstate",m=>{m.preventDefault(),t("close")});const C=Bt($t?document.body:null);_e(()=>{de(()=>{C.value=!0,de().then(()=>s())})}),Wt(()=>{C.value=!1});function I(){v.value="",de().then(()=>N(!1))}function M(m){return new RegExp([...m].sort((x,$)=>$.length-x.length).map(x=>`(${er(x)})`).join("|"),"gi")}return(m,x)=>{var $,K,q,H;return ee(),Kt(qt,{to:"body"},[k("div",{ref_key:"el",ref:r,role:"button","aria-owns":($=g.value)!=null&&$.length?"localsearch-list":void 0,"aria-expanded":"true","aria-haspopup":"listbox","aria-labelledby":"localsearch-label",class:"VPLocalSearchBox"},[k("div",{class:"backdrop",onClick:x[0]||(x[0]=V=>m.$emit("close"))}),k("div",Qr,[k("form",{class:"search-bar",onPointerup:x[4]||(x[4]=V=>_(V)),onSubmit:x[5]||(x[5]=Jt(()=>{},["prevent"]))},[k("label",{title:E.value,id:"localsearch-label",for:"localsearch-input"},Xr,8,Yr),k("div",ea,[k("button",{class:"back-button",title:j(p)("modal.backButtonTitle"),onClick:x[1]||(x[1]=V=>m.$emit("close"))},aa,8,ta)]),Ut(k("input",{ref_key:"searchInput",ref:R,"onUpdate:modelValue":x[2]||(x[2]=V=>Gt(v)?v.value=V:null),placeholder:E.value,id:"localsearch-input","aria-labelledby":"localsearch-label",class:"search-input"},null,8,na),[[jt,j(v)]]),k("div",ia,[b.value?Se("",!0):(ee(),re("button",{key:0,class:rt(["toggle-layout-button",{"detailed-list":j(y)}]),type:"button",title:j(p)("modal.displayDetails"),onClick:x[3]||(x[3]=V=>A.value>-1&&(y.value=!j(y)))},ua,10,oa)),k("button",{class:"clear-button",type:"reset",disabled:B.value,title:j(p)("modal.resetButtonTitle"),onClick:I},fa,8,la)])],32),k("ul",{ref_key:"resultsEl",ref:n,id:(K=g.value)!=null&&K.length?"localsearch-list":void 0,role:(q=g.value)!=null&&q.length?"listbox":void 0,"aria-labelledby":(H=g.value)!=null&&H.length?"localsearch-label":void 0,class:"results",onMousemove:x[7]||(x[7]=V=>O.value=!1)},[(ee(!0),re(nt,null,at(g.value,(V,U)=>(ee(),re("li",{key:V.id,role:"option","aria-selected":A.value===U?"true":"false"},[k("a",{href:V.id,class:rt(["result",{selected:A.value===U}]),"aria-label":[...V.titles,V.title].join(" > "),onMouseenter:Z=>!O.value&&(A.value=U),onFocusin:Z=>A.value=U,onClick:x[6]||(x[6]=Z=>m.$emit("close"))},[k("div",null,[k("div",pa,[ya,(ee(!0),re(nt,null,at(V.titles,(Z,be)=>(ee(),re("span",{key:be,class:"title"},[k("span",{class:"text",innerHTML:Z},null,8,ma),ga]))),128)),k("span",ba,[k("span",{class:"text",innerHTML:V.title},null,8,wa)])]),j(y)?(ee(),re("div",xa,[V.text?(ee(),re("div",Fa,[k("div",{class:"vp-doc",innerHTML:V.text},null,8,Ea)])):Se("",!0),Sa,Aa])):Se("",!0)])],42,va)],8,da))),128)),j(v)&&!g.value.length&&S.value?(ee(),re("li",Ta,[ve(pe(j(p)("modal.noResultsText"))+' "',1),k("strong",null,pe(j(v)),1),ve('" ')])):Se("",!0)],40,ha),k("div",Na,[k("span",null,[k("kbd",{"aria-label":j(p)("modal.footer.navigateUpKeyAriaLabel")},Da,8,Ca),k("kbd",{"aria-label":j(p)("modal.footer.navigateDownKeyAriaLabel")},_a,8,ka),ve(" "+pe(j(p)("modal.footer.navigateText")),1)]),k("span",null,[k("kbd",{"aria-label":j(p)("modal.footer.selectKeyAriaLabel")},La,8,Ra),ve(" "+pe(j(p)("modal.footer.selectText")),1)]),k("span",null,[k("kbd",{"aria-label":j(p)("modal.footer.closeKeyAriaLabel")},"esc",8,Pa),ve(" "+pe(j(p)("modal.footer.closeText")),1)])])])],8,Hr)])}}}),Ja=tr(za,[["__scopeId","data-v-43c4f204"]]);export{Ja as default}; diff --git a/vitepress/docs/.vitepress/dist/assets/chunks/download.BUUib3PP.js b/vitepress/docs/.vitepress/dist/assets/chunks/download.BUUib3PP.js new file mode 100644 index 0000000..e5a0587 --- /dev/null +++ b/vitepress/docs/.vitepress/dist/assets/chunks/download.BUUib3PP.js @@ -0,0 +1 @@ +const A="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAB0AAAAZCAIAAABCYLJOAAACLUlEQVR4Ab2Vw6IfPxiG3zfJHPPP2rbdfW3rProsLqCr7rqsbVur2raPPb+Z5Du2+YyRJ87HtLQ0dAIKnYNBQ5BEI4hI271BEIjUNZAgqbUm2WovyRLpyVMnfd83xggq3ATDMHTOzZo1q3ev3iRbXV4RKZEuXLBQayPOAQSESjlnDx85nJ+fjwpa7zUlaHPj2CO/oLTUNnTR8Wb2kvGeZ9rVbwJxTuArm69haAMaqtJXgnZ5y1tVmxKsMoqgKS0p2z1+WdEgItWXjp4XJEiCHesVZ50LnbUOrcE0LQURk2BsYHU0ASmnuqUgrfaSEAcvWs9eMQbKGe0J0L17j8TERJICW+hnx0Ylk6o17SAVF6U1lL3/bld+UbrAzpgx9f///4sEeT/TH955srMwkk2wNeUlROCsiBNCicu7dH+zH5BUgChapThh0NrYqCRpbTsoxZiEKBu60EbSsr+m5Z7RaoiIJQkQkv3lz8De/8/0tJEWekmKdSXb9MUjRYK7L3bk+996/7PpT/Zr6yIko0xcSsK0r2n33/+4NLjnXNIA0nz7kizy/b379ly6ckGIb+kPUhP7zZu5zTN/B/ZzaL+lxPecN2O7YsKbL2edOLLF5f3/v/+zsrOSk1MAxEb1z8j5dezaVggTYiYDyCnIP359q4gENl4EDdJwfLPWAiCplAptABEHp2oMKSfljzTaa0W/GVPxXkQ8EwWw5gCs+VhCK7w1/25o0ZHOj8dd7C0GRnwgNA5r8rwAAAAASUVORK5CYII=";export{A as _}; diff --git a/vitepress/docs/.vitepress/dist/assets/chunks/framework.nQaBHiNx.js b/vitepress/docs/.vitepress/dist/assets/chunks/framework.nQaBHiNx.js new file mode 100644 index 0000000..6b3a396 --- /dev/null +++ b/vitepress/docs/.vitepress/dist/assets/chunks/framework.nQaBHiNx.js @@ -0,0 +1,17 @@ +/** +* @vue/shared v3.4.21 +* (c) 2018-present Yuxi (Evan) You and Vue contributors +* @license MIT +**/function Sr(e,t){const n=new Set(e.split(","));return t?r=>n.has(r.toLowerCase()):r=>n.has(r)}const ee={},_t=[],xe=()=>{},Ti=()=>!1,Wt=e=>e.charCodeAt(0)===111&&e.charCodeAt(1)===110&&(e.charCodeAt(2)>122||e.charCodeAt(2)<97),Tr=e=>e.startsWith("onUpdate:"),ce=Object.assign,Ar=(e,t)=>{const n=e.indexOf(t);n>-1&&e.splice(n,1)},Ai=Object.prototype.hasOwnProperty,Y=(e,t)=>Ai.call(e,t),B=Array.isArray,vt=e=>Rn(e)==="[object Map]",eo=e=>Rn(e)==="[object Set]",q=e=>typeof e=="function",ne=e=>typeof e=="string",At=e=>typeof e=="symbol",Z=e=>e!==null&&typeof e=="object",to=e=>(Z(e)||q(e))&&q(e.then)&&q(e.catch),no=Object.prototype.toString,Rn=e=>no.call(e),Ri=e=>Rn(e).slice(8,-1),ro=e=>Rn(e)==="[object Object]",Rr=e=>ne(e)&&e!=="NaN"&&e[0]!=="-"&&""+parseInt(e,10)===e,bt=Sr(",key,ref,ref_for,ref_key,onVnodeBeforeMount,onVnodeMounted,onVnodeBeforeUpdate,onVnodeUpdated,onVnodeBeforeUnmount,onVnodeUnmounted"),Ln=e=>{const t=Object.create(null);return n=>t[n]||(t[n]=e(n))},Li=/-(\w)/g,Fe=Ln(e=>e.replace(Li,(t,n)=>n?n.toUpperCase():"")),Oi=/\B([A-Z])/g,ft=Ln(e=>e.replace(Oi,"-$1").toLowerCase()),On=Ln(e=>e.charAt(0).toUpperCase()+e.slice(1)),hn=Ln(e=>e?`on${On(e)}`:""),Ze=(e,t)=>!Object.is(e,t),pn=(e,t)=>{for(let n=0;n{Object.defineProperty(e,t,{configurable:!0,enumerable:!1,value:n})},ur=e=>{const t=parseFloat(e);return isNaN(t)?e:t},Ii=e=>{const t=ne(e)?Number(e):NaN;return isNaN(t)?e:t};let rs;const so=()=>rs||(rs=typeof globalThis<"u"?globalThis:typeof self<"u"?self:typeof window<"u"?window:typeof global<"u"?global:{});function Lr(e){if(B(e)){const t={};for(let n=0;n{if(n){const r=n.split(Pi);r.length>1&&(t[r[0].trim()]=r[1].trim())}}),t}function Or(e){let t="";if(ne(e))t=e;else if(B(e))for(let n=0;nne(e)?e:e==null?"":B(e)||Z(e)&&(e.toString===no||!q(e.toString))?JSON.stringify(e,io,2):String(e),io=(e,t)=>t&&t.__v_isRef?io(e,t.value):vt(t)?{[`Map(${t.size})`]:[...t.entries()].reduce((n,[r,s],o)=>(n[Gn(r,o)+" =>"]=s,n),{})}:eo(t)?{[`Set(${t.size})`]:[...t.values()].map(n=>Gn(n))}:At(t)?Gn(t):Z(t)&&!B(t)&&!ro(t)?String(t):t,Gn=(e,t="")=>{var n;return At(e)?`Symbol(${(n=e.description)!=null?n:t})`:e};/** +* @vue/reactivity v3.4.21 +* (c) 2018-present Yuxi (Evan) You and Vue contributors +* @license MIT +**/let ve;class ji{constructor(t=!1){this.detached=t,this._active=!0,this.effects=[],this.cleanups=[],this.parent=ve,!t&&ve&&(this.index=(ve.scopes||(ve.scopes=[])).push(this)-1)}get active(){return this._active}run(t){if(this._active){const n=ve;try{return ve=this,t()}finally{ve=n}}}on(){ve=this}off(){ve=this.parent}stop(t){if(this._active){let n,r;for(n=0,r=this.effects.length;n=4))break}this._dirtyLevel===1&&(this._dirtyLevel=0),ht()}return this._dirtyLevel>=4}set dirty(t){this._dirtyLevel=t?4:0}run(){if(this._dirtyLevel=0,!this.active)return this.fn();let t=Ye,n=ct;try{return Ye=!0,ct=this,this._runnings++,ss(this),this.fn()}finally{os(this),this._runnings--,ct=n,Ye=t}}stop(){var t;this.active&&(ss(this),os(this),(t=this.onStop)==null||t.call(this),this.active=!1)}}function Ui(e){return e.value}function ss(e){e._trackId++,e._depsLength=0}function os(e){if(e.deps.length>e._depsLength){for(let t=e._depsLength;t{const n=new Map;return n.cleanup=e,n.computed=t,n},vn=new WeakMap,at=Symbol(""),hr=Symbol("");function ye(e,t,n){if(Ye&&ct){let r=vn.get(e);r||vn.set(e,r=new Map);let s=r.get(n);s||r.set(n,s=ho(()=>r.delete(n))),uo(ct,s)}}function je(e,t,n,r,s,o){const i=vn.get(e);if(!i)return;let l=[];if(t==="clear")l=[...i.values()];else if(n==="length"&&B(e)){const c=Number(r);i.forEach((a,f)=>{(f==="length"||!At(f)&&f>=c)&&l.push(a)})}else switch(n!==void 0&&l.push(i.get(n)),t){case"add":B(e)?Rr(n)&&l.push(i.get("length")):(l.push(i.get(at)),vt(e)&&l.push(i.get(hr)));break;case"delete":B(e)||(l.push(i.get(at)),vt(e)&&l.push(i.get(hr)));break;case"set":vt(e)&&l.push(i.get(at));break}Mr();for(const c of l)c&&fo(c,4);Pr()}function Bi(e,t){var n;return(n=vn.get(e))==null?void 0:n.get(t)}const ki=Sr("__proto__,__v_isRef,__isVue"),po=new Set(Object.getOwnPropertyNames(Symbol).filter(e=>e!=="arguments"&&e!=="caller").map(e=>Symbol[e]).filter(At)),is=Ki();function Ki(){const e={};return["includes","indexOf","lastIndexOf"].forEach(t=>{e[t]=function(...n){const r=J(this);for(let o=0,i=this.length;o{e[t]=function(...n){dt(),Mr();const r=J(this)[t].apply(this,n);return Pr(),ht(),r}}),e}function Wi(e){const t=J(this);return ye(t,"has",e),t.hasOwnProperty(e)}class go{constructor(t=!1,n=!1){this._isReadonly=t,this._isShallow=n}get(t,n,r){const s=this._isReadonly,o=this._isShallow;if(n==="__v_isReactive")return!s;if(n==="__v_isReadonly")return s;if(n==="__v_isShallow")return o;if(n==="__v_raw")return r===(s?o?sl:vo:o?_o:yo).get(t)||Object.getPrototypeOf(t)===Object.getPrototypeOf(r)?t:void 0;const i=B(t);if(!s){if(i&&Y(is,n))return Reflect.get(is,n,r);if(n==="hasOwnProperty")return Wi}const l=Reflect.get(t,n,r);return(At(n)?po.has(n):ki(n))||(s||ye(t,"get",n),o)?l:de(l)?i&&Rr(n)?l:l.value:Z(l)?s?Pn(l):Mn(l):l}}class mo extends go{constructor(t=!1){super(!1,t)}set(t,n,r,s){let o=t[n];if(!this._isShallow){const c=St(o);if(!bn(r)&&!St(r)&&(o=J(o),r=J(r)),!B(t)&&de(o)&&!de(r))return c?!1:(o.value=r,!0)}const i=B(t)&&Rr(n)?Number(n)e,In=e=>Reflect.getPrototypeOf(e);function Qt(e,t,n=!1,r=!1){e=e.__v_raw;const s=J(e),o=J(t);n||(Ze(t,o)&&ye(s,"get",t),ye(s,"get",o));const{has:i}=In(s),l=r?Nr:n?Hr:Dt;if(i.call(s,t))return l(e.get(t));if(i.call(s,o))return l(e.get(o));e!==s&&e.get(t)}function Zt(e,t=!1){const n=this.__v_raw,r=J(n),s=J(e);return t||(Ze(e,s)&&ye(r,"has",e),ye(r,"has",s)),e===s?n.has(e):n.has(e)||n.has(s)}function en(e,t=!1){return e=e.__v_raw,!t&&ye(J(e),"iterate",at),Reflect.get(e,"size",e)}function ls(e){e=J(e);const t=J(this);return In(t).has.call(t,e)||(t.add(e),je(t,"add",e,e)),this}function cs(e,t){t=J(t);const n=J(this),{has:r,get:s}=In(n);let o=r.call(n,e);o||(e=J(e),o=r.call(n,e));const i=s.call(n,e);return n.set(e,t),o?Ze(t,i)&&je(n,"set",e,t):je(n,"add",e,t),this}function as(e){const t=J(this),{has:n,get:r}=In(t);let s=n.call(t,e);s||(e=J(e),s=n.call(t,e)),r&&r.call(t,e);const o=t.delete(e);return s&&je(t,"delete",e,void 0),o}function us(){const e=J(this),t=e.size!==0,n=e.clear();return t&&je(e,"clear",void 0,void 0),n}function tn(e,t){return function(r,s){const o=this,i=o.__v_raw,l=J(i),c=t?Nr:e?Hr:Dt;return!e&&ye(l,"iterate",at),i.forEach((a,f)=>r.call(s,c(a),c(f),o))}}function nn(e,t,n){return function(...r){const s=this.__v_raw,o=J(s),i=vt(o),l=e==="entries"||e===Symbol.iterator&&i,c=e==="keys"&&i,a=s[e](...r),f=n?Nr:t?Hr:Dt;return!t&&ye(o,"iterate",c?hr:at),{next(){const{value:h,done:p}=a.next();return p?{value:h,done:p}:{value:l?[f(h[0]),f(h[1])]:f(h),done:p}},[Symbol.iterator](){return this}}}}function Be(e){return function(...t){return e==="delete"?!1:e==="clear"?void 0:this}}function Yi(){const e={get(o){return Qt(this,o)},get size(){return en(this)},has:Zt,add:ls,set:cs,delete:as,clear:us,forEach:tn(!1,!1)},t={get(o){return Qt(this,o,!1,!0)},get size(){return en(this)},has:Zt,add:ls,set:cs,delete:as,clear:us,forEach:tn(!1,!0)},n={get(o){return Qt(this,o,!0)},get size(){return en(this,!0)},has(o){return Zt.call(this,o,!0)},add:Be("add"),set:Be("set"),delete:Be("delete"),clear:Be("clear"),forEach:tn(!0,!1)},r={get(o){return Qt(this,o,!0,!0)},get size(){return en(this,!0)},has(o){return Zt.call(this,o,!0)},add:Be("add"),set:Be("set"),delete:Be("delete"),clear:Be("clear"),forEach:tn(!0,!0)};return["keys","values","entries",Symbol.iterator].forEach(o=>{e[o]=nn(o,!1,!1),n[o]=nn(o,!0,!1),t[o]=nn(o,!1,!0),r[o]=nn(o,!0,!0)}),[e,n,t,r]}const[Ji,Qi,Zi,el]=Yi();function Fr(e,t){const n=t?e?el:Zi:e?Qi:Ji;return(r,s,o)=>s==="__v_isReactive"?!e:s==="__v_isReadonly"?e:s==="__v_raw"?r:Reflect.get(Y(n,s)&&s in r?n:r,s,o)}const tl={get:Fr(!1,!1)},nl={get:Fr(!1,!0)},rl={get:Fr(!0,!1)},yo=new WeakMap,_o=new WeakMap,vo=new WeakMap,sl=new WeakMap;function ol(e){switch(e){case"Object":case"Array":return 1;case"Map":case"Set":case"WeakMap":case"WeakSet":return 2;default:return 0}}function il(e){return e.__v_skip||!Object.isExtensible(e)?0:ol(Ri(e))}function Mn(e){return St(e)?e:$r(e,!1,Gi,tl,yo)}function ll(e){return $r(e,!1,Xi,nl,_o)}function Pn(e){return $r(e,!0,zi,rl,vo)}function $r(e,t,n,r,s){if(!Z(e)||e.__v_raw&&!(t&&e.__v_isReactive))return e;const o=s.get(e);if(o)return o;const i=il(e);if(i===0)return e;const l=new Proxy(e,i===2?r:n);return s.set(e,l),l}function wt(e){return St(e)?wt(e.__v_raw):!!(e&&e.__v_isReactive)}function St(e){return!!(e&&e.__v_isReadonly)}function bn(e){return!!(e&&e.__v_isShallow)}function bo(e){return wt(e)||St(e)}function J(e){const t=e&&e.__v_raw;return t?J(t):e}function Mt(e){return Object.isExtensible(e)&&_n(e,"__v_skip",!0),e}const Dt=e=>Z(e)?Mn(e):e,Hr=e=>Z(e)?Pn(e):e;class wo{constructor(t,n,r,s){this.getter=t,this._setter=n,this.dep=void 0,this.__v_isRef=!0,this.__v_isReadonly=!1,this.effect=new Ir(()=>t(this._value),()=>Pt(this,this.effect._dirtyLevel===2?2:3)),this.effect.computed=this,this.effect.active=this._cacheable=!s,this.__v_isReadonly=r}get value(){const t=J(this);return(!t._cacheable||t.effect.dirty)&&Ze(t._value,t._value=t.effect.run())&&Pt(t,4),jr(t),t.effect._dirtyLevel>=2&&Pt(t,2),t._value}set value(t){this._setter(t)}get _dirty(){return this.effect.dirty}set _dirty(t){this.effect.dirty=t}}function cl(e,t,n=!1){let r,s;const o=q(e);return o?(r=e,s=xe):(r=e.get,s=e.set),new wo(r,s,o||!s,n)}function jr(e){var t;Ye&&ct&&(e=J(e),uo(ct,(t=e.dep)!=null?t:e.dep=ho(()=>e.dep=void 0,e instanceof wo?e:void 0)))}function Pt(e,t=4,n){e=J(e);const r=e.dep;r&&fo(r,t)}function de(e){return!!(e&&e.__v_isRef===!0)}function se(e){return Eo(e,!1)}function Vr(e){return Eo(e,!0)}function Eo(e,t){return de(e)?e:new al(e,t)}class al{constructor(t,n){this.__v_isShallow=n,this.dep=void 0,this.__v_isRef=!0,this._rawValue=n?t:J(t),this._value=n?t:Dt(t)}get value(){return jr(this),this._value}set value(t){const n=this.__v_isShallow||bn(t)||St(t);t=n?t:J(t),Ze(t,this._rawValue)&&(this._rawValue=t,this._value=n?t:Dt(t),Pt(this,4))}}function Co(e){return de(e)?e.value:e}const ul={get:(e,t,n)=>Co(Reflect.get(e,t,n)),set:(e,t,n,r)=>{const s=e[t];return de(s)&&!de(n)?(s.value=n,!0):Reflect.set(e,t,n,r)}};function xo(e){return wt(e)?e:new Proxy(e,ul)}class fl{constructor(t){this.dep=void 0,this.__v_isRef=!0;const{get:n,set:r}=t(()=>jr(this),()=>Pt(this));this._get=n,this._set=r}get value(){return this._get()}set value(t){this._set(t)}}function dl(e){return new fl(e)}class hl{constructor(t,n,r){this._object=t,this._key=n,this._defaultValue=r,this.__v_isRef=!0}get value(){const t=this._object[this._key];return t===void 0?this._defaultValue:t}set value(t){this._object[this._key]=t}get dep(){return Bi(J(this._object),this._key)}}class pl{constructor(t){this._getter=t,this.__v_isRef=!0,this.__v_isReadonly=!0}get value(){return this._getter()}}function gl(e,t,n){return de(e)?e:q(e)?new pl(e):Z(e)&&arguments.length>1?ml(e,t,n):se(e)}function ml(e,t,n){const r=e[t];return de(r)?r:new hl(e,t,n)}/** +* @vue/runtime-core v3.4.21 +* (c) 2018-present Yuxi (Evan) You and Vue contributors +* @license MIT +**/function Je(e,t,n,r){try{return r?e(...r):e()}catch(s){qt(s,t,n)}}function Se(e,t,n,r){if(q(e)){const o=Je(e,t,n,r);return o&&to(o)&&o.catch(i=>{qt(i,t,n)}),o}const s=[];for(let o=0;o>>1,s=he[r],o=Bt(s);oPe&&he.splice(t,1)}function bl(e){B(e)?Et.push(...e):(!qe||!qe.includes(e,e.allowRecurse?ot+1:ot))&&Et.push(e),To()}function fs(e,t,n=Ut?Pe+1:0){for(;nBt(n)-Bt(r));if(Et.length=0,qe){qe.push(...t);return}for(qe=t,ot=0;ote.id==null?1/0:e.id,wl=(e,t)=>{const n=Bt(e)-Bt(t);if(n===0){if(e.pre&&!t.pre)return-1;if(t.pre&&!e.pre)return 1}return n};function Ao(e){pr=!1,Ut=!0,he.sort(wl);try{for(Pe=0;Pene(y)?y.trim():y)),h&&(s=n.map(ur))}let l,c=r[l=hn(t)]||r[l=hn(Fe(t))];!c&&o&&(c=r[l=hn(ft(t))]),c&&Se(c,e,6,s);const a=r[l+"Once"];if(a){if(!e.emitted)e.emitted={};else if(e.emitted[l])return;e.emitted[l]=!0,Se(a,e,6,s)}}function Ro(e,t,n=!1){const r=t.emitsCache,s=r.get(e);if(s!==void 0)return s;const o=e.emits;let i={},l=!1;if(!q(e)){const c=a=>{const f=Ro(a,t,!0);f&&(l=!0,ce(i,f))};!n&&t.mixins.length&&t.mixins.forEach(c),e.extends&&c(e.extends),e.mixins&&e.mixins.forEach(c)}return!o&&!l?(Z(e)&&r.set(e,null),null):(B(o)?o.forEach(c=>i[c]=null):ce(i,o),Z(e)&&r.set(e,i),i)}function $n(e,t){return!e||!Wt(t)?!1:(t=t.slice(2).replace(/Once$/,""),Y(e,t[0].toLowerCase()+t.slice(1))||Y(e,ft(t))||Y(e,t))}let le=null,Hn=null;function En(e){const t=le;return le=e,Hn=e&&e.type.__scopeId||null,t}function Za(e){Hn=e}function eu(){Hn=null}function Cl(e,t=le,n){if(!t||e._n)return e;const r=(...s)=>{r._d&&Ss(-1);const o=En(t);let i;try{i=e(...s)}finally{En(o),r._d&&Ss(1)}return i};return r._n=!0,r._c=!0,r._d=!0,r}function zn(e){const{type:t,vnode:n,proxy:r,withProxy:s,props:o,propsOptions:[i],slots:l,attrs:c,emit:a,render:f,renderCache:h,data:p,setupState:y,ctx:w,inheritAttrs:I}=e;let N,K;const k=En(e);try{if(n.shapeFlag&4){const _=s||r,M=_;N=Re(f.call(M,_,h,o,y,p,w)),K=c}else{const _=t;N=Re(_.length>1?_(o,{attrs:c,slots:l,emit:a}):_(o,null)),K=t.props?c:xl(c)}}catch(_){jt.length=0,qt(_,e,1),N=oe(be)}let g=N;if(K&&I!==!1){const _=Object.keys(K),{shapeFlag:M}=g;_.length&&M&7&&(i&&_.some(Tr)&&(K=Sl(K,i)),g=et(g,K))}return n.dirs&&(g=et(g),g.dirs=g.dirs?g.dirs.concat(n.dirs):n.dirs),n.transition&&(g.transition=n.transition),N=g,En(k),N}const xl=e=>{let t;for(const n in e)(n==="class"||n==="style"||Wt(n))&&((t||(t={}))[n]=e[n]);return t},Sl=(e,t)=>{const n={};for(const r in e)(!Tr(r)||!(r.slice(9)in t))&&(n[r]=e[r]);return n};function Tl(e,t,n){const{props:r,children:s,component:o}=e,{props:i,children:l,patchFlag:c}=t,a=o.emitsOptions;if(t.dirs||t.transition)return!0;if(n&&c>=0){if(c&1024)return!0;if(c&16)return r?ds(r,i,a):!!i;if(c&8){const f=t.dynamicProps;for(let h=0;he.__isSuspense;function Io(e,t){t&&t.pendingBranch?B(e)?t.effects.push(...e):t.effects.push(e):bl(e)}const Ll=Symbol.for("v-scx"),Ol=()=>xt(Ll);function Br(e,t){return jn(e,null,t)}function ru(e,t){return jn(e,null,{flush:"post"})}const rn={};function Ve(e,t,n){return jn(e,t,n)}function jn(e,t,{immediate:n,deep:r,flush:s,once:o,onTrack:i,onTrigger:l}=ee){if(t&&o){const L=t;t=(...F)=>{L(...F),M()}}const c=ue,a=L=>r===!0?L:lt(L,r===!1?1:void 0);let f,h=!1,p=!1;if(de(e)?(f=()=>e.value,h=bn(e)):wt(e)?(f=()=>a(e),h=!0):B(e)?(p=!0,h=e.some(L=>wt(L)||bn(L)),f=()=>e.map(L=>{if(de(L))return L.value;if(wt(L))return a(L);if(q(L))return Je(L,c,2)})):q(e)?t?f=()=>Je(e,c,2):f=()=>(y&&y(),Se(e,c,3,[w])):f=xe,t&&r){const L=f;f=()=>lt(L())}let y,w=L=>{y=g.onStop=()=>{Je(L,c,4),y=g.onStop=void 0}},I;if(Xt)if(w=xe,t?n&&Se(t,c,3,[f(),p?[]:void 0,w]):f(),s==="sync"){const L=Ol();I=L.__watcherHandles||(L.__watcherHandles=[])}else return xe;let N=p?new Array(e.length).fill(rn):rn;const K=()=>{if(!(!g.active||!g.dirty))if(t){const L=g.run();(r||h||(p?L.some((F,T)=>Ze(F,N[T])):Ze(L,N)))&&(y&&y(),Se(t,c,3,[L,N===rn?void 0:p&&N[0]===rn?[]:N,w]),N=L)}else g.run()};K.allowRecurse=!!t;let k;s==="sync"?k=K:s==="post"?k=()=>ge(K,c&&c.suspense):(K.pre=!0,c&&(K.id=c.uid),k=()=>Fn(K));const g=new Ir(f,xe,k),_=lo(),M=()=>{g.stop(),_&&Ar(_.effects,g)};return t?n?K():N=g.run():s==="post"?ge(g.run.bind(g),c&&c.suspense):g.run(),I&&I.push(M),M}function Il(e,t,n){const r=this.proxy,s=ne(e)?e.includes(".")?Mo(r,e):()=>r[e]:e.bind(r,r);let o;q(t)?o=t:(o=t.handler,n=t);const i=zt(this),l=jn(s,o.bind(r),n);return i(),l}function Mo(e,t){const n=t.split(".");return()=>{let r=e;for(let s=0;s0){if(n>=t)return e;n++}if(r=r||new Set,r.has(e))return e;if(r.add(e),de(e))lt(e.value,t,n,r);else if(B(e))for(let s=0;s{lt(s,t,n,r)});else if(ro(e))for(const s in e)lt(e[s],t,n,r);return e}function su(e,t){if(le===null)return e;const n=kn(le)||le.proxy,r=e.dirs||(e.dirs=[]);for(let s=0;s{e.isMounted=!0}),Ho(()=>{e.isUnmounting=!0}),e}const we=[Function,Array],Po={mode:String,appear:Boolean,persisted:Boolean,onBeforeEnter:we,onEnter:we,onAfterEnter:we,onEnterCancelled:we,onBeforeLeave:we,onLeave:we,onAfterLeave:we,onLeaveCancelled:we,onBeforeAppear:we,onAppear:we,onAfterAppear:we,onAppearCancelled:we},Pl={name:"BaseTransition",props:Po,setup(e,{slots:t}){const n=Bn(),r=Ml();return()=>{const s=t.default&&Fo(t.default(),!0);if(!s||!s.length)return;let o=s[0];if(s.length>1){for(const p of s)if(p.type!==be){o=p;break}}const i=J(e),{mode:l}=i;if(r.isLeaving)return Xn(o);const c=ps(o);if(!c)return Xn(o);const a=gr(c,i,r,n);mr(c,a);const f=n.subTree,h=f&&ps(f);if(h&&h.type!==be&&!it(c,h)){const p=gr(h,i,r,n);if(mr(h,p),l==="out-in")return r.isLeaving=!0,p.afterLeave=()=>{r.isLeaving=!1,n.update.active!==!1&&(n.effect.dirty=!0,n.update())},Xn(o);l==="in-out"&&c.type!==be&&(p.delayLeave=(y,w,I)=>{const N=No(r,h);N[String(h.key)]=h,y[Ge]=()=>{w(),y[Ge]=void 0,delete a.delayedLeave},a.delayedLeave=I})}return o}}},Nl=Pl;function No(e,t){const{leavingVNodes:n}=e;let r=n.get(t.type);return r||(r=Object.create(null),n.set(t.type,r)),r}function gr(e,t,n,r){const{appear:s,mode:o,persisted:i=!1,onBeforeEnter:l,onEnter:c,onAfterEnter:a,onEnterCancelled:f,onBeforeLeave:h,onLeave:p,onAfterLeave:y,onLeaveCancelled:w,onBeforeAppear:I,onAppear:N,onAfterAppear:K,onAppearCancelled:k}=t,g=String(e.key),_=No(n,e),M=(T,$)=>{T&&Se(T,r,9,$)},L=(T,$)=>{const E=$[1];M(T,$),B(T)?T.every(j=>j.length<=1)&&E():T.length<=1&&E()},F={mode:o,persisted:i,beforeEnter(T){let $=l;if(!n.isMounted)if(s)$=I||l;else return;T[Ge]&&T[Ge](!0);const E=_[g];E&&it(e,E)&&E.el[Ge]&&E.el[Ge](),M($,[T])},enter(T){let $=c,E=a,j=f;if(!n.isMounted)if(s)$=N||c,E=K||a,j=k||f;else return;let A=!1;const G=T[sn]=ie=>{A||(A=!0,ie?M(j,[T]):M(E,[T]),F.delayedLeave&&F.delayedLeave(),T[sn]=void 0)};$?L($,[T,G]):G()},leave(T,$){const E=String(e.key);if(T[sn]&&T[sn](!0),n.isUnmounting)return $();M(h,[T]);let j=!1;const A=T[Ge]=G=>{j||(j=!0,$(),G?M(w,[T]):M(y,[T]),T[Ge]=void 0,_[E]===e&&delete _[E])};_[E]=e,p?L(p,[T,A]):A()},clone(T){return gr(T,t,n,r)}};return F}function Xn(e){if(Gt(e))return e=et(e),e.children=null,e}function ps(e){return Gt(e)?e.children?e.children[0]:void 0:e}function mr(e,t){e.shapeFlag&6&&e.component?mr(e.component.subTree,t):e.shapeFlag&128?(e.ssContent.transition=t.clone(e.ssContent),e.ssFallback.transition=t.clone(e.ssFallback)):e.transition=t}function Fo(e,t=!1,n){let r=[],s=0;for(let o=0;o1)for(let o=0;o!!e.type.__asyncLoader;/*! #__NO_SIDE_EFFECTS__ */function ou(e){q(e)&&(e={loader:e});const{loader:t,loadingComponent:n,errorComponent:r,delay:s=200,timeout:o,suspensible:i=!0,onError:l}=e;let c=null,a,f=0;const h=()=>(f++,c=null,p()),p=()=>{let y;return c||(y=c=t().catch(w=>{if(w=w instanceof Error?w:new Error(String(w)),l)return new Promise((I,N)=>{l(w,()=>I(h()),()=>N(w),f+1)});throw w}).then(w=>y!==c&&c?c:(w&&(w.__esModule||w[Symbol.toStringTag]==="Module")&&(w=w.default),a=w,w)))};return kr({name:"AsyncComponentWrapper",__asyncLoader:p,get __asyncResolved(){return a},setup(){const y=ue;if(a)return()=>Yn(a,y);const w=k=>{c=null,qt(k,y,13,!r)};if(i&&y.suspense||Xt)return p().then(k=>()=>Yn(k,y)).catch(k=>(w(k),()=>r?oe(r,{error:k}):null));const I=se(!1),N=se(),K=se(!!s);return s&&setTimeout(()=>{K.value=!1},s),o!=null&&setTimeout(()=>{if(!I.value&&!N.value){const k=new Error(`Async component timed out after ${o}ms.`);w(k),N.value=k}},o),p().then(()=>{I.value=!0,y.parent&&Gt(y.parent.vnode)&&(y.parent.effect.dirty=!0,Fn(y.parent.update))}).catch(k=>{w(k),N.value=k}),()=>{if(I.value&&a)return Yn(a,y);if(N.value&&r)return oe(r,{error:N.value});if(n&&!K.value)return oe(n)}}})}function Yn(e,t){const{ref:n,props:r,children:s,ce:o}=t.vnode,i=oe(e,r,s);return i.ref=n,i.ce=o,delete t.vnode.ce,i}const Gt=e=>e.type.__isKeepAlive;function Fl(e,t){$o(e,"a",t)}function $l(e,t){$o(e,"da",t)}function $o(e,t,n=ue){const r=e.__wdc||(e.__wdc=()=>{let s=n;for(;s;){if(s.isDeactivated)return;s=s.parent}return e()});if(Vn(t,r,n),n){let s=n.parent;for(;s&&s.parent;)Gt(s.parent.vnode)&&Hl(r,t,n,s),s=s.parent}}function Hl(e,t,n,r){const s=Vn(t,e,r,!0);Dn(()=>{Ar(r[t],s)},n)}function Vn(e,t,n=ue,r=!1){if(n){const s=n[e]||(n[e]=[]),o=t.__weh||(t.__weh=(...i)=>{if(n.isUnmounted)return;dt();const l=zt(n),c=Se(t,n,e,i);return l(),ht(),c});return r?s.unshift(o):s.push(o),o}}const Ue=e=>(t,n=ue)=>(!Xt||e==="sp")&&Vn(e,(...r)=>t(...r),n),jl=Ue("bm"),Rt=Ue("m"),Vl=Ue("bu"),Dl=Ue("u"),Ho=Ue("bum"),Dn=Ue("um"),Ul=Ue("sp"),Bl=Ue("rtg"),kl=Ue("rtc");function Kl(e,t=ue){Vn("ec",e,t)}function iu(e,t,n,r){let s;const o=n&&n[r];if(B(e)||ne(e)){s=new Array(e.length);for(let i=0,l=e.length;it(i,l,void 0,o&&o[l]));else{const i=Object.keys(e);s=new Array(i.length);for(let l=0,c=i.length;lSn(t)?!(t.type===be||t.type===me&&!jo(t.children)):!0)?e:null}function cu(e,t){const n={};for(const r in e)n[t&&/[A-Z]/.test(r)?`on:${r}`:hn(r)]=e[r];return n}const yr=e=>e?ni(e)?kn(e)||e.proxy:yr(e.parent):null,Nt=ce(Object.create(null),{$:e=>e,$el:e=>e.vnode.el,$data:e=>e.data,$props:e=>e.props,$attrs:e=>e.attrs,$slots:e=>e.slots,$refs:e=>e.refs,$parent:e=>yr(e.parent),$root:e=>yr(e.root),$emit:e=>e.emit,$options:e=>Kr(e),$forceUpdate:e=>e.f||(e.f=()=>{e.effect.dirty=!0,Fn(e.update)}),$nextTick:e=>e.n||(e.n=Nn.bind(e.proxy)),$watch:e=>Il.bind(e)}),Jn=(e,t)=>e!==ee&&!e.__isScriptSetup&&Y(e,t),Wl={get({_:e},t){const{ctx:n,setupState:r,data:s,props:o,accessCache:i,type:l,appContext:c}=e;let a;if(t[0]!=="$"){const y=i[t];if(y!==void 0)switch(y){case 1:return r[t];case 2:return s[t];case 4:return n[t];case 3:return o[t]}else{if(Jn(r,t))return i[t]=1,r[t];if(s!==ee&&Y(s,t))return i[t]=2,s[t];if((a=e.propsOptions[0])&&Y(a,t))return i[t]=3,o[t];if(n!==ee&&Y(n,t))return i[t]=4,n[t];_r&&(i[t]=0)}}const f=Nt[t];let h,p;if(f)return t==="$attrs"&&ye(e,"get",t),f(e);if((h=l.__cssModules)&&(h=h[t]))return h;if(n!==ee&&Y(n,t))return i[t]=4,n[t];if(p=c.config.globalProperties,Y(p,t))return p[t]},set({_:e},t,n){const{data:r,setupState:s,ctx:o}=e;return Jn(s,t)?(s[t]=n,!0):r!==ee&&Y(r,t)?(r[t]=n,!0):Y(e.props,t)||t[0]==="$"&&t.slice(1)in e?!1:(o[t]=n,!0)},has({_:{data:e,setupState:t,accessCache:n,ctx:r,appContext:s,propsOptions:o}},i){let l;return!!n[i]||e!==ee&&Y(e,i)||Jn(t,i)||(l=o[0])&&Y(l,i)||Y(r,i)||Y(Nt,i)||Y(s.config.globalProperties,i)},defineProperty(e,t,n){return n.get!=null?e._.accessCache[t]=0:Y(n,"value")&&this.set(e,t,n.value,null),Reflect.defineProperty(e,t,n)}};function au(){return ql().slots}function ql(){const e=Bn();return e.setupContext||(e.setupContext=si(e))}function gs(e){return B(e)?e.reduce((t,n)=>(t[n]=null,t),{}):e}let _r=!0;function Gl(e){const t=Kr(e),n=e.proxy,r=e.ctx;_r=!1,t.beforeCreate&&ms(t.beforeCreate,e,"bc");const{data:s,computed:o,methods:i,watch:l,provide:c,inject:a,created:f,beforeMount:h,mounted:p,beforeUpdate:y,updated:w,activated:I,deactivated:N,beforeDestroy:K,beforeUnmount:k,destroyed:g,unmounted:_,render:M,renderTracked:L,renderTriggered:F,errorCaptured:T,serverPrefetch:$,expose:E,inheritAttrs:j,components:A,directives:G,filters:ie}=t;if(a&&zl(a,r,null),i)for(const X in i){const V=i[X];q(V)&&(r[X]=V.bind(n))}if(s){const X=s.call(n,n);Z(X)&&(e.data=Mn(X))}if(_r=!0,o)for(const X in o){const V=o[X],$e=q(V)?V.bind(n,n):q(V.get)?V.get.bind(n,n):xe,Yt=!q(V)&&q(V.set)?V.set.bind(n):xe,tt=re({get:$e,set:Yt});Object.defineProperty(r,X,{enumerable:!0,configurable:!0,get:()=>tt.value,set:Oe=>tt.value=Oe})}if(l)for(const X in l)Vo(l[X],r,n,X);if(c){const X=q(c)?c.call(n):c;Reflect.ownKeys(X).forEach(V=>{ec(V,X[V])})}f&&ms(f,e,"c");function D(X,V){B(V)?V.forEach($e=>X($e.bind(n))):V&&X(V.bind(n))}if(D(jl,h),D(Rt,p),D(Vl,y),D(Dl,w),D(Fl,I),D($l,N),D(Kl,T),D(kl,L),D(Bl,F),D(Ho,k),D(Dn,_),D(Ul,$),B(E))if(E.length){const X=e.exposed||(e.exposed={});E.forEach(V=>{Object.defineProperty(X,V,{get:()=>n[V],set:$e=>n[V]=$e})})}else e.exposed||(e.exposed={});M&&e.render===xe&&(e.render=M),j!=null&&(e.inheritAttrs=j),A&&(e.components=A),G&&(e.directives=G)}function zl(e,t,n=xe){B(e)&&(e=vr(e));for(const r in e){const s=e[r];let o;Z(s)?"default"in s?o=xt(s.from||r,s.default,!0):o=xt(s.from||r):o=xt(s),de(o)?Object.defineProperty(t,r,{enumerable:!0,configurable:!0,get:()=>o.value,set:i=>o.value=i}):t[r]=o}}function ms(e,t,n){Se(B(e)?e.map(r=>r.bind(t.proxy)):e.bind(t.proxy),t,n)}function Vo(e,t,n,r){const s=r.includes(".")?Mo(n,r):()=>n[r];if(ne(e)){const o=t[e];q(o)&&Ve(s,o)}else if(q(e))Ve(s,e.bind(n));else if(Z(e))if(B(e))e.forEach(o=>Vo(o,t,n,r));else{const o=q(e.handler)?e.handler.bind(n):t[e.handler];q(o)&&Ve(s,o,e)}}function Kr(e){const t=e.type,{mixins:n,extends:r}=t,{mixins:s,optionsCache:o,config:{optionMergeStrategies:i}}=e.appContext,l=o.get(t);let c;return l?c=l:!s.length&&!n&&!r?c=t:(c={},s.length&&s.forEach(a=>Cn(c,a,i,!0)),Cn(c,t,i)),Z(t)&&o.set(t,c),c}function Cn(e,t,n,r=!1){const{mixins:s,extends:o}=t;o&&Cn(e,o,n,!0),s&&s.forEach(i=>Cn(e,i,n,!0));for(const i in t)if(!(r&&i==="expose")){const l=Xl[i]||n&&n[i];e[i]=l?l(e[i],t[i]):t[i]}return e}const Xl={data:ys,props:_s,emits:_s,methods:It,computed:It,beforeCreate:pe,created:pe,beforeMount:pe,mounted:pe,beforeUpdate:pe,updated:pe,beforeDestroy:pe,beforeUnmount:pe,destroyed:pe,unmounted:pe,activated:pe,deactivated:pe,errorCaptured:pe,serverPrefetch:pe,components:It,directives:It,watch:Jl,provide:ys,inject:Yl};function ys(e,t){return t?e?function(){return ce(q(e)?e.call(this,this):e,q(t)?t.call(this,this):t)}:t:e}function Yl(e,t){return It(vr(e),vr(t))}function vr(e){if(B(e)){const t={};for(let n=0;n1)return n&&q(t)?t.call(r&&r.proxy):t}}function tc(e,t,n,r=!1){const s={},o={};_n(o,Un,1),e.propsDefaults=Object.create(null),Uo(e,t,s,o);for(const i in e.propsOptions[0])i in s||(s[i]=void 0);n?e.props=r?s:ll(s):e.type.props?e.props=s:e.props=o,e.attrs=o}function nc(e,t,n,r){const{props:s,attrs:o,vnode:{patchFlag:i}}=e,l=J(s),[c]=e.propsOptions;let a=!1;if((r||i>0)&&!(i&16)){if(i&8){const f=e.vnode.dynamicProps;for(let h=0;h{c=!0;const[p,y]=Bo(h,t,!0);ce(i,p),y&&l.push(...y)};!n&&t.mixins.length&&t.mixins.forEach(f),e.extends&&f(e.extends),e.mixins&&e.mixins.forEach(f)}if(!o&&!c)return Z(e)&&r.set(e,_t),_t;if(B(o))for(let f=0;f-1,y[1]=I<0||w-1||Y(y,"default"))&&l.push(h)}}}const a=[i,l];return Z(e)&&r.set(e,a),a}function vs(e){return e[0]!=="$"&&!bt(e)}function bs(e){return e===null?"null":typeof e=="function"?e.name||"":typeof e=="object"&&e.constructor&&e.constructor.name||""}function ws(e,t){return bs(e)===bs(t)}function Es(e,t){return B(t)?t.findIndex(n=>ws(n,e)):q(t)&&ws(t,e)?0:-1}const ko=e=>e[0]==="_"||e==="$stable",Wr=e=>B(e)?e.map(Re):[Re(e)],rc=(e,t,n)=>{if(t._n)return t;const r=Cl((...s)=>Wr(t(...s)),n);return r._c=!1,r},Ko=(e,t,n)=>{const r=e._ctx;for(const s in e){if(ko(s))continue;const o=e[s];if(q(o))t[s]=rc(s,o,r);else if(o!=null){const i=Wr(o);t[s]=()=>i}}},Wo=(e,t)=>{const n=Wr(t);e.slots.default=()=>n},sc=(e,t)=>{if(e.vnode.shapeFlag&32){const n=t._;n?(e.slots=J(t),_n(t,"_",n)):Ko(t,e.slots={})}else e.slots={},t&&Wo(e,t);_n(e.slots,Un,1)},oc=(e,t,n)=>{const{vnode:r,slots:s}=e;let o=!0,i=ee;if(r.shapeFlag&32){const l=t._;l?n&&l===1?o=!1:(ce(s,t),!n&&l===1&&delete s._):(o=!t.$stable,Ko(t,s)),i=t}else t&&(Wo(e,t),i={default:1});if(o)for(const l in s)!ko(l)&&i[l]==null&&delete s[l]};function xn(e,t,n,r,s=!1){if(B(e)){e.forEach((p,y)=>xn(p,t&&(B(t)?t[y]:t),n,r,s));return}if(Ct(r)&&!s)return;const o=r.shapeFlag&4?kn(r.component)||r.component.proxy:r.el,i=s?null:o,{i:l,r:c}=e,a=t&&t.r,f=l.refs===ee?l.refs={}:l.refs,h=l.setupState;if(a!=null&&a!==c&&(ne(a)?(f[a]=null,Y(h,a)&&(h[a]=null)):de(a)&&(a.value=null)),q(c))Je(c,l,12,[i,f]);else{const p=ne(c),y=de(c);if(p||y){const w=()=>{if(e.f){const I=p?Y(h,c)?h[c]:f[c]:c.value;s?B(I)&&Ar(I,o):B(I)?I.includes(o)||I.push(o):p?(f[c]=[o],Y(h,c)&&(h[c]=f[c])):(c.value=[o],e.k&&(f[e.k]=c.value))}else p?(f[c]=i,Y(h,c)&&(h[c]=i)):y&&(c.value=i,e.k&&(f[e.k]=i))};i?(w.id=-1,ge(w,n)):w()}}}let ke=!1;const ic=e=>e.namespaceURI.includes("svg")&&e.tagName!=="foreignObject",lc=e=>e.namespaceURI.includes("MathML"),on=e=>{if(ic(e))return"svg";if(lc(e))return"mathml"},ln=e=>e.nodeType===8;function cc(e){const{mt:t,p:n,o:{patchProp:r,createText:s,nextSibling:o,parentNode:i,remove:l,insert:c,createComment:a}}=e,f=(g,_)=>{if(!_.hasChildNodes()){n(null,g,_),wn(),_._vnode=g;return}ke=!1,h(_.firstChild,g,null,null,null),wn(),_._vnode=g,ke&&console.error("Hydration completed but contains mismatches.")},h=(g,_,M,L,F,T=!1)=>{const $=ln(g)&&g.data==="[",E=()=>I(g,_,M,L,F,$),{type:j,ref:A,shapeFlag:G,patchFlag:ie}=_;let fe=g.nodeType;_.el=g,ie===-2&&(T=!1,_.dynamicChildren=null);let D=null;switch(j){case Tt:fe!==3?_.children===""?(c(_.el=s(""),i(g),g),D=g):D=E():(g.data!==_.children&&(ke=!0,g.data=_.children),D=o(g));break;case be:k(g)?(D=o(g),K(_.el=g.content.firstChild,g,M)):fe!==8||$?D=E():D=o(g);break;case Ht:if($&&(g=o(g),fe=g.nodeType),fe===1||fe===3){D=g;const X=!_.children.length;for(let V=0;V<_.staticCount;V++)X&&(_.children+=D.nodeType===1?D.outerHTML:D.data),V===_.staticCount-1&&(_.anchor=D),D=o(D);return $?o(D):D}else E();break;case me:$?D=w(g,_,M,L,F,T):D=E();break;default:if(G&1)(fe!==1||_.type.toLowerCase()!==g.tagName.toLowerCase())&&!k(g)?D=E():D=p(g,_,M,L,F,T);else if(G&6){_.slotScopeIds=F;const X=i(g);if($?D=N(g):ln(g)&&g.data==="teleport start"?D=N(g,g.data,"teleport end"):D=o(g),t(_,X,null,M,L,on(X),T),Ct(_)){let V;$?(V=oe(me),V.anchor=D?D.previousSibling:X.lastChild):V=g.nodeType===3?ti(""):oe("div"),V.el=g,_.component.subTree=V}}else G&64?fe!==8?D=E():D=_.type.hydrate(g,_,M,L,F,T,e,y):G&128&&(D=_.type.hydrate(g,_,M,L,on(i(g)),F,T,e,h))}return A!=null&&xn(A,null,L,_),D},p=(g,_,M,L,F,T)=>{T=T||!!_.dynamicChildren;const{type:$,props:E,patchFlag:j,shapeFlag:A,dirs:G,transition:ie}=_,fe=$==="input"||$==="option";if(fe||j!==-1){G&&Me(_,null,M,"created");let D=!1;if(k(g)){D=Go(L,ie)&&M&&M.vnode.props&&M.vnode.props.appear;const V=g.content.firstChild;D&&ie.beforeEnter(V),K(V,g,M),_.el=g=V}if(A&16&&!(E&&(E.innerHTML||E.textContent))){let V=y(g.firstChild,_,g,M,L,F,T);for(;V;){ke=!0;const $e=V;V=V.nextSibling,l($e)}}else A&8&&g.textContent!==_.children&&(ke=!0,g.textContent=_.children);if(E)if(fe||!T||j&48)for(const V in E)(fe&&(V.endsWith("value")||V==="indeterminate")||Wt(V)&&!bt(V)||V[0]===".")&&r(g,V,null,E[V],void 0,void 0,M);else E.onClick&&r(g,"onClick",null,E.onClick,void 0,void 0,M);let X;(X=E&&E.onVnodeBeforeMount)&&Ee(X,M,_),G&&Me(_,null,M,"beforeMount"),((X=E&&E.onVnodeMounted)||G||D)&&Io(()=>{X&&Ee(X,M,_),D&&ie.enter(g),G&&Me(_,null,M,"mounted")},L)}return g.nextSibling},y=(g,_,M,L,F,T,$)=>{$=$||!!_.dynamicChildren;const E=_.children,j=E.length;for(let A=0;A{const{slotScopeIds:$}=_;$&&(F=F?F.concat($):$);const E=i(g),j=y(o(g),_,E,M,L,F,T);return j&&ln(j)&&j.data==="]"?o(_.anchor=j):(ke=!0,c(_.anchor=a("]"),E,j),j)},I=(g,_,M,L,F,T)=>{if(ke=!0,_.el=null,T){const j=N(g);for(;;){const A=o(g);if(A&&A!==j)l(A);else break}}const $=o(g),E=i(g);return l(g),n(null,_,E,$,M,L,on(E),F),$},N=(g,_="[",M="]")=>{let L=0;for(;g;)if(g=o(g),g&&ln(g)&&(g.data===_&&L++,g.data===M)){if(L===0)return o(g);L--}return g},K=(g,_,M)=>{const L=_.parentNode;L&&L.replaceChild(g,_);let F=M;for(;F;)F.vnode.el===_&&(F.vnode.el=F.subTree.el=g),F=F.parent},k=g=>g.nodeType===1&&g.tagName.toLowerCase()==="template";return[f,h]}const ge=Io;function ac(e){return qo(e)}function uc(e){return qo(e,cc)}function qo(e,t){const n=so();n.__VUE__=!0;const{insert:r,remove:s,patchProp:o,createElement:i,createText:l,createComment:c,setText:a,setElementText:f,parentNode:h,nextSibling:p,setScopeId:y=xe,insertStaticContent:w}=e,I=(u,d,m,v=null,b=null,S=null,O=void 0,x=null,R=!!d.dynamicChildren)=>{if(u===d)return;u&&!it(u,d)&&(v=Jt(u),Oe(u,b,S,!0),u=null),d.patchFlag===-2&&(R=!1,d.dynamicChildren=null);const{type:C,ref:P,shapeFlag:U}=d;switch(C){case Tt:N(u,d,m,v);break;case be:K(u,d,m,v);break;case Ht:u==null&&k(d,m,v,O);break;case me:A(u,d,m,v,b,S,O,x,R);break;default:U&1?M(u,d,m,v,b,S,O,x,R):U&6?G(u,d,m,v,b,S,O,x,R):(U&64||U&128)&&C.process(u,d,m,v,b,S,O,x,R,pt)}P!=null&&b&&xn(P,u&&u.ref,S,d||u,!d)},N=(u,d,m,v)=>{if(u==null)r(d.el=l(d.children),m,v);else{const b=d.el=u.el;d.children!==u.children&&a(b,d.children)}},K=(u,d,m,v)=>{u==null?r(d.el=c(d.children||""),m,v):d.el=u.el},k=(u,d,m,v)=>{[u.el,u.anchor]=w(u.children,d,m,v,u.el,u.anchor)},g=({el:u,anchor:d},m,v)=>{let b;for(;u&&u!==d;)b=p(u),r(u,m,v),u=b;r(d,m,v)},_=({el:u,anchor:d})=>{let m;for(;u&&u!==d;)m=p(u),s(u),u=m;s(d)},M=(u,d,m,v,b,S,O,x,R)=>{d.type==="svg"?O="svg":d.type==="math"&&(O="mathml"),u==null?L(d,m,v,b,S,O,x,R):$(u,d,b,S,O,x,R)},L=(u,d,m,v,b,S,O,x)=>{let R,C;const{props:P,shapeFlag:U,transition:H,dirs:W}=u;if(R=u.el=i(u.type,S,P&&P.is,P),U&8?f(R,u.children):U&16&&T(u.children,R,null,v,b,Qn(u,S),O,x),W&&Me(u,null,v,"created"),F(R,u,u.scopeId,O,v),P){for(const Q in P)Q!=="value"&&!bt(Q)&&o(R,Q,null,P[Q],S,u.children,v,b,He);"value"in P&&o(R,"value",null,P.value,S),(C=P.onVnodeBeforeMount)&&Ee(C,v,u)}W&&Me(u,null,v,"beforeMount");const z=Go(b,H);z&&H.beforeEnter(R),r(R,d,m),((C=P&&P.onVnodeMounted)||z||W)&&ge(()=>{C&&Ee(C,v,u),z&&H.enter(R),W&&Me(u,null,v,"mounted")},b)},F=(u,d,m,v,b)=>{if(m&&y(u,m),v)for(let S=0;S{for(let C=R;C{const x=d.el=u.el;let{patchFlag:R,dynamicChildren:C,dirs:P}=d;R|=u.patchFlag&16;const U=u.props||ee,H=d.props||ee;let W;if(m&&nt(m,!1),(W=H.onVnodeBeforeUpdate)&&Ee(W,m,d,u),P&&Me(d,u,m,"beforeUpdate"),m&&nt(m,!0),C?E(u.dynamicChildren,C,x,m,v,Qn(d,b),S):O||V(u,d,x,null,m,v,Qn(d,b),S,!1),R>0){if(R&16)j(x,d,U,H,m,v,b);else if(R&2&&U.class!==H.class&&o(x,"class",null,H.class,b),R&4&&o(x,"style",U.style,H.style,b),R&8){const z=d.dynamicProps;for(let Q=0;Q{W&&Ee(W,m,d,u),P&&Me(d,u,m,"updated")},v)},E=(u,d,m,v,b,S,O)=>{for(let x=0;x{if(m!==v){if(m!==ee)for(const x in m)!bt(x)&&!(x in v)&&o(u,x,m[x],null,O,d.children,b,S,He);for(const x in v){if(bt(x))continue;const R=v[x],C=m[x];R!==C&&x!=="value"&&o(u,x,C,R,O,d.children,b,S,He)}"value"in v&&o(u,"value",m.value,v.value,O)}},A=(u,d,m,v,b,S,O,x,R)=>{const C=d.el=u?u.el:l(""),P=d.anchor=u?u.anchor:l("");let{patchFlag:U,dynamicChildren:H,slotScopeIds:W}=d;W&&(x=x?x.concat(W):W),u==null?(r(C,m,v),r(P,m,v),T(d.children||[],m,P,b,S,O,x,R)):U>0&&U&64&&H&&u.dynamicChildren?(E(u.dynamicChildren,H,m,b,S,O,x),(d.key!=null||b&&d===b.subTree)&&qr(u,d,!0)):V(u,d,m,P,b,S,O,x,R)},G=(u,d,m,v,b,S,O,x,R)=>{d.slotScopeIds=x,u==null?d.shapeFlag&512?b.ctx.activate(d,m,v,O,R):ie(d,m,v,b,S,O,R):fe(u,d,R)},ie=(u,d,m,v,b,S,O)=>{const x=u.component=wc(u,v,b);if(Gt(u)&&(x.ctx.renderer=pt),Ec(x),x.asyncDep){if(b&&b.registerDep(x,D),!u.el){const R=x.subTree=oe(be);K(null,R,d,m)}}else D(x,u,d,m,b,S,O)},fe=(u,d,m)=>{const v=d.component=u.component;if(Tl(u,d,m))if(v.asyncDep&&!v.asyncResolved){X(v,d,m);return}else v.next=d,vl(v.update),v.effect.dirty=!0,v.update();else d.el=u.el,v.vnode=d},D=(u,d,m,v,b,S,O)=>{const x=()=>{if(u.isMounted){let{next:P,bu:U,u:H,parent:W,vnode:z}=u;{const gt=zo(u);if(gt){P&&(P.el=z.el,X(u,P,O)),gt.asyncDep.then(()=>{u.isUnmounted||x()});return}}let Q=P,te;nt(u,!1),P?(P.el=z.el,X(u,P,O)):P=z,U&&pn(U),(te=P.props&&P.props.onVnodeBeforeUpdate)&&Ee(te,W,P,z),nt(u,!0);const ae=zn(u),Ae=u.subTree;u.subTree=ae,I(Ae,ae,h(Ae.el),Jt(Ae),u,b,S),P.el=ae.el,Q===null&&Al(u,ae.el),H&&ge(H,b),(te=P.props&&P.props.onVnodeUpdated)&&ge(()=>Ee(te,W,P,z),b)}else{let P;const{el:U,props:H}=d,{bm:W,m:z,parent:Q}=u,te=Ct(d);if(nt(u,!1),W&&pn(W),!te&&(P=H&&H.onVnodeBeforeMount)&&Ee(P,Q,d),nt(u,!0),U&&qn){const ae=()=>{u.subTree=zn(u),qn(U,u.subTree,u,b,null)};te?d.type.__asyncLoader().then(()=>!u.isUnmounted&&ae()):ae()}else{const ae=u.subTree=zn(u);I(null,ae,m,v,u,b,S),d.el=ae.el}if(z&&ge(z,b),!te&&(P=H&&H.onVnodeMounted)){const ae=d;ge(()=>Ee(P,Q,ae),b)}(d.shapeFlag&256||Q&&Ct(Q.vnode)&&Q.vnode.shapeFlag&256)&&u.a&&ge(u.a,b),u.isMounted=!0,d=m=v=null}},R=u.effect=new Ir(x,xe,()=>Fn(C),u.scope),C=u.update=()=>{R.dirty&&R.run()};C.id=u.uid,nt(u,!0),C()},X=(u,d,m)=>{d.component=u;const v=u.vnode.props;u.vnode=d,u.next=null,nc(u,d.props,v,m),oc(u,d.children,m),dt(),fs(u),ht()},V=(u,d,m,v,b,S,O,x,R=!1)=>{const C=u&&u.children,P=u?u.shapeFlag:0,U=d.children,{patchFlag:H,shapeFlag:W}=d;if(H>0){if(H&128){Yt(C,U,m,v,b,S,O,x,R);return}else if(H&256){$e(C,U,m,v,b,S,O,x,R);return}}W&8?(P&16&&He(C,b,S),U!==C&&f(m,U)):P&16?W&16?Yt(C,U,m,v,b,S,O,x,R):He(C,b,S,!0):(P&8&&f(m,""),W&16&&T(U,m,v,b,S,O,x,R))},$e=(u,d,m,v,b,S,O,x,R)=>{u=u||_t,d=d||_t;const C=u.length,P=d.length,U=Math.min(C,P);let H;for(H=0;HP?He(u,b,S,!0,!1,U):T(d,m,v,b,S,O,x,R,U)},Yt=(u,d,m,v,b,S,O,x,R)=>{let C=0;const P=d.length;let U=u.length-1,H=P-1;for(;C<=U&&C<=H;){const W=u[C],z=d[C]=R?ze(d[C]):Re(d[C]);if(it(W,z))I(W,z,m,null,b,S,O,x,R);else break;C++}for(;C<=U&&C<=H;){const W=u[U],z=d[H]=R?ze(d[H]):Re(d[H]);if(it(W,z))I(W,z,m,null,b,S,O,x,R);else break;U--,H--}if(C>U){if(C<=H){const W=H+1,z=WH)for(;C<=U;)Oe(u[C],b,S,!0),C++;else{const W=C,z=C,Q=new Map;for(C=z;C<=H;C++){const _e=d[C]=R?ze(d[C]):Re(d[C]);_e.key!=null&&Q.set(_e.key,C)}let te,ae=0;const Ae=H-z+1;let gt=!1,es=0;const Lt=new Array(Ae);for(C=0;C=Ae){Oe(_e,b,S,!0);continue}let Ie;if(_e.key!=null)Ie=Q.get(_e.key);else for(te=z;te<=H;te++)if(Lt[te-z]===0&&it(_e,d[te])){Ie=te;break}Ie===void 0?Oe(_e,b,S,!0):(Lt[Ie-z]=C+1,Ie>=es?es=Ie:gt=!0,I(_e,d[Ie],m,null,b,S,O,x,R),ae++)}const ts=gt?fc(Lt):_t;for(te=ts.length-1,C=Ae-1;C>=0;C--){const _e=z+C,Ie=d[_e],ns=_e+1{const{el:S,type:O,transition:x,children:R,shapeFlag:C}=u;if(C&6){tt(u.component.subTree,d,m,v);return}if(C&128){u.suspense.move(d,m,v);return}if(C&64){O.move(u,d,m,pt);return}if(O===me){r(S,d,m);for(let U=0;Ux.enter(S),b);else{const{leave:U,delayLeave:H,afterLeave:W}=x,z=()=>r(S,d,m),Q=()=>{U(S,()=>{z(),W&&W()})};H?H(S,z,Q):Q()}else r(S,d,m)},Oe=(u,d,m,v=!1,b=!1)=>{const{type:S,props:O,ref:x,children:R,dynamicChildren:C,shapeFlag:P,patchFlag:U,dirs:H}=u;if(x!=null&&xn(x,null,m,u,!0),P&256){d.ctx.deactivate(u);return}const W=P&1&&H,z=!Ct(u);let Q;if(z&&(Q=O&&O.onVnodeBeforeUnmount)&&Ee(Q,d,u),P&6)Si(u.component,m,v);else{if(P&128){u.suspense.unmount(m,v);return}W&&Me(u,null,d,"beforeUnmount"),P&64?u.type.remove(u,d,m,b,pt,v):C&&(S!==me||U>0&&U&64)?He(C,d,m,!1,!0):(S===me&&U&384||!b&&P&16)&&He(R,d,m),v&&Qr(u)}(z&&(Q=O&&O.onVnodeUnmounted)||W)&&ge(()=>{Q&&Ee(Q,d,u),W&&Me(u,null,d,"unmounted")},m)},Qr=u=>{const{type:d,el:m,anchor:v,transition:b}=u;if(d===me){xi(m,v);return}if(d===Ht){_(u);return}const S=()=>{s(m),b&&!b.persisted&&b.afterLeave&&b.afterLeave()};if(u.shapeFlag&1&&b&&!b.persisted){const{leave:O,delayLeave:x}=b,R=()=>O(m,S);x?x(u.el,S,R):R()}else S()},xi=(u,d)=>{let m;for(;u!==d;)m=p(u),s(u),u=m;s(d)},Si=(u,d,m)=>{const{bum:v,scope:b,update:S,subTree:O,um:x}=u;v&&pn(v),b.stop(),S&&(S.active=!1,Oe(O,u,d,m)),x&&ge(x,d),ge(()=>{u.isUnmounted=!0},d),d&&d.pendingBranch&&!d.isUnmounted&&u.asyncDep&&!u.asyncResolved&&u.suspenseId===d.pendingId&&(d.deps--,d.deps===0&&d.resolve())},He=(u,d,m,v=!1,b=!1,S=0)=>{for(let O=S;Ou.shapeFlag&6?Jt(u.component.subTree):u.shapeFlag&128?u.suspense.next():p(u.anchor||u.el);let Kn=!1;const Zr=(u,d,m)=>{u==null?d._vnode&&Oe(d._vnode,null,null,!0):I(d._vnode||null,u,d,null,null,null,m),Kn||(Kn=!0,fs(),wn(),Kn=!1),d._vnode=u},pt={p:I,um:Oe,m:tt,r:Qr,mt:ie,mc:T,pc:V,pbc:E,n:Jt,o:e};let Wn,qn;return t&&([Wn,qn]=t(pt)),{render:Zr,hydrate:Wn,createApp:Zl(Zr,Wn)}}function Qn({type:e,props:t},n){return n==="svg"&&e==="foreignObject"||n==="mathml"&&e==="annotation-xml"&&t&&t.encoding&&t.encoding.includes("html")?void 0:n}function nt({effect:e,update:t},n){e.allowRecurse=t.allowRecurse=n}function Go(e,t){return(!e||e&&!e.pendingBranch)&&t&&!t.persisted}function qr(e,t,n=!1){const r=e.children,s=t.children;if(B(r)&&B(s))for(let o=0;o>1,e[n[l]]0&&(t[r]=n[o-1]),n[o]=r)}}for(o=n.length,i=n[o-1];o-- >0;)n[o]=i,i=t[i];return n}function zo(e){const t=e.subTree.component;if(t)return t.asyncDep&&!t.asyncResolved?t:zo(t)}const dc=e=>e.__isTeleport,$t=e=>e&&(e.disabled||e.disabled===""),Cs=e=>typeof SVGElement<"u"&&e instanceof SVGElement,xs=e=>typeof MathMLElement=="function"&&e instanceof MathMLElement,wr=(e,t)=>{const n=e&&e.to;return ne(n)?t?t(n):null:n},hc={name:"Teleport",__isTeleport:!0,process(e,t,n,r,s,o,i,l,c,a){const{mc:f,pc:h,pbc:p,o:{insert:y,querySelector:w,createText:I,createComment:N}}=a,K=$t(t.props);let{shapeFlag:k,children:g,dynamicChildren:_}=t;if(e==null){const M=t.el=I(""),L=t.anchor=I("");y(M,n,r),y(L,n,r);const F=t.target=wr(t.props,w),T=t.targetAnchor=I("");F&&(y(T,F),i==="svg"||Cs(F)?i="svg":(i==="mathml"||xs(F))&&(i="mathml"));const $=(E,j)=>{k&16&&f(g,E,j,s,o,i,l,c)};K?$(n,L):F&&$(F,T)}else{t.el=e.el;const M=t.anchor=e.anchor,L=t.target=e.target,F=t.targetAnchor=e.targetAnchor,T=$t(e.props),$=T?n:L,E=T?M:F;if(i==="svg"||Cs(L)?i="svg":(i==="mathml"||xs(L))&&(i="mathml"),_?(p(e.dynamicChildren,_,$,s,o,i,l),qr(e,t,!0)):c||h(e,t,$,E,s,o,i,l,!1),K)T?t.props&&e.props&&t.props.to!==e.props.to&&(t.props.to=e.props.to):cn(t,n,M,a,1);else if((t.props&&t.props.to)!==(e.props&&e.props.to)){const j=t.target=wr(t.props,w);j&&cn(t,j,null,a,0)}else T&&cn(t,L,F,a,1)}Xo(t)},remove(e,t,n,r,{um:s,o:{remove:o}},i){const{shapeFlag:l,children:c,anchor:a,targetAnchor:f,target:h,props:p}=e;if(h&&o(f),i&&o(a),l&16){const y=i||!$t(p);for(let w=0;w0?Le||_t:null,gc(),kt>0&&Le&&Le.push(e),e}function fu(e,t,n,r,s,o){return Jo(ei(e,t,n,r,s,o,!0))}function Qo(e,t,n,r,s){return Jo(oe(e,t,n,r,s,!0))}function Sn(e){return e?e.__v_isVNode===!0:!1}function it(e,t){return e.type===t.type&&e.key===t.key}const Un="__vInternal",Zo=({key:e})=>e??null,gn=({ref:e,ref_key:t,ref_for:n})=>(typeof e=="number"&&(e=""+e),e!=null?ne(e)||de(e)||q(e)?{i:le,r:e,k:t,f:!!n}:e:null);function ei(e,t=null,n=null,r=0,s=null,o=e===me?0:1,i=!1,l=!1){const c={__v_isVNode:!0,__v_skip:!0,type:e,props:t,key:t&&Zo(t),ref:t&&gn(t),scopeId:Hn,slotScopeIds:null,children:n,component:null,suspense:null,ssContent:null,ssFallback:null,dirs:null,transition:null,el:null,anchor:null,target:null,targetAnchor:null,staticCount:0,shapeFlag:o,patchFlag:r,dynamicProps:s,dynamicChildren:null,appContext:null,ctx:le};return l?(Gr(c,n),o&128&&e.normalize(c)):n&&(c.shapeFlag|=ne(n)?8:16),kt>0&&!i&&Le&&(c.patchFlag>0||o&6)&&c.patchFlag!==32&&Le.push(c),c}const oe=mc;function mc(e,t=null,n=null,r=0,s=null,o=!1){if((!e||e===Lo)&&(e=be),Sn(e)){const l=et(e,t,!0);return n&&Gr(l,n),kt>0&&!o&&Le&&(l.shapeFlag&6?Le[Le.indexOf(e)]=l:Le.push(l)),l.patchFlag|=-2,l}if(Tc(e)&&(e=e.__vccOpts),t){t=yc(t);let{class:l,style:c}=t;l&&!ne(l)&&(t.class=Or(l)),Z(c)&&(bo(c)&&!B(c)&&(c=ce({},c)),t.style=Lr(c))}const i=ne(e)?1:Rl(e)?128:dc(e)?64:Z(e)?4:q(e)?2:0;return ei(e,t,n,r,s,i,o,!0)}function yc(e){return e?bo(e)||Un in e?ce({},e):e:null}function et(e,t,n=!1){const{props:r,ref:s,patchFlag:o,children:i}=e,l=t?_c(r||{},t):r;return{__v_isVNode:!0,__v_skip:!0,type:e.type,props:l,key:l&&Zo(l),ref:t&&t.ref?n&&s?B(s)?s.concat(gn(t)):[s,gn(t)]:gn(t):s,scopeId:e.scopeId,slotScopeIds:e.slotScopeIds,children:i,target:e.target,targetAnchor:e.targetAnchor,staticCount:e.staticCount,shapeFlag:e.shapeFlag,patchFlag:t&&e.type!==me?o===-1?16:o|16:o,dynamicProps:e.dynamicProps,dynamicChildren:e.dynamicChildren,appContext:e.appContext,dirs:e.dirs,transition:e.transition,component:e.component,suspense:e.suspense,ssContent:e.ssContent&&et(e.ssContent),ssFallback:e.ssFallback&&et(e.ssFallback),el:e.el,anchor:e.anchor,ctx:e.ctx,ce:e.ce}}function ti(e=" ",t=0){return oe(Tt,null,e,t)}function du(e,t){const n=oe(Ht,null,e);return n.staticCount=t,n}function hu(e="",t=!1){return t?(Yo(),Qo(be,null,e)):oe(be,null,e)}function Re(e){return e==null||typeof e=="boolean"?oe(be):B(e)?oe(me,null,e.slice()):typeof e=="object"?ze(e):oe(Tt,null,String(e))}function ze(e){return e.el===null&&e.patchFlag!==-1||e.memo?e:et(e)}function Gr(e,t){let n=0;const{shapeFlag:r}=e;if(t==null)t=null;else if(B(t))n=16;else if(typeof t=="object")if(r&65){const s=t.default;s&&(s._c&&(s._d=!1),Gr(e,s()),s._c&&(s._d=!0));return}else{n=32;const s=t._;!s&&!(Un in t)?t._ctx=le:s===3&&le&&(le.slots._===1?t._=1:(t._=2,e.patchFlag|=1024))}else q(t)?(t={default:t,_ctx:le},n=32):(t=String(t),r&64?(n=16,t=[ti(t)]):n=8);e.children=t,e.shapeFlag|=n}function _c(...e){const t={};for(let n=0;nue||le;let Tn,Er;{const e=so(),t=(n,r)=>{let s;return(s=e[n])||(s=e[n]=[]),s.push(r),o=>{s.length>1?s.forEach(i=>i(o)):s[0](o)}};Tn=t("__VUE_INSTANCE_SETTERS__",n=>ue=n),Er=t("__VUE_SSR_SETTERS__",n=>Xt=n)}const zt=e=>{const t=ue;return Tn(e),e.scope.on(),()=>{e.scope.off(),Tn(t)}},Ts=()=>{ue&&ue.scope.off(),Tn(null)};function ni(e){return e.vnode.shapeFlag&4}let Xt=!1;function Ec(e,t=!1){t&&Er(t);const{props:n,children:r}=e.vnode,s=ni(e);tc(e,n,s,t),sc(e,r);const o=s?Cc(e,t):void 0;return t&&Er(!1),o}function Cc(e,t){const n=e.type;e.accessCache=Object.create(null),e.proxy=Mt(new Proxy(e.ctx,Wl));const{setup:r}=n;if(r){const s=e.setupContext=r.length>1?si(e):null,o=zt(e);dt();const i=Je(r,e,0,[e.props,s]);if(ht(),o(),to(i)){if(i.then(Ts,Ts),t)return i.then(l=>{As(e,l,t)}).catch(l=>{qt(l,e,0)});e.asyncDep=i}else As(e,i,t)}else ri(e,t)}function As(e,t,n){q(t)?e.type.__ssrInlineRender?e.ssrRender=t:e.render=t:Z(t)&&(e.setupState=xo(t)),ri(e,n)}let Rs;function ri(e,t,n){const r=e.type;if(!e.render){if(!t&&Rs&&!r.render){const s=r.template||Kr(e).template;if(s){const{isCustomElement:o,compilerOptions:i}=e.appContext.config,{delimiters:l,compilerOptions:c}=r,a=ce(ce({isCustomElement:o,delimiters:l},i),c);r.render=Rs(s,a)}}e.render=r.render||xe}{const s=zt(e);dt();try{Gl(e)}finally{ht(),s()}}}function xc(e){return e.attrsProxy||(e.attrsProxy=new Proxy(e.attrs,{get(t,n){return ye(e,"get","$attrs"),t[n]}}))}function si(e){const t=n=>{e.exposed=n||{}};return{get attrs(){return xc(e)},slots:e.slots,emit:e.emit,expose:t}}function kn(e){if(e.exposed)return e.exposeProxy||(e.exposeProxy=new Proxy(xo(Mt(e.exposed)),{get(t,n){if(n in t)return t[n];if(n in Nt)return Nt[n](e)},has(t,n){return n in t||n in Nt}}))}function Sc(e,t=!0){return q(e)?e.displayName||e.name:e.name||t&&e.__name}function Tc(e){return q(e)&&"__vccOpts"in e}const re=(e,t)=>cl(e,t,Xt);function Cr(e,t,n){const r=arguments.length;return r===2?Z(t)&&!B(t)?Sn(t)?oe(e,null,[t]):oe(e,t):oe(e,null,t):(r>3?n=Array.prototype.slice.call(arguments,2):r===3&&Sn(n)&&(n=[n]),oe(e,t,n))}const Ac="3.4.21";/** +* @vue/runtime-dom v3.4.21 +* (c) 2018-present Yuxi (Evan) You and Vue contributors +* @license MIT +**/const Rc="http://www.w3.org/2000/svg",Lc="http://www.w3.org/1998/Math/MathML",Xe=typeof document<"u"?document:null,Ls=Xe&&Xe.createElement("template"),Oc={insert:(e,t,n)=>{t.insertBefore(e,n||null)},remove:e=>{const t=e.parentNode;t&&t.removeChild(e)},createElement:(e,t,n,r)=>{const s=t==="svg"?Xe.createElementNS(Rc,e):t==="mathml"?Xe.createElementNS(Lc,e):Xe.createElement(e,n?{is:n}:void 0);return e==="select"&&r&&r.multiple!=null&&s.setAttribute("multiple",r.multiple),s},createText:e=>Xe.createTextNode(e),createComment:e=>Xe.createComment(e),setText:(e,t)=>{e.nodeValue=t},setElementText:(e,t)=>{e.textContent=t},parentNode:e=>e.parentNode,nextSibling:e=>e.nextSibling,querySelector:e=>Xe.querySelector(e),setScopeId(e,t){e.setAttribute(t,"")},insertStaticContent(e,t,n,r,s,o){const i=n?n.previousSibling:t.lastChild;if(s&&(s===o||s.nextSibling))for(;t.insertBefore(s.cloneNode(!0),n),!(s===o||!(s=s.nextSibling)););else{Ls.innerHTML=r==="svg"?`${e}`:r==="mathml"?`${e}`:e;const l=Ls.content;if(r==="svg"||r==="mathml"){const c=l.firstChild;for(;c.firstChild;)l.appendChild(c.firstChild);l.removeChild(c)}t.insertBefore(l,n)}return[i?i.nextSibling:t.firstChild,n?n.previousSibling:t.lastChild]}},Ke="transition",Ot="animation",Kt=Symbol("_vtc"),oi=(e,{slots:t})=>Cr(Nl,Ic(e),t);oi.displayName="Transition";const ii={name:String,type:String,css:{type:Boolean,default:!0},duration:[String,Number,Object],enterFromClass:String,enterActiveClass:String,enterToClass:String,appearFromClass:String,appearActiveClass:String,appearToClass:String,leaveFromClass:String,leaveActiveClass:String,leaveToClass:String};oi.props=ce({},Po,ii);const rt=(e,t=[])=>{B(e)?e.forEach(n=>n(...t)):e&&e(...t)},Os=e=>e?B(e)?e.some(t=>t.length>1):e.length>1:!1;function Ic(e){const t={};for(const A in e)A in ii||(t[A]=e[A]);if(e.css===!1)return t;const{name:n="v",type:r,duration:s,enterFromClass:o=`${n}-enter-from`,enterActiveClass:i=`${n}-enter-active`,enterToClass:l=`${n}-enter-to`,appearFromClass:c=o,appearActiveClass:a=i,appearToClass:f=l,leaveFromClass:h=`${n}-leave-from`,leaveActiveClass:p=`${n}-leave-active`,leaveToClass:y=`${n}-leave-to`}=e,w=Mc(s),I=w&&w[0],N=w&&w[1],{onBeforeEnter:K,onEnter:k,onEnterCancelled:g,onLeave:_,onLeaveCancelled:M,onBeforeAppear:L=K,onAppear:F=k,onAppearCancelled:T=g}=t,$=(A,G,ie)=>{st(A,G?f:l),st(A,G?a:i),ie&&ie()},E=(A,G)=>{A._isLeaving=!1,st(A,h),st(A,y),st(A,p),G&&G()},j=A=>(G,ie)=>{const fe=A?F:k,D=()=>$(G,A,ie);rt(fe,[G,D]),Is(()=>{st(G,A?c:o),We(G,A?f:l),Os(fe)||Ms(G,r,I,D)})};return ce(t,{onBeforeEnter(A){rt(K,[A]),We(A,o),We(A,i)},onBeforeAppear(A){rt(L,[A]),We(A,c),We(A,a)},onEnter:j(!1),onAppear:j(!0),onLeave(A,G){A._isLeaving=!0;const ie=()=>E(A,G);We(A,h),Fc(),We(A,p),Is(()=>{A._isLeaving&&(st(A,h),We(A,y),Os(_)||Ms(A,r,N,ie))}),rt(_,[A,ie])},onEnterCancelled(A){$(A,!1),rt(g,[A])},onAppearCancelled(A){$(A,!0),rt(T,[A])},onLeaveCancelled(A){E(A),rt(M,[A])}})}function Mc(e){if(e==null)return null;if(Z(e))return[Zn(e.enter),Zn(e.leave)];{const t=Zn(e);return[t,t]}}function Zn(e){return Ii(e)}function We(e,t){t.split(/\s+/).forEach(n=>n&&e.classList.add(n)),(e[Kt]||(e[Kt]=new Set)).add(t)}function st(e,t){t.split(/\s+/).forEach(r=>r&&e.classList.remove(r));const n=e[Kt];n&&(n.delete(t),n.size||(e[Kt]=void 0))}function Is(e){requestAnimationFrame(()=>{requestAnimationFrame(e)})}let Pc=0;function Ms(e,t,n,r){const s=e._endId=++Pc,o=()=>{s===e._endId&&r()};if(n)return setTimeout(o,n);const{type:i,timeout:l,propCount:c}=Nc(e,t);if(!i)return r();const a=i+"end";let f=0;const h=()=>{e.removeEventListener(a,p),o()},p=y=>{y.target===e&&++f>=c&&h()};setTimeout(()=>{f(n[w]||"").split(", "),s=r(`${Ke}Delay`),o=r(`${Ke}Duration`),i=Ps(s,o),l=r(`${Ot}Delay`),c=r(`${Ot}Duration`),a=Ps(l,c);let f=null,h=0,p=0;t===Ke?i>0&&(f=Ke,h=i,p=o.length):t===Ot?a>0&&(f=Ot,h=a,p=c.length):(h=Math.max(i,a),f=h>0?i>a?Ke:Ot:null,p=f?f===Ke?o.length:c.length:0);const y=f===Ke&&/\b(transform|all)(,|$)/.test(r(`${Ke}Property`).toString());return{type:f,timeout:h,propCount:p,hasTransform:y}}function Ps(e,t){for(;e.lengthNs(n)+Ns(e[r])))}function Ns(e){return e==="auto"?0:Number(e.slice(0,-1).replace(",","."))*1e3}function Fc(){return document.body.offsetHeight}function $c(e,t,n){const r=e[Kt];r&&(t=(t?[t,...r]:[...r]).join(" ")),t==null?e.removeAttribute("class"):n?e.setAttribute("class",t):e.className=t}const Fs=Symbol("_vod"),Hc=Symbol("_vsh"),jc=Symbol(""),Vc=/(^|;)\s*display\s*:/;function Dc(e,t,n){const r=e.style,s=ne(n);let o=!1;if(n&&!s){if(t)if(ne(t))for(const i of t.split(";")){const l=i.slice(0,i.indexOf(":")).trim();n[l]==null&&mn(r,l,"")}else for(const i in t)n[i]==null&&mn(r,i,"");for(const i in n)i==="display"&&(o=!0),mn(r,i,n[i])}else if(s){if(t!==n){const i=r[jc];i&&(n+=";"+i),r.cssText=n,o=Vc.test(n)}}else t&&e.removeAttribute("style");Fs in e&&(e[Fs]=o?r.display:"",e[Hc]&&(r.display="none"))}const $s=/\s*!important$/;function mn(e,t,n){if(B(n))n.forEach(r=>mn(e,t,r));else if(n==null&&(n=""),t.startsWith("--"))e.setProperty(t,n);else{const r=Uc(e,t);$s.test(n)?e.setProperty(ft(r),n.replace($s,""),"important"):e[r]=n}}const Hs=["Webkit","Moz","ms"],er={};function Uc(e,t){const n=er[t];if(n)return n;let r=Fe(t);if(r!=="filter"&&r in e)return er[t]=r;r=On(r);for(let s=0;str||(Gc.then(()=>tr=0),tr=Date.now());function Xc(e,t){const n=r=>{if(!r._vts)r._vts=Date.now();else if(r._vts<=n.attached)return;Se(Yc(r,n.value),t,5,[r])};return n.value=e,n.attached=zc(),n}function Yc(e,t){if(B(t)){const n=e.stopImmediatePropagation;return e.stopImmediatePropagation=()=>{n.call(e),e._stopped=!0},t.map(r=>s=>!s._stopped&&r&&r(s))}else return t}const Us=e=>e.charCodeAt(0)===111&&e.charCodeAt(1)===110&&e.charCodeAt(2)>96&&e.charCodeAt(2)<123,Jc=(e,t,n,r,s,o,i,l,c)=>{const a=s==="svg";t==="class"?$c(e,r,a):t==="style"?Dc(e,n,r):Wt(t)?Tr(t)||Wc(e,t,n,r,i):(t[0]==="."?(t=t.slice(1),!0):t[0]==="^"?(t=t.slice(1),!1):Qc(e,t,r,a))?kc(e,t,r,o,i,l,c):(t==="true-value"?e._trueValue=r:t==="false-value"&&(e._falseValue=r),Bc(e,t,r,a))};function Qc(e,t,n,r){if(r)return!!(t==="innerHTML"||t==="textContent"||t in e&&Us(t)&&q(n));if(t==="spellcheck"||t==="draggable"||t==="translate"||t==="form"||t==="list"&&e.tagName==="INPUT"||t==="type"&&e.tagName==="TEXTAREA")return!1;if(t==="width"||t==="height"){const s=e.tagName;if(s==="IMG"||s==="VIDEO"||s==="CANVAS"||s==="SOURCE")return!1}return Us(t)&&ne(n)?!1:t in e}const Bs=e=>{const t=e.props["onUpdate:modelValue"]||!1;return B(t)?n=>pn(t,n):t};function Zc(e){e.target.composing=!0}function ks(e){const t=e.target;t.composing&&(t.composing=!1,t.dispatchEvent(new Event("input")))}const nr=Symbol("_assign"),pu={created(e,{modifiers:{lazy:t,trim:n,number:r}},s){e[nr]=Bs(s);const o=r||s.props&&s.props.type==="number";mt(e,t?"change":"input",i=>{if(i.target.composing)return;let l=e.value;n&&(l=l.trim()),o&&(l=ur(l)),e[nr](l)}),n&&mt(e,"change",()=>{e.value=e.value.trim()}),t||(mt(e,"compositionstart",Zc),mt(e,"compositionend",ks),mt(e,"change",ks))},mounted(e,{value:t}){e.value=t??""},beforeUpdate(e,{value:t,modifiers:{lazy:n,trim:r,number:s}},o){if(e[nr]=Bs(o),e.composing)return;const i=s||e.type==="number"?ur(e.value):e.value,l=t??"";i!==l&&(document.activeElement===e&&e.type!=="range"&&(n||r&&e.value.trim()===l)||(e.value=l))}},ea=["ctrl","shift","alt","meta"],ta={stop:e=>e.stopPropagation(),prevent:e=>e.preventDefault(),self:e=>e.target!==e.currentTarget,ctrl:e=>!e.ctrlKey,shift:e=>!e.shiftKey,alt:e=>!e.altKey,meta:e=>!e.metaKey,left:e=>"button"in e&&e.button!==0,middle:e=>"button"in e&&e.button!==1,right:e=>"button"in e&&e.button!==2,exact:(e,t)=>ea.some(n=>e[`${n}Key`]&&!t.includes(n))},gu=(e,t)=>{const n=e._withMods||(e._withMods={}),r=t.join(".");return n[r]||(n[r]=(s,...o)=>{for(let i=0;i{const n=e._withKeys||(e._withKeys={}),r=t.join(".");return n[r]||(n[r]=s=>{if(!("key"in s))return;const o=ft(s.key);if(t.some(i=>i===o||na[i]===o))return e(s)})},li=ce({patchProp:Jc},Oc);let Vt,Ks=!1;function ra(){return Vt||(Vt=ac(li))}function sa(){return Vt=Ks?Vt:uc(li),Ks=!0,Vt}const yu=(...e)=>{const t=ra().createApp(...e),{mount:n}=t;return t.mount=r=>{const s=ai(r);if(!s)return;const o=t._component;!q(o)&&!o.render&&!o.template&&(o.template=s.innerHTML),s.innerHTML="";const i=n(s,!1,ci(s));return s instanceof Element&&(s.removeAttribute("v-cloak"),s.setAttribute("data-v-app","")),i},t},_u=(...e)=>{const t=sa().createApp(...e),{mount:n}=t;return t.mount=r=>{const s=ai(r);if(s)return n(s,!0,ci(s))},t};function ci(e){if(e instanceof SVGElement)return"svg";if(typeof MathMLElement=="function"&&e instanceof MathMLElement)return"mathml"}function ai(e){return ne(e)?document.querySelector(e):e}const vu=(e,t)=>{const n=e.__vccOpts||e;for(const[r,s]of t)n[r]=s;return n},oa="modulepreload",ia=function(e){return"/"+e},Ws={},bu=function(t,n,r){let s=Promise.resolve();if(n&&n.length>0){const o=document.getElementsByTagName("link");s=Promise.all(n.map(i=>{if(i=ia(i),i in Ws)return;Ws[i]=!0;const l=i.endsWith(".css"),c=l?'[rel="stylesheet"]':"";if(!!r)for(let h=o.length-1;h>=0;h--){const p=o[h];if(p.href===i&&(!l||p.rel==="stylesheet"))return}else if(document.querySelector(`link[href="${i}"]${c}`))return;const f=document.createElement("link");if(f.rel=l?"stylesheet":oa,l||(f.as="script",f.crossOrigin=""),f.href=i,document.head.appendChild(f),l)return new Promise((h,p)=>{f.addEventListener("load",h),f.addEventListener("error",()=>p(new Error(`Unable to preload CSS for ${i}`)))})}))}return s.then(()=>t()).catch(o=>{const i=new Event("vite:preloadError",{cancelable:!0});if(i.payload=o,window.dispatchEvent(i),!i.defaultPrevented)throw o})},la=window.__VP_SITE_DATA__;function zr(e){return lo()?(Di(e),!0):!1}function Ne(e){return typeof e=="function"?e():Co(e)}const ui=typeof window<"u"&&typeof document<"u";typeof WorkerGlobalScope<"u"&&globalThis instanceof WorkerGlobalScope;const ca=Object.prototype.toString,aa=e=>ca.call(e)==="[object Object]",Qe=()=>{},xr=ua();function ua(){var e,t;return ui&&((e=window==null?void 0:window.navigator)==null?void 0:e.userAgent)&&(/iP(ad|hone|od)/.test(window.navigator.userAgent)||((t=window==null?void 0:window.navigator)==null?void 0:t.maxTouchPoints)>2&&/iPad|Macintosh/.test(window==null?void 0:window.navigator.userAgent))}function fa(e,t){function n(...r){return new Promise((s,o)=>{Promise.resolve(e(()=>t.apply(this,r),{fn:t,thisArg:this,args:r})).then(s).catch(o)})}return n}const fi=e=>e();function da(e,t={}){let n,r,s=Qe;const o=l=>{clearTimeout(l),s(),s=Qe};return l=>{const c=Ne(e),a=Ne(t.maxWait);return n&&o(n),c<=0||a!==void 0&&a<=0?(r&&(o(r),r=null),Promise.resolve(l())):new Promise((f,h)=>{s=t.rejectOnCancel?h:f,a&&!r&&(r=setTimeout(()=>{n&&o(n),r=null,f(l())},a)),n=setTimeout(()=>{r&&o(r),r=null,f(l())},c)})}}function ha(e=fi){const t=se(!0);function n(){t.value=!1}function r(){t.value=!0}const s=(...o)=>{t.value&&e(...o)};return{isActive:Pn(t),pause:n,resume:r,eventFilter:s}}function pa(e){return e||Bn()}function di(...e){if(e.length!==1)return gl(...e);const t=e[0];return typeof t=="function"?Pn(dl(()=>({get:t,set:Qe}))):se(t)}function hi(e,t,n={}){const{eventFilter:r=fi,...s}=n;return Ve(e,fa(r,t),s)}function ga(e,t,n={}){const{eventFilter:r,...s}=n,{eventFilter:o,pause:i,resume:l,isActive:c}=ha(r);return{stop:hi(e,t,{...s,eventFilter:o}),pause:i,resume:l,isActive:c}}function Xr(e,t=!0,n){pa()?Rt(e,n):t?e():Nn(e)}function wu(e,t,n={}){const{debounce:r=0,maxWait:s=void 0,...o}=n;return hi(e,t,{...o,eventFilter:da(r,{maxWait:s})})}function Eu(e,t,n){let r;de(n)?r={evaluating:n}:r=n||{};const{lazy:s=!1,evaluating:o=void 0,shallow:i=!0,onError:l=Qe}=r,c=se(!s),a=i?Vr(t):se(t);let f=0;return Br(async h=>{if(!c.value)return;f++;const p=f;let y=!1;o&&Promise.resolve().then(()=>{o.value=!0});try{const w=await e(I=>{h(()=>{o&&(o.value=!1),y||I()})});p===f&&(a.value=w)}catch(w){l(w)}finally{o&&p===f&&(o.value=!1),y=!0}}),s?re(()=>(c.value=!0,a.value)):a}function yt(e){var t;const n=Ne(e);return(t=n==null?void 0:n.$el)!=null?t:n}const Te=ui?window:void 0;function De(...e){let t,n,r,s;if(typeof e[0]=="string"||Array.isArray(e[0])?([n,r,s]=e,t=Te):[t,n,r,s]=e,!t)return Qe;Array.isArray(n)||(n=[n]),Array.isArray(r)||(r=[r]);const o=[],i=()=>{o.forEach(f=>f()),o.length=0},l=(f,h,p,y)=>(f.addEventListener(h,p,y),()=>f.removeEventListener(h,p,y)),c=Ve(()=>[yt(t),Ne(s)],([f,h])=>{if(i(),!f)return;const p=aa(h)?{...h}:h;o.push(...n.flatMap(y=>r.map(w=>l(f,y,w,p))))},{immediate:!0,flush:"post"}),a=()=>{c(),i()};return zr(a),a}let qs=!1;function Cu(e,t,n={}){const{window:r=Te,ignore:s=[],capture:o=!0,detectIframe:i=!1}=n;if(!r)return Qe;xr&&!qs&&(qs=!0,Array.from(r.document.body.children).forEach(p=>p.addEventListener("click",Qe)),r.document.documentElement.addEventListener("click",Qe));let l=!0;const c=p=>s.some(y=>{if(typeof y=="string")return Array.from(r.document.querySelectorAll(y)).some(w=>w===p.target||p.composedPath().includes(w));{const w=yt(y);return w&&(p.target===w||p.composedPath().includes(w))}}),f=[De(r,"click",p=>{const y=yt(e);if(!(!y||y===p.target||p.composedPath().includes(y))){if(p.detail===0&&(l=!c(p)),!l){l=!0;return}t(p)}},{passive:!0,capture:o}),De(r,"pointerdown",p=>{const y=yt(e);l=!c(p)&&!!(y&&!p.composedPath().includes(y))},{passive:!0}),i&&De(r,"blur",p=>{setTimeout(()=>{var y;const w=yt(e);((y=r.document.activeElement)==null?void 0:y.tagName)==="IFRAME"&&!(w!=null&&w.contains(r.document.activeElement))&&t(p)},0)})].filter(Boolean);return()=>f.forEach(p=>p())}function ma(e){return typeof e=="function"?e:typeof e=="string"?t=>t.key===e:Array.isArray(e)?t=>e.includes(t.key):()=>!0}function xu(...e){let t,n,r={};e.length===3?(t=e[0],n=e[1],r=e[2]):e.length===2?typeof e[1]=="object"?(t=!0,n=e[0],r=e[1]):(t=e[0],n=e[1]):(t=!0,n=e[0]);const{target:s=Te,eventName:o="keydown",passive:i=!1,dedupe:l=!1}=r,c=ma(t);return De(s,o,f=>{f.repeat&&Ne(l)||c(f)&&n(f)},i)}function ya(){const e=se(!1),t=Bn();return t&&Rt(()=>{e.value=!0},t),e}function _a(e){const t=ya();return re(()=>(t.value,!!e()))}function pi(e,t={}){const{window:n=Te}=t,r=_a(()=>n&&"matchMedia"in n&&typeof n.matchMedia=="function");let s;const o=se(!1),i=a=>{o.value=a.matches},l=()=>{s&&("removeEventListener"in s?s.removeEventListener("change",i):s.removeListener(i))},c=Br(()=>{r.value&&(l(),s=n.matchMedia(Ne(e)),"addEventListener"in s?s.addEventListener("change",i):s.addListener(i),o.value=s.matches)});return zr(()=>{c(),l(),s=void 0}),o}const an=typeof globalThis<"u"?globalThis:typeof window<"u"?window:typeof global<"u"?global:typeof self<"u"?self:{},un="__vueuse_ssr_handlers__",va=ba();function ba(){return un in an||(an[un]=an[un]||{}),an[un]}function gi(e,t){return va[e]||t}function wa(e){return e==null?"any":e instanceof Set?"set":e instanceof Map?"map":e instanceof Date?"date":typeof e=="boolean"?"boolean":typeof e=="string"?"string":typeof e=="object"?"object":Number.isNaN(e)?"any":"number"}const Ea={boolean:{read:e=>e==="true",write:e=>String(e)},object:{read:e=>JSON.parse(e),write:e=>JSON.stringify(e)},number:{read:e=>Number.parseFloat(e),write:e=>String(e)},any:{read:e=>e,write:e=>String(e)},string:{read:e=>e,write:e=>String(e)},map:{read:e=>new Map(JSON.parse(e)),write:e=>JSON.stringify(Array.from(e.entries()))},set:{read:e=>new Set(JSON.parse(e)),write:e=>JSON.stringify(Array.from(e))},date:{read:e=>new Date(e),write:e=>e.toISOString()}},Gs="vueuse-storage";function Yr(e,t,n,r={}){var s;const{flush:o="pre",deep:i=!0,listenToStorageChanges:l=!0,writeDefaults:c=!0,mergeDefaults:a=!1,shallow:f,window:h=Te,eventFilter:p,onError:y=E=>{console.error(E)},initOnMounted:w}=r,I=(f?Vr:se)(typeof t=="function"?t():t);if(!n)try{n=gi("getDefaultStorage",()=>{var E;return(E=Te)==null?void 0:E.localStorage})()}catch(E){y(E)}if(!n)return I;const N=Ne(t),K=wa(N),k=(s=r.serializer)!=null?s:Ea[K],{pause:g,resume:_}=ga(I,()=>L(I.value),{flush:o,deep:i,eventFilter:p});h&&l&&Xr(()=>{De(h,"storage",T),De(h,Gs,$),w&&T()}),w||T();function M(E,j){h&&h.dispatchEvent(new CustomEvent(Gs,{detail:{key:e,oldValue:E,newValue:j,storageArea:n}}))}function L(E){try{const j=n.getItem(e);if(E==null)M(j,null),n.removeItem(e);else{const A=k.write(E);j!==A&&(n.setItem(e,A),M(j,A))}}catch(j){y(j)}}function F(E){const j=E?E.newValue:n.getItem(e);if(j==null)return c&&N!=null&&n.setItem(e,k.write(N)),N;if(!E&&a){const A=k.read(j);return typeof a=="function"?a(A,N):K==="object"&&!Array.isArray(A)?{...N,...A}:A}else return typeof j!="string"?j:k.read(j)}function T(E){if(!(E&&E.storageArea!==n)){if(E&&E.key==null){I.value=N;return}if(!(E&&E.key!==e)){g();try{(E==null?void 0:E.newValue)!==k.write(I.value)&&(I.value=F(E))}catch(j){y(j)}finally{E?Nn(_):_()}}}}function $(E){T(E.detail)}return I}function mi(e){return pi("(prefers-color-scheme: dark)",e)}function Ca(e={}){const{selector:t="html",attribute:n="class",initialValue:r="auto",window:s=Te,storage:o,storageKey:i="vueuse-color-scheme",listenToStorageChanges:l=!0,storageRef:c,emitAuto:a,disableTransition:f=!0}=e,h={auto:"",light:"light",dark:"dark",...e.modes||{}},p=mi({window:s}),y=re(()=>p.value?"dark":"light"),w=c||(i==null?di(r):Yr(i,r,o,{window:s,listenToStorageChanges:l})),I=re(()=>w.value==="auto"?y.value:w.value),N=gi("updateHTMLAttrs",(_,M,L)=>{const F=typeof _=="string"?s==null?void 0:s.document.querySelector(_):yt(_);if(!F)return;let T;if(f&&(T=s.document.createElement("style"),T.appendChild(document.createTextNode("*,*::before,*::after{-webkit-transition:none!important;-moz-transition:none!important;-o-transition:none!important;-ms-transition:none!important;transition:none!important}")),s.document.head.appendChild(T)),M==="class"){const $=L.split(/\s/g);Object.values(h).flatMap(E=>(E||"").split(/\s/g)).filter(Boolean).forEach(E=>{$.includes(E)?F.classList.add(E):F.classList.remove(E)})}else F.setAttribute(M,L);f&&(s.getComputedStyle(T).opacity,document.head.removeChild(T))});function K(_){var M;N(t,n,(M=h[_])!=null?M:_)}function k(_){e.onChanged?e.onChanged(_,K):K(_)}Ve(I,k,{flush:"post",immediate:!0}),Xr(()=>k(I.value));const g=re({get(){return a?w.value:I.value},set(_){w.value=_}});try{return Object.assign(g,{store:w,system:y,state:I})}catch{return g}}function xa(e={}){const{valueDark:t="dark",valueLight:n="",window:r=Te}=e,s=Ca({...e,onChanged:(l,c)=>{var a;e.onChanged?(a=e.onChanged)==null||a.call(e,l==="dark",c,l):c(l)},modes:{dark:t,light:n}}),o=re(()=>s.system?s.system.value:mi({window:r}).value?"dark":"light");return re({get(){return s.value==="dark"},set(l){const c=l?"dark":"light";o.value===c?s.value="auto":s.value=c}})}function rr(e){return typeof Window<"u"&&e instanceof Window?e.document.documentElement:typeof Document<"u"&&e instanceof Document?e.documentElement:e}function Su(e,t,n={}){const{window:r=Te}=n;return Yr(e,t,r==null?void 0:r.localStorage,n)}function yi(e){const t=window.getComputedStyle(e);if(t.overflowX==="scroll"||t.overflowY==="scroll"||t.overflowX==="auto"&&e.clientWidth1?!0:(t.preventDefault&&t.preventDefault(),!1)}const fn=new WeakMap;function Tu(e,t=!1){const n=se(t);let r=null;Ve(di(e),i=>{const l=rr(Ne(i));if(l){const c=l;fn.get(c)||fn.set(c,c.style.overflow),n.value&&(c.style.overflow="hidden")}},{immediate:!0});const s=()=>{const i=rr(Ne(e));!i||n.value||(xr&&(r=De(i,"touchmove",l=>{Sa(l)},{passive:!1})),i.style.overflow="hidden",n.value=!0)},o=()=>{var i;const l=rr(Ne(e));!l||!n.value||(xr&&(r==null||r()),l.style.overflow=(i=fn.get(l))!=null?i:"",fn.delete(l),n.value=!1)};return zr(o),re({get(){return n.value},set(i){i?s():o()}})}function Au(e,t,n={}){const{window:r=Te}=n;return Yr(e,t,r==null?void 0:r.sessionStorage,n)}function Ru(e={}){const{window:t=Te,behavior:n="auto"}=e;if(!t)return{x:se(0),y:se(0)};const r=se(t.scrollX),s=se(t.scrollY),o=re({get(){return r.value},set(l){scrollTo({left:l,behavior:n})}}),i=re({get(){return s.value},set(l){scrollTo({top:l,behavior:n})}});return De(t,"scroll",()=>{r.value=t.scrollX,s.value=t.scrollY},{capture:!1,passive:!0}),{x:o,y:i}}function Lu(e={}){const{window:t=Te,initialWidth:n=Number.POSITIVE_INFINITY,initialHeight:r=Number.POSITIVE_INFINITY,listenOrientation:s=!0,includeScrollbar:o=!0}=e,i=se(n),l=se(r),c=()=>{t&&(o?(i.value=t.innerWidth,l.value=t.innerHeight):(i.value=t.document.documentElement.clientWidth,l.value=t.document.documentElement.clientHeight))};if(c(),Xr(c),De("resize",c,{passive:!0}),s){const a=pi("(orientation: portrait)");Ve(a,()=>c())}return{width:i,height:l}}var sr={BASE_URL:"/",MODE:"production",DEV:!1,PROD:!0,SSR:!1},or={};const _i=/^(?:[a-z]+:|\/\/)/i,Ta="vitepress-theme-appearance",Aa=/#.*$/,Ra=/[?#].*$/,La=/(?:(^|\/)index)?\.(?:md|html)$/,Ce=typeof document<"u",vi={relativePath:"",filePath:"",title:"404",description:"Not Found",headers:[],frontmatter:{sidebar:!1,layout:"page"},lastUpdated:0,isNotFound:!0};function Oa(e,t,n=!1){if(t===void 0)return!1;if(e=zs(`/${e}`),n)return new RegExp(t).test(e);if(zs(t)!==e)return!1;const r=t.match(Aa);return r?(Ce?location.hash:"")===r[0]:!0}function zs(e){return decodeURI(e).replace(Ra,"").replace(La,"$1")}function Ia(e){return _i.test(e)}function Ma(e,t){var r,s,o,i,l,c,a;const n=Object.keys(e.locales).find(f=>f!=="root"&&!Ia(f)&&Oa(t,`/${f}/`,!0))||"root";return Object.assign({},e,{localeIndex:n,lang:((r=e.locales[n])==null?void 0:r.lang)??e.lang,dir:((s=e.locales[n])==null?void 0:s.dir)??e.dir,title:((o=e.locales[n])==null?void 0:o.title)??e.title,titleTemplate:((i=e.locales[n])==null?void 0:i.titleTemplate)??e.titleTemplate,description:((l=e.locales[n])==null?void 0:l.description)??e.description,head:wi(e.head,((c=e.locales[n])==null?void 0:c.head)??[]),themeConfig:{...e.themeConfig,...(a=e.locales[n])==null?void 0:a.themeConfig}})}function bi(e,t){const n=t.title||e.title,r=t.titleTemplate??e.titleTemplate;if(typeof r=="string"&&r.includes(":title"))return r.replace(/:title/g,n);const s=Pa(e.title,r);return n===s.slice(3)?n:`${n}${s}`}function Pa(e,t){return t===!1?"":t===!0||t===void 0?` | ${e}`:e===t?"":` | ${t}`}function Na(e,t){const[n,r]=t;if(n!=="meta")return!1;const s=Object.entries(r)[0];return s==null?!1:e.some(([o,i])=>o===n&&i[s[0]]===s[1])}function wi(e,t){return[...e.filter(n=>!Na(t,n)),...t]}const Fa=/[\u0000-\u001F"#$&*+,:;<=>?[\]^`{|}\u007F]/g,$a=/^[a-z]:/i;function Xs(e){const t=$a.exec(e),n=t?t[0]:"";return n+e.slice(n.length).replace(Fa,"_").replace(/(^|\/)_+(?=[^/]*$)/,"$1")}const ir=new Set;function Ha(e){if(ir.size===0){const n=typeof process=="object"&&(or==null?void 0:or.VITE_EXTRA_EXTENSIONS)||(sr==null?void 0:sr.VITE_EXTRA_EXTENSIONS)||"";("3g2,3gp,aac,ai,apng,au,avif,bin,bmp,cer,class,conf,crl,css,csv,dll,doc,eps,epub,exe,gif,gz,ics,ief,jar,jpe,jpeg,jpg,js,json,jsonld,m4a,man,mid,midi,mjs,mov,mp2,mp3,mp4,mpe,mpeg,mpg,mpp,oga,ogg,ogv,ogx,opus,otf,p10,p7c,p7m,p7s,pdf,png,ps,qt,roff,rtf,rtx,ser,svg,t,tif,tiff,tr,ts,tsv,ttf,txt,vtt,wav,weba,webm,webp,woff,woff2,xhtml,xml,yaml,yml,zip"+(n&&typeof n=="string"?","+n:"")).split(",").forEach(r=>ir.add(r))}const t=e.split(".").pop();return t==null||!ir.has(t.toLowerCase())}function Ou(e){return e.replace(/[|\\{}()[\]^$+*?.]/g,"\\$&").replace(/-/g,"\\x2d")}const ja=Symbol(),ut=Vr(la);function Iu(e){const t=re(()=>Ma(ut.value,e.data.relativePath)),n=t.value.appearance,r=n==="force-dark"?se(!0):n?xa({storageKey:Ta,initialValue:()=>typeof n=="string"?n:"auto",...typeof n=="object"?n:{}}):se(!1);return{site:t,theme:re(()=>t.value.themeConfig),page:re(()=>e.data),frontmatter:re(()=>e.data.frontmatter),params:re(()=>e.data.params),lang:re(()=>t.value.lang),dir:re(()=>e.data.frontmatter.dir||t.value.dir),localeIndex:re(()=>t.value.localeIndex||"root"),title:re(()=>bi(t.value,e.data)),description:re(()=>e.data.description||t.value.description),isDark:r}}function Va(){const e=xt(ja);if(!e)throw new Error("vitepress data not properly injected in app");return e}function Da(e,t){return`${e}${t}`.replace(/\/+/g,"/")}function Ys(e){return _i.test(e)||!e.startsWith("/")?e:Da(ut.value.base,e)}function Ua(e){let t=e.replace(/\.html$/,"");if(t=decodeURIComponent(t),t=t.replace(/\/$/,"/index"),Ce){const n="/";t=Xs(t.slice(n.length).replace(/\//g,"_")||"index")+".md";let r=__VP_HASH_MAP__[t.toLowerCase()];if(r||(t=t.endsWith("_index.md")?t.slice(0,-9)+".md":t.slice(0,-3)+"_index.md",r=__VP_HASH_MAP__[t.toLowerCase()]),!r)return null;t=`${n}assets/${t}.${r}.js`}else t=`./${Xs(t.slice(1).replace(/\//g,"_"))}.md.js`;return t}let yn=[];function Mu(e){yn.push(e),Dn(()=>{yn=yn.filter(t=>t!==e)})}function Ba(){let e=ut.value.scrollOffset,t=0,n=24;if(typeof e=="object"&&"padding"in e&&(n=e.padding,e=e.selector),typeof e=="number")t=e;else if(typeof e=="string")t=Js(e,n);else if(Array.isArray(e))for(const r of e){const s=Js(r,n);if(s){t=s;break}}return t}function Js(e,t){const n=document.querySelector(e);if(!n)return 0;const r=n.getBoundingClientRect().bottom;return r<0?0:r+t}const ka=Symbol(),Jr="http://a.com",Ka=()=>({path:"/",component:null,data:vi});function Pu(e,t){const n=Mn(Ka()),r={route:n,go:s};async function s(l=Ce?location.href:"/"){var c,a;l=An(l),await((c=r.onBeforeRouteChange)==null?void 0:c.call(r,l))!==!1&&(Zs(l),await i(l),await((a=r.onAfterRouteChanged)==null?void 0:a.call(r,l)))}let o=null;async function i(l,c=0,a=!1){var p;if(await((p=r.onBeforePageLoad)==null?void 0:p.call(r,l))===!1)return;const f=new URL(l,Jr),h=o=f.pathname;try{let y=await e(h);if(!y)throw new Error(`Page not found: ${h}`);if(o===h){o=null;const{default:w,__pageData:I}=y;if(!w)throw new Error(`Invalid route component: ${w}`);n.path=Ce?h:Ys(h),n.component=Mt(w),n.data=Mt(I),Ce&&Nn(()=>{let N=ut.value.base+I.relativePath.replace(/(?:(^|\/)index)?\.md$/,"$1");if(!ut.value.cleanUrls&&!N.endsWith("/")&&(N+=".html"),N!==f.pathname&&(f.pathname=N,l=N+f.search+f.hash,history.replaceState(null,"",l)),f.hash&&!c){let K=null;try{K=document.getElementById(decodeURIComponent(f.hash).slice(1))}catch(k){console.warn(k)}if(K){Qs(K,f.hash);return}}window.scrollTo(0,c)})}}catch(y){if(!/fetch|Page not found/.test(y.message)&&!/^\/404(\.html|\/)?$/.test(l)&&console.error(y),!a)try{const w=await fetch(ut.value.base+"hashmap.json");window.__VP_HASH_MAP__=await w.json(),await i(l,c,!0);return}catch{}o===h&&(o=null,n.path=Ce?h:Ys(h),n.component=t?Mt(t):null,n.data=vi)}}return Ce&&(window.addEventListener("click",l=>{if(l.target.closest("button"))return;const a=l.target.closest("a");if(a&&!a.closest(".vp-raw")&&(a instanceof SVGElement||!a.download)){const{target:f}=a,{href:h,origin:p,pathname:y,hash:w,search:I}=new URL(a.href instanceof SVGAnimatedString?a.href.animVal:a.href,a.baseURI),N=new URL(window.location.href);!l.ctrlKey&&!l.shiftKey&&!l.altKey&&!l.metaKey&&!f&&p===N.origin&&Ha(y)&&(l.preventDefault(),y===N.pathname&&I===N.search?(w!==N.hash&&(history.pushState(null,"",w),window.dispatchEvent(new Event("hashchange"))),w?Qs(a,w,a.classList.contains("header-anchor")):(Zs(h,!1),window.scrollTo(0,0))):s(h))}},{capture:!0}),window.addEventListener("popstate",async l=>{var c;await i(An(location.href),l.state&&l.state.scrollPosition||0),(c=r.onAfterRouteChanged)==null||c.call(r,location.href)}),window.addEventListener("hashchange",l=>{l.preventDefault()})),r}function Wa(){const e=xt(ka);if(!e)throw new Error("useRouter() is called without provider.");return e}function Ei(){return Wa().route}function Qs(e,t,n=!1){let r=null;try{r=e.classList.contains("header-anchor")?e:document.getElementById(decodeURIComponent(t).slice(1))}catch(s){console.warn(s)}if(r){let s=function(){!n||Math.abs(i-window.scrollY)>window.innerHeight?window.scrollTo(0,i):window.scrollTo({left:0,top:i,behavior:"smooth"})};const o=parseInt(window.getComputedStyle(r).paddingTop,10),i=window.scrollY+r.getBoundingClientRect().top-Ba()+o;requestAnimationFrame(s)}}function Zs(e,t=!0){if(Ce&&An(e)!==An(location.href)){const n=location.hash;history.replaceState({scrollPosition:window.scrollY},document.title),history.pushState(null,"",e),t&&new URL(e,Jr).hash!==n&&window.dispatchEvent(new Event("hashchange"))}}function An(e){const t=new URL(e,Jr);return t.pathname=t.pathname.replace(/(^|\/)index(\.html)?$/,"$1"),ut.value.cleanUrls?t.pathname=t.pathname.replace(/\.html$/,""):!t.pathname.endsWith("/")&&!t.pathname.endsWith(".html")&&(t.pathname+=".html"),t.pathname+t.search+t.hash}const lr=()=>yn.forEach(e=>e()),Nu=kr({name:"VitePressContent",props:{as:{type:[Object,String],default:"div"}},setup(e){const t=Ei(),{site:n}=Va();return()=>Cr(e.as,n.value.contentProps??{style:{position:"relative"}},[t.component?Cr(t.component,{onVnodeMounted:lr,onVnodeUpdated:lr,onVnodeUnmounted:lr}):"404 Page Not Found"])}}),Fu=kr({setup(e,{slots:t}){const n=se(!1);return Rt(()=>{n.value=!0}),()=>n.value&&t.default?t.default():null}});function $u(){Ce&&window.addEventListener("click",e=>{var n;const t=e.target;if(t.matches(".vp-code-group input")){const r=(n=t.parentElement)==null?void 0:n.parentElement;if(!r)return;const s=Array.from(r.querySelectorAll("input")).indexOf(t);if(s<0)return;const o=r.querySelector(".blocks");if(!o)return;const i=Array.from(o.children).find(a=>a.classList.contains("active"));if(!i)return;const l=o.children[s];if(!l||i===l)return;i.classList.remove("active"),l.classList.add("active");const c=r==null?void 0:r.querySelector(`label[for="${t.id}"]`);c==null||c.scrollIntoView({block:"nearest"})}})}function Hu(){if(Ce){const e=new WeakMap;window.addEventListener("click",t=>{var r;const n=t.target;if(n.matches('div[class*="language-"] > button.copy')){const s=n.parentElement,o=(r=n.nextElementSibling)==null?void 0:r.nextElementSibling;if(!s||!o)return;const i=/language-(shellscript|shell|bash|sh|zsh)/.test(s.className),l=[".vp-copy-ignore",".diff.remove"],c=o.cloneNode(!0);c.querySelectorAll(l.join(",")).forEach(f=>f.remove());let a=c.textContent||"";i&&(a=a.replace(/^ *(\$|>) /gm,"").trim()),qa(a).then(()=>{n.classList.add("copied"),clearTimeout(e.get(n));const f=setTimeout(()=>{n.classList.remove("copied"),n.blur(),e.delete(n)},2e3);e.set(n,f)})}})}}async function qa(e){try{return navigator.clipboard.writeText(e)}catch{const t=document.createElement("textarea"),n=document.activeElement;t.value=e,t.setAttribute("readonly",""),t.style.contain="strict",t.style.position="absolute",t.style.left="-9999px",t.style.fontSize="12pt";const r=document.getSelection(),s=r?r.rangeCount>0&&r.getRangeAt(0):null;document.body.appendChild(t),t.select(),t.selectionStart=0,t.selectionEnd=e.length,document.execCommand("copy"),document.body.removeChild(t),s&&(r.removeAllRanges(),r.addRange(s)),n&&n.focus()}}function ju(e,t){let n=!0,r=[];const s=o=>{if(n){n=!1,o.forEach(l=>{const c=cr(l);for(const a of document.head.children)if(a.isEqualNode(c)){r.push(a);return}});return}const i=o.map(cr);r.forEach((l,c)=>{const a=i.findIndex(f=>f==null?void 0:f.isEqualNode(l??null));a!==-1?delete i[a]:(l==null||l.remove(),delete r[c])}),i.forEach(l=>l&&document.head.appendChild(l)),r=[...r,...i].filter(Boolean)};Br(()=>{const o=e.data,i=t.value,l=o&&o.description,c=o&&o.frontmatter.head||[],a=bi(i,o);a!==document.title&&(document.title=a);const f=l||i.description;let h=document.querySelector("meta[name=description]");h?h.getAttribute("content")!==f&&h.setAttribute("content",f):cr(["meta",{name:"description",content:f}]),s(wi(i.head,za(c)))})}function cr([e,t,n]){const r=document.createElement(e);for(const s in t)r.setAttribute(s,t[s]);return n&&(r.innerHTML=n),e==="script"&&!t.async&&(r.async=!1),r}function Ga(e){return e[0]==="meta"&&e[1]&&e[1].name==="description"}function za(e){return e.filter(t=>!Ga(t))}const ar=new Set,Ci=()=>document.createElement("link"),Xa=e=>{const t=Ci();t.rel="prefetch",t.href=e,document.head.appendChild(t)},Ya=e=>{const t=new XMLHttpRequest;t.open("GET",e,t.withCredentials=!0),t.send()};let dn;const Ja=Ce&&(dn=Ci())&&dn.relList&&dn.relList.supports&&dn.relList.supports("prefetch")?Xa:Ya;function Vu(){if(!Ce||!window.IntersectionObserver)return;let e;if((e=navigator.connection)&&(e.saveData||/2g/.test(e.effectiveType)))return;const t=window.requestIdleCallback||setTimeout;let n=null;const r=()=>{n&&n.disconnect(),n=new IntersectionObserver(o=>{o.forEach(i=>{if(i.isIntersecting){const l=i.target;n.unobserve(l);const{pathname:c}=l;if(!ar.has(c)){ar.add(c);const a=Ua(c);a&&Ja(a)}}})}),t(()=>{document.querySelectorAll("#app a").forEach(o=>{const{hostname:i,pathname:l}=new URL(o.href instanceof SVGAnimatedString?o.href.animVal:o.href,o.baseURI),c=l.match(/\.\w+$/);c&&c[0]!==".html"||o.target!=="_blank"&&i===location.hostname&&(l!==location.pathname?n.observe(o):ar.add(l))})})};Rt(r);const s=Ei();Ve(()=>s.path,r),Dn(()=>{n&&n.disconnect()})}export{ec as $,Dn as A,ru as B,Dl as C,Ba as D,tu as E,me as F,iu as G,Vr as H,Mu as I,oe as J,nu as K,_i as L,Ei as M,_c as N,xt as O,Lu as P,Lr as Q,Cu as R,xu as S,oi as T,Nn as U,Ru as V,Pn as W,ou as X,bu as Y,Tu as Z,vu as _,ti as a,mu as a0,cu as a1,gu as a2,au as a3,du as a4,ju as a5,ka as a6,Iu as a7,ja as a8,Nu as a9,Fu as aa,ut as ab,_u as ac,Pu as ad,Ua as ae,Vu as af,Hu as ag,$u as ah,Cr as ai,yt as aj,zr as ak,Eu as al,Au as am,Su as an,wu as ao,Wa as ap,De as aq,Ho as ar,su as as,pu as at,de as au,uu as av,Mt as aw,yu as ax,Ou as ay,Qo as b,fu as c,kr as d,hu as e,Ha as f,Ys as g,se as h,Ia as i,Ce as j,re as k,Rt as l,ei as m,Or as n,Yo as o,Co as p,Za as q,lu as r,eu as s,Qa as t,Va as u,Oa as v,Cl as w,pi as x,Ve as y,Br as z}; diff --git a/vitepress/docs/.vitepress/dist/assets/chunks/theme.Dx0ZSJLU.js b/vitepress/docs/.vitepress/dist/assets/chunks/theme.Dx0ZSJLU.js new file mode 100644 index 0000000..54fba55 --- /dev/null +++ b/vitepress/docs/.vitepress/dist/assets/chunks/theme.Dx0ZSJLU.js @@ -0,0 +1,7 @@ +function __vite__mapDeps(indexes) { + if (!__vite__mapDeps.viteFileDeps) { + __vite__mapDeps.viteFileDeps = ["assets/chunks/VPLocalSearchBox.B0G8URRa.js","assets/chunks/framework.nQaBHiNx.js"] + } + return indexes.map((i) => __vite__mapDeps.viteFileDeps[i]) +} +import{d as _,o as a,c,r as l,n as N,a as F,t as S,b,w as d,T as ve,e as f,_ as k,u as Ge,i as je,f as ze,g as pe,h as T,j as R,k as g,l as j,m as v,p as r,q as B,s as H,v as G,x as ie,y as z,z as x,A as he,B as Pe,C as Ke,D as qe,E as K,F as M,G as E,H as Ve,I as ee,J as m,K as W,L as Le,M as te,N as Q,O as oe,P as We,Q as Se,R as Re,S as le,U as Je,V as we,W as Ye,X as Qe,Y as Xe,Z as Te,$ as Ie,a0 as Ze,a1 as xe,a2 as et,a3 as tt}from"./framework.nQaBHiNx.js";const ot=_({__name:"VPBadge",props:{text:{},type:{default:"tip"}},setup(o){return(e,t)=>(a(),c("span",{class:N(["VPBadge",e.type])},[l(e.$slots,"default",{},()=>[F(S(e.text),1)])],2))}}),st={key:0,class:"VPBackdrop"},nt=_({__name:"VPBackdrop",props:{show:{type:Boolean}},setup(o){return(e,t)=>(a(),b(ve,{name:"fade"},{default:d(()=>[e.show?(a(),c("div",st)):f("",!0)]),_:1}))}}),at=k(nt,[["__scopeId","data-v-c79a1216"]]),V=Ge;function rt(o,e){let t,n=!1;return()=>{t&&clearTimeout(t),n?t=setTimeout(o,e):(o(),(n=!0)&&setTimeout(()=>n=!1,e))}}function ce(o){return/^\//.test(o)?o:`/${o}`}function fe(o){const{pathname:e,search:t,hash:n,protocol:s}=new URL(o,"http://a.com");if(je(o)||o.startsWith("#")||!s.startsWith("http")||!ze(e))return o;const{site:i}=V(),u=e.endsWith("/")||e.endsWith(".html")?o:o.replace(/(?:(^\.+)\/)?.*$/,`$1${e.replace(/(\.md)?$/,i.value.cleanUrls?"":".html")}${t}${n}`);return pe(u)}const _e=T(R?location.hash:"");R&&window.addEventListener("hashchange",()=>{_e.value=location.hash});function J({removeCurrent:o=!0,correspondingLink:e=!1}={}){const{site:t,localeIndex:n,page:s,theme:i}=V(),u=g(()=>{var p,$;return{label:(p=t.value.locales[n.value])==null?void 0:p.label,link:(($=t.value.locales[n.value])==null?void 0:$.link)||(n.value==="root"?"/":`/${n.value}/`)}});return{localeLinks:g(()=>Object.entries(t.value.locales).flatMap(([p,$])=>o&&u.value.label===$.label?[]:{text:$.label,link:it($.link||(p==="root"?"/":`/${p}/`),i.value.i18nRouting!==!1&&e,s.value.relativePath.slice(u.value.link.length-1),!t.value.cleanUrls)+_e.value})),currentLang:u}}function it(o,e,t,n){return e?o.replace(/\/$/,"")+ce(t.replace(/(^|\/)index\.md$/,"$1").replace(/\.md$/,n?".html":"")):o}const lt=o=>(B("data-v-f87ff6e4"),o=o(),H(),o),ct={class:"NotFound"},ut={class:"code"},dt={class:"title"},vt=lt(()=>v("div",{class:"divider"},null,-1)),pt={class:"quote"},ht={class:"action"},ft=["href","aria-label"],_t=_({__name:"NotFound",setup(o){const{site:e,theme:t}=V(),{localeLinks:n}=J({removeCurrent:!1}),s=T("/");return j(()=>{var u;const i=window.location.pathname.replace(e.value.base,"").replace(/(^.*?\/).*$/,"/$1");n.value.length&&(s.value=((u=n.value.find(({link:h})=>h.startsWith(i)))==null?void 0:u.link)||n.value[0].link)}),(i,u)=>{var h,p,$,P,y;return a(),c("div",ct,[v("p",ut,S(((h=r(t).notFound)==null?void 0:h.code)??"404"),1),v("h1",dt,S(((p=r(t).notFound)==null?void 0:p.title)??"PAGE NOT FOUND"),1),vt,v("blockquote",pt,S((($=r(t).notFound)==null?void 0:$.quote)??"But if you don't change your direction, and if you keep looking, you may end up where you are heading."),1),v("div",ht,[v("a",{class:"link",href:r(pe)(s.value),"aria-label":((P=r(t).notFound)==null?void 0:P.linkLabel)??"go to home"},S(((y=r(t).notFound)==null?void 0:y.linkText)??"Take me home"),9,ft)])])}}}),mt=k(_t,[["__scopeId","data-v-f87ff6e4"]]);function Ne(o,e){if(Array.isArray(o))return X(o);if(o==null)return[];e=ce(e);const t=Object.keys(o).sort((s,i)=>i.split("/").length-s.split("/").length).find(s=>e.startsWith(ce(s))),n=t?o[t]:[];return Array.isArray(n)?X(n):X(n.items,n.base)}function kt(o){const e=[];let t=0;for(const n in o){const s=o[n];if(s.items){t=e.push(s);continue}e[t]||e.push({items:[]}),e[t].items.push(s)}return e}function $t(o){const e=[];function t(n){for(const s of n)s.text&&s.link&&e.push({text:s.text,link:s.link,docFooterText:s.docFooterText}),s.items&&t(s.items)}return t(o),e}function ue(o,e){return Array.isArray(e)?e.some(t=>ue(o,t)):G(o,e.link)?!0:e.items?ue(o,e.items):!1}function X(o,e){return[...o].map(t=>{const n={...t},s=n.base||e;return s&&n.link&&(n.link=s+n.link),n.items&&(n.items=X(n.items,s)),n})}function O(){const{frontmatter:o,page:e,theme:t}=V(),n=ie("(min-width: 960px)"),s=T(!1),i=g(()=>{const C=t.value.sidebar,I=e.value.relativePath;return C?Ne(C,I):[]}),u=T(i.value);z(i,(C,I)=>{JSON.stringify(C)!==JSON.stringify(I)&&(u.value=i.value)});const h=g(()=>o.value.sidebar!==!1&&u.value.length>0&&o.value.layout!=="home"),p=g(()=>$?o.value.aside==null?t.value.aside==="left":o.value.aside==="left":!1),$=g(()=>o.value.layout==="home"?!1:o.value.aside!=null?!!o.value.aside:t.value.aside!==!1),P=g(()=>h.value&&n.value),y=g(()=>h.value?kt(u.value):[]);function L(){s.value=!0}function w(){s.value=!1}function A(){s.value?w():L()}return{isOpen:s,sidebar:u,sidebarGroups:y,hasSidebar:h,hasAside:$,leftAside:p,isSidebarEnabled:P,open:L,close:w,toggle:A}}function bt(o,e){let t;x(()=>{t=o.value?document.activeElement:void 0}),j(()=>{window.addEventListener("keyup",n)}),he(()=>{window.removeEventListener("keyup",n)});function n(s){s.key==="Escape"&&o.value&&(e(),t==null||t.focus())}}function gt(o){const{page:e}=V(),t=T(!1),n=g(()=>o.value.collapsed!=null),s=g(()=>!!o.value.link),i=T(!1),u=()=>{i.value=G(e.value.relativePath,o.value.link)};z([e,o,_e],u),j(u);const h=g(()=>i.value?!0:o.value.items?ue(e.value.relativePath,o.value.items):!1),p=g(()=>!!(o.value.items&&o.value.items.length));x(()=>{t.value=!!(n.value&&o.value.collapsed)}),Pe(()=>{(i.value||h.value)&&(t.value=!1)});function $(){n.value&&(t.value=!t.value)}return{collapsed:t,collapsible:n,isLink:s,isActiveLink:i,hasActiveLink:h,hasChildren:p,toggle:$}}function yt(){const{hasSidebar:o}=O(),e=ie("(min-width: 960px)"),t=ie("(min-width: 1280px)");return{isAsideEnabled:g(()=>!t.value&&!e.value?!1:o.value?t.value:e.value)}}const de=[];function Me(o){return typeof o.outline=="object"&&!Array.isArray(o.outline)&&o.outline.label||o.outlineTitle||"On this page"}function me(o){const e=[...document.querySelectorAll(".VPDoc :where(h1,h2,h3,h4,h5,h6)")].filter(t=>t.id&&t.hasChildNodes()).map(t=>{const n=Number(t.tagName[1]);return{element:t,title:Pt(t),link:"#"+t.id,level:n}});return Vt(e,o)}function Pt(o){let e="";for(const t of o.childNodes)if(t.nodeType===1){if(t.classList.contains("VPBadge")||t.classList.contains("header-anchor")||t.classList.contains("ignore-header"))continue;e+=t.textContent}else t.nodeType===3&&(e+=t.textContent);return e.trim()}function Vt(o,e){if(e===!1)return[];const t=(typeof e=="object"&&!Array.isArray(e)?e.level:e)||2,[n,s]=typeof t=="number"?[t,t]:t==="deep"?[2,6]:t;o=o.filter(u=>u.level>=n&&u.level<=s),de.length=0;for(const{element:u,link:h}of o)de.push({element:u,link:h});const i=[];e:for(let u=0;u=0;p--){const $=o[p];if($.level{requestAnimationFrame(i),window.addEventListener("scroll",n)}),Ke(()=>{u(location.hash)}),he(()=>{window.removeEventListener("scroll",n)});function i(){if(!t.value)return;const h=window.scrollY,p=window.innerHeight,$=document.body.offsetHeight,P=Math.abs(h+p-$)<1,y=de.map(({element:w,link:A})=>({link:A,top:St(w)})).filter(({top:w})=>!Number.isNaN(w)).sort((w,A)=>w.top-A.top);if(!y.length){u(null);return}if(h<1){u(null);return}if(P){u(y[y.length-1].link);return}let L=null;for(const{link:w,top:A}of y){if(A>h+qe()+4)break;L=w}u(L)}function u(h){s&&s.classList.remove("active"),h==null?s=null:s=o.value.querySelector(`a[href="${decodeURIComponent(h)}"]`);const p=s;p?(p.classList.add("active"),e.value.style.top=p.offsetTop+39+"px",e.value.style.opacity="1"):(e.value.style.top="33px",e.value.style.opacity="0")}}function St(o){let e=0;for(;o!==document.body;){if(o===null)return NaN;e+=o.offsetTop,o=o.offsetParent}return e}const wt=["href","title"],Tt=_({__name:"VPDocOutlineItem",props:{headers:{},root:{type:Boolean}},setup(o){function e({target:t}){const n=t.href.split("#")[1],s=document.getElementById(decodeURIComponent(n));s==null||s.focus({preventScroll:!0})}return(t,n)=>{const s=K("VPDocOutlineItem",!0);return a(),c("ul",{class:N(["VPDocOutlineItem",t.root?"root":"nested"])},[(a(!0),c(M,null,E(t.headers,({children:i,link:u,title:h})=>(a(),c("li",null,[v("a",{class:"outline-link",href:u,onClick:e,title:h},S(h),9,wt),i!=null&&i.length?(a(),b(s,{key:0,headers:i},null,8,["headers"])):f("",!0)]))),256))],2)}}}),Ae=k(Tt,[["__scopeId","data-v-b933a997"]]),It=o=>(B("data-v-935f8a84"),o=o(),H(),o),Nt={class:"content"},Mt={class:"outline-title",role:"heading","aria-level":"2"},At={"aria-labelledby":"doc-outline-aria-label"},Ct=It(()=>v("span",{class:"visually-hidden",id:"doc-outline-aria-label"}," Table of Contents for current page ",-1)),Bt=_({__name:"VPDocAsideOutline",setup(o){const{frontmatter:e,theme:t}=V(),n=Ve([]);ee(()=>{n.value=me(e.value.outline??t.value.outline)});const s=T(),i=T();return Lt(s,i),(u,h)=>(a(),c("div",{class:N(["VPDocAsideOutline",{"has-outline":n.value.length>0}]),ref_key:"container",ref:s,role:"navigation"},[v("div",Nt,[v("div",{class:"outline-marker",ref_key:"marker",ref:i},null,512),v("div",Mt,S(r(Me)(r(t))),1),v("nav",At,[Ct,m(Ae,{headers:n.value,root:!0},null,8,["headers"])])])],2))}}),Ht=k(Bt,[["__scopeId","data-v-935f8a84"]]),Et={class:"VPDocAsideCarbonAds"},Ft=_({__name:"VPDocAsideCarbonAds",props:{carbonAds:{}},setup(o){const e=()=>null;return(t,n)=>(a(),c("div",Et,[m(r(e),{"carbon-ads":t.carbonAds},null,8,["carbon-ads"])]))}}),Dt=o=>(B("data-v-3f215769"),o=o(),H(),o),Ot={class:"VPDocAside"},Ut=Dt(()=>v("div",{class:"spacer"},null,-1)),Gt=_({__name:"VPDocAside",setup(o){const{theme:e}=V();return(t,n)=>(a(),c("div",Ot,[l(t.$slots,"aside-top",{},void 0,!0),l(t.$slots,"aside-outline-before",{},void 0,!0),m(Ht),l(t.$slots,"aside-outline-after",{},void 0,!0),Ut,l(t.$slots,"aside-ads-before",{},void 0,!0),r(e).carbonAds?(a(),b(Ft,{key:0,"carbon-ads":r(e).carbonAds},null,8,["carbon-ads"])):f("",!0),l(t.$slots,"aside-ads-after",{},void 0,!0),l(t.$slots,"aside-bottom",{},void 0,!0)]))}}),jt=k(Gt,[["__scopeId","data-v-3f215769"]]);function zt(){const{theme:o,page:e}=V();return g(()=>{const{text:t="Edit this page",pattern:n=""}=o.value.editLink||{};let s;return typeof n=="function"?s=n(e.value):s=n.replace(/:path/g,e.value.filePath),{url:s,text:t}})}function Kt(){const{page:o,theme:e,frontmatter:t}=V();return g(()=>{var p,$,P,y,L,w,A,C;const n=Ne(e.value.sidebar,o.value.relativePath),s=$t(n),i=s.findIndex(I=>G(o.value.relativePath,I.link)),u=((p=e.value.docFooter)==null?void 0:p.prev)===!1&&!t.value.prev||t.value.prev===!1,h=(($=e.value.docFooter)==null?void 0:$.next)===!1&&!t.value.next||t.value.next===!1;return{prev:u?void 0:{text:(typeof t.value.prev=="string"?t.value.prev:typeof t.value.prev=="object"?t.value.prev.text:void 0)??((P=s[i-1])==null?void 0:P.docFooterText)??((y=s[i-1])==null?void 0:y.text),link:(typeof t.value.prev=="object"?t.value.prev.link:void 0)??((L=s[i-1])==null?void 0:L.link)},next:h?void 0:{text:(typeof t.value.next=="string"?t.value.next:typeof t.value.next=="object"?t.value.next.text:void 0)??((w=s[i+1])==null?void 0:w.docFooterText)??((A=s[i+1])==null?void 0:A.text),link:(typeof t.value.next=="object"?t.value.next.link:void 0)??((C=s[i+1])==null?void 0:C.link)}}})}const D=_({__name:"VPLink",props:{tag:{},href:{},noIcon:{type:Boolean},target:{},rel:{}},setup(o){const e=o,t=g(()=>e.tag??(e.href?"a":"span")),n=g(()=>e.href&&Le.test(e.href));return(s,i)=>(a(),b(W(t.value),{class:N(["VPLink",{link:s.href,"vp-external-link-icon":n.value,"no-icon":s.noIcon}]),href:s.href?r(fe)(s.href):void 0,target:s.target??(n.value?"_blank":void 0),rel:s.rel??(n.value?"noreferrer":void 0)},{default:d(()=>[l(s.$slots,"default")]),_:3},8,["class","href","target","rel"]))}}),qt={class:"VPLastUpdated"},Wt=["datetime"],Rt=_({__name:"VPDocFooterLastUpdated",setup(o){const{theme:e,page:t,frontmatter:n,lang:s}=V(),i=g(()=>new Date(n.value.lastUpdated??t.value.lastUpdated)),u=g(()=>i.value.toISOString()),h=T("");return j(()=>{x(()=>{var p,$,P;h.value=new Intl.DateTimeFormat(($=(p=e.value.lastUpdated)==null?void 0:p.formatOptions)!=null&&$.forceLocale?s.value:void 0,((P=e.value.lastUpdated)==null?void 0:P.formatOptions)??{dateStyle:"short",timeStyle:"short"}).format(i.value)})}),(p,$)=>{var P;return a(),c("p",qt,[F(S(((P=r(e).lastUpdated)==null?void 0:P.text)||r(e).lastUpdatedText||"Last updated")+": ",1),v("time",{datetime:u.value},S(h.value),9,Wt)])}}}),Jt=k(Rt,[["__scopeId","data-v-7e05ebdb"]]),Yt=o=>(B("data-v-09de1c0f"),o=o(),H(),o),Qt={key:0,class:"VPDocFooter"},Xt={key:0,class:"edit-info"},Zt={key:0,class:"edit-link"},xt=Yt(()=>v("span",{class:"vpi-square-pen edit-link-icon"},null,-1)),eo={key:1,class:"last-updated"},to={key:1,class:"prev-next"},oo={class:"pager"},so=["innerHTML"],no=["innerHTML"],ao={class:"pager"},ro=["innerHTML"],io=["innerHTML"],lo=_({__name:"VPDocFooter",setup(o){const{theme:e,page:t,frontmatter:n}=V(),s=zt(),i=Kt(),u=g(()=>e.value.editLink&&n.value.editLink!==!1),h=g(()=>t.value.lastUpdated&&n.value.lastUpdated!==!1),p=g(()=>u.value||h.value||i.value.prev||i.value.next);return($,P)=>{var y,L,w,A;return p.value?(a(),c("footer",Qt,[l($.$slots,"doc-footer-before",{},void 0,!0),u.value||h.value?(a(),c("div",Xt,[u.value?(a(),c("div",Zt,[m(D,{class:"edit-link-button",href:r(s).url,"no-icon":!0},{default:d(()=>[xt,F(" "+S(r(s).text),1)]),_:1},8,["href"])])):f("",!0),h.value?(a(),c("div",eo,[m(Jt)])):f("",!0)])):f("",!0),(y=r(i).prev)!=null&&y.link||(L=r(i).next)!=null&&L.link?(a(),c("nav",to,[v("div",oo,[(w=r(i).prev)!=null&&w.link?(a(),b(D,{key:0,class:"pager-link prev",href:r(i).prev.link},{default:d(()=>{var C;return[v("span",{class:"desc",innerHTML:((C=r(e).docFooter)==null?void 0:C.prev)||"Previous page"},null,8,so),v("span",{class:"title",innerHTML:r(i).prev.text},null,8,no)]}),_:1},8,["href"])):f("",!0)]),v("div",ao,[(A=r(i).next)!=null&&A.link?(a(),b(D,{key:0,class:"pager-link next",href:r(i).next.link},{default:d(()=>{var C;return[v("span",{class:"desc",innerHTML:((C=r(e).docFooter)==null?void 0:C.next)||"Next page"},null,8,ro),v("span",{class:"title",innerHTML:r(i).next.text},null,8,io)]}),_:1},8,["href"])):f("",!0)])])):f("",!0)])):f("",!0)}}}),co=k(lo,[["__scopeId","data-v-09de1c0f"]]),uo=o=>(B("data-v-39a288b8"),o=o(),H(),o),vo={class:"container"},po=uo(()=>v("div",{class:"aside-curtain"},null,-1)),ho={class:"aside-container"},fo={class:"aside-content"},_o={class:"content"},mo={class:"content-container"},ko={class:"main"},$o=_({__name:"VPDoc",setup(o){const{theme:e}=V(),t=te(),{hasSidebar:n,hasAside:s,leftAside:i}=O(),u=g(()=>t.path.replace(/[./]+/g,"_").replace(/_html$/,""));return(h,p)=>{const $=K("Content");return a(),c("div",{class:N(["VPDoc",{"has-sidebar":r(n),"has-aside":r(s)}])},[l(h.$slots,"doc-top",{},void 0,!0),v("div",vo,[r(s)?(a(),c("div",{key:0,class:N(["aside",{"left-aside":r(i)}])},[po,v("div",ho,[v("div",fo,[m(jt,null,{"aside-top":d(()=>[l(h.$slots,"aside-top",{},void 0,!0)]),"aside-bottom":d(()=>[l(h.$slots,"aside-bottom",{},void 0,!0)]),"aside-outline-before":d(()=>[l(h.$slots,"aside-outline-before",{},void 0,!0)]),"aside-outline-after":d(()=>[l(h.$slots,"aside-outline-after",{},void 0,!0)]),"aside-ads-before":d(()=>[l(h.$slots,"aside-ads-before",{},void 0,!0)]),"aside-ads-after":d(()=>[l(h.$slots,"aside-ads-after",{},void 0,!0)]),_:3})])])],2)):f("",!0),v("div",_o,[v("div",mo,[l(h.$slots,"doc-before",{},void 0,!0),v("main",ko,[m($,{class:N(["vp-doc",[u.value,r(e).externalLinkIcon&&"external-link-icon-enabled"]])},null,8,["class"])]),m(co,null,{"doc-footer-before":d(()=>[l(h.$slots,"doc-footer-before",{},void 0,!0)]),_:3}),l(h.$slots,"doc-after",{},void 0,!0)])])]),l(h.$slots,"doc-bottom",{},void 0,!0)],2)}}}),bo=k($o,[["__scopeId","data-v-39a288b8"]]),go=_({__name:"VPButton",props:{tag:{},size:{default:"medium"},theme:{default:"brand"},text:{},href:{},target:{},rel:{}},setup(o){const e=o,t=g(()=>e.href&&Le.test(e.href)),n=g(()=>e.tag||e.href?"a":"button");return(s,i)=>(a(),b(W(n.value),{class:N(["VPButton",[s.size,s.theme]]),href:s.href?r(fe)(s.href):void 0,target:e.target??(t.value?"_blank":void 0),rel:e.rel??(t.value?"noreferrer":void 0)},{default:d(()=>[F(S(s.text),1)]),_:1},8,["class","href","target","rel"]))}}),yo=k(go,[["__scopeId","data-v-cad61b99"]]),Po=["src","alt"],Vo=_({inheritAttrs:!1,__name:"VPImage",props:{image:{},alt:{}},setup(o){return(e,t)=>{const n=K("VPImage",!0);return e.image?(a(),c(M,{key:0},[typeof e.image=="string"||"src"in e.image?(a(),c("img",Q({key:0,class:"VPImage"},typeof e.image=="string"?e.$attrs:{...e.image,...e.$attrs},{src:r(pe)(typeof e.image=="string"?e.image:e.image.src),alt:e.alt??(typeof e.image=="string"?"":e.image.alt||"")}),null,16,Po)):(a(),c(M,{key:1},[m(n,Q({class:"dark",image:e.image.dark,alt:e.image.alt},e.$attrs),null,16,["image","alt"]),m(n,Q({class:"light",image:e.image.light,alt:e.image.alt},e.$attrs),null,16,["image","alt"])],64))],64)):f("",!0)}}}),Z=k(Vo,[["__scopeId","data-v-8426fc1a"]]),Lo=o=>(B("data-v-303bb580"),o=o(),H(),o),So={class:"container"},wo={class:"main"},To={key:0,class:"name"},Io=["innerHTML"],No=["innerHTML"],Mo=["innerHTML"],Ao={key:0,class:"actions"},Co={key:0,class:"image"},Bo={class:"image-container"},Ho=Lo(()=>v("div",{class:"image-bg"},null,-1)),Eo=_({__name:"VPHero",props:{name:{},text:{},tagline:{},image:{},actions:{}},setup(o){const e=oe("hero-image-slot-exists");return(t,n)=>(a(),c("div",{class:N(["VPHero",{"has-image":t.image||r(e)}])},[v("div",So,[v("div",wo,[l(t.$slots,"home-hero-info-before",{},void 0,!0),l(t.$slots,"home-hero-info",{},()=>[t.name?(a(),c("h1",To,[v("span",{innerHTML:t.name,class:"clip"},null,8,Io)])):f("",!0),t.text?(a(),c("p",{key:1,innerHTML:t.text,class:"text"},null,8,No)):f("",!0),t.tagline?(a(),c("p",{key:2,innerHTML:t.tagline,class:"tagline"},null,8,Mo)):f("",!0)],!0),l(t.$slots,"home-hero-info-after",{},void 0,!0),t.actions?(a(),c("div",Ao,[(a(!0),c(M,null,E(t.actions,s=>(a(),c("div",{key:s.link,class:"action"},[m(yo,{tag:"a",size:"medium",theme:s.theme,text:s.text,href:s.link,target:s.target,rel:s.rel},null,8,["theme","text","href","target","rel"])]))),128))])):f("",!0),l(t.$slots,"home-hero-actions-after",{},void 0,!0)]),t.image||r(e)?(a(),c("div",Co,[v("div",Bo,[Ho,l(t.$slots,"home-hero-image",{},()=>[t.image?(a(),b(Z,{key:0,class:"image-src",image:t.image},null,8,["image"])):f("",!0)],!0)])])):f("",!0)])],2))}}),Fo=k(Eo,[["__scopeId","data-v-303bb580"]]),Do=_({__name:"VPHomeHero",setup(o){const{frontmatter:e}=V();return(t,n)=>r(e).hero?(a(),b(Fo,{key:0,class:"VPHomeHero",name:r(e).hero.name,text:r(e).hero.text,tagline:r(e).hero.tagline,image:r(e).hero.image,actions:r(e).hero.actions},{"home-hero-info-before":d(()=>[l(t.$slots,"home-hero-info-before")]),"home-hero-info":d(()=>[l(t.$slots,"home-hero-info")]),"home-hero-info-after":d(()=>[l(t.$slots,"home-hero-info-after")]),"home-hero-actions-after":d(()=>[l(t.$slots,"home-hero-actions-after")]),"home-hero-image":d(()=>[l(t.$slots,"home-hero-image")]),_:3},8,["name","text","tagline","image","actions"])):f("",!0)}}),Oo=o=>(B("data-v-a3976bdc"),o=o(),H(),o),Uo={class:"box"},Go={key:0,class:"icon"},jo=["innerHTML"],zo=["innerHTML"],Ko=["innerHTML"],qo={key:4,class:"link-text"},Wo={class:"link-text-value"},Ro=Oo(()=>v("span",{class:"vpi-arrow-right link-text-icon"},null,-1)),Jo=_({__name:"VPFeature",props:{icon:{},title:{},details:{},link:{},linkText:{},rel:{},target:{}},setup(o){return(e,t)=>(a(),b(D,{class:"VPFeature",href:e.link,rel:e.rel,target:e.target,"no-icon":!0,tag:e.link?"a":"div"},{default:d(()=>[v("article",Uo,[typeof e.icon=="object"&&e.icon.wrap?(a(),c("div",Go,[m(Z,{image:e.icon,alt:e.icon.alt,height:e.icon.height||48,width:e.icon.width||48},null,8,["image","alt","height","width"])])):typeof e.icon=="object"?(a(),b(Z,{key:1,image:e.icon,alt:e.icon.alt,height:e.icon.height||48,width:e.icon.width||48},null,8,["image","alt","height","width"])):e.icon?(a(),c("div",{key:2,class:"icon",innerHTML:e.icon},null,8,jo)):f("",!0),v("h2",{class:"title",innerHTML:e.title},null,8,zo),e.details?(a(),c("p",{key:3,class:"details",innerHTML:e.details},null,8,Ko)):f("",!0),e.linkText?(a(),c("div",qo,[v("p",Wo,[F(S(e.linkText)+" ",1),Ro])])):f("",!0)])]),_:1},8,["href","rel","target","tag"]))}}),Yo=k(Jo,[["__scopeId","data-v-a3976bdc"]]),Qo={key:0,class:"VPFeatures"},Xo={class:"container"},Zo={class:"items"},xo=_({__name:"VPFeatures",props:{features:{}},setup(o){const e=o,t=g(()=>{const n=e.features.length;if(n){if(n===2)return"grid-2";if(n===3)return"grid-3";if(n%3===0)return"grid-6";if(n>3)return"grid-4"}else return});return(n,s)=>n.features?(a(),c("div",Qo,[v("div",Xo,[v("div",Zo,[(a(!0),c(M,null,E(n.features,i=>(a(),c("div",{key:i.title,class:N(["item",[t.value]])},[m(Yo,{icon:i.icon,title:i.title,details:i.details,link:i.link,"link-text":i.linkText,rel:i.rel,target:i.target},null,8,["icon","title","details","link","link-text","rel","target"])],2))),128))])])])):f("",!0)}}),es=k(xo,[["__scopeId","data-v-a6181336"]]),ts=_({__name:"VPHomeFeatures",setup(o){const{frontmatter:e}=V();return(t,n)=>r(e).features?(a(),b(es,{key:0,class:"VPHomeFeatures",features:r(e).features},null,8,["features"])):f("",!0)}}),os=_({__name:"VPHomeContent",setup(o){const{width:e}=We({includeScrollbar:!1});return(t,n)=>(a(),c("div",{class:"vp-doc container",style:Se(r(e)?{"--vp-offset":`calc(50% - ${r(e)/2}px)`}:{})},[l(t.$slots,"default",{},void 0,!0)],4))}}),ss=k(os,[["__scopeId","data-v-82d4af08"]]),ns={class:"VPHome"},as=_({__name:"VPHome",setup(o){const{frontmatter:e}=V();return(t,n)=>{const s=K("Content");return a(),c("div",ns,[l(t.$slots,"home-hero-before",{},void 0,!0),m(Do,null,{"home-hero-info-before":d(()=>[l(t.$slots,"home-hero-info-before",{},void 0,!0)]),"home-hero-info":d(()=>[l(t.$slots,"home-hero-info",{},void 0,!0)]),"home-hero-info-after":d(()=>[l(t.$slots,"home-hero-info-after",{},void 0,!0)]),"home-hero-actions-after":d(()=>[l(t.$slots,"home-hero-actions-after",{},void 0,!0)]),"home-hero-image":d(()=>[l(t.$slots,"home-hero-image",{},void 0,!0)]),_:3}),l(t.$slots,"home-hero-after",{},void 0,!0),l(t.$slots,"home-features-before",{},void 0,!0),m(ts),l(t.$slots,"home-features-after",{},void 0,!0),r(e).markdownStyles!==!1?(a(),b(ss,{key:0},{default:d(()=>[m(s)]),_:1})):(a(),b(s,{key:1}))])}}}),rs=k(as,[["__scopeId","data-v-686f80a6"]]),is={},ls={class:"VPPage"};function cs(o,e){const t=K("Content");return a(),c("div",ls,[l(o.$slots,"page-top"),m(t),l(o.$slots,"page-bottom")])}const us=k(is,[["render",cs]]),ds=_({__name:"VPContent",setup(o){const{page:e,frontmatter:t}=V(),{hasSidebar:n}=O();return(s,i)=>(a(),c("div",{class:N(["VPContent",{"has-sidebar":r(n),"is-home":r(t).layout==="home"}]),id:"VPContent"},[r(e).isNotFound?l(s.$slots,"not-found",{key:0},()=>[m(mt)],!0):r(t).layout==="page"?(a(),b(us,{key:1},{"page-top":d(()=>[l(s.$slots,"page-top",{},void 0,!0)]),"page-bottom":d(()=>[l(s.$slots,"page-bottom",{},void 0,!0)]),_:3})):r(t).layout==="home"?(a(),b(rs,{key:2},{"home-hero-before":d(()=>[l(s.$slots,"home-hero-before",{},void 0,!0)]),"home-hero-info-before":d(()=>[l(s.$slots,"home-hero-info-before",{},void 0,!0)]),"home-hero-info":d(()=>[l(s.$slots,"home-hero-info",{},void 0,!0)]),"home-hero-info-after":d(()=>[l(s.$slots,"home-hero-info-after",{},void 0,!0)]),"home-hero-actions-after":d(()=>[l(s.$slots,"home-hero-actions-after",{},void 0,!0)]),"home-hero-image":d(()=>[l(s.$slots,"home-hero-image",{},void 0,!0)]),"home-hero-after":d(()=>[l(s.$slots,"home-hero-after",{},void 0,!0)]),"home-features-before":d(()=>[l(s.$slots,"home-features-before",{},void 0,!0)]),"home-features-after":d(()=>[l(s.$slots,"home-features-after",{},void 0,!0)]),_:3})):r(t).layout&&r(t).layout!=="doc"?(a(),b(W(r(t).layout),{key:3})):(a(),b(bo,{key:4},{"doc-top":d(()=>[l(s.$slots,"doc-top",{},void 0,!0)]),"doc-bottom":d(()=>[l(s.$slots,"doc-bottom",{},void 0,!0)]),"doc-footer-before":d(()=>[l(s.$slots,"doc-footer-before",{},void 0,!0)]),"doc-before":d(()=>[l(s.$slots,"doc-before",{},void 0,!0)]),"doc-after":d(()=>[l(s.$slots,"doc-after",{},void 0,!0)]),"aside-top":d(()=>[l(s.$slots,"aside-top",{},void 0,!0)]),"aside-outline-before":d(()=>[l(s.$slots,"aside-outline-before",{},void 0,!0)]),"aside-outline-after":d(()=>[l(s.$slots,"aside-outline-after",{},void 0,!0)]),"aside-ads-before":d(()=>[l(s.$slots,"aside-ads-before",{},void 0,!0)]),"aside-ads-after":d(()=>[l(s.$slots,"aside-ads-after",{},void 0,!0)]),"aside-bottom":d(()=>[l(s.$slots,"aside-bottom",{},void 0,!0)]),_:3}))],2))}}),vs=k(ds,[["__scopeId","data-v-1428d186"]]),ps={class:"container"},hs=["innerHTML"],fs=["innerHTML"],_s=_({__name:"VPFooter",setup(o){const{theme:e,frontmatter:t}=V(),{hasSidebar:n}=O();return(s,i)=>r(e).footer&&r(t).footer!==!1?(a(),c("footer",{key:0,class:N(["VPFooter",{"has-sidebar":r(n)}])},[v("div",ps,[r(e).footer.message?(a(),c("p",{key:0,class:"message",innerHTML:r(e).footer.message},null,8,hs)):f("",!0),r(e).footer.copyright?(a(),c("p",{key:1,class:"copyright",innerHTML:r(e).footer.copyright},null,8,fs)):f("",!0)])],2)):f("",!0)}}),ms=k(_s,[["__scopeId","data-v-e315a0ad"]]);function Ce(){const{theme:o,frontmatter:e}=V(),t=Ve([]),n=g(()=>t.value.length>0);return ee(()=>{t.value=me(e.value.outline??o.value.outline)}),{headers:t,hasLocalNav:n}}const ks=o=>(B("data-v-d2ecc192"),o=o(),H(),o),$s=ks(()=>v("span",{class:"vpi-chevron-right icon"},null,-1)),bs={class:"header"},gs={class:"outline"},ys=_({__name:"VPLocalNavOutlineDropdown",props:{headers:{},navHeight:{}},setup(o){const e=o,{theme:t}=V(),n=T(!1),s=T(0),i=T(),u=T();Re(i,()=>{n.value=!1}),le("Escape",()=>{n.value=!1}),ee(()=>{n.value=!1});function h(){n.value=!n.value,s.value=window.innerHeight+Math.min(window.scrollY-e.navHeight,0)}function p(P){P.target.classList.contains("outline-link")&&(u.value&&(u.value.style.transition="none"),Je(()=>{n.value=!1}))}function $(){n.value=!1,window.scrollTo({top:0,left:0,behavior:"smooth"})}return(P,y)=>(a(),c("div",{class:"VPLocalNavOutlineDropdown",style:Se({"--vp-vh":s.value+"px"}),ref_key:"main",ref:i},[P.headers.length>0?(a(),c("button",{key:0,onClick:h,class:N({open:n.value})},[F(S(r(Me)(r(t)))+" ",1),$s],2)):(a(),c("button",{key:1,onClick:$},S(r(t).returnToTopLabel||"Return to top"),1)),m(ve,{name:"flyout"},{default:d(()=>[n.value?(a(),c("div",{key:0,ref_key:"items",ref:u,class:"items",onClick:p},[v("div",bs,[v("a",{class:"top-link",href:"#",onClick:$},S(r(t).returnToTopLabel||"Return to top"),1)]),v("div",gs,[m(Ae,{headers:P.headers},null,8,["headers"])])],512)):f("",!0)]),_:1})],4))}}),Ps=k(ys,[["__scopeId","data-v-d2ecc192"]]),Vs=o=>(B("data-v-a6f0e41e"),o=o(),H(),o),Ls={class:"container"},Ss=["aria-expanded"],ws=Vs(()=>v("span",{class:"vpi-align-left menu-icon"},null,-1)),Ts={class:"menu-text"},Is=_({__name:"VPLocalNav",props:{open:{type:Boolean}},emits:["open-menu"],setup(o){const{theme:e,frontmatter:t}=V(),{hasSidebar:n}=O(),{headers:s}=Ce(),{y:i}=we(),u=T(0);j(()=>{u.value=parseInt(getComputedStyle(document.documentElement).getPropertyValue("--vp-nav-height"))}),ee(()=>{s.value=me(t.value.outline??e.value.outline)});const h=g(()=>s.value.length===0),p=g(()=>h.value&&!n.value),$=g(()=>({VPLocalNav:!0,"has-sidebar":n.value,empty:h.value,fixed:p.value}));return(P,y)=>r(t).layout!=="home"&&(!p.value||r(i)>=u.value)?(a(),c("div",{key:0,class:N($.value)},[v("div",Ls,[r(n)?(a(),c("button",{key:0,class:"menu","aria-expanded":P.open,"aria-controls":"VPSidebarNav",onClick:y[0]||(y[0]=L=>P.$emit("open-menu"))},[ws,v("span",Ts,S(r(e).sidebarMenuLabel||"Menu"),1)],8,Ss)):f("",!0),m(Ps,{headers:r(s),navHeight:u.value},null,8,["headers","navHeight"])])],2)):f("",!0)}}),Ns=k(Is,[["__scopeId","data-v-a6f0e41e"]]);function Ms(){const o=T(!1);function e(){o.value=!0,window.addEventListener("resize",s)}function t(){o.value=!1,window.removeEventListener("resize",s)}function n(){o.value?t():e()}function s(){window.outerWidth>=768&&t()}const i=te();return z(()=>i.path,t),{isScreenOpen:o,openScreen:e,closeScreen:t,toggleScreen:n}}const As={},Cs={class:"VPSwitch",type:"button",role:"switch"},Bs={class:"check"},Hs={key:0,class:"icon"};function Es(o,e){return a(),c("button",Cs,[v("span",Bs,[o.$slots.default?(a(),c("span",Hs,[l(o.$slots,"default",{},void 0,!0)])):f("",!0)])])}const Fs=k(As,[["render",Es],["__scopeId","data-v-1d5665e3"]]),Be=o=>(B("data-v-d1f28634"),o=o(),H(),o),Ds=Be(()=>v("span",{class:"vpi-sun sun"},null,-1)),Os=Be(()=>v("span",{class:"vpi-moon moon"},null,-1)),Us=_({__name:"VPSwitchAppearance",setup(o){const{isDark:e,theme:t}=V(),n=oe("toggle-appearance",()=>{e.value=!e.value}),s=g(()=>e.value?t.value.lightModeSwitchTitle||"Switch to light theme":t.value.darkModeSwitchTitle||"Switch to dark theme");return(i,u)=>(a(),b(Fs,{title:s.value,class:"VPSwitchAppearance","aria-checked":r(e),onClick:r(n)},{default:d(()=>[Ds,Os]),_:1},8,["title","aria-checked","onClick"]))}}),ke=k(Us,[["__scopeId","data-v-d1f28634"]]),Gs={key:0,class:"VPNavBarAppearance"},js=_({__name:"VPNavBarAppearance",setup(o){const{site:e}=V();return(t,n)=>r(e).appearance&&r(e).appearance!=="force-dark"?(a(),c("div",Gs,[m(ke)])):f("",!0)}}),zs=k(js,[["__scopeId","data-v-e6aabb21"]]),$e=T();let He=!1,re=0;function Ks(o){const e=T(!1);if(R){!He&&qs(),re++;const t=z($e,n=>{var s,i,u;n===o.el.value||(s=o.el.value)!=null&&s.contains(n)?(e.value=!0,(i=o.onFocus)==null||i.call(o)):(e.value=!1,(u=o.onBlur)==null||u.call(o))});he(()=>{t(),re--,re||Ws()})}return Ye(e)}function qs(){document.addEventListener("focusin",Ee),He=!0,$e.value=document.activeElement}function Ws(){document.removeEventListener("focusin",Ee)}function Ee(){$e.value=document.activeElement}const Rs={class:"VPMenuLink"},Js=_({__name:"VPMenuLink",props:{item:{}},setup(o){const{page:e}=V();return(t,n)=>(a(),c("div",Rs,[m(D,{class:N({active:r(G)(r(e).relativePath,t.item.activeMatch||t.item.link,!!t.item.activeMatch)}),href:t.item.link,target:t.item.target,rel:t.item.rel},{default:d(()=>[F(S(t.item.text),1)]),_:1},8,["class","href","target","rel"])]))}}),se=k(Js,[["__scopeId","data-v-43f1e123"]]),Ys={class:"VPMenuGroup"},Qs={key:0,class:"title"},Xs=_({__name:"VPMenuGroup",props:{text:{},items:{}},setup(o){return(e,t)=>(a(),c("div",Ys,[e.text?(a(),c("p",Qs,S(e.text),1)):f("",!0),(a(!0),c(M,null,E(e.items,n=>(a(),c(M,null,["link"in n?(a(),b(se,{key:0,item:n},null,8,["item"])):f("",!0)],64))),256))]))}}),Zs=k(Xs,[["__scopeId","data-v-69e747b5"]]),xs={class:"VPMenu"},en={key:0,class:"items"},tn=_({__name:"VPMenu",props:{items:{}},setup(o){return(e,t)=>(a(),c("div",xs,[e.items?(a(),c("div",en,[(a(!0),c(M,null,E(e.items,n=>(a(),c(M,{key:n.text},["link"in n?(a(),b(se,{key:0,item:n},null,8,["item"])):(a(),b(Zs,{key:1,text:n.text,items:n.items},null,8,["text","items"]))],64))),128))])):f("",!0),l(e.$slots,"default",{},void 0,!0)]))}}),on=k(tn,[["__scopeId","data-v-e7ea1737"]]),sn=o=>(B("data-v-b6c34ac9"),o=o(),H(),o),nn=["aria-expanded","aria-label"],an={key:0,class:"text"},rn=["innerHTML"],ln=sn(()=>v("span",{class:"vpi-chevron-down text-icon"},null,-1)),cn={key:1,class:"vpi-more-horizontal icon"},un={class:"menu"},dn=_({__name:"VPFlyout",props:{icon:{},button:{},label:{},items:{}},setup(o){const e=T(!1),t=T();Ks({el:t,onBlur:n});function n(){e.value=!1}return(s,i)=>(a(),c("div",{class:"VPFlyout",ref_key:"el",ref:t,onMouseenter:i[1]||(i[1]=u=>e.value=!0),onMouseleave:i[2]||(i[2]=u=>e.value=!1)},[v("button",{type:"button",class:"button","aria-haspopup":"true","aria-expanded":e.value,"aria-label":s.label,onClick:i[0]||(i[0]=u=>e.value=!e.value)},[s.button||s.icon?(a(),c("span",an,[s.icon?(a(),c("span",{key:0,class:N([s.icon,"option-icon"])},null,2)):f("",!0),s.button?(a(),c("span",{key:1,innerHTML:s.button},null,8,rn)):f("",!0),ln])):(a(),c("span",cn))],8,nn),v("div",un,[m(on,{items:s.items},{default:d(()=>[l(s.$slots,"default",{},void 0,!0)]),_:3},8,["items"])])],544))}}),be=k(dn,[["__scopeId","data-v-b6c34ac9"]]),vn=["href","aria-label","innerHTML"],pn=_({__name:"VPSocialLink",props:{icon:{},link:{},ariaLabel:{}},setup(o){const e=o,t=g(()=>typeof e.icon=="object"?e.icon.svg:``);return(n,s)=>(a(),c("a",{class:"VPSocialLink no-icon",href:n.link,"aria-label":n.ariaLabel??(typeof n.icon=="string"?n.icon:""),target:"_blank",rel:"noopener",innerHTML:t.value},null,8,vn))}}),hn=k(pn,[["__scopeId","data-v-eee4e7cb"]]),fn={class:"VPSocialLinks"},_n=_({__name:"VPSocialLinks",props:{links:{}},setup(o){return(e,t)=>(a(),c("div",fn,[(a(!0),c(M,null,E(e.links,({link:n,icon:s,ariaLabel:i})=>(a(),b(hn,{key:n,icon:s,link:n,ariaLabel:i},null,8,["icon","link","ariaLabel"]))),128))]))}}),ge=k(_n,[["__scopeId","data-v-7bc22406"]]),mn={key:0,class:"group translations"},kn={class:"trans-title"},$n={key:1,class:"group"},bn={class:"item appearance"},gn={class:"label"},yn={class:"appearance-action"},Pn={key:2,class:"group"},Vn={class:"item social-links"},Ln=_({__name:"VPNavBarExtra",setup(o){const{site:e,theme:t}=V(),{localeLinks:n,currentLang:s}=J({correspondingLink:!0}),i=g(()=>n.value.length&&s.value.label||e.value.appearance||t.value.socialLinks);return(u,h)=>i.value?(a(),b(be,{key:0,class:"VPNavBarExtra",label:"extra navigation"},{default:d(()=>[r(n).length&&r(s).label?(a(),c("div",mn,[v("p",kn,S(r(s).label),1),(a(!0),c(M,null,E(r(n),p=>(a(),b(se,{key:p.link,item:p},null,8,["item"]))),128))])):f("",!0),r(e).appearance&&r(e).appearance!=="force-dark"?(a(),c("div",$n,[v("div",bn,[v("p",gn,S(r(t).darkModeSwitchLabel||"Appearance"),1),v("div",yn,[m(ke)])])])):f("",!0),r(t).socialLinks?(a(),c("div",Pn,[v("div",Vn,[m(ge,{class:"social-links-list",links:r(t).socialLinks},null,8,["links"])])])):f("",!0)]),_:1})):f("",!0)}}),Sn=k(Ln,[["__scopeId","data-v-d0bd9dde"]]),wn=o=>(B("data-v-e5dd9c1c"),o=o(),H(),o),Tn=["aria-expanded"],In=wn(()=>v("span",{class:"container"},[v("span",{class:"top"}),v("span",{class:"middle"}),v("span",{class:"bottom"})],-1)),Nn=[In],Mn=_({__name:"VPNavBarHamburger",props:{active:{type:Boolean}},emits:["click"],setup(o){return(e,t)=>(a(),c("button",{type:"button",class:N(["VPNavBarHamburger",{active:e.active}]),"aria-label":"mobile navigation","aria-expanded":e.active,"aria-controls":"VPNavScreen",onClick:t[0]||(t[0]=n=>e.$emit("click"))},Nn,10,Tn))}}),An=k(Mn,[["__scopeId","data-v-e5dd9c1c"]]),Cn=["innerHTML"],Bn=_({__name:"VPNavBarMenuLink",props:{item:{}},setup(o){const{page:e}=V();return(t,n)=>(a(),b(D,{class:N({VPNavBarMenuLink:!0,active:r(G)(r(e).relativePath,t.item.activeMatch||t.item.link,!!t.item.activeMatch)}),href:t.item.link,target:t.item.target,rel:t.item.rel,tabindex:"0"},{default:d(()=>[v("span",{innerHTML:t.item.text},null,8,Cn)]),_:1},8,["class","href","target","rel"]))}}),Hn=k(Bn,[["__scopeId","data-v-42ef59de"]]),En=_({__name:"VPNavBarMenuGroup",props:{item:{}},setup(o){const e=o,{page:t}=V(),n=i=>"link"in i?G(t.value.relativePath,i.link,!!e.item.activeMatch):i.items.some(n),s=g(()=>n(e.item));return(i,u)=>(a(),b(be,{class:N({VPNavBarMenuGroup:!0,active:r(G)(r(t).relativePath,i.item.activeMatch,!!i.item.activeMatch)||s.value}),button:i.item.text,items:i.item.items},null,8,["class","button","items"]))}}),Fn=o=>(B("data-v-7f418b0f"),o=o(),H(),o),Dn={key:0,"aria-labelledby":"main-nav-aria-label",class:"VPNavBarMenu"},On=Fn(()=>v("span",{id:"main-nav-aria-label",class:"visually-hidden"},"Main Navigation",-1)),Un=_({__name:"VPNavBarMenu",setup(o){const{theme:e}=V();return(t,n)=>r(e).nav?(a(),c("nav",Dn,[On,(a(!0),c(M,null,E(r(e).nav,s=>(a(),c(M,{key:s.text},["link"in s?(a(),b(Hn,{key:0,item:s},null,8,["item"])):(a(),b(En,{key:1,item:s},null,8,["item"]))],64))),128))])):f("",!0)}}),Gn=k(Un,[["__scopeId","data-v-7f418b0f"]]);function jn(o){const{localeIndex:e,theme:t}=V();function n(s){var A,C,I;const i=s.split("."),u=(A=t.value.search)==null?void 0:A.options,h=u&&typeof u=="object",p=h&&((I=(C=u.locales)==null?void 0:C[e.value])==null?void 0:I.translations)||null,$=h&&u.translations||null;let P=p,y=$,L=o;const w=i.pop();for(const Y of i){let U=null;const q=L==null?void 0:L[Y];q&&(U=L=q);const ne=y==null?void 0:y[Y];ne&&(U=y=ne);const ae=P==null?void 0:P[Y];ae&&(U=P=ae),q||(L=U),ne||(y=U),ae||(P=U)}return(P==null?void 0:P[w])??(y==null?void 0:y[w])??(L==null?void 0:L[w])??""}return n}const zn=["aria-label"],Kn={class:"DocSearch-Button-Container"},qn=v("span",{class:"vp-icon DocSearch-Search-Icon"},null,-1),Wn={class:"DocSearch-Button-Placeholder"},Rn=v("span",{class:"DocSearch-Button-Keys"},[v("kbd",{class:"DocSearch-Button-Key"}),v("kbd",{class:"DocSearch-Button-Key"},"K")],-1),ye=_({__name:"VPNavBarSearchButton",setup(o){const t=jn({button:{buttonText:"Search",buttonAriaLabel:"Search"}});return(n,s)=>(a(),c("button",{type:"button",class:"DocSearch DocSearch-Button","aria-label":r(t)("button.buttonAriaLabel")},[v("span",Kn,[qn,v("span",Wn,S(r(t)("button.buttonText")),1)]),Rn],8,zn))}}),Jn={class:"VPNavBarSearch"},Yn={id:"local-search"},Qn={key:1,id:"docsearch"},Xn=_({__name:"VPNavBarSearch",setup(o){const e=Qe(()=>Xe(()=>import("./VPLocalSearchBox.B0G8URRa.js"),__vite__mapDeps([0,1]))),t=()=>null,{theme:n}=V(),s=T(!1),i=T(!1);j(()=>{});function u(){s.value||(s.value=!0,setTimeout(h,16))}function h(){const y=new Event("keydown");y.key="k",y.metaKey=!0,window.dispatchEvent(y),setTimeout(()=>{document.querySelector(".DocSearch-Modal")||h()},16)}function p(y){const L=y.target,w=L.tagName;return L.isContentEditable||w==="INPUT"||w==="SELECT"||w==="TEXTAREA"}const $=T(!1);le("k",y=>{(y.ctrlKey||y.metaKey)&&(y.preventDefault(),$.value=!0)}),le("/",y=>{p(y)||(y.preventDefault(),$.value=!0)});const P="local";return(y,L)=>{var w;return a(),c("div",Jn,[r(P)==="local"?(a(),c(M,{key:0},[$.value?(a(),b(r(e),{key:0,onClose:L[0]||(L[0]=A=>$.value=!1)})):f("",!0),v("div",Yn,[m(ye,{onClick:L[1]||(L[1]=A=>$.value=!0)})])],64)):r(P)==="algolia"?(a(),c(M,{key:1},[s.value?(a(),b(r(t),{key:0,algolia:((w=r(n).search)==null?void 0:w.options)??r(n).algolia,onVnodeBeforeMount:L[2]||(L[2]=A=>i.value=!0)},null,8,["algolia"])):f("",!0),i.value?f("",!0):(a(),c("div",Qn,[m(ye,{onClick:u})]))],64)):f("",!0)])}}}),Zn=_({__name:"VPNavBarSocialLinks",setup(o){const{theme:e}=V();return(t,n)=>r(e).socialLinks?(a(),b(ge,{key:0,class:"VPNavBarSocialLinks",links:r(e).socialLinks},null,8,["links"])):f("",!0)}}),xn=k(Zn,[["__scopeId","data-v-0394ad82"]]),ea=["href","rel","target"],ta={key:1},oa={key:2},sa=_({__name:"VPNavBarTitle",setup(o){const{site:e,theme:t}=V(),{hasSidebar:n}=O(),{currentLang:s}=J(),i=g(()=>{var p;return typeof t.value.logoLink=="string"?t.value.logoLink:(p=t.value.logoLink)==null?void 0:p.link}),u=g(()=>{var p;return typeof t.value.logoLink=="string"||(p=t.value.logoLink)==null?void 0:p.rel}),h=g(()=>{var p;return typeof t.value.logoLink=="string"||(p=t.value.logoLink)==null?void 0:p.target});return(p,$)=>(a(),c("div",{class:N(["VPNavBarTitle",{"has-sidebar":r(n)}])},[v("a",{class:"title",href:i.value??r(fe)(r(s).link),rel:u.value,target:h.value},[l(p.$slots,"nav-bar-title-before",{},void 0,!0),r(t).logo?(a(),b(Z,{key:0,class:"logo",image:r(t).logo},null,8,["image"])):f("",!0),r(t).siteTitle?(a(),c("span",ta,S(r(t).siteTitle),1)):r(t).siteTitle===void 0?(a(),c("span",oa,S(r(e).title),1)):f("",!0),l(p.$slots,"nav-bar-title-after",{},void 0,!0)],8,ea)],2))}}),na=k(sa,[["__scopeId","data-v-ab179fa1"]]),aa={class:"items"},ra={class:"title"},ia=_({__name:"VPNavBarTranslations",setup(o){const{theme:e}=V(),{localeLinks:t,currentLang:n}=J({correspondingLink:!0});return(s,i)=>r(t).length&&r(n).label?(a(),b(be,{key:0,class:"VPNavBarTranslations",icon:"vpi-languages",label:r(e).langMenuLabel||"Change language"},{default:d(()=>[v("div",aa,[v("p",ra,S(r(n).label),1),(a(!0),c(M,null,E(r(t),u=>(a(),b(se,{key:u.link,item:u},null,8,["item"]))),128))])]),_:1},8,["label"])):f("",!0)}}),la=k(ia,[["__scopeId","data-v-88af2de4"]]),ca=o=>(B("data-v-19c990f1"),o=o(),H(),o),ua={class:"wrapper"},da={class:"container"},va={class:"title"},pa={class:"content"},ha={class:"content-body"},fa=ca(()=>v("div",{class:"divider"},[v("div",{class:"divider-line"})],-1)),_a=_({__name:"VPNavBar",props:{isScreenOpen:{type:Boolean}},emits:["toggle-screen"],setup(o){const{y:e}=we(),{hasSidebar:t}=O(),{hasLocalNav:n}=Ce(),{frontmatter:s}=V(),i=T({});return Pe(()=>{i.value={"has-sidebar":t.value,"has-local-nav":n.value,top:s.value.layout==="home"&&e.value===0}}),(u,h)=>(a(),c("div",{class:N(["VPNavBar",i.value])},[v("div",ua,[v("div",da,[v("div",va,[m(na,null,{"nav-bar-title-before":d(()=>[l(u.$slots,"nav-bar-title-before",{},void 0,!0)]),"nav-bar-title-after":d(()=>[l(u.$slots,"nav-bar-title-after",{},void 0,!0)]),_:3})]),v("div",pa,[v("div",ha,[l(u.$slots,"nav-bar-content-before",{},void 0,!0),m(Xn,{class:"search"}),m(Gn,{class:"menu"}),m(la,{class:"translations"}),m(zs,{class:"appearance"}),m(xn,{class:"social-links"}),m(Sn,{class:"extra"}),l(u.$slots,"nav-bar-content-after",{},void 0,!0),m(An,{class:"hamburger",active:u.isScreenOpen,onClick:h[0]||(h[0]=p=>u.$emit("toggle-screen"))},null,8,["active"])])])])]),fa],2))}}),ma=k(_a,[["__scopeId","data-v-19c990f1"]]),ka={key:0,class:"VPNavScreenAppearance"},$a={class:"text"},ba=_({__name:"VPNavScreenAppearance",setup(o){const{site:e,theme:t}=V();return(n,s)=>r(e).appearance&&r(e).appearance!=="force-dark"?(a(),c("div",ka,[v("p",$a,S(r(t).darkModeSwitchLabel||"Appearance"),1),m(ke)])):f("",!0)}}),ga=k(ba,[["__scopeId","data-v-2d7af913"]]),ya=_({__name:"VPNavScreenMenuLink",props:{item:{}},setup(o){const e=oe("close-screen");return(t,n)=>(a(),b(D,{class:"VPNavScreenMenuLink",href:t.item.link,target:t.item.target,rel:t.item.rel,onClick:r(e)},{default:d(()=>[F(S(t.item.text),1)]),_:1},8,["href","target","rel","onClick"]))}}),Pa=k(ya,[["__scopeId","data-v-05f27b2a"]]),Va=_({__name:"VPNavScreenMenuGroupLink",props:{item:{}},setup(o){const e=oe("close-screen");return(t,n)=>(a(),b(D,{class:"VPNavScreenMenuGroupLink",href:t.item.link,target:t.item.target,rel:t.item.rel,onClick:r(e)},{default:d(()=>[F(S(t.item.text),1)]),_:1},8,["href","target","rel","onClick"]))}}),Fe=k(Va,[["__scopeId","data-v-19976ae1"]]),La={class:"VPNavScreenMenuGroupSection"},Sa={key:0,class:"title"},wa=_({__name:"VPNavScreenMenuGroupSection",props:{text:{},items:{}},setup(o){return(e,t)=>(a(),c("div",La,[e.text?(a(),c("p",Sa,S(e.text),1)):f("",!0),(a(!0),c(M,null,E(e.items,n=>(a(),b(Fe,{key:n.text,item:n},null,8,["item"]))),128))]))}}),Ta=k(wa,[["__scopeId","data-v-8133b170"]]),Ia=o=>(B("data-v-ff6087d4"),o=o(),H(),o),Na=["aria-controls","aria-expanded"],Ma=["innerHTML"],Aa=Ia(()=>v("span",{class:"vpi-plus button-icon"},null,-1)),Ca=["id"],Ba={key:1,class:"group"},Ha=_({__name:"VPNavScreenMenuGroup",props:{text:{},items:{}},setup(o){const e=o,t=T(!1),n=g(()=>`NavScreenGroup-${e.text.replace(" ","-").toLowerCase()}`);function s(){t.value=!t.value}return(i,u)=>(a(),c("div",{class:N(["VPNavScreenMenuGroup",{open:t.value}])},[v("button",{class:"button","aria-controls":n.value,"aria-expanded":t.value,onClick:s},[v("span",{class:"button-text",innerHTML:i.text},null,8,Ma),Aa],8,Na),v("div",{id:n.value,class:"items"},[(a(!0),c(M,null,E(i.items,h=>(a(),c(M,{key:h.text},["link"in h?(a(),c("div",{key:h.text,class:"item"},[m(Fe,{item:h},null,8,["item"])])):(a(),c("div",Ba,[m(Ta,{text:h.text,items:h.items},null,8,["text","items"])]))],64))),128))],8,Ca)],2))}}),Ea=k(Ha,[["__scopeId","data-v-ff6087d4"]]),Fa={key:0,class:"VPNavScreenMenu"},Da=_({__name:"VPNavScreenMenu",setup(o){const{theme:e}=V();return(t,n)=>r(e).nav?(a(),c("nav",Fa,[(a(!0),c(M,null,E(r(e).nav,s=>(a(),c(M,{key:s.text},["link"in s?(a(),b(Pa,{key:0,item:s},null,8,["item"])):(a(),b(Ea,{key:1,text:s.text||"",items:s.items},null,8,["text","items"]))],64))),128))])):f("",!0)}}),Oa=_({__name:"VPNavScreenSocialLinks",setup(o){const{theme:e}=V();return(t,n)=>r(e).socialLinks?(a(),b(ge,{key:0,class:"VPNavScreenSocialLinks",links:r(e).socialLinks},null,8,["links"])):f("",!0)}}),De=o=>(B("data-v-858fe1a4"),o=o(),H(),o),Ua=De(()=>v("span",{class:"vpi-languages icon lang"},null,-1)),Ga=De(()=>v("span",{class:"vpi-chevron-down icon chevron"},null,-1)),ja={class:"list"},za=_({__name:"VPNavScreenTranslations",setup(o){const{localeLinks:e,currentLang:t}=J({correspondingLink:!0}),n=T(!1);function s(){n.value=!n.value}return(i,u)=>r(e).length&&r(t).label?(a(),c("div",{key:0,class:N(["VPNavScreenTranslations",{open:n.value}])},[v("button",{class:"title",onClick:s},[Ua,F(" "+S(r(t).label)+" ",1),Ga]),v("ul",ja,[(a(!0),c(M,null,E(r(e),h=>(a(),c("li",{key:h.link,class:"item"},[m(D,{class:"link",href:h.link},{default:d(()=>[F(S(h.text),1)]),_:2},1032,["href"])]))),128))])],2)):f("",!0)}}),Ka=k(za,[["__scopeId","data-v-858fe1a4"]]),qa={class:"container"},Wa=_({__name:"VPNavScreen",props:{open:{type:Boolean}},setup(o){const e=T(null),t=Te(R?document.body:null);return(n,s)=>(a(),b(ve,{name:"fade",onEnter:s[0]||(s[0]=i=>t.value=!0),onAfterLeave:s[1]||(s[1]=i=>t.value=!1)},{default:d(()=>[n.open?(a(),c("div",{key:0,class:"VPNavScreen",ref_key:"screen",ref:e,id:"VPNavScreen"},[v("div",qa,[l(n.$slots,"nav-screen-content-before",{},void 0,!0),m(Da,{class:"menu"}),m(Ka,{class:"translations"}),m(ga,{class:"appearance"}),m(Oa,{class:"social-links"}),l(n.$slots,"nav-screen-content-after",{},void 0,!0)])],512)):f("",!0)]),_:3}))}}),Ra=k(Wa,[["__scopeId","data-v-cc5739dd"]]),Ja={key:0,class:"VPNav"},Ya=_({__name:"VPNav",setup(o){const{isScreenOpen:e,closeScreen:t,toggleScreen:n}=Ms(),{frontmatter:s}=V(),i=g(()=>s.value.navbar!==!1);return Ie("close-screen",t),x(()=>{R&&document.documentElement.classList.toggle("hide-nav",!i.value)}),(u,h)=>i.value?(a(),c("header",Ja,[m(ma,{"is-screen-open":r(e),onToggleScreen:r(n)},{"nav-bar-title-before":d(()=>[l(u.$slots,"nav-bar-title-before",{},void 0,!0)]),"nav-bar-title-after":d(()=>[l(u.$slots,"nav-bar-title-after",{},void 0,!0)]),"nav-bar-content-before":d(()=>[l(u.$slots,"nav-bar-content-before",{},void 0,!0)]),"nav-bar-content-after":d(()=>[l(u.$slots,"nav-bar-content-after",{},void 0,!0)]),_:3},8,["is-screen-open","onToggleScreen"]),m(Ra,{open:r(e)},{"nav-screen-content-before":d(()=>[l(u.$slots,"nav-screen-content-before",{},void 0,!0)]),"nav-screen-content-after":d(()=>[l(u.$slots,"nav-screen-content-after",{},void 0,!0)]),_:3},8,["open"])])):f("",!0)}}),Qa=k(Ya,[["__scopeId","data-v-ae24b3ad"]]),Oe=o=>(B("data-v-93e7e794"),o=o(),H(),o),Xa=["role","tabindex"],Za=Oe(()=>v("div",{class:"indicator"},null,-1)),xa=Oe(()=>v("span",{class:"vpi-chevron-right caret-icon"},null,-1)),er=[xa],tr={key:1,class:"items"},or=_({__name:"VPSidebarItem",props:{item:{},depth:{}},setup(o){const e=o,{collapsed:t,collapsible:n,isLink:s,isActiveLink:i,hasActiveLink:u,hasChildren:h,toggle:p}=gt(g(()=>e.item)),$=g(()=>h.value?"section":"div"),P=g(()=>s.value?"a":"div"),y=g(()=>h.value?e.depth+2===7?"p":`h${e.depth+2}`:"p"),L=g(()=>s.value?void 0:"button"),w=g(()=>[[`level-${e.depth}`],{collapsible:n.value},{collapsed:t.value},{"is-link":s.value},{"is-active":i.value},{"has-active":u.value}]);function A(I){"key"in I&&I.key!=="Enter"||!e.item.link&&p()}function C(){e.item.link&&p()}return(I,Y)=>{const U=K("VPSidebarItem",!0);return a(),b(W($.value),{class:N(["VPSidebarItem",w.value])},{default:d(()=>[I.item.text?(a(),c("div",Q({key:0,class:"item",role:L.value},xe(I.item.items?{click:A,keydown:A}:{},!0),{tabindex:I.item.items&&0}),[Za,I.item.link?(a(),b(D,{key:0,tag:P.value,class:"link",href:I.item.link,rel:I.item.rel,target:I.item.target},{default:d(()=>[(a(),b(W(y.value),{class:"text",innerHTML:I.item.text},null,8,["innerHTML"]))]),_:1},8,["tag","href","rel","target"])):(a(),b(W(y.value),{key:1,class:"text",innerHTML:I.item.text},null,8,["innerHTML"])),I.item.collapsed!=null?(a(),c("div",{key:2,class:"caret",role:"button","aria-label":"toggle section",onClick:C,onKeydown:Ze(C,["enter"]),tabindex:"0"},er,32)):f("",!0)],16,Xa)):f("",!0),I.item.items&&I.item.items.length?(a(),c("div",tr,[I.depth<5?(a(!0),c(M,{key:0},E(I.item.items,q=>(a(),b(U,{key:q.text,item:q,depth:I.depth+1},null,8,["item","depth"]))),128)):f("",!0)])):f("",!0)]),_:1},8,["class"])}}}),sr=k(or,[["__scopeId","data-v-93e7e794"]]),Ue=o=>(B("data-v-575e6a36"),o=o(),H(),o),nr=Ue(()=>v("div",{class:"curtain"},null,-1)),ar={class:"nav",id:"VPSidebarNav","aria-labelledby":"sidebar-aria-label",tabindex:"-1"},rr=Ue(()=>v("span",{class:"visually-hidden",id:"sidebar-aria-label"}," Sidebar Navigation ",-1)),ir=_({__name:"VPSidebar",props:{open:{type:Boolean}},setup(o){const{sidebarGroups:e,hasSidebar:t}=O(),n=o,s=T(null),i=Te(R?document.body:null);return z([n,s],()=>{var u;n.open?(i.value=!0,(u=s.value)==null||u.focus()):i.value=!1},{immediate:!0,flush:"post"}),(u,h)=>r(t)?(a(),c("aside",{key:0,class:N(["VPSidebar",{open:u.open}]),ref_key:"navEl",ref:s,onClick:h[0]||(h[0]=et(()=>{},["stop"]))},[nr,v("nav",ar,[rr,l(u.$slots,"sidebar-nav-before",{},void 0,!0),(a(!0),c(M,null,E(r(e),p=>(a(),c("div",{key:p.text,class:"group"},[m(sr,{item:p,depth:0},null,8,["item"])]))),128)),l(u.$slots,"sidebar-nav-after",{},void 0,!0)])],2)):f("",!0)}}),lr=k(ir,[["__scopeId","data-v-575e6a36"]]),cr=_({__name:"VPSkipLink",setup(o){const e=te(),t=T();z(()=>e.path,()=>t.value.focus());function n({target:s}){const i=document.getElementById(decodeURIComponent(s.hash).slice(1));if(i){const u=()=>{i.removeAttribute("tabindex"),i.removeEventListener("blur",u)};i.setAttribute("tabindex","-1"),i.addEventListener("blur",u),i.focus(),window.scrollTo(0,0)}}return(s,i)=>(a(),c(M,null,[v("span",{ref_key:"backToTop",ref:t,tabindex:"-1"},null,512),v("a",{href:"#VPContent",class:"VPSkipLink visually-hidden",onClick:n}," Skip to content ")],64))}}),ur=k(cr,[["__scopeId","data-v-0f60ec36"]]),dr=_({__name:"Layout",setup(o){const{isOpen:e,open:t,close:n}=O(),s=te();z(()=>s.path,n),bt(e,n);const{frontmatter:i}=V(),u=tt(),h=g(()=>!!u["home-hero-image"]);return Ie("hero-image-slot-exists",h),(p,$)=>{const P=K("Content");return r(i).layout!==!1?(a(),c("div",{key:0,class:N(["Layout",r(i).pageClass])},[l(p.$slots,"layout-top",{},void 0,!0),m(ur),m(at,{class:"backdrop",show:r(e),onClick:r(n)},null,8,["show","onClick"]),m(Qa,null,{"nav-bar-title-before":d(()=>[l(p.$slots,"nav-bar-title-before",{},void 0,!0)]),"nav-bar-title-after":d(()=>[l(p.$slots,"nav-bar-title-after",{},void 0,!0)]),"nav-bar-content-before":d(()=>[l(p.$slots,"nav-bar-content-before",{},void 0,!0)]),"nav-bar-content-after":d(()=>[l(p.$slots,"nav-bar-content-after",{},void 0,!0)]),"nav-screen-content-before":d(()=>[l(p.$slots,"nav-screen-content-before",{},void 0,!0)]),"nav-screen-content-after":d(()=>[l(p.$slots,"nav-screen-content-after",{},void 0,!0)]),_:3}),m(Ns,{open:r(e),onOpenMenu:r(t)},null,8,["open","onOpenMenu"]),m(lr,{open:r(e)},{"sidebar-nav-before":d(()=>[l(p.$slots,"sidebar-nav-before",{},void 0,!0)]),"sidebar-nav-after":d(()=>[l(p.$slots,"sidebar-nav-after",{},void 0,!0)]),_:3},8,["open"]),m(vs,null,{"page-top":d(()=>[l(p.$slots,"page-top",{},void 0,!0)]),"page-bottom":d(()=>[l(p.$slots,"page-bottom",{},void 0,!0)]),"not-found":d(()=>[l(p.$slots,"not-found",{},void 0,!0)]),"home-hero-before":d(()=>[l(p.$slots,"home-hero-before",{},void 0,!0)]),"home-hero-info-before":d(()=>[l(p.$slots,"home-hero-info-before",{},void 0,!0)]),"home-hero-info":d(()=>[l(p.$slots,"home-hero-info",{},void 0,!0)]),"home-hero-info-after":d(()=>[l(p.$slots,"home-hero-info-after",{},void 0,!0)]),"home-hero-actions-after":d(()=>[l(p.$slots,"home-hero-actions-after",{},void 0,!0)]),"home-hero-image":d(()=>[l(p.$slots,"home-hero-image",{},void 0,!0)]),"home-hero-after":d(()=>[l(p.$slots,"home-hero-after",{},void 0,!0)]),"home-features-before":d(()=>[l(p.$slots,"home-features-before",{},void 0,!0)]),"home-features-after":d(()=>[l(p.$slots,"home-features-after",{},void 0,!0)]),"doc-footer-before":d(()=>[l(p.$slots,"doc-footer-before",{},void 0,!0)]),"doc-before":d(()=>[l(p.$slots,"doc-before",{},void 0,!0)]),"doc-after":d(()=>[l(p.$slots,"doc-after",{},void 0,!0)]),"doc-top":d(()=>[l(p.$slots,"doc-top",{},void 0,!0)]),"doc-bottom":d(()=>[l(p.$slots,"doc-bottom",{},void 0,!0)]),"aside-top":d(()=>[l(p.$slots,"aside-top",{},void 0,!0)]),"aside-bottom":d(()=>[l(p.$slots,"aside-bottom",{},void 0,!0)]),"aside-outline-before":d(()=>[l(p.$slots,"aside-outline-before",{},void 0,!0)]),"aside-outline-after":d(()=>[l(p.$slots,"aside-outline-after",{},void 0,!0)]),"aside-ads-before":d(()=>[l(p.$slots,"aside-ads-before",{},void 0,!0)]),"aside-ads-after":d(()=>[l(p.$slots,"aside-ads-after",{},void 0,!0)]),_:3}),m(ms),l(p.$slots,"layout-bottom",{},void 0,!0)],2)):(a(),b(P,{key:1}))}}}),vr=k(dr,[["__scopeId","data-v-5d98c3a5"]]),hr={Layout:vr,enhanceApp:({app:o})=>{o.component("Badge",ot)}};export{jn as c,hr as t,V as u}; diff --git a/vitepress/docs/.vitepress/dist/assets/d_security_deep-linking.C1poVAy4.svg b/vitepress/docs/.vitepress/dist/assets/d_security_deep-linking.C1poVAy4.svg new file mode 100644 index 0000000..5030e84 --- /dev/null +++ b/vitepress/docs/.vitepress/dist/assets/d_security_deep-linking.C1poVAy4.svg @@ -0,0 +1 @@ +app://user datadeep linking \ No newline at end of file diff --git a/vitepress/docs/.vitepress/dist/assets/diagram_ios-android-views.ClKysHl7.svg b/vitepress/docs/.vitepress/dist/assets/diagram_ios-android-views.ClKysHl7.svg new file mode 100644 index 0000000..0c0b215 --- /dev/null +++ b/vitepress/docs/.vitepress/dist/assets/diagram_ios-android-views.ClKysHl7.svg @@ -0,0 +1 @@ +PouncivalUIViewUIImageViewUITextViewViewGroupImageViewTextViewChoupetteMrs. NorrisTunaTabbyRum Tum TuggerPouncivalSpotMaruCat Cafe MenuChoupetteMrs. NorrisTunaTabbyRum Tum TuggerPouncivalSpotMaruCat Cafe Menu \ No newline at end of file diff --git a/vitepress/docs/.vitepress/dist/assets/diagram_react-native-components.C8UF7CVQ.svg b/vitepress/docs/.vitepress/dist/assets/diagram_react-native-components.C8UF7CVQ.svg new file mode 100644 index 0000000..643dd4b --- /dev/null +++ b/vitepress/docs/.vitepress/dist/assets/diagram_react-native-components.C8UF7CVQ.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/vitepress/docs/.vitepress/dist/assets/diagram_testing.D4maG0bg.svg b/vitepress/docs/.vitepress/dist/assets/diagram_testing.D4maG0bg.svg new file mode 100644 index 0000000..5aa356d --- /dev/null +++ b/vitepress/docs/.vitepress/dist/assets/diagram_testing.D4maG0bg.svg @@ -0,0 +1 @@ +testfixfailpassrelease \ No newline at end of file diff --git a/vitepress/docs/.vitepress/dist/assets/docs_accessibility.md.BwWJ5VBO.js b/vitepress/docs/.vitepress/dist/assets/docs_accessibility.md.BwWJ5VBO.js new file mode 100644 index 0000000..25c1ee7 --- /dev/null +++ b/vitepress/docs/.vitepress/dist/assets/docs_accessibility.md.BwWJ5VBO.js @@ -0,0 +1,82 @@ +import{_ as a,c as s,o as e,a4 as i}from"./chunks/framework.nQaBHiNx.js";const m=JSON.parse('{"title":"Acessibilidade","description":"","frontmatter":{},"headers":[],"relativePath":"docs/accessibility.md","filePath":"docs/accessibility.md"}'),t={name:"docs/accessibility.md"},o=i(`

Acessibilidade

Tanto o Android quanto o iOS fornecem APIs para integração de aplicativos com tecnologias assistivas, como os leitores de tela incluídos VoiceOver (iOS) e TalkBack (Android). React Native possui APIs complementares que permitem que seu aplicativo acomode todos os usuários.

INFORMAÇÕES Android e iOS diferem ligeiramente em suas abordagens e, portanto, as implementações do React Native podem variar de acordo com a plataforma.

Propriedades de acessibilidade

accessible

Quando verdadeiro, indica que a visualização é um elemento de acessibilidade. Quando uma visualização é um elemento de acessibilidade, ela agrupa seus filhos em um único componente selecionável. Por padrão, todos os elementos tocáveis estão acessíveis.

No Android, a propriedade access={true} para uma visualização react-native será traduzida em focusable={true} nativo.

tsx
<View accessible={true}>
+  <Text>texto um</Text>
+  <Text>texto dois</Text>
+</View>

No exemplo acima, o foco de acessibilidade está disponível apenas na visualização pai com a propriedade acessível, e não individualmente para 'texto um' e 'texto dois'.

accessibilityLabel

Quando uma visualização é marcada como acessível, é uma boa prática definir um accessibilityLabel na visualização, para que as pessoas que usam o VoiceOver ou o TalkBack saibam qual elemento selecionaram. Um leitor de tela verbalizará esta string quando o elemento associado for selecionado.

Para usar, defina a propriedade accessibilityLabel como uma string personalizada em sua View, Text ou Touchable:

tsx
<TouchableOpacity
+  accessible={true}
+  accessibilityLabel="Tap me!"
+  onPress={onPress}>
+  <View style={styles.button}>
+    <Text style={styles.buttonText}>Press me!</Text>
+  </View>
+</TouchableOpacity>

No exemplo acima, o accessLabel no elemento TouchableOpacity seria padronizado como "Press me!". O rótulo é construído concatenando todos os filhos do nó Text separados por espaços.

accessibilityLabelledBy [Android]

Uma referência a outro elemento nativeID usado para criar formulários complexos. O valor de acessibilidadeLabelledBy deve corresponder ao nativeID do elemento relacionado:

jsx
<View>
+  <Text nativeID="formLabel">Label for Input Field</Text>
+  <TextInput
+    accessibilityLabel="input"
+    accessibilityLabelledBy="formLabel"
+  />
+</View>

No exemplo acima, o leitor de tela anuncia Input, Edit Box for Label for Input Field ao focar no TextInput.

accessibilityHint

Uma dica de acessibilidade pode ser usada para fornecer contexto adicional ao usuário sobre o resultado da ação quando isso não estiver claro apenas no rótulo de acessibilidade.

Forneça à propriedade acessibilidadeHint uma string personalizada em sua View, Text ou Touchable:

jsx
<TouchableOpacity
+  accessible={true}
+  accessibilityLabel="Go back"
+  accessibilityHint="Navigates to the previous screen"
+  onPress={onPress}>
+  <View style={styles.button}>
+    <Text style={styles.buttonText}>Back</Text>
+  </View>
+</TouchableOpacity>

iOS

No exemplo acima, o VoiceOver lerá a dica após o rótulo, se o usuário tiver as dicas habilitadas nas configurações do VoiceOver do dispositivo. Leia mais sobre as diretrizes para acessibilidadeHint nos documentos do desenvolvedor iOS

Android

No exemplo acima, o TalkBack lerá a dica após o rótulo. No momento, as dicas não podem ser desativadas no Android.

accessibilityLanguage [iOS]

Ao usar a propriedade accessibilityLanguage, o leitor de tela entenderá qual idioma usar ao ler o label, o value e o hint. O valor da string fornecido deve seguir a especificação BCP 47.

tsx
<View
+  accessible={true}
+  accessibilityLabel="Pizza"
+  accessibilityLanguage="it-IT">
+  <Text>🍕</Text>
+</View>

acessibilidadeIgnoresInvertColors [iOS]

A inversão das cores da tela é um recurso de acessibilidade disponível no iOS e iPadOS para pessoas com daltonismo, baixa visão ou deficiência visual. Se houver uma visualização que você não deseja inverter quando esta configuração estiver ativada, possivelmente uma foto, defina esta propriedade como verdadeira.

accessibilityLiveRegion [Android]

Quando os componentes mudam dinamicamente, queremos que o TalkBack alerte o usuário final. Isso é possível graças à propriedade accessibilityLiveRegion. Pode ser definido como none, polite e assertive:

  • none Os serviços de acessibilidade não devem anunciar alterações nesta visão.
  • polite serviços de acessibilidade educados devem anunciar mudanças nesta visão.
  • assertive Os serviços de acessibilidade devem interromper o discurso em curso para anunciar imediatamente alterações nesta visão.
tsx
<TouchableWithoutFeedback onPress={addOne}>
+  <View style={styles.embedded}>
+    <Text>Click me</Text>
+  </View>
+</TouchableWithoutFeedback>
+<Text accessibilityLiveRegion="polite">
+  Clicked {count} times
+</Text>

No exemplo acima, o método addOne altera a contagem (count} da variável de estado. Quando TouchableWithoutFeedback é acionado, o TalkBack lê o texto na visualização Texto devido à sua propriedade accessibilityLiveRegion="polite".

accessibilityRole

accessibilityRole comunica a finalidade de um componente ao usuário de tecnologia assistiva.

accessibilityRole pode ser um dos seguintes:

  • adjustable Usado quando um elemento pode ser "ajustado" (por exemplo, um controle deslizante).
  • alert Usado quando um elemento contém texto importante a ser apresentado ao usuário.
  • button Usado quando o elemento deve ser tratado como um botão.
  • checkbox Usado quando um elemento representa uma caixa de seleção que pode ser marcada, desmarcada ou ter um estado misto de marcado.
  • combobox Usado quando um elemento representa uma caixa de combinação, que permite ao usuário selecionar entre diversas opções.
  • header Usado quando um elemento atua como cabeçalho para uma seção de conteúdo (por exemplo, o título de uma barra de navegação).
  • image Usado quando o elemento deve ser tratado como uma imagem. Pode ser combinado com um botão ou link.
  • imagebutton Utilizado quando o elemento deve ser tratado como um botão e também é uma imagem.
  • keyboardkey Usado quando o elemento atua como uma tecla do teclado.
  • link Usado quando o elemento deve ser tratado como um link.
  • menu Usado quando o componente é um menu de opções.
  • menubar Usada quando um componente é um contêiner de vários menus.
  • menuitem Usado para representar um item dentro de um menu.
  • none Usado quando o elemento não tem função.
  • progressbar Usado para representar um componente que indica o progresso de uma tarefa.
  • radio Usado para representar um botão de opção.
  • radiogroup Usado para representar um grupo de botões de opção.
  • scrollbar Usada para representar uma barra de rolagem.
  • search Usado quando um elemento de campo de texto também deve ser tratado como um campo de pesquisa.
  • spinbutton Usado para representar um botão que abre uma lista de opções.
  • summary Usado quando um elemento pode ser usado para fornecer um resumo rápido das condições atuais no aplicativo quando ele é iniciado pela primeira vez.
  • switch Usado para representar um switch que pode ser ligado e desligado.
  • tab Usado para representar uma guia.
  • tablist Usado para representar uma lista de guias.
  • text Usado quando o elemento deve ser tratado como texto estático que não pode ser alterado.
  • timer Usado para representar um timer.
  • togglebutton Usado para representar um botão de alternância. Deve ser usado com acessibilidadeState marcado para indicar se o botão está ativado ou desativado.
  • toolbar Usada para representar uma barra de ferramentas (um contêiner de botões de ação ou componentes).
  • grid Usado com ScrollView, VirtualizedList, FlatList ou SectionList para representar uma grade. Adiciona anúncios de entrada/saída da grade ao GridView do Android.

accessibilityState

Descreve o estado atual de um componente para o usuário de tecnologia assistiva.

acessibilidadeState é um objeto. Ele contém os seguintes campos:

NOMEDESCRIÇÃOTIPOOBRIGATÓRIO
disabledIndica se o elemento está desabilitado ou não.booleanNão
selectedIndica se um elemento selecionável está selecionado ou não.booleanNão
checkedIndica o estado de um elemento verificável. Este campo pode receber uma string booleana ou "mista" para representar caixas de seleção mistas.boolean ou 'mixed'Não
busyIndica se um elemento está ocupado ou não.booleanNão
expandedIndica se um elemento expansível está atualmente expandido ou recolhido.booleanNão

Para usar, defina accessibilityState como um objeto com uma definição específica.

accessibilityValue

Representa o valor atual de um componente. Pode ser uma descrição textual do valor de um componente ou, para componentes baseados em intervalo, como controles deslizantes e barras de progresso, contém informações de intervalo (mínimo, atual e máximo).

accessibilityValue é um objeto. Ele contém os seguintes campos:

NOMEDESCRIÇÃOTIPONECESSÁRIO
minO valor mínimo do intervalo deste componente.integerObrigatório se now estiver definido.
maxO valor máximo do intervalo deste componente.integerObrigatório se now estiver definido.
nowO valor atual do intervalo deste componente.integerNão
textUma descrição textual do valor deste componente. Substituirá min, now e max se definido.integerNão

accessibilityViewIsModal [iOS]

Um valor booleano que indica se o VoiceOver deve ignorar os elementos nas visualizações que são irmãos do receptor.

Por exemplo, em uma janela que contém visualizações irmãs A e B, definir accessibilityViewIsModal como true na visualização B faz com que o VoiceOver ignore os elementos na visualização A. Por outro lado, se a visualização B contiver uma visualização filha C e você definir accessibilityViewIsModal como true na visualização C, o VoiceOver não ignora os elementos da visualização A.

accessibilityElementsHidden [iOS]

Um valor booleano que indica se os elementos de acessibilidade contidos neste elemento de acessibilidade estão ocultos.

Por exemplo, em uma janela que contém visualizações irmãs A e B, definir accessibilityElementsHidden como verdadeiro na visualização B faz com que o VoiceOver ignore os elementos na visualização B. Isso é semelhante à propriedade Android importantForAccessibility="no-hide-descendants".

aria-valuemax

Representa o valor máximo para componentes baseados em intervalo, como controles deslizantes e barras de progresso.

aria-valuemin

Representa o valor mínimo para componentes baseados em intervalo, como controles deslizantes e barras de progresso.

aria-valuenow

Representa o valor atual para componentes baseados em intervalo, como controles deslizantes e barras de progresso.

aria-valuetext

Representa a descrição textual do componente.

aria-busy

Indica que um elemento está sendo modificado e que as tecnologias assistivas podem querer esperar até que as alterações sejam concluídas antes de informar o usuário sobre a atualização.

TIPOPADRÃO
booleanfalse

aria-checked

Indica o estado de um elemento verificável. Este campo pode receber uma string booleana ou "mista" para representar caixas de seleção mistas.

TIPOPADRÃO
boolean, 'mixed'false

aria-disabled

Indica que o elemento é perceptível, mas desabilitado, portanto não é editável ou operável de outra forma.

TIPOPADRÃO
booleanfalse

aria-expanded

Indica se um elemento expansível está atualmente expandido ou recolhido.

TIPOPADRÃO
booleanfalse

aria-hidden

Indica se os elementos de acessibilidade contidos neste elemento de acessibilidade estão ocultos.

Por exemplo, numa janela que contém vistas irmãs A e B, definir aria-hidden como verdadeiro na vista B faz com que o VoiceOver ignore os elementos na vista B.

TIPOPADRÃO
booleanfalse

aria-label

Define um valor de string que rotula um elemento interativo.

TIPO
string

aria-labelledby [Android]

Identifica o elemento que rotula o elemento ao qual é aplicado. O valor de aria-labelledby deve corresponder ao nativeID do elemento relacionado:

jsx
<View>
+  <Text nativeID="formLabel">Label for Input Field</Text>
+  <TextInput aria-label="input" aria-labelledby="formLabel" />
+</View>
TIPO
string

aria-live [Android]

Indica que um elemento será atualizado e descreve os tipos de atualizações que os agentes de usuário, as tecnologias assistivas e o usuário podem esperar da região ativa.

  • off Os serviços de acessibilidade não devem anunciar alterações nesta visualização.
  • polite Os serviços de acessibilidade devem anunciar alterações nesta visão.
  • assertive Os serviços de acessibilidade devem interromper o discurso em curso para anunciar imediatamente alterações nesta visão.
TIPOPADRÃO
enum('assertive', 'off', 'polite')'off'

aria-modal [iOS]

Valor booleano que indica se o VoiceOver deve ignorar os elementos nas visualizações que são irmãos do receptor.

TIPOPADRÃO
booleanfalse

aria-selected

Indica se um elemento selecionável está selecionado ou não.

TIPO
boolean

importantForAccessibility [Android]

No caso de dois componentes de UI sobrepostos com o mesmo pai, o foco de acessibilidade padrão pode ter um comportamento imprevisível. A propriedade importantForAccessibility resolverá isso controlando se uma visualização dispara eventos de acessibilidade e se é reportada aos serviços de acessibilidade. Pode ser definido como auto, yes, no e no-hide-descendants (o último valor forçará os serviços de acessibilidade a ignorar o componente e todos os seus filhos).

jsx
<View style={styles.container}>
+  <View
+    style={[styles.layout, {backgroundColor: 'green'}]}
+    importantForAccessibility="yes">
+    <Text>First layout</Text>
+  </View>
+  <View
+    style={[styles.layout, {backgroundColor: 'yellow'}]}
+    importantForAccessibility="no-hide-descendants">
+    <Text>Second layout</Text>
+  </View>
+</View>

No exemplo acima, o layout yellow e seus descendentes são completamente invisíveis para o TalkBack e todos os outros serviços de acessibilidade. Assim, podemos usar visualizações sobrepostas com o mesmo pai sem confundir o TalkBack.

onAccessibilityEscape [iOS]

Atribua esta propriedade a uma função personalizada que será chamada quando alguém realizar o gesto de "escape", que é um gesto em forma de Z com dois dedos. Uma função de escape deve voltar hierarquicamente na interface do usuário. Isso pode significar subir ou voltar em uma hierarquia de navegação ou descartar uma interface de usuário modal. Se o elemento selecionado não tiver uma função onAccessibilityEscape, o sistema tentará percorrer a hierarquia de visualizações até encontrar uma visualização que tenha ou piscar para indicar que não foi possível encontrar uma.

onAccessibilityTap

Use esta propriedade para atribuir uma função personalizada a ser chamada quando alguém ativar um elemento acessível tocando duas vezes nele enquanto estiver selecionado.

onMagicTap [iOS]

Atribua esta propriedade a uma função personalizada que será chamada quando alguém realizar o gesto de "toque mágico", que é um toque duplo com dois dedos. Uma função de toque mágico deve executar a ação mais relevante que um usuário pode realizar em um componente. No aplicativo Telefone do iPhone, um toque mágico atende uma chamada ou encerra a atual. Se o elemento selecionado não tiver uma função onMagicTap, o sistema percorrerá a hierarquia de visualizações até encontrar uma visualização que tenha.

role

role comunica a finalidade de um componente e tem precedência sobre a propriedade accessRole.

a função pode ser uma das seguintes:

  • alert Usado quando um elemento contém texto importante a ser apresentado ao usuário.
  • button Usado quando o elemento deve ser tratado como um botão.
  • checkbox Usado quando um elemento representa uma caixa de seleção que pode ser marcada, desmarcada ou ter um estado misto de marcado.
  • combobox Usado quando um elemento representa uma caixa de combinação, que permite ao usuário selecionar entre diversas opções.
  • grid Usado com ScrollView, VirtualizedList, FlatList ou SectionList para representar uma grade. Adiciona os anúncios de entrada/saída da grade ao GridView do Android.
  • heading Usado quando um elemento atua como cabeçalho para uma seção de conteúdo (por exemplo, o título de uma barra de navegação).
  • img Usado quando o elemento deve ser tratado como uma imagem. Pode ser combinado com um botão ou link, por exemplo.
  • link Usado quando o elemento deve ser tratado como um link.
  • list Usado para identificar uma lista de itens.
  • menu Usado quando o componente é um menu de opções.
  • menubar Usada quando um componente é um contêiner de vários menus.
  • menuitem Usado para representar um item dentro de um menu.
  • none Usado quando o elemento não tem função.
  • presentation Usado quando o elemento não tem função.
  • progressbar Usado para representar um componente que indica o progresso de uma tarefa.
  • radio Usado para representar um botão de opção.
  • radiogroup Usado para representar um grupo de botões de opção.
  • scrollbar Usada para representar uma barra de rolagem.
  • searchbox Usado quando o elemento do campo de texto também deve ser tratado como um campo de pesquisa.
  • slider Usado quando um elemento pode ser "ajustado" (por exemplo, um controle deslizante).
  • spinbutton Usado para representar um botão que abre uma lista de opções.
  • summary Usado quando um elemento pode ser usado para fornecer um resumo rápido das condições atuais no aplicativo quando ele é iniciado pela primeira vez.
  • switch Usado para representar um switch que pode ser ligado e desligado.
  • tab Usado para representar uma guia.
  • tablist Usado para representar uma lista de guias.
  • timer Usado para representar um timer.
  • toolbar Usada para representar uma barra de ferramentas (um contêiner de botões de ação ou componentes).

Ações de acessibilidade

As ações de acessibilidade permitem que a tecnologia assistiva invoque programaticamente a(s) ação(ões) de um componente. Para apoiar ações de acessibilidade, um componente deve fazer duas coisas:

  • Defina a lista de ações suportadas por meio da propriedade accessibilityActions.
  • Implemente uma função onAccessibilityAction para lidar com solicitações de ação.

A propriedade accessibilityActions deve conter uma lista de objetos de ação. Cada objeto de ação deve conter os seguintes campos:

NOMETIPOOBRIGATÓRIO
namestringSim
labelstringNão

As ações representam ações padrão, como clicar em um botão ou ajustar um controle deslizante, ou ações personalizadas específicas de um determinado componente, como excluir uma mensagem de email. O campo name é obrigatório para ações padrão e personalizadas, mas o label é opcional para ações padrão.

Ao adicionar suporte para ações padrão, o name deve ser um dos seguintes:

  • 'magicTap' - apenas iOS - Enquanto o foco do VoiceOver está no componente ou dentro dele, o usuário toca duas vezes com dois dedos.
  • 'escape' - apenas iOS - Enquanto o foco do VoiceOver está no componente ou dentro dele, o usuário executou um gesto de esfregar com dois dedos (esquerda, direita, esquerda).
  • 'activate' - Ativa o componente. Este deve realizar a mesma ação com ou sem tecnologia assistiva. Ativado quando um usuário de leitor de tela toca duas vezes no componente.
  • 'increment' - Incrementa um componente ajustável. No iOS, o VoiceOver gera essa ação quando o componente tem a função de ‘ajustável’ e o usuário coloca o foco nele e desliza para cima. No Android, o TalkBack gera essa ação quando o usuário coloca o foco de acessibilidade no componente e pressiona o botão de aumentar volume.
  • 'decrement' - Diminui um componente ajustável. No iOS, o VoiceOver gera essa ação quando o componente tem a função de ‘ajustável’ e o usuário coloca o foco nele e desliza para baixo. No Android, o TalkBack gera essa ação quando o usuário coloca o foco de acessibilidade no componente e pressiona o botão de diminuir volume.
  • 'longpress' - somente Android - Esta ação é gerada quando o usuário coloca o foco de acessibilidade no componente, depois dá um toque duplo e mantém um dedo na tela. Este deve realizar a mesma ação com ou sem tecnologia assistiva.

O campo label é opcional para ações padrão e muitas vezes não é utilizado por tecnologias assistivas. Para ações customizadas, é uma string localizada contendo uma descrição da ação a ser apresentada ao usuário.

Para lidar com solicitações de ação, um componente deve implementar uma função onAccessibilityAction. O único argumento para esta função é um evento contendo o nome da ação a ser executada. O exemplo abaixo do RNTester mostra como criar um componente que define e trata diversas ações customizadas.

jsx
<View
+  accessible={true}
+  accessibilityActions={[
+    {name: 'cut', label: 'cut'},
+    {name: 'copy', label: 'copy'},
+    {name: 'paste', label: 'paste'},
+  ]}
+  onAccessibilityAction={event => {
+    switch (event.nativeEvent.actionName) {
+      case 'cut':
+        Alert.alert('Alert', 'cut action success');
+        break;
+      case 'copy':
+        Alert.alert('Alert', 'copy action success');
+        break;
+      case 'paste':
+        Alert.alert('Alert', 'paste action success');
+        break;
+    }
+  }}
+/>

Verificando se um leitor de tela está ativado

A API AccessibilityInfo permite determinar se um leitor de tela está ativo ou não. Consulte a documentação do AccessibilityInfo para obter detalhes.

Envio de eventos de acessibilidade Android [Android]

Às vezes é útil acionar um evento de acessibilidade em um componente de UI (ou seja, quando uma visualização personalizada aparece em uma tela ou define o foco de acessibilidade para uma visualização). O módulo UIManager nativo expõe um método 'sendAccessibilityEvent' para esta finalidade. São necessários dois argumentos: uma tag de visualização e um tipo de evento. Os tipos de eventos suportados são typeWindowStateChanged, typeViewFocused e typeViewClicked.

jsx
import {Platform, UIManager, findNodeHandle} from 'react-native';
+
+if (Platform.OS === 'android') {
+  UIManager.sendAccessibilityEvent(
+    findNodeHandle(this),
+    UIManager.AccessibilityEventTypes.typeViewFocused,
+  );
+}

Testando o suporte do TalkBack [Android]

Para ativar o TalkBack, acesse o aplicativo Configurações em seu dispositivo ou emulador Android. Toque em Acessibilidade e depois em TalkBack. Alterne a opção "Usar serviço" para ativá-lo ou desativá-lo.

Os emuladores Android não têm o TalkBack instalado por padrão. Você pode instalar o TalkBack no seu emulador através da Google Play Store. Certifique-se de escolher um emulador com a Google Play Store instalada. Eles estão disponíveis no Android Studio.

Você pode usar o atalho da tecla de volume para alternar o TalkBack. Para ativar o atalho da tecla de volume, vá para o aplicativo Configurações e, em seguida, Acessibilidade. Na parte superior, ative o atalho da tecla de volume.

Para usar o atalho da tecla de volume, pressione ambas as teclas de volume por 3 segundos para iniciar uma ferramenta de acessibilidade.

Além disso, se preferir, você pode alternar o TalkBack por meio da linha de comando com:

# desabilitado
+adb shell settings put secure enabled_accessibility_services com.android.talkback/com.google.android.marvin.talkback.TalkBackService
+
+# habilitado
+adb shell settings put secure enabled_accessibility_services com.google.android.marvin.talkback/com.google.android.marvin.talkback.TalkBackService

Testando o suporte do VoiceOver [iOS]

Para ativar o VoiceOver em seu dispositivo iOS ou iPadOS, acesse o aplicativo Ajustes, toque em Geral e em Acessibilidade. Lá você encontrará muitas ferramentas disponíveis para as pessoas permitirem que seus dispositivos sejam mais utilizáveis, incluindo VoiceOver. Para ativar o VoiceOver, toque em VoiceOver em “Visão” e alterne o botão que aparece na parte superior.

Na parte inferior das configurações de acessibilidade, há um “Atalho de acessibilidade”. Você pode usar isso para alternar o VoiceOver clicando três vezes no botão Início.

O VoiceOver não está disponível por meio do simulador, mas você pode usar o Accessibility Inspector do Xcode para usar o macOS VoiceOver por meio de um aplicativo. Observe que é sempre melhor testar com um dispositivo, pois o VoiceOver do macOS pode resultar em experiências variadas.

Recursos adicionais

`,139),n=[o];function l(d,r,p,h,c,k){return e(),s("div",null,n)}const g=a(t,[["render",l]]);export{m as __pageData,g as default}; diff --git a/vitepress/docs/.vitepress/dist/assets/docs_accessibility.md.BwWJ5VBO.lean.js b/vitepress/docs/.vitepress/dist/assets/docs_accessibility.md.BwWJ5VBO.lean.js new file mode 100644 index 0000000..4c5ddd7 --- /dev/null +++ b/vitepress/docs/.vitepress/dist/assets/docs_accessibility.md.BwWJ5VBO.lean.js @@ -0,0 +1 @@ +import{_ as a,c as s,o as e,a4 as i}from"./chunks/framework.nQaBHiNx.js";const m=JSON.parse('{"title":"Acessibilidade","description":"","frontmatter":{},"headers":[],"relativePath":"docs/accessibility.md","filePath":"docs/accessibility.md"}'),t={name:"docs/accessibility.md"},o=i("",139),n=[o];function l(d,r,p,h,c,k){return e(),s("div",null,n)}const g=a(t,[["render",l]]);export{m as __pageData,g as default}; diff --git a/vitepress/docs/.vitepress/dist/assets/docs_animations.md.ByV0vIgI.js b/vitepress/docs/.vitepress/dist/assets/docs_animations.md.ByV0vIgI.js new file mode 100644 index 0000000..53e4c97 --- /dev/null +++ b/vitepress/docs/.vitepress/dist/assets/docs_animations.md.ByV0vIgI.js @@ -0,0 +1,391 @@ +import{_ as s,c as i,o as a,a4 as n}from"./chunks/framework.nQaBHiNx.js";const e="/assets/294185554-0a53d571-a6d4-4d9c-8473-e1a497cb4771.BlrqqiBi.png",t="/assets/294203476-c38ee8dd-d990-491b-ac01-5940b5237aeb.BC4ZRAsI.png",p="/assets/294206249-2c01dacd-b0e9-4160-8f63-01d73c758f9b.VTgm5Fcw.png",l="/assets/294212416-ca6367a9-3d9d-46f2-bb61-8683320171dc.Daxz8nah.png",u=JSON.parse('{"title":"Animações","description":"","frontmatter":{},"headers":[],"relativePath":"docs/animations.md","filePath":"docs/animations.md"}'),h={name:"docs/animations.md"},k=n(`

Animações

As animações são muito importantes para criar uma ótima experiência do usuário. Objetos estacionários devem superar a inércia à medida que começam a se mover. Objetos em movimento têm impulso e raramente param imediatamente. As animações permitem transmitir movimentos fisicamente verossímeis em sua interface.

React Native fornece dois sistemas de animação complementares: Animated para controle granular e interativo de valores específicos e LayoutAnimation para transações de layout global animadas.

Animated API

A API Animated foi projetada para expressar de forma concisa uma ampla variedade de padrões interessantes de animação e interação com muito desempenho. Animated concentra-se em relacionamentos declarativos entre entradas e saídas, com transformações configuráveis entre elas e métodos de start/stop para controlar a execução da animação baseada em tempo.

Animated exporta seis tipos de componentes animáveis: View, Text, Image, ScrollView, FlatList e SectionList, mas você também pode criar o seu próprio usando Animated.createAnimatedComponent().

Por exemplo, uma visualização de contêiner que aparece gradualmente quando é montada pode ter esta aparência:

tsx
import React, {useRef, useEffect} from 'react';
+import {Animated, Text, View} from 'react-native';
+import type {PropsWithChildren} from 'react';
+import type {ViewStyle} from 'react-native';
+
+type FadeInViewProps = PropsWithChildren<{style: ViewStyle}>;
+
+const FadeInView: React.FC<FadeInViewProps> = props => {
+  const fadeAnim = useRef(new Animated.Value(0)).current; // Valor inicial para opacidade: 0
+
+  useEffect(() => {
+    Animated.timing(fadeAnim, {
+      toValue: 1,
+      duration: 10000,
+      useNativeDriver: true,
+    }).start();
+  }, [fadeAnim]);
+
+  return (
+    <Animated.View // View especial animável
+      style={{
+        ...props.style,
+        opacity: fadeAnim, // Vincular opacidade ao valor animado
+      }}>
+      {props.children}
+    </Animated.View>
+  );
+};
+
+// Você pode então usar seu \`FadeInView\` no lugar de um \`View\` em seus componentes:
+export default () => {
+  return (
+    <View
+      style={{
+        flex: 1,
+        alignItems: 'center',
+        justifyContent: 'center',
+      }}>
+      <FadeInView
+        style={{
+          width: 250,
+          height: 50,
+          backgroundColor: 'powderblue',
+        }}>
+        <Text style={{fontSize: 28, textAlign: 'center', margin: 10}}>
+          Fading in
+        </Text>
+      </FadeInView>
+    </View>
+  );
+};

image

Vamos analisar o que está acontecendo aqui. No construtor FadeInView, um novo Animated.Value chamado fadeAnim é inicializado como parte do estado. A propriedade de opacidade na View é mapeada para esse valor animado. Nos bastidores, o valor numérico é extraído e usado para definir a opacidade.

Quando o componente é montado, a opacidade é definida como 0. Em seguida, uma animação de atenuação é iniciada no valor animado fadeAnim, que atualizará todos os seus mapeamentos dependentes (neste caso, apenas a opacidade) em cada quadro à medida que o valor for animado para o valor final de 1.

Isso é feito de maneira otimizada e mais rápida do que chamar setState e renderizar novamente. Como toda a configuração é declarativa, poderemos implementar otimizações adicionais que serializam a configuração e executam a animação em um thread de alta prioridade.

Configurando animações

As animações são altamente configuráveis. Funções de atenuação personalizadas e predefinidas, atrasos, durações, fatores de decaimento, constantes de mola e muito mais podem ser ajustados dependendo do tipo de animação.

Animated fornece vários tipos de animação, sendo o mais comumente usado Animated.timing(). Ele suporta a animação de um valor ao longo do tempo usando uma das várias funções de atenuação predefinidas, ou você pode usar a sua própria. As funções de atenuação são normalmente usadas em animação para transmitir aceleração e desaceleração graduais de objetos.

Por padrão, o tempo usará uma curva easyInOut que transmite aceleração gradual até a velocidade máxima e termina desacelerando gradualmente até parar. Você pode especificar uma função de atenuação diferente passando um parâmetro de easing. A durationpersonalizada ou mesmo umdelay\` antes do início da animação também é suportada.

Por exemplo, se quisermos criar uma animação de 2 segundos de um objeto que recua ligeiramente antes de se mover para sua posição final:

js
Animated.timing(this.state.xPosition, {
+  toValue: 100,
+  easing: Easing.back(),
+  duration: 2000,
+  useNativeDriver: true,
+}).start();

Dê uma olhada na seção Configurando animações da referência da API animada para saber mais sobre todos os parâmetros de configuração suportados pelas animações integradas.

Compondo animações

As animações podem ser combinadas e reproduzidas em sequência ou em paralelo. As animações sequenciais podem ser reproduzidas imediatamente após o término da animação anterior ou podem começar após um atraso especificado. A API Animated fornece vários métodos, como sequence() e delay(), cada um dos quais usa uma matriz de animações para ser executado e chama automaticamente start()/stop() conforme necessário.

Por exemplo, a animação a seguir para e depois retorna enquanto gira em paralelo:

jsx
Animated.sequence([
+  // decair, então o spring começa e gira
+  Animated.decay(position, {
+    // desce até parar
+    velocity: {x: gestureState.vx, y: gestureState.vy}, // velocidade da liberação do gesto
+    deceleration: 0.997,
+    useNativeDriver: true,
+  }),
+  Animated.parallel([
+    // após a decadência, em paralelo:
+    Animated.spring(position, {
+      toValue: {x: 0, y: 0}, // voltar para começar
+      useNativeDriver: true,
+    }),
+    Animated.timing(twirl, {
+      // e girar
+      toValue: 360,
+      useNativeDriver: true,
+    }),
+  ]),
+]).start(); // iniciar o grupo de sequência

Se uma animação for parada ou interrompida, todas as outras animações do grupo também serão interrompidas. Animated.parallel tem uma opção stopTogether que pode ser definida como false para desabilitar isso.

Você pode encontrar uma lista completa de métodos de composição na seção Compondo animações da referência da API Animated.

Combinando valores animados

Você pode combinar dois valores animados por meio de adição, multiplicação, divisão ou módulo para criar um novo valor animado.

Existem alguns casos em que um valor animado precisa inverter outro valor animado para cálculo. Um exemplo é inverter uma escala (2x -> 0,5x):

jsx
const a = new Animated.Value(1);
+const b = Animated.divide(1, a);
+
+Animated.spring(a, {
+  toValue: 2,
+  useNativeDriver: true,
+}).start();

Interpolação

Cada propriedade pode ser executada primeiro por meio de uma interpolação. Uma interpolação mapeia intervalos de entrada para intervalos de saída, normalmente usando uma interpolação linear, mas também oferece suporte a funções de atenuação. Por padrão, ele extrapolará a curva além dos intervalos fornecidos, mas você também poderá limitar o valor de saída.

Um mapeamento básico para converter um intervalo de 0-1 em um intervalo de 0-100 seria:

js
value.interpolate({
+  inputRange: [0, 1],
+  outputRange: [0, 100],
+});

Por exemplo, você pode querer pensar em seu Animated.Value como indo de 0 a 1, mas anime a posição de 150px para 0px e a opacidade de 0 a 1. Isso pode ser feito modificando o style do exemplo acima, assim:

jsx
  style={{
+    opacity: this.state.fadeAnim, // Vincula diretamente
+    transform: [{
+      translateY: this.state.fadeAnim.interpolate({
+        inputRange: [0, 1],
+        outputRange: [150, 0]  // 0 : 150, 0.5 : 75, 1 : 0
+      }),
+    }],
+  }}

interpolate() também suporta vários segmentos de intervalo, o que é útil para definir zonas mortas e outros truques úteis. Por exemplo, para obter um relacionamento de negação em -300 que vai para 0 em -100, depois volta para 1 em 0 e depois volta para zero em 100 seguido por uma zona morta que permanece em 0 para tudo além disso, você poderia fazer:

js
value.interpolate({
+  inputRange: [-300, -100, 0, 100, 101],
+  outputRange: [300, 0, 1, 0, 0],
+});

O que seria mapeado assim:

Input | Output
+------|-------
+  -400|    450
+  -300|    300
+  -200|    150
+  -100|      0
+   -50|    0.5
+     0|      1
+    50|    0.5
+   100|      0
+   101|      0
+   200|      0

interpolate() também suporta mapeamento para strings, permitindo animar cores e também valores com unidades. Por exemplo, se você quiser animar uma rotação você poderia fazer:

js
value.interpolate({
+  inputRange: [0, 360],
+  outputRange: ['0deg', '360deg'],
+});

interpolate() também suporta funções de atenuação arbitrárias, muitas das quais já estão implementadas no módulo Easing. interpolate() também possui comportamento configurável para extrapolar o outputRange. Você pode definir a extrapolação definindo as opções extrapolate, extrapolateLeft ou extrapolateRight. O valor padrão é extend, mas você pode usar clamp para evitar que o valor de saída exceda outputRange.

Rastreando valores dinâmicos

Os valores animados também podem rastrear outros valores definindo toValue de uma animação como outro valor animado em vez de um número simples. Por exemplo, uma animação "Chat Heads" como a usada pelo Messenger no Android poderia ser implementada com um spring() fixado em outro valor animado, ou com timing() e uma duration de 0 para rastreamento rígido. Também podem ser compostos com interpolações:

jsx
Animated.spring(follower, {toValue: leader}).start();
+Animated.timing(opacity, {
+  toValue: pan.x.interpolate({
+    inputRange: [0, 300],
+    outputRange: [1, 0],
+    useNativeDriver: true,
+  }),
+}).start();

Os valores animados do leader e do follower seriam implementados usando Animated.ValueXY(). ValueXY é uma maneira prática de lidar com interações 2D, como panorâmica ou arrastamento. É um wrapper básico que contém duas instâncias de Animated.Value e algumas funções auxiliares que as chamam, tornando ValueXY um substituto imediato para Value em muitos casos. Isso nos permite rastrear os valores de x e y no exemplo acima.

Gestos de rastreamento

Gestos, como movimento panorâmico ou rolagem, e outros eventos podem ser mapeados diretamente para valores animados usando Animated.event. Isto é feito com uma sintaxe de mapa estruturada para que os valores possam ser extraídos de objetos de eventos complexos. O primeiro nível é uma matriz para permitir o mapeamento entre vários argumentos, e essa matriz contém objetos aninhados.

Por exemplo, ao trabalhar com gestos de rolagem horizontal, você faria o seguinte para mapear event.nativeEvent.contentOffset.x para scrollX (um Animated.Value):

jsx
 onScroll={Animated.event(
+   // scrollX = e.nativeEvent.contentOffset.x
+   [{nativeEvent: {
+        contentOffset: {
+          x: scrollX
+        }
+      }
+    }]
+ )}

O exemplo a seguir implementa um carrossel de rolagem horizontal onde os indicadores de posição de rolagem são animados usando o Animated.event usado no ScrollView

ScrollView com exemplo de evento animado

jsx
import React, {useRef} from 'react';
+import {
+  SafeAreaView,
+  ScrollView,
+  Text,
+  StyleSheet,
+  View,
+  ImageBackground,
+  Animated,
+  useWindowDimensions,
+} from 'react-native';
+
+const images = new Array(6).fill(
+  'https://images.unsplash.com/photo-1556740749-887f6717d7e4',
+);
+
+const App = () => {
+  const scrollX = useRef(new Animated.Value(0)).current;
+
+  const {width: windowWidth} = useWindowDimensions();
+
+  return (
+    <SafeAreaView style={styles.container}>
+      <View style={styles.scrollContainer}>
+        <ScrollView
+          horizontal={true}
+          pagingEnabled
+          showsHorizontalScrollIndicator={false}
+          onScroll={Animated.event([
+            {
+              nativeEvent: {
+                contentOffset: {
+                  x: scrollX,
+                },
+              },
+            },
+          ])}
+          scrollEventThrottle={1}>
+          {images.map((image, imageIndex) => {
+            return (
+              <View style={{width: windowWidth, height: 250}} key={imageIndex}>
+                <ImageBackground source={{uri: image}} style={styles.card}>
+                  <View style={styles.textContainer}>
+                    <Text style={styles.infoText}>
+                      {'Image - ' + imageIndex}
+                    </Text>
+                  </View>
+                </ImageBackground>
+              </View>
+            );
+          })}
+        </ScrollView>
+        <View style={styles.indicatorContainer}>
+          {images.map((image, imageIndex) => {
+            const width = scrollX.interpolate({
+              inputRange: [
+                windowWidth * (imageIndex - 1),
+                windowWidth * imageIndex,
+                windowWidth * (imageIndex + 1),
+              ],
+              outputRange: [8, 16, 8],
+              extrapolate: 'clamp',
+            });
+            return (
+              <Animated.View
+                key={imageIndex}
+                style={[styles.normalDot, {width}]}
+              />
+            );
+          })}
+        </View>
+      </View>
+    </SafeAreaView>
+  );
+};
+
+const styles = StyleSheet.create({
+  container: {
+    flex: 1,
+    alignItems: 'center',
+    justifyContent: 'center',
+  },
+  scrollContainer: {
+    height: 300,
+    alignItems: 'center',
+    justifyContent: 'center',
+  },
+  card: {
+    flex: 1,
+    marginVertical: 4,
+    marginHorizontal: 16,
+    borderRadius: 5,
+    overflow: 'hidden',
+    alignItems: 'center',
+    justifyContent: 'center',
+  },
+  textContainer: {
+    backgroundColor: 'rgba(0,0,0, 0.7)',
+    paddingHorizontal: 24,
+    paddingVertical: 8,
+    borderRadius: 5,
+  },
+  infoText: {
+    color: 'white',
+    fontSize: 16,
+    fontWeight: 'bold',
+  },
+  normalDot: {
+    height: 8,
+    width: 8,
+    borderRadius: 4,
+    backgroundColor: 'silver',
+    marginHorizontal: 4,
+  },
+  indicatorContainer: {
+    flexDirection: 'row',
+    alignItems: 'center',
+    justifyContent: 'center',
+  },
+});
+
+export default App;

image

Ao usar o PanResponder, você pode usar o código a seguir para extrair as posições x e y de gestureState.dx e gestureState.dy. Usamos um null na primeira posição do array, pois estamos interessados apenas no segundo argumento passado para o manipulador PanResponder, que é o gestureState.

jsx
onPanResponderMove={Animated.event(
+  [null, // ignora o evento nativo
+  // extraia dx e dy do gestureState
+  // como 'pan.x = gestureState.dx, pan.y = gestureState.dy'
+  {dx: pan.x, dy: pan.y}
+])}

PanResponder com exemplo de evento animado

jsx
import React, {useRef} from 'react';
+import {Animated, View, StyleSheet, PanResponder, Text} from 'react-native';
+
+const App = () => {
+  const pan = useRef(new Animated.ValueXY()).current;
+  const panResponder = useRef(
+    PanResponder.create({
+      onMoveShouldSetPanResponder: () => true,
+      onPanResponderMove: Animated.event([null, {dx: pan.x, dy: pan.y}]),
+      onPanResponderRelease: () => {
+        Animated.spring(pan, {
+          toValue: {x: 0, y: 0},
+          useNativeDriver: true,
+        }).start();
+      },
+    }),
+  ).current;
+
+  return (
+    <View style={styles.container}>
+      <Text style={styles.titleText}>Drag & Release this box!</Text>
+      <Animated.View
+        style={{
+          transform: [{translateX: pan.x}, {translateY: pan.y}],
+        }}
+        {...panResponder.panHandlers}>
+        <View style={styles.box} />
+      </Animated.View>
+    </View>
+  );
+};
+
+const styles = StyleSheet.create({
+  container: {
+    flex: 1,
+    alignItems: 'center',
+    justifyContent: 'center',
+  },
+  titleText: {
+    fontSize: 14,
+    lineHeight: 24,
+    fontWeight: 'bold',
+  },
+  box: {
+    height: 150,
+    width: 150,
+    backgroundColor: 'blue',
+    borderRadius: 5,
+  },
+});
+
+export default App;

image

Respondendo ao valor atual da animação

Você pode perceber que não há uma maneira clara de ler o valor atual durante a animação. Isso ocorre porque o valor só pode ser conhecido no tempo de execução nativo devido a otimizações. Se você precisar executar JavaScript em resposta ao valor atual, existem duas abordagens:

  • spring.stopAnimation(callback) interromperá a animação e invocará o retorno de chamada com o valor final. Isto é útil ao fazer transições de gestos.
  • spring.addListener(callback) invocará o retorno de chamada de forma assíncrona enquanto a animação estiver em execução, fornecendo um valor recente. Isso é útil para acionar mudanças de estado, por exemplo, encaixar um bobble em uma nova opção conforme o usuário o arrasta para mais perto, porque essas mudanças de estado maiores são menos sensíveis a alguns quadros de atraso em comparação com gestos contínuos como o movimento panorâmico, que precisa ser executado a 60 fps.

Animated foi projetado para ser totalmente serializável para que as animações possam ser executadas com alto desempenho, independentemente do loop de eventos normal do JavaScript. Isso influencia a API, então tenha isso em mente quando parecer um pouco mais complicado fazer algo em comparação com um sistema totalmente síncrono. Confira Animated.Value.addListener como uma forma de contornar algumas dessas limitações, mas use-o com moderação, pois pode ter implicações de desempenho no futuro.

Usando o driver nativo

A API Animated foi projetada para ser serializável. Ao usar o driver nativo, enviamos tudo sobre a animação para o nativo antes de iniciá-la, permitindo que o código nativo execute a animação no thread da UI sem ter que passar pela ponte em cada quadro. Depois que a animação for iniciada, o thread JS poderá ser bloqueado sem afetar a animação.

O uso do driver nativo para animações normais pode ser feito definindo useNativeDriver: true na configuração da animação ao iniciá-la. Animações sem uma propriedade useNativeDriver serão padronizadas como false por motivos legados, mas emitirão um aviso (e erro de verificação de digitação no TypeScript).

js
Animated.timing(this.state.animatedValue, {
+  toValue: 1,
+  duration: 500,
+  useNativeDriver: true, // <-- Seta isso como true
+}).start();

Os valores animados são compatíveis apenas com um driver, portanto, se você usar o driver nativo ao iniciar uma animação em um valor, certifique-se de que cada animação nesse valor também use o driver nativo.

O driver nativo também funciona com Animated.event. Isso é especialmente útil para animações que seguem a posição de rolagem, pois sem o driver nativo, a animação sempre executará um quadro atrás do gesto devido à natureza assíncrona do React Native.

jsx
<Animated.ScrollView // <-- Use o wrapper ScrollView animado
+  scrollEventThrottle={1} // <--Use 1 aqui para garantir que nenhum evento seja perdido
+  onScroll={Animated.event(
+    [
+      {
+        nativeEvent: {
+          contentOffset: {y: this.state.animatedValue},
+        },
+      },
+    ],
+    {useNativeDriver: true}, // <-- Seta isso como true
+  )}>
+  {content}
+</Animated.ScrollView>

Você pode ver o driver nativo em ação executando o aplicativo RNTester e carregando o exemplo animado nativo. Você também pode dar uma olhada no código-fonte para saber como esses exemplos foram produzidos.

Ressalvas

Nem tudo o que você pode fazer com o Animated é atualmente compatível com o driver nativo. A principal limitação é que você só pode animar propriedades que não sejam de layout: coisas como transformation e opacity funcionarão, mas Flexbox e propriedades de posição não. Ao usar Animated.event, ele funcionará apenas com eventos diretos e não com eventos "borbulhantes". Isso significa que ele não funciona com PanResponder, mas funciona com coisas como ScrollView#onScroll.

Quando uma animação está em execução, ela pode impedir que os componentes VirtualizedList renderizem mais linhas. Se você precisar executar uma animação longa ou em loop enquanto o usuário percorre uma lista, você pode usar isInteraction: false na configuração da sua animação para evitar esse problema.

Tenha em mente

Ao usar estilos de transformação, como rotateY, rotateX e outros, certifique-se de que a perspectiva do estilo de transformação esteja em vigor. No momento, algumas animações podem não ser renderizadas no Android sem ele. Exemplo abaixo.

jsx
<Animated.View
+  style={{
+    transform: [
+      {scale: this.state.scale},
+      {rotateY: this.state.rotateY},
+      {perspective: 1000}, // sem esta linha esta animação não será renderizada no Android enquanto funciona bem no iOS
+    ],
+  }}
+/>

Exemplos adicionais

O aplicativo RNTester possui vários exemplos de Animated em uso:

API LayoutAnimation

LayoutAnimation permite configurar globalmente, criar e atualizar animações que serão usadas para todas as visualizações no próximo ciclo de renderização/layout. Isto é útil para fazer atualizações de layout do Flexbox sem se preocupar em medir ou calcular propriedades específicas para animá-las diretamente, e é especialmente útil quando alterações de layout podem afetar ancestrais, por exemplo, uma expansão "veja mais" que também aumenta o tamanho do pai e empurra para baixo a linha abaixo, o que de outra forma exigiria coordenação explícita entre os componentes para animá-los todos em sincronia.

Observe que, embora o LayoutAnimation seja muito poderoso e possa ser bastante útil, ele fornece muito menos controle do que o Animated e outras bibliotecas de animação, portanto, talvez seja necessário usar outra abordagem se não conseguir que o LayoutAnimation faça o que deseja.

Observe que para que isso funcione no Android, você precisa definir os seguintes sinalizadores via UIManager:

java
UIManager.setLayoutAnimationEnabledExperimental(true);
jsx
import React from 'react';
+import {
+  NativeModules,
+  LayoutAnimation,
+  Text,
+  TouchableOpacity,
+  StyleSheet,
+  View,
+} from 'react-native';
+
+const {UIManager} = NativeModules;
+
+UIManager.setLayoutAnimationEnabledExperimental &&
+  UIManager.setLayoutAnimationEnabledExperimental(true);
+
+export default class App extends React.Component {
+  state = {
+    w: 100,
+    h: 100,
+  };
+
+  _onPress = () => {
+    // Animate the update
+    LayoutAnimation.spring();
+    this.setState({w: this.state.w + 15, h: this.state.h + 15});
+  };
+
+  render() {
+    return (
+      <View style={styles.container}>
+        <View
+          style={[styles.box, {width: this.state.w, height: this.state.h}]}
+        />
+        <TouchableOpacity onPress={this._onPress}>
+          <View style={styles.button}>
+            <Text style={styles.buttonText}>Press me!</Text>
+          </View>
+        </TouchableOpacity>
+      </View>
+    );
+  }
+}
+
+const styles = StyleSheet.create({
+  container: {
+    flex: 1,
+    alignItems: 'center',
+    justifyContent: 'center',
+  },
+  box: {
+    width: 200,
+    height: 200,
+    backgroundColor: 'red',
+  },
+  button: {
+    backgroundColor: 'black',
+    paddingHorizontal: 20,
+    paddingVertical: 15,
+    marginTop: 15,
+  },
+  buttonText: {
+    color: '#fff',
+    fontWeight: 'bold',
+  },
+});

image

Este exemplo usa um valor predefinido, você pode personalizar as animações conforme necessário, consulte LayoutAnimation.js para obter mais informações.

Notas Adicionais

requestAnimationFrame

requestAnimationFrame é um polyfill do navegador com o qual você deve estar familiarizado. Ele aceita uma função como seu único argumento e chama essa função antes da próxima repintura. É um elemento essencial para animações que sustenta todas as APIs de animação baseadas em JavaScript. Em geral, você não precisa chamar isso sozinho - as APIs de animação gerenciarão as atualizações de quadros para você.

setNativeProps

Conforme mencionado na seção Manipulação Direta, setNativeProps nos permite modificar propriedades de componentes com suporte nativo (componentes que são realmente apoiados por visualizações nativas, ao contrário dos componentes compostos) diretamente, sem ter que setState renderizar novamente a hierarquia de componentes.

Poderíamos usar isso no exemplo Rebound para atualizar a escala - isso pode ser útil se o componente que estamos atualizando estiver profundamente aninhado e não tiver sido otimizado com shouldComponentUpdate.

Se você encontrar suas animações com queda de quadros (desempenho abaixo de 60 quadros por segundo), use setNativeProps ou shouldComponentUpdate para otimizá-las. Ou você pode executar as animações no thread da UI em vez do thread JavaScript com a opção useNativeDriver. Você também pode adiar qualquer trabalho computacional intensivo até que as animações sejam concluídas, usando o InteractionManager. Você pode monitorar a taxa de quadros usando a ferramenta "FPS Monitor" do menu de desenvolvimento do aplicativo.

',95),E=[k];function r(d,o,g,c,y,m){return a(),i("div",null,E)}const C=s(h,[["render",r]]);export{u as __pageData,C as default}; diff --git a/vitepress/docs/.vitepress/dist/assets/docs_animations.md.ByV0vIgI.lean.js b/vitepress/docs/.vitepress/dist/assets/docs_animations.md.ByV0vIgI.lean.js new file mode 100644 index 0000000..5030c57 --- /dev/null +++ b/vitepress/docs/.vitepress/dist/assets/docs_animations.md.ByV0vIgI.lean.js @@ -0,0 +1 @@ +import{_ as s,c as i,o as a,a4 as n}from"./chunks/framework.nQaBHiNx.js";const e="/assets/294185554-0a53d571-a6d4-4d9c-8473-e1a497cb4771.BlrqqiBi.png",t="/assets/294203476-c38ee8dd-d990-491b-ac01-5940b5237aeb.BC4ZRAsI.png",p="/assets/294206249-2c01dacd-b0e9-4160-8f63-01d73c758f9b.VTgm5Fcw.png",l="/assets/294212416-ca6367a9-3d9d-46f2-bb61-8683320171dc.Daxz8nah.png",u=JSON.parse('{"title":"Animações","description":"","frontmatter":{},"headers":[],"relativePath":"docs/animations.md","filePath":"docs/animations.md"}'),h={name:"docs/animations.md"},k=n("",95),E=[k];function r(d,o,g,c,y,m){return a(),i("div",null,E)}const C=s(h,[["render",r]]);export{u as __pageData,C as default}; diff --git a/vitepress/docs/.vitepress/dist/assets/docs_app-extensions.md.CvbwvPY8.js b/vitepress/docs/.vitepress/dist/assets/docs_app-extensions.md.CvbwvPY8.js new file mode 100644 index 0000000..5d4bd3b --- /dev/null +++ b/vitepress/docs/.vitepress/dist/assets/docs_app-extensions.md.CvbwvPY8.js @@ -0,0 +1 @@ +import{_ as e,c as a,o as s,a4 as o}from"./chunks/framework.nQaBHiNx.js";const x=JSON.parse('{"title":"Extensões de aplicativos","description":"","frontmatter":{},"headers":[],"relativePath":"docs/app-extensions.md","filePath":"docs/app-extensions.md"}'),t={name:"docs/app-extensions.md"},i=o('

Extensões de aplicativos

As extensões de aplicativo permitem fornecer funcionalidade e conteúdo personalizados fora do aplicativo principal. Existem diferentes tipos de extensões de aplicativos no iOS, e todas elas são abordadas no Guia de programação de extensões de aplicativos. Neste guia, abordaremos brevemente como você pode aproveitar as vantagens das extensões de aplicativos no iOS.

Uso de memória em extensões

Como essas extensões são carregadas fora da sandbox normal do aplicativo, é altamente provável que várias dessas extensões de aplicativo sejam carregadas simultaneamente. Como seria de esperar, essas extensões têm pequenos limites de uso de memória. Tenha isso em mente ao desenvolver suas extensões de aplicativo. É sempre altamente recomendável testar seu aplicativo em um dispositivo real, ainda mais ao desenvolver extensões de aplicativo: com muita frequência, os desenvolvedores descobrem que sua extensão funciona bem no simulador iOS, apenas para receber relatórios de usuários de que sua extensão não está carregando em dispositivos reais.

É altamente recomendável que você assista à palestra de Conrad Kramer sobre Uso de memória em extensões para saber mais sobre esse tópico.

Widget Today

O limite de memória de um widget Hoje é de 16 MB. Acontece que as implementações do widget Today usando React Native podem não funcionar de maneira confiável porque o uso de memória tende a ser muito alto. Você pode saber se o widget Today está excedendo o limite de memória se exibir a mensagem 'Não é possível carregar':

image

Sempre teste suas extensões de aplicativo em um dispositivo real, mas esteja ciente de que isso pode não ser suficiente, especialmente ao lidar com o widget Today. As compilações configuradas para depuração têm maior probabilidade de exceder os limites de memória, enquanto as compilações configuradas para versão não falham imediatamente. É altamente recomendável que você use Instrumentos do Xcode para analisar seu uso de memória no mundo real, pois é muito provável que sua compilação configurada para lançamento está muito próxima do limite de 16 MB. Em situações como essas, você pode ultrapassar rapidamente o limite de 16 MB executando operações comuns, como buscar dados de uma API.

Para experimentar os limites das implementações do widget React Native Today, tente estender o projeto de exemplo em react-native-today-widget.

Outras extensões de aplicativos

Outros tipos de extensões de aplicativo têm limites de memória maiores que o widget Today. Por exemplo, as extensões de teclado personalizado são limitadas a 48 MB e as extensões de compartilhamento são limitadas a 120 MB. Implementar essas extensões de aplicativo com React Native é mais viável. Um exemplo de prova de conceito é react-native-ios-share-extension.

',12),r=[i];function n(d,m,l,p,c,u){return s(),a("div",null,r)}const h=e(t,[["render",n]]);export{x as __pageData,h as default}; diff --git a/vitepress/docs/.vitepress/dist/assets/docs_app-extensions.md.CvbwvPY8.lean.js b/vitepress/docs/.vitepress/dist/assets/docs_app-extensions.md.CvbwvPY8.lean.js new file mode 100644 index 0000000..9ecc439 --- /dev/null +++ b/vitepress/docs/.vitepress/dist/assets/docs_app-extensions.md.CvbwvPY8.lean.js @@ -0,0 +1 @@ +import{_ as e,c as a,o as s,a4 as o}from"./chunks/framework.nQaBHiNx.js";const x=JSON.parse('{"title":"Extensões de aplicativos","description":"","frontmatter":{},"headers":[],"relativePath":"docs/app-extensions.md","filePath":"docs/app-extensions.md"}'),t={name:"docs/app-extensions.md"},i=o("",12),r=[i];function n(d,m,l,p,c,u){return s(),a("div",null,r)}const h=e(t,[["render",n]]);export{x as __pageData,h as default}; diff --git a/vitepress/docs/.vitepress/dist/assets/docs_build-speed.md.DV6MDRQw.js b/vitepress/docs/.vitepress/dist/assets/docs_build-speed.md.DV6MDRQw.js new file mode 100644 index 0000000..56678cb --- /dev/null +++ b/vitepress/docs/.vitepress/dist/assets/docs_build-speed.md.DV6MDRQw.js @@ -0,0 +1,53 @@ +import{_ as s,c as a,o as i,a4 as e}from"./chunks/framework.nQaBHiNx.js";const F=JSON.parse('{"title":"Acelerando sua fase de construção","description":"","frontmatter":{},"headers":[],"relativePath":"docs/build-speed.md","filePath":"docs/build-speed.md"}'),n={name:"docs/build-speed.md"},o=e(`

Acelerando sua fase de construção

Construir seu aplicativo React Native pode ser caro e levar vários minutos do tempo dos desenvolvedores. Isso pode ser problemático à medida que seu projeto cresce e geralmente em organizações maiores com vários desenvolvedores React Native.

Para mitigar esse impacto no desempenho, esta página compartilha algumas sugestões sobre como melhorar o tempo de construção.

INFORMAÇÕES

Se você notar um tempo de construção mais lento com a nova arquitetura no Android, recomendamos atualizar para o React Native 0.71

Crie apenas uma ABI durante o desenvolvimento (somente Android)

Ao construir seu aplicativo Android localmente, por padrão você constrói todas as 4 interfaces binárias de aplicativo (ABIs): armeabi-v7a, arm64-v8a, x86 e x86_64.

No entanto, você provavelmente não precisará compilar todos eles se estiver compilando localmente e testando seu emulador ou em um dispositivo físico.

Isso deve reduzir o tempo de construção nativo em um fator de aproximadamente 75%.

Se estiver usando o React Native CLI, você pode adicionar o sinalizador --active-arch-only ao comando run-Android. Este sinalizador garantirá que a ABI correta seja obtida no emulador em execução ou no telefone conectado. Para confirmar se essa abordagem está funcionando bem, você verá uma mensagem como info Detected Architectures arm64-v8a no console.

bash
$ yarn react-native run-android --active-arch-only
+
+[ ... ]
+info Running jetifier to migrate libraries to AndroidX. You can disable it using "--no-jetifier" flag.
+Jetifier found 1037 file(s) to forward-jetify. Using 32 workers...
+info JS server already running.
+info Detected architectures arm64-v8a
+info Installing the app...

Este mecanismo depende da propriedade reactNativeArchitectures do Gradle.

Portanto, se você estiver compilando diretamente com o Gradle na linha de comando e sem a CLI, poderá especificar a ABI que deseja compilar da seguinte maneira:

bash
$ ./gradlew :app:assembleDebug -PreactNativeArchitectures=x86,x86_64

Isso pode ser útil se você deseja construir seu aplicativo Android em um CI e usar uma matriz para paralelizar a construção das diferentes arquiteturas.

Se desejar, você também pode substituir esse valor localmente, usando o arquivo gradle.properties que você possui na pasta de nível superior do seu projeto:

bash
# Use esta propriedade para especificar qual arquitetura você deseja construir.
+# Você também pode substituí-lo na CLI usando
+# ./gradlew <task> -PreactNativeArchitectures=x86_64
+reactNativeArchitectures=armeabi-v7a,arm64-v8a,x86,x86_64

Depois de criar uma versão de lançamento do seu aplicativo, não se esqueça de remover esses sinalizadores, pois deseja criar um pacote apk/app que funcione para todas as ABIs e não apenas para aquela que você está usando em seu fluxo de trabalho de desenvolvimento diário.

Use um cache do compilador

Se você estiver executando compilações nativas frequentes (C++ ou Objective-C), poderá se beneficiar do uso de um cache do compilador.

Especificamente, você pode usar dois tipos de caches: caches de compilador local e caches de compilador distribuídos.

Caches locais

INFORMAÇÕES

As instruções a seguir funcionarão para Android e iOS. Se você estiver criando apenas aplicativos Android, você deve estar pronto. Se você também estiver criando aplicativos iOS, siga as instruções na seção Configuração específica do XCode abaixo.

Sugerimos usar o ccache para armazenar em cache a compilação de suas compilações nativas. O Ccache funciona agrupando os compiladores C++, armazenando os resultados da compilação e ignorando a compilação se um resultado intermediário da compilação tiver sido originalmente armazenado.

Para instalá-lo, você pode seguir as instruções oficiais de instalação.

No macOS, podemos instalar o ccache com brew install ccache. Depois de instalado, você pode configurá-lo da seguinte maneira para armazenar em cache os resultados da compilação do NDK:

bash
ln -s $(which ccache) /usr/local/bin/gcc
+ln -s $(which ccache) /usr/local/bin/g++
+ln -s $(which ccache) /usr/local/bin/cc
+ln -s $(which ccache) /usr/local/bin/c++
+ln -s $(which ccache) /usr/local/bin/clang
+ln -s $(which ccache) /usr/local/bin/clang++

Isso criará links simbólicos para o ccache dentro do /usr/local/bin/ que são chamados de gcc, g++ e assim por diante.

Isso funciona desde que /usr/local/bin/ venha primeiro que /usr/bin/ dentro de sua variável $PATH, que é o padrão.

Você pode verificar se funciona usando o comando which:

bash
$ which gcc
+/usr/local/bin/gcc

Se o resultado for /usr/local/bin/gcc, então você está efetivamente chamando o ccache, que agrupará as chamadas do gcc.

CUIDADO

Observe que esta configuração do ccache afetará todas as compilações que você está executando em sua máquina, não apenas aquelas relacionadas ao React Native. Use-o por sua conta e risco. Se você não conseguir instalar/compilar outro software, esse pode ser o motivo. Se for esse o caso, você pode remover o link simbólico criado com:

bash
unlink /usr/local/bin/gcc
+unlink /usr/local/bin/g++
+unlink /usr/local/bin/cc
+unlink /usr/local/bin/c++
+unlink /usr/local/bin/clang
+unlink /usr/local/bin/clang++

para reverter sua máquina ao status original e usar os compiladores padrão.

Você pode então fazer duas compilações limpas (por exemplo, no Android você pode primeiro executar o yarn react-native run-android, excluir a pasta android/app/build e executar o primeiro comando mais uma vez). Você notará que a segunda compilação foi muito mais rápida que a primeira (deve levar segundos em vez de minutos). Durante a construção, você pode verificar se o ccache funciona corretamente e verificar a taxa de acertos/erros do cache ccache -s

bash
$ ccache -s
+Summary:
+  Hits:             196 /  3068 (6.39 %)
+    Direct:           0 /  3068 (0.00 %)
+    Preprocessed:   196 /  3068 (6.39 %)
+  Misses:          2872
+    Direct:        3068
+    Preprocessed:  2872
+  Uncacheable:        1
+Primary storage:
+  Hits:             196 /  6136 (3.19 %)
+  Misses:          5940
+  Cache size (GB): 0.60 / 20.00 (3.00 %)

Observe que o ccache agrega as estatísticas de todas as compilações. Você pode usar ccache --zero-stats para redefini-los antes de uma compilação para verificar a taxa de acertos do cache.

Se precisar limpar seu cache, você pode fazer isso com ccache --clear

Configuração específica do XCode

Para garantir que o ccache funcione corretamente com iOS e XCode, você precisa seguir algumas etapas extras:

  1. Você deve alterar a forma como o Xcode e o xcodebuild chamam o comando do compilador. Por padrão eles usam caminhos totalmente especificados para os binários do compilador, portanto os links simbólicos instalados em /usr/local/bin não serão usados. Você pode configurar o Xcode para usar nomes relativos para os compiladores usando qualquer uma destas duas opções:
  • Variáveis de ambiente prefixadas na linha de comando se você usar uma linha de comando direta: CLANG=clang CLANGPLUSPLUS=clang++ LD=clang LDPLUSPLUS=clang++ xcodebuild <resto da linha de comando do xcodebuild>
  • Uma seção post_install em seu ios/Podfile que altera o compilador em seu espaço de trabalho Xcode durante a etapa de instalação do pod:
  post_install do |installer|
+    react_native_post_install(installer)
+
+    # ...possibly other post_install items here
+
+    installer.pods_project.targets.each do |target|
+      target.build_configurations.each do |config|
+        # Using the un-qualified names means you can swap in different implementations, for example ccache
+        config.build_settings["CC"] = "clang"
+        config.build_settings["LD"] = "clang"
+        config.build_settings["CXX"] = "clang++"
+        config.build_settings["LDPLUSPLUS"] = "clang++"
+      end
+    end
+
+    __apply_Xcode_12_5_M1_post_install_workaround(installer)
+  end
  1. Você precisa de uma configuração de ccache que permita um certo nível de negligência e comportamento de cache, de modo que o ccache registre ocorrências de cache durante as compilações do Xcode. As variáveis de configuração do ccache que são diferentes do padrão são as seguintes se configuradas pela variável de ambiente:
bash
export CCACHE_SLOPPINESS=clang_index_store,file_stat_matches,include_file_ctime,include_file_mtime,ivfsoverlay,pch_defines,modules,system_headers,time_macros
+export CCACHE_FILECLONE=true
+export CCACHE_DEPEND=true
+export CCACHE_INODECACHE=true

O mesmo pode ser configurado em um arquivo ccache.conf ou qualquer outro mecanismo fornecido pelo ccache. Mais sobre isso pode ser encontrado no manual oficial do ccache.

Usando esta abordagem em um IC

Ccache usa a pasta /Users/$USER/Library/Caches/ccache no macOS para armazenar o cache. Portanto, você pode salvar e restaurar a pasta correspondente também no CI para acelerar suas compilações.

No entanto, há algumas coisas que você deve estar ciente:

  1. No CI, recomendamos fazer uma compilação totalmente limpa, para evitar problemas de cache envenenado. Se você seguir a abordagem mencionada no parágrafo anterior, poderá paralelizar a construção nativa em 4 ABIs diferentes e provavelmente não precisará do ccache no CI.

  2. O ccache depende de carimbos de data/hora para calcular uma ocorrência no cache. Isso não funciona bem no CI, pois os arquivos são baixados novamente a cada execução do CI. Para superar isso, você precisará usar a opção de conteúdo compiler_check, que depende do hash do conteúdo do arquivo.

Caches distribuídos

Semelhante aos caches locais, você pode considerar o uso de um cache distribuído para suas compilações nativas. Isso pode ser especificamente útil em organizações maiores que fazem compilações nativas frequentes.

Recomendamos usar sccache para conseguir isso. Seguimos o início rápido da compilação distribuída do sccache para obter instruções sobre como configurar e usar esta ferramenta.

`,51),t=[o];function l(p,r,c,h,d,k){return i(),a("div",null,t)}const g=s(n,[["render",l]]);export{F as __pageData,g as default}; diff --git a/vitepress/docs/.vitepress/dist/assets/docs_build-speed.md.DV6MDRQw.lean.js b/vitepress/docs/.vitepress/dist/assets/docs_build-speed.md.DV6MDRQw.lean.js new file mode 100644 index 0000000..a9dc062 --- /dev/null +++ b/vitepress/docs/.vitepress/dist/assets/docs_build-speed.md.DV6MDRQw.lean.js @@ -0,0 +1 @@ +import{_ as s,c as a,o as i,a4 as e}from"./chunks/framework.nQaBHiNx.js";const F=JSON.parse('{"title":"Acelerando sua fase de construção","description":"","frontmatter":{},"headers":[],"relativePath":"docs/build-speed.md","filePath":"docs/build-speed.md"}'),n={name:"docs/build-speed.md"},o=e("",51),t=[o];function l(p,r,c,h,d,k){return i(),a("div",null,t)}const g=s(n,[["render",l]]);export{F as __pageData,g as default}; diff --git a/vitepress/docs/.vitepress/dist/assets/docs_building-for-tv.md.CwVLBrRD.js b/vitepress/docs/.vitepress/dist/assets/docs_building-for-tv.md.CwVLBrRD.js new file mode 100644 index 0000000..f6566b3 --- /dev/null +++ b/vitepress/docs/.vitepress/dist/assets/docs_building-for-tv.md.CwVLBrRD.js @@ -0,0 +1,91 @@ +import{_ as s,c as i,o as a,a4 as n}from"./chunks/framework.nQaBHiNx.js";const g=JSON.parse('{"title":"Construção para dispositivos de TV","description":"","frontmatter":{},"headers":[],"relativePath":"docs/building-for-tv.md","filePath":"docs/building-for-tv.md"}'),e={name:"docs/building-for-tv.md"},t=n(`

Construção para dispositivos de TV

O suporte a dispositivos de TV foi implementado com a intenção de fazer com que os aplicativos React Native existentes funcionem na Apple TV e Android TV, com poucas ou nenhuma alteração necessária no código JavaScript dos aplicativos.

Android TV

Mudanças de compilação

  • Camada nativa: para executar o projeto React Native na Android TV, certifique-se de fazer as seguintes alterações em AndroidManifest.xml:
xml
  <!-- Adicione uma imagem de banner personalizada para exibir como ícone do iniciador do Android TV -->
+ <application
+  ...
+  android:banner="@drawable/tv_banner"
+  >
+    ...
+    <intent-filter>
+      ...
+      <!-- Necessário para criar corretamente uma intenção de lançamento ao executar no Android TV -->
+      <category android:name="android.intent.category.LEANBACK_LAUNCHER"/>
+    </intent-filter>
+    ...
+  </application>
  • Camada JavaScript: suporte para Android TV foi adicionado a Platform.android.js. Você pode verificar se o código está sendo executado na Android TV fazendo:
jsx
const Platform = require('Platform');
+const running_on_android_tv = Platform.isTV;

Mudanças de código

  • Acesso a controles touchs: ao executar no Android TV, a estrutura do Android aplicará automaticamente um esquema de navegação direcional com base na posição relativa dos elementos focáveis em suas visualizações. O mixin Touchable tem código adicionado para detectar mudanças de foco e usar métodos existentes para estilizar os componentes corretamente e iniciar as ações adequadas quando a visualização é selecionada usando o controle remoto da TV, então TouchableWithoutFeedback, TouchableHighlight, TouchableOpacity e TouchableNativeFeedback funcionarão conforme esperado. Em particular:

    • onFocus será executado quando a visualização tocável entrar em foco
    • onBlur será executado quando a visualização tocável ficar fora de foco
    • onPress será executado quando a visualização tocável for realmente selecionada pressionando o botão "selecionar" no controle remoto da TV.
  • Entrada de controle remoto/teclado de TV: uma nova classe nativa, ReactAndroidTVRootViewHelper, configura manipuladores de eventos importantes para eventos remotos de TV. Quando ocorrem eventos remotos de TV, esta classe dispara um evento JS. Este evento será captado por instâncias do objeto JavaScript TVEventHandler. O código do aplicativo que precisa implementar o tratamento personalizado de eventos remotos de TV pode criar uma instância de TVEventHandler e escutar esses eventos, como no código a seguir:

js
const TVEventHandler = require('TVEventHandler');
+
+class Game2048 extends React.Component {
+  _tvEventHandler: any;
+
+  _enableTVEventHandler() {
+    this._tvEventHandler = new TVEventHandler();
+    this._tvEventHandler.enable(this, function (cmp, evt) {
+      if (evt && evt.eventType === 'right') {
+        cmp.setState({board: cmp.state.board.move(2)});
+      } else if (evt && evt.eventType === 'up') {
+        cmp.setState({board: cmp.state.board.move(1)});
+      } else if (evt && evt.eventType === 'left') {
+        cmp.setState({board: cmp.state.board.move(0)});
+      } else if (evt && evt.eventType === 'down') {
+        cmp.setState({board: cmp.state.board.move(3)});
+      } else if (evt && evt.eventType === 'playPause') {
+        cmp.restartGame();
+      }
+    });
+  }
+
+  _disableTVEventHandler() {
+    if (this._tvEventHandler) {
+      this._tvEventHandler.disable();
+      delete this._tvEventHandler;
+    }
+  }
+
+  componentDidMount() {
+    this._enableTVEventHandler();
+  }
+
+  componentWillUnmount() {
+    this._disableTVEventHandler();
+  }
+}
  • Suporte ao Dev Menu: No emulador, cmd-M abrirá o Dev Menu, semelhante ao Android. Para acessá-lo em um dispositivo Android TV real, pressione o botão de menu ou pressione longamente o botão de avanço rápido no controle remoto. (Por favor, não agite o dispositivo Android TV, isso não funcionará 😃)

Problemas conhecidos:

  • Os componentes TextInput não funcionam por enquanto (ou seja, eles não podem receber o foco automaticamente, veja este comentário).
    • No entanto, é possível usar um ref para acionar manualmente inputRef.current.focus().
    • Você pode agrupar sua entrada dentro de um componente TouchableWithoutFeedback e acionar o foco no evento onFocus desse touch. Isto permite abrir o teclado através das teclas de seta.
    • O teclado pode redefinir seu estado após cada pressionamento de tecla (isso só pode acontecer dentro do emulador do Android TV).
  • O conteúdo dos componentes Modal não pode receber foco, consulte este comentário para obter detalhes.

tvOS

Descontinuado

Em vez disso, use react-native-tvos. Para obter detalhes, verifique a postagem do blog da versão 0.62.

Alterações de compilação

  • Camada nativa: todos os projetos React Native Xcode agora têm alvos de construção da Apple TV, com nomes terminando na string '-tvOS'.
  • react-native init: Novos projetos React Native criados com react-native init terão o destino Apple TV criado automaticamente em seus projetos XCode.
  • Camada JavaScript: suporte para Apple TV foi adicionado a Platform.ios.js. Você pode verificar se o código está sendo executado na AppleTV fazendo
js
const Platform = require('Platform');
+const running_on_tv = Platform.isTV;
+
+// Se você quiser ser mais específico e detectar apenas dispositivos rodando tvOS
+// (mas sem dispositivos Android TV) você pode usar:
+const running_on_apple_tv = Platform.isTVOS;

Mudanças de código

  • Suporte geral para tvOS: alterações específicas da Apple TV no código nativo são todas agrupadas pela definição TARGET_OS_TV. Isso inclui alterações para suprimir APIs que não são suportadas no tvOS (por exemplo, visualizações da web, controles deslizantes, interruptores, barra de status, etc.) e alterações para oferecer suporte à entrada do usuário a partir do controle remoto ou teclado da TV.

  • Base de código comum: como tvOS e iOS compartilham a maior parte do código Objective-C e JavaScript em comum, a maior parte da documentação para iOS se aplica igualmente ao tvOS.

  • Acesso a controles touch: Ao executar no Apple TV, a classe de visualização nativa é RCTTVView, que possui métodos adicionais para fazer uso do mecanismo de foco tvOS. O mixin Touchable tem código adicionado para detectar mudanças de foco e usar métodos existentes para estilizar os componentes corretamente e iniciar as ações adequadas quando a visualização é selecionada usando o controle remoto da TV, então TouchableWithoutFeedback, TouchableHighlight e TouchableOpacity funcionarão conforme esperado. Em particular:

    • onFocus será executado quando a visualização tocável entrar em foco
    • onBlur será executado quando a visualização tocável ficar fora de foco
    • onPress será executado quando a visualização tocável for realmente selecionada pressionando o botão "selecionar" no controle remoto da TV.
  • Entrada de controle remoto/teclado de TV: uma nova classe nativa, RCTTVRemoteHandler, configura reconhecedores de gestos para eventos remotos de TV. Quando ocorrem eventos remotos de TV, esta classe dispara notificações que são captadas por RCTTVNavigationEventEmitter (uma subclasse de RCTEventEmitter), que dispara um evento JS. Este evento será captado por instâncias do objeto JavaScript TVEventHandler. O código do aplicativo que precisa implementar o tratamento personalizado de eventos remotos de TV pode criar uma instância de TVEventHandler e escutar esses eventos, como no código a seguir:

js
const TVEventHandler = require('TVEventHandler');
+
+class Game2048 extends React.Component {
+  _tvEventHandler: any;
+
+  _enableTVEventHandler() {
+    this._tvEventHandler = new TVEventHandler();
+    this._tvEventHandler.enable(this, function (cmp, evt) {
+      if (evt && evt.eventType === 'right') {
+        cmp.setState({board: cmp.state.board.move(2)});
+      } else if (evt && evt.eventType === 'up') {
+        cmp.setState({board: cmp.state.board.move(1)});
+      } else if (evt && evt.eventType === 'left') {
+        cmp.setState({board: cmp.state.board.move(0)});
+      } else if (evt && evt.eventType === 'down') {
+        cmp.setState({board: cmp.state.board.move(3)});
+      } else if (evt && evt.eventType === 'playPause') {
+        cmp.restartGame();
+      }
+    });
+  }
+
+  _disableTVEventHandler() {
+    if (this._tvEventHandler) {
+      this._tvEventHandler.disable();
+      delete this._tvEventHandler;
+    }
+  }
+
+  componentDidMount() {
+    this._enableTVEventHandler();
+  }
+
+  componentWillUnmount() {
+    this._disableTVEventHandler();
+  }
+}
  • Suporte ao Dev Menu: No simulador, cmd-D abrirá o Dev Menu, semelhante ao iOS. Para acessá-lo em um dispositivo Apple TV real, pressione longamente o botão reproduzir/pausar no controle remoto. (Por favor, não agite o dispositivo Apple TV, isso não funcionará 😃)

  • Animações remotas de TV: o código nativo RCTTVView implementa animações de paralaxe recomendadas pela Apple para ajudar a guiar o olho enquanto o usuário navega pelas visualizações. As animações podem ser desativadas ou ajustadas com novas propriedades de visualização opcionais.

  • Navegação de retorno com o botão de menu do controle remoto da TV: o componente BackHandler, originalmente escrito para oferecer suporte ao botão de retorno do Android, agora também oferece suporte à navegação de retorno na Apple TV usando o botão de menu no controle remoto da TV.

  • Comportamento do TabBarIOS: o componente TabBarIOS envolve a API UITabBar nativa, que funciona de maneira diferente no Apple TV. Para evitar a nova renderização instável da barra de guias no tvOS (consulte esta issue), o item selecionado da barra de guias só pode ser definido a partir de JavaScript na renderização inicial e é controlado depois disso pelo usuário por meio de código nativo.

Problemas conhecidos

  • Rolagem ListView: O problema pode ser contornado definindo removeClippedSubviews como false em ListView e componentes semelhantes. Para mais discussão sobre este assunto, consulte este PR.
`,25),l=[t];function p(h,k,o,r,d,E){return a(),i("div",null,l)}const y=s(e,[["render",p]]);export{g as __pageData,y as default}; diff --git a/vitepress/docs/.vitepress/dist/assets/docs_building-for-tv.md.CwVLBrRD.lean.js b/vitepress/docs/.vitepress/dist/assets/docs_building-for-tv.md.CwVLBrRD.lean.js new file mode 100644 index 0000000..daa53b4 --- /dev/null +++ b/vitepress/docs/.vitepress/dist/assets/docs_building-for-tv.md.CwVLBrRD.lean.js @@ -0,0 +1 @@ +import{_ as s,c as i,o as a,a4 as n}from"./chunks/framework.nQaBHiNx.js";const g=JSON.parse('{"title":"Construção para dispositivos de TV","description":"","frontmatter":{},"headers":[],"relativePath":"docs/building-for-tv.md","filePath":"docs/building-for-tv.md"}'),e={name:"docs/building-for-tv.md"},t=n("",25),l=[t];function p(h,k,o,r,d,E){return a(),i("div",null,l)}const y=s(e,[["render",p]]);export{g as __pageData,y as default}; diff --git a/vitepress/docs/.vitepress/dist/assets/docs_colors.md.DKDwf1Wk.js b/vitepress/docs/.vitepress/dist/assets/docs_colors.md.DKDwf1Wk.js new file mode 100644 index 0000000..191277a --- /dev/null +++ b/vitepress/docs/.vitepress/dist/assets/docs_colors.md.DKDwf1Wk.js @@ -0,0 +1 @@ +import{_ as e,c as l,o as i,a4 as a}from"./chunks/framework.nQaBHiNx.js";const m=JSON.parse('{"title":"Referência de Cores","description":"","frontmatter":{},"headers":[],"relativePath":"docs/colors.md","filePath":"docs/colors.md"}'),o={name:"docs/colors.md"},r=a('

Referência de Cores

Os componentes do React Native são estilizados usando JavaScript. As propriedades de cores geralmente correspondem ao modo como o CSS funciona na web. Guias gerais sobre o uso de cores em cada plataforma podem ser encontrados abaixo:

APIs de cores

React Native possui diversas APIs de cores projetadas para permitir que você aproveite ao máximo o design da sua plataforma e as preferências do usuário.

  • PlatformColor permite fazer referência ao sistema de cores da plataforma.
  • DynamicColorIOS é específico para iOS e permite especificar quais cores devem ser usadas no modo claro ou escuro.

Representações de cores

Vermelho Verde Azul (RGB)

React Native suporta rgb() e rgba() em notação hexadecimal e funcional:

  • '#f0f' (#rgb)
  • '#ff00ff' (#rrggbb)
  • '#f0ff' (#rgba)
  • '#ff00ff00' (#rrggbbaa)
  • 'rgb(255, 0, 255)'
  • 'rgb(255 0 255)'
  • 'rgb(255, 0, 255, 1,0)'
  • 'rgba(255 0 255/1,0)'

Tonalidade Saturação Iluminação (HSL)

React Native suporta hsl() e hsla() em notação funcional:

  • 'hsl(360, 100%, 100%)'
  • 'hsl(360 100% 100%)'
  • 'hsla(360, 100%, 100%, 1,0)'
  • 'hsla(360 100% 100% / 1,0)'

Matiz Brancura Escuridão (HWB)

React Native suporta hwb() em notação funcional:

  • 'hwb(0, 0%, 100%)'
  • 'hwb(360, 100%, 100%)'
  • 'hwb(0 0% 0%)'
  • 'hwb(70 50% 0%)'

Informações de cor

React Native também suporta cores como valores int (no modo de cores RGB):

  • 0xff00ff00 (0xrrggbbaa)

CUIDADO

Isso pode parecer semelhante à representação de cores do Android, mas no Android os valores são armazenados no modo de cores SRGB (0xaarrggbb).

Cores nomeadas

No React Native você também pode usar strings de nomes de cores como valores.

INFORMAÇÕES

React Native suporta apenas nomes de cores em minúsculas. Nomes de cores em letras maiúsculas não são suportados.

transparent

Este é um atalho para rgba(0,0,0,0), igual ao CSS3.

Palavras-chave das cores

A implementação de cores nomeadas segue a especificação CSS3/SVG

  • aliceblue (#f0f8ff)
  • antiquewhite (#faebd7)
  • aqua (#00ffff)
  • aquamarine (#7fffd4)
  • azure (#f0ffff)
  • beige (#f5f5dc)
  • bisque (#ffe4c4)
  • black (#000000)
  • blanchedalmond (#ffebcd)
  • blue (#0000ff)
  • blueviolet (#8a2be2)
  • brown (#a52a2a)
  • burlywood (#deb887)
  • cadetblue (#5f9ea0)
  • chartreuse (#7fff00)
  • chocolate (#d2691e)
  • coral (#ff7f50)
  • cornflowerblue (#6495ed)
  • cornsilk (#fff8dc)
  • crimson (#dc143c)
  • cyan (#00ffff)
  • darkblue (#00008b)
  • darkcyan (#008b8b)
  • darkgoldenrod (#b8860b)
  • darkgray (#a9a9a9)
  • darkgreen (#006400)
  • darkgrey (#a9a9a9)
  • darkkhaki (#bdb76b)
  • darkmagenta (#8b008b)
  • darkolivegreen (#556b2f)
  • darkorange (#ff8c00)
  • darkorchid (#9932cc)
  • darkred (#8b0000)
  • darksalmon (#e9967a)
  • darkseagreen (#8fbc8f)
  • darkslateblue (#483d8b)
  • darkslategrey (#2f4f4f)
  • darkturquoise (#00ced1)
  • darkviolet (#9400d3)
  • deeppink (#ff1493)
  • deepskyblue (#00bfff)
  • dimgray (#696969)
  • dimgrey (#696969)
  • dodgerblue (#1e90ff)
  • firebrick (#b22222)
  • floralwhite (#fffaf0)
  • forestgreen (#228b22)
  • fuchsia (#ff00ff)
  • gainsboro (#dcdcdc)
  • ghostwhite (#f8f8ff)
  • gold (#ffd700)
  • goldenrod (#daa520)
  • gray (#808080)
  • green (#008000)
  • greenyellow (#adff2f)
  • grey (#808080)
  • honeydew (#f0fff0)
  • hotpink (#ff69b4)
  • indianred (#cd5c5c)
  • indigo (#4b0082)
  • ivory (#fffff0)
  • khaki (#f0e68c)
  • lavender (#e6e6fa)
  • lavenderblush (#fff0f5)
  • lawngreen (#7cfc00)
  • lemonchiffon (#fffacd)
  • lightblue (#add8e6)
  • lightcoral (#f08080)
  • lightcyan (#e0ffff)
  • lightgoldenrodyellow (#fafad2)
  • lightgray (#d3d3d3)
  • lightgreen (#90ee90)
  • lightgrey (#d3d3d3)
  • lightpink (#ffb6c1)
  • lightsalmon (#ffa07a)
  • lightseagreen (#20b2aa)
  • lightskyblue (#87cefa)
  • lightslategrey (#778899)
  • lightsteelblue (#b0c4de)
  • lightyellow (#ffffe0)
  • lime (#00ff00)
  • limegreen (#32cd32)
  • linen (#faf0e6)
  • magenta (#ff00ff)
  • maroon (#800000)
  • mediumaquamarine (#66cdaa)
  • mediumblue (#0000cd)
  • mediumorchid (#ba55d3)
  • mediumpurple (#9370db)
  • mediumseagreen (#3cb371)
  • mediumslateblue (#7b68ee)
  • mediumspringgreen (#00fa9a)
  • mediumturquoise (#48d1cc)
  • mediumvioletred (#c71585)
  • midnightblue (#191970)
  • mintcream (#f5fffa)
  • mistyrose (#ffe4e1)
  • moccasin (#ffe4b5)
  • navajowhite (#ffdead)
  • navy (#000080)
  • oldlace (#fdf5e6)
  • olive (#808000)
  • olivedrab (#6b8e23)
  • orange (#ffa500)
  • orangered (#ff4500)
  • orchid (#da70d6)
  • palegoldenrod (#eee8aa)
  • palegreen (#98fb98)
  • paleturquoise (#afeeee)
  • palevioletred (#db7093)
  • papayawhip (#ffefd5)
  • peachpuff (#ffdab9)
  • peru (#cd853f)
  • pink (#ffc0cb)
  • plum (#dda0dd)
  • powderblue (#b0e0e6)
  • purple (#800080)
  • rebeccapurple (#663399)
  • red (#ff0000)
  • rosybrown (#bc8f8f)
  • royalblue (#4169e1)
  • saddlebrown (#8b4513)
  • salmon (#fa8072)
  • sandybrown (#f4a460)
  • seagreen (#2e8b57)
  • seashell (#fff5ee)
  • sienna (#a0522d)
  • silver (#c0c0c0)
  • skyblue (#87ceeb)
  • slateblue (#6a5acd)
  • slategray (#708090)
  • snow (#fffafa)
  • springgreen (#00ff7f)
  • steelblue (#4682b4)
  • tan (#d2b48c)
  • teal (#008080)
  • thistle (#d8bfd8)
  • tomato (#ff6347)
  • turquoise (#40e0d0)
  • violet (#ee82ee)
  • wheat (#f5deb3)
  • white (#ffffff)
  • whitesmoke (#f5f5f5)
  • yellow (#ffff00)
  • yellowgreen (#9acd32)
',28),d=[r];function c(s,f,t,n,u,b){return i(),l("div",null,d)}const p=e(o,[["render",c]]);export{m as __pageData,p as default}; diff --git a/vitepress/docs/.vitepress/dist/assets/docs_colors.md.DKDwf1Wk.lean.js b/vitepress/docs/.vitepress/dist/assets/docs_colors.md.DKDwf1Wk.lean.js new file mode 100644 index 0000000..972f081 --- /dev/null +++ b/vitepress/docs/.vitepress/dist/assets/docs_colors.md.DKDwf1Wk.lean.js @@ -0,0 +1 @@ +import{_ as e,c as l,o as i,a4 as a}from"./chunks/framework.nQaBHiNx.js";const m=JSON.parse('{"title":"Referência de Cores","description":"","frontmatter":{},"headers":[],"relativePath":"docs/colors.md","filePath":"docs/colors.md"}'),o={name:"docs/colors.md"},r=a("",28),d=[r];function c(s,f,t,n,u,b){return i(),l("div",null,d)}const p=e(o,[["render",c]]);export{m as __pageData,p as default}; diff --git a/vitepress/docs/.vitepress/dist/assets/docs_communication-android.md.qDQRzEbQ.js b/vitepress/docs/.vitepress/dist/assets/docs_communication-android.md.qDQRzEbQ.js new file mode 100644 index 0000000..645b106 --- /dev/null +++ b/vitepress/docs/.vitepress/dist/assets/docs_communication-android.md.qDQRzEbQ.js @@ -0,0 +1,45 @@ +import{_ as s,c as a,o as i,a4 as e}from"./chunks/framework.nQaBHiNx.js";const m=JSON.parse('{"title":"Comunicação entre nativo e React Native","description":"","frontmatter":{},"headers":[],"relativePath":"docs/communication-android.md","filePath":"docs/communication-android.md"}'),t={name:"docs/communication-android.md"},n=e(`

Comunicação entre nativo e React Native

Em Guia de integração com aplicativos existentes e Guia de componentes de UI nativos aprendemos como incorporar o React Native em um componente nativo e vice-versa. Quando misturamos componentes nativos e React Native, eventualmente encontraremos a necessidade de comunicação entre esses dois mundos. Algumas maneiras de conseguir isso já foram mencionadas em outros guias. Este artigo resume as técnicas disponíveis.

Introdução

O React Native é inspirado no React, então a ideia básica do fluxo de informações é semelhante. O fluxo no React é unidirecional. Mantemos uma hierarquia de componentes, na qual cada componente depende apenas de seu pai e de seu próprio estado interno. Fazemos isso com propriedades: os dados são passados ​​de um pai para seus filhos de cima para baixo. Se um componente ancestral depende do estado de seu descendente, deve-se transmitir um retorno de chamada a ser usado pelo descendente para atualizar o ancestral.

O mesmo conceito se aplica ao React Native. Contanto que estejamos construindo nosso aplicativo exclusivamente dentro da estrutura, podemos direcioná-lo com propriedades e retornos de chamada. Mas, quando misturamos componentes React Native e nativos, precisamos de alguns mecanismos específicos entre linguagens que nos permitam passar informações entre eles.

Propriedades

As propriedades são a forma mais direta de comunicação entre componentes. Portanto, precisamos de uma maneira de passar propriedades tanto de nativo para React Native quanto de React Native para nativo.

Passando propriedades de Native para React Native

Você pode passar propriedades para o aplicativo React Native fornecendo uma implementação personalizada de ReactActivityDelegate em sua atividade principal. Esta implementação deve substituir getLaunchOptions para retornar um Bundle com as propriedades desejadas.

java
public class MainActivity extends ReactActivity {
+  @Override
+  protected ReactActivityDelegate createReactActivityDelegate() {
+    return new ReactActivityDelegate(this, getMainComponentName()) {
+      @Override
+      protected Bundle getLaunchOptions() {
+        Bundle initialProperties = new Bundle();
+        ArrayList<String> imageList = new ArrayList<String>(Arrays.asList(
+                "https://dummyimage.com/600x400/ffffff/000000.png",
+                "https://dummyimage.com/600x400/000000/ffffff.png"
+        ));
+        initialProperties.putStringArrayList("images", imageList);
+        return initialProperties;
+      }
+    };
+  }
+}
kotlin
class MainActivity : ReactActivity() {
+    override fun createReactActivityDelegate(): ReactActivityDelegate {
+        return object : ReactActivityDelegate(this, mainComponentName) {
+            override fun getLaunchOptions(): Bundle {
+                val imageList = arrayListOf("https://dummyimage.com/600x400/ffffff/000000.png", "https://dummyimage.com/600x400/000000/ffffff.png")
+                val initialProperties = Bundle().apply { putStringArrayList("images", imageList) }
+                return initialProperties
+            }
+        }
+    }
+}
tsx
import React from 'react';
+import {View, Image} from 'react-native';
+
+export default class ImageBrowserApp extends React.Component {
+  renderImage(imgURI) {
+    return <Image source={{uri: imgURI}} />;
+  }
+  render() {
+    return <View>{this.props.images.map(this.renderImage)}</View>;
+  }
+}

ReactRootView fornece uma propriedade de leitura e gravação appProperties. Depois que appProperties for definido, o aplicativo React Native será renderizado novamente com novas propriedades. A atualização só é realizada quando as novas propriedades atualizadas diferem das anteriores.

java
Bundle updatedProps = mReactRootView.getAppProperties();
+ArrayList<String> imageList = new ArrayList<String>(Arrays.asList(
+        "https://dummyimage.com/600x400/ff0000/000000.png",
+        "https://dummyimage.com/600x400/ffffff/ff0000.png"
+));
+updatedProps.putStringArrayList("images", imageList);
+
+mReactRootView.setAppProperties(updatedProps);
kotlin
var updatedProps: Bundle = reactRootView.getAppProperties()
+var imageList = arrayListOf("https://dummyimage.com/600x400/ff0000/000000.png", "https://dummyimage.com/600x400/ffffff/ff0000.png")

Não há problema em atualizar propriedades a qualquer momento. No entanto, as atualizações devem ser realizadas no thread principal. Você usa o getter em qualquer thread.

Não há como atualizar apenas algumas propriedades por vez. Sugerimos que você o crie em seu próprio wrapper.

Nota

Atualmente, a função JS componentWillUpdateProps do componente RN de nível superior não será chamada após uma atualização de prop. No entanto, você pode acessar os novos adereços na função componentDidMount.

Passando propriedades do React Native para Native

O problema de exposição de propriedades de componentes nativos é abordado em detalhes neste artigo. Resumindo, as propriedades que devem ser refletidas em JavaScript precisam ser expostas como um método setter anotado com @ReactProp e, em seguida, usá-las no React Native como se o componente fosse um componente React Native comum.

Limites de propriedades

A principal desvantagem das propriedades entre linguagens é que elas não suportam retornos de chamada, o que nos permitiria lidar com ligações de dados de baixo para cima. Imagine que você tem uma pequena visualização RN que deseja remover da visualização pai nativa como resultado de uma ação JS. Não há como fazer isso com adereços, pois as informações precisariam ir de baixo para cima.

Embora tenhamos uma variedade de retornos de chamada entre linguagens (descritos aqui), esses retornos de chamada nem sempre são o que precisamos. O principal problema é que eles não devem ser passados ​​como propriedades. Em vez disso, esse mecanismo nos permite acionar uma ação nativa de JS e manipular o resultado dessa ação em JS.

Outras formas de interação entre idiomas (eventos e módulos nativos)

Conforme declarado no capítulo anterior, o uso de propriedades apresenta algumas limitações. Às vezes, as propriedades não são suficientes para conduzir a lógica do nosso aplicativo e precisamos de uma solução que dê mais flexibilidade. Este capítulo cobre outras técnicas de comunicação disponíveis no React Native. Eles podem ser usados ​​para comunicação interna (entre JS e camadas nativas no RN), bem como para comunicação externa (entre RN e a parte 'nativa pura' do seu aplicativo).

React Native permite que você execute chamadas de função em vários idiomas. Você pode executar código nativo personalizado de JS e vice-versa. Infelizmente, dependendo do lado em que trabalhamos, alcançamos o mesmo objetivo de maneiras diferentes. Para nativo - usamos mecanismo de eventos para agendar a execução de uma função manipuladora em JS, enquanto para React Native chamamos diretamente métodos exportados por módulos nativos.

Chamando funções React Native a partir de nativos (eventos)

Os eventos são descritos em detalhes neste artigo. Observe que o uso de eventos não nos dá garantias sobre o tempo de execução, pois o evento é tratado em um thread separado.

Os eventos são poderosos porque nos permitem alterar os componentes do React Native sem precisar de uma referência a eles. No entanto, existem algumas armadilhas nas quais você pode cair ao usá-los:

  • Como os eventos podem ser enviados de qualquer lugar, eles podem introduzir dependências do tipo espaguete em seu projeto.
  • Os eventos compartilham namespace, o que significa que você pode encontrar algumas colisões de nomes. As colisões não serão detectadas estaticamente, o que as torna difíceis de depurar.
  • Se você usar várias instâncias do mesmo componente React Native e quiser distingui-las da perspectiva do seu evento, provavelmente precisará introduzir identificadores e passá-los junto com os eventos (você pode usar o reactTag da visualização nativa como um identificador).

Chamando funções nativas do React Native (módulos nativos)

Módulos nativos são classes Java/Kotlin disponíveis em JS. Normalmente, uma instância de cada módulo é criada por ponte JS. Eles podem exportar funções e constantes arbitrárias para React Native. Eles foram abordados em detalhes neste artigo.

Aviso

Todos os módulos nativos compartilham o mesmo namespace. Cuidado com colisões de nomes ao criar novos.

`,31),p=[n];function o(l,r,h,d,k,c){return i(),a("div",null,p)}const g=s(t,[["render",o]]);export{m as __pageData,g as default}; diff --git a/vitepress/docs/.vitepress/dist/assets/docs_communication-android.md.qDQRzEbQ.lean.js b/vitepress/docs/.vitepress/dist/assets/docs_communication-android.md.qDQRzEbQ.lean.js new file mode 100644 index 0000000..67e4599 --- /dev/null +++ b/vitepress/docs/.vitepress/dist/assets/docs_communication-android.md.qDQRzEbQ.lean.js @@ -0,0 +1 @@ +import{_ as s,c as a,o as i,a4 as e}from"./chunks/framework.nQaBHiNx.js";const m=JSON.parse('{"title":"Comunicação entre nativo e React Native","description":"","frontmatter":{},"headers":[],"relativePath":"docs/communication-android.md","filePath":"docs/communication-android.md"}'),t={name:"docs/communication-android.md"},n=e("",31),p=[n];function o(l,r,h,d,k,c){return i(),a("div",null,p)}const g=s(t,[["render",o]]);export{m as __pageData,g as default}; diff --git a/vitepress/docs/.vitepress/dist/assets/docs_communication-ios.md.4nM-4AlR.js b/vitepress/docs/.vitepress/dist/assets/docs_communication-ios.md.4nM-4AlR.js new file mode 100644 index 0000000..d3347e5 --- /dev/null +++ b/vitepress/docs/.vitepress/dist/assets/docs_communication-ios.md.4nM-4AlR.js @@ -0,0 +1,54 @@ +import{_ as a,c as i,o as s,a4 as e}from"./chunks/framework.nQaBHiNx.js";const u=JSON.parse('{"title":"Comunicação entre nativo e React Native","description":"","frontmatter":{},"headers":[],"relativePath":"docs/communication-ios.md","filePath":"docs/communication-ios.md"}'),o={name:"docs/communication-ios.md"},t=e(`

Comunicação entre nativo e React Native

Em [Guia de integração com aplicativos existentes](integração com aplicativos existentes) e Guia de componentes de UI nativos aprendemos como incorporar o React Native em um componente nativo e vice-versa. Quando misturamos componentes nativos e React Native, eventualmente encontraremos a necessidade de comunicação entre esses dois mundos. Algumas maneiras de conseguir isso já foram mencionadas em outros guias. Este artigo resume as técnicas disponíveis.

Introdução

O React Native é inspirado no React, então a ideia básica do fluxo de informações é semelhante. O fluxo no React é unidirecional. Mantemos uma hierarquia de componentes, na qual cada componente depende apenas de seu pai e de seu próprio estado interno. Fazemos isso com propriedades: os dados são passados ​​de um pai para seus filhos de cima para baixo. Se um componente ancestral depende do estado de seu descendente, deve-se transmitir um retorno de chamada a ser usado pelo descendente para atualizar o ancestral.

O mesmo conceito se aplica ao React Native. Contanto que estejamos construindo nosso aplicativo exclusivamente dentro da estrutura, podemos direcioná-lo com propriedades e retornos de chamada. Mas, quando misturamos componentes React Native e nativos, precisamos de alguns mecanismos específicos entre linguagens que nos permitam passar informações entre eles.

Propriedades

As propriedades são a forma mais direta de comunicação entre componentes. Portanto, precisamos de uma maneira de passar propriedades tanto de nativo para React Native quanto de React Native para nativo.

Passando propriedades de Native para React Native

Para incorporar uma visualização React Native em um componente nativo, usamos RCTRootView. RCTRootView é um UIView que contém um aplicativo React Native. Ele também fornece uma interface entre o lado nativo e o aplicativo hospedado.

RCTRootView possui um inicializador que permite passar propriedades arbitrárias para o aplicativo React Native. O parâmetro initialProperties deve ser uma instância de NSDictionary. O dicionário é convertido internamente em um objeto JSON que o componente JS de nível superior pode referenciar.

objective-c
NSArray *imageList = @[@"https://dummyimage.com/600x400/ffffff/000000.png",
+                       @"https://dummyimage.com/600x400/000000/ffffff.png"];
+
+NSDictionary *props = @{@"images" : imageList};
+
+RCTRootView *rootView = [[RCTRootView alloc] initWithBridge:bridge
+                                                 moduleName:@"ImageBrowserApp"
+                                          initialProperties:props];
tsx
import React from 'react';
+import {View, Image} from 'react-native';
+
+export default class ImageBrowserApp extends React.Component {
+  renderImage(imgURI) {
+    return <Image source={{uri: imgURI}} />;
+  }
+  render() {
+    return <View>{this.props.images.map(this.renderImage)}</View>;
+  }
+}

RCTRootView também fornece uma propriedade de leitura e gravação appProperties. Depois que appProperties for definido, o aplicativo React Native será renderizado novamente com novas propriedades. A atualização só é realizada quando as novas propriedades atualizadas diferem das anteriores.

objective-c
NSArray *imageList = @[@"https://dummyimage.com/600x400/ff0000/000000.png",
+                       @"https://dummyimage.com/600x400/ffffff/ff0000.png"];
+
+rootView.appProperties = @{@"images" : imageList};

Não há problema em atualizar propriedades a qualquer momento. No entanto, as atualizações devem ser realizadas no thread principal. Você usa o getter em qualquer thread.

Observação

Atualmente, há um problema conhecido em que, ao definir appProperties durante a inicialização da ponte, a alteração pode ser perdida. Consulte https://github.com/facebook/react-native/issues/20115 para obter mais informações.

Não há como atualizar apenas algumas propriedades por vez. Sugerimos que você o crie em seu próprio wrapper.

Passando propriedades do React Native para Native

O problema de exposição de propriedades de componentes nativos é abordado em detalhes neste artigo. Resumindo, exporte propriedades com a macro RCT_CUSTOM_VIEW_PROPERTY em seu componente nativo personalizado e, em seguida, use-as no React Native como se o componente fosse um componente React Native comum.

Limites de propriedades

A principal desvantagem das propriedades entre linguagens é que elas não suportam retornos de chamada, o que nos permitiria lidar com ligações de dados de baixo para cima. Imagine que você tem uma pequena visualização RN que deseja remover da visualização pai nativa como resultado de uma ação JS. Não há como fazer isso com adereços, pois as informações precisariam ir de baixo para cima.

Embora tenhamos uma variedade de retornos de chamada entre idiomas (descritos aqui), esses retornos de chamada nem sempre são o que precisamos. O principal problema é que eles não devem ser passados ​​como propriedades. Em vez disso, esse mecanismo nos permite acionar uma ação nativa de JS e manipular o resultado dessa ação em JS.

Outras formas de interação entre linguagens (eventos e módulos nativos)

Conforme declarado no capítulo anterior, o uso de propriedades apresenta algumas limitações. Às vezes, as propriedades não são suficientes para conduzir a lógica do nosso aplicativo e precisamos de uma solução que dê mais flexibilidade. Este capítulo cobre outras técnicas de comunicação disponíveis no React Native. Eles podem ser usados ​​para comunicação interna (entre JS e camadas nativas no RN), bem como para comunicação externa (entre RN e a parte 'nativa pura' do seu aplicativo).

React Native permite que você execute chamadas de função em vários idiomas. Você pode executar código nativo personalizado de JS e vice-versa. Infelizmente, dependendo do lado em que trabalhamos, alcançamos o mesmo objetivo de maneiras diferentes. Para nativo - usamos mecanismo de eventos para agendar a execução de uma função manipuladora em JS, enquanto para React Native chamamos diretamente métodos exportados por módulos nativos.

Chamando funções React Native a partir de nativos (eventos)

Os eventos são descritos detalhadamente neste artigo. Observe que o uso de eventos não nos dá garantias sobre o tempo de execução, pois o evento é tratado em um thread separado.

Os eventos são poderosos porque nos permitem alterar os componentes do React Native sem precisar de uma referência a eles. No entanto, existem algumas armadilhas nas quais você pode cair ao usá-los:

  • Como os eventos podem ser enviados de qualquer lugar, eles podem introduzir dependências do tipo espaguete em seu projeto.
  • Os eventos compartilham namespace, o que significa que você pode encontrar algumas colisões de nomes. As colisões não serão detectadas estaticamente, o que as torna difíceis de depurar.
  • Se você usar várias instâncias do mesmo componente React Native e quiser distingui-las da perspectiva do seu evento, provavelmente precisará introduzir identificadores e passá-los junto com os eventos (você pode usar o reactTag da visualização nativa como um identificador).

O padrão comum que usamos ao incorporar nativo no React Native é tornar o RCTViewManager do componente nativo um delegado para as visualizações, enviando eventos de volta ao JavaScript por meio da ponte. Isso mantém as chamadas de eventos relacionadas em um só lugar.

Chamando funções nativas do React Native (módulos nativos)

Módulos nativos são classes Objective-C disponíveis em JS. Normalmente, uma instância de cada módulo é criada por ponte JS. Eles podem exportar funções e constantes arbitrárias para React Native. Eles foram abordados em detalhes neste artigo.

O fato de os módulos nativos serem singletons limita o mecanismo no contexto de incorporação. Digamos que temos um componente React Native incorporado em uma visualização nativa e queremos atualizar a visualização pai nativa. Usando o mecanismo de módulo nativo, exportaríamos uma função que não apenas recebe os argumentos esperados, mas também um identificador da visão nativa pai. O identificador seria usado para recuperar uma referência à visualização pai a ser atualizada. Dito isto, precisaríamos manter um mapeamento dos identificadores para as visualizações nativas no módulo.

Embora esta solução seja complexa, ela é usada em RCTUIManager, que é uma classe interna do React Native que gerencia todas as visualizações do React Native.

Módulos nativos também podem ser usados ​​para expor bibliotecas nativas existentes ao JS. A biblioteca de geolocalização é um exemplo vivo da ideia.

Cuidado

Todos os módulos nativos compartilham o mesmo namespace. Cuidado com colisões de nomes ao criar novos.

Fluxo de cálculo de layout

Ao integrar o nativo e o React Native, também precisamos de uma maneira de consolidar dois sistemas de layout diferentes. Esta seção aborda problemas comuns de layout e fornece uma breve descrição dos mecanismos para resolvê-los.

Layout de um componente nativo incorporado no React Native

Este caso é abordado neste artigo. Para resumir, como todas as nossas visualizações de react nativas são subclasses de UIView, a maioria dos atributos de estilo e tamanho funcionarão como você esperaria imediatamente.

Layout de um componente React Native incorporado no nativo

React Native com tamanho fixo

O cenário geral é quando temos um aplicativo React Native com tamanho fixo, que é conhecido pelo lado nativo. Em particular, uma visualização React Native em tela inteira se enquadra neste caso. Se quisermos uma visualização raiz menor, podemos definir explicitamente o quadro do RTRRootView.

Por exemplo, para criar um aplicativo RN com 200 pixels (lógicos) de altura e largura da visualização de hospedagem ampla, poderíamos fazer:

objective-c
- (void)viewDidLoad
+{
+  [...]
+  RCTRootView *rootView = [[RCTRootView alloc] initWithBridge:bridge
+                                                   moduleName:appName
+                                            initialProperties:props];
+  rootView.frame = CGRectMake(0, 0, self.view.width, 200);
+  [self.view addSubview:rootView];
+}

Quando temos uma visualização raiz de tamanho fixo, precisamos respeitar seus limites no lado JS. Em outras palavras, precisamos garantir que o conteúdo do React Native possa estar contido na visualização raiz de tamanho fixo. A maneira mais fácil de garantir isso é usar o layout Flexbox. Se você usar posicionamento absoluto e os componentes do React estiverem visíveis fora dos limites da visualização raiz, você obterá sobreposição com visualizações nativas, fazendo com que alguns recursos se comportem de forma inesperada. Por exemplo, 'TouchableHighlight' não destacará seus toques fora dos limites da visualização raiz.

Não há problema em atualizar dinamicamente o tamanho da visualização raiz, redefinindo sua propriedade de quadro. React Native cuidará do layout do conteúdo.

React Native com tamanho flexível

Em alguns casos, gostaríamos de renderizar conteúdo de tamanho inicialmente desconhecido. Digamos que o tamanho será definido dinamicamente em JS. Temos duas soluções para este problema.

  1. Você pode agrupar sua visualização React Native em um componente ScrollView. Isso garante que seu conteúdo estará sempre disponível e não se sobreporá às visualizações nativas.
  2. React Native permite determinar, em JS, o tamanho do aplicativo RN e fornecê-lo ao proprietário da hospedagem RCTRootView. O proprietário é então responsável por reorganizar as subvisualizações e manter a IU consistente. Conseguimos isso com os modos de flexibilidade do RCTRootView.

RCTRootView suporta 4 modos de flexibilidade de tamanhos diferentes:

objective-c
typedef NS_ENUM(NSInteger, RCTRootViewSizeFlexibility) {
+  RCTRootViewSizeFlexibilityNone = 0,
+  RCTRootViewSizeFlexibilityWidth,
+  RCTRootViewSizeFlexibilityHeight,
+  RCTRootViewSizeFlexibilityWidthAndHeight,
+};

RCTRootViewSizeFlexibilityNone é o valor padrão, o que torna fixo o tamanho da visualização raiz (mas ainda pode ser atualizado com setFrame:). Os outros três modos nos permitem rastrear as atualizações de tamanho do conteúdo do React Native. Por exemplo, definir o modo como RCTRootViewSizeFlexibilityHeight fará com que o React Native meça a altura do conteúdo e passe essa informação de volta ao delegado de RCTRootView. Uma ação arbitrária pode ser executada dentro do delegado, incluindo a configuração do quadro da visualização raiz, para que o conteúdo se ajuste. O delegado é chamado somente quando o tamanho do conteúdo é alterado.

Cuidado

Tornar uma dimensão flexível em JS e nativo leva a um comportamento indefinido. Por exemplo - não torne flexível a largura de um componente React de nível superior (com flexbox) enquanto estiver usando RCTRootViewSizeFlexibilityWidth na hospedagem RCTRootView.

Vejamos um exemplo.

objective-c
- (instancetype)initWithFrame:(CGRect)frame
+{
+  [...]
+
+  _rootView = [[RCTRootView alloc] initWithBridge:bridge
+  moduleName:@"FlexibilityExampleApp"
+  initialProperties:@{}];
+
+  _rootView.delegate = self;
+  _rootView.sizeFlexibility = RCTRootViewSizeFlexibilityHeight;
+  _rootView.frame = CGRectMake(0, 0, self.frame.size.width, 0);
+}
+
+#pragma mark - RCTRootViewDelegate
+- (void)rootViewDidChangeIntrinsicSize:(RCTRootView *)rootView
+{
+  CGRect newFrame = rootView.frame;
+  newFrame.size = rootView.intrinsicContentSize;
+
+  rootView.frame = newFrame;
+}

No exemplo, temos uma visualização FlexibleSizeExampleView que contém uma visualização raiz. Criamos a visualização raiz, inicializamos e definimos o delegado. O delegado cuidará das atualizações de tamanho. Em seguida, definimos a flexibilidade de tamanho da visualização raiz para RCTRootViewSizeFlexibilityHeight, o que significa que o método rootViewDidChangeIntrinsicSize: será chamado toda vez que o conteúdo do React Native mudar sua altura. Finalmente, definimos a largura e a posição da visualização raiz. Observe que definimos a altura também, mas isso não tem efeito, pois tornamos a altura dependente de RN.

Você pode verificar o código-fonte completo do exemplo aqui.

Não há problema em alterar dinamicamente o modo de flexibilidade de tamanho da visualização raiz. Alterar o modo de flexibilidade de uma visualização raiz agendará um recálculo do layout e o método delegado rootViewDidChangeIntrinsicSize: será chamado assim que o tamanho do conteúdo for conhecido.

Observação

O cálculo do layout do React Native é executado em um thread separado, enquanto as atualizações da visualização da UI nativa são feitas no thread principal. Isso pode causar inconsistências temporárias na interface do usuário entre o nativo e o React Native. Este é um problema conhecido e nossa equipe está trabalhando na sincronização de atualizações de IU provenientes de diferentes fontes.

Observação

O React Native não executa nenhum cálculo de layout até que a visualização raiz se torne uma subvisão de algumas outras visualizações. Se você deseja ocultar a visualização React Native até que suas dimensões sejam conhecidas, adicione a visualização raiz como uma subvisualização e torne-a inicialmente oculta (use a propriedade hidden de UIView). Em seguida, altere sua visibilidade no método delegado.

`,61),n=[t];function r(p,l,d,h,c,k){return s(),i("div",null,n)}const E=a(o,[["render",r]]);export{u as __pageData,E as default}; diff --git a/vitepress/docs/.vitepress/dist/assets/docs_communication-ios.md.4nM-4AlR.lean.js b/vitepress/docs/.vitepress/dist/assets/docs_communication-ios.md.4nM-4AlR.lean.js new file mode 100644 index 0000000..5280cbc --- /dev/null +++ b/vitepress/docs/.vitepress/dist/assets/docs_communication-ios.md.4nM-4AlR.lean.js @@ -0,0 +1 @@ +import{_ as a,c as i,o as s,a4 as e}from"./chunks/framework.nQaBHiNx.js";const u=JSON.parse('{"title":"Comunicação entre nativo e React Native","description":"","frontmatter":{},"headers":[],"relativePath":"docs/communication-ios.md","filePath":"docs/communication-ios.md"}'),o={name:"docs/communication-ios.md"},t=e("",61),n=[t];function r(p,l,d,h,c,k){return s(),i("div",null,n)}const E=a(o,[["render",r]]);export{u as __pageData,E as default}; diff --git a/vitepress/docs/.vitepress/dist/assets/docs_debugging.md.DXY2CnKb.js b/vitepress/docs/.vitepress/dist/assets/docs_debugging.md.DXY2CnKb.js new file mode 100644 index 0000000..7ca9b58 --- /dev/null +++ b/vitepress/docs/.vitepress/dist/assets/docs_debugging.md.DXY2CnKb.js @@ -0,0 +1,7 @@ +import{_ as e,c as o,o as a,a4 as s}from"./chunks/framework.nQaBHiNx.js";const r="/assets/307929568-c4514d57-633d-48d7-acd8-85b15c785dee.BSCw5qYK.png",g=JSON.parse('{"title":"Noções básicas de depuração","description":"","frontmatter":{},"headers":[],"relativePath":"docs/debugging.md","filePath":"docs/debugging.md"}'),i={name:"docs/debugging.md"},t=s('

Noções básicas de depuração

Acessando o menu de desenvolvimento

React Native fornece um menu de desenvolvedor no aplicativo que oferece várias opções de depuração. Você pode acessar o Menu Dev agitando seu dispositivo ou por meio de atalhos de teclado:

  • Simulador iOS: Cmd ⌘ + D (ou Dispositivo > Agitar)
  • Emuladores Android: Cmd ⌘ + M (macOS) ou Ctrl + M (Windows e Linux)

Alternativamente, para dispositivos e emuladores Android, você pode executar adb shell input keyevent 82 em seu terminal.

image

OBSERVAÇÃO

O menu Dev está desabilitado em compilações de lançamento (produção).

LogBox

Erros e avisos em builds de desenvolvimento são exibidos no LogBox dentro do seu aplicativo.

OBSERVAÇÃO

LogBox está desabilitado em compilações de lançamento (produção).

Erros e avisos do console

Os erros e avisos do console são exibidos como notificações na tela com um emblema vermelho ou amarelo e o número de erros ou avisos no console, respectivamente. Para visualizar um erro ou avisos do console, toque na notificação para visualizar as informações em tela cheia sobre o log e para paginar todos os logs no console.

Essas notificações podem ser ocultadas usando LogBox.ignoreAllLogs(). Isso é útil ao fazer demonstrações de produtos, por exemplo. Além disso, as notificações podem ser ocultadas por log por meio de LogBox.ignoreLogs(). Isto é útil quando há um aviso frequente que não pode ser corrigido, como aqueles em uma dependência de terceiros.

INFORMAÇÕES

Ignore os logs como último recurso e crie uma tarefa para corrigir quaisquer logs que sejam ignorados.

jsx
import {LogBox} from 'react-native';
+
+// Ignorar notificação de log por mensagem:
+LogBox.ignoreLogs(['Warning: ...']);
+
+// Ignore todas as notificações de log:
+LogBox.ignoreAllLogs();

Erros não tratados

Erros de JavaScript não tratados, marcado como undefined is not a function, abrirão automaticamente um erro LogBox em tela inteira com a origem do erro. Esses erros são dispensáveis e minimizáveis para que você possa ver o estado do seu aplicativo quando esses erros ocorrem, mas sempre devem ser resolvidos.

Erros de sintaxe

Quando ocorre um erro de sintaxe, o erro LogBox em tela cheia será aberto automaticamente com o rastreamento de pilha e a localização do erro de sintaxe. Este erro não pode ser descartado porque representa uma execução inválida de JavaScript que deve ser corrigida antes de continuar com seu aplicativo. Para descartar esses erros, corrija o erro de sintaxe e salve para descartar automaticamente (com Atualização Rápida habilitada) ou Cmd ⌘/Ctrl + R para recarregar (com Atualização Rápida desabilitada).

Ferramentas para desenvolvedores do Chrome

Para depurar o código JavaScript no Chrome, selecione "Open Debugger" no menu Dev. Isso abrirá uma nova guia em http://localhost:8081/debugger-ui.

A partir daqui, selecione More Tools → Developer Tools no menu do Chrome para abrir o Chrome DevTools. Alternativamente, você pode usar o atalho ⌥ Option + Cmd ⌘ + I (macOS) / Ctrl + Shift + I (Windows e Linux).

  • Se você é novo no Chrome DevTools, recomendamos aprender sobre as guias Console e Fontes nos documentos.
  • Você pode querer habilitar Pause on Caught Exceptions para uma melhor experiência de depuração.

INFORMAÇÕES

A extensão React Developer Tools Chrome não funciona com React Native, mas você pode usar sua versão independente. Leia esta seção para saber como.

DICA

No Android, se os tempos entre o depurador e o dispositivo variarem, coisas como animações e comportamento de eventos poderão não funcionar corretamente. Isso pode ser corrigido executando adb shell "date date +%m%d%H%M%Y.%S%3N". O acesso root é necessário se estiver usando um dispositivo físico.

Depuração em um dispositivo físico

Informações

Se você estiver usando Expo CLI, isso já está configurado para você.

Android

Em dispositivos Android 5.0+ conectados via USB, você pode usar a ferramenta de linha de comando adb para configurar o encaminhamento de porta do dispositivo para o seu computador:

bash
adb reverse tcp:8081 tcp:8081

Como alternativa, selecione “Configurações” no menu Dev e atualize a configuração “Host do servidor de depuração para dispositivo” para corresponder ao endereço IP do seu computador.

iOS

Em dispositivos iOS, abra o arquivo RCTWebSocketExecutor.mm e altere "localhost" para o endereço IP do seu computador e selecione "Debug JS Remotely" no menu Dev.

Observação

Se você tiver algum problema, pode ser que uma de suas extensões do Chrome esteja interagindo de maneira inesperada com o depurador. Tente desabilitar todas as suas extensões e reativá-las uma por uma até encontrar a extensão problemática.

Avançado: depuração usando um depurador JavaScript personalizado

Para usar um depurador JavaScript personalizado no lugar das Ferramentas de desenvolvedor do Chrome, defina a variável de ambiente REACT_DEBUGGER como um comando que iniciará seu depurador personalizado. Você pode então selecionar "Open Debugger" no menu Dev para iniciar a depuração.

O depurador receberá uma lista de todas as raízes do projeto, separadas por um espaço. Por exemplo, se você definir REACT_DEBUGGER="node /path/to/launchDebugger.js --port 2345 --type ReactNative", então o comando node /path/to/launchDebugger.js --port 2345 --type ReactNative /path/to/reactNative/app será usado para iniciar seu depurador.

Observação

Os comandos do depurador personalizado executados dessa maneira devem ser processos de curta duração e não devem produzir mais de 200 kilobytes de saída.

Ferramentas para desenvolvedores Safari

Você pode usar o Safari para depurar a versão iOS do seu aplicativo sem precisar ativar "Depurar JS remotamente".

  • Em um dispositivo físico, vá para: Settings → Safari → Advanced → Make sure "Web Inspector" is turned on (esta etapa não é necessária no Simulador)
  • No seu Mac, ative o menu Desenvolver no Safari: Settings... (or Preferences...) → Advanced → Select "Show Develop menu in menu bar"
  • Selecione o JSContext do seu aplicativo: Develop → Simulator (or other device) → JSContext
  • O Web Inspector do Safari deve abrir, contendo um console e um depurador

Embora os mapas de origem possam não estar habilitados por padrão, você pode seguir este guia ou vídeo para habilitá-los e definir pontos de interrupção nos locais certos no código-fonte.

No entanto, sempre que o aplicativo é recarregado (usando recarregamento ao vivo ou recarregando manualmente), um novo JSContext é criado. Escolher "Mostrar automaticamente inspetores da Web para JSContexts" evita que você tenha que selecionar manualmente o JSContext mais recente.

Monitor de desempenho

Você pode ativar uma sobreposição de desempenho para ajudá-lo a depurar problemas de desempenho selecionando "Perf Monitor" no menu Dev.

`,43),n=[t];function d(c,l,p,u,m,h){return a(),o("div",null,n)}const b=e(i,[["render",d]]);export{g as __pageData,b as default}; diff --git a/vitepress/docs/.vitepress/dist/assets/docs_debugging.md.DXY2CnKb.lean.js b/vitepress/docs/.vitepress/dist/assets/docs_debugging.md.DXY2CnKb.lean.js new file mode 100644 index 0000000..2c5cdbe --- /dev/null +++ b/vitepress/docs/.vitepress/dist/assets/docs_debugging.md.DXY2CnKb.lean.js @@ -0,0 +1 @@ +import{_ as e,c as o,o as a,a4 as s}from"./chunks/framework.nQaBHiNx.js";const r="/assets/307929568-c4514d57-633d-48d7-acd8-85b15c785dee.BSCw5qYK.png",g=JSON.parse('{"title":"Noções básicas de depuração","description":"","frontmatter":{},"headers":[],"relativePath":"docs/debugging.md","filePath":"docs/debugging.md"}'),i={name:"docs/debugging.md"},t=s("",43),n=[t];function d(c,l,p,u,m,h){return a(),o("div",null,n)}const b=e(i,[["render",d]]);export{g as __pageData,b as default}; diff --git a/vitepress/docs/.vitepress/dist/assets/docs_direct-manipulation.md.DDnwwmfN.js b/vitepress/docs/.vitepress/dist/assets/docs_direct-manipulation.md.DDnwwmfN.js new file mode 100644 index 0000000..8619c9e --- /dev/null +++ b/vitepress/docs/.vitepress/dist/assets/docs_direct-manipulation.md.DDnwwmfN.js @@ -0,0 +1,264 @@ +import{_ as s,c as i,o as a,a4 as n}from"./chunks/framework.nQaBHiNx.js";const y=JSON.parse('{"title":"Manipulação Direta","description":"","frontmatter":{},"headers":[],"relativePath":"docs/direct-manipulation.md","filePath":"docs/direct-manipulation.md"}'),t={name:"docs/direct-manipulation.md"},e=n(`

Manipulação Direta

Às vezes é necessário fazer alterações diretamente em um componente sem usar state/props para acionar uma nova renderização de toda a subárvore. Ao usar React no navegador, por exemplo, às vezes você precisa modificar diretamente um nó DOM, e o mesmo se aplica a visualizações em aplicativos móveis. setNativeProps é o equivalente React Native para definir propriedades diretamente em um nó DOM.

ATENÇÃO

Use setNativeProps quando a nova renderização frequentemente criar um gargalo de desempenho!

A manipulação direta não será uma ferramenta que você utiliza com frequência. Normalmente, você o usará apenas para criar animações contínuas para evitar a sobrecarga de renderizar a hierarquia de componentes e reconciliar muitas visualizações.

setNativeProps é imperativo e armazena o estado na camada nativa (DOM, UIView, etc.) e não nos componentes do React, o que torna seu código mais difícil de compreender.

Antes de usá-lo, tente resolver seu problema com setState e shouldComponentUpdate.

setNativeProps com TouchableOpacity

TouchableOpacity usa setNativeProps internamente para atualizar a opacidade de seu filho componente:

tsx
const viewRef = useRef<View>();
+const setOpacityTo = useCallback(value => {
+  // Redigido: código relacionado à animação
+  viewRef.current.setNativeProps({
+    opacity: value,
+  });
+}, []);

Isso nos permite escrever o código a seguir e saber que a criança terá sua opacidade atualizada em resposta aos toques, sem que a criança tenha conhecimento desse fato ou exija quaisquer alterações em sua implementação:

tsx
<TouchableOpacity onPress={handlePress}>
+  <View>
+    <Text>Press me!</Text>
+  </View>
+</TouchableOpacity>

Vamos imaginar que setNativeProps não estava disponível. Uma maneira de implementá-lo com essa restrição é armazenar o valor de opacidade no estado e, em seguida, atualizar esse valor sempre que onPress for acionado:

tsx
const [buttonOpacity, setButtonOpacity] = useState(1);
+return (
+  <TouchableOpacity
+    onPressIn={() => setButtonOpacity(0.5)}
+    onPressOut={() => setButtonOpacity(1)}>
+    <View style={{opacity: buttonOpacity}}>
+      <Text>Press me!</Text>
+    </View>
+  </TouchableOpacity>
+);

Isso é computacionalmente intensivo em comparação com o exemplo original - o React precisa renderizar novamente a hierarquia de componentes cada vez que a opacidade muda, mesmo que outras propriedades da visualização e de seus filhos não tenham mudado. Normalmente, essa sobrecarga não é uma preocupação, mas ao executar animações contínuas e responder a gestos, otimizar criteriosamente seus componentes pode melhorar a fidelidade de suas animações.

Se você observar a implementação de setNativeProps em NativeMethodsMixin, você notará que é um wrapper em torno de RCTUIManager.updateView - esta é exatamente a mesma chamada de função que resulta da nova renderização - consulte [receiveComponent in ReactNativeBaseComponent](https://github.com/facebook/react-native /blob/fb2ec1ea47c53c2e7b873acb1cb46192ac74274e/Libraries/Renderer/oss/ReactNativeRenderer-prod.js#L5793-L5813).

Componentes compostos e setNativeProps

Os componentes compostos não são apoiados por uma visualização nativa, portanto você não pode chamar setNativeProps neles. Considere este exemplo:

jsx
import React from 'react';
+import {Text, TouchableOpacity, View} from 'react-native';
+
+const MyButton = props => (
+  <View style={{marginTop: 50}}>
+    <Text>{props.label}</Text>
+  </View>
+);
+
+const App = () => (
+  <TouchableOpacity>
+    <MyButton label="Press me!" />
+  </TouchableOpacity>
+);
+
+export default App;
tsx
import React from 'react';
+import {Text, TouchableOpacity, View} from 'react-native';
+
+const MyButton = (props: {label: string}) => (
+  <View style={{marginTop: 50}}>
+    <Text>{props.label}</Text>
+  </View>
+);
+
+const App = () => (
+  <TouchableOpacity>
+    <MyButton label="Press me!" />
+  </TouchableOpacity>
+);
+
+export default App;

Se você executar isso, verá imediatamente este erro: "Touchable child must either be native or forward setNativeProps to a native component" (O filho tocável deve ser nativo ou encaminhar setNativeProps para um componente nativo. Isso ocorre porque MyButton não é apoiado diretamente por uma visualização nativa cuja opacidade deve ser definida. Você pode pensar assim: se você definir um componente com createReactClass você não esperaria ser capaz de definir um suporte de estilo nele e fazer isso funcionar - você precisaria passar o suporte de estilo para um filho, a menos que você esteja agrupando um componente nativo. Da mesma forma, encaminharemos setNativeProps para um componente filho com suporte nativo.

Encaminha setNativeProps para um filho

Como o método setNativeProps existe em qualquer referência a um componente View, é suficiente encaminhar uma referência em seu componente personalizado para um dos componentes <View /> que ele renderiza. Isso significa que uma chamada para setNativeProps no componente personalizado terá o mesmo efeito como se você chamasse setNativeProps no próprio componente View encapsulado.

js
import React from 'react';
+import {Text, TouchableOpacity, View} from 'react-native';
+
+const MyButton = React.forwardRef((props, ref) => (
+  <View {...props} ref={ref} style={{marginTop: 50}}>
+    <Text>{props.label}</Text>
+  </View>
+));
+
+const App = () => (
+  <TouchableOpacity>
+    <MyButton label="Press me!" />
+  </TouchableOpacity>
+);
+
+export default App;
tsx
import React from 'react';
+import {Text, TouchableOpacity, View} from 'react-native';
+
+const MyButton = React.forwardRef<View, {label: string}>((props, ref) => (
+  <View {...props} ref={ref} style={{marginTop: 50}}>
+    <Text>{props.label}</Text>
+  </View>
+));
+
+const App = () => (
+  <TouchableOpacity>
+    <MyButton label="Press me!" />
+  </TouchableOpacity>
+);
+
+export default App;

Agora você pode usar MyButton dentro de TouchableOpacity!

Você deve ter notado que passamos todos os adereços para a visualização filha usando {...props}. A razão para isso é que TouchableOpacity é na verdade um componente composto e, portanto, além de depender de setNativeProps em seu filho, também requer que o filho execute o tratamento de toque. Para fazer isso, ele passa vários adereços que chamam de volta para o componente TouchableOpacity. TouchableHighlight, por outro lado, é apoiado por uma visão nativa e requer apenas que implementemos setNativeProps.

setNativeProps para editar o valor TextInput

Outro caso de uso muito comum de setNativeProps é editar o valor do TextInput. A propriedade controlled do TextInput às vezes pode descartar caracteres quando o bufferDelay está baixo e o usuário digita muito rapidamente. Alguns desenvolvedores preferem ignorar totalmente esta propriedade e, em vez disso, usar setNativeProps para manipular diretamente o valor TextInput quando necessário. Por exemplo, o código a seguir demonstra a edição da entrada quando você toca em um botão:

jsx
import React from 'react';
+import {useCallback, useRef} from 'react';
+import {
+  StyleSheet,
+  TextInput,
+  Text,
+  TouchableOpacity,
+  View,
+} from 'react-native';
+
+const App = () => {
+  const inputRef = useRef(null);
+  const editText = useCallback(() => {
+    inputRef.current.setNativeProps({text: 'Edited Text'});
+  }, []);
+
+  return (
+    <View style={styles.container}>
+      <TextInput ref={inputRef} style={styles.input} />
+      <TouchableOpacity onPress={editText}>
+        <Text>Edit text</Text>
+      </TouchableOpacity>
+    </View>
+  );
+};
+
+const styles = StyleSheet.create({
+  container: {
+    flex: 1,
+    alignItems: 'center',
+    justifyContent: 'center',
+  },
+  input: {
+    height: 50,
+    width: 200,
+    marginHorizontal: 20,
+    borderWidth: 1,
+    borderColor: '#ccc',
+  },
+});
+
+export default App;
tsx
import React from 'react';
+import {useCallback, useRef} from 'react';
+import {
+  StyleSheet,
+  TextInput,
+  Text,
+  TouchableOpacity,
+  View,
+} from 'react-native';
+
+const App = () => {
+  const inputRef = useRef<TextInput>(null);
+  const editText = useCallback(() => {
+    inputRef.current?.setNativeProps({text: 'Edited Text'});
+  }, []);
+
+  return (
+    <View style={styles.container}>
+      <TextInput ref={inputRef} style={styles.input} />
+      <TouchableOpacity onPress={editText}>
+        <Text>Edit text</Text>
+      </TouchableOpacity>
+    </View>
+  );
+};
+
+const styles = StyleSheet.create({
+  container: {
+    flex: 1,
+    alignItems: 'center',
+    justifyContent: 'center',
+  },
+  input: {
+    height: 50,
+    width: 200,
+    marginHorizontal: 20,
+    borderWidth: 1,
+    borderColor: '#ccc',
+  },
+});
+
+export default App;

Você pode usar o método clear para limpar o TextInput que limpa o texto de entrada atual usando a mesma abordagem.

Evitando conflitos com a função render

Se você atualizar uma propriedade que também é gerenciada pela função de renderização, poderá acabar com alguns bugs imprevisíveis e confusos porque sempre que o componente for renderizado novamente e essa propriedade mudar, qualquer valor que tenha sido definido anteriormente em setNativeProps será completamente ignorado e substituído.

setNativeProps e shouldComponentUpdate

Ao aplicar de forma inteligente shouldComponentUpdate, você pode evitar a sobrecarga desnecessária envolvida na reconciliação de subárvores de componentes inalteradas a ponto de ter um desempenho suficiente, basta usar setState em vez de setNativeProps.

Outros métodos nativos

Os métodos descritos aqui estão disponíveis na maioria dos componentes padrão fornecidos pelo React Native. Observe, entretanto, que eles não estão disponíveis em componentes compostos que não sejam diretamente apoiados por uma visualização nativa. Geralmente, isso incluirá a maioria dos componentes definidos em seu próprio aplicativo.

measure(callback)

Determina a localização na tela, largura e altura na janela de visualização da view fornecida e retorna os valores por meio de um retorno de chamada assíncrono. Se for bem-sucedido, o retorno de chamada será chamado com os seguintes argumentos:

  • x
  • y
  • width
  • height
  • pageX
  • pageY

Observe que essas medidas não estarão disponíveis até que a renderização seja concluída no modo nativo. Se você precisar das medidas o mais rápido possível e não precisar de pageX e pageY, considere usar a propriedade onLayout.

Além disso, a largura e a altura retornadas por measure() são a largura e a altura do componente na janela de visualização. Se você precisar do tamanho real do componente, considere usar a propriedade onLayout.

measureInWindow(callback)

Determina a localização da visualização fornecida na janela e retorna os valores por meio de um retorno de chamada assíncrono. Se a visualização raiz do React estiver incorporada em outra visualização nativa, isso fornecerá as coordenadas absolutas. Se for bem-sucedido, o retorno de chamada será chamado com os seguintes argumentos:

  • x
  • y
  • width
  • height

measureLayout(relativeToNativeComponentRef, onSuccess, onFail)

Como measure(), mas mede a visualização relativa a um ancestral, especificado com a referência relativeToNativeComponentRef. Isso significa que as coordenadas retornadas são relativas à origem x, y da visão ancestral.

Observação

Este método também pode ser chamado com um manipulador relativeToNativeNode (em vez de referência), mas esta variante está obsoleta.

jsx
import React, {useEffect, useRef, useState} from 'react';
+import {Text, View, StyleSheet} from 'react-native';
+
+const App = () => {
+  const textContainerRef = useRef(null);
+  const textRef = useRef(null);
+  const [measure, setMeasure] = useState(null);
+
+  useEffect(() => {
+    if (textRef.current && textContainerRef.current) {
+      textRef.current.measureLayout(
+        textContainerRef.current,
+        (left, top, width, height) => {
+          setMeasure({left, top, width, height});
+        },
+      );
+    }
+  }, [measure]);
+
+  return (
+    <View style={styles.container}>
+      <View ref={textContainerRef} style={styles.textContainer}>
+        <Text ref={textRef}>Where am I? (relative to the text container)</Text>
+      </View>
+      <Text style={styles.measure}>{JSON.stringify(measure)}</Text>
+    </View>
+  );
+};
+
+const styles = StyleSheet.create({
+  container: {
+    flex: 1,
+    justifyContent: 'center',
+  },
+  textContainer: {
+    backgroundColor: '#61dafb',
+    justifyContent: 'center',
+    alignItems: 'center',
+    padding: 12,
+  },
+  measure: {
+    textAlign: 'center',
+    padding: 12,
+  },
+});
+
+export default App;
tsx
import React, {useEffect, useRef, useState} from 'react';
+import {Text, View, StyleSheet} from 'react-native';
+
+type Measurements = {
+  left: number;
+  top: number;
+  width: number;
+  height: number;
+};
+
+const App = () => {
+  const textContainerRef = useRef<View>(null);
+  const textRef = useRef<Text>(null);
+  const [measure, setMeasure] = useState<Measurements | null>(null);
+
+  useEffect(() => {
+    if (textRef.current && textContainerRef.current) {
+      textRef.current?.measureLayout(
+        textContainerRef.current,
+        (left, top, width, height) => {
+          setMeasure({left, top, width, height});
+        },
+        () => {
+          console.error('measurement failed');
+        },
+      );
+    }
+  }, [measure]);
+
+  return (
+    <View style={styles.container}>
+      <View ref={textContainerRef} style={styles.textContainer}>
+        <Text ref={textRef}>Where am I? (relative to the text container)</Text>
+      </View>
+      <Text style={styles.measure}>{JSON.stringify(measure)}</Text>
+    </View>
+  );
+};
+
+const styles = StyleSheet.create({
+  container: {
+    flex: 1,
+    justifyContent: 'center',
+  },
+  textContainer: {
+    backgroundColor: '#61dafb',
+    justifyContent: 'center',
+    alignItems: 'center',
+    padding: 12,
+  },
+  measure: {
+    textAlign: 'center',
+    padding: 12,
+  },
+});
+
+export default App;

focus()

Solicita foco para a entrada ou visualização fornecida. O comportamento exato acionado dependerá da plataforma e do tipo de visualização.

blur()

Remove o foco de uma entrada ou visualização. Este é o oposto de focus().

`,51),h=[e];function l(p,k,E,r,d,o){return a(),i("div",null,h)}const c=s(t,[["render",l]]);export{y as __pageData,c as default}; diff --git a/vitepress/docs/.vitepress/dist/assets/docs_direct-manipulation.md.DDnwwmfN.lean.js b/vitepress/docs/.vitepress/dist/assets/docs_direct-manipulation.md.DDnwwmfN.lean.js new file mode 100644 index 0000000..a2104d6 --- /dev/null +++ b/vitepress/docs/.vitepress/dist/assets/docs_direct-manipulation.md.DDnwwmfN.lean.js @@ -0,0 +1 @@ +import{_ as s,c as i,o as a,a4 as n}from"./chunks/framework.nQaBHiNx.js";const y=JSON.parse('{"title":"Manipulação Direta","description":"","frontmatter":{},"headers":[],"relativePath":"docs/direct-manipulation.md","filePath":"docs/direct-manipulation.md"}'),t={name:"docs/direct-manipulation.md"},e=n("",51),h=[e];function l(p,k,E,r,d,o){return a(),i("div",null,h)}const c=s(t,[["render",l]]);export{y as __pageData,c as default}; diff --git a/vitepress/docs/.vitepress/dist/assets/docs_environment-setup.md.B4_6Jwis.js b/vitepress/docs/.vitepress/dist/assets/docs_environment-setup.md.B4_6Jwis.js new file mode 100644 index 0000000..eac97c5 --- /dev/null +++ b/vitepress/docs/.vitepress/dist/assets/docs_environment-setup.md.B4_6Jwis.js @@ -0,0 +1,7 @@ +import{_ as e,c as a,o,a4 as i}from"./chunks/framework.nQaBHiNx.js";const v=JSON.parse('{"title":"Configurando o ambiente de desenvolvimento","description":"","frontmatter":{},"headers":[],"relativePath":"docs/environment-setup.md","filePath":"docs/environment-setup.md"}'),s={name:"docs/environment-setup.md"},t=i(`

Configurando o ambiente de desenvolvimento

Esta página te ajudará a instalar e construir seu primeiro aplicativo React Native.

Se você é novo no desenvolvimento móvel, a maneira mais fácil de começar é com o Expo Go. Expo é um conjunto de ferramentas e serviços construídos em torno do React Native e, embora tenha muitos recursos, o recurso mais relevante para nós no momento é que você pode escrever um aplicativo React Native em minutos. Você só precisará de uma versão recente do Node.js e de um telefone ou emulador. Se quiser experimentar o React Native diretamente em seu navegador antes de instalar qualquer ferramenta, você pode experimentar o Snack.

Se você já está familiarizado com o desenvolvimento móvel, você pode querer usar o React Native CLI. Requer Xcode ou Android Studio para começar. Se você já tiver uma dessas ferramentas instalada, poderá colocá-la em funcionamento em alguns minutos. Se eles não estiverem instalados, você deverá gastar cerca de uma hora instalando-os e configurando-os.

Expo Go Início Rápido

Execute o seguinte comando para criar um novo projeto React Native chamado "AwesomeProject":

bash
npx create-expo-app AwesomeProject
+
+cd AwesomeProject
+npx expo start
bash
yarn create expo-app AwesomeProject
+
+cd AwesomeProject
+yarn expo start

Isso iniciará um servidor de desenvolvimento para você.

Executando seu aplicativo React Native

Instale o aplicativo Expo Go em seu telefone iOS ou Android e conecte-se à mesma rede sem fio do seu computador. No Android, use o aplicativo Expo Go para escanear o código QR do seu terminal para abrir seu projeto. No iOS, use o leitor de código QR integrado do aplicativo iOS Camera padrão.

React Native CLI Início Rápido

Siga estas instruções se precisar criar código nativo em seu projeto. Por exemplo, se você estiver integrando o React Native em um aplicativo existente ou se executou o "prebuild" do Expo para gerar o código nativo do seu projeto, você precisará desta seção.

As instruções são um pouco diferentes dependendo do seu sistema operacional de desenvolvimento e se você deseja começar a desenvolver para iOS ou Android. Se você deseja desenvolver para Android e iOS, tudo bem - você pode escolher um para começar, já que a configuração é um pouco diferente.

macOS

Windows

Linux

`,19),n=[t];function r(d,l,c,p,u,h){return o(),a("div",null,n)}const k=e(s,[["render",r]]);export{v as __pageData,k as default}; diff --git a/vitepress/docs/.vitepress/dist/assets/docs_environment-setup.md.B4_6Jwis.lean.js b/vitepress/docs/.vitepress/dist/assets/docs_environment-setup.md.B4_6Jwis.lean.js new file mode 100644 index 0000000..9afa0e2 --- /dev/null +++ b/vitepress/docs/.vitepress/dist/assets/docs_environment-setup.md.B4_6Jwis.lean.js @@ -0,0 +1 @@ +import{_ as e,c as a,o,a4 as i}from"./chunks/framework.nQaBHiNx.js";const v=JSON.parse('{"title":"Configurando o ambiente de desenvolvimento","description":"","frontmatter":{},"headers":[],"relativePath":"docs/environment-setup.md","filePath":"docs/environment-setup.md"}'),s={name:"docs/environment-setup.md"},t=i("",19),n=[t];function r(d,l,c,p,u,h){return o(),a("div",null,n)}const k=e(s,[["render",r]]);export{v as __pageData,k as default}; diff --git a/vitepress/docs/.vitepress/dist/assets/docs_environment-setup_linux_android.md.Bjd4UZfh.js b/vitepress/docs/.vitepress/dist/assets/docs_environment-setup_linux_android.md.Bjd4UZfh.js new file mode 100644 index 0000000..eef20b1 --- /dev/null +++ b/vitepress/docs/.vitepress/dist/assets/docs_environment-setup_linux_android.md.Bjd4UZfh.js @@ -0,0 +1,5 @@ +import{_ as a}from"./chunks/download.BUUib3PP.js";import{_ as e}from"./chunks/289088717-bc864112-bd55-43b6-8369-9d78e896376e.CT8xxMv0.js";import{_ as o,c as i,o as s,a4 as t}from"./chunks/framework.nQaBHiNx.js";const f=JSON.parse('{"title":"Instalando dependências","description":"","frontmatter":{},"headers":[],"relativePath":"docs/environment-setup/linux/android.md","filePath":"docs/environment-setup/linux/android.md"}'),r={name:"docs/environment-setup/linux/android.md"},d=t(`

Instalando dependências

Você precisará do Node, da interface de linha de comando React Native, de um JDK e do Android Studio.

Embora você possa usar qualquer editor de sua escolha para desenvolver seu aplicativo, você precisará instalar o Android Studio para configurar as ferramentas necessárias para construir seu aplicativo React Native para Android.

Node

Siga as instruções de instalação da sua distribuição Linux para instalar o Node 18 ou mais recente.

Kit de desenvolvimento do Java

Atualmente, o React Native recomenda a versão 17 do Java SE Development Kit (JDK). Você pode encontrar problemas ao usar versões superiores do JDK. Você pode baixar e instalar o OpenJDK do AdoptOpenJDK ou do seu empacotador de sistema.

Ambiente de desenvolvimento Android

Configurar seu ambiente de desenvolvimento pode ser um tanto entediante se você for novo no desenvolvimento Android. Se você já estiver familiarizado com o desenvolvimento Android, talvez seja necessário configurar algumas coisas. Em ambos os casos, certifique-se de seguir cuidadosamente as próximas etapas.

1. Instale o Android Studio

Baixe e instale o Android Studio. No assistente de instalação do Android Studio, certifique-se de que as caixas ao lado de todos os itens a seguir estejam marcadas:

  • SDK Android
  • Android SDK Platform
  • Android Virtual Device

Em seguida, clique em “Next” para instalar todos esses componentes.

Nota

Se as caixas de seleção estiverem esmaecidas, você terá a chance de instalar esses componentes mais tarde.

Depois que a configuração for finalizada e a tela de boas-vindas for exibida, prossiga para a próxima etapa.

2. Instale o Android SDK

O Android Studio instala o Android SDK mais recente por padrão. Construir um aplicativo React Native com código nativo, no entanto, requer o SDK do Android 13 (Tiramisu) em particular. SDKs Android adicionais podem ser instalados por meio do SDK Manager no Android Studio.

Para fazer isso, abra o Android Studio, clique no botão "Configure" e selecione "SDK Manager".

Nota

O SDK Manager também pode ser encontrado na caixa de diálogo "Settings" do Android Studio, em Languages & Frameworks → Android SDK.

Selecione a guia "SDK Platforms" no SDK Manager e marque a caixa ao lado de "Show Package Details" no canto inferior direito. Procure e expanda a entrada Android 13 (Tiramisu) e certifique-se de que os seguintes itens estejam marcados:

  • Android SDK Platform 33
  • Intel x86 Atom_64 System Image ou Google APIs Intel x86 Atom System Image

Em seguida, selecione a guia "SDK Tools" e marque a caixa ao lado de "Show Package Details" aqui também. Procure e expanda a entrada "Android SDK Build-Tools" e certifique-se de que 33.0.0 esteja selecionado.

Por fim, clique em “Apply” para baixar e instalar o Android SDK e ferramentas de construção relacionadas.

  1. Configure a variável de ambiente ANDROID_HOME As ferramentas React Native requerem a configuração de algumas variáveis de ambiente para construir aplicativos com código nativo.

Adicione as seguintes linhas ao seu arquivo de configuração $HOME/.bash_profile ou $HOME/.bashrc (se você estiver usando zsh, então ~/.zprofile ou ~/.zshrc):

export ANDROID_HOME=$HOME/Android/Sdk
+export PATH=$PATH:$ANDROID_HOME/emulator
+export PATH=$PATH:$ANDROID_HOME/platform-tools

Usando outro Shell

.bash_profile é específico do bash. Se estiver usando outro shell, você precisará editar o arquivo de configuração específico do shell apropriado.

Digite source $HOME/.bash_profile para bash ou source $HOME/.zprofile para carregar a configuração em seu shell atual. Verifique se ANDROID_HOME foi configurado executando echo $ANDROID_HOME e os diretórios apropriados foram adicionados ao seu caminho executando echo $PATH.

Caminho do Android

Certifique-se de usar o caminho correto do Android SDK. Você pode encontrar a localização real do SDK na caixa de diálogo "Settings" do Android Studio, em Languages & Frameworks → Android SDK.

Watchman

Siga o guia de instalação do Watchman para compilar e instalar o Watchman a partir do código-fonte.

Sobre o Watchman

Watchman é uma ferramenta do Facebook para observar mudanças no sistema de arquivos. É altamente recomendável que você o instale para obter melhor desempenho e maior compatibilidade em certos casos extremos (tradução: você pode conseguir sobreviver sem instalar isso, mas sua milhagem pode variar; instalar isso agora pode evitar dores de cabeça mais tarde).

Interface de linha de comando nativa do React

React Native possui uma interface de linha de comando integrada. Em vez de instalar e gerenciar uma versão específica da CLI globalmente, recomendamos que você acesse a versão atual em tempo de execução usando npx, que acompanha o Node.js. Com npx react-native <command>, a versão estável atual da CLI será baixada e executada no momento em que o comando for executado.

Criando um novo aplicativo

Atenção

Se você instalou anteriormente um pacote global react-native-cli, remova-o, pois pode causar problemas inesperados:

bash
npm desinstalar -g react-native-cli @react-native-community/cli

React Native possui uma interface de linha de comando integrada, que você pode usar para gerar um novo projeto. Você pode acessá-lo sem instalar nada globalmente usando o npx, que acompanha o Node.js. Vamos criar um novo projeto React Native chamado "AwesomeProject":

bash
npx react-native@latest init AwesomeProject

Isso não é necessário se você estiver integrando o React Native em um aplicativo existente, se você "expulsou" da Expo ou se estiver adicionando suporte Android a um projeto React Native existente (consulte Integração com aplicativos existentes). Você também pode usar uma CLI de terceiros para iniciar seu aplicativo React Native, como Ignite CLI.

[Opcional] Usando uma versão ou modelo específico

Se quiser iniciar um novo projeto com uma versão específica do React Native, você pode usar o argumento --version:

bash
npx react-native@X.XX.X init AwesomeProject --version X.XX.X

Você também pode iniciar um projeto com um modelo React Native personalizado com o argumento --template.

Preparando o dispositivo Android

Você precisará de um dispositivo Android para executar seu aplicativo React Native para Android. Pode ser um dispositivo Android físico ou, mais comumente, você pode usar um dispositivo virtual Android que permite emular um dispositivo Android em seu computador.

De qualquer forma, você precisará preparar o dispositivo para executar aplicativos Android para desenvolvimento.

Usando um dispositivo físico

Se você tiver um dispositivo Android físico, poderá usá-lo para desenvolvimento no lugar de um AVD, conectando-o ao computador usando um cabo USB e seguindo as instruções aqui.

Usando um dispositivo virtual

Se você usar o Android Studio para abrir ./AwesomeProject/android, poderá ver a lista de dispositivos virtuais Android (AVDs) disponíveis abrindo o "AVD Manager" no Android Studio. Procure um ícone parecido com este:

image

Se você instalou recentemente o Android Studio, provavelmente precisará criar um novo AVD. Selecione "Create Virtual Device...", escolha qualquer telefone da lista e clique em "Next" e selecione a imagem Tiramisu API nível 33.

Aceleração de VM

Recomendamos configurar a aceleração de VM em seu sistema para melhorar o desempenho. Depois de seguir essas instruções, volte para o AVD Manager.

Clique em "Next" e depois em "Finish" para criar seu AVD. Neste ponto, você poderá clicar no botão de triângulo verde próximo ao seu AVD para iniciá-lo e, em seguida, prosseguir para a próxima etapa.

Executando seu aplicativo React Native

Etapa 1: iniciar o Metro

Metro é a ferramenta de construção JavaScript para React Native. Para iniciar o servidor de desenvolvimento Metro, execute o seguinte na pasta do projeto:

bash
npm start
+# ou
+yarn start

OBSERVAÇÃO

Se você estiver familiarizado com desenvolvimento web, o Metro é semelhante a empacotadores como Vite e webpack, mas foi projetado de ponta a ponta para React Native. Por exemplo, Metro usa Babel para transformar sintaxe como JSX em JavaScript executável.

Etapa 2: inicie seu aplicativo

Deixe o Metro Bundler rodar em seu próprio terminal. Abra um novo terminal dentro da pasta do projeto React Native. Execute o seguinte:

bash
npm run android
bash
yarn android

Se tudo estiver configurado corretamente, você deverá ver seu novo aplicativo em execução no emulador do Android em breve.

Essa é uma maneira de executar seu aplicativo: você também pode executá-lo diretamente no Android Studio.

Ajuda

Se você não conseguir fazer isso funcionar, consulte a página Solução de problemas.

Modificando seu aplicativo

Agora que você executou o aplicativo com sucesso, vamos modificá-lo.

  • Abra App.tsx no editor de texto de sua preferência e edite algumas linhas.
  • Pressione a tecla R duas vezes ou selecione Reload no menu Dev (Ctrl + M) para ver suas alterações!

É isso!

Parabéns! Você executou e modificou com sucesso seu primeiro aplicativo React Native.

image

E agora?

  • Se você deseja adicionar este novo código React Native a um aplicativo existente, consulte o guia de integração.

Se você estiver curioso para saber mais sobre o React Native, confira a Introdução ao React Native.

',74),n=[d];function c(l,p,u,m,h,v){return s(),i("div",null,n)}const q=o(r,[["render",c]]);export{f as __pageData,q as default}; diff --git a/vitepress/docs/.vitepress/dist/assets/docs_environment-setup_linux_android.md.Bjd4UZfh.lean.js b/vitepress/docs/.vitepress/dist/assets/docs_environment-setup_linux_android.md.Bjd4UZfh.lean.js new file mode 100644 index 0000000..792cfe1 --- /dev/null +++ b/vitepress/docs/.vitepress/dist/assets/docs_environment-setup_linux_android.md.Bjd4UZfh.lean.js @@ -0,0 +1 @@ +import{_ as a}from"./chunks/download.BUUib3PP.js";import{_ as e}from"./chunks/289088717-bc864112-bd55-43b6-8369-9d78e896376e.CT8xxMv0.js";import{_ as o,c as i,o as s,a4 as t}from"./chunks/framework.nQaBHiNx.js";const f=JSON.parse('{"title":"Instalando dependências","description":"","frontmatter":{},"headers":[],"relativePath":"docs/environment-setup/linux/android.md","filePath":"docs/environment-setup/linux/android.md"}'),r={name:"docs/environment-setup/linux/android.md"},d=t("",74),n=[d];function c(l,p,u,m,h,v){return s(),i("div",null,n)}const q=o(r,[["render",c]]);export{f as __pageData,q as default}; diff --git a/vitepress/docs/.vitepress/dist/assets/docs_environment-setup_mac-os_android.md.DzvP4V5m.js b/vitepress/docs/.vitepress/dist/assets/docs_environment-setup_mac-os_android.md.DzvP4V5m.js new file mode 100644 index 0000000..18b2809 --- /dev/null +++ b/vitepress/docs/.vitepress/dist/assets/docs_environment-setup_mac-os_android.md.DzvP4V5m.js @@ -0,0 +1,8 @@ +import{_ as a}from"./chunks/download.BUUib3PP.js";import{_ as e,c as i,o,a4 as s}from"./chunks/framework.nQaBHiNx.js";const t="/assets/288755758-175ae9d7-3e6d-42ba-9b12-a1e89bf0df53.BLU9lmvg.png",n="/assets/288759376-65fb76bd-40b8-4301-b292-a776ea55f17e.CSnjBM8e.png",f=JSON.parse('{"title":"Android","description":"","frontmatter":{},"headers":[],"relativePath":"docs/environment-setup/mac-os/android.md","filePath":"docs/environment-setup/mac-os/android.md"}'),r={name:"docs/environment-setup/mac-os/android.md"},d=s(`

Android

Instalando dependências

Você precisará do Node, do Watchman, da interface de linha de comando React Native, de um JDK e do Android Studio.

Embora você possa usar qualquer editor de sua escolha para desenvolver seu aplicativo, você precisará instalar o Android Studio para configurar as ferramentas necessárias para criar seu aplicativo React Native para Android.

Node & Watchman

Recomendamos instalar o Node e o Watchman usando o Homebrew. Execute os seguintes comandos em um Terminal após instalar o Homebrew:

bash
brew install node
+brew install watchman

Se você já instalou o Node em seu sistema, certifique-se de que seja o Node 18 ou mais recente.

Watchman é uma ferramenta do Facebook para observar mudanças no sistema de arquivos. É altamente recomendável instalá-lo para melhor desempenho.

kit de desenvolvimento do Java

Recomendamos instalar a distribuição OpenJDK chamada Azul Zulu usando Homebrew. Execute os seguintes comandos em um Terminal após instalar o Homebrew:

bash
brew tap homebrew/cask-versions
+brew install --cask zulu17
+
+# Obtenha o caminho para onde o cask foi instalado para clicar duas vezes no instalador
+brew info --cask zulu17

Depois de instalar o JDK, atualize sua variável de ambiente JAVA_HOME. Se você usou as etapas acima, o JDK provavelmente estará em /Library/Java/JavaVirtualMachines/zulu-17.jdk/Contents/Home

A distribuição Zulu OpenJDK oferece JDKs para Macs Intel e M1. Isso garantirá que suas compilações sejam mais rápidas em Macs M1 em comparação com o uso de um JDK baseado em Intel.

Se você já instalou o JDK em seu sistema, recomendamos o JDK 17. Você pode encontrar problemas ao usar versões superiores do JDK.

1. Instale o Android Studio

Baixe e instale o Android Studio. No assistente de instalação do Android Studio, certifique-se de que as caixas ao lado de todos os itens a seguir estejam marcadas:

SDK AndroidPlataforma Android SDKDispositivo virtual Android

Em seguida, clique em "Next" para instalar todos esses componentes.

Nota

Se as caixas de seleção estiverem esmaecidas, você terá a chance de instalar esses componentes mais tarde.

Depois que a configuração for finalizada e a tela de boas-vindas for exibida, prossiga para a próxima etapa.

2. Instale o Android SDK

O Android Studio instala o Android SDK mais recente por padrão. Construir um aplicativo React Native com código nativo, no entanto, requer o SDK do Android 13 (Tiramisu) em particular. SDKs Android adicionais podem ser instalados por meio do SDK Manager no Android Studio.

Para fazer isso, abra o Android Studio, clique no botão "More Actions" e selecione "SDK Manager".

image

Nota

O SDK Manager também pode ser encontrado na caixa de diálogo "Settings" do Android Studio, em Languages & Frameworks → Android SDK.

Selecione a guia "Plataformas SDK" no SDK Manager e marque a caixa ao lado de "Mostrar detalhes do pacote" no canto inferior direito. Procure e expanda a entrada Android 13 (Tiramisu) e certifique-se de que os seguintes itens estejam marcados:

  • Plataforma Android SDK 33
  • Imagem do sistema Intel x86 Atom_64 ou Google APIs Intel x86 Atom System Image ou (para Apple M1 Silicon) Google APIs ARM 64 v8a System Image

Em seguida, selecione a guia "SDK Tools" e marque a caixa ao lado de "Show Package Details" aqui também. Procure e expanda a entrada "Android SDK Build-Tools" e certifique-se de que 33.0.0 esteja selecionado.

Por fim, clique em “Apply” para baixar e instalar o Android SDK e ferramentas de construção relacionadas.

  1. Configure a variável de ambiente ANDROID_HOME As ferramentas React Native requerem a configuração de algumas variáveis de ambiente para construir aplicativos com código nativo.

Adicione as seguintes linhas ao seu arquivo de configuração ~/.zprofile ou ~/.zshrc (se você estiver usando bash, então ~/.bash_profile ou ~/.bashrc):

bash
export ANDROID_HOME=$HOME/Library/Android/sdk
+export PATH=$PATH:$ANDROID_HOME/emulator
+export PATH=$PATH:$ANDROID_HOME/platform-tools

Execute source ~/.zprofile (ou source ~/.bash_profile para bash) para carregar a configuração em seu shell atual. Verifique se ANDROID_HOME foi configurado executando echo $ANDROID_HOME e os diretórios apropriados foram adicionados ao seu caminho executando echo $PATH.

Atenção

Certifique-se de usar o caminho correto do Android SDK. Você pode encontrar a localização real do SDK na caixa de diálogo "Settings" do Languages & Frameworks → Android SDK.

Interface de linha de comando nativa do React

React Native possui uma interface de linha de comando integrada. Em vez de instalar e gerenciar uma versão específica da CLI globalmente, recomendamos que você acesse a versão atual em tempo de execução usando npx, que acompanha o Node.js. Com npx react-native <command>, a versão estável atual da CLI será baixada e executada no momento em que o comando for executado.

Criando um novo aplicativo

Atenção

Se você instalou anteriormente um pacote global react-native-cli, remova-o, pois pode causar problemas inesperados:

bash
npm uninstall -g react-native-cli @react-native-community/cli

React Native possui uma interface de linha de comando integrada, que você pode usar para gerar um novo projeto. Você pode acessá-lo sem instalar nada globalmente usando o npx, que acompanha o Node.js. Vamos criar um novo projeto React Native chamado "AwesomeProject":

bash
npx react-native@latest init AwesomeProject

Isso não é necessário se você estiver integrando o React Native em um aplicativo existente, se você "expulsou" da Expo ou se estiver adicionando suporte Android a um projeto React Native existente (consulte Integração com aplicativos existentes). Você também pode usar uma CLI de terceiros para iniciar seu aplicativo React Native, como Ignite CLI.

[Opcional] Usando uma versão ou modelo específico

Se quiser iniciar um novo projeto com uma versão específica do React Native, você pode usar o argumento --version:

bash
npx react-native@X.XX.X init AwesomeProject --version X.XX.X

Você também pode iniciar um projeto com um modelo React Native personalizado com o argumento --template.

Preparando o dispositivo Android

Você precisará de um dispositivo Android para executar seu aplicativo React Native para Android. Pode ser um dispositivo Android físico ou, mais comumente, você pode usar um dispositivo virtual Android que permite emular um dispositivo Android em seu computador.

De qualquer forma, você precisará preparar o dispositivo para executar aplicativos Android para desenvolvimento.

Usando um dispositivo físico

Se você tiver um dispositivo Android físico, poderá usá-lo para desenvolvimento no lugar de um AVD, conectando-o ao computador usando um cabo USB e seguindo as instruções aqui.

Usando um dispositivo virtual

Se você usar o Android Studio para abrir ./AwesomeProject/android, poderá ver a lista de dispositivos virtuais Android (AVDs) disponíveis abrindo o "AVD Manager" no Android Studio. Procure um ícone parecido com este:

image

Se você instalou recentemente o Android Studio, provavelmente precisará criar um novo AVD. Selecione "Create Virtual Device...", escolha qualquer telefone da lista e clique em "Next" e selecione a imagem Tiramisu API nível 33.

Clique em “Next” e depois em “Finish” para criar seu AVD. Neste ponto, você poderá clicar no botão de triângulo verde próximo ao seu AVD para iniciá-lo e, em seguida, prosseguir para a próxima etapa.

Executando seu aplicativo React Native

Etapa 1: iniciar o Metro

Metro é a ferramenta de construção JavaScript para React Native. Para iniciar o servidor de desenvolvimento Metro, execute o seguinte na pasta do projeto:

bash
npm start
bash
yarn start

OBSERVAÇÃO

Se você estiver familiarizado com desenvolvimento web, o Metro é semelhante a empacotadores como Vite e webpack, mas foi projetado de ponta a ponta para React Native. Por exemplo, Metro usa Babel para transformar sintaxe como JSX em JavaScript executável.

Step 2: Inicie sua aplicação

bash
npm run android
bash
yarn android

Se tudo estiver configurado corretamente, você deverá ver seu novo aplicativo em execução no emulador do Android em breve.

image

Essa é uma maneira de executar seu aplicativo: você também pode executá-lo diretamente no Android Studio.

Nota

Se você não conseguir fazer isso funcionar, consulte a página Solução de problemas.

Modificando seu aplicativo

Agora que você executou o aplicativo com sucesso, vamos modificá-lo.

  • Abra App.tsx no editor de texto de sua preferência e edite algumas linhas.
  • Pressione a tecla R duas vezes ou selecione Reload no menu Dev (Cmd ⌘ + M) para ver suas alterações!

É isso!

Parabéns! Você executou e modificou com sucesso seu primeiro aplicativo React Native.

image

E agora?

  • Se você deseja adicionar este novo código React Native a um aplicativo existente, consulte o guia de integração.

Se você estiver curioso para saber mais sobre o React Native, confira a Introdução ao React Native.

',76),c=[d];function l(p,h,u,m,v,k){return o(),i("div",null,c)}const F=e(r,[["render",l]]);export{f as __pageData,F as default}; diff --git a/vitepress/docs/.vitepress/dist/assets/docs_environment-setup_mac-os_android.md.DzvP4V5m.lean.js b/vitepress/docs/.vitepress/dist/assets/docs_environment-setup_mac-os_android.md.DzvP4V5m.lean.js new file mode 100644 index 0000000..dde2abf --- /dev/null +++ b/vitepress/docs/.vitepress/dist/assets/docs_environment-setup_mac-os_android.md.DzvP4V5m.lean.js @@ -0,0 +1 @@ +import{_ as a}from"./chunks/download.BUUib3PP.js";import{_ as e,c as i,o,a4 as s}from"./chunks/framework.nQaBHiNx.js";const t="/assets/288755758-175ae9d7-3e6d-42ba-9b12-a1e89bf0df53.BLU9lmvg.png",n="/assets/288759376-65fb76bd-40b8-4301-b292-a776ea55f17e.CSnjBM8e.png",f=JSON.parse('{"title":"Android","description":"","frontmatter":{},"headers":[],"relativePath":"docs/environment-setup/mac-os/android.md","filePath":"docs/environment-setup/mac-os/android.md"}'),r={name:"docs/environment-setup/mac-os/android.md"},d=s("",76),c=[d];function l(p,h,u,m,v,k){return o(),i("div",null,c)}const F=e(r,[["render",l]]);export{f as __pageData,F as default}; diff --git a/vitepress/docs/.vitepress/dist/assets/docs_environment-setup_mac-os_ios.md.DF3dIjK5.js b/vitepress/docs/.vitepress/dist/assets/docs_environment-setup_mac-os_ios.md.DF3dIjK5.js new file mode 100644 index 0000000..0fd379b --- /dev/null +++ b/vitepress/docs/.vitepress/dist/assets/docs_environment-setup_mac-os_ios.md.DF3dIjK5.js @@ -0,0 +1,3 @@ +import{_ as a}from"./chunks/289088717-bc864112-bd55-43b6-8369-9d78e896376e.CT8xxMv0.js";import{_ as e,c as o,o as s,a4 as i}from"./chunks/framework.nQaBHiNx.js";const t="/assets/289078069-79daecf4-41df-45e4-bdfd-34120ecb2d9b.DqQEPRQ3.png",n="/assets/289086561-8042a459-ead2-4b1a-ba59-41b673d9b7d8.DDX45esF.png",f=JSON.parse('{"title":"iOS","description":"","frontmatter":{},"headers":[],"relativePath":"docs/environment-setup/mac-os/ios.md","filePath":"docs/environment-setup/mac-os/ios.md"}'),r={name:"docs/environment-setup/mac-os/ios.md"},c=i(`

iOS

Instalando dependências

Você precisará de Node, Watchman, interface de linha de comando React Native, Xcode e CocoaPods.

Embora você possa usar qualquer editor de sua escolha para desenvolver seu aplicativo, você precisará instalar o Xcode para configurar as ferramentas necessárias para construir seu aplicativo React Native para iOS.

Node e Watchman

Recomendamos instalar o Node e o Watchman usando o Homebrew. Execute os seguintes comandos em um Terminal após instalar o Homebrew:

bash
brew install node
+brew install watchman

Se você já instalou o Node em seu sistema, certifique-se de que seja o Node 18 ou mais recente.

Watchman é uma ferramenta do Facebook para observar mudanças no sistema de arquivos. É altamente recomendável instalá-lo para melhor desempenho.

Xcode

A maneira mais fácil de instalar o Xcode é através da Mac App Store. A instalação do Xcode também instalará o Simulador iOS e todas as ferramentas necessárias para construir seu aplicativo iOS.

Se você já instalou o Xcode em seu sistema, certifique-se de que seja a versão 10 ou mais recente.

Ferramentas de linha de comando

Você também precisará instalar as ferramentas de linha de comando do Xcode. Abra o Xcode e escolha Settings... (ou Preferences...) no menu Xcode. Vá para o painel Locais e instale as ferramentas selecionando a versão mais recente no menu suspenso Ferramentas de linha de comando.

image

Instalando um simulador iOS no Xcode

Para instalar um simulador, abra Xcode > Settings... (ou Preferences...) e selecione a aba Platforms (ou Components). Selecione um simulador com a versão correspondente do iOS que você deseja usar.

Se você estiver usando o Xcode versão 14.0 ou superior para instalar um simulador, abra Xcode > Settings > Platforms, clique no ícone "+" e selecione a opção iOS….

CocoaPods

CocoaPods é um dos sistemas de gerenciamento de dependências disponíveis para iOS. CocoaPods é uma gem Ruby. Você pode instalar CocoaPods usando a versão do Ruby fornecida com a versão mais recente do macOS.

Para obter mais informações, visite o guia de primeiros passos do CocoaPods.

Interface de linha de comando nativa do React

React Native possui uma interface de linha de comando integrada. Em vez de instalar e gerenciar uma versão específica da CLI globalmente, recomendamos que você acesse a versão atual em tempo de execução usando npx, que acompanha o Node.js. Com npx react-native <command>, a versão estável atual da CLI será baixada e executada no momento em que o comando for executado.

Criando um novo aplicativo

Atenção!

Se você instalou anteriormente o pacote global react-native-cli, remova-o, pois pode causar problemas inesperados:

bash
npm uninstall -g react-native-cli @react-native-community/cli

Você pode usar a interface de linha de comando integrada do React Native para gerar um novo projeto. Vamos criar um novo projeto React Native chamado "AwesomeProject":

bash
npx react-native@latest init AwesomeProject

Isso não é necessário se você estiver integrando o React Native em um aplicativo existente, se você "expulsou" da Expo ou se estiver adicionando suporte a iOS ao projeto React Native existente (consulte Integração com aplicativos existentes). Você também pode usar uma CLI de terceiros para iniciar seu aplicativo React Native, como Ignite CLI.

INFORMAÇÕES

Se você estiver tendo problemas com o iOS, tente reinstalar as dependências executando:

  • cd ios para navegar até a pasta ios.
  • bundle install para instalar o Bundler
  • bundle exec pod install para instalar as dependências do iOS gerenciadas pelo CocoaPods.

[Opcional] Usando uma versão ou modelo específico

Se quiser iniciar um novo projeto com uma versão específica do React Native, você pode usar o argumento --version:

bash
npx react-native@X.XX.X init AwesomeProject --version X.XX.X

Você também pode iniciar um projeto com um modelo React Native personalizado com o argumento --template.

Nota

Se o comando acima estiver falhando, você pode ter uma versão antiga do react-native ou react-native-cli instalada globalmente no seu PC. Tente desinstalar o cli e execute-o usando npx.

[Opcional] Configurando seu ambiente

A partir do React Native versão 0.69, é possível configurar o ambiente Xcode usando o arquivo .xcode.env fornecido pelo template.

O arquivo .xcode.env contém uma variável de ambiente para exportar o caminho para o executável do node na variável NODE_BINARY. Esta é a abordagem sugerida para dissociar a infraestrutura de construção da versão do sistema do node. Você deve customizar esta variável com seu próprio caminho ou seu próprio gerenciador de versão de node, se for diferente do padrão.

Além disso, é possível adicionar qualquer outra variável de ambiente e originar o arquivo .xcode.env nas fases do script de construção. Caso você precise executar um script que requeira algum ambiente específico, esta é a abordagem sugerida: permite desacoplar as fases de construção de um ambiente específico.

INFORMAÇÕES

Se você já estiver usando NVM (um comando que ajuda a instalar e alternar entre versões do Node.js) e zsh, você pode querer mover o código que inicializa o NVM de seu ~/.zshrc para um arquivo ~/.zshenv para ajudar o Xcode a encontre seu executável Node:

bash
export NVM_DIR="$HOME/.nvm"
+[ -s "$NVM_DIR/nvm.sh" ] && \\. "$NVM_DIR/nvm.sh"  # Isso carrega o nvm

Você também pode querer garantir que toda a "fase de construção do script de shell" do seu projeto Xcode esteja usando /bin/zsh como seu shell.

Executando seu aplicativo React Native

Etapa 1: iniciar o Metro

Metro é a ferramenta de construção JavaScript para React Native. Para iniciar o servidor de desenvolvimento Metro, execute o seguinte na pasta do projeto:

bash
npm start
bash
yarn start

OBSERVAÇÃO

Se você estiver familiarizado com desenvolvimento web, o Metro é semelhante a empacotadores como Vite e webpack, mas foi projetado de ponta a ponta para React Native. Por exemplo, Metro usa Babel para transformar sintaxe como JSX em JavaScript executável.

Etapa 2: inicie seu aplicativo

Deixe o Metro Bundler rodar em seu próprio terminal. Abra um novo terminal dentro da pasta do projeto React Native. Execute o seguinte:

bash
npm run ios
bash
yarn ios

Você deverá ver seu novo aplicativo em execução no iOS Simulator em breve.

image

Esta é uma maneira de executar seu aplicativo. Você também pode executá-lo diretamente no Xcode.

Ajuda

Se você não conseguir fazer isso funcionar, consulte a página Solução de problemas.

Executando em um dispositivo

O comando acima executará automaticamente seu aplicativo no iOS Simulator por padrão. Se você deseja executar o aplicativo em um dispositivo iOS físico real, siga as instruções aqui.

Modificando seu aplicativo

Agora que você executou o aplicativo com sucesso, vamos modificá-lo.

  • Abra App.tsx no editor de texto de sua preferência e edite algumas linhas.
  • Pressione Cmd ⌘ + R no seu simulador iOS para recarregar o aplicativo e ver suas alterações!

É isso!

Parabéns! Você executou e modificou com sucesso seu primeiro aplicativo React Native.

image

E agora?

  • Se você deseja adicionar este novo código React Native a um aplicativo existente, consulte o guia de integração.

Se você estiver curioso para saber mais sobre o React Native, confira a Introdução ao React Native.

',62),d=[c];function l(p,h,u,m,v,g){return s(),o("div",null,d)}const F=e(r,[["render",l]]);export{f as __pageData,F as default}; diff --git a/vitepress/docs/.vitepress/dist/assets/docs_environment-setup_mac-os_ios.md.DF3dIjK5.lean.js b/vitepress/docs/.vitepress/dist/assets/docs_environment-setup_mac-os_ios.md.DF3dIjK5.lean.js new file mode 100644 index 0000000..fefdd02 --- /dev/null +++ b/vitepress/docs/.vitepress/dist/assets/docs_environment-setup_mac-os_ios.md.DF3dIjK5.lean.js @@ -0,0 +1 @@ +import{_ as a}from"./chunks/289088717-bc864112-bd55-43b6-8369-9d78e896376e.CT8xxMv0.js";import{_ as e,c as o,o as s,a4 as i}from"./chunks/framework.nQaBHiNx.js";const t="/assets/289078069-79daecf4-41df-45e4-bdfd-34120ecb2d9b.DqQEPRQ3.png",n="/assets/289086561-8042a459-ead2-4b1a-ba59-41b673d9b7d8.DDX45esF.png",f=JSON.parse('{"title":"iOS","description":"","frontmatter":{},"headers":[],"relativePath":"docs/environment-setup/mac-os/ios.md","filePath":"docs/environment-setup/mac-os/ios.md"}'),r={name:"docs/environment-setup/mac-os/ios.md"},c=i("",62),d=[c];function l(p,h,u,m,v,g){return s(),o("div",null,d)}const F=e(r,[["render",l]]);export{f as __pageData,F as default}; diff --git a/vitepress/docs/.vitepress/dist/assets/docs_environment-setup_windows_android.md.B0rJC79z.js b/vitepress/docs/.vitepress/dist/assets/docs_environment-setup_windows_android.md.B0rJC79z.js new file mode 100644 index 0000000..64ebc61 --- /dev/null +++ b/vitepress/docs/.vitepress/dist/assets/docs_environment-setup_windows_android.md.B0rJC79z.js @@ -0,0 +1 @@ +import{_ as e}from"./chunks/download.BUUib3PP.js";import{_ as a}from"./chunks/289088717-bc864112-bd55-43b6-8369-9d78e896376e.CT8xxMv0.js";import{_ as o,c as i,o as s,a4 as t}from"./chunks/framework.nQaBHiNx.js";const r="/assets/289275766-33a7f3de-c80c-47db-b195-35cf25023b27.CVLMUrnd.png",n="/assets/289276022-2b29397f-f3d1-41cb-a25c-84aff19487bf.DNIwmI-g.png",d="/assets/289277030-71da2fbe-ea92-48ae-b243-edf07876a7db.BSjnj2JO.png",x=JSON.parse('{"title":"Instalando dependências","description":"","frontmatter":{},"headers":[],"relativePath":"docs/environment-setup/windows/android.md","filePath":"docs/environment-setup/windows/android.md"}'),c={name:"docs/environment-setup/windows/android.md"},l=t('

Instalando dependências

Você precisará do Node, da interface de linha de comando React Native, de um JDK e do Android Studio.

Embora você possa usar qualquer editor de sua escolha para desenvolver seu aplicativo, você precisará instalar o Android Studio para configurar as ferramentas necessárias para criar seu aplicativo React Native para Android.

Node, JDK

Recomendamos instalar o Node via Chocolatey, um popular gerenciador de pacotes para Windows.

Recomenda-se usar uma versão LTS do Node. Se você quiser alternar entre versões diferentes, você pode instalar o Node via nvm-windows, um gerenciador de versões do Node para Windows.

React Native também requer Java SE Development Kit (JDK), que também pode ser instalado usando Chocolatey.

Abra um prompt de comando do administrador (clique com o botão direito em prompt de comando e selecione "Executar como administrador") e execute o seguinte comando:

bash
choco install -y nodejs-lts microsoft-openjdk17

Se você já instalou o Node em seu sistema, certifique-se de que seja o Node 18 ou mais recente. Se você já possui um JDK em seu sistema, recomendamos o JDK17. Você pode encontrar problemas ao usar versões superiores do JDK.

Node

Você pode encontrar opções de instalação adicionais na página de downloads do Nodehttps://nodejs.org/en/download/.

Java Development Kit

Se estiver usando a versão mais recente do Java Development Kit, você precisará alterar a versão Gradle do seu projeto para que ele possa reconhecer o JDK. Você pode fazer isso acessando {pasta raiz do projeto}\\android\\gradle\\wrapper\\gradle-wrapper.properties e alterando o valor DistributionUrl para atualizar a versão Gradle. Você pode conferir aqui os últimos lançamentos do Gradle.

Ambiente de desenvolvimento Android

Configurar seu ambiente de desenvolvimento pode ser um tanto entediante se você for novo no desenvolvimento Android. Se você já estiver familiarizado com o desenvolvimento Android, talvez seja necessário configurar algumas coisas. Em ambos os casos, certifique-se de seguir cuidadosamente as próximas etapas.

1. Instale o Android Studio

Baixe e instale o Android Studio. No assistente de instalação do Android Studio, certifique-se de que as caixas ao lado de todos os itens a seguir estejam marcadas:

  • SDK Android
  • Plataforma Android SDK
  • Dispositivo Virtual Android
  • Se você ainda não estiver usando Hyper-V: Performance (Intel ® HAXM) (Veja aqui para AMD ou Hyper-V)

Em seguida, clique em “Next” para instalar todos esses componentes.

Nota

Se as caixas de seleção estiverem esmaecidas, você terá a chance de instalar esses componentes mais tarde.

Depois que a configuração for finalizada e a tela de boas-vindas for exibida, prossiga para a próxima etapa.

2. Instale o Android SDK

O Android Studio instala o Android SDK mais recente por padrão. Construir um aplicativo React Native com código nativo, no entanto, requer o SDK do Android 13 (Tiramisu) em particular. SDKs Android adicionais podem ser instalados por meio do SDK Manager no Android Studio.

Para fazer isso, abra o Android Studio, clique no botão "More Actions" e selecione "SDK Manager".

image

Nota

O SDK Manager também pode ser encontrado na caixa de diálogo "Settings" do Android Studio, em Languages & Frameworks → Android SDK.

Selecione a guia "SDK Platforms" no SDK Manager e marque a caixa ao lado de "Show Package Details" no canto inferior direito. Procure e expanda a entrada Android 13 (Tiramisu) e certifique-se de que os seguintes itens estejam marcados:

  • Plataforma Android SDK 33
  • Intel x86 Atom_64 System Image ou Google APIs Intel x86 Atom System Image

Em seguida, selecione a guia "SDK Tools" e marque a caixa ao lado de "Show Package Details" aqui também. Procure e expanda a entrada Android SDK Build-Tools e certifique-se de que 33.0.0 esteja selecionado.

Por fim, clique em "Apply" para baixar e instalar o Android SDK e ferramentas de construção relacionadas.

  1. Configure a variável de ambiente ANDROID_HOME As ferramentas React Native requerem a configuração de algumas variáveis de ambiente para construir aplicativos com código nativo.

  2. Abra o Painel de Controle do Windows.

  3. Clique em Contas de usuário e clique em Contas de usuário novamente

  4. Clique em Alterar minhas variáveis de ambiente

  5. Clique em Novo... para criar uma nova variável de usuário ANDROID_HOME que aponta para o caminho para seu Android SDK:

image

O SDK é instalado, por padrão, no seguinte local:

%LOCALAPPDATA%\\Android\\Sdk

Você pode encontrar a localização real do SDK na caixa de diálogo "Settings" do Android Studio, em Languages & Frameworks → Android SDK.

Abra uma nova janela do prompt de comando para garantir que a nova variável de ambiente seja carregada antes de prosseguir para a próxima etapa.

  1. Abra o PowerShell

  2. Copie e cole *Get-ChildItem -Path Env:* no PowerShell

  3. Verifique se ANDROID_HOME foi adicionado

  4. Adicione ferramentas de plataforma ao Path

  5. Abra o Painel de Controle do Windows.

  6. Clique em Contas de usuário e clique em Contas de usuário novamente

  7. Clique em Alterar minhas variáveis de ambiente

  8. Selecione a variável Caminho.

  9. Clique em Editar.

  10. Clique em Novo e adicione o caminho para ferramentas de plataforma à lista.

O local padrão para esta pasta é:

%LOCALAPPDATA%\\Android\\Sdk\\platform-tools

Interface de linha de comando nativa do React

React Native possui uma interface de linha de comando integrada. Em vez de instalar e gerenciar uma versão específica da CLI globalmente, recomendamos que você acesse a versão atual em tempo de execução usando npx, que acompanha o Node.js. Com npx react-native <command>, a versão estável atual da CLI será baixada e executada no momento em que o comando for executado.

Criando um novo aplicativo

Atenção

Se você instalou anteriormente o pacote global react-native-cli, remova-o, pois pode causar problemas inesperados:

npm desinstalar -g react-native-cli @react-native-community/cli

React Native possui uma interface de linha de comando integrada, que você pode usar para gerar um novo projeto. Você pode acessá-lo sem instalar nada globalmente usando o npx, que acompanha o Node.js. Vamos criar um novo projeto React Native chamado "AwesomeProject":

bash
npx react-native@latest init AwesomeProject

Isso não é necessário se você estiver integrando o React Native em um aplicativo existente, se você "expulsou" da Expo ou se estiver adicionando suporte Android a um projeto React Native existente (consulte Integração com aplicativos existentes). Você também pode usar uma CLI de terceiros para iniciar seu aplicativo React Native, como Ignite CLI.

[Opcional] Usando uma versão ou modelo específico

Se quiser iniciar um novo projeto com uma versão específica do React Native, você pode usar o argumento --version:

npx react-native@X.XX.X init AwesomeProject --versão X.XX.X

Você também pode iniciar um projeto com um modelo React Native personalizado com o argumento --template.

Preparando o dispositivo Android

Você precisará de um dispositivo Android para executar seu aplicativo React Native para Android. Pode ser um dispositivo Android físico ou, mais comumente, você pode usar um dispositivo virtual Android que permite emular um dispositivo Android em seu computador.

De qualquer forma, você precisará preparar o dispositivo para executar aplicativos Android para desenvolvimento.

Usando um dispositivo físico

Se você tiver um dispositivo Android físico, poderá usá-lo para desenvolvimento no lugar de um AVD, conectando-o ao computador usando um cabo USB e seguindo as instruções aqui.

Usando um dispositivo virtual

Se você usar o Android Studio para abrir ./AwesomeProject/android, poderá ver a lista de dispositivos virtuais Android (AVDs) disponíveis abrindo o "AVD Manager" no Android Studio. Procure um ícone parecido com este:

image

Se você instalou recentemente o Android Studio, provavelmente precisará criar um novo AVD. Selecione "Create Virtual Device...", escolha qualquer telefone da lista e clique em "Next" e selecione a imagem Tiramisu API nível 33.

Nota

Se você não possui o HAXM instalado, clique em "Install HAXM" ou siga estas instruções para configurá-lo e volte para o AVD Manager.

Clique em “Next” e depois em “Finish” para criar seu AVD. Neste ponto, você poderá clicar no botão de triângulo verde próximo ao seu AVD para iniciá-lo e, em seguida, prosseguir para a próxima etapa.

Executando seu aplicativo React Native

Etapa 1: iniciar o Metro

Metro é a ferramenta de construção JavaScript para React Native. Para iniciar o servidor de desenvolvimento Metro, execute o seguinte na pasta do projeto:

bash
npm start
bash
yarn start

OBSERVAÇÃO

Se você estiver familiarizado com desenvolvimento web, o Metro é semelhante a empacotadores como Vite e webpack, mas foi projetado de ponta a ponta para React Native. Por exemplo, Metro usa Babel para transformar sintaxe como JSX em JavaScript executável.

Etapa 2: inicie seu aplicativo

Deixe o Metro Bundler rodar em seu próprio terminal. Abra um novo terminal dentro da pasta do projeto React Native. Execute o seguinte:

bash
npm run android
bash
yarn android

Se tudo configurou tudo corretamente, você deverá ver seu novo aplicativo em execução no emulador do Android em breve.

image

Essa é uma maneira de executar seu aplicativo: você também pode executá-lo diretamente no Android Studio.

Ajuda

Se você não conseguir fazer isso funcionar, consulte a página Solução de problemas.

Modificando seu aplicativo

Agora que você executou o aplicativo com sucesso, vamos modificá-lo.

  • Abra App.tsx no editor de texto de sua preferência e edite algumas linhas.
  • Pressione a tecla R duas vezes ou selecione "Reload" no menu Dev (Ctrl + M) para ver suas alterações!

É isso!

Parabéns! Você executou e modificou com sucesso seu primeiro aplicativo React Native.

image

E agora?

  • Se você deseja adicionar este novo código React Native a um aplicativo existente, consulte o guia de integração.

Se você estiver curioso para saber mais sobre o React Native, confira a Introdução ao React Native.

',81),p=[l];function u(m,v,h,g,b,k){return s(),i("div",null,p)}const S=o(c,[["render",u]]);export{x as __pageData,S as default}; diff --git a/vitepress/docs/.vitepress/dist/assets/docs_environment-setup_windows_android.md.B0rJC79z.lean.js b/vitepress/docs/.vitepress/dist/assets/docs_environment-setup_windows_android.md.B0rJC79z.lean.js new file mode 100644 index 0000000..168822b --- /dev/null +++ b/vitepress/docs/.vitepress/dist/assets/docs_environment-setup_windows_android.md.B0rJC79z.lean.js @@ -0,0 +1 @@ +import{_ as e}from"./chunks/download.BUUib3PP.js";import{_ as a}from"./chunks/289088717-bc864112-bd55-43b6-8369-9d78e896376e.CT8xxMv0.js";import{_ as o,c as i,o as s,a4 as t}from"./chunks/framework.nQaBHiNx.js";const r="/assets/289275766-33a7f3de-c80c-47db-b195-35cf25023b27.CVLMUrnd.png",n="/assets/289276022-2b29397f-f3d1-41cb-a25c-84aff19487bf.DNIwmI-g.png",d="/assets/289277030-71da2fbe-ea92-48ae-b243-edf07876a7db.BSjnj2JO.png",x=JSON.parse('{"title":"Instalando dependências","description":"","frontmatter":{},"headers":[],"relativePath":"docs/environment-setup/windows/android.md","filePath":"docs/environment-setup/windows/android.md"}'),c={name:"docs/environment-setup/windows/android.md"},l=t("",81),p=[l];function u(m,v,h,g,b,k){return s(),i("div",null,p)}const S=o(c,[["render",u]]);export{x as __pageData,S as default}; diff --git a/vitepress/docs/.vitepress/dist/assets/docs_fast-refresh.md.CBUe46rB.js b/vitepress/docs/.vitepress/dist/assets/docs_fast-refresh.md.CBUe46rB.js new file mode 100644 index 0000000..3e2d00b --- /dev/null +++ b/vitepress/docs/.vitepress/dist/assets/docs_fast-refresh.md.CBUe46rB.js @@ -0,0 +1 @@ +import{_ as e,c as a,o,a4 as r}from"./chunks/framework.nQaBHiNx.js";const h=JSON.parse('{"title":"Atualização rápida","description":"","frontmatter":{},"headers":[],"relativePath":"docs/fast-refresh.md","filePath":"docs/fast-refresh.md"}'),s={name:"docs/fast-refresh.md"},t=r('

Atualização rápida

Fast Refresh é um recurso do React Native que permite obter feedback quase instantâneo sobre alterações em seus componentes React. A atualização rápida está habilitada por padrão e você pode alternar "Enable Fast Refresh" no menu React Native Dev. Com a Atualização rápida ativada, a maioria das edições deve ficar visível em um ou dois segundos.

Como funciona

  • Se você editar um módulo que exporta apenas componentes React, o Fast Refresh atualizará o código apenas para esse módulo e renderizará novamente seu componente. Você pode editar qualquer coisa nesse arquivo, incluindo estilos, lógica de renderização, manipuladores de eventos ou efeitos.
  • Se você editar um módulo com exportações que não sejam componentes do React, o Fast Refresh executará novamente esse módulo e os outros módulos que o importam. Portanto, se Button.js e Modal.js importarem Theme.js, a edição de Theme.js atualizará ambos os componentes.
  • Finalmente, se você editar um arquivo importado por módulos fora da árvore React, o Fast Refresh voltará a fazer uma recarga completa. Você pode ter um arquivo que renderiza um componente React, mas também exporta um valor que é importado por um componente não React. Por exemplo, talvez seu componente também exporte uma constante e um módulo utilitário não React a importe. Nesse caso, considere migrar a constante para um arquivo separado e importá-la para ambos os arquivos. Isso reativará o funcionamento do Fast Refresh. Outros casos geralmente podem ser resolvidos de maneira semelhante.

Resiliência a erros

Se você cometer um erro de sintaxe durante uma sessão de atualização rápida, poderá corrigi-lo e salvar o arquivo novamente. A caixa vermelha desaparecerá. Módulos com erros de sintaxe são impedidos de serem executados, portanto você não precisará recarregar o aplicativo.

Se você cometer um erro de tempo de execução durante a inicialização do módulo (por exemplo, digitando Style.create em vez de StyleSheet.create), a sessão de atualização rápida continuará depois que o erro for corrigido. A caixa vermelha desaparecerá e o módulo será atualizado.

Se você cometer um erro que leve a um erro de tempo de execução dentro do seu componente, a sessão de atualização rápida também continuará após a correção do erro. Nesse caso, o React remontará seu aplicativo usando o código atualizado.

Se você tiver limites de erro em seu aplicativo (o que é uma boa ideia para falhas normais na produção), eles tentarão renderizar novamente na próxima edição após uma caixa vermelha. Nesse sentido, ter um limite de erro pode impedir que você seja sempre expulso da tela raiz do aplicativo. No entanto, lembre-se de que os limites de erro não devem ser muito granulares. Eles são usados pelo React em produção e devem sempre ser projetados intencionalmente.

Limitações

O Fast Refresh tenta preservar o estado React local no componente que você está editando, mas somente se for seguro fazê-lo. Aqui estão alguns motivos pelos quais você pode ver o estado local sendo redefinido a cada edição de um arquivo:

  • O estado local não é preservado para componentes de classe (apenas componentes de função e Hooks preservam o estado).
  • O módulo que você está editando pode ter outras exportações além de um componente React.
  • Às vezes, um módulo exportaria o resultado da chamada de um componente de ordem superior como createNavigationContainer(MyScreen). Se o componente retornado for uma classe, o estado será redefinido.

No longo prazo, à medida que mais da sua base de código se move para componentes de função e ganchos, você pode esperar que o estado seja preservado em mais casos.

Dicas

  • A atualização rápida preserva o estado local do React nos componentes de função (e hooks) por padrão.
  • Às vezes, você pode querer forçar a redefinição do estado e a remontagem de um componente. Por exemplo, isso pode ser útil se você estiver ajustando uma animação que só acontece na montagem. Para fazer isso, você pode adicionar // @refresh reset em qualquer lugar do arquivo que está editando. Esta diretiva é local para o arquivo e instrui o Fast Refresh a remontar os componentes definidos nesse arquivo em cada edição.

Atualização rápida e ganchos

Quando possível, a Atualização Rápida tenta preservar o estado do seu componente entre as edições. Em particular, useState e useRef preservam seus valores anteriores, desde que você não altere seus argumentos ou a ordem das chamadas do Hook.

Ganchos com dependências — como useEffect, useMemo e useCallback — sempre serão atualizados durante o Fast Refresh. Sua lista de dependências será ignorada enquanto a atualização rápida estiver acontecendo.

Por exemplo, quando você edita useMemo(() => x * 2, [x]) para useMemo(() => x * 10, [x]), ele será executado novamente mesmo que x (a dependência) não tenha mudado. Se o React não fizesse isso, sua edição não seria refletida na tela!

Às vezes, isso pode levar a resultados inesperados. Por exemplo, mesmo um useEffect com uma matriz vazia de dependências ainda seria executado novamente uma vez durante a Atualização Rápida. No entanto, escrever código resiliente a uma nova execução ocasional de useEffect é uma boa prática, mesmo sem o Fast Refresh. Isso torna mais fácil para você introduzir posteriormente novas dependências nele.

',20),i=[t];function d(n,c,u,m,l,p){return o(),a("div",null,i)}const f=e(s,[["render",d]]);export{h as __pageData,f as default}; diff --git a/vitepress/docs/.vitepress/dist/assets/docs_fast-refresh.md.CBUe46rB.lean.js b/vitepress/docs/.vitepress/dist/assets/docs_fast-refresh.md.CBUe46rB.lean.js new file mode 100644 index 0000000..3c787c5 --- /dev/null +++ b/vitepress/docs/.vitepress/dist/assets/docs_fast-refresh.md.CBUe46rB.lean.js @@ -0,0 +1 @@ +import{_ as e,c as a,o,a4 as r}from"./chunks/framework.nQaBHiNx.js";const h=JSON.parse('{"title":"Atualização rápida","description":"","frontmatter":{},"headers":[],"relativePath":"docs/fast-refresh.md","filePath":"docs/fast-refresh.md"}'),s={name:"docs/fast-refresh.md"},t=r("",20),i=[t];function d(n,c,u,m,l,p){return o(),a("div",null,i)}const f=e(s,[["render",d]]);export{h as __pageData,f as default}; diff --git a/vitepress/docs/.vitepress/dist/assets/docs_flexbox.md.BrZwMBtp.js b/vitepress/docs/.vitepress/dist/assets/docs_flexbox.md.BrZwMBtp.js new file mode 100644 index 0000000..f73e8af --- /dev/null +++ b/vitepress/docs/.vitepress/dist/assets/docs_flexbox.md.BrZwMBtp.js @@ -0,0 +1,1321 @@ +import{_ as s,c as i,o as a,a4 as n}from"./chunks/framework.nQaBHiNx.js";const l="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAPgAAAHpCAYAAACvLPGBAAAABHNCSVQICAgIfAhkiAAAABl0RVh0U29mdHdhcmUAZ25vbWUtc2NyZWVuc2hvdO8Dvz4AAAAmdEVYdENyZWF0aW9uIFRpbWUAc2VnIDI1IGRleiAyMDIzIDE1OjAyOjU41rkENgAABcJJREFUeJzt3DEKw0AMAMFc8PPz3PTyD1wcNoZlpheoWdRpzcx8gKTv2wsAzxE4hAkcwgQOYQKHMIFDmMAhTOAQJnAIEziECRzCBA5hAocwgUOYwCHs2Jpa6+Y1gEubbxtccAgTOIQJHMIEDmEChzCBQ5jAIUzgECZwCBM4hAkcwgQOYQKHMIFDmMAhTOAQJnAIEziECRzCBA5hAocwgUOYwCFM4BAmcAgTOIQJHMIEDmEChzCBQ5jAIUzgECZwCBM4hAkcwgQOYQKHMIFDmMAhTOAQJnAIEziECRzCBA5hAocwgUOYwCFM4BAmcAgTOIQJHMIEDmEChzCBQ5jAIUzgECZwCBM4hAkcwgQOYQKHMIFDmMAhTOAQJnAIEziECRzCBA5hAocwgUOYwCFM4BAmcAgTOIQJHMKOranfzVsAj3DBIUzgECZwCBM4hAkcwgQOYQKHMIFDmMAhTOAQJnAIEziECRzCBA5hAocwgUOYwCFM4BAmcAgTOIQJHMIEDmEChzCBQ5jAIUzgECZwCBM4hAkcwgQOYQKHMIFDmMAhTOAQJnAIEziECRzCBA5hAocwgUOYwCFM4BAmcAgTOIQJHMIEDmEChzCBQ5jAIUzgECZwCBM4hAkcwgQOYQKHMIFDmMAhTOAQJnAIEziECRzCBA5hAocwgUOYwCFM4BAmcAgTOIQJHMIEDmEChzCBQ5jAIUzgECZwCBM4hAkcwgQOYQKHMIFDmMAhTOAQJnAIEziECRzCBA5hAocwgUOYwCFM4BAmcAgTOIQJHMIEDmEChzCBQ5jAIUzgECZwCBM4hAkcwgQOYQKHMIFDmMAhTOAQJnAIEziECRzCBA5hAocwgUOYwCFM4BAmcAgTOIQJHMIEDmEChzCBQ5jAIUzgECZwCBM4hAkcwgQOYQKHMIFDmMAhTOAQJnAIEziECRzCBA5hAocwgUOYwCFM4BAmcAgTOIQJHMIEDmEChzCBQ5jAIUzgECZwCBM4hAkcwgQOYQKHMIFD2LEztP53rwFcmc05FxzCBA5hAocwgUOYwCFM4BAmcAgTOIQJHMIEDmEChzCBQ5jAIUzgECZwCBM4hAkcwgQOYQKHMIFDmMAhTOAQJnAIEziECRzCBA5hAocwgUOYwCFM4BAmcAgTOIQJHMIEDmEChzCBQ5jAIUzgECZwCBM4hAkcwgQOYQKHMIFDmMAhTOAQJnAIEziECRzCBA5hAocwgUOYwCFM4BAmcAgTOIQJHMIEDmEChzCBQ5jAIUzgECZwCBM4hAkcwgQOYQKHMIFDmMAhTOAQJnAIEziECRzCBA5hAocwgUOYwCFM4BAmcAgTOIQJHMIEDmEChzCBQ5jAIUzgECZwCBM4hAkcwgQOYQKHMIFDmMAhTOAQJnAIEziECRzCBA5hAocwgUOYwCFM4BAmcAgTOIQJHMIEDmEChzCBQ5jAIUzgECZwCBM4hAkcwgQOYQKHMIFDmMAhTOAQJnAIEziECRzCBA5hAocwgUOYwCFM4BAmcAgTOIQJHMIEDmEChzCBQ5jAIUzgECZwCBM4hAkcwgQOYQKHMIFDmMAhTOAQJnAIEziECRzCBA5hAocwgUOYwCFM4BAmcAgTOIQJHMIEDmEChzCBQ5jAIUzgECZwCBM4hAkcwgQOYQKHMIFDmMAhTOAQJnAIEziECRzCBA5hAocwgUOYwCFM4BAmcAgTOIQJHMIEDmEChzCBQ5jAIUzgECZwCBM4hAkcwgQOYQKHMIFDmMAhTOAQJnAIEziECRzCBA5hAocwgUOYwCFM4BAmcAgTOIQJHMIEDmEChzCBQ5jAIUzgECZwCBM4hAkcwgQOYQKHMIFDmMAhTOAQJnAIEziECRzCBA5hAocwgUOYwCFM4BAmcAgTOIQJHMIEDmEChzCBQ9iamXl7CeAZLjiECRzCBA5hAocwgUOYwCFM4BAmcAgTOIQJHMIEDmEChzCBQ5jAIewESc0QT9wKvogAAAAASUVORK5CYII=",h="/assets/292773723-4e84051a-1fec-4af3-9247-f77801e5cf2f.DPH5HlJX.png",k="/assets/292774360-4866ca27-dcd8-44d5-bc7f-d5cc864c7569.DlhRBBRV.png",p="/assets/292776696-6843784a-f791-4bd5-ab46-4ff7474071a4.B3kSNbXp.png",t="/assets/292776780-7a00c116-9d7b-447f-a495-06d36b22412a.jMbfBvi5.png",e="/assets/292776889-1c43a42c-e7d9-4023-ba05-acdc68054c4d.B3lF5OxB.png",E="/assets/292777024-b01e455d-d2d3-435e-9208-6b8fc11c3afb.Dcc4DmSJ.png",r="/assets/292777301-a9a5c486-b7e3-4f15-964d-678cc622e8d7.Cy5Owgdo.png",d="/assets/292777538-c0bbee71-c62d-4873-8d20-e04598d39a8a.Bg_JNI9Y.png",g="/assets/292777602-6f4ee12a-ddac-4dfb-9516-c093cc9282f0.CXjiaS2U.png",y="/assets/292777671-998be8d3-8e5f-4541-a938-0b3c016991ea.Br2fgusV.png",x=JSON.parse('{"title":"Layout com Flexbox","description":"","frontmatter":{},"headers":[],"relativePath":"docs/flexbox.md","filePath":"docs/flexbox.md"}'),F={name:"docs/flexbox.md"},c=n(`

Layout com Flexbox

Um componente pode especificar o layout de seus filhos usando o algoritmo Flexbox. Flexbox foi projetado para fornecer um layout consistente em diferentes tamanhos de tela.

Normalmente, você usará uma combinação de flexDirection, alignItems e justifyContent para obter o layout correto.

CUIDADO

O Flexbox funciona no React Native da mesma maneira que no CSS na web, com algumas exceções. Os padrões são diferentes, com flexDirection padronizando para coluna em vez de linha, alignContent padronizando para flex-start em vez de stretch, flexShrink padronizando para 0 em vez de 1, o parâmetro flex suportando apenas um único número.

Flex

flex definirá como seus itens irão “preencher” o espaço disponível ao longo de seu eixo principal. O espaço será dividido de acordo com a propriedade flex de cada elemento.

No exemplo a seguir, as visualizações vermelha, laranja e verde são todas filhas na visualização do contêiner que possui flex: 1 definido. A visualização vermelha usa flex: 1 , a visualização laranja usa flex: 2 e a visualização verde usa flex: 3. 1+2+3 = 6, o que significa que a visualização vermelha obterá 1/6 do espaço, a laranja 2/6 do espaço e a verde 3/6 do espaço.

jsx
import React from 'react';
+import {StyleSheet, View} from 'react-native';
+
+const Flex = () => {
+  return (
+    <View
+      style={[
+        styles.container,
+        {
+          // Tente definir \`flexDirection\` como \`"row"\`.
+          flexDirection: 'column',
+        },
+      ]}>
+      <View style={{flex: 1, backgroundColor: 'red'}} />
+      <View style={{flex: 2, backgroundColor: 'darkorange'}} />
+      <View style={{flex: 3, backgroundColor: 'green'}} />
+    </View>
+  );
+};
+
+const styles = StyleSheet.create({
+  container: {
+    flex: 1,
+    padding: 20,
+  },
+});
+
+export default Flex;

image

Direção flexível

flexDirection controla a direção na qual os filhos de um nó são dispostos. Isso também é conhecido como eixo principal. O eixo transversal é o eixo perpendicular ao eixo principal, ou o eixo no qual as linhas de quebra são dispostas.

  • column (valor padrão) Alinhe os filhos de cima para baixo. Se o empacotamento estiver ativado, a próxima linha começará à direita do primeiro item na parte superior do contêiner.
  • row Alinhe os filhos da esquerda para a direita. Se o empacotamento estiver ativado, a próxima linha começará no primeiro item à esquerda do contêiner.
  • column-reverse Alinhe os filhos de baixo para cima. Se o empacotamento estiver ativado, a próxima linha começará à direita do primeiro item na parte inferior do contêiner.
  • row-reverse Alinha os filhos da direita para a esquerda. Se o empacotamento estiver ativado, a próxima linha começará no primeiro item à direita do contêiner.

Você pode aprender mais aqui.

jsx
import React, {useState} from 'react';
+import {StyleSheet, Text, TouchableOpacity, View} from 'react-native';
+import type {PropsWithChildren} from 'react';
+
+const FlexDirectionBasics = () => {
+  const [flexDirection, setflexDirection] = useState('column');
+
+  return (
+    <PreviewLayout
+      label="flexDirection"
+      values={['column', 'row', 'row-reverse', 'column-reverse']}
+      selectedValue={flexDirection}
+      setSelectedValue={setflexDirection}>
+      <View style={[styles.box, {backgroundColor: 'powderblue'}]} />
+      <View style={[styles.box, {backgroundColor: 'skyblue'}]} />
+      <View style={[styles.box, {backgroundColor: 'steelblue'}]} />
+    </PreviewLayout>
+  );
+};
+
+type PreviewLayoutProps = PropsWithChildren<{
+  label: string;
+  values: string[];
+  selectedValue: string;
+  setSelectedValue: (value: string) => void;
+}>;
+
+const PreviewLayout = ({
+  label,
+  children,
+  values,
+  selectedValue,
+  setSelectedValue,
+}: PreviewLayoutProps) => (
+  <View style={{padding: 10, flex: 1}}>
+    <Text style={styles.label}>{label}</Text>
+    <View style={styles.row}>
+      {values.map(value => (
+        <TouchableOpacity
+          key={value}
+          onPress={() => setSelectedValue(value)}
+          style={[styles.button, selectedValue === value && styles.selected]}>
+          <Text
+            style={[
+              styles.buttonLabel,
+              selectedValue === value && styles.selectedLabel,
+            ]}>
+            {value}
+          </Text>
+        </TouchableOpacity>
+      ))}
+    </View>
+    <View style={[styles.container, {[label]: selectedValue}]}>{children}</View>
+  </View>
+);
+
+const styles = StyleSheet.create({
+  container: {
+    flex: 1,
+    marginTop: 8,
+    backgroundColor: 'aliceblue',
+  },
+  box: {
+    width: 50,
+    height: 50,
+  },
+  row: {
+    flexDirection: 'row',
+    flexWrap: 'wrap',
+  },
+  button: {
+    paddingHorizontal: 8,
+    paddingVertical: 6,
+    borderRadius: 4,
+    backgroundColor: 'oldlace',
+    alignSelf: 'flex-start',
+    marginHorizontal: '1%',
+    marginBottom: 6,
+    minWidth: '48%',
+    textAlign: 'center',
+  },
+  selected: {
+    backgroundColor: 'coral',
+    borderWidth: 0,
+  },
+  buttonLabel: {
+    fontSize: 12,
+    fontWeight: '500',
+    color: 'coral',
+  },
+  selectedLabel: {
+    color: 'white',
+  },
+  label: {
+    textAlign: 'center',
+    marginBottom: 10,
+    fontSize: 24,
+  },
+});
+
+export default FlexDirectionBasics;

image

Direção do layout

A direção do layout especifica a direção na qual os filhos e o texto em uma hierarquia devem ser dispostos. A direção do layout também afeta a que ponto o início e o fim da borda se referem. Por padrão, o React Native apresenta a direção do layout LTR. Neste modo, o início refere-se à esquerda e o fim refere-se à direita.

  • LTR (valor padrão) O texto e os filhos são dispostos da esquerda para a direita. A margem e o preenchimento aplicados ao início de um elemento são aplicados no lado esquerdo.
  • O texto RTL e os filhos são dispostos da direita para a esquerda. A margem e o preenchimento aplicados ao início de um elemento são aplicados no lado direito.
tsx
import React, {useState} from 'react';
+import {View, TouchableOpacity, Text, StyleSheet} from 'react-native';
+import type {PropsWithChildren} from 'react';
+
+const DirectionLayout = () => {
+  const [direction, setDirection] = useState('ltr');
+
+  return (
+    <PreviewLayout
+      label="direction"
+      selectedValue={direction}
+      values={['ltr', 'rtl']}
+      setSelectedValue={setDirection}>
+      <View style={[styles.box, {backgroundColor: 'powderblue'}]} />
+      <View style={[styles.box, {backgroundColor: 'skyblue'}]} />
+      <View style={[styles.box, {backgroundColor: 'steelblue'}]} />
+    </PreviewLayout>
+  );
+};
+
+type PreviewLayoutProps = PropsWithChildren<{
+  label: string;
+  values: string[];
+  selectedValue: string;
+  setSelectedValue: (value: string) => void;
+}>;
+
+const PreviewLayout = ({
+  label,
+  children,
+  values,
+  selectedValue,
+  setSelectedValue,
+}: PreviewLayoutProps) => (
+  <View style={{padding: 10, flex: 1}}>
+    <Text style={styles.label}>{label}</Text>
+    <View style={styles.row}>
+      {values.map(value => (
+        <TouchableOpacity
+          key={value}
+          onPress={() => setSelectedValue(value)}
+          style={[styles.button, selectedValue === value && styles.selected]}>
+          <Text
+            style={[
+              styles.buttonLabel,
+              selectedValue === value && styles.selectedLabel,
+            ]}>
+            {value}
+          </Text>
+        </TouchableOpacity>
+      ))}
+    </View>
+    <View style={[styles.container, {[label]: selectedValue}]}>{children}</View>
+  </View>
+);
+
+const styles = StyleSheet.create({
+  container: {
+    flex: 1,
+    marginTop: 8,
+    backgroundColor: 'aliceblue',
+  },
+  box: {
+    width: 50,
+    height: 50,
+  },
+  row: {
+    flexDirection: 'row',
+    flexWrap: 'wrap',
+  },
+  button: {
+    paddingHorizontal: 8,
+    paddingVertical: 6,
+    borderRadius: 4,
+    backgroundColor: 'oldlace',
+    alignSelf: 'flex-start',
+    marginHorizontal: '1%',
+    marginBottom: 6,
+    minWidth: '48%',
+    textAlign: 'center',
+  },
+  selected: {
+    backgroundColor: 'coral',
+    borderWidth: 0,
+  },
+  buttonLabel: {
+    fontSize: 12,
+    fontWeight: '500',
+    color: 'coral',
+  },
+  selectedLabel: {
+    color: 'white',
+  },
+  label: {
+    textAlign: 'center',
+    marginBottom: 10,
+    fontSize: 24,
+  },
+});
+
+export default DirectionLayout;

image

Justificar o conteúdo

justifyContent descreve como alinhar filhos dentro do eixo principal de seu contêiner. Por exemplo, você pode usar essa propriedade para centralizar um filho horizontalmente em um contêiner com flexDirection definido como linha ou verticalmente em um contêiner com flexDirection definido como coluna.

  • flex-start(valor padrão) Alinha os filhos de um contêiner ao início do eixo principal do contêiner.
  • flex-end Alinha os filhos de um contêiner ao final do eixo principal do contêiner.
  • center Alinha os filhos de um contêiner no centro do eixo principal do contêiner.
  • space-between Espaçar uniformemente os filhos no eixo principal do contêiner, distribuindo o espaço restante entre os filhos.
  • space-around Afaste uniformemente os filhos no eixo principal do contêiner, distribuindo o espaço restante ao redor dos filhos. Comparado ao espaço entre, usar o espaço ao redor resultará na distribuição do espaço para o início do primeiro filho e o final do último filho.

space-evenly Distribua uniformemente os filhos dentro do contêiner de alinhamento ao longo do eixo principal. O espaçamento entre cada par de itens adjacentes, a borda inicial principal e o primeiro item, e a borda final principal e o último item, são todos exatamente iguais.

Você pode aprender mais aqui.

tsx
import React, {useState} from 'react';
+import {View, TouchableOpacity, Text, StyleSheet} from 'react-native';
+import type {PropsWithChildren} from 'react';
+
+const JustifyContentBasics = () => {
+  const [justifyContent, setJustifyContent] = useState('flex-start');
+
+  return (
+    <PreviewLayout
+      label="justifyContent"
+      selectedValue={justifyContent}
+      values={[
+        'flex-start',
+        'flex-end',
+        'center',
+        'space-between',
+        'space-around',
+        'space-evenly',
+      ]}
+      setSelectedValue={setJustifyContent}>
+      <View style={[styles.box, {backgroundColor: 'powderblue'}]} />
+      <View style={[styles.box, {backgroundColor: 'skyblue'}]} />
+      <View style={[styles.box, {backgroundColor: 'steelblue'}]} />
+    </PreviewLayout>
+  );
+};
+
+type PreviewLayoutProps = PropsWithChildren<{
+  label: string;
+  values: string[];
+  selectedValue: string;
+  setSelectedValue: (value: string) => void;
+}>;
+
+const PreviewLayout = ({
+  label,
+  children,
+  values,
+  selectedValue,
+  setSelectedValue,
+}: PreviewLayoutProps) => (
+  <View style={{padding: 10, flex: 1}}>
+    <Text style={styles.label}>{label}</Text>
+    <View style={styles.row}>
+      {values.map(value => (
+        <TouchableOpacity
+          key={value}
+          onPress={() => setSelectedValue(value)}
+          style={[styles.button, selectedValue === value && styles.selected]}>
+          <Text
+            style={[
+              styles.buttonLabel,
+              selectedValue === value && styles.selectedLabel,
+            ]}>
+            {value}
+          </Text>
+        </TouchableOpacity>
+      ))}
+    </View>
+    <View style={[styles.container, {[label]: selectedValue}]}>{children}</View>
+  </View>
+);
+
+const styles = StyleSheet.create({
+  container: {
+    flex: 1,
+    marginTop: 8,
+    backgroundColor: 'aliceblue',
+  },
+  box: {
+    width: 50,
+    height: 50,
+  },
+  row: {
+    flexDirection: 'row',
+    flexWrap: 'wrap',
+  },
+  button: {
+    paddingHorizontal: 8,
+    paddingVertical: 6,
+    borderRadius: 4,
+    backgroundColor: 'oldlace',
+    alignSelf: 'flex-start',
+    marginHorizontal: '1%',
+    marginBottom: 6,
+    minWidth: '48%',
+    textAlign: 'center',
+  },
+  selected: {
+    backgroundColor: 'coral',
+    borderWidth: 0,
+  },
+  buttonLabel: {
+    fontSize: 12,
+    fontWeight: '500',
+    color: 'coral',
+  },
+  selectedLabel: {
+    color: 'white',
+  },
+  label: {
+    textAlign: 'center',
+    marginBottom: 10,
+    fontSize: 24,
+  },
+});
+
+export default JustifyContentBasics;

image

Alinhar itens

alignItems descreve como alinhar filhos ao longo do eixo cruzado de seu contêiner. É muito semelhante a justifyContent, mas em vez de aplicar ao eixo principal, alignItems aplica-se ao eixo cruzado.

  • stretch (valor padrão) Alonga os filhos de um contêiner para corresponder à altura do eixo transversal do contêiner.
  • flex-start Alinha os filhos de um contêiner ao início do eixo cruzado do contêiner.
  • flex-end Alinha os filhos de um contêiner ao final do eixo transversal do contêiner.
  • center Alinhe os filhos de um contêiner no centro do eixo transversal do contêiner.
  • baseline Alinha os filhos de um contêiner ao longo de uma linha de base comum. Cada criança pode ser definida como referência para seus pais.

INFORMAÇÕES

Para que o stretch tenha efeito, as crianças não devem ter uma dimensão fixa ao longo do eixo secundário. No exemplo a seguir, a configuração de alignItems: stretch não faz nada até que width: 50 seja removido dos filhos.

Você pode aprender mais aqui.

tsx
import React, {useState} from 'react';
+import {View, TouchableOpacity, Text, StyleSheet} from 'react-native';
+import type {PropsWithChildren} from 'react';
+
+const AlignItemsLayout = () => {
+  const [alignItems, setAlignItems] = useState('stretch');
+
+  return (
+    <PreviewLayout
+      label="alignItems"
+      selectedValue={alignItems}
+      values={['stretch', 'flex-start', 'flex-end', 'center', 'baseline']}
+      setSelectedValue={setAlignItems}>
+      <View style={[styles.box, {backgroundColor: 'powderblue'}]} />
+      <View style={[styles.box, {backgroundColor: 'skyblue'}]} />
+      <View
+        style={[
+          styles.box,
+          {
+            backgroundColor: 'steelblue',
+            width: 'auto',
+            minWidth: 50,
+          },
+        ]}
+      />
+    </PreviewLayout>
+  );
+};
+
+type PreviewLayoutProps = PropsWithChildren<{
+  label: string;
+  values: string[];
+  selectedValue: string;
+  setSelectedValue: (value: string) => void;
+}>;
+
+const PreviewLayout = ({
+  label,
+  children,
+  values,
+  selectedValue,
+  setSelectedValue,
+}: PreviewLayoutProps) => (
+  <View style={{padding: 10, flex: 1}}>
+    <Text style={styles.label}>{label}</Text>
+    <View style={styles.row}>
+      {values.map(value => (
+        <TouchableOpacity
+          key={value}
+          onPress={() => setSelectedValue(value)}
+          style={[styles.button, selectedValue === value && styles.selected]}>
+          <Text
+            style={[
+              styles.buttonLabel,
+              selectedValue === value && styles.selectedLabel,
+            ]}>
+            {value}
+          </Text>
+        </TouchableOpacity>
+      ))}
+    </View>
+    <View style={[styles.container, {[label]: selectedValue}]}>{children}</View>
+  </View>
+);
+
+const styles = StyleSheet.create({
+  container: {
+    flex: 1,
+    marginTop: 8,
+    backgroundColor: 'aliceblue',
+    minHeight: 200,
+  },
+  box: {
+    width: 50,
+    height: 50,
+  },
+  row: {
+    flexDirection: 'row',
+    flexWrap: 'wrap',
+  },
+  button: {
+    paddingHorizontal: 8,
+    paddingVertical: 6,
+    borderRadius: 4,
+    backgroundColor: 'oldlace',
+    alignSelf: 'flex-start',
+    marginHorizontal: '1%',
+    marginBottom: 6,
+    minWidth: '48%',
+    textAlign: 'center',
+  },
+  selected: {
+    backgroundColor: 'coral',
+    borderWidth: 0,
+  },
+  buttonLabel: {
+    fontSize: 12,
+    fontWeight: '500',
+    color: 'coral',
+  },
+  selectedLabel: {
+    color: 'white',
+  },
+  label: {
+    textAlign: 'center',
+    marginBottom: 10,
+    fontSize: 24,
+  },
+});
+
+export default AlignItemsLayout;

image

Alinhar-se

alignSelf tem as mesmas opções e efeitos que alignItems, mas em vez de afetar os filhos dentro de um contêiner, você pode aplicar essa propriedade a um único filho para alterar seu alinhamento dentro de seu pai. alignSelf substitui qualquer opção definida pelo pai com alignItems.

tsx
import React, {useState} from 'react';
+import {View, TouchableOpacity, Text, StyleSheet} from 'react-native';
+import type {PropsWithChildren} from 'react';
+import type {FlexAlignType} from 'react-native';
+
+const AlignSelfLayout = () => {
+  const [alignSelf, setAlignSelf] = useState<FlexAlignType>('stretch');
+
+  return (
+    <PreviewLayout
+      label="alignSelf"
+      selectedValue={alignSelf}
+      values={['stretch', 'flex-start', 'flex-end', 'center', 'baseline']}
+      setSelectedValue={setAlignSelf}>
+      <View
+        style={[
+          styles.box,
+          {
+            alignSelf,
+            width: 'auto',
+            minWidth: 50,
+            backgroundColor: 'powderblue',
+          },
+        ]}
+      />
+      <View style={[styles.box, {backgroundColor: 'skyblue'}]} />
+      <View style={[styles.box, {backgroundColor: 'steelblue'}]} />
+    </PreviewLayout>
+  );
+};
+
+type PreviewLayoutProps = PropsWithChildren<{
+  label: string;
+  values: FlexAlignType[];
+  selectedValue: string;
+  setSelectedValue: (value: FlexAlignType) => void;
+}>;
+
+const PreviewLayout = ({
+  label,
+  children,
+  values,
+  selectedValue,
+  setSelectedValue,
+}: PreviewLayoutProps) => (
+  <View style={{padding: 10, flex: 1}}>
+    <Text style={styles.label}>{label}</Text>
+    <View style={styles.row}>
+      {values.map(value => (
+        <TouchableOpacity
+          key={value}
+          onPress={() => setSelectedValue(value)}
+          style={[styles.button, selectedValue === value && styles.selected]}>
+          <Text
+            style={[
+              styles.buttonLabel,
+              selectedValue === value && styles.selectedLabel,
+            ]}>
+            {value}
+          </Text>
+        </TouchableOpacity>
+      ))}
+    </View>
+    <View style={styles.container}>{children}</View>
+  </View>
+);
+
+const styles = StyleSheet.create({
+  container: {
+    flex: 1,
+    marginTop: 8,
+    backgroundColor: 'aliceblue',
+    minHeight: 200,
+  },
+  box: {
+    width: 50,
+    height: 50,
+  },
+  row: {
+    flexDirection: 'row',
+    flexWrap: 'wrap',
+  },
+  button: {
+    paddingHorizontal: 8,
+    paddingVertical: 6,
+    borderRadius: 4,
+    backgroundColor: 'oldlace',
+    alignSelf: 'flex-start',
+    marginHorizontal: '1%',
+    marginBottom: 6,
+    minWidth: '48%',
+    textAlign: 'center',
+  },
+  selected: {
+    backgroundColor: 'coral',
+    borderWidth: 0,
+  },
+  buttonLabel: {
+    fontSize: 12,
+    fontWeight: '500',
+    color: 'coral',
+  },
+  selectedLabel: {
+    color: 'white',
+  },
+  label: {
+    textAlign: 'center',
+    marginBottom: 10,
+    fontSize: 24,
+  },
+});
+
+export default AlignSelfLayout;

image

Alinhar conteúdo

alignContent define a distribuição de linhas ao longo do eixo cruzado. Isso só tem efeito quando os itens são agrupados em várias linhas usando flexWrap.

  • flex-start (valor padrão) Alinha as linhas quebradas ao início do eixo cruzado do contêiner.
  • flex-end Alinhe as linhas quebradas ao final do eixo cruzado do contêiner.
  • stretch (valor padrão ao usar o Yoga na Web) Estica as linhas quebradas para corresponder à altura do eixo transversal do contêiner.
  • center Alinhe as linhas quebradas no centro do eixo transversal do contêiner.
  • space-between Espaçar uniformemente as linhas agrupadas ao longo do eixo cruzado do contêiner, distribuindo o espaço restante entre as linhas.
  • space-around Espaça uniformemente as linhas quebradas ao longo do eixo cruzado do contêiner, distribuindo o espaço restante ao redor das linhas. Comparado ao space-between, usar space-around resultará na distribuição do espaço no início da primeira linha e no final da última linha.

Você pode aprender mais aqui.

tsx
import React, {useState} from 'react';
+import {View, TouchableOpacity, Text, StyleSheet} from 'react-native';
+import type {PropsWithChildren} from 'react';
+
+const AlignContentLayout = () => {
+  const [alignContent, setAlignContent] = useState('flex-start');
+
+  return (
+    <PreviewLayout
+      label="alignContent"
+      selectedValue={alignContent}
+      values={[
+        'flex-start',
+        'flex-end',
+        'stretch',
+        'center',
+        'space-between',
+        'space-around',
+      ]}
+      setSelectedValue={setAlignContent}>
+      <View style={[styles.box, {backgroundColor: 'orangered'}]} />
+      <View style={[styles.box, {backgroundColor: 'orange'}]} />
+      <View style={[styles.box, {backgroundColor: 'mediumseagreen'}]} />
+      <View style={[styles.box, {backgroundColor: 'deepskyblue'}]} />
+      <View style={[styles.box, {backgroundColor: 'mediumturquoise'}]} />
+      <View style={[styles.box, {backgroundColor: 'mediumslateblue'}]} />
+      <View style={[styles.box, {backgroundColor: 'purple'}]} />
+    </PreviewLayout>
+  );
+};
+
+type PreviewLayoutProps = PropsWithChildren<{
+  label: string;
+  values: string[];
+  selectedValue: string;
+  setSelectedValue: (value: string) => void;
+}>;
+
+const PreviewLayout = ({
+  label,
+  children,
+  values,
+  selectedValue,
+  setSelectedValue,
+}: PreviewLayoutProps) => (
+  <View style={{padding: 10, flex: 1}}>
+    <Text style={styles.label}>{label}</Text>
+    <View style={styles.row}>
+      {values.map(value => (
+        <TouchableOpacity
+          key={value}
+          onPress={() => setSelectedValue(value)}
+          style={[styles.button, selectedValue === value && styles.selected]}>
+          <Text
+            style={[
+              styles.buttonLabel,
+              selectedValue === value && styles.selectedLabel,
+            ]}>
+            {value}
+          </Text>
+        </TouchableOpacity>
+      ))}
+    </View>
+    <View style={[styles.container, {[label]: selectedValue}]}>{children}</View>
+  </View>
+);
+
+const styles = StyleSheet.create({
+  container: {
+    flex: 1,
+    flexWrap: 'wrap',
+    marginTop: 8,
+    backgroundColor: 'aliceblue',
+    maxHeight: 400,
+  },
+  box: {
+    width: 50,
+    height: 80,
+  },
+  row: {
+    flexDirection: 'row',
+    flexWrap: 'wrap',
+  },
+  button: {
+    paddingHorizontal: 8,
+    paddingVertical: 6,
+    borderRadius: 4,
+    backgroundColor: 'oldlace',
+    alignSelf: 'flex-start',
+    marginHorizontal: '1%',
+    marginBottom: 6,
+    minWidth: '48%',
+    textAlign: 'center',
+  },
+  selected: {
+    backgroundColor: 'coral',
+    borderWidth: 0,
+  },
+  buttonLabel: {
+    fontSize: 12,
+    fontWeight: '500',
+    color: 'coral',
+  },
+  selectedLabel: {
+    color: 'white',
+  },
+  label: {
+    textAlign: 'center',
+    marginBottom: 10,
+    fontSize: 24,
+  },
+});
+
+export default AlignContentLayout;

image

Flex Wrap

A propriedade flexWrap é definida em contêineres e controla o que acontece quando os filhos excedem o tamanho do contêiner ao longo do eixo principal. Por padrão, os filhos são forçados a formar uma única linha (o que pode reduzir os elementos). Se o agrupamento for permitido, os itens serão agrupados em diversas linhas ao longo do eixo principal, se necessário.

Ao agrupar linhas, alignContent pode ser usado para especificar como as linhas são colocadas no contêiner. Saiba mais aqui.

tsx
import React, {useState} from 'react';
+import {View, TouchableOpacity, Text, StyleSheet} from 'react-native';
+import type {PropsWithChildren} from 'react';
+
+const FlexWrapLayout = () => {
+  const [flexWrap, setFlexWrap] = useState('wrap');
+
+  return (
+    <PreviewLayout
+      label="flexWrap"
+      selectedValue={flexWrap}
+      values={['wrap', 'nowrap']}
+      setSelectedValue={setFlexWrap}>
+      <View style={[styles.box, {backgroundColor: 'orangered'}]} />
+      <View style={[styles.box, {backgroundColor: 'orange'}]} />
+      <View style={[styles.box, {backgroundColor: 'mediumseagreen'}]} />
+      <View style={[styles.box, {backgroundColor: 'deepskyblue'}]} />
+      <View style={[styles.box, {backgroundColor: 'mediumturquoise'}]} />
+      <View style={[styles.box, {backgroundColor: 'mediumslateblue'}]} />
+      <View style={[styles.box, {backgroundColor: 'purple'}]} />
+    </PreviewLayout>
+  );
+};
+
+type PreviewLayoutProps = PropsWithChildren<{
+  label: string;
+  values: string[];
+  selectedValue: string;
+  setSelectedValue: (value: string) => void;
+}>;
+
+const PreviewLayout = ({
+  label,
+  children,
+  values,
+  selectedValue,
+  setSelectedValue,
+}: PreviewLayoutProps) => (
+  <View style={{padding: 10, flex: 1}}>
+    <Text style={styles.label}>{label}</Text>
+    <View style={styles.row}>
+      {values.map(value => (
+        <TouchableOpacity
+          key={value}
+          onPress={() => setSelectedValue(value)}
+          style={[styles.button, selectedValue === value && styles.selected]}>
+          <Text
+            style={[
+              styles.buttonLabel,
+              selectedValue === value && styles.selectedLabel,
+            ]}>
+            {value}
+          </Text>
+        </TouchableOpacity>
+      ))}
+    </View>
+    <View style={[styles.container, {[label]: selectedValue}]}>{children}</View>
+  </View>
+);
+
+const styles = StyleSheet.create({
+  container: {
+    flex: 1,
+    marginTop: 8,
+    backgroundColor: 'aliceblue',
+    maxHeight: 400,
+  },
+  box: {
+    width: 50,
+    height: 80,
+  },
+  row: {
+    flexDirection: 'row',
+    flexWrap: 'wrap',
+  },
+  button: {
+    paddingHorizontal: 8,
+    paddingVertical: 6,
+    borderRadius: 4,
+    backgroundColor: 'oldlace',
+    marginHorizontal: '1%',
+    marginBottom: 6,
+    minWidth: '48%',
+    textAlign: 'center',
+  },
+  selected: {
+    backgroundColor: 'coral',
+    borderWidth: 0,
+  },
+  buttonLabel: {
+    fontSize: 12,
+    fontWeight: '500',
+    color: 'coral',
+  },
+  selectedLabel: {
+    color: 'white',
+  },
+  label: {
+    textAlign: 'center',
+    marginBottom: 10,
+    fontSize: 24,
+  },
+});
+
+export default FlexWrapLayout;

image

Base Flexível, Crescer e Encolher

  • flexBasis é uma forma independente de eixo de fornecer o tamanho padrão de um item ao longo do eixo principal. Definir o flexBasis de um filho é semelhante a definir o width desse filho se seu pai for um contêiner com flexDirection: row ou definir o height de um filho se seu pai for um contêiner com flexDirection: column. O flexBasis de um item é o tamanho padrão desse item, o tamanho do item antes de qualquer cálculo de flexGrow e flexShrink ser executado.
  • flexGrow descreve quanto espaço dentro de um contêiner deve ser distribuído entre seus filhos ao longo do eixo principal. Depois de dispor seus filhos, um contêiner distribuirá qualquer espaço restante de acordo com os valores flex grow especificados por seus filhos.

flexGrow aceita qualquer valor de ponto flutuante >= 0, sendo 0 o valor padrão. Um contêiner distribuirá qualquer espaço restante entre seus filhos, ponderado pelos valores flexGrow dos filhos.

  • flexShrink descreve como reduzir os filhos ao longo do eixo principal no caso em que o tamanho total dos filhos excede o tamanho do contêiner no eixo principal. flexShrink é muito semelhante ao flexGrow e pode ser pensado da mesma maneira se qualquer tamanho excedente for considerado espaço restante negativo. Essas duas propriedades também funcionam bem juntas, permitindo que as crianças cresçam e diminuam conforme necessário.

flexShrink aceita qualquer valor de ponto flutuante >= 0, sendo 0 o valor padrão (na web, o padrão é 1). Um contêiner reduzirá seus filhos ponderados pelos valores flexShrink dos filhos.

Você pode aprender mais aqui.

tsx
import React, {useState} from 'react';
+import {View, Text, TextInput, StyleSheet} from 'react-native';
+import type {ViewStyle} from 'react-native';
+
+const App = () => {
+  const [powderblue, setPowderblue] = useState<ViewStyle>({
+    flexGrow: 0,
+    flexShrink: 1,
+    flexBasis: 'auto',
+  });
+  const [skyblue, setSkyblue] = useState<ViewStyle>({
+    flexGrow: 1,
+    flexShrink: 0,
+    flexBasis: 100,
+  });
+  const [steelblue, setSteelblue] = useState<ViewStyle>({
+    flexGrow: 0,
+    flexShrink: 1,
+    flexBasis: 200,
+  });
+  return (
+    <View style={styles.container}>
+      <View
+        style={[
+          styles.container,
+          {
+            flexDirection: 'row',
+            alignContent: 'space-between',
+          },
+        ]}>
+        <BoxInfo color="powderblue" {...powderblue} setStyle={setPowderblue} />
+        <BoxInfo color="skyblue" {...skyblue} setStyle={setSkyblue} />
+        <BoxInfo color="steelblue" {...steelblue} setStyle={setSteelblue} />
+      </View>
+      <View style={styles.previewContainer}>
+        <View
+          style={[
+            styles.box,
+            {
+              flexBasis: powderblue.flexBasis,
+              flexGrow: powderblue.flexGrow,
+              flexShrink: powderblue.flexShrink,
+              backgroundColor: 'powderblue',
+            },
+          ]}
+        />
+        <View
+          style={[
+            styles.box,
+            {
+              flexBasis: skyblue.flexBasis,
+              flexGrow: skyblue.flexGrow,
+              flexShrink: skyblue.flexShrink,
+              backgroundColor: 'skyblue',
+            },
+          ]}
+        />
+        <View
+          style={[
+            styles.box,
+            {
+              flexBasis: steelblue.flexBasis,
+              flexGrow: steelblue.flexGrow,
+              flexShrink: steelblue.flexShrink,
+              backgroundColor: 'steelblue',
+            },
+          ]}
+        />
+      </View>
+    </View>
+  );
+};
+
+type BoxInfoProps = ViewStyle & {
+  color: string;
+  setStyle: React.Dispatch<React.SetStateAction<ViewStyle>>;
+};
+
+const BoxInfo = ({
+  color,
+  flexBasis,
+  flexShrink,
+  setStyle,
+  flexGrow,
+}: BoxInfoProps) => (
+  <View style={[styles.row, {flexDirection: 'column'}]}>
+    <View
+      style={[
+        styles.boxLabel,
+        {
+          backgroundColor: color,
+        },
+      ]}>
+      <Text
+        style={{
+          color: '#fff',
+          fontWeight: '500',
+          textAlign: 'center',
+        }}>
+        Box
+      </Text>
+    </View>
+    <Text style={styles.label}>flexBasis</Text>
+    <TextInput
+      value={String(flexBasis)}
+      style={styles.input}
+      onChangeText={fB =>
+        setStyle(value => ({
+          ...value,
+          flexBasis: isNaN(parseInt(fB, 10)) ? 'auto' : parseInt(fB, 10),
+        }))
+      }
+    />
+    <Text style={styles.label}>flexShrink</Text>
+    <TextInput
+      value={String(flexShrink)}
+      style={styles.input}
+      onChangeText={fS =>
+        setStyle(value => ({
+          ...value,
+          flexShrink: isNaN(parseInt(fS, 10)) ? undefined : parseInt(fS, 10),
+        }))
+      }
+    />
+    <Text style={styles.label}>flexGrow</Text>
+    <TextInput
+      value={String(flexGrow)}
+      style={styles.input}
+      onChangeText={fG =>
+        setStyle(value => ({
+          ...value,
+          flexGrow: isNaN(parseInt(fG, 10)) ? undefined : parseInt(fG, 10),
+        }))
+      }
+    />
+  </View>
+);
+
+const styles = StyleSheet.create({
+  container: {
+    flex: 1,
+    paddingHorizontal: 10,
+  },
+  box: {
+    flex: 1,
+    height: 50,
+    width: 50,
+  },
+  boxLabel: {
+    minWidth: 80,
+    padding: 8,
+    borderRadius: 4,
+    marginTop: 8,
+  },
+  label: {
+    marginTop: 6,
+    fontSize: 16,
+    fontWeight: '100',
+  },
+  previewContainer: {
+    flex: 1,
+    flexDirection: 'row',
+    backgroundColor: 'aliceblue',
+  },
+  row: {
+    flex: 1,
+    flexDirection: 'row',
+    flexWrap: 'wrap',
+    alignItems: 'center',
+    marginBottom: 10,
+  },
+  input: {
+    borderBottomWidth: 1,
+    paddingVertical: 3,
+    width: 50,
+    textAlign: 'center',
+  },
+});
+
+export default App;

image

Lacuna de linha, lacuna de coluna e lacuna

  • rowGap define o tamanho da lacuna (gutter) entre as linhas de um elemento.
  • columnGap define o tamanho da lacuna (gutter) entre as colunas de um elemento.
  • gap define o tamanho do intervalo (gutter) entre linhas e colunas. É uma abreviação de rowGap e columnGap.

Você pode usar flexWrap e alignContent junto com gap para adicionar espaçamento consistente entre os itens.

tsx
import React, {useState} from 'react';
+import {View, Text, StyleSheet, TextInput} from 'react-native';
+import type {PropsWithChildren} from 'react';
+
+const RowGapAndColumnGap = () => {
+  const [rowGap, setRowGap] = useState(10);
+  const [columnGap, setColumnGap] = useState(10);
+
+  return (
+    <PreviewLayout
+      columnGap={columnGap}
+      handleColumnGapChange={setColumnGap}
+      rowGap={rowGap}
+      handleRowGapChange={setRowGap}>
+      <View style={[styles.box, styles.box1]} />
+      <View style={[styles.box, styles.box2]} />
+      <View style={[styles.box, styles.box3]} />
+      <View style={[styles.box, styles.box4]} />
+      <View style={[styles.box, styles.box5]} />
+    </PreviewLayout>
+  );
+};
+
+type PreviewLayoutProps = PropsWithChildren<{
+  columnGap: number;
+  handleColumnGapChange: (gap: number) => void;
+  rowGap: number;
+  handleRowGapChange: (gap: number) => void;
+}>;
+
+const PreviewLayout = ({
+  children,
+  handleColumnGapChange,
+  handleRowGapChange,
+  rowGap,
+  columnGap,
+}: PreviewLayoutProps) => (
+  <View style={styles.previewContainer}>
+    <View style={styles.inputContainer}>
+      <View style={styles.itemsCenter}>
+        <Text>Row Gap</Text>
+        <TextInput
+          style={styles.input}
+          value={String(rowGap)}
+          onChangeText={v => handleRowGapChange(Number(v))}
+        />
+      </View>
+      <View style={styles.itemsCenter}>
+        <Text>Column Gap</Text>
+        <TextInput
+          style={styles.input}
+          value={String(columnGap)}
+          onChangeText={v => handleColumnGapChange(Number(v))}
+        />
+      </View>
+    </View>
+    <View style={[styles.container, {rowGap, columnGap}]}>{children}</View>
+  </View>
+);
+
+const styles = StyleSheet.create({
+  itemsCenter: {alignItems: 'center'},
+  inputContainer: {
+    gap: 4,
+    flexDirection: 'row',
+    justifyContent: 'space-around',
+  },
+  previewContainer: {padding: 10, flex: 1},
+  input: {
+    borderBottomWidth: 1,
+    paddingVertical: 3,
+    width: 50,
+    textAlign: 'center',
+  },
+  container: {
+    flex: 1,
+    marginTop: 8,
+    backgroundColor: 'aliceblue',
+    maxHeight: 400,
+    flexWrap: 'wrap',
+    alignContent: 'flex-start',
+  },
+  box: {
+    width: 50,
+    height: 80,
+  },
+  box1: {
+    backgroundColor: 'orangered',
+  },
+  box2: {
+    backgroundColor: 'orange',
+  },
+  box3: {
+    backgroundColor: 'mediumseagreen',
+  },
+  box4: {
+    backgroundColor: 'deepskyblue',
+  },
+  box5: {
+    backgroundColor: 'mediumturquoise',
+  },
+});
+
+export default RowGapAndColumnGap;

image

Largura e altura

A propriedade width especifica a largura da área de conteúdo de um elemento. Da mesma forma, a propriedade height especifica a altura da área de conteúdo de um elemento.

Tanto a largura quanto a altura podem assumir os seguintes valores:

  • auto (valor padrão) React Native calcula a largura/altura do elemento com base em seu conteúdo, seja ele outros filhos, texto ou uma imagem.
  • pixels Define a largura/altura em pixels absolutos. Dependendo de outros estilos definidos no componente, esta pode ou não ser a dimensão final do nó.
  • percentage Define a largura ou altura em porcentagem da largura ou altura do pai, respectivamente.
tsx
import React, {useState} from 'react';
+import {
+  View,
+  SafeAreaView,
+  TouchableOpacity,
+  Text,
+  StyleSheet,
+} from 'react-native';
+import type {PropsWithChildren} from 'react';
+
+type Dimension = 'auto' | \`\${number}%\` | number;
+
+const WidthHeightBasics = () => {
+  const [widthType, setWidthType] = useState<Dimension>('auto');
+  const [heightType, setHeightType] = useState<Dimension>('auto');
+
+  return (
+    <PreviewLayout
+      widthType={widthType}
+      heightType={heightType}
+      widthValues={['auto', 300, '80%']}
+      heightValues={['auto', 200, '60%']}
+      setWidthType={setWidthType}
+      setHeightType={setHeightType}>
+      <View
+        style={{
+          alignSelf: 'flex-start',
+          backgroundColor: 'aliceblue',
+          height: heightType,
+          width: widthType,
+          padding: 15,
+        }}>
+        <View style={[styles.box, {backgroundColor: 'powderblue'}]} />
+        <View style={[styles.box, {backgroundColor: 'skyblue'}]} />
+        <View style={[styles.box, {backgroundColor: 'steelblue'}]} />
+      </View>
+    </PreviewLayout>
+  );
+};
+
+type PreviewLayoutProps = PropsWithChildren<{
+  widthType: Dimension;
+  heightType: Dimension;
+  widthValues: Dimension[];
+  heightValues: Dimension[];
+  setWidthType: (value: Dimension) => void;
+  setHeightType: (value: Dimension) => void;
+}>;
+
+const PreviewLayout = ({
+  children,
+  widthType,
+  heightType,
+  widthValues,
+  heightValues,
+  setWidthType,
+  setHeightType,
+}: PreviewLayoutProps) => (
+  <SafeAreaView style={{flex: 1, padding: 10}}>
+    <View style={styles.row}>
+      <Text style={styles.label}>width </Text>
+      {widthValues.map(value => (
+        <TouchableOpacity
+          key={value}
+          onPress={() => setWidthType(value)}
+          style={[styles.button, widthType === value && styles.selected]}>
+          <Text
+            style={[
+              styles.buttonLabel,
+              widthType === value && styles.selectedLabel,
+            ]}>
+            {value}
+          </Text>
+        </TouchableOpacity>
+      ))}
+    </View>
+    <View style={styles.row}>
+      <Text style={styles.label}>height </Text>
+      {heightValues.map(value => (
+        <TouchableOpacity
+          key={value}
+          onPress={() => setHeightType(value)}
+          style={[styles.button, heightType === value && styles.selected]}>
+          <Text
+            style={[
+              styles.buttonLabel,
+              heightType === value && styles.selectedLabel,
+            ]}>
+            {value}
+          </Text>
+        </TouchableOpacity>
+      ))}
+    </View>
+    {children}
+  </SafeAreaView>
+);
+
+const styles = StyleSheet.create({
+  box: {
+    width: 50,
+    height: 50,
+  },
+  row: {
+    flexDirection: 'row',
+    flexWrap: 'wrap',
+  },
+  button: {
+    padding: 8,
+    borderRadius: 4,
+    backgroundColor: 'oldlace',
+    alignSelf: 'flex-start',
+    marginRight: 10,
+    marginBottom: 10,
+  },
+  selected: {
+    backgroundColor: 'coral',
+    shadowOpacity: 0,
+    borderWidth: 0,
+  },
+  buttonLabel: {
+    fontSize: 12,
+    fontWeight: '500',
+    color: 'coral',
+  },
+  selectedLabel: {
+    color: 'white',
+  },
+  label: {
+    textAlign: 'center',
+    marginBottom: 10,
+    fontSize: 24,
+  },
+});
+
+export default WidthHeightBasics;

image

Layout Absoluto e Relativo

O tipo de position de um elemento define como ele é posicionado em seu pai.

  • relative (valor padrão) Por padrão, um elemento é posicionado relativamente. Isso significa que um elemento é posicionado de acordo com o fluxo normal do layout e, em seguida, deslocado em relação a essa posição com base nos valores top, right, bottom e left. O deslocamento não afeta a posição de nenhum elemento irmão ou pai.
  • absolute Quando posicionado de forma absoluta, um elemento não participa do fluxo normal do layout. Em vez disso, é apresentado independente de seus irmãos. A posição é determinada com base nos valores superior, direito, inferior e esquerdo.
tsx
import React, {useState} from 'react';
+import {View, TouchableOpacity, Text, StyleSheet} from 'react-native';
+import type {PropsWithChildren} from 'react';
+
+const PositionLayout = () => {
+  const [position, setPosition] = useState<'relative' | 'absolute'>('relative');
+
+  return (
+    <PreviewLayout
+      label="position"
+      selectedValue={position}
+      values={['relative', 'absolute']}
+      setSelectedValue={setPosition}>
+      <View
+        style={[
+          styles.box,
+          {
+            top: 25,
+            left: 25,
+            position,
+            backgroundColor: 'powderblue',
+          },
+        ]}
+      />
+      <View
+        style={[
+          styles.box,
+          {
+            top: 50,
+            left: 50,
+            position,
+            backgroundColor: 'skyblue',
+          },
+        ]}
+      />
+      <View
+        style={[
+          styles.box,
+          {
+            top: 75,
+            left: 75,
+            position,
+            backgroundColor: 'steelblue',
+          },
+        ]}
+      />
+    </PreviewLayout>
+  );
+};
+
+type PreviewLayoutProps = PropsWithChildren<{
+  label: string;
+  values: Array<'relative' | 'absolute'>;
+  selectedValue: string;
+  setSelectedValue: (value: 'relative' | 'absolute') => void;
+}>;
+
+const PreviewLayout = ({
+  label,
+  children,
+  values,
+  selectedValue,
+  setSelectedValue,
+}: PreviewLayoutProps) => (
+  <View style={{padding: 10, flex: 1}}>
+    <Text style={styles.label}>{label}</Text>
+    <View style={styles.row}>
+      {values.map(value => (
+        <TouchableOpacity
+          key={value}
+          onPress={() => setSelectedValue(value)}
+          style={[styles.button, selectedValue === value && styles.selected]}>
+          <Text
+            style={[
+              styles.buttonLabel,
+              selectedValue === value && styles.selectedLabel,
+            ]}>
+            {value}
+          </Text>
+        </TouchableOpacity>
+      ))}
+    </View>
+    <View style={styles.container}>{children}</View>
+  </View>
+);
+
+const styles = StyleSheet.create({
+  container: {
+    flex: 1,
+    marginTop: 8,
+    backgroundColor: 'aliceblue',
+    minHeight: 200,
+  },
+  box: {
+    width: 50,
+    height: 50,
+  },
+  row: {
+    flexDirection: 'row',
+    flexWrap: 'wrap',
+  },
+  button: {
+    paddingHorizontal: 8,
+    paddingVertical: 6,
+    borderRadius: 4,
+    backgroundColor: 'oldlace',
+    alignSelf: 'flex-start',
+    marginHorizontal: '1%',
+    marginBottom: 6,
+    minWidth: '48%',
+    textAlign: 'center',
+  },
+  selected: {
+    backgroundColor: 'coral',
+    borderWidth: 0,
+  },
+  buttonLabel: {
+    fontSize: 12,
+    fontWeight: '500',
+    color: 'coral',
+  },
+  selectedLabel: {
+    color: 'white',
+  },
+  label: {
+    textAlign: 'center',
+    marginBottom: 10,
+    fontSize: 24,
+  },
+});
+
+export default PositionLayout;

image

Indo mais fundo

Confira o playground interativo de ioga que você pode usar para entender melhor o flexbox.

Abordamos o básico, mas existem muitos outros estilos que você pode precisar para layouts. A lista completa de adereços que controlam o layout está documentada aqui.

Além disso, você pode ver alguns exemplos dos Engenheiros da Wix.

',77),o=[c];function C(B,u,A,D,m,b){return a(),i("div",null,o)}const w=s(F,[["render",C]]);export{x as __pageData,w as default}; diff --git a/vitepress/docs/.vitepress/dist/assets/docs_flexbox.md.BrZwMBtp.lean.js b/vitepress/docs/.vitepress/dist/assets/docs_flexbox.md.BrZwMBtp.lean.js new file mode 100644 index 0000000..109b9b7 --- /dev/null +++ b/vitepress/docs/.vitepress/dist/assets/docs_flexbox.md.BrZwMBtp.lean.js @@ -0,0 +1 @@ +import{_ as s,c as i,o as a,a4 as n}from"./chunks/framework.nQaBHiNx.js";const l="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAPgAAAHpCAYAAACvLPGBAAAABHNCSVQICAgIfAhkiAAAABl0RVh0U29mdHdhcmUAZ25vbWUtc2NyZWVuc2hvdO8Dvz4AAAAmdEVYdENyZWF0aW9uIFRpbWUAc2VnIDI1IGRleiAyMDIzIDE1OjAyOjU41rkENgAABcJJREFUeJzt3DEKw0AMAMFc8PPz3PTyD1wcNoZlpheoWdRpzcx8gKTv2wsAzxE4hAkcwgQOYQKHMIFDmMAhTOAQJnAIEziECRzCBA5hAocwgUOYwCHs2Jpa6+Y1gEubbxtccAgTOIQJHMIEDmEChzCBQ5jAIUzgECZwCBM4hAkcwgQOYQKHMIFDmMAhTOAQJnAIEziECRzCBA5hAocwgUOYwCFM4BAmcAgTOIQJHMIEDmEChzCBQ5jAIUzgECZwCBM4hAkcwgQOYQKHMIFDmMAhTOAQJnAIEziECRzCBA5hAocwgUOYwCFM4BAmcAgTOIQJHMIEDmEChzCBQ5jAIUzgECZwCBM4hAkcwgQOYQKHMIFDmMAhTOAQJnAIEziECRzCBA5hAocwgUOYwCFM4BAmcAgTOIQJHMKOranfzVsAj3DBIUzgECZwCBM4hAkcwgQOYQKHMIFDmMAhTOAQJnAIEziECRzCBA5hAocwgUOYwCFM4BAmcAgTOIQJHMIEDmEChzCBQ5jAIUzgECZwCBM4hAkcwgQOYQKHMIFDmMAhTOAQJnAIEziECRzCBA5hAocwgUOYwCFM4BAmcAgTOIQJHMIEDmEChzCBQ5jAIUzgECZwCBM4hAkcwgQOYQKHMIFDmMAhTOAQJnAIEziECRzCBA5hAocwgUOYwCFM4BAmcAgTOIQJHMIEDmEChzCBQ5jAIUzgECZwCBM4hAkcwgQOYQKHMIFDmMAhTOAQJnAIEziECRzCBA5hAocwgUOYwCFM4BAmcAgTOIQJHMIEDmEChzCBQ5jAIUzgECZwCBM4hAkcwgQOYQKHMIFDmMAhTOAQJnAIEziECRzCBA5hAocwgUOYwCFM4BAmcAgTOIQJHMIEDmEChzCBQ5jAIUzgECZwCBM4hAkcwgQOYQKHMIFDmMAhTOAQJnAIEziECRzCBA5hAocwgUOYwCFM4BAmcAgTOIQJHMIEDmEChzCBQ5jAIUzgECZwCBM4hAkcwgQOYQKHMIFD2LEztP53rwFcmc05FxzCBA5hAocwgUOYwCFM4BAmcAgTOIQJHMIEDmEChzCBQ5jAIUzgECZwCBM4hAkcwgQOYQKHMIFDmMAhTOAQJnAIEziECRzCBA5hAocwgUOYwCFM4BAmcAgTOIQJHMIEDmEChzCBQ5jAIUzgECZwCBM4hAkcwgQOYQKHMIFDmMAhTOAQJnAIEziECRzCBA5hAocwgUOYwCFM4BAmcAgTOIQJHMIEDmEChzCBQ5jAIUzgECZwCBM4hAkcwgQOYQKHMIFDmMAhTOAQJnAIEziECRzCBA5hAocwgUOYwCFM4BAmcAgTOIQJHMIEDmEChzCBQ5jAIUzgECZwCBM4hAkcwgQOYQKHMIFDmMAhTOAQJnAIEziECRzCBA5hAocwgUOYwCFM4BAmcAgTOIQJHMIEDmEChzCBQ5jAIUzgECZwCBM4hAkcwgQOYQKHMIFDmMAhTOAQJnAIEziECRzCBA5hAocwgUOYwCFM4BAmcAgTOIQJHMIEDmEChzCBQ5jAIUzgECZwCBM4hAkcwgQOYQKHMIFDmMAhTOAQJnAIEziECRzCBA5hAocwgUOYwCFM4BAmcAgTOIQJHMIEDmEChzCBQ5jAIUzgECZwCBM4hAkcwgQOYQKHMIFDmMAhTOAQJnAIEziECRzCBA5hAocwgUOYwCFM4BAmcAgTOIQJHMIEDmEChzCBQ5jAIUzgECZwCBM4hAkcwgQOYQKHMIFDmMAhTOAQJnAIEziECRzCBA5hAocwgUOYwCFM4BAmcAgTOIQJHMIEDmEChzCBQ5jAIUzgECZwCBM4hAkcwgQOYQKHMIFDmMAhTOAQJnAIEziECRzCBA5hAocwgUOYwCFM4BAmcAgTOIQJHMIEDmEChzCBQ9iamXl7CeAZLjiECRzCBA5hAocwgUOYwCFM4BAmcAgTOIQJHMIEDmEChzCBQ5jAIewESc0QT9wKvogAAAAASUVORK5CYII=",h="/assets/292773723-4e84051a-1fec-4af3-9247-f77801e5cf2f.DPH5HlJX.png",k="/assets/292774360-4866ca27-dcd8-44d5-bc7f-d5cc864c7569.DlhRBBRV.png",p="/assets/292776696-6843784a-f791-4bd5-ab46-4ff7474071a4.B3kSNbXp.png",t="/assets/292776780-7a00c116-9d7b-447f-a495-06d36b22412a.jMbfBvi5.png",e="/assets/292776889-1c43a42c-e7d9-4023-ba05-acdc68054c4d.B3lF5OxB.png",E="/assets/292777024-b01e455d-d2d3-435e-9208-6b8fc11c3afb.Dcc4DmSJ.png",r="/assets/292777301-a9a5c486-b7e3-4f15-964d-678cc622e8d7.Cy5Owgdo.png",d="/assets/292777538-c0bbee71-c62d-4873-8d20-e04598d39a8a.Bg_JNI9Y.png",g="/assets/292777602-6f4ee12a-ddac-4dfb-9516-c093cc9282f0.CXjiaS2U.png",y="/assets/292777671-998be8d3-8e5f-4541-a938-0b3c016991ea.Br2fgusV.png",x=JSON.parse('{"title":"Layout com Flexbox","description":"","frontmatter":{},"headers":[],"relativePath":"docs/flexbox.md","filePath":"docs/flexbox.md"}'),F={name:"docs/flexbox.md"},c=n("",77),o=[c];function C(B,u,A,D,m,b){return a(),i("div",null,o)}const w=s(F,[["render",C]]);export{x as __pageData,w as default}; diff --git a/vitepress/docs/.vitepress/dist/assets/docs_gesture-responder-system.md.C0ulhXXT.js b/vitepress/docs/.vitepress/dist/assets/docs_gesture-responder-system.md.C0ulhXXT.js new file mode 100644 index 0000000..f689284 --- /dev/null +++ b/vitepress/docs/.vitepress/dist/assets/docs_gesture-responder-system.md.C0ulhXXT.js @@ -0,0 +1 @@ +import{_ as e,c as o,o as a,a4 as s}from"./chunks/framework.nQaBHiNx.js";const q=JSON.parse('{"title":"Sistema de resposta por gestos","description":"","frontmatter":{},"headers":[],"relativePath":"docs/gesture-responder-system.md","filePath":"docs/gesture-responder-system.md"}'),t={name:"docs/gesture-responder-system.md"},r=s('

Sistema de resposta por gestos

O sistema de resposta por gestos gerencia o ciclo de vida dos gestos no seu aplicativo. Um toque pode passar por diversas fases enquanto o app determina qual é a intenção do usuário. Por exemplo, o aplicativo precisa determinar se o toque está rolando, deslizando em um widget ou tocando. Isso pode até mudar durante um toque. Também pode haver vários toques simultâneos.

O sistema de resposta ao toque é necessário para permitir que os componentes negociem essas interações por toque sem qualquer conhecimento adicional sobre seus componentes pai ou filho.

Melhores Práticas

Para que seu aplicativo seja ótimo, cada ação deve ter os seguintes atributos:

  • Feedback/destaque – mostre ao usuário o que está acontecendo com seu toque e o que acontecerá quando ele liberar o gesto
  • Capacidade de cancelamento - ao realizar uma ação, o usuário deve ser capaz de abortá-la no meio do toque, arrastando o dedo para longe

Esses recursos deixam os usuários mais confortáveis ao usar um aplicativo, pois permitem que as pessoas experimentem e interajam sem medo de cometer erros.

TouchableHighlight and Touchable*

O sistema de resposta pode ser complicado de usar. Portanto, fornecemos uma implementação abstrata Touchable para coisas que deveriam ser "tocáveis". Isso usa o sistema de resposta e permite configurar interações de toque de forma declarativa. Use TouchableHighlight em qualquer lugar onde você usaria um botão ou link na web.

Ciclo de vida do Respondente

Uma visualização pode se tornar a resposta ao toque, implementando os métodos de negociação corretos. Existem dois métodos para perguntar à visualização se ela deseja se tornar respondente:

  • View.props.onStartShouldSetResponder: evt => true, - Esta visualização deseja se tornar respondente no início de um toque?
  • View.props.onMoveShouldSetResponder: evt => true, - Chamado para cada movimento de toque na Visualização quando não é o respondedor: esta visualização deseja "reivindicar" capacidade de resposta ao toque?

Se a View retornar true e tentar se tornar o respondente, uma das seguintes situações acontecerá:

  • View.props.onResponderGrant: evt => {} - A visualização agora está respondendo a eventos de toque. Este é o momento de destacar e mostrar ao usuário o que está acontecendo
  • View.props.onResponderReject: evt => {} - Outra coisa está respondendo agora e não irá liberá-la

Se a visualização estiver respondendo, os seguintes manipuladores poderão ser chamados:

  • View.props.onResponderMove: evt => {} - O usuário está movendo o dedo
  • View.props.onResponderRelease: evt => {} - Disparado no final do toque, ou seja, "touchUp"
  • View.props.onResponderTerminationRequest: evt => true - Outra coisa deseja se tornar respondedor. Essa visão deve liberar o respondedor? Retornar verdadeiro permite a liberação
  • View.props.onResponderTerminate: evt => {} - O respondente foi retirado da Visualização. Pode ser obtido por outras visualizações após uma chamada para onResponderTerminationRequest ou pode ser obtido pelo sistema operacional sem perguntar (acontece com o centro de controle/centro de notificação no iOS)

evt é um evento de toque sintético com o seguinte formato:

  • nativeEvent
    • changeTouches - Matriz de todos os eventos de toque que foram alterados desde o último evento
    • identifier - O ID do toque
    • locationX - A posição X do toque, em relação ao elemento
    • locationY - A posição Y do toque, em relação ao elemento
    • pageX - A posição X do toque, em relação ao elemento raiz
    • pageY - A posição Y do toque, em relação ao elemento raiz
    • target - O ID do nó do elemento que recebe o evento de toque
    • timestamp - Um identificador de tempo para o toque, útil para cálculo de velocidade
    • touches - Matriz de todos os toques atuais na tela

Capturar manipuladores ShouldSet

onStartShouldSetResponder e onMoveShouldSetResponder são chamados com um padrão de bolha, onde o nó mais profundo é chamado primeiro. Isso significa que o componente mais profundo se tornará respondedor quando múltiplas Views retornarem true para manipuladores *ShouldSetResponder. Isso é desejável na maioria dos casos, porque garante que todos os controles e botões possam ser usados.

No entanto, às vezes um pai vai querer ter certeza de que ele responderá. Isso pode ser resolvido usando a fase de captura. Antes que o sistema de resposta surja do componente mais profundo, ele fará uma fase de captura, disparando em *ShouldSetResponderCapture. Portanto, se uma visualização pai quiser evitar que o filho se torne respondedor em uma inicialização por toque, ela deverá ter um manipulador onStartShouldSetResponderCapture que retorne verdadeiro.

  • View.props.onStartShouldSetResponderCapture: evt => true,
  • View.props.onMoveShouldSetResponderCapture: evt => true,

PanResponder

Para interpretação de gestos de nível superior, confira PanResponder.

',24),d=[r];function i(n,u,p,l,c,m){return a(),o("div",null,d)}const v=e(t,[["render",i]]);export{q as __pageData,v as default}; diff --git a/vitepress/docs/.vitepress/dist/assets/docs_gesture-responder-system.md.C0ulhXXT.lean.js b/vitepress/docs/.vitepress/dist/assets/docs_gesture-responder-system.md.C0ulhXXT.lean.js new file mode 100644 index 0000000..9d8590f --- /dev/null +++ b/vitepress/docs/.vitepress/dist/assets/docs_gesture-responder-system.md.C0ulhXXT.lean.js @@ -0,0 +1 @@ +import{_ as e,c as o,o as a,a4 as s}from"./chunks/framework.nQaBHiNx.js";const q=JSON.parse('{"title":"Sistema de resposta por gestos","description":"","frontmatter":{},"headers":[],"relativePath":"docs/gesture-responder-system.md","filePath":"docs/gesture-responder-system.md"}'),t={name:"docs/gesture-responder-system.md"},r=s("",24),d=[r];function i(n,u,p,l,c,m){return a(),o("div",null,d)}const v=e(t,[["render",i]]);export{q as __pageData,v as default}; diff --git a/vitepress/docs/.vitepress/dist/assets/docs_getting-started.md.QTale-rH.js b/vitepress/docs/.vitepress/dist/assets/docs_getting-started.md.QTale-rH.js new file mode 100644 index 0000000..e7d9e24 --- /dev/null +++ b/vitepress/docs/.vitepress/dist/assets/docs_getting-started.md.QTale-rH.js @@ -0,0 +1,18 @@ +import{_ as s,c as a,o as e,a4 as i}from"./chunks/framework.nQaBHiNx.js";const u=JSON.parse('{"title":"Introdução","description":"","frontmatter":{},"headers":[],"relativePath":"docs/getting-started.md","filePath":"docs/getting-started.md"}'),t={name:"docs/getting-started.md"},n=i(`

Introdução

Bem-vindo ao início de sua jornada React Native! Se você estiver procurando instruções de configuração do ambiente, elas foram movidas para sua própria seção. Continue lendo para obter uma introdução à documentação, componentes nativos, React e muito mais!

Muitos tipos diferentes de pessoas usam React Native: desde desenvolvedores iOS avançados até iniciantes em React, até pessoas que estão começando a programar pela primeira vez em suas carreiras. Esses documentos foram escritos para todos os alunos, independentemente do nível de experiência ou formação.

Como usar esses documentos

Você pode começar aqui e ler esses documentos linearmente como um livro; ou você pode ler as seções específicas de que precisa. Já conhece o React? Você pode pular para essa seção - ou lê-la para uma atualização leve.

Pré-requisitos

Para trabalhar com React Native, você precisará entender os fundamentos do JavaScript. Se você é novo em JavaScript ou precisa de uma atualização, você pode mergulhar ou se atualizar na Mozilla Developer Network.

Exemplos interativos

Esta introdução permite que você comece imediatamente em seu navegador com exemplos interativos como este:

js
// Hello World
+import React from 'react';
+import {Text, View} from 'react-native';
+
+const YourApp = () => {
+  return (
+    <View
+      style={{
+        flex: 1,
+        justifyContent: 'center',
+        alignItems: 'center',
+      }}>
+      <Text>Try editing me! 🎉</Text>
+    </View>
+  );
+};
+
+export default YourApp;

Opcionalmente

Se desejar configurar um ambiente de desenvolvimento local, você pode seguir nosso guia para configurar seu ambiente em sua máquina local e colar os exemplos de código em seu arquivo App.js. (Se você é um desenvolvedor web, talvez já tenha um ambiente local configurado para testes de navegadores móveis!)

Notas do desenvolvedor

Pessoas de diversas origens de desenvolvimento estão aprendendo React Native. Você pode ter experiência com uma variedade de tecnologias, desde web até Android, iOS e muito mais. Tentamos escrever para desenvolvedores de todas as origens.

Formatação

Os caminhos dos menus são escritos em negrito e usam sinais de intercalação para navegar nos submenus. Exemplo: Android Studio > Preference

Agora que você sabe como funciona este guia, é hora de conhecer a base do React Native: Native Components.

`,16),o=[n];function r(l,p,d,h,c,k){return e(),a("div",null,o)}const E=s(t,[["render",r]]);export{u as __pageData,E as default}; diff --git a/vitepress/docs/.vitepress/dist/assets/docs_getting-started.md.QTale-rH.lean.js b/vitepress/docs/.vitepress/dist/assets/docs_getting-started.md.QTale-rH.lean.js new file mode 100644 index 0000000..9fa1b26 --- /dev/null +++ b/vitepress/docs/.vitepress/dist/assets/docs_getting-started.md.QTale-rH.lean.js @@ -0,0 +1 @@ +import{_ as s,c as a,o as e,a4 as i}from"./chunks/framework.nQaBHiNx.js";const u=JSON.parse('{"title":"Introdução","description":"","frontmatter":{},"headers":[],"relativePath":"docs/getting-started.md","filePath":"docs/getting-started.md"}'),t={name:"docs/getting-started.md"},n=i("",16),o=[n];function r(l,p,d,h,c,k){return e(),a("div",null,o)}const E=s(t,[["render",r]]);export{u as __pageData,E as default}; diff --git a/vitepress/docs/.vitepress/dist/assets/docs_handling-text-input.md.4h5B6goh.js b/vitepress/docs/.vitepress/dist/assets/docs_handling-text-input.md.4h5B6goh.js new file mode 100644 index 0000000..52479c4 --- /dev/null +++ b/vitepress/docs/.vitepress/dist/assets/docs_handling-text-input.md.4h5B6goh.js @@ -0,0 +1,24 @@ +import{_ as s,c as i,o as a,a4 as t}from"./chunks/framework.nQaBHiNx.js";const y=JSON.parse('{"title":"Tratamento de entrada de texto","description":"","frontmatter":{},"headers":[],"relativePath":"docs/handling-text-input.md","filePath":"docs/handling-text-input.md"}'),n={name:"docs/handling-text-input.md"},e=t(`

Tratamento de entrada de texto

TextInput é um componente principal que permite ao usuário inserir texto. Ele tem uma propriedade onChangeText que leva uma função a ser chamada toda vez que o texto é alterado, e uma propriedade onSubmitEditing que leva uma função a ser chamada quando o texto é enviado.

Por exemplo, digamos que enquanto o usuário digita, você traduz as palavras dele para um idioma diferente. Neste novo idioma, cada palavra é escrita da mesma maneira: 🍕. Portanto, a frase "Olá, Bob" seria traduzida como "🍕 🍕 🍕".

jsx
import React, {useState} from 'react';
+import {Text, TextInput, View} from 'react-native';
+
+const PizzaTranslator = () => {
+  const [text, setText] = useState('');
+  return (
+    <View style={{padding: 10}}>
+      <TextInput
+        style={{height: 40}}
+        placeholder="Type here to translate!"
+        onChangeText={newText => setText(newText)}
+        defaultValue={text}
+      />
+      <Text style={{padding: 10, fontSize: 42}}>
+        {text
+          .split(' ')
+          .map(word => word && '🍕')
+          .join(' ')}
+      </Text>
+    </View>
+  );
+};
+
+export default PizzaTranslator;

Neste exemplo, armazenamos texto no estado, pois ele muda com o tempo.

Há muito mais coisas que você pode querer fazer com uma entrada de texto. Por exemplo, você pode validar o texto interno enquanto o usuário digita. Para exemplos mais detalhados, consulte a documentação do React sobre componentes controlados ou a documentação de referência para TextInput.

A entrada de texto é uma das maneiras pelas quais o usuário interage com o aplicativo. A seguir, vamos examinar outro tipo de entrada e aprender como lidar com toques.

`,7),h=[e];function p(l,k,r,d,E,o){return a(),i("div",null,h)}const c=s(n,[["render",p]]);export{y as __pageData,c as default}; diff --git a/vitepress/docs/.vitepress/dist/assets/docs_handling-text-input.md.4h5B6goh.lean.js b/vitepress/docs/.vitepress/dist/assets/docs_handling-text-input.md.4h5B6goh.lean.js new file mode 100644 index 0000000..c4a7e89 --- /dev/null +++ b/vitepress/docs/.vitepress/dist/assets/docs_handling-text-input.md.4h5B6goh.lean.js @@ -0,0 +1 @@ +import{_ as s,c as i,o as a,a4 as t}from"./chunks/framework.nQaBHiNx.js";const y=JSON.parse('{"title":"Tratamento de entrada de texto","description":"","frontmatter":{},"headers":[],"relativePath":"docs/handling-text-input.md","filePath":"docs/handling-text-input.md"}'),n={name:"docs/handling-text-input.md"},e=t("",7),h=[e];function p(l,k,r,d,E,o){return a(),i("div",null,h)}const c=s(n,[["render",p]]);export{y as __pageData,c as default}; diff --git a/vitepress/docs/.vitepress/dist/assets/docs_handling-touches.md.CyOwDJM4.js b/vitepress/docs/.vitepress/dist/assets/docs_handling-touches.md.CyOwDJM4.js new file mode 100644 index 0000000..4849760 --- /dev/null +++ b/vitepress/docs/.vitepress/dist/assets/docs_handling-touches.md.CyOwDJM4.js @@ -0,0 +1,132 @@ +import{_ as s,c as i,o as a,a4 as n}from"./chunks/framework.nQaBHiNx.js";const t="/assets/294049976-589c99ab-cfb1-4274-bdea-e1c6c630adee.JemQ_fhc.png",h="/assets/294050118-afc6df54-903b-4821-8e0d-e57a396d126f.DCWfcER7.png",l="/assets/294050559-b6bcc0f9-8745-4ead-ac9b-98a7cf92ef38.70zhE0u1.png",u=JSON.parse('{"title":"Lidando com toques","description":"","frontmatter":{},"headers":[],"relativePath":"docs/handling-touches.md","filePath":"docs/handling-touches.md"}'),k={name:"docs/handling-touches.md"},p=n(`

Lidando com toques

Os usuários interagem com aplicativos móveis principalmente por meio do toque. Eles podem usar uma combinação de gestos, como tocar em um botão, rolar uma lista ou ampliar um mapa. O React Native fornece componentes para lidar com todos os tipos de gestos comuns, bem como um sistema abrangente de resposta a gestos para permitir um reconhecimento de gestos mais avançado, mas o componente no qual você provavelmente estará interessado é o botão básico.

Exibindo um botão básico

Button fornece um componente básico de botão que é bem renderizado em todas as plataformas. O exemplo mínimo para exibir um botão é assim:

tsx
<Button
+  onPress={() => {
+    console.log('You tapped the button!');
+  }}
+  title="Press Me"
+/>

Isso renderizará um rótulo azul no iOS e um retângulo arredondado azul com texto claro no Android. Pressionar o botão chamará a função "onPress", que neste caso exibe um pop-up de alerta. Se desejar, você pode especificar um adereço "color" para alterar a cor do seu botão.

Vá em frente e brinque com o componente Button usando o exemplo abaixo. Você pode selecionar em qual plataforma seu aplicativo será visualizado clicando no botão de alternância no canto inferior direito e depois clicando em "Tap to Play" para visualizar o aplicativo.

jsx
import React, {Component} from 'react';
+import {Alert, Button, StyleSheet, View} from 'react-native';
+
+export default class ButtonBasics extends Component {
+  _onPressButton() {
+    Alert.alert('You tapped the button!');
+  }
+
+  render() {
+    return (
+      <View style={styles.container}>
+        <View style={styles.buttonContainer}>
+          <Button onPress={this._onPressButton} title="Press Me" />
+        </View>
+        <View style={styles.buttonContainer}>
+          <Button
+            onPress={this._onPressButton}
+            title="Press Me"
+            color="#841584"
+          />
+        </View>
+        <View style={styles.alternativeLayoutButtonContainer}>
+          <Button onPress={this._onPressButton} title="This looks great!" />
+          <Button onPress={this._onPressButton} title="OK!" color="#841584" />
+        </View>
+      </View>
+    );
+  }
+}
+
+const styles = StyleSheet.create({
+  container: {
+    flex: 1,
+    justifyContent: 'center',
+  },
+  buttonContainer: {
+    margin: 20,
+  },
+  alternativeLayoutButtonContainer: {
+    margin: 20,
+    flexDirection: 'row',
+    justifyContent: 'space-between',
+  },
+});

image

Tocáveis

Se o botão básico não parecer adequado ao seu aplicativo, você poderá criar seu próprio botão usando qualquer um dos componentes "Tocáveis" fornecidos pelo React Native. Os componentes "Tocáveis" oferecem a capacidade de capturar gestos de toque e podem exibir feedback quando um gesto é reconhecido. Esses componentes não fornecem nenhum estilo padrão, portanto, você precisará trabalhar um pouco para que eles tenham uma boa aparência em seu aplicativo.

O componente "Tocável" que você usará dependerá do tipo de feedback que você deseja fornecer:

  • Geralmente, você pode usar TouchableHighlight em qualquer lugar onde usaria um botão ou link na web. O fundo da visualização ficará escurecido quando o usuário pressionar o botão.
  • Você pode considerar usar TouchableNativeFeedback no Android para exibir ondulações de reação na superfície que respondem ao toque do usuário.
  • TouchableOpacity pode ser usado para fornecer feedback, reduzindo a opacidade do botão, permitindo que o fundo seja visto enquanto o usuário pressiona.
  • Se você precisar manipular um gesto de toque, mas não quiser que nenhum feedback seja exibido, use TouchableWithoutFeedback.

Em alguns casos, você pode querer detectar quando um usuário pressiona e mantém uma visualização por um determinado período de tempo. Essas pressões longas podem ser tratadas passando uma função para os adereços onLongPress de qualquer um dos componentes "Tocáveis".

Vamos ver tudo isso em ação:

jsx
import React, {Component} from 'react';
+import {
+  Alert,
+  Platform,
+  StyleSheet,
+  Text,
+  TouchableHighlight,
+  TouchableOpacity,
+  TouchableNativeFeedback,
+  TouchableWithoutFeedback,
+  View,
+} from 'react-native';
+
+export default class Touchables extends Component {
+  _onPressButton() {
+    Alert.alert('You tapped the button!');
+  }
+
+  _onLongPressButton() {
+    Alert.alert('You long-pressed the button!');
+  }
+
+  render() {
+    return (
+      <View style={styles.container}>
+        <TouchableHighlight onPress={this._onPressButton} underlayColor="white">
+          <View style={styles.button}>
+            <Text style={styles.buttonText}>TouchableHighlight</Text>
+          </View>
+        </TouchableHighlight>
+        <TouchableOpacity onPress={this._onPressButton}>
+          <View style={styles.button}>
+            <Text style={styles.buttonText}>TouchableOpacity</Text>
+          </View>
+        </TouchableOpacity>
+        <TouchableNativeFeedback
+          onPress={this._onPressButton}
+          background={
+            Platform.OS === 'android'
+              ? TouchableNativeFeedback.SelectableBackground()
+              : undefined
+          }>
+          <View style={styles.button}>
+            <Text style={styles.buttonText}>
+              TouchableNativeFeedback{' '}
+              {Platform.OS !== 'android' ? '(Android only)' : ''}
+            </Text>
+          </View>
+        </TouchableNativeFeedback>
+        <TouchableWithoutFeedback onPress={this._onPressButton}>
+          <View style={styles.button}>
+            <Text style={styles.buttonText}>TouchableWithoutFeedback</Text>
+          </View>
+        </TouchableWithoutFeedback>
+        <TouchableHighlight
+          onPress={this._onPressButton}
+          onLongPress={this._onLongPressButton}
+          underlayColor="white">
+          <View style={styles.button}>
+            <Text style={styles.buttonText}>Touchable with Long Press</Text>
+          </View>
+        </TouchableHighlight>
+      </View>
+    );
+  }
+}
+
+const styles = StyleSheet.create({
+  container: {
+    paddingTop: 60,
+    alignItems: 'center',
+  },
+  button: {
+    marginBottom: 30,
+    width: 260,
+    alignItems: 'center',
+    backgroundColor: '#2196F3',
+  },
+  buttonText: {
+    textAlign: 'center',
+    padding: 20,
+    color: 'white',
+  },
+});

image

Rolar e deslizar

Os gestos comumente usados em dispositivos com telas tocáveis incluem deslizar e movimentar. Eles permitem que o usuário role por uma lista de itens ou percorra páginas de conteúdo. Para estes, verifique o componente ScrollView Core.

Problemas conhecidos

  • react-native#29308: A área de toque nunca ultrapassa os limites da visualização pai e no Android a margem negativa não é suportada.
',22),e=[p];function E(r,d,o,g,y,c){return a(),i("div",null,e)}const C=s(k,[["render",E]]);export{u as __pageData,C as default}; diff --git a/vitepress/docs/.vitepress/dist/assets/docs_handling-touches.md.CyOwDJM4.lean.js b/vitepress/docs/.vitepress/dist/assets/docs_handling-touches.md.CyOwDJM4.lean.js new file mode 100644 index 0000000..4aeab69 --- /dev/null +++ b/vitepress/docs/.vitepress/dist/assets/docs_handling-touches.md.CyOwDJM4.lean.js @@ -0,0 +1 @@ +import{_ as s,c as i,o as a,a4 as n}from"./chunks/framework.nQaBHiNx.js";const t="/assets/294049976-589c99ab-cfb1-4274-bdea-e1c6c630adee.JemQ_fhc.png",h="/assets/294050118-afc6df54-903b-4821-8e0d-e57a396d126f.DCWfcER7.png",l="/assets/294050559-b6bcc0f9-8745-4ead-ac9b-98a7cf92ef38.70zhE0u1.png",u=JSON.parse('{"title":"Lidando com toques","description":"","frontmatter":{},"headers":[],"relativePath":"docs/handling-touches.md","filePath":"docs/handling-touches.md"}'),k={name:"docs/handling-touches.md"},p=n("",22),e=[p];function E(r,d,o,g,y,c){return a(),i("div",null,e)}const C=s(k,[["render",E]]);export{u as __pageData,C as default}; diff --git a/vitepress/docs/.vitepress/dist/assets/docs_headless-js-android.md.eP8fnmCn.js b/vitepress/docs/.vitepress/dist/assets/docs_headless-js-android.md.eP8fnmCn.js new file mode 100644 index 0000000..9ccee32 --- /dev/null +++ b/vitepress/docs/.vitepress/dist/assets/docs_headless-js-android.md.eP8fnmCn.js @@ -0,0 +1,252 @@ +import{_ as s,c as i,o as a,a4 as n}from"./chunks/framework.nQaBHiNx.js";const c=JSON.parse('{"title":"Headless JS","description":"","frontmatter":{},"headers":[],"relativePath":"docs/headless-js-android.md","filePath":"docs/headless-js-android.md"}'),t={name:"docs/headless-js-android.md"},l=n(`

Headless JS

Headless JS é uma forma de executar tarefas em JavaScript enquanto seu aplicativo está em segundo plano. Ele pode ser usado, por exemplo, para sincronizar dados recentes, lidar com notificações push ou reproduzir música.

A API JS

Uma tarefa é uma função assíncrona que você registra no AppRegistry, semelhante ao registro de aplicativos React:

tsx
import {AppRegistry} from 'react-native';
+AppRegistry.registerHeadlessTask('SomeTaskName', () =>
+  require('SomeTaskName'),
+);

Então, em SomeTaskName.js:

tsx
module.exports = async taskData => {
+  // Fazer coisas
+};

Você pode fazer qualquer coisa em sua tarefa, como solicitações de rede, temporizadores e assim por diante, desde que não toque na interface do usuário. Assim que sua tarefa for concluída (ou seja, a promessa for resolvida), o React Native entrará no modo "pausado" (a menos que haja outras tarefas em execução ou um aplicativo em primeiro plano).

A API da plataforma

Sim, isso ainda requer algum código nativo, mas é bastante limitado. Você precisa estender HeadlessJsTaskService e substituir getTaskConfig, por exemplo:

java
package com.your_application_name;
+
+import android.content.Intent;
+import android.os.Bundle;
+import com.facebook.react.HeadlessJsTaskService;
+import com.facebook.react.bridge.Arguments;
+import com.facebook.react.jstasks.HeadlessJsTaskConfig;
+import javax.annotation.Nullable;
+
+public class MyTaskService extends HeadlessJsTaskService {
+
+  @Override
+  protected @Nullable HeadlessJsTaskConfig getTaskConfig(Intent intent) {
+    Bundle extras = intent.getExtras();
+    if (extras != null) {
+      return new HeadlessJsTaskConfig(
+          "SomeTaskName",
+          Arguments.fromBundle(extras),
+          5000, // timeout in milliseconds for the task
+          false // optional: defines whether or not the task is allowed in foreground. Default is false
+        );
+    }
+    return null;
+  }
+}
kotlin
package com.your_application_name;
+
+import android.content.Intent
+import com.facebook.react.HeadlessJsTaskService
+import com.facebook.react.bridge.Arguments
+import com.facebook.react.jstasks.HeadlessJsTaskConfig
+
+class MyTaskService : HeadlessJsTaskService() {
+    override fun getTaskConfig(intent: Intent): HeadlessJsTaskConfig? {
+        return intent.extras?.let {
+            HeadlessJsTaskConfig(
+                "SomeTaskName",
+                Arguments.fromBundle(it),
+                5000, // timeout for the task
+                false // optional: defines whether or not the task is allowed in foreground.
+                // Default is false
+            )
+        }
+    }
+}

Em seguida, adicione o serviço ao seu arquivo AndroidManifest.xml dentro da tag application:

<service android:name="com.example.MyTaskService" />

Agora, sempre que você iniciar seu serviço, por exemplo. como uma tarefa periódica ou em resposta a algum evento/transmissão do sistema, o JS irá acelerar, executar sua tarefa e, em seguida, diminuir a rotação.

Exemplo:

java
Intent service = new Intent(getApplicationContext(), MyTaskService.class);
+Bundle bundle = new Bundle();
+
+bundle.putString("foo", "bar");
+service.putExtras(bundle);
+
+getApplicationContext().startService(service);
kotlin
val service = Intent(applicationContext, MyTaskService::class.java)
+val bundle = Bundle()
+
+bundle.putString("foo", "bar")
+
+service.putExtras(bundle)
+
+applicationContext.startService(service)

Novas tentativas

Por padrão, a tarefa JS headless não executará nenhuma nova tentativa. Para fazer isso, você precisa criar um HeadlessJsRetryPolicy e lançar um Error específico.

LinearCountingRetryPolicy é uma implementação de HeadlessJsRetryPolicy que permite especificar um número máximo de novas tentativas com um atraso fixo entre cada tentativa. Se isso não atender às suas necessidades, você pode implementar seu próprio HeadlessJsRetryPolicy. Essas políticas podem ser passadas como um argumento extra para o construtor HeadlessJsTaskConfig, por exemplo.

java
HeadlessJsRetryPolicy retryPolicy = new LinearCountingRetryPolicy(
+  3, // Número máximo de novas tentativas
+  1000 // Atraso entre cada nova tentativa
+);
+
+return new HeadlessJsTaskConfig(
+  'SomeTaskName',
+  Arguments.fromBundle(extras),
+  5000,
+  false,
+  retryPolicy
+);
kotlin
val retryPolicy: HeadlessJsTaskRetryPolicy =
+    LinearCountingRetryPolicy(
+        3, // Número máximo de novas tentativas
+        1000 // Atraso entre cada nova tentativa
+    )
+
+return HeadlessJsTaskConfig("SomeTaskName", Arguments.fromBundle(extras), 5000, false, retryPolicy)

Uma nova tentativa só será feita quando um Error específico for lançado. Dentro de uma tarefa JS headless, você pode importar o erro e lançá-lo quando uma nova tentativa for necessária.

Exemplo:

tsx
import {HeadlessJsTaskError} from 'HeadlessJsTask';
+
+module.exports = async taskData => {
+  const condition = ...;
+  if (!condition) {
+    throw new HeadlessJsTaskError();
+  }
+};

Se desejar que todos os erros causem uma nova tentativa, você precisará capturá-los e lançar o erro acima.

Ressalvas

  • Por padrão, seu aplicativo travará se você tentar executar uma tarefa enquanto o aplicativo estiver em primeiro plano. Isso evita que os desenvolvedores dêem um tiro no próprio pé ao trabalhar muito em uma tarefa e tornar a interface do usuário lenta. Você pode passar um quarto argumento booleano para controlar este comportamento.
  • Se você iniciar seu serviço a partir de um BroadcastReceiver, certifique-se de chamar HeadlessJsTaskService.acquireWakeLockNow() antes de retornar de onReceive().

Exemplo de uso

O serviço pode ser iniciado a partir da API Java. Primeiro você precisa decidir quando o serviço deve ser iniciado e implementar sua solução de acordo. Aqui está um exemplo que reage à mudança na conexão de rede.

As linhas a seguir mostram parte do arquivo de manifesto do Android para registrar o receptor de transmissão.

xml
<receiver android:name=".NetworkChangeReceiver" >
+  <intent-filter>
+    <action android:name="android.net.conn.CONNECTIVITY_CHANGE" />
+  </intent-filter>
+</receiver>

O receptor de transmissão então lida com a intenção que foi transmitida na função onReceive. Este é um ótimo lugar para verificar se seu aplicativo está em primeiro plano ou não. Se o aplicativo não estiver em primeiro plano, podemos preparar nossa intenção para ser iniciado, sem informações ou informações adicionais agrupadas usando putExtra (lembre-se de que o pacote pode lidar apenas com valores parcelados). No final o serviço é iniciado e o wakelock é adquirido.

java
import android.app.ActivityManager;
+import android.content.BroadcastReceiver;
+import android.content.Context;
+import android.content.Intent;
+import android.net.ConnectivityManager;
+import android.net.Network;
+import android.net.NetworkCapabilities;
+import android.net.NetworkInfo;
+import android.os.Build;
+
+import com.facebook.react.HeadlessJsTaskService;
+
+public class NetworkChangeReceiver extends BroadcastReceiver {
+
+    @Override
+    public void onReceive(final Context context, final Intent intent) {
+        /**
+          Esta parte será chamada sempre que a conexão de rede for alterada
+          por exemplo. Conectado -> Não conectado
+         **/
+        if (!isAppOnForeground((context))) {
+            /**
+             Iniciaremos nosso serviço e enviaremos informações extras sobre
+             conexões de rede
+             **/
+            boolean hasInternet = isNetworkAvailable(context);
+            Intent serviceIntent = new Intent(context, MyTaskService.class);
+            serviceIntent.putExtra("hasInternet", hasInternet);
+            context.startService(serviceIntent);
+            HeadlessJsTaskService.acquireWakeLockNow(context);
+        }
+    }
+
+    private boolean isAppOnForeground(Context context) {
+        /**
+          Precisamos verificar se o aplicativo está em primeiro plano, caso contrário ele irá travar.
+          https://stackoverflow.com/questions/8489993/check-android-application-is-in-foreground-or-not
+         **/
+        ActivityManager activityManager = (ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE);
+        List<ActivityManager.RunningAppProcessInfo> appProcesses =
+                activityManager.getRunningAppProcesses();
+        if (appProcesses == null) {
+            return false;
+        }
+        final String packageName = context.getPackageName();
+        for (ActivityManager.RunningAppProcessInfo appProcess : appProcesses) {
+            if (appProcess.importance ==
+                    ActivityManager.RunningAppProcessInfo.IMPORTANCE_FOREGROUND &&
+                    appProcess.processName.equals(packageName)) {
+                return true;
+            }
+        }
+        return false;
+    }
+
+    public static boolean isNetworkAvailable(Context context) {
+        ConnectivityManager cm = (ConnectivityManager)
+                context.getSystemService(Context.CONNECTIVITY_SERVICE);
+
+        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
+            Network networkCapabilities = cm.getActiveNetwork();
+
+            if(networkCapabilities == null) {
+                return false;
+            }
+
+            NetworkCapabilities actNw = cm.getNetworkCapabilities(networkCapabilities);
+
+            if(actNw == null) {
+                return false;
+            }
+
+            if(actNw.hasTransport(NetworkCapabilities.TRANSPORT_WIFI) || actNw.hasTransport(NetworkCapabilities.TRANSPORT_CELLULAR) || actNw.hasTransport(NetworkCapabilities.TRANSPORT_ETHERNET)) {
+                return true;
+            }
+
+            return false;
+        }
+
+        // obsoleto na API nível 29
+        NetworkInfo netInfo = cm.getActiveNetworkInfo();
+        return (netInfo != null && netInfo.isConnected());
+    }
+}
kotlin
import android.app.ActivityManager
+import android.app.ActivityManager.RunningAppProcessInfo
+import android.content.BroadcastReceiver
+import android.content.Context
+import android.content.Intent
+import android.net.ConnectivityManager
+import android.net.NetworkCapabilities
+import android.os.Build
+import com.facebook.react.HeadlessJsTaskService
+
+class NetworkChangeReceiver : BroadcastReceiver() {
+    override fun onReceive(context: Context, intent: Intent?) {
+        /**
+         * Esta parte será chamada sempre que a conexão de rede for alterada, por exemplo. Conectado -> Não Conectado
+         */
+        if (!isAppOnForeground(context)) {
+            /** Iniciaremos nosso serviço e enviaremos informações extras sobre conexões de rede */
+            val hasInternet = isNetworkAvailable(context)
+            val serviceIntent = Intent(context, MyTaskService::class.java)
+            serviceIntent.putExtra("hasInternet", hasInternet)
+            context.startService(serviceIntent)
+            HeadlessJsTaskService.acquireWakeLockNow(context)
+        }
+    }
+
+    private fun isAppOnForeground(context: Context): Boolean {
+        /**
+         * Precisamos verificar se o aplicativo está em primeiro plano, caso contrário ele irá travar.
+         * https://stackoverflow.com/questions/8489993/check-android-application-is-in-foreground-or-not
+         */
+        val activityManager = context.getSystemService(Context.ACTIVITY_SERVICE) as ActivityManager
+        val appProcesses = activityManager.runningAppProcesses ?: return false
+        val packageName: String = context.getPackageName()
+        for (appProcess in appProcesses) {
+            if (appProcess.importance == RunningAppProcessInfo.IMPORTANCE_FOREGROUND &&
+                    appProcess.processName == packageName
+            ) {
+                return true
+            }
+        }
+        return false
+    }
+
+    companion object {
+        fun isNetworkAvailable(context: Context): Boolean {
+            val cm = context.getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager
+            var result = false
+
+            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
+                val networkCapabilities = cm.activeNetwork ?: return false
+
+                val actNw = cm.getNetworkCapabilities(networkCapabilities) ?: return false
+
+                result =
+                    when {
+                        actNw.hasTransport(NetworkCapabilities.TRANSPORT_WIFI) -> true
+                        actNw.hasTransport(NetworkCapabilities.TRANSPORT_CELLULAR) -> true
+                        actNw.hasTransport(NetworkCapabilities.TRANSPORT_ETHERNET) -> true
+                        else -> false
+                    }
+
+                return result
+            } else {
+                cm.run {
+                    // obsoleto na API nível 29
+                    cm.activeNetworkInfo?.run {
+                        result =
+                            when (type) {
+                                ConnectivityManager.TYPE_WIFI -> true
+                                ConnectivityManager.TYPE_MOBILE -> true
+                                ConnectivityManager.TYPE_ETHERNET -> true
+                                else -> false
+                            }
+                    }
+                }
+            }
+            return result
+        }
+    }
+}
`,32),p=[l];function e(h,k,r,E,d,o){return a(),i("div",null,p)}const y=s(t,[["render",e]]);export{c as __pageData,y as default}; diff --git a/vitepress/docs/.vitepress/dist/assets/docs_headless-js-android.md.eP8fnmCn.lean.js b/vitepress/docs/.vitepress/dist/assets/docs_headless-js-android.md.eP8fnmCn.lean.js new file mode 100644 index 0000000..5e84191 --- /dev/null +++ b/vitepress/docs/.vitepress/dist/assets/docs_headless-js-android.md.eP8fnmCn.lean.js @@ -0,0 +1 @@ +import{_ as s,c as i,o as a,a4 as n}from"./chunks/framework.nQaBHiNx.js";const c=JSON.parse('{"title":"Headless JS","description":"","frontmatter":{},"headers":[],"relativePath":"docs/headless-js-android.md","filePath":"docs/headless-js-android.md"}'),t={name:"docs/headless-js-android.md"},l=n("",32),p=[l];function e(h,k,r,E,d,o){return a(),i("div",null,p)}const y=s(t,[["render",e]]);export{c as __pageData,y as default}; diff --git a/vitepress/docs/.vitepress/dist/assets/docs_height-and-width.md.BMEpPzGn.js b/vitepress/docs/.vitepress/dist/assets/docs_height-and-width.md.BMEpPzGn.js new file mode 100644 index 0000000..84ecffd --- /dev/null +++ b/vitepress/docs/.vitepress/dist/assets/docs_height-and-width.md.BMEpPzGn.js @@ -0,0 +1,80 @@ +import{_ as s,c as i,o as a,a4 as A}from"./chunks/framework.nQaBHiNx.js";const E="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAARQAAAExCAYAAAC9EV38AAAABHNCSVQICAgIfAhkiAAAABl0RVh0U29mdHdhcmUAZ25vbWUtc2NyZWVuc2hvdO8Dvz4AAAAmdEVYdENyZWF0aW9uIFRpbWUAc2VnIDI1IGRleiAyMDIzIDE0OjQ2OjAxDody9AAABDlJREFUeJzt1iFOA2EURlEGyg4wKNbAOirYDgbLjghhJUUgEBgS0g1Mm0GVYCE3/Ek5xz33qZs3LcuynAAEVs8vr6M3AEdimnf7rw/l4e195JbMzdXl6AnwL52OHgAcD0EBMoICZAQFyAgKkBEUICMoQEZQgIygABlBATKCAmQEBcgICpARFCAjKEBGUICMoAAZQQEyggJkBAXICAqQERQgIyhARlCAjKAAGUEBMoICZAQFyAgKkBEUICMoQEZQgIygABlBATKCAmQEBcgICpARFCAjKEBGUICMoAAZQQEyggJkBAXICAqQERQgIyhARlCAjKAAmdX3Y7M9H7Ujtdl+jJ6QuL2+GD0BfsSHAmQEBcgICpARFCAjKEBGUICMoAAZQQEyggJkBAXICAqQERQgIyhARlCAjKAAGUEBMoICZAQFyAgKkBEUICMoQEZQgIygABlBATKCAmQEBcgICpARFCAjKEBGUICMoAAZQQEyggJkBAXICAqQERQgIyhARlCAjKAAGUEBMoICZAQFyAgKkBEUICMoQEZQgIygABlBATKCAmQEBcgICpARFCAjKEBGUICMoAAZQQEyggJkBAXICAqQERQgIyhARlCAjKAAGUEBMoICZAQFyAgKkBEUICMoQEZQgIygABlBATKCAmQEBcgICpARFCAjKEBGUICMoAAZQQEyggJkBAXICAqQERQgIyhARlCAjKAAGUEBMoICZAQFyAgKkBEUICMoQEZQgIygABlBATKCAmQEBcgICpCZ5t1+ORzr+8eRWzhST3fr0RP4Iz4UICMoQEZQgIygABlBATKCAmQEBcgICpARFCAjKEBGUICMoAAZQQEyggJkBAXICAqQERQgIyhARlCAjKAAGUEBMoICZAQFyAgKkBEUICMoQEZQgIygABlBATKCAmQEBcgICpARFCAjKEBGUICMoAAZQQEyggJkBAXICAqQERQgIyhARlCAjKAAGUEBMoICZAQFyAgKkBEUICMoQEZQgIygABlBATKCAmQEBcgICpARFCAjKEBGUICMoAAZQQEyggJkBAXICAqQERQgIyhARlCAjKAAGUEBMoICZAQFyAgKkBEUICMoQEZQgIygABlBATKCAmQEBcgICpARFCAjKEBGUICMoAAZQQEyggJkBAXICAqQERQgIyhARlCAjKAAGUEBMoICZAQFyAgKkBEUICMoQEZQgIygABlBATKCAmQEBcgICpARFCAjKEBGUICMoAAZQQEyggJkBAXICAqQERQgIyhARlCAjKAAGUEBMoICZAQFyAgKkBEUICMoQEZQgIygABlBATKCAmQEBcgICpARFCAjKEBGUICMoAAZQQEyggJkBAXICAqQERQgIyhARlCAjKAAGUEBMoICZAQFyAgKkBEUICMoQEZQgIygABlBATLTvNsvh2N1pi/A7ykIkBEUIPMJ3zkgH6zzuH0AAAAASUVORK5CYII=",n="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAQQAAAHzCAYAAADGn2OrAAAABHNCSVQICAgIfAhkiAAAABl0RVh0U29mdHdhcmUAZ25vbWUtc2NyZWVuc2hvdO8Dvz4AAAAmdEVYdENyZWF0aW9uIFRpbWUAc2VnIDI1IGRleiAyMDIzIDE0OjUxOjA5oOvrzwAABbZJREFUeJzt1zFqVVEUhtGd5Fo7gwcG0wQcjaXT1NraEShEggQbGyfw8rwW8j4zgxPIWtXhVn/1se/Fvu/7AC/a3f3D3Fwf5nL1EOD52L59/7F6A7DY1eW/22B7++YwMzOffv5auQdY6PZ0nJnxywD8JwhABAGIIAARBCCCAEQQgAgCEEEAIghABAGIIAARBCCCAEQQgAgCEEEAIghABAGIIAARBCCCAEQQgAgCEEEAIghABAGIIAARBCCCAEQQgAgCEEEAIghABAGIIAARBCCCAEQQgAgCEEEAIghABAGIIAARBCCCAEQQgAgCEEEAIghABAGIIAARBCCCAEQQgAgCEEEAIghABAGIIAARBCCCAEQQgAgCEEEAIghABAGIIAARBCCCAEQQgAgCEEEAIghABAGIIAARBCCCAEQQgAgCEEEAsp0fX3+/WrkDWOj29XFmXAjAE4IARBCACAIQQQAiCEAEAYggABEEIIIARBCACAIQQQAiCEAEAYggABEEIIIARBCACAIQQQAiCEAEAYggABEEIIIARBCACAIQQQAiCEAEAYggABEEIIIARBCACAIQQQAiCEAEAYggABEEIIIARBCACAIQQQAiCEAEAYggABEEIIIARBCACAIQQQAiCEAEAYggABEEIIIARBCACAIQQQAiCEAEAYggABEEIIIARBCACAIQQQAiCEAEAYggABEEIIIARBCACAIQQQAiCEAEAYggABEEIIIARBCACAIQQQAiCEAEAYggABEEIIIARBCACAIQQQAiCEAEAYggABEEIIIARBCACAIQQQAiCEAEAYggABEEIIIARBCACAIQQQAiCEAEAYggABEEIIIARBCACAIQQQAiCEAEAYggABEEIIIARBCACAIQQQAiCEAEAYggABEEIIIARBCACAIQQQAiCEAEAYggABEEIIIARBCACAIQQQAiCEAEAYggABEEIIIARBCACAIQQQAiCEAEAYggABEEIIIARBCACAIQQQAiCEAEAYggABEEIIIARBCACAKQ7fz4/PHLyh3AQu8/vJsZFwLwhCAAEQQgggBEEIAIAhBBACIIQAQBiCAAEQQgggBEEIAIAhBBACIIQAQBiCAAEQQgggBEEIAIAhBBACIIQAQBiCAAEQQgggBEEIAIAhBBACIIQAQBiCAAEQQgggBEEIAIAhBBACIIQAQBiCAAEQQgggBEEIAIAhBBACIIQAQBiCAAEQQgggBEEIAIAhBBACIIQAQBiCAAEQQgggBEEIAIAhBBACIIQAQBiCAAEQQgggBEEIAIAhBBACIIQAQBiCAAEQQgggBEEIAIAhBBACIIQAQBiCAAEQQgggBEEIAIAhBBACIIQAQBiCAAEQQgggBEEIAIAhBBACIIQAQBiCAAEQQgggBEEIAIAhBBACIIQAQBiCAAEQQgggBEEIAIAhBBACIIQAQBiCAAEQQgggBEEIAIAhBBACIIQAQBiCAAEQQgggBEEIAIAhBBACIIQAQBiCAAEQQgggBEEIAIAhBBACIIQAQBiCAAEQQgggBEEIAIAhBBACIIQAQBiCAAEQQgggBEEIAIAhBBACIIQAQBiCAAEQQgggBEEIAIAhBBACIIQAQBiCAAEQQgggBEEIAIAhBBACIIQAQBiCAAEQQgggBEEIAIAhBBACIIQAQBiCAAEQQgggBEEIAIAhBBACIIQAQBiCAAEQQgggBEEIAIAhBBACIIQAQBiCAAEQQgggBEEIAIAhBBACIIQAQBiCAAEQQgggBEEIAIAhBBACIIQAQBiCAAEQQgggBEEIAIAhBBACIIQAQBiCAAEQQgggBEEIAIAhBBACIIQAQBiCAAEQQgggBEEIAIAhBBACIIQAQBiCAAEQQgggBEEIAIAhBBACIIQAQBiCAAEQQgggBEEIAIApCL4+Npn5nZrrQBXqq7+4e5uT7Mdv7wePqzcg/wDPwFFL4ilZOgtc4AAAAASUVORK5CYII=",h="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAQQAAAHzCAYAAADGn2OrAAAABHNCSVQICAgIfAhkiAAAABl0RVh0U29mdHdhcmUAZ25vbWUtc2NyZWVuc2hvdO8Dvz4AAAAmdEVYdENyZWF0aW9uIFRpbWUAc2VnIDI1IGRleiAyMDIzIDE0OjUzOjA1A1RvbwAABcNJREFUeJzt1yFuFHEYh+Gv7XAD9CY01OA4BxfCcCsQKDQngGTJhmwwGC7QLoMg+4IENU37POqfUT/15puLdV3XAR61/eE4N9e7udx6CHB/LJ+/fN16A7Cxq8vft8Hy/NluZmbeffu+5R5gQy9OtzMzfhmAPwQBiCAAEQQgggBEEIAIAhBBACIIQAQBiCAAEQQgggBEEIAIAhBBACIIQAQBiCAAEQQgggBEEIAIAhBBACIIQAQBiCAAEQQgggBEEIAIAhBBACIIQAQBiCAAEQQgggBEEIAIAhBBACIIQAQBiCAAEQQgggBEEIAIAhBBACIIQAQBiCAAEQQgggBEEIAIAhBBACIIQAQBiCAAEQQgggBEEIAIAhBBACIIQAQBiCAAEQQgggBEEIAIAhBBACIIQJbz49OPJ1vugH/y+uXTrSc8SPvDcWZcCMBfBAGIIAARBCCCAEQQgAgCEEEAIghABAGIIAARBCCCAEQQgAgCEEEAIghABAGIIAARBCCCAEQQgAgCEEEAIghABAGIIAARBCCCAEQQgAgCEEEAIghABAGIIAARBCCCAEQQgAgCEEEAIghABAGIIAARBCCCAEQQgAgCEEEAIghABAGIIAARBCCCAEQQgAgCEEEAIghABAGIIAARBCCCAEQQgAgCEEEAIghABAGIIAARBCCCAEQQgAgCEEEAIghABAGIIAARBCCCAEQQgAgCEEEAIghABAGIIAARBCCCAEQQgAgCEEEAIghABAGIIAARBCCCAEQQgAgCEEEAIghABAGIIAARBCCCAEQQgAgCEEEAIghABAGIIAARBCCCAEQQgAgCEEEAIghABAGIIAARBCCCAEQQgAgCEEEAIghABAGIIAARBCCCAEQQgAgCEEEAIghABAGIIAARBCCCAEQQgAgCEEEAIghABAGIIAARBCCCAEQQgAgCEEEAIghABAGIIAARBCCCAEQQgAgCEEEAIghABAGIIAARBCCCAEQQgAgCEEEAIghABAGIIAARBCCCAEQQgAgCEEEAIghABAGIIAARBCDL+fHh7cctdzxI79+82noC/BcXAhBBACIIQAQBiCAAEQQgggBEEIAIAhBBACIIQAQBiCAAEQQgggBEEIAIAhBBACIIQAQBiCAAEQQgggBEEIAIAhBBACIIQAQBiCAAEQQgggBEEIAIAhBBACIIQAQBiCAAEQQgggBEEIAIAhBBACIIQAQBiCAAEQQgggBEEIAIAhBBACIIQAQBiCAAEQQgggBEEIAIAhBBACIIQAQBiCAAEQQgggBEEIAIAhBBACIIQAQBiCAAEQQgggBEEIAIAhBBACIIQAQBiCAAEQQgggBEEIAIAhBBACIIQAQBiCAAEQQgggBEEIAIAhBBACIIQAQBiCAAEQQgggBEEIAIAhBBACIIQAQBiCAAEQQgggBEEIAIAhBBACIIQAQBiCAAEQQgggBEEIAIAhBBACIIQAQBiCAAEQQgggBEEIAIAhBBACIIQAQBiCAAEQQgggBEEIAIAhBBACIIQAQBiCAAEQQgggBEEIAIAhBBACIIQAQBiCAAEQQgggBEEIAIAhBBACIIQAQBiCAAEQQgggBEEIAIAhBBACIIQAQBiCAAEQQgggBEEIAIAhBBACIIQAQBiCAAEQQgggBEEIAIAhBBACIIQAQBiCAAEQQgggBEEIAIAhBBACIIQAQBiCAAEQQgggBEEIAIAhBBACIIQAQBiCAAEQQgggBEEIAIAhBBACIIQAQBiCAAEQQgggBEEIAIAhBBACIIQAQBiCAAEQQgggBEEIAIAhBBACIIQAQBiCAAEQQgggBEEIAIAhBBACIIQAQBiCAAEQQgggBEEIAIAhBBACIIQAQBiCAAEQQgggBEEIAIAhBBACIIQAQBiCAAEQQgggBEEIAIAhBBACIIQAQBiCAAEQQgF7d3p3VmZrnSBnis9ofj3FzvZjl/uDv93HIPcA/8Al28JV8gvDx+AAAAAElFTkSuQmCC",d=JSON.parse('{"title":"Altura e Largura","description":"","frontmatter":{},"headers":[],"relativePath":"docs/height-and-width.md","filePath":"docs/height-and-width.md"}'),l={name:"docs/height-and-width.md"},e=A(`

Altura e Largura

A altura e a largura de um componente determinam seu tamanho na tela.

Dimensões fixas

A maneira geral de definir as dimensões de um componente é adicionando uma width (largura) e uma height (altura) fixas ao estilo. Todas as dimensões no React Native não têm unidade e representam pixels independentes de densidade.

jsx
import React from 'react';
+import {View} from 'react-native';
+
+const FixedDimensionsBasics = () => {
+  return (
+    <View>
+      <View
+        style={{
+          width: 50,
+          height: 50,
+          backgroundColor: 'powderblue',
+        }}
+      />
+      <View
+        style={{
+          width: 100,
+          height: 100,
+          backgroundColor: 'skyblue',
+        }}
+      />
+      <View
+        style={{
+          width: 150,
+          height: 150,
+          backgroundColor: 'steelblue',
+        }}
+      />
+    </View>
+  );
+};
+
+export default FixedDimensionsBasics;

image

Definir dimensões desta forma é comum para componentes cujo tamanho deve sempre ser fixado em um número de pontos e não calculado com base no tamanho da tela.

CUIDADO

Não existe um mapeamento universal de pontos para unidades físicas de medida. Isso significa que um componente com dimensões fixas pode não ter o mesmo tamanho físico em diferentes dispositivos e tamanhos de tela. No entanto, essa diferença é imperceptível na maioria dos casos de uso.

Dimensões flexíveis

Use flex no estilo de um componente para que o componente se expanda e diminua dinamicamente com base no espaço disponível. Normalmente você usará flex: 1, que diz a um componente para preencher todo o espaço disponível, compartilhado igualmente entre outros componentes com o mesmo pai. Quanto maior for a flexibilidade fornecida, maior será a proporção de espaço que um componente ocupará em comparação com seus irmãos.

INFORMAÇÕES

Um componente só pode se expandir para preencher o espaço disponível se seu pai tiver dimensões maiores que 0. Se um pai não tiver width e height fixas ou flex, o pai terá dimensões de 0 e os filhos flexíveis não serão visíveis.

jsx
import React from 'react';
+import {View} from 'react-native';
+
+const FlexDimensionsBasics = () => {
+  return (
+    //Tente remover o \`flex: 1\` na visualização pai.
+    // O pai não terá dimensões, portanto os filhos não poderão expandir.
+    // E se você adicionar \`height: 300\` em vez de \`flex: 1\`?
+    <View style={{flex: 1}}>
+      <View style={{flex: 1, backgroundColor: 'powderblue'}} />
+      <View style={{flex: 2, backgroundColor: 'skyblue'}} />
+      <View style={{flex: 3, backgroundColor: 'steelblue'}} />
+    </View>
+  );
+};
+
+export default FlexDimensionsBasics;

image

Depois de controlar o tamanho de um componente, a próxima etapa é aprender como organizá-lo na tela.

Dimensões percentuais

Se quiser preencher uma determinada parte da tela, mas não quiser usar o layout flexível, você pode usar valores percentuais no estilo do componente. Semelhante às dimensões flexíveis, as dimensões percentuais exigem um pai com um tamanho definido.

jsx
import React from 'react';
+import {View} from 'react-native';
+
+const PercentageDimensionsBasics = () => {
+  // Tente remover \`height: '100%'\` na visualização pai.
+  // O pai não terá dimensões, portanto os filhos não poderão expandir.
+  return (
+    <View style={{height: '100%'}}>
+      <View
+        style={{
+          height: '15%',
+          backgroundColor: 'powderblue',
+        }}
+      />
+      <View
+        style={{
+          width: '66%',
+          height: '35%',
+          backgroundColor: 'skyblue',
+        }}
+      />
+      <View
+        style={{
+          width: '33%',
+          height: '50%',
+          backgroundColor: 'steelblue',
+        }}
+      />
+    </View>
+  );
+};
+
+export default PercentageDimensionsBasics;

image

',18),p=[e];function g(t,k,I,B,C,Q){return a(),i("div",null,p)}const o=s(l,[["render",g]]);export{d as __pageData,o as default}; diff --git a/vitepress/docs/.vitepress/dist/assets/docs_height-and-width.md.BMEpPzGn.lean.js b/vitepress/docs/.vitepress/dist/assets/docs_height-and-width.md.BMEpPzGn.lean.js new file mode 100644 index 0000000..9bdb274 --- /dev/null +++ b/vitepress/docs/.vitepress/dist/assets/docs_height-and-width.md.BMEpPzGn.lean.js @@ -0,0 +1 @@ +import{_ as s,c as i,o as a,a4 as A}from"./chunks/framework.nQaBHiNx.js";const E="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAARQAAAExCAYAAAC9EV38AAAABHNCSVQICAgIfAhkiAAAABl0RVh0U29mdHdhcmUAZ25vbWUtc2NyZWVuc2hvdO8Dvz4AAAAmdEVYdENyZWF0aW9uIFRpbWUAc2VnIDI1IGRleiAyMDIzIDE0OjQ2OjAxDody9AAABDlJREFUeJzt1iFOA2EURlEGyg4wKNbAOirYDgbLjghhJUUgEBgS0g1Mm0GVYCE3/Ek5xz33qZs3LcuynAAEVs8vr6M3AEdimnf7rw/l4e195JbMzdXl6AnwL52OHgAcD0EBMoICZAQFyAgKkBEUICMoQEZQgIygABlBATKCAmQEBcgICpARFCAjKEBGUICMoAAZQQEyggJkBAXICAqQERQgIyhARlCAjKAAGUEBMoICZAQFyAgKkBEUICMoQEZQgIygABlBATKCAmQEBcgICpARFCAjKEBGUICMoAAZQQEyggJkBAXICAqQERQgIyhARlCAjKAAmdX3Y7M9H7Ujtdl+jJ6QuL2+GD0BfsSHAmQEBcgICpARFCAjKEBGUICMoAAZQQEyggJkBAXICAqQERQgIyhARlCAjKAAGUEBMoICZAQFyAgKkBEUICMoQEZQgIygABlBATKCAmQEBcgICpARFCAjKEBGUICMoAAZQQEyggJkBAXICAqQERQgIyhARlCAjKAAGUEBMoICZAQFyAgKkBEUICMoQEZQgIygABlBATKCAmQEBcgICpARFCAjKEBGUICMoAAZQQEyggJkBAXICAqQERQgIyhARlCAjKAAGUEBMoICZAQFyAgKkBEUICMoQEZQgIygABlBATKCAmQEBcgICpARFCAjKEBGUICMoAAZQQEyggJkBAXICAqQERQgIyhARlCAjKAAGUEBMoICZAQFyAgKkBEUICMoQEZQgIygABlBATKCAmQEBcgICpCZ5t1+ORzr+8eRWzhST3fr0RP4Iz4UICMoQEZQgIygABlBATKCAmQEBcgICpARFCAjKEBGUICMoAAZQQEyggJkBAXICAqQERQgIyhARlCAjKAAGUEBMoICZAQFyAgKkBEUICMoQEZQgIygABlBATKCAmQEBcgICpARFCAjKEBGUICMoAAZQQEyggJkBAXICAqQERQgIyhARlCAjKAAGUEBMoICZAQFyAgKkBEUICMoQEZQgIygABlBATKCAmQEBcgICpARFCAjKEBGUICMoAAZQQEyggJkBAXICAqQERQgIyhARlCAjKAAGUEBMoICZAQFyAgKkBEUICMoQEZQgIygABlBATKCAmQEBcgICpARFCAjKEBGUICMoAAZQQEyggJkBAXICAqQERQgIyhARlCAjKAAGUEBMoICZAQFyAgKkBEUICMoQEZQgIygABlBATKCAmQEBcgICpARFCAjKEBGUICMoAAZQQEyggJkBAXICAqQERQgIyhARlCAjKAAGUEBMoICZAQFyAgKkBEUICMoQEZQgIygABlBATKCAmQEBcgICpARFCAjKEBGUICMoAAZQQEyggJkBAXICAqQERQgIyhARlCAjKAAGUEBMoICZAQFyAgKkBEUICMoQEZQgIygABlBATLTvNsvh2N1pi/A7ykIkBEUIPMJ3zkgH6zzuH0AAAAASUVORK5CYII=",n="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAQQAAAHzCAYAAADGn2OrAAAABHNCSVQICAgIfAhkiAAAABl0RVh0U29mdHdhcmUAZ25vbWUtc2NyZWVuc2hvdO8Dvz4AAAAmdEVYdENyZWF0aW9uIFRpbWUAc2VnIDI1IGRleiAyMDIzIDE0OjUxOjA5oOvrzwAABbZJREFUeJzt1zFqVVEUhtGd5Fo7gwcG0wQcjaXT1NraEShEggQbGyfw8rwW8j4zgxPIWtXhVn/1se/Fvu/7AC/a3f3D3Fwf5nL1EOD52L59/7F6A7DY1eW/22B7++YwMzOffv5auQdY6PZ0nJnxywD8JwhABAGIIAARBCCCAEQQgAgCEEEAIghABAGIIAARBCCCAEQQgAgCEEEAIghABAGIIAARBCCCAEQQgAgCEEEAIghABAGIIAARBCCCAEQQgAgCEEEAIghABAGIIAARBCCCAEQQgAgCEEEAIghABAGIIAARBCCCAEQQgAgCEEEAIghABAGIIAARBCCCAEQQgAgCEEEAIghABAGIIAARBCCCAEQQgAgCEEEAIghABAGIIAARBCCCAEQQgAgCEEEAIghABAGIIAARBCCCAEQQgAgCEEEAsp0fX3+/WrkDWOj29XFmXAjAE4IARBCACAIQQQAiCEAEAYggABEEIIIARBCACAIQQQAiCEAEAYggABEEIIIARBCACAIQQQAiCEAEAYggABEEIIIARBCACAIQQQAiCEAEAYggABEEIIIARBCACAIQQQAiCEAEAYggABEEIIIARBCACAIQQQAiCEAEAYggABEEIIIARBCACAIQQQAiCEAEAYggABEEIIIARBCACAIQQQAiCEAEAYggABEEIIIARBCACAIQQQAiCEAEAYggABEEIIIARBCACAIQQQAiCEAEAYggABEEIIIARBCACAIQQQAiCEAEAYggABEEIIIARBCACAIQQQAiCEAEAYggABEEIIIARBCACAIQQQAiCEAEAYggABEEIIIARBCACAIQQQAiCEAEAYggABEEIIIARBCACAIQQQAiCEAEAYggABEEIIIARBCACAIQQQAiCEAEAYggABEEIIIARBCACAIQQQAiCEAEAYggABEEIIIARBCACAIQQQAiCEAEAYggABEEIIIARBCACAIQQQAiCEAEAYggABEEIIIARBCACAIQQQAiCEAEAYggABEEIIIARBCACAKQ7fz4/PHLyh3AQu8/vJsZFwLwhCAAEQQgggBEEIAIAhBBACIIQAQBiCAAEQQgggBEEIAIAhBBACIIQAQBiCAAEQQgggBEEIAIAhBBACIIQAQBiCAAEQQgggBEEIAIAhBBACIIQAQBiCAAEQQgggBEEIAIAhBBACIIQAQBiCAAEQQgggBEEIAIAhBBACIIQAQBiCAAEQQgggBEEIAIAhBBACIIQAQBiCAAEQQgggBEEIAIAhBBACIIQAQBiCAAEQQgggBEEIAIAhBBACIIQAQBiCAAEQQgggBEEIAIAhBBACIIQAQBiCAAEQQgggBEEIAIAhBBACIIQAQBiCAAEQQgggBEEIAIAhBBACIIQAQBiCAAEQQgggBEEIAIAhBBACIIQAQBiCAAEQQgggBEEIAIAhBBACIIQAQBiCAAEQQgggBEEIAIAhBBACIIQAQBiCAAEQQgggBEEIAIAhBBACIIQAQBiCAAEQQgggBEEIAIAhBBACIIQAQBiCAAEQQgggBEEIAIAhBBACIIQAQBiCAAEQQgggBEEIAIAhBBACIIQAQBiCAAEQQgggBEEIAIAhBBACIIQAQBiCAAEQQgggBEEIAIAhBBACIIQAQBiCAAEQQgggBEEIAIAhBBACIIQAQBiCAAEQQgggBEEIAIAhBBACIIQAQBiCAAEQQgggBEEIAIAhBBACIIQAQBiCAAEQQgggBEEIAIAhBBACIIQAQBiCAAEQQgggBEEIAIAhBBACIIQAQBiCAAEQQgggBEEIAIAhBBACIIQAQBiCAAEQQgggBEEIAIAhBBACIIQAQBiCAAEQQgggBEEIAIAhBBACIIQAQBiCAAEQQgggBEEIAIAhBBACIIQAQBiCAAEQQgggBEEIAIApCL4+Npn5nZrrQBXqq7+4e5uT7Mdv7wePqzcg/wDPwFFL4ilZOgtc4AAAAASUVORK5CYII=",h="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAQQAAAHzCAYAAADGn2OrAAAABHNCSVQICAgIfAhkiAAAABl0RVh0U29mdHdhcmUAZ25vbWUtc2NyZWVuc2hvdO8Dvz4AAAAmdEVYdENyZWF0aW9uIFRpbWUAc2VnIDI1IGRleiAyMDIzIDE0OjUzOjA1A1RvbwAABcNJREFUeJzt1yFuFHEYh+Gv7XAD9CY01OA4BxfCcCsQKDQngGTJhmwwGC7QLoMg+4IENU37POqfUT/15puLdV3XAR61/eE4N9e7udx6CHB/LJ+/fN16A7Cxq8vft8Hy/NluZmbeffu+5R5gQy9OtzMzfhmAPwQBiCAAEQQgggBEEIAIAhBBACIIQAQBiCAAEQQgggBEEIAIAhBBACIIQAQBiCAAEQQgggBEEIAIAhBBACIIQAQBiCAAEQQgggBEEIAIAhBBACIIQAQBiCAAEQQgggBEEIAIAhBBACIIQAQBiCAAEQQgggBEEIAIAhBBACIIQAQBiCAAEQQgggBEEIAIAhBBACIIQAQBiCAAEQQgggBEEIAIAhBBACIIQAQBiCAAEQQgggBEEIAIAhBBACIIQJbz49OPJ1vugH/y+uXTrSc8SPvDcWZcCMBfBAGIIAARBCCCAEQQgAgCEEEAIghABAGIIAARBCCCAEQQgAgCEEEAIghABAGIIAARBCCCAEQQgAgCEEEAIghABAGIIAARBCCCAEQQgAgCEEEAIghABAGIIAARBCCCAEQQgAgCEEEAIghABAGIIAARBCCCAEQQgAgCEEEAIghABAGIIAARBCCCAEQQgAgCEEEAIghABAGIIAARBCCCAEQQgAgCEEEAIghABAGIIAARBCCCAEQQgAgCEEEAIghABAGIIAARBCCCAEQQgAgCEEEAIghABAGIIAARBCCCAEQQgAgCEEEAIghABAGIIAARBCCCAEQQgAgCEEEAIghABAGIIAARBCCCAEQQgAgCEEEAIghABAGIIAARBCCCAEQQgAgCEEEAIghABAGIIAARBCCCAEQQgAgCEEEAIghABAGIIAARBCCCAEQQgAgCEEEAIghABAGIIAARBCCCAEQQgAgCEEEAIghABAGIIAARBCCCAEQQgAgCEEEAIghABAGIIAARBCCCAEQQgAgCEEEAIghABAGIIAARBCCCAEQQgAgCEEEAIghABAGIIAARBCCCAEQQgAgCEEEAIghABAGIIAARBCDL+fHh7cctdzxI79+82noC/BcXAhBBACIIQAQBiCAAEQQgggBEEIAIAhBBACIIQAQBiCAAEQQgggBEEIAIAhBBACIIQAQBiCAAEQQgggBEEIAIAhBBACIIQAQBiCAAEQQgggBEEIAIAhBBACIIQAQBiCAAEQQgggBEEIAIAhBBACIIQAQBiCAAEQQgggBEEIAIAhBBACIIQAQBiCAAEQQgggBEEIAIAhBBACIIQAQBiCAAEQQgggBEEIAIAhBBACIIQAQBiCAAEQQgggBEEIAIAhBBACIIQAQBiCAAEQQgggBEEIAIAhBBACIIQAQBiCAAEQQgggBEEIAIAhBBACIIQAQBiCAAEQQgggBEEIAIAhBBACIIQAQBiCAAEQQgggBEEIAIAhBBACIIQAQBiCAAEQQgggBEEIAIAhBBACIIQAQBiCAAEQQgggBEEIAIAhBBACIIQAQBiCAAEQQgggBEEIAIAhBBACIIQAQBiCAAEQQgggBEEIAIAhBBACIIQAQBiCAAEQQgggBEEIAIAhBBACIIQAQBiCAAEQQgggBEEIAIAhBBACIIQAQBiCAAEQQgggBEEIAIAhBBACIIQAQBiCAAEQQgggBEEIAIAhBBACIIQAQBiCAAEQQgggBEEIAIAhBBACIIQAQBiCAAEQQgggBEEIAIAhBBACIIQAQBiCAAEQQgggBEEIAIAhBBACIIQAQBiCAAEQQgggBEEIAIAhBBACIIQAQBiCAAEQQgggBEEIAIAhBBACIIQAQBiCAAEQQgggBEEIAIAhBBACIIQAQBiCAAEQQgggBEEIAIAhBBACIIQAQBiCAAEQQgggBEEIAIAhBBACIIQAQBiCAAEQQgggBEEIAIAhBBACIIQAQBiCAAEQQgF7d3p3VmZrnSBnis9ofj3FzvZjl/uDv93HIPcA/8Al28JV8gvDx+AAAAAElFTkSuQmCC",d=JSON.parse('{"title":"Altura e Largura","description":"","frontmatter":{},"headers":[],"relativePath":"docs/height-and-width.md","filePath":"docs/height-and-width.md"}'),l={name:"docs/height-and-width.md"},e=A("",18),p=[e];function g(t,k,I,B,C,Q){return a(),i("div",null,p)}const o=s(l,[["render",g]]);export{d as __pageData,o as default}; diff --git a/vitepress/docs/.vitepress/dist/assets/docs_images.md.CwJwsq7S.js b/vitepress/docs/.vitepress/dist/assets/docs_images.md.CwJwsq7S.js new file mode 100644 index 0000000..c9eaf4f --- /dev/null +++ b/vitepress/docs/.vitepress/dist/assets/docs_images.md.CwJwsq7S.js @@ -0,0 +1,60 @@ +import{_ as a,c as s,o as i,a4 as e}from"./chunks/framework.nQaBHiNx.js";const g=JSON.parse('{"title":"Imagens","description":"","frontmatter":{},"headers":[],"relativePath":"docs/images.md","filePath":"docs/images.md"}'),n={name:"docs/images.md"},o=e(`

Imagens

Recursos de imagem estática

React Native fornece uma maneira unificada de gerenciar imagens e outros ativos de mídia em seus aplicativos Android e iOS. Para adicionar uma imagem estática ao seu aplicativo, coloque-a em algum lugar da árvore do código-fonte e referencie-a assim:

jsx
<Image source={require('./my-icon.png')} />

O nome da imagem é resolvido da mesma forma que os módulos JS são resolvidos. No exemplo acima, o bundler procurará my-icon.png na mesma pasta do componente que o requer.

Você pode usar os sufixos @2x e @3x para fornecer imagens para diferentes densidades de tela. Se você tiver a seguinte estrutura de arquivos:

.
+├── button.js
+└── img
+    ├── check.png
+    ├── check@2x.png
+    └── check@3x.png

...e o código button.js contém:

jsx
<Image source={require('./img/check.png')} />

...o empacotador agrupará e exibirá a imagem correspondente à densidade da tela do dispositivo. Por exemplo, check@2x.png será usado em um iPhone 7, enquanto check@3x.png será usado em um iPhone 7 Plus ou Nexus 5. Se não houver imagem que corresponda à densidade da tela, a melhor opção mais próxima será ser selecionado.

No Windows, talvez seja necessário reiniciar o empacotador se você adicionar novas imagens ao seu projeto.

Aqui estão alguns benefícios que você obtém:

  1. Mesmo sistema em Android e iOS.
  2. As imagens ficam na mesma pasta do seu código JavaScript. Os componentes são independentes.
  3. Nenhum namespace global, ou seja, você não precisa se preocupar com colisões de nomes.
  4. Somente as imagens realmente usadas serão empacotadas em seu aplicativo.
  5. Adicionar e alterar imagens não requer recompilação do aplicativo, você pode atualizar o simulador normalmente.
  6. O empacotador conhece as dimensões da imagem, não há necessidade de duplicá-la no código.
  7. As imagens podem ser distribuídas por meio de pacotes npm.

Para que isso funcione, o nome da imagem em require deve ser conhecido estaticamente.

// BOM
+<Image source={require('./my-icon.png')} />;
+
+// RUIM
+const icon = this.props.active
+  ? 'my-icon-active'
+  : 'my-icon-inactive';
+<Image source={require('./' + icon + '.png')} />;
+
+// BOM
+const icon = this.props.active
+  ? require('./my-icon-active.png')
+  : require('./my-icon-inactive.png');
+<Image source={icon} />;

Observe que as fontes de imagem exigidas desta forma incluem informações de tamanho (largura, altura) da imagem. Se você precisar dimensionar a imagem dinamicamente (ou seja, via flex), pode ser necessário definir manualmente {width: undefined, height: undefined} no atributo de estilo.

Recursos estáticos sem imagem

A sintaxe require descrita acima também pode ser usada para incluir estaticamente arquivos de áudio, vídeo ou documentos em seu projeto. Os tipos de arquivo mais comuns são suportados, incluindo .mp3, .wav, .mp4, .mov, .html e .pdf. Consulte os padrões do bundler para obter a lista completa.

Você pode adicionar suporte para outros tipos adicionando uma opção de resolvedor assetsExts em sua configuração Metro.

Uma ressalva é que os vídeos devem usar posicionamento absoluto em vez de flexGrow, uma vez que as informações de tamanho não são transmitidas atualmente para ativos que não sejam de imagem. Essa limitação não ocorre para vídeos vinculados diretamente ao Xcode ou à pasta Assets para Android.

Imagens dos recursos do aplicativo híbrido

Se você estiver construindo um aplicativo híbrido (algumas UIs no React Native, algumas UIs no código da plataforma), você ainda poderá usar imagens que já estão incluídas no aplicativo.

Para imagens incluídas nos catálogos de ativos do Xcode ou na pasta drawable do Android, use o nome da imagem sem a extensão:

jsx
<Image
+  source={{uri: 'app_icon'}}
+  style={{width: 40, height: 40}}
+/>

Para imagens na pasta de ativos do Android, use o esquema assets:/:

jsx
<Image
+  source={{uri: 'asset:/app_icon.png'}}
+  style={{width: 40, height: 40}}
+/>

Essas abordagens não fornecem verificações de segurança. Cabe a você garantir que essas imagens estejam disponíveis no aplicativo. Além disso, você deve especificar as dimensões da imagem manualmente.

Imagens de rede

Muitas das imagens que você exibirá em seu aplicativo não estarão disponíveis em tempo de compilação ou você desejará carregar algumas dinamicamente para manter o tamanho binário baixo. Ao contrário dos recursos estáticos, você precisará especificar manualmente as dimensões da sua imagem. É altamente recomendável que você use https também para atender aos requisitos de segurança de transporte de aplicativos no iOS.

jsx
// BOM
+<Image source={{uri: 'https://reactjs.org/logo-og.png'}}
+       style={{width: 400, height: 400}} />
+
+// RUIM
+<Image source={{uri: 'https://reactjs.org/logo-og.png'}} />

Solicitações de rede para imagens

Se você quiser definir coisas como HTTP-Verb, Headers ou Body junto com a solicitação de imagem, você pode fazer isso definindo estas propriedades no objeto de origem:

jsx
<Image
+  source={{
+    uri: 'https://reactjs.org/logo-og.png',
+    method: 'POST',
+    headers: {
+      Pragma: 'no-cache',
+    },
+    body: 'Your Body goes here',
+  }}
+  style={{width: 400, height: 400}}
+/>

URI com dados

Às vezes, você pode obter dados de imagem codificados de uma chamada da API REST. Você pode usar o esquema uri 'data:' para usar essas imagens. Da mesma forma que para os recursos de rede, você precisará especificar manualmente as dimensões da sua imagem.

INFORMAÇÕES Isso é recomendado apenas para imagens muito pequenas e dinâmicas, como ícones em uma lista de um banco de dados.

jsx
// inclua pelo menos largura e altura!
+<Image
+  style={{
+    width: 51,
+    height: 51,
+    resizeMode: 'contain',
+  }}
+  source={{
+    uri: 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADMAAAAzCAYAAAA6oTAqAAAAEXRFWHRTb2Z0d2FyZQBwbmdjcnVzaEB1SfMAAABQSURBVGje7dSxCQBACARB+2/ab8BEeQNhFi6WSYzYLYudDQYGBgYGBgYGBgYGBgYGBgZmcvDqYGBgmhivGQYGBgYGBgYGBgYGBgYGBgbmQw+P/eMrC5UTVAAAAABJRU5ErkJggg==',
+  }}
+/>

Controle de cache (somente iOS)

Em alguns casos, você pode querer exibir uma imagem apenas se ela já estiver no cache local, ou seja, um espaço reservado de baixa resolução até que uma resolução mais alta esteja disponível. Em outros casos, você não se importa se a imagem está desatualizada e está disposto a exibi-la para economizar largura de banda. A propriedade de origem do cache fornece controle sobre como a camada de rede interage com o cache.

  • default: use a estratégia padrão das plataformas nativas.
  • reload: os dados do URL serão carregados da fonte de origem. Nenhum dado de cache existente deve ser usado para atender a uma solicitação de carregamento de URL.
  • force-cache: Os dados existentes em cache serão usados para atender à solicitação, independentemente de sua idade ou data de expiração. Se não houver dados existentes no cache correspondente à solicitação, os dados serão carregados da fonte de origem.
  • only-if-cached: os dados de cache existentes serão usados para atender a uma solicitação, independentemente de sua idade ou data de expiração. Se não houver dados existentes no cache correspondentes a uma solicitação de carregamento de URL, nenhuma tentativa será feita para carregar os dados da fonte de origem e o carregamento será considerado como tendo falhado.
jsx
<Image
+  source={{
+    uri: 'https://reactjs.org/logo-og.png',
+    cache: 'only-if-cached',
+  }}
+  style={{width: 400, height: 400}}
+/>

Imagens do sistema de arquivos local

Consulte CameraRoll para obter um exemplo de uso de recursos locais que estão fora de Images.xcassets.

Melhor imagem do rolo da câmera

O iOS salva vários tamanhos para a mesma imagem no rolo da câmera. É muito importante escolher aquele que seja o mais próximo possível por motivos de desempenho. Você não gostaria de usar a imagem de 3264x2448 com qualidade total como fonte ao exibir uma miniatura de 200x200. Se houver uma correspondência exata, o React Native irá escolhê-la, caso contrário, usará a primeira que for pelo menos 50% maior para evitar desfoque ao redimensionar de um tamanho próximo. Tudo isso é feito por padrão, então você não precisa se preocupar em escrever o código tedioso (e sujeito a erros) para fazer isso sozinho.

Por que não dimensionar tudo automaticamente?

No navegador, se você não fornecer um tamanho para uma imagem, o navegador renderizará um elemento 0x0, fará o download da imagem e, em seguida, renderizará a imagem com base no tamanho correto. O grande problema com esse comportamento é que sua IU vai pular conforme as imagens são carregadas, o que torna a experiência do usuário muito ruim. Isso é chamado de mudança cumulativa de layout.

No React Native esse comportamento não é implementado intencionalmente. É mais trabalhoso para o desenvolvedor saber antecipadamente as dimensões (ou proporção) da imagem remota, mas acreditamos que isso leva a uma melhor experiência do usuário. Imagens estáticas carregadas do pacote de aplicativos por meio da sintaxe require('./my-icon.png') podem ser dimensionadas automaticamente porque suas dimensões estão disponíveis imediatamente no momento da montagem.

Por exemplo, o resultado de require('./my-icon.png') pode ser:

jsx
{"__packager_asset":true,"uri":"my-icon.png","width":591,"height":573}

Fonte como um objeto

No React Native, uma decisão interessante é que o atributo src é denominado source e não aceita uma string, mas um objeto com um atributo uri.

jsx
<Image source={{uri: 'something.jpg'}} />

Do lado da infraestrutura, a razão é que nos permite anexar metadados a este objeto. Por exemplo, se você estiver usando require('./my-icon.png'), adicionamos informações sobre sua localização e tamanho reais (não confie neste fato, pois pode mudar no futuro!). Isso também é uma prova futura, por exemplo, podemos querer oferecer suporte a sprites em algum momento, em vez de gerar {uri: ...}, podemos gerar {uri: ..., crop: {left: 10, top: 50, width: 20, height: 40}} e suporta sprites de forma transparente em todos os sites de chamada existentes.

Do lado do usuário, isso permite anotar o objeto com atributos úteis, como a dimensão da imagem, para calcular o tamanho em que ela será exibida. Sinta-se à vontade para usá-lo como sua estrutura de dados para armazenar mais informações sobre sua imagem .

Imagem de fundo via aninhamento

Uma solicitação de recurso comum de desenvolvedores familiarizados com a web é a imagem de fundo. Para lidar com esse caso de uso, você pode usar o componente <ImageBackground>, que possui os mesmos adereços de <Image>, e adicionar quaisquer filhos que você gostaria de colocar em camadas sobre ele.

Talvez você não queira usar <ImageBackground> em alguns casos, pois a implementação é básica. Consulte a documentação do <ImageBackground> para obter mais informações e crie seu próprio componente personalizado quando necessário.

jsx
return (
+  <ImageBackground source={...} style={{width: '100%', height: '100%'}}>
+    <Text>Inside</Text>
+  </ImageBackground>
+);

Observe que você deve especificar alguns atributos de estilo de largura e altura.

Estilo arredondado do iOS

Observe que as seguintes propriedades de estilo de raio de borda específicas de canto podem ser ignoradas pelo componente de imagem do iOS:

  • borderTopLeftRadius
  • borderTopRightRadius
  • borderBottomLeftRadius
  • borderBottomRightRadius

Decodificação fora do thread

A decodificação de imagens pode levar mais do que um quadro. Esta é uma das principais fontes de queda de quadros na web porque a decodificação é feita na thread principal. No React Native, a decodificação da imagem é feita em uma thread diferente. Na prática, você já precisa cuidar do caso quando a imagem ainda não foi baixada, portanto, exibir o espaço reservado para mais alguns quadros enquanto ela é decodificada não requer nenhuma alteração de código.

Configurando limites de cache de imagens do iOS

No iOS, expomos uma API para substituir os limites de cache de imagem padrão do React Native. Isso deve ser chamado de dentro do seu código AppDelegate nativo (por exemplo, dentro de didFinishLaunchingWithOptions).

RCTSetImageCacheLimits(4*1024*1024, 200*1024*1024);

Parâmetros

NOMETIPOOBRIGATÓRIODESCRIÇÃO
imageSizeLimitnumberSimLimite de tamanho do cache de imagem.
totalCostLimitnumberSimLimite total de custo do cache.

No exemplo de código acima, o limite de tamanho da imagem é definido como 4 MB e o limite de custo total é definido como 200 MB.

`,71),t=[o];function d(p,r,l,h,c,k){return i(),s("div",null,t)}const u=a(n,[["render",d]]);export{g as __pageData,u as default}; diff --git a/vitepress/docs/.vitepress/dist/assets/docs_images.md.CwJwsq7S.lean.js b/vitepress/docs/.vitepress/dist/assets/docs_images.md.CwJwsq7S.lean.js new file mode 100644 index 0000000..618618f --- /dev/null +++ b/vitepress/docs/.vitepress/dist/assets/docs_images.md.CwJwsq7S.lean.js @@ -0,0 +1 @@ +import{_ as a,c as s,o as i,a4 as e}from"./chunks/framework.nQaBHiNx.js";const g=JSON.parse('{"title":"Imagens","description":"","frontmatter":{},"headers":[],"relativePath":"docs/images.md","filePath":"docs/images.md"}'),n={name:"docs/images.md"},o=e("",71),t=[o];function d(p,r,l,h,c,k){return i(),s("div",null,t)}const u=a(n,[["render",d]]);export{g as __pageData,u as default}; diff --git a/vitepress/docs/.vitepress/dist/assets/docs_integration-with-android-fragment.md.LAbR2gAq.js b/vitepress/docs/.vitepress/dist/assets/docs_integration-with-android-fragment.md.LAbR2gAq.js new file mode 100644 index 0000000..759a8b9 --- /dev/null +++ b/vitepress/docs/.vitepress/dist/assets/docs_integration-with-android-fragment.md.LAbR2gAq.js @@ -0,0 +1,117 @@ +import{_ as s,c as i,o as a,a4 as n}from"./chunks/framework.nQaBHiNx.js";const g=JSON.parse('{"title":"Integração com um fragmento Android","description":"","frontmatter":{},"headers":[],"relativePath":"docs/integration-with-android-fragment.md","filePath":"docs/integration-with-android-fragment.md"}'),t={name:"docs/integration-with-android-fragment.md"},e=n(`

Integração com um fragmento Android

O guia para integração com aplicativos existentes detalha como integrar um aplicativo React Native de tela inteira em um aplicativo Android existente como uma Activity. Usar componentes React Native em Fragments em um aplicativo existente requer alguma configuração adicional. A vantagem disso é que permite que um aplicativo nativo integre componentes React Native junto com fragmentos nativos em uma Activity.

1. Adicione React Native ao seu aplicativo

Siga o guia de integração com aplicativos existentes até a seção Integração de código. Continue seguindo a Etapa 1. Crie um arquivo index.android.js e a Etapa 2. Adicione seu código React Native desta seção.

2. Integrando seu aplicativo com um fragmento React Native

Você pode renderizar seu componente React Native em um Fragment em vez de uma Activity React Native em tela inteira. O componente pode ser denominado “screen” ou “fragment” e funcionará da mesma maneira que um fragmento do Android, provavelmente contendo componentes filhos. Esses componentes podem ser colocados em uma pasta /fragments e os componentes filhos usados para compor o fragmento podem ser colocados em uma pasta /components.

Você precisará implementar a interface ReactApplication em sua classe principal do aplicativo Java/Kotlin. Se você criou um novo projeto no Android Studio com uma Activity padrão, precisará criar uma nova classe (por exemplo, MyReactApplication.java ou MyReactApplication.kt). Se for uma classe existente, você poderá encontrar esta classe principal em seu arquivo AndroidManifest.xml. Sob a tag <application /> você deverá ver uma propriedade android:name, por exemplo. android:name=".MyReactApplication". Este valor é a classe que você deseja implementar e para a qual fornecer os métodos necessários.

Certifique-se de que sua classe principal Application implemente ReactApplication:

java
public class MyReactApplication extends Application implements ReactApplication {...}
kt
class MyReactApplication: Application(), ReactApplication {...}

Substitua os métodos necessários getUseDeveloperSupport, getPackages e getReactNativeHost:

java
public class MyReactApplication extends Application implements ReactApplication {
+    @Override
+    public void onCreate() {
+        super.onCreate();
+        SoLoader.init(this, false);
+    }
+
+    private final ReactNativeHost mReactNativeHost = new DefaultReactNativeHost(this) {
+        @Override
+        public boolean getUseDeveloperSupport() {
+            return BuildConfig.DEBUG;
+        }
+
+        protected List<ReactPackage> getPackages() {
+            List<ReactPackage> packages = new PackageList(this).getPackages();
+            // Pacotes que ainda não podem ser vinculados automaticamente podem ser adicionados manualmente aqui
+            return packages;
+        }
+    };
+
+    @Override
+    public ReactNativeHost getReactNativeHost() {
+        return mReactNativeHost;
+    }
+}
kotlin
class MyReactApplication : Application(), ReactApplication {
+    override fun onCreate() {
+        super.onCreate()
+        SoLoader.init(this, false)
+    }
+    private val reactNativeHost =
+        object : DefaultReactNativeHost(this) {
+            override fun getUseDeveloperSupport() = BuildConfig.DEBUG
+            override fun getPackages(): List<ReactPackage> {
+                val packages = PackageList(this).getPackages().toMutableList()
+                // Pacotes que ainda não podem ser vinculados automaticamente podem ser adicionados manualmente aqui
+                return packages
+            }
+        }
+    override fun getReactNativeHost(): ReactNativeHost = reactNativeHost
+}

Se você estiver usando o Android Studio, use Alt + Enter para adicionar todas as importações ausentes na sua classe. Alternativamente, estas são as importações necessárias para incluir manualmente:

java
import android.app.Application;
+
+import com.facebook.react.PackageList;
+import com.facebook.react.ReactApplication;
+import com.facebook.react.ReactNativeHost;
+import com.facebook.react.ReactPackage;
+import com.facebook.react.defaults.DefaultReactNativeHost;
+import com.facebook.soloader.SoLoader;
+
+import java.util.List;
kotlin
import android.app.Application
+
+import com.facebook.react.PackageList
+import com.facebook.react.ReactApplication
+import com.facebook.react.ReactNativeHost
+import com.facebook.react.ReactPackage
+import com.facebook.react.defaults.DefaultReactNativeHost
+import com.facebook.soloader.SoLoader

Execute uma operação "Sync Project files with Gradle".

3. Adicione um FrameLayout para o fragmento React Native

Agora você adicionará seu fragmento React Native a uma Activity. Para um novo projeto, esta Activity será MainActivity, mas pode ser qualquer activity e mais fragmentos podem ser adicionados a Activity à medida que você integra mais componentes React Native em seu aplicativo.

Primeiro adicione o React Native Fragment ao layout da sua Activity. Por exemplo main_activity.xml na pasta res/layouts\`.

Adicione um <FrameLayout> com 'id\`, largura e altura. Este é o layout no qual você encontrará e renderizará seu fragmento React Native.

xml
<FrameLayout
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    android:id="@+id/reactNativeFragment"
+    android:layout_width="match_parent"
+    android:layout_height="match_parent" />

4. Adicionar um fragmento React Native ao FrameLayout

Para adicionar seu React Native Fragment ao seu layout, você precisa ter uma Activity. Conforme mencionado em um novo projeto, esta será a MainActivity. Nesta Activity adicione um botão e um ouvinte de evento. Ao clicar no botão, você renderizará seu fragmento React Native.

Modifique o layout da sua Activity para adicionar o botão:

xml
<Button
+    android:layout_margin="10dp"
+    android:id="@+id/button"
+    android:layout_width="match_parent"
+    android:layout_height="wrap_content"
+    android:text="Show react fragment" />

Agora, em sua classe Activity (por exemplo, MainActivity.java ou MainActivity.kt), você precisa adicionar um OnClickListener para o botão, instanciar seu ReactFragment e adicioná-lo ao layout do quadro.

Adicione o campo do botão ao topo da sua Activity:

java
private Button mButton;
kotlin
private lateinit var button: Button

Atualize o método onCreate da sua Activity da seguinte forma:

java
@Override
+protected void onCreate(Bundle savedInstanceState) {
+    super.onCreate(savedInstanceState);
+    setContentView(R.layout.main_activity);
+
+    mButton = findViewById(R.id.button);
+    mButton.setOnClickListener(new View.OnClickListener() {
+        public void onClick(View v) {
+            Fragment reactNativeFragment = new ReactFragment.Builder()
+                    .setComponentName("HelloWorld")
+                    .setLaunchOptions(getLaunchOptions("test message"))
+                    .build();
+
+            getSupportFragmentManager()
+                    .beginTransaction()
+                    .add(R.id.reactNativeFragment, reactNativeFragment)
+                    .commit();
+
+        }
+    });
+}
kotlin
override fun onCreate(savedInstanceState: Bundle) {
+    super.onCreate(savedInstanceState)
+    setContentView(R.layout.main_activity)
+    button = findViewById<Button>(R.id.button)
+    button.setOnClickListener {
+        val reactNativeFragment = ReactFragment.Builder()
+                .setComponentName("HelloWorld")
+                .setLaunchOptions(getLaunchOptions("test message"))
+                .build()
+        getSupportFragmentManager()
+                .beginTransaction()
+                .add(R.id.reactNativeFragment, reactNativeFragment)
+                .commit()
+    }
+}

No código acima, Fragment reactNativeFragment = new ReactFragment.Builder() cria o ReactFragment e getSupportFragmentManager().beginTransaction().add() adiciona o Fragment ao Frame Layout.\`

Se você estiver usando um kit inicial para React Native, substitua a string "HelloWorld" pela que está em seu arquivo index.js ou index.android.js (é o primeiro argumento para o método AppRegistry.registerComponent()).

Adicione o método getLaunchOptions que permitirá que você passe acessórios para o seu componente. Isso é opcional e você pode remover setLaunchOptions se não precisar passar nenhum props.

java
private Bundle getLaunchOptions(String message) {
+    Bundle initialProperties = new Bundle();
+    initialProperties.putString("message", message);
+    return initialProperties;
+}
kotlin
private fun getLaunchOptions(message: String) = Bundle().apply {
+    putString("message", message)
+}

Adicione todas as importações ausentes na sua classe Activity. Tenha cuidado ao usar o BuildConfig do seu pacote e não o do pacote Facebook! Alternativamente, estas são as importações necessárias para incluir manualmente:

java
import android.app.Application;
+
+import com.facebook.react.ReactApplication;
+import com.facebook.react.ReactNativeHost;
+import com.facebook.react.ReactPackage;
+import com.facebook.react.shell.MainReactPackage;
+import com.facebook.soloader.SoLoader;
kotlin
import android.app.Application
+
+import com.facebook.react.ReactApplication
+import com.facebook.react.ReactNativeHost
+import com.facebook.react.ReactPackage
+import com.facebook.react.shell.MainReactPackage
+import com.facebook.soloader.SoLoader

Execute uma operação "Sync Project files with Gradle".

5. Teste sua integração

Certifique-se de executar o yarn para instalar suas dependências react-native e executar o yarn native para iniciar o empacotador metro. Execute seu aplicativo Android no Android Studio e ele deverá carregar o código JavaScript do servidor de desenvolvimento e exibi-lo em seu fragmento React Native na Activity.

6. Configuração adicional – Módulos nativos

Pode ser necessário chamar o código Java/Kotlin existente do seu componente react. Os módulos nativos permitem que você chame código nativo e execute métodos em seu aplicativo nativo. Siga a configuração aqui native-modules-android

`,39),p=[e];function l(h,k,o,r,d,c){return a(),i("div",null,p)}const y=s(t,[["render",l]]);export{g as __pageData,y as default}; diff --git a/vitepress/docs/.vitepress/dist/assets/docs_integration-with-android-fragment.md.LAbR2gAq.lean.js b/vitepress/docs/.vitepress/dist/assets/docs_integration-with-android-fragment.md.LAbR2gAq.lean.js new file mode 100644 index 0000000..9ce06e3 --- /dev/null +++ b/vitepress/docs/.vitepress/dist/assets/docs_integration-with-android-fragment.md.LAbR2gAq.lean.js @@ -0,0 +1 @@ +import{_ as s,c as i,o as a,a4 as n}from"./chunks/framework.nQaBHiNx.js";const g=JSON.parse('{"title":"Integração com um fragmento Android","description":"","frontmatter":{},"headers":[],"relativePath":"docs/integration-with-android-fragment.md","filePath":"docs/integration-with-android-fragment.md"}'),t={name:"docs/integration-with-android-fragment.md"},e=n("",39),p=[e];function l(h,k,o,r,d,c){return a(),i("div",null,p)}const y=s(t,[["render",l]]);export{g as __pageData,y as default}; diff --git a/vitepress/docs/.vitepress/dist/assets/docs_integration-with-existing-apps.md.sEybxE0W.js b/vitepress/docs/.vitepress/dist/assets/docs_integration-with-existing-apps.md.sEybxE0W.js new file mode 100644 index 0000000..d7214f5 --- /dev/null +++ b/vitepress/docs/.vitepress/dist/assets/docs_integration-with-existing-apps.md.sEybxE0W.js @@ -0,0 +1 @@ +import{_ as a,c as i,o as t,a4 as e}from"./chunks/framework.nQaBHiNx.js";const v=JSON.parse('{"title":"Integração com aplicativos existentes","description":"","frontmatter":{},"headers":[],"relativePath":"docs/integration-with-existing-apps.md","filePath":"docs/integration-with-existing-apps.md"}'),o={name:"docs/integration-with-existing-apps.md"},s=e('

Integração com aplicativos existentes

React Native é ótimo quando você inicia um novo aplicativo móvel do zero. No entanto, também funciona bem para adicionar uma visualização única ou fluxo de usuário a aplicativos nativos existentes. Com algumas etapas, você pode adicionar novos recursos, telas, visualizações, etc. baseados no React Native.

As etapas específicas são diferentes dependendo da plataforma que você está almejando.

',4),n=[s];function c(r,p,d,l,m,h){return t(),i("div",null,n)}const g=a(o,[["render",c]]);export{v as __pageData,g as default}; diff --git a/vitepress/docs/.vitepress/dist/assets/docs_integration-with-existing-apps.md.sEybxE0W.lean.js b/vitepress/docs/.vitepress/dist/assets/docs_integration-with-existing-apps.md.sEybxE0W.lean.js new file mode 100644 index 0000000..7e7c89d --- /dev/null +++ b/vitepress/docs/.vitepress/dist/assets/docs_integration-with-existing-apps.md.sEybxE0W.lean.js @@ -0,0 +1 @@ +import{_ as a,c as i,o as t,a4 as e}from"./chunks/framework.nQaBHiNx.js";const v=JSON.parse('{"title":"Integração com aplicativos existentes","description":"","frontmatter":{},"headers":[],"relativePath":"docs/integration-with-existing-apps.md","filePath":"docs/integration-with-existing-apps.md"}'),o={name:"docs/integration-with-existing-apps.md"},s=e("",4),n=[s];function c(r,p,d,l,m,h){return t(),i("div",null,n)}const g=a(o,[["render",c]]);export{v as __pageData,g as default}; diff --git a/vitepress/docs/.vitepress/dist/assets/docs_integration-with-existing-apps_android-java.md.D1ywsP1m.js b/vitepress/docs/.vitepress/dist/assets/docs_integration-with-existing-apps_android-java.md.D1ywsP1m.js new file mode 100644 index 0000000..ab1a861 --- /dev/null +++ b/vitepress/docs/.vitepress/dist/assets/docs_integration-with-existing-apps_android-java.md.D1ywsP1m.js @@ -0,0 +1,160 @@ +import{_ as s,c as i,o as a,a4 as e}from"./chunks/framework.nQaBHiNx.js";const n="/assets/289311225-21b28d91-4031-4e02-bbcd-0232c1c24a16.BzZG4-5V.png",u=JSON.parse('{"title":"Android (Java)","description":"","frontmatter":{},"headers":[],"relativePath":"docs/integration-with-existing-apps/android-java.md","filePath":"docs/integration-with-existing-apps/android-java.md"}'),t={name:"docs/integration-with-existing-apps/android-java.md"},p=e(`

Android (Java)

Conceitos chave

Os segredos para integrar componentes React Native em seu aplicativo Android são:

  1. Configure as dependências e a estrutura de diretórios do React Native.
  2. Desenvolva seus componentes React Native em JavaScript.
  3. Adicione um ReactRootView ao seu aplicativo Android. Esta visualização servirá como contêiner para seu componente React Native.
  4. Inicie o servidor React Native e execute seu aplicativo nativo.
  5. Verifique se o aspecto do React Native no seu aplicativo funciona conforme o esperado.

Pré-requisitos

Siga o início rápido do React Native CLI no guia de configuração do ambiente para configurar seu ambiente de desenvolvimento para construir aplicativos React Native para Android.

1. Configure a estrutura de diretórios

Para garantir uma experiência tranquila, crie uma nova pasta para seu projeto React Native integrado e copie seu projeto Android existente para uma subpasta /android.

2. Instale dependências JavaScript

Vá para o diretório raiz do seu projeto e crie um novo arquivo package.json com o seguinte conteúdo:

json
{
+  "name": "MyReactNativeApp",
+  "version": "0.0.1",
+  "private": true,
+  "scripts": {
+    "start": "react-native start"
+  }
+}

Em seguida, instale os pacotes react e react-native. Abra um terminal ou prompt de comando, navegue até o diretório com seu arquivo package.json e execute:

bash
npm install react-native
bash
yarn add react-native

Isso imprimirá uma mensagem semelhante à seguinte (role para cima na saída do yarn para vê-la):

bash
warning "react-native@0.70.5" has unmet peer dependency "react@18.1.0"

Tudo bem, significa que também precisamos instalar o React:

bash
npm install react@version_printed_above
bash
yarn add react@version_printed_above

Yarn/npm criou uma nova pasta chamada /node_modules. Esta pasta armazena todas as dependências JavaScript necessárias para construir seu projeto.

Adicione node_modules/ ao seu arquivo .gitignore.

Adicionando React Native ao seu aplicativo

Configurando o Gradle

React Native usa o plugin React Native Gradle para configurar suas dependências e configuração do projeto.

Primeiro, vamos editar seu arquivo settings.gradle adicionando esta linha:

includeBuild('../node_modules/@react-native/gradle-plugin')

Então você precisa abrir seu build.gradle de nível superior e incluir esta linha:

buildscript {
+    repositories {
+        google()
+        mavenCentral()
+    }
+    dependencies {
+        classpath("com.android.tools.build:gradle:7.3.1")
+        classpath("com.facebook.react:react-native-gradle-plugin")
+    }
+}

Isso garante que o plugin React Native Gradle esteja disponível em seu projeto. Por fim, adicione essas linhas ao arquivo build.gradle do seu aplicativo (é um arquivo build.gradle diferente dentro da pasta do seu aplicativo):

apply plugin: "com.android.application"
+apply plugin: "com.facebook.react"
+
+repositories {
+    mavenCentral()
+}
+
+dependencies {
+    // Outras dependências aqui
+    implementation "com.facebook.react:react-android"
+    implementation "com.facebook.react:hermes-android"
+}

Essas dependências estão disponíveis em mavenCentral(), portanto, certifique-se de tê-las definidas no bloco repositories{}.

INFORMAÇÕES

Intencionalmente não especificamos a versão para essas dependências de implementation, pois o React Native Gradle Plugin cuidará disso. Se você não usar o plugin React Native Gradle, terá que especificar a versão manualmente.

Habilitar autolinking de módulos nativos

Para usar o poder do autolinking, temos que aplicá-lo em alguns lugares. Primeiro adicione a seguinte entrada em settings.gradle:

apply from: file("../node_modules/@react-native-community/cli-platform-android/native_modules.gradle"); applyNativeModulesSettingsGradle(settings)

Em seguida, adicione a seguinte entrada na parte inferior do app/build.gradle:

apply from: file("../../node_modules/@react-native-community/cli-platform-android/native_modules.gradle"); applyNativeModulesAppBuildGradle(project)

Configurando permissões

Em seguida, certifique-se de ter permissão de Internet em seu AndroidManifest.xml:

xml
<uses-permission android:name="android.permission.INTERNET" />

Se você precisar acessar DevSettingsActivity, adicione ao seu AndroidManifest.xml:

xml
<activity android:name="com.facebook.react.devsupport.DevSettingsActivity" />

Isso só é usado no modo de desenvolvimento ao recarregar o JavaScript do servidor de desenvolvimento, portanto, você pode removê-lo nas compilações de lançamento, se necessário.

Tráfego de texto simples (nível de API 28+)

Texto não criptografado

A partir do Android 9 (API de nível 28), o tráfego de texto não criptografado é desativado por padrão; isso evita que seu aplicativo se conecte ao empacotador Metro. As alterações abaixo permitem tráfego de texto não criptografado em compilações de depuração.

  1. Aplique a opção usesCleartextTraffic ao seu Debug AndroidManifest.xml
xml
<!-- ... -->
+<application
+  android:usesCleartextTraffic="true" tools:targetApi="28" >
+  <!-- ... -->
+</application>
+<!-- ... -->

Isso não é necessário para compilações de versão.

Para saber mais sobre a configuração de segurança de rede e a política de tráfego de texto não criptografado, consulte este link.

Integração de código

Agora vamos modificar o aplicativo Android nativo para integrar o React Native.

O componente React Native

O primeiro código que escreveremos é o código React Native real para a nova tela "High Score" que será integrada em nosso aplicativo.

1. Crie um arquivo index.js

Primeiro, crie um arquivo index.js vazio na raiz do seu projeto React Native.

index.js é o ponto de partida para aplicativos React Native e é sempre necessário. Pode ser um arquivo pequeno que requer outro arquivo que faça parte do seu componente ou aplicativo React Native, ou pode conter todo o código necessário para ele. No nosso caso, colocaremos tudo em index.js.

2. Adicione seu código React Native

No seu index.js, crie seu componente. Em nosso exemplo aqui, adicionaremos um componente <Text> dentro de um <View> estilizado:

jsx
import React from 'react';
+import {AppRegistry, StyleSheet, Text, View} from 'react-native';
+
+const HelloWorld = () => {
+  return (
+    <View style={styles.container}>
+      <Text style={styles.hello}>Hello, World</Text>
+    </View>
+  );
+};
+const styles = StyleSheet.create({
+  container: {
+    flex: 1,
+    justifyContent: 'center',
+  },
+  hello: {
+    fontSize: 20,
+    textAlign: 'center',
+    margin: 10,
+  },
+});
+
+AppRegistry.registerComponent(
+  'MyReactNativeApp',
+  () => HelloWorld,
+);

3. Configure permissões para sobreposição de erros de desenvolvimento

Se o seu aplicativo for direcionado à API Android de nível 23 ou superior, verifique se você tem a permissão android.permission.SYSTEM_ALERT_WINDOW ativada para a compilação de desenvolvimento. Você pode verificar isso com Settings.canDrawOverlays(this);. Isso é necessário em compilações de desenvolvimento porque os erros de desenvolvimento do React Native devem ser exibidos acima de todas as outras janelas. Devido ao novo sistema de permissões introduzido na API nível 23 (Android M), o usuário precisa aprová-lo. Isso pode ser conseguido adicionando o seguinte código ao método onCreate() da sua atividade.

java
private final int OVERLAY_PERMISSION_REQ_CODE = 1;  // Escolha qualquer valor
+
+...
+
+if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
+    if (!Settings.canDrawOverlays(this)) {
+        Intent intent = new Intent(Settings.ACTION_MANAGE_OVERLAY_PERMISSION,
+                                   Uri.parse("package:" + getPackageName()));
+        startActivityForResult(intent, OVERLAY_PERMISSION_REQ_CODE);
+    }
+}

Finalmente, o método onActivityResult() (conforme mostrado no código abaixo) deve ser substituído para lidar com os casos de permissão aceita ou negada para uma UX consistente. Além disso, para integrar módulos nativos que usam startActivityForResult, precisamos passar o resultado para o método onActivityResult de nossa instância ReactInstanceManager.

java
@Override
+protected void onActivityResult(int requestCode, int resultCode, Intent data) {
+    if (requestCode == OVERLAY_PERMISSION_REQ_CODE) {
+        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
+            if (!Settings.canDrawOverlays(this)) {
+                // Permissão SYSTEM_ALERT_WINDOW não concedida
+            }
+        }
+    }
+    mReactInstanceManager.onActivityResult( this, requestCode, resultCode, data );
+}

A mágica: ReactRootView

Vamos adicionar algum código nativo para iniciar o tempo de execução do React Native e solicitar que ele renderize nosso componente JS. Para fazer isso, vamos criar uma Activity que cria um ReactRootView, inicia um aplicativo React dentro dele e o define como a visualização de conteúdo principal.

Android

Se você estiver direcionando a versão Android <5, use a classe AppCompatActivity do pacote com.android.support:appcompat em vez de Activity.

java
public class MyReactActivity extends Activity implements DefaultHardwareBackBtnHandler {
+    private ReactRootView mReactRootView;
+    private ReactInstanceManager mReactInstanceManager;
+
+    @Override
+    protected void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+        SoLoader.init(this, false);
+
+        mReactRootView = new ReactRootView(this);
+        List<ReactPackage> packages = new PackageList(getApplication()).getPackages();
+        // Pacotes que ainda não podem ser vinculados automaticamente podem ser adicionados manualmente aqui, por exemplo:
+        // pacotes.add(new MyReactNativePackage());
+        // Lembre-se de incluí-los em \`settings.gradle\` e \`app/build.gradle\` também.
+
+        mReactInstanceManager = ReactInstanceManager.builder()
+                .setApplication(getApplication())
+                .setCurrentActivity(this)
+                .setBundleAssetName("index.android.bundle")
+                .setJSMainModulePath("index")
+                .addPackages(packages)
+                .setUseDeveloperSupport(BuildConfig.DEBUG)
+                .setInitialLifecycleState(LifecycleState.RESUMED)
+                .build();
+
+        // A string aqui (por exemplo, "MyReactNativeApp") deve corresponder
+        // a string em AppRegistry.registerComponent() em index.js
+        mReactRootView.startReactApplication(mReactInstanceManager, "MyReactNativeApp", null);
+
+        setContentView(mReactRootView);
+    }
+
+    @Override
+    public void invokeDefaultOnBackPressed() {
+        super.onBackPressed();
+    }
+}

Informação

Se você estiver usando um kit inicial para React Native, substitua a string "HelloWorld" pela do seu arquivo index.js (é o primeiro argumento para o método AppRegistry.registerComponent()).

Execute a operação “Sync Project files with Gradle”.

Se você estiver usando o Android Studio, use Alt + Enter para adicionar todas as importações ausentes em sua classe MyReactActivity. Tenha cuidado ao usar o BuildConfig do seu pacote e não o do pacote facebook.

Precisamos definir o tema de MyReactActivity como Theme.AppCompat.Light.NoActionBar porque alguns componentes da UI do React Native dependem deste tema.

xml
<activity
+  android:name=".MyReactActivity"
+  android:label="@string/app_name"
+  android:theme="@style/Theme.AppCompat.Light.NoActionBar">
+</activity>

Dica

Um ReactInstanceManager pode ser compartilhado por múltiplas atividades e/ou fragmentos. Você desejará criar seu próprio ReactFragment ou ReactActivity e ter um suporte singleton que contenha um ReactInstanceManager. Quando você precisar do ReactInstanceManager (por exemplo, para conectar o ReactInstanceManager ao ciclo de vida dessas atividades ou fragmentos), use aquele fornecido pelo singleton.

Em seguida, precisamos passar alguns retornos de chamada do ciclo de vida da atividade para ReactInstanceManager e ReactRootView:

java
@Override
+protected void onPause() {
+    super.onPause();
+
+    if (mReactInstanceManager != null) {
+        mReactInstanceManager.onHostPause(this);
+    }
+}
+
+@Override
+protected void onResume() {
+    super.onResume();
+
+    if (mReactInstanceManager != null) {
+        mReactInstanceManager.onHostResume(this, this);
+    }
+}
+
+@Override
+protected void onDestroy() {
+    super.onDestroy();
+
+    if (mReactInstanceManager != null) {
+        mReactInstanceManager.onHostDestroy(this);
+    }
+    if (mReactRootView != null) {
+        mReactRootView.unmountReactApplication();
+    }
+}

Também precisamos passar de volta os eventos do botão para o React Native:

java
@Override
+ public void onBackPressed() {
+    if (mReactInstanceManager != null) {
+        mReactInstanceManager.onBackPressed();
+    } else {
+        super.onBackPressed();
+    }
+}

Isso permite que o JavaScript controle o que acontece quando o usuário pressiona o botão Voltar do hardware (por exemplo, para implementar a navegação). Quando o JavaScript não controla o pressionamento do botão Voltar, seu método invocaDefaultOnBackPressed será chamado. Por padrão, isso encerra sua atividade.

Finalmente, precisamos conectar o menu de desenvolvimento. Por padrão, isso é ativado agitando o dispositivo, mas isso não é muito útil em emuladores. Então, mostramos isso quando você pressiona o botão do menu de hardware (use Ctrl + M se estiver usando o emulador do Android Studio):

java
@Override
+public boolean onKeyUp(int keyCode, KeyEvent event) {
+    if (keyCode == KeyEvent.KEYCODE_MENU && mReactInstanceManager != null) {
+        mReactInstanceManager.showDevOptionsDialog();
+        return true;
+    }
+    return super.onKeyUp(keyCode, event);
+}

Agora sua atividade está pronta para executar algum código JavaScript.

Teste sua integração

Agora você executou todas as etapas básicas para integrar o React Native ao seu aplicativo atual. Agora iniciaremos o empacotador Metro para construir o pacote index.bundle e o servidor rodando em localhost para servi-lo.

1. Execute o empacotador

Para executar seu aplicativo, primeiro você precisa iniciar o servidor de desenvolvimento. Para fazer isso, execute o seguinte comando no diretório raiz do seu projeto React Native:

bash
npm start
bash
yarn start

2. Execute o aplicativo

Agora crie e execute seu aplicativo Android normalmente.

Assim que você atingir sua atividade com React dentro do aplicativo, ele deverá carregar o código JavaScript do servidor de desenvolvimento e exibir:

image

Criando uma versão de lançamento no Android Studio

Você também pode usar o Android Studio para criar suas versões de lançamento! É tão rápido quanto criar versões de lançamento do seu aplicativo Android nativo já existente.

Se você usar o plugin React Native Gradle conforme descrito acima, tudo deverá funcionar ao executar o aplicativo do Android Studio.

Se você não estiver usando o plugin React Native Gradle, há uma etapa adicional que você terá que executar antes de cada versão. Você precisa executar o seguinte para criar um pacote React Native, que será incluído em seu aplicativo Android nativo:

bash
$ npx react-native bundle --platform android --dev false --entry-file index.js --bundle-output android/com/your-company-name/app-package-name/src/main/assets/index.android.bundle --assets-dest android/com/your-company-name/app-package-name/src/main/res/

Dica

Não se esqueça de substituir os caminhos pelos corretos e criar a pasta de ativos caso ela não exista.

Agora, crie uma versão de lançamento do seu aplicativo nativo no Android Studio, como de costume, e você estará pronto para prosseguir!

E agora?

Neste ponto, você pode continuar desenvolvendo seu aplicativo normalmente. Consulte nossos documentos de depuração e implantação para saber mais sobre como trabalhar com React Native.

',98),l=[p];function h(o,k,d,r,c,E){return a(),i("div",null,l)}const y=s(t,[["render",h]]);export{u as __pageData,y as default}; diff --git a/vitepress/docs/.vitepress/dist/assets/docs_integration-with-existing-apps_android-java.md.D1ywsP1m.lean.js b/vitepress/docs/.vitepress/dist/assets/docs_integration-with-existing-apps_android-java.md.D1ywsP1m.lean.js new file mode 100644 index 0000000..c7b4a5c --- /dev/null +++ b/vitepress/docs/.vitepress/dist/assets/docs_integration-with-existing-apps_android-java.md.D1ywsP1m.lean.js @@ -0,0 +1 @@ +import{_ as s,c as i,o as a,a4 as e}from"./chunks/framework.nQaBHiNx.js";const n="/assets/289311225-21b28d91-4031-4e02-bbcd-0232c1c24a16.BzZG4-5V.png",u=JSON.parse('{"title":"Android (Java)","description":"","frontmatter":{},"headers":[],"relativePath":"docs/integration-with-existing-apps/android-java.md","filePath":"docs/integration-with-existing-apps/android-java.md"}'),t={name:"docs/integration-with-existing-apps/android-java.md"},p=e("",98),l=[p];function h(o,k,d,r,c,E){return a(),i("div",null,l)}const y=s(t,[["render",h]]);export{u as __pageData,y as default}; diff --git a/vitepress/docs/.vitepress/dist/assets/docs_integration-with-existing-apps_android-kotlin.md.CmoaTw48.js b/vitepress/docs/.vitepress/dist/assets/docs_integration-with-existing-apps_android-kotlin.md.CmoaTw48.js new file mode 100644 index 0000000..75fc0fb --- /dev/null +++ b/vitepress/docs/.vitepress/dist/assets/docs_integration-with-existing-apps_android-kotlin.md.CmoaTw48.js @@ -0,0 +1,137 @@ +import{_ as s,c as a,o as i,a4 as e}from"./chunks/framework.nQaBHiNx.js";const n="/assets/289311225-21b28d91-4031-4e02-bbcd-0232c1c24a16.BzZG4-5V.png",u=JSON.parse('{"title":"Android (Kotlin)","description":"","frontmatter":{},"headers":[],"relativePath":"docs/integration-with-existing-apps/android-kotlin.md","filePath":"docs/integration-with-existing-apps/android-kotlin.md"}'),t={name:"docs/integration-with-existing-apps/android-kotlin.md"},p=e(`

Android (Kotlin)

Conceitos chave

Os segredos para integrar componentes React Native em seu aplicativo Android são:

  1. Configure as dependências e a estrutura de diretórios do React Native.
  2. Desenvolva seus componentes React Native em JavaScript.
  3. Adicione um ReactRootView ao seu aplicativo Android. Esta visualização servirá como contêiner para seu componente React Native.
  4. Inicie o servidor React Native e execute seu aplicativo nativo.
  5. Verifique se o aspecto do seu aplicativo React Native funciona conforme o esperado.

Pré-requisitos

Siga o início rápido do React Native CLI no guia de configuração do ambiente para configurar seu ambiente de desenvolvimento para construir aplicativos React Native para Android.

  1. Configure a estrutura de diretórios Para garantir uma experiência tranquila, crie uma nova pasta para seu projeto React Native integrado e copie seu projeto Android existente para uma subpasta /android.

  2. Instale as dependências do JavaScript Vá para o diretório raiz do seu projeto e crie um novo arquivo package.json com o seguinte conteúdo:

json
{
+  "name": "MyReactNativeApp",
+  "version": "0.0.1",
+  "private": true,
+  "scripts": {
+    "start": "yarn react-native start"
+  }
+}

Em seguida, instale os pacotes react e react-native. Abra um terminal ou prompt de comando, navegue até o diretório com seu arquivo package.json e execute:

bash
npm install react-native
bash
yarn add react-native

Isso imprimirá uma mensagem semelhante à seguinte (role para cima na saída do fio para vê-la):

Atenção

O pacote "react-native@0.70.5" tem dependência de peer não atendida de "react@18.1.0"

Tudo bem, significa que também precisamos instalar o React:

bash
npm install react@version_printed_above
bash
yarn add react@version_printed_above

Yarn/npm criou uma nova pasta /node_modules. Esta pasta armazena todas as dependências JavaScript necessárias para construir seu projeto.

Adicione node_modules/ ao seu arquivo .gitignore.

Adicionando React Native ao seu aplicativo

Configurando o Gradle

React Native usa o plugin React Native Gradle para configurar suas dependências e configuração do projeto.

Primeiro, vamos editar seu arquivo settings.gradle adicionando esta linha:

includeBuild('../node_modules/@react-native/gradle-plugin')

Então você precisa abrir seu build.gradle de nível superior e incluir esta linha:

buildscript {
+    repositories {
+        google()
+        mavenCentral()
+    }
+    dependencies {
+        classpath("com.android.tools.build:gradle:7.3.1")
+        classpath("com.facebook.react:react-native-gradle-plugin")
+    }
+}

Isso garante que o plugin React Native Gradle esteja disponível em seu projeto. Por fim, adicione essas linhas ao arquivo build.gradle do seu aplicativo (é um arquivo build.gradle diferente dentro da pasta do seu aplicativo):

apply plugin: "com.android.application"
+apply plugin: "com.facebook.react"
+
+repositories {
+    mavenCentral()
+}
+
+dependencies {
+    // Outras dependências aqui
+    implementation "com.facebook.react:react-android"
+    implementation "com.facebook.react:hermes-android"
+}

Essas dependências estão disponíveis em mavenCentral(), portanto, certifique-se de tê-las definidas no repositories {}.

INFORMAÇÕES

Intencionalmente não especificamos a versão para essas dependências de implementation, pois o React Native Gradle Plugin cuidará disso. Se você não usar o plugin React Native Gradle, terá que especificar a versão manualmente.

Habilitar autolinking de módulos nativos

Para usar o poder do autolinking, temos que aplicá-lo em alguns lugares. Primeiro adicione a seguinte entrada em settings.gradle:

apply from: file("../node_modules/@react-native-community/cli-platform-android/native_modules.gradle"); applyNativeModulesSettingsGradle(settings)

Em seguida, adicione a seguinte entrada na parte inferior do app/build.gradle:

apply from: file("../../node_modules/@react-native-community/cli-platform-android/native_modules.gradle"); applyNativeModulesAppBuildGradle(project)

Configurando permissões

Em seguida, certifique-se de ter permissão de Internet em seu AndroidManifest.xml:

xml
<uses-permission android:name="android.permission.INTERNET" />

Se você precisar acessar DevSettingsActivity, adicione ao seu AndroidManifest.xml:

xml
<activity android:name="com.facebook.react.devsupport.DevSettingsActivity" />

Isso só é usado no modo de desenvolvimento ao recarregar o JavaScript do servidor de desenvolvimento, portanto, você pode removê-lo nas compilações de lançamento, se necessário.

Tráfego de texto simples (nível de API 28+)

Dica

A partir do Android 9 (API de nível 28), o tráfego de texto não criptografado é desativado por padrão; isso evita que seu aplicativo se conecte ao empacotador Metro. As alterações abaixo permitem tráfego de texto não criptografado em compilações de depuração.

  1. Aplique a opção usesCleartextTraffic ao seu Debug AndroidManifest.xml
xml
<!-- ... -->
+<application
+  android:usesCleartextTraffic="true" tools:targetApi="28" >
+  <!-- ... -->
+</application>
+<!-- ... -->

Isso não é necessário para compilações de versão.

Para saber mais sobre a configuração de segurança de rede e a política de tráfego de texto não criptografado, consulte este link.

Integração de código

Agora vamos modificar o aplicativo Android nativo para integrar o React Native.

O componente React Native

O primeiro código que escreveremos é o código React Native real para a nova tela "High Score" que será integrada em nosso aplicativo.

1. Crie um arquivo index.js

Primeiro, crie um arquivo index.js vazio na raiz do seu projeto React Native.

index.js é o ponto de partida para aplicativos React Native e é sempre necessário. Pode ser um arquivo pequeno que require outro arquivo que faça parte do seu componente ou aplicativo React Native, ou pode conter todo o código necessário para ele. No nosso caso, colocaremos tudo em index.js.

2. Adicione seu código React Native

No seu index.js, crie seu componente. Em nosso exemplo aqui, adicionaremos um componente <Text> dentro de um <View> estilizado:

jsx
import React from 'react';
+import {AppRegistry, StyleSheet, Text, View} from 'react-native';
+
+const HelloWorld = () => {
+  return (
+    <View style={styles.container}>
+      <Text style={styles.hello}>Hello, World</Text>
+    </View>
+  );
+};
+const styles = StyleSheet.create({
+  container: {
+    flex: 1,
+    justifyContent: 'center',
+  },
+  hello: {
+    fontSize: 20,
+    textAlign: 'center',
+    margin: 10,
+  },
+});
+
+AppRegistry.registerComponent(
+  'MyReactNativeApp',
+  () => HelloWorld,
+);

3. Configure permissões para sobreposição de erros de desenvolvimento

Se o seu aplicativo for direcionado à API Android de nível 23 ou superior, verifique se você tem a permissão android.permission.SYSTEM_ALERT_WINDOW ativada para a compilação de desenvolvimento. Você pode verificar isso com Settings.canDrawOverlays(this). Isso é necessário em compilações de desenvolvimento porque os erros de desenvolvimento do React Native devem ser exibidos acima de todas as outras janelas. Devido ao novo sistema de permissões introduzido na API nível 23 (Android M), o usuário precisa aprová-lo. Isso pode ser conseguido adicionando o seguinte código ao método onCreate() da sua Activity.

companion object {
+    const val OVERLAY_PERMISSION_REQ_CODE = 1  // Escolha qualquer valor
+}
+
+...
+
+if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
+    if(!Settings.canDrawOverlays(this)) {
+        val intent = Intent(Settings.ACTION_MANAGE_OVERLAY_PERMISSION,
+                                    Uri.parse("package: $packageName"))
+        startActivityForResult(intent, OVERLAY_PERMISSION_REQ_CODE);
+    }
+}

Finalmente, o método onActivityResult() (conforme mostrado no código abaixo) deve ser substituído para lidar com os casos de permissão aceita ou negada para um UX consistente. Além disso, para integrar módulos nativos que usam startActivityForResult, precisamos passar o resultado para o método onActivityResult de nossa instância ReactInstanceManager.

kotlin
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
+    if (requestCode == OVERLAY_PERMISSION_REQ_CODE) {
+        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
+            if (!Settings.canDrawOverlays(this)) {
+                // SYSTEM_ALERT_WINDOW permission not granted
+            }
+        }
+    }
+    reactInstanceManager?.onActivityResult(this, requestCode, resultCode, data)
+}

A mágica: ReactRootView

Vamos adicionar algum código nativo para iniciar o runtime do React Native e solicitar que ele renderize nosso componente JS. Para fazer isso, vamos criar uma Activity que cria um ReactRootView, inicia um aplicativo React dentro dele e o define como a visualização de conteúdo principal.

Se você estiver direcionando a versão Android <5, use a classe AppCompatActivity do pacote com.android.support:appcompat em vez de Activity.

kotlin
class MyReactActivity : Activity(), DefaultHardwareBackBtnHandler {
+    private lateinit var reactRootView: ReactRootView
+    private lateinit var reactInstanceManager: ReactInstanceManager
+    override fun onCreate(savedInstanceState: Bundle?) {
+        super.onCreate(savedInstanceState)
+        SoLoader.init(this, false)
+        reactRootView = ReactRootView(this)
+        val packages: List<ReactPackage> = PackageList(application).packages
+
+        // Pacotes que ainda não podem ser vinculados automaticamente podem ser adicionados manualmente aqui, por exemplo:
+        // packages.add(MyReactNativePackage())
+        // Lembre-se de incluí-los em \`settings.gradle\` e \`app/build.gradle\` também.
+        reactInstanceManager = ReactInstanceManager.builder()
+            .setApplication(application)
+            .setCurrentActivity(this)
+            .setBundleAssetName("index.android.bundle")
+            .setJSMainModulePath("index")
+            .addPackages(packages)
+            .setUseDeveloperSupport(BuildConfig.DEBUG)
+            .setInitialLifecycleState(LifecycleState.RESUMED)
+            .build()
+
+        // A string aqui (por exemplo, "MyReactNativeApp") deve corresponder
+        // a string em AppRegistry.registerComponent() em index.js
+        reactRootView?.startReactApplication(reactInstanceManager, "MyReactNativeApp", null)
+        setContentView(reactRootView)
+    }
+
+    override fun invokeDefaultOnBackPressed() {
+        super.onBackPressed()
+    }
+}

Se você estiver usando um kit inicial para React Native, substitua a string "HelloWorld" pela do seu arquivo index.js (é o primeiro argumento para o método AppRegistry.registerComponent()).

Execute uma operação “Sync Project files with Gradle”.

Se você estiver usando o Android Studio, use Alt + Enter para adicionar todas as importações ausentes em sua classe MyReactActivity. Tenha cuidado ao usar o BuildConfig do seu pacote e não o do pacote facebook.

Precisamos definir o tema de MyReactActivity como Theme.AppCompat.Light.NoActionBar porque alguns componentes da UI do React Native dependem deste tema.

<activity
+  android:name=".MyReactActivity"
+  android:label="@string/app_name"
+  android:theme="@style/Theme.AppCompat.Light.NoActionBar">
+</activity>

Nota

Um ReactInstanceManager pode ser compartilhado por múltiplas atividades e/ou fragmentos. Você desejará criar seu próprio ReactFragment ou ReactActivity e ter um suporte singleton que contenha um ReactInstanceManager. Quando você precisar do ReactInstanceManager (por exemplo, para conectar o ReactInstanceManager ao ciclo de vida dessas atividades ou fragmentos), use aquele fornecido pelo singleton.

Em seguida, precisamos passar alguns retornos de chamada do ciclo de vida da atividade para ReactInstanceManager e ReactRootView:

kotlin
override fun onPause() {
+    super.onPause()
+    reactInstanceManager.onHostPause(this)
+}
+
+override fun onResume() {
+    super.onResume()
+    reactInstanceManager.onHostResume(this, this)
+}
+
+override fun onDestroy() {
+    super.onDestroy()
+    reactInstanceManager.onHostDestroy(this)
+    reactRootView.unmountReactApplication()
+}

Também precisamos passar de volta os eventos do botão para o React Native:

kotlin
override fun onBackPressed() {
+    reactInstanceManager.onBackPressed()
+    super.onBackPressed()
+}

Isso permite que o JavaScript controle o que acontece quando o usuário pressiona o botão Voltar do hardware (por exemplo, para implementar a navegação). Quando o JavaScript não controla o pressionamento do botão Voltar, seu método invocaDefaultOnBackPressed será chamado. Por padrão, isso encerra sua Activity.

Finalmente, precisamos conectar o menu de desenvolvimento. Por padrão, isso é ativado agitando (intensamente) o dispositivo, mas isso não é muito útil em emuladores. Então, mostramos isso quando você pressiona o botão do menu de hardware (use Ctrl + M se estiver usando o emulador do Android Studio):

kt
override fun onKeyUp(keyCode: Int, event: KeyEvent?): Boolean {
+    if (keyCode == KeyEvent.KEYCODE_MENU && reactInstanceManager != null) {
+        reactInstanceManager.showDevOptionsDialog()
+        return true
+    }
+    return super.onKeyUp(keyCode, event)
+}

Agora sua atividade está pronta para executar algum código JavaScript.

Teste sua integração

Agora você executou todas as etapas básicas para integrar o React Native ao seu aplicativo atual. Agora iniciaremos o empacotador Metro para construir o pacote index.bundle e o servidor rodando em localhost para servi-lo.

1. Execute o empacotador

Para executar seu aplicativo, primeiro você precisa iniciar o servidor de desenvolvimento. Para fazer isso, execute o seguinte comando no diretório raiz do seu projeto React Native:

bash
npm start
bash
yarn start

2. Execute o aplicativo

Agora crie e execute seu aplicativo Android normalmente.

Assim que você atingir sua atividade com React dentro do aplicativo, ele deverá carregar o código JavaScript do servidor de desenvolvimento e exibir:

image

Criando uma versão de lançamento no Android Studio

Você também pode usar o Android Studio para criar suas versões de lançamento! É tão rápido quanto criar versões de lançamento do seu aplicativo Android nativo já existente.

Se você usar o plugin React Native Gradle conforme descrito acima, tudo deverá funcionar ao executar o aplicativo do Android Studio.

Se você não estiver usando o plugin React Native Gradle, há uma etapa adicional que você terá que executar antes de cada versão. Você precisa executar o seguinte para criar um pacote React Native, que será incluído em seu aplicativo Android nativo:

bash
$ npx react-native bundle --platform android --dev false --entry-file index.js --bundle-output android/com/your-company-name/app-package-name/src/main/assets/index.android.bundle --assets-dest android/com/your-company-name/app-package-name/src/main/res/

Nota

Não se esqueça de substituir os caminhos pelos corretos e criar a pasta de ativos caso ela não exista.

Agora, crie uma versão de lançamento do seu aplicativo nativo no Android Studio, como de costume, e você estará pronto para prosseguir!

E agora?

Neste ponto, você pode continuar desenvolvendo seu aplicativo normalmente. Consulte nossos documentos de depuração e implantação para saber mais sobre como trabalhar com React Native.

',95),l=[p];function o(h,d,r,k,c,E){return i(),a("div",null,l)}const y=s(t,[["render",o]]);export{u as __pageData,y as default}; diff --git a/vitepress/docs/.vitepress/dist/assets/docs_integration-with-existing-apps_android-kotlin.md.CmoaTw48.lean.js b/vitepress/docs/.vitepress/dist/assets/docs_integration-with-existing-apps_android-kotlin.md.CmoaTw48.lean.js new file mode 100644 index 0000000..2b72e2a --- /dev/null +++ b/vitepress/docs/.vitepress/dist/assets/docs_integration-with-existing-apps_android-kotlin.md.CmoaTw48.lean.js @@ -0,0 +1 @@ +import{_ as s,c as a,o as i,a4 as e}from"./chunks/framework.nQaBHiNx.js";const n="/assets/289311225-21b28d91-4031-4e02-bbcd-0232c1c24a16.BzZG4-5V.png",u=JSON.parse('{"title":"Android (Kotlin)","description":"","frontmatter":{},"headers":[],"relativePath":"docs/integration-with-existing-apps/android-kotlin.md","filePath":"docs/integration-with-existing-apps/android-kotlin.md"}'),t={name:"docs/integration-with-existing-apps/android-kotlin.md"},p=e("",95),l=[p];function o(h,d,r,k,c,E){return i(),a("div",null,l)}const y=s(t,[["render",o]]);export{u as __pageData,y as default}; diff --git a/vitepress/docs/.vitepress/dist/assets/docs_integration-with-existing-apps_ios-objective-c.md.DN1AFpQp.js b/vitepress/docs/.vitepress/dist/assets/docs_integration-with-existing-apps_ios-objective-c.md.DN1AFpQp.js new file mode 100644 index 0000000..4a9f900 --- /dev/null +++ b/vitepress/docs/.vitepress/dist/assets/docs_integration-with-existing-apps_ios-objective-c.md.DN1AFpQp.js @@ -0,0 +1,125 @@ +import{_ as a,c as s,o as i,a4 as e}from"./chunks/framework.nQaBHiNx.js";const n="/assets/290205035-be5d7e97-b86c-4a0f-94d3-673886cc49a3.wE_Ms7Jv.png",t="/assets/289078069-79daecf4-41df-45e4-bdfd-34120ecb2d9b.DqQEPRQ3.png",o="/assets/290218954-e41f72f9-dabc-4735-a4df-ab3260c30f3f.09D_xvWf.png",p="/assets/290220401-8f9b33a4-3f00-4caf-9be3-2d06a10584a5.BMzNTl1l.png",l="/assets/290225173-8c00a858-3507-4de4-84e0-536c094532f8.GQqlKtKq.png",c="/assets/290225251-23ad63ff-3ee2-4767-a7c0-438cc2c20ece.VCEr0iJR.png",F=JSON.parse('{"title":"iOS (Objective-C)","description":"","frontmatter":{},"headers":[],"relativePath":"docs/integration-with-existing-apps/ios-objective-c.md","filePath":"docs/integration-with-existing-apps/ios-objective-c.md"}'),r={name:"docs/integration-with-existing-apps/ios-objective-c.md"},d=e(`

iOS (Objective-C)

Conceitos chave

Os segredos para integrar componentes React Native em seu aplicativo iOS são:

  1. Configure as dependências e a estrutura de diretórios do React Native.
  2. Entenda quais componentes do React Native você usará em seu aplicativo.
  3. Adicione esses componentes como dependências usando CocoaPods. 4.Desenvolva seus componentes React Native em JavaScript.
  4. Adicione um RTRRootView ao seu aplicativo iOS. Esta visualização servirá como contêiner para seu componente React Native.
  5. Inicie o servidor React Native e execute seu aplicativo nativo.
  6. Verifique se o aspecto React Native do seu aplicativo funciona conforme o esperado.

Pré-requisitos

Siga o início rápido do React Native CLI no guia de configuração do ambiente para configurar seu ambiente de desenvolvimento para construir aplicativos React Native para iOS.

1. Configure a estrutura de diretórios

Para garantir uma experiência tranquila, crie uma nova pasta para seu projeto React Native integrado e copie seu projeto iOS existente para uma subpasta /ios.

2. Instale dependências JavaScript

Vá para o diretório raiz do seu projeto e crie um novo arquivo package.json com o seguinte conteúdo:

json
{
+  "name": "MyReactNativeApp",
+  "version": "0.0.1",
+  "private": true,
+  "scripts": {
+    "start": "yarn react-native start"
+  }
+}

Em seguida, certifique-se de ter instalado o gerenciador de pacotes Yarn.

Instale os pacotes react e react-native. Abra um terminal ou prompt de comando, navegue até o diretório com seu arquivo package.json e execute:

bash
npm install react-native
bash
yarn add react-native

Isso imprimirá uma mensagem semelhante à seguinte (role para cima na saída do fio para vê-la):

warning "react-native@0.52.2" has unmet peer dependency "react@16.2.0".

Tudo bem, significa que também precisamos instalar o React:

bash
npm install react@version_printed_above
bash
yarn add react@version_printed_above

O processo de instalação criou uma nova pasta /node_modules. Esta pasta armazena todas as dependências JavaScript necessárias para construir seu projeto.

Adicione node_modules/ ao seu arquivo .gitignore.

3. Instale CocoaPods

CocoaPods é uma ferramenta de gerenciamento de pacotes para desenvolvimento iOS e macOS. Nós o usamos para adicionar o código da estrutura React Native localmente ao seu projeto atual.

Recomendamos instalar CocoaPods usando Homebrew.

brew install cocoapods

Nota

É tecnicamente possível não usar CocoaPods, mas isso exigiria adições manuais de biblioteca e vinculador que complicariam excessivamente esse processo.

Adicionando React Native ao seu aplicativo

Suponha que o aplicativo para integração seja um jogo de 2048. Esta é a aparência do menu principal do aplicativo nativo sem o React Native.

image

Ferramentas de linha de comando para Xcode

Instale as ferramentas de linha de comando. Escolha Settings... (ou Preferences...) no menu do Xcode. Vá para o painel Locais e instale as ferramentas selecionando a versão mais recente no menu suspenso Ferramentas de linha de comando.

image

Configurando dependências do CocoaPods

Antes de integrar o React Native ao seu aplicativo, você desejará decidir quais partes da estrutura React Native você gostaria de integrar. Usaremos CocoaPods para especificar de quais dessas "subespecificações" seu aplicativo dependerá.

A lista de subespecificações suportadas está disponível em /node_modules/react-native/React.podspec. Eles geralmente são nomeados por funcionalidade. Por exemplo, geralmente você sempre desejará a subespecificação Core. Isso lhe dará o AppRegistry, StyleSheet, View e outras bibliotecas principais do React Native. Se você deseja adicionar a biblioteca React Native Text (por exemplo, para elementos <Text> ), você precisará da subespecificação RCTText. Se você quiser a biblioteca de imagens (por exemplo, para elementos <Image> ), precisará da subespecificação RCTImage.

Você pode especificar de quais subespecificações seu aplicativo dependerá em um arquivo Podfile. A maneira mais fácil de criar um Podfile é executando o comando init do CocoaPods na subpasta /ios do seu projeto:

bash
pod init

O Podfile conterá uma configuração padrão que você ajustará para fins de integração.

Nota

A versão do 'Podfilemuda dependendo da sua versão doreact-native. Consulte [https://react-native-community.github.io/upgrade-helper/](https://react-native-community.github.io/upgrade-helper/) para a versão específica do Podfile\` que você deve usar.

No final das contas, seu Podfile deve ser semelhante a isto:

# The target name is most likely the name of your project.
+target 'NumberTileGame' do
+
+  # Your 'node_modules' directory is probably in the root of your project,
+  # but if not, adjust the \`:path\` accordingly
+  pod 'FBLazyVector', :path => "../node_modules/react-native/Libraries/FBLazyVector"
+  pod 'FBReactNativeSpec', :path => "../node_modules/react-native/Libraries/FBReactNativeSpec"
+  pod 'RCTRequired', :path => "../node_modules/react-native/Libraries/RCTRequired"
+  pod 'RCTTypeSafety', :path => "../node_modules/react-native/Libraries/TypeSafety"
+  pod 'React', :path => '../node_modules/react-native/'
+  pod 'React-Core', :path => '../node_modules/react-native/'
+  pod 'React-CoreModules', :path => '../node_modules/react-native/React/CoreModules'
+  pod 'React-Core/DevSupport', :path => '../node_modules/react-native/'
+  pod 'React-RCTActionSheet', :path => '../node_modules/react-native/Libraries/ActionSheetIOS'
+  pod 'React-RCTAnimation', :path => '../node_modules/react-native/Libraries/NativeAnimation'
+  pod 'React-RCTBlob', :path => '../node_modules/react-native/Libraries/Blob'
+  pod 'React-RCTImage', :path => '../node_modules/react-native/Libraries/Image'
+  pod 'React-RCTLinking', :path => '../node_modules/react-native/Libraries/LinkingIOS'
+  pod 'React-RCTNetwork', :path => '../node_modules/react-native/Libraries/Network'
+  pod 'React-RCTSettings', :path => '../node_modules/react-native/Libraries/Settings'
+  pod 'React-RCTText', :path => '../node_modules/react-native/Libraries/Text'
+  pod 'React-RCTVibration', :path => '../node_modules/react-native/Libraries/Vibration'
+  pod 'React-Core/RCTWebSocket', :path => '../node_modules/react-native/'
+
+  pod 'React-cxxreact', :path => '../node_modules/react-native/ReactCommon/cxxreact'
+  pod 'React-jsi', :path => '../node_modules/react-native/ReactCommon/jsi'
+  pod 'React-jsiexecutor', :path => '../node_modules/react-native/ReactCommon/jsiexecutor'
+  pod 'React-jsinspector', :path => '../node_modules/react-native/ReactCommon/jsinspector'
+  pod 'ReactCommon/callinvoker', :path => "../node_modules/react-native/ReactCommon"
+  pod 'ReactCommon/turbomodule/core', :path => "../node_modules/react-native/ReactCommon"
+  pod 'Yoga', :path => '../node_modules/react-native/ReactCommon/yoga'
+
+  pod 'DoubleConversion', :podspec => '../node_modules/react-native/third-party-podspecs/DoubleConversion.podspec'
+  pod 'glog', :podspec => '../node_modules/react-native/third-party-podspecs/glog.podspec'
+  pod 'Folly', :podspec => '../node_modules/react-native/third-party-podspecs/Folly.podspec'
+
+end

Depois de criar seu Podfile, você estará pronto para instalar o pod React Native.

bash
pod install

Você deverá ver resultados como:

Analyzing dependencies
+Fetching podspec for \`React\` from \`../node_modules/react-native\`
+Downloading dependencies
+Installing React (0.62.0)
+Generating Pods project
+Integrating client project
+Sending stats
+Pod installation complete! There are 3 dependencies from the Podfile and 1 total pod installed.

Dica

Se isso falhar com erros mencionando o xcrun, certifique-se de que no Xcode em Settings... (or Preferences...) > Locations as Ferramentas de Linha de Comando estejam atribuídas.

Integração de código

Agora iremos modificar o aplicativo iOS nativo para integrar o React Native. Para nosso aplicativo de amostra 2048, adicionaremos uma tela "High Score" no React Native.

O componente React Native

O primeiro código que escreveremos é o código React Native real para a nova tela "High Score" que será integrada em nosso aplicativo.

1. Crie um arquivo index.js

Primeiro, crie um arquivo index.js vazio na raiz do seu projeto React Native.

index.js é o ponto de partida para aplicativos React Native e é sempre necessário. Pode ser um arquivo pequeno que requer outro arquivo que faça parte do seu componente ou aplicativo React Native, ou pode conter todo o código necessário para ele. No nosso caso, colocaremos tudo em index.js.

2. Adicione seu código React Native

No seu index.js, crie seu componente. Em nosso exemplo aqui, adicionaremos um componente <Text> dentro de um estilo <View>

jsx
import React from 'react';
+import {AppRegistry, StyleSheet, Text, View} from 'react-native';
+
+const RNHighScores = ({scores}) => {
+  const contents = scores.map(score => (
+    <Text key={score.name}>
+      {score.name}:{score.value}
+      {'\\n'}
+    </Text>
+  ));
+  return (
+    <View style={styles.container}>
+      <Text style={styles.highScoresTitle}>
+        2048 High Scores!
+      </Text>
+      <Text style={styles.scores}>{contents}</Text>
+    </View>
+  );
+};
+
+const styles = StyleSheet.create({
+  container: {
+    flex: 1,
+    justifyContent: 'center',
+    alignItems: 'center',
+    backgroundColor: '#FFFFFF',
+  },
+  highScoresTitle: {
+    fontSize: 20,
+    textAlign: 'center',
+    margin: 10,
+  },
+  scores: {
+    textAlign: 'center',
+    color: '#333333',
+    marginBottom: 5,
+  },
+});
+
+// Nome do módulo
+AppRegistry.registerComponent('RNHighScores', () => RNHighScores);

Nota

RNHighScores é o nome do seu módulo que será usado quando você adicionar uma visualização ao React Native de dentro do seu aplicativo iOS.

A mágica: RCTRootView

Agora que seu componente React Native foi criado por meio de index.js, você precisa adicionar esse componente a um ViewController novo ou existente. O caminho mais fácil é criar opcionalmente um caminho de evento para seu componente e, em seguida, adicionar esse componente a um ViewController existente.

Amarraremos nosso componente React Native a uma nova visualização nativa no ViewController que na verdade o conterá uma chamada a RCTRootView .

1. Crie um caminho de evento

Você pode adicionar um novo link no menu principal do jogo para ir para a página “High Score” do React Native.

image

2. Manipulador de eventos

Agora adicionaremos um manipulador de eventos no link do menu. Um método será adicionado ao ViewController principal da sua aplicação. É aqui que o RTRRootView entra em ação.

Ao construir um aplicativo React Native, você usa o empacotador Metro para criar um index.bundle que será servido pelo servidor React Native. Dentro de index.bundle estará nosso módulo RNHighScore. Portanto, precisamos apontar nosso RTRRootView para o local do recurso index.bundle (via NSURL) e vinculá-lo ao módulo.

Iremos, para fins de depuração, registrar que o manipulador de eventos foi invocado. Em seguida, criaremos uma string com a localização do nosso código React Native que existe dentro do index.bundle. Por fim, criaremos o RTRRootView principal. Observe como fornecemos RNHighScores como moduleName que criamos acima ao escrever o código para nosso componente React Native.

Primeiro import o cabeçalho RTRRootView.

objective-c
#import <React/RCTRootView.h>

Nota

As initialProperties (propriedades iniciais) estão aqui para fins ilustrativos, por isso temos alguns dados para nossa tela de pontuação mais alta. Em nosso componente React Native, usaremos this.props para obter acesso a esses dados.

objective-c
- (IBAction)highScoreButtonPressed:(id)sender {
+    NSLog(@"High Score Button Pressed");
+    NSURL *jsCodeLocation = [NSURL URLWithString:@"http://localhost:8081/index.bundle?platform=ios"];
+
+    RCTRootView *rootView =
+      [[RCTRootView alloc] initWithBundleURL: jsCodeLocation
+                                  moduleName: @"RNHighScores"
+                           initialProperties:
+                             @{
+                               @"scores" : @[
+                                 @{
+                                   @"name" : @"Alex",
+                                   @"value": @"42"
+                                  },
+                                 @{
+                                   @"name" : @"Joel",
+                                   @"value": @"10"
+                                 }
+                               ]
+                             }
+                               launchOptions: nil];
+    UIViewController *vc = [[UIViewController alloc] init];
+    vc.view = rootView;
+    [self presentViewController:vc animated:YES completion:nil];
+}

Nota

Observe que o RTRRootView initWithURL inicia uma nova VM JSC. Para economizar recursos e simplificar a comunicação entre visualizações RN em diferentes partes do seu aplicativo nativo, você pode ter várias visualizações desenvolvidas pelo React Native associadas a um único tempo de execução JS. Para fazer isso, em vez de usar [RCTRootView alloc] initWithURL, use RCTBridge initWithBundleURL para criar uma ponte e, em seguida, use RCTRootView initWithBridge.

Dica

Ao mover seu aplicativo para produção, o NSURL pode apontar para um arquivo pré-empacotado no disco por meio de algo como [[NSBundle mainBundle] URLForResource:@"main" withExtension:@"jsbundle"];. Você pode usar o script react-native-xcode.sh em node_modules/react-native/scripts/ para gerar esse arquivo pré-empacotado.

3. Conecte

Conecte o novo link no menu principal ao método manipulador de eventos recém-adicionado.

image

Dica

Uma das maneiras mais fáceis de fazer isso é abrir a visualização no storyboard e clicar com o botão direito no novo link. Selecione algo como o evento Touch Up Inside, arraste-o para o storyboard e selecione o método criado na lista fornecida.

Teste sua integração

Agora você executou todas as etapas básicas para integrar o React Native ao seu aplicativo atual. Agora iniciaremos o empacotador Metro para construir o pacote index.bundle e o servidor rodando em localhost para servi-lo.

1. Adicionar exceção de segurança de transporte de aplicativos

A Apple bloqueou o carregamento implícito de recursos HTTP em texto não criptografado. Portanto, precisamos adicionar o seguinte arquivo Info.plist (ou equivalente) do nosso projeto.

<key>NSAppTransportSecurity</key>
+<dict>
+    <key>NSExceptionDomains</key>
+    <dict>
+        <key>localhost</key>
+        <dict>
+            <key>NSTemporaryExceptionAllowsInsecureHTTPLoads</key>
+            <true/>
+        </dict>
+    </dict>
+</dict>

Dica

O App Transport Security é bom para seus usuários. Certifique-se de reativá-lo antes de lançar seu aplicativo para produção.

2. Execute o empacotador

Para executar seu aplicativo, primeiro você precisa iniciar o servidor de desenvolvimento. Para fazer isso, execute o seguinte comando no diretório raiz do seu projeto React Native:

bash
npm start
bash
yarn start

3. Execute o aplicativo

Se você estiver usando o Xcode ou seu editor favorito, crie e execute seu aplicativo iOS nativo normalmente. Alternativamente, você pode executar o aplicativo na linha de comando usando:

bash
npm run ios
bash
yarn ios

Em nosso aplicativo de exemplo, você deverá ver o link para "High Scores" e, ao clicar nele, verá a renderização do seu componente React Native.

Aqui está a tela inicial do aplicativo nativo:

image

Aqui está a tela de pontuação mais alta do React Native:

image

Nota

Se você estiver tendo problemas de resolução de módulo ao executar seu aplicativo, consulte este problema do GitHub para obter informações e possível resolução. Este comentário parecia ser a última resolução possível.

E agora?

Neste ponto, você pode continuar desenvolvendo seu aplicativo normalmente. Consulte nossos documentos de depuração e implantação para saber mais sobre como trabalhar com React Native.

',96),h=[d];function k(u,g,E,m,v,y){return i(),s("div",null,h)}const C=a(r,[["render",k]]);export{F as __pageData,C as default}; diff --git a/vitepress/docs/.vitepress/dist/assets/docs_integration-with-existing-apps_ios-objective-c.md.DN1AFpQp.lean.js b/vitepress/docs/.vitepress/dist/assets/docs_integration-with-existing-apps_ios-objective-c.md.DN1AFpQp.lean.js new file mode 100644 index 0000000..428bb86 --- /dev/null +++ b/vitepress/docs/.vitepress/dist/assets/docs_integration-with-existing-apps_ios-objective-c.md.DN1AFpQp.lean.js @@ -0,0 +1 @@ +import{_ as a,c as s,o as i,a4 as e}from"./chunks/framework.nQaBHiNx.js";const n="/assets/290205035-be5d7e97-b86c-4a0f-94d3-673886cc49a3.wE_Ms7Jv.png",t="/assets/289078069-79daecf4-41df-45e4-bdfd-34120ecb2d9b.DqQEPRQ3.png",o="/assets/290218954-e41f72f9-dabc-4735-a4df-ab3260c30f3f.09D_xvWf.png",p="/assets/290220401-8f9b33a4-3f00-4caf-9be3-2d06a10584a5.BMzNTl1l.png",l="/assets/290225173-8c00a858-3507-4de4-84e0-536c094532f8.GQqlKtKq.png",c="/assets/290225251-23ad63ff-3ee2-4767-a7c0-438cc2c20ece.VCEr0iJR.png",F=JSON.parse('{"title":"iOS (Objective-C)","description":"","frontmatter":{},"headers":[],"relativePath":"docs/integration-with-existing-apps/ios-objective-c.md","filePath":"docs/integration-with-existing-apps/ios-objective-c.md"}'),r={name:"docs/integration-with-existing-apps/ios-objective-c.md"},d=e("",96),h=[d];function k(u,g,E,m,v,y){return i(),s("div",null,h)}const C=a(r,[["render",k]]);export{F as __pageData,C as default}; diff --git a/vitepress/docs/.vitepress/dist/assets/docs_integration-with-existing-apps_ios-swift.md.CJQfODMc.js b/vitepress/docs/.vitepress/dist/assets/docs_integration-with-existing-apps_ios-swift.md.CJQfODMc.js new file mode 100644 index 0000000..2ff73b3 --- /dev/null +++ b/vitepress/docs/.vitepress/dist/assets/docs_integration-with-existing-apps_ios-swift.md.CJQfODMc.js @@ -0,0 +1,98 @@ +import{_ as s,c as a,o as i,a4 as e}from"./chunks/framework.nQaBHiNx.js";const n="/assets/290205035-be5d7e97-b86c-4a0f-94d3-673886cc49a3.wE_Ms7Jv.png",t="/assets/289078069-79daecf4-41df-45e4-bdfd-34120ecb2d9b.DqQEPRQ3.png",o="/assets/290218954-e41f72f9-dabc-4735-a4df-ab3260c30f3f.09D_xvWf.png",p="/assets/290225173-8c00a858-3507-4de4-84e0-536c094532f8.GQqlKtKq.png",l="/assets/290225251-23ad63ff-3ee2-4767-a7c0-438cc2c20ece.VCEr0iJR.png",F=JSON.parse('{"title":"iOS (Swift)","description":"","frontmatter":{},"headers":[],"relativePath":"docs/integration-with-existing-apps/ios-swift.md","filePath":"docs/integration-with-existing-apps/ios-swift.md"}'),r={name:"docs/integration-with-existing-apps/ios-swift.md"},h=e(`

iOS (Swift)

Conceitos chave

Os segredos para integrar componentes React Native em seu aplicativo iOS são:

  1. Configure as dependências e a estrutura de diretórios do React Native.
  2. Entenda quais componentes do React Native você usará em seu aplicativo.
  3. Adicione esses componentes como dependências usando CocoaPods.
  4. Desenvolva seus componentes React Native em JavaScript.
  5. Adicione um RTRRootView ao seu aplicativo iOS. Esta visualização servirá como contêiner para seu componente React Native.
  6. Inicie o servidor React Native e execute seu aplicativo nativo.
  7. Verifique se o aspecto React Native do seu aplicativo funciona conforme o esperado.

Pré-requisitos

Siga o início rápido do React Native CLI no guia de configuração do ambiente para configurar seu ambiente de desenvolvimento para construir aplicativos React Native para iOS.

1. Configure a estrutura de diretórios

Para garantir uma experiência tranquila, crie uma nova pasta para seu projeto React Native integrado e copie seu projeto iOS existente para uma subpasta /ios.

2. Instale dependências JavaScript

Vá para o diretório raiz do seu projeto e crie um novo arquivo package.json com o seguinte conteúdo:

json
{
+  "name": "MyReactNativeApp",
+  "version": "0.0.1",
+  "private": true,
+  "scripts": {
+    "start": "yarn react-native start"
+  }
+}

Em seguida, instale os pacotes react e react-native. Abra um terminal ou prompt de comando, navegue até o diretório com seu arquivo package.json e execute:

bash
npm install react-native
bash
yarn add react-native

Isso imprimirá uma mensagem semelhante à seguinte (role para cima na saída do yarn para vê-la):

warning "react-native@0.52.2" has unmet peer dependency "react@16.2.0".

Tudo bem, significa que também precisamos instalar o React:

bash
npm install react@version_printed_above
bash
yarn add react@version_printed_above

Yarn criou uma nova pasta /node_modules. Esta pasta armazena todas as dependências JavaScript necessárias para construir seu projeto.

Adicione node_modules/ ao seu arquivo .gitignore.

3. Instale CocoaPods

CocoaPods é uma ferramenta de gerenciamento de pacotes para desenvolvimento iOS e macOS. Nós o usamos para adicionar o código da estrutura React Native localmente ao seu projeto atual.

Recomendamos instalar CocoaPods usando Homebrew.

bash
brew install cocoapods

Dica

É tecnicamente possível não usar CocoaPods, mas isso exigiria adições manuais de biblioteca e vinculador que complicariam excessivamente esse processo.

Adicionando React Native ao seu aplicativo

Suponha que o aplicativo para integração seja um jogo de 2048. Esta é a aparência do menu principal do aplicativo nativo sem o React Native.

image

Ferramentas de linha de comando para Xcode

Instale as ferramentas de linha de comando. Escolha Settings... (or Preferences...) no menu Xcode. Vá para o painel Locais e instale as ferramentas selecionando a versão mais recente no menu suspenso Ferramentas de linha de comando.

image

Configurando dependências do CocoaPods

Antes de integrar o React Native ao seu aplicativo, você desejará decidir quais partes da estrutura React Native você gostaria de integrar. Usaremos CocoaPods para especificar de quais dessas "subespecificações" seu aplicativo dependerá.

A lista de subespecificações suportadas está disponível em /node_modules/react-native/React.podspec. Eles geralmente são nomeados por funcionalidade. Por exemplo, geralmente você sempre desejará a subespecificação Core. Isso lhe dará o AppRegistry, StyleSheet, View e outras bibliotecas principais do React Native. Se você deseja adicionar a biblioteca React Native Text (por exemplo, para elementos <Text>), você precisará da subespecificação RCTText. Se você quiser a biblioteca de imagens (por exemplo, para elementos <Image>), precisará da subespecificação RCTImage.

Você pode especificar de quais subespecificações seu aplicativo dependerá em um arquivo Podfile. A maneira mais fácil de criar um Podfile é executando o comando init CocoaPods na subpasta /ios do seu projeto:

bash
pod init

O Podfile conterá uma configuração padrão que você ajustará para fins de integração.

Nota

A versão do Podfile muda dependendo da sua versão do react-native. Consulte https://react-native-community.github.io/upgrade-helper/ para a versão específica do Podfile que você deve usar.

No final das contas, seu Podfile deve ser semelhante a este: Template Podfile

Depois de criar seu Podfile, você estará pronto para instalar o pod React Native.

bash
pod install

Você deverá ver resultados como:

Analyzing dependencies
+Fetching podspec for \`React\` from \`../node_modules/react-native\`
+Downloading dependencies
+Installing React (0.62.0)
+Generating Pods project
+Integrating client project
+Sending stats
+Pod installation complete! There are 3 dependencies from the Podfile and 1 total pod installed.

Nota

Se isso falhar com erros mencionando o xcrun, certifique-se de que no Xcode em Settings... (or Preferences...) > Locations as Ferramentas de Linha de Comando estejam atribuídas.

Dica

Se você receber um aviso como "The swift-2048 [Debug] target overrides the FRAMEWORK_SEARCH_PATHS build setting defined in Pods/Target Support Files/Pods-swift-2048/Pods-swift-2048.debug.xcconfig. This can lead to problems with the CocoaPods installation", certifique-se de que os caminhos de pesquisa da estrutura nas configurações de compilação para depuração e versão contenham apenas $(inherited).

Integração de código

Agora iremos modificar o aplicativo iOS nativo para integrar o React Native. Para nosso aplicativo de amostra 2048, adicionaremos uma tela "High Score" no React Native.

O componente React Native

O primeiro código que escreveremos é o código React Native real para a nova tela "High Score" que será integrada em nosso aplicativo.

1. Crie um arquivo index.js

Primeiro, crie um arquivo index.js vazio na raiz do seu projeto React Native.

index.js é o ponto de partida para aplicativos React Native e é sempre necessário. Pode ser um arquivo pequeno que requer outro arquivo que faça parte do seu componente ou aplicativo React Native, ou pode conter todo o código necessário para ele. No nosso caso, colocaremos tudo em index.js.

2. Adicione seu código React Native

No seu index.js, crie seu componente. Em nosso exemplo aqui, adicionaremos um componente <Text> dentro de um estilo <View>

jsx
import React from 'react';
+import {AppRegistry, StyleSheet, Text, View} from 'react-native';
+
+const RNHighScores = ({scores}) => {
+  const contents = scores.map(score => (
+    <Text key={score.name}>
+      {score.name}:{score.value}
+      {'\\n'}
+    </Text>
+  ));
+  return (
+    <View style={styles.container}>
+      <Text style={styles.highScoresTitle}>
+        2048 High Scores!
+      </Text>
+      <Text style={styles.scores}>{contents}</Text>
+    </View>
+  );
+};
+
+const styles = StyleSheet.create({
+  container: {
+    flex: 1,
+    justifyContent: 'center',
+    alignItems: 'center',
+    backgroundColor: '#FFFFFF',
+  },
+  highScoresTitle: {
+    fontSize: 20,
+    textAlign: 'center',
+    margin: 10,
+  },
+  scores: {
+    textAlign: 'center',
+    color: '#333333',
+    marginBottom: 5,
+  },
+});
+
+// Nome do módulo
+AppRegistry.registerComponent('RNHighScores', () => RNHighScores);

Nota

RNHighScores é o nome do seu módulo que será usado quando você adicionar uma visualização ao React Native de dentro do seu aplicativo iOS.

A mágica: RCTRootView

Agora que seu componente React Native foi criado por meio de index.js, você precisa adicionar esse componente a um ViewController novo ou existente. O caminho mais fácil é criar opcionalmente um caminho de evento para seu componente e, em seguida, adicionar esse componente a um ViewController existente.

Amarraremos nosso componente React Native a uma nova visualização nativa no ViewController que na verdade o conterá, chamada RCTRootView.

1. Crie um caminho de evento

Você pode adicionar um novo link no menu principal do jogo para ir para a página "High Score" do React Native.

image

2. Manipulador de eventos

Agora adicionaremos um manipulador de eventos no link do menu. Um método será adicionado ao ViewController principal da sua aplicação. É aqui que o RTRRootView entra em ação.

Ao construir um aplicativo React Native, você usa o empacotador Metro para criar um index.bundle que será servido pelo servidor React Native. Dentro de index.bundle estará nosso módulo RNHighScore. Portanto, precisamos apontar nosso RTRRootView para o local do recurso index.bundle (via NSURL) e vinculá-lo ao módulo.

Iremos, para fins de depuração, registrar que o manipulador de eventos foi invocado. Em seguida, criaremos uma string com a localização do nosso código React Native que existe dentro do index.bundle. Por fim, criaremos o RTRRootView principal. Observe como fornecemos RNHighScores como moduleName que criamos acima ao escrever o código para nosso componente React Native.

Primeiro import a biblioteca React.

js
import React

Informação

As initialProperties (propriedades iniciais) estão aqui para fins ilustrativos, por isso temos alguns dados para nossa tela de pontuação mais alta. Em nosso componente React Native, usaremos this.props para obter acesso a esses dados.

swift
@IBAction func highScoreButtonTapped(sender : UIButton) {
+  NSLog("Hello")
+  let jsCodeLocation = URL(string: "http://localhost:8081/index.bundle?platform=ios")
+  let mockData:NSDictionary = ["scores":
+      [
+          ["name":"Alex", "value":"42"],
+          ["name":"Joel", "value":"10"]
+      ]
+  ]
+
+  let rootView = RCTRootView(
+      bundleURL: jsCodeLocation,
+      moduleName: "RNHighScores",
+      initialProperties: mockData as [NSObject : AnyObject],
+      launchOptions: nil
+  )
+  let vc = UIViewController()
+  vc.view = rootView
+  self.present(vc, animated: true, completion: nil)
+}

Nota

Observe que o RTRRootView bundleURL inicia uma nova VM JSC. Para economizar recursos e simplificar a comunicação entre visualizações RN em diferentes partes do seu aplicativo nativo, você pode ter várias visualizações desenvolvidas pelo React Native associadas a um único tempo de execução JS. Para fazer isso, em vez de usar RCTRootView bundleURL, use RCTBridge initWithBundleURL para criar uma ponte e, em seguida, use RCTRootView initWithBridge.

Ao mover seu aplicativo para produção, o NSURL pode apontar para um arquivo pré-empacotado no disco por meio de algo como let mainBundle = NSBundle(URLForResource: "main" withExtension:"jsbundle"). Você pode usar o script react-native-xcode.sh em node_modules/react-native/scripts/ para gerar esse arquivo pré-empacotado.

3. Conecte

Conecte o novo link no menu principal ao método manipulador de eventos recém-adicionado.

image

Dica

Uma das maneiras mais fáceis de fazer isso é abrir a visualização no storyboard e clicar com o botão direito no novo link. Selecione algo como o evento Touch Up Inside, arraste-o para o storyboard e selecione o método criado na lista fornecida.

4. Referência da janela

Adicione uma referência de janela ao seu arquivo AppDelegate.swift. Por fim, seu AppDelegate deve ser algo semelhante a isto:

swift
import UIKit
+
+@main
+class AppDelegate: UIResponder, UIApplicationDelegate {
+
+    // Adicionar referência de janela
+    var window: UIWindow?
+
+    func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
+        // Ponto de substituição para personalização após o lançamento do aplicativo.
+        return true
+    }
+
+    ....
+}

Teste sua integração

Agora você executou todas as etapas básicas para integrar o React Native ao seu aplicativo atual. Agora iniciaremos o empacotador Metro para construir o pacote index.bundle e o servidor rodando em localhost para servi-lo.

1. Adicionar exceção de segurança de transporte de aplicativos

A Apple bloqueou o carregamento implícito de recursos HTTP em texto não criptografado. Portanto, precisamos adicionar o seguinte arquivo Info.plist (ou equivalente) do nosso projeto.

<key>NSAppTransportSecurity</key>
+<dict>
+    <key>NSExceptionDomains</key>
+    <dict>
+        <key>localhost</key>
+        <dict>
+            <key>NSTemporaryExceptionAllowsInsecureHTTPLoads</key>
+            <true/>
+        </dict>
+    </dict>
+</dict>

Dica

O App Transport Security é bom para seus usuários. Certifique-se de reativá-lo antes de lançar seu aplicativo para produção.

2. Execute o empacotador

Para executar seu aplicativo, primeiro você precisa iniciar o servidor de desenvolvimento. Para fazer isso, execute o seguinte comando no diretório raiz do seu projeto React Native:

bash
npm start
bash
yarn start

3. Execute o aplicativo

Se você estiver usando o Xcode ou seu editor favorito, crie e execute seu aplicativo iOS nativo normalmente. Alternativamente, você pode executar o aplicativo a partir da linha de comando usando o seguinte comando do diretório raiz do seu projeto React Native:

bash
npm run ios
bash
yarn ios

Em nosso aplicativo de exemplo, você deverá ver o link para "High Scores" e, ao clicar nele, verá a renderização do seu componente React Native.

Aqui está a tela inicial do aplicativo nativo:

image

Aqui está a tela de pontuação mais alta do React Native:

image

Se você estiver tendo problemas de resolução de módulo ao executar seu aplicativo, consulte este problema do GitHub para obter informações e possível resolução. Este comentário parecia ser a última resolução possível.

E agora?

Neste ponto, você pode continuar desenvolvendo seu aplicativo normalmente. Consulte nossos documentos de depuração e implantação para saber mais sobre como trabalhar com React Native.

',98),d=[h];function c(k,g,u,E,m,v){return i(),a("div",null,d)}const b=s(r,[["render",c]]);export{F as __pageData,b as default}; diff --git a/vitepress/docs/.vitepress/dist/assets/docs_integration-with-existing-apps_ios-swift.md.CJQfODMc.lean.js b/vitepress/docs/.vitepress/dist/assets/docs_integration-with-existing-apps_ios-swift.md.CJQfODMc.lean.js new file mode 100644 index 0000000..3204323 --- /dev/null +++ b/vitepress/docs/.vitepress/dist/assets/docs_integration-with-existing-apps_ios-swift.md.CJQfODMc.lean.js @@ -0,0 +1 @@ +import{_ as s,c as a,o as i,a4 as e}from"./chunks/framework.nQaBHiNx.js";const n="/assets/290205035-be5d7e97-b86c-4a0f-94d3-673886cc49a3.wE_Ms7Jv.png",t="/assets/289078069-79daecf4-41df-45e4-bdfd-34120ecb2d9b.DqQEPRQ3.png",o="/assets/290218954-e41f72f9-dabc-4735-a4df-ab3260c30f3f.09D_xvWf.png",p="/assets/290225173-8c00a858-3507-4de4-84e0-536c094532f8.GQqlKtKq.png",l="/assets/290225251-23ad63ff-3ee2-4767-a7c0-438cc2c20ece.VCEr0iJR.png",F=JSON.parse('{"title":"iOS (Swift)","description":"","frontmatter":{},"headers":[],"relativePath":"docs/integration-with-existing-apps/ios-swift.md","filePath":"docs/integration-with-existing-apps/ios-swift.md"}'),r={name:"docs/integration-with-existing-apps/ios-swift.md"},h=e("",98),d=[h];function c(k,g,u,E,m,v){return i(),a("div",null,d)}const b=s(r,[["render",c]]);export{F as __pageData,b as default}; diff --git a/vitepress/docs/.vitepress/dist/assets/docs_intro-react-native-components.md.BwonAn8f.js b/vitepress/docs/.vitepress/dist/assets/docs_intro-react-native-components.md.BwonAn8f.js new file mode 100644 index 0000000..7159d14 --- /dev/null +++ b/vitepress/docs/.vitepress/dist/assets/docs_intro-react-native-components.md.BwonAn8f.js @@ -0,0 +1,29 @@ +import{_ as s,c as a,o as i,a4 as e}from"./chunks/framework.nQaBHiNx.js";const t="/assets/diagram_ios-android-views.ClKysHl7.svg",n="/assets/diagram_react-native-components.C8UF7CVQ.svg",u=JSON.parse('{"title":"Componentes principais e componentes nativos","description":"","frontmatter":{},"headers":[],"relativePath":"docs/intro-react-native-components.md","filePath":"docs/intro-react-native-components.md"}'),o={name:"docs/intro-react-native-components.md"},p=e('

Componentes principais e componentes nativos

React Native é uma estrutura de código aberto para construir aplicativos Android e iOS usando React e os recursos nativos da plataforma de aplicativos. Com o React Native, você usa JavaScript para acessar as APIs da sua plataforma, bem como para descrever a aparência e o comportamento da sua UI usando componentes do React: pacotes de código reutilizável e aninhado. Você pode aprender mais sobre React na próxima seção. Mas primeiro, vamos abordar como os componentes funcionam no React Native.

Visualizações e desenvolvimento móvel

No desenvolvimento Android e iOS, uma visualização é o bloco de construção básico da UI: um pequeno elemento retangular na tela que pode ser usado para exibir texto, imagens ou responder à entrada do usuário. Mesmo os menores elementos visuais de um aplicativo, como uma linha de texto ou um botão, são tipos de visualizações. Alguns tipos de visualizações podem conter outras visualizações. São visualizações até o fim!

Apenas uma amostra das muitas visualizações usadas em aplicativos Android e iOS.

Componentes nativos

No desenvolvimento Android, você escreve visualizações em Kotlin ou Java; no desenvolvimento iOS, você usa Swift ou Objective-C. Com React Native, você pode invocar essas visualizações com JavaScript usando componentes React. Em tempo de execução, o React Native cria as visualizações Android e iOS correspondentes para esses componentes. Como os componentes React Native são apoiados pelas mesmas visualizações do Android e iOS, os aplicativos React Native têm aparência, comportamento e desempenho como qualquer outro aplicativo. Chamamos esses componentes apoiados pela plataforma de Componentes Nativos.

React Native vem com um conjunto de componentes nativos essenciais e prontos para uso que você pode usar para começar a construir seu aplicativo hoje mesmo. Estes são os componentes principais do React Native.

React Native também permite que você crie seus próprios componentes nativos para Android e iOS para atender às necessidades exclusivas do seu aplicativo. Também temos um ecossistema próspero desses componentes contribuídos pela comunidade. Confira o Native Directory para descobrir o que a comunidade está criando.

Core Componentes

React Native possui muitos componentes principais para tudo, desde controles até indicadores de atividade. Você pode encontrá-los todos documentados na seção API. Você trabalhará principalmente com os seguintes componentes principais:

REACT NATIVE UI COMPONENTANDROID VIEWIOS VIEWWEB ANÁLOGODESCRIÇÃO
<View><ViewGroup><UIView>Um <div> sem rolagemUm contêiner que suporta layout com flexbox, estilo, algum manuseio de toque e controles de acessibilidade
<Text><TextView><UITextView><p>Exibe, estiliza e aninha sequências de texto e até mesmo manipula eventos de toque
<Image><ImageView><UIImageView><img>Exibe diferentes tipos de imagens
<ScrollView><ScrollView><UIScrollView><div>Um contêiner de rolagem genérico que pode conter vários componentes e visualizações
<TextInput><EditText><UITextField><input type="text">Permite que o usuário insira texto

Na próxima seção, você começará a combinar esses componentes principais para aprender como o React funciona:

js
import React from 'react';
+import {View, Text, Image, ScrollView, TextInput} from 'react-native';
+
+const App = () => {
+  return (
+    <ScrollView>
+      <Text>Some text</Text>
+      <View>
+        <Text>Some more text</Text>
+        <Image
+          source={{
+            uri: 'https://reactnative.dev/docs/assets/p_cat2.png',
+          }}
+          style={{width: 200, height: 200}}
+        />
+      </View>
+      <TextInput
+        style={{
+          height: 40,
+          borderColor: 'gray',
+          borderWidth: 1,
+        }}
+        defaultValue="You can type in me"
+      />
+    </ScrollView>
+  );
+};
+
+export default App;

Como o React Native usa a mesma estrutura de API dos componentes do React, você precisará entender as APIs dos componentes do React para começar. A próxima seção faz uma rápida introdução ou atualização sobre o tópico. No entanto, se você já estiver familiarizado com o React, sinta-se à vontade para avançar.

',16),l=[p];function d(r,h,c,k,E,m){return i(),a("div",null,l)}const v=s(o,[["render",d]]);export{u as __pageData,v as default}; diff --git a/vitepress/docs/.vitepress/dist/assets/docs_intro-react-native-components.md.BwonAn8f.lean.js b/vitepress/docs/.vitepress/dist/assets/docs_intro-react-native-components.md.BwonAn8f.lean.js new file mode 100644 index 0000000..9a66383 --- /dev/null +++ b/vitepress/docs/.vitepress/dist/assets/docs_intro-react-native-components.md.BwonAn8f.lean.js @@ -0,0 +1 @@ +import{_ as s,c as a,o as i,a4 as e}from"./chunks/framework.nQaBHiNx.js";const t="/assets/diagram_ios-android-views.ClKysHl7.svg",n="/assets/diagram_react-native-components.C8UF7CVQ.svg",u=JSON.parse('{"title":"Componentes principais e componentes nativos","description":"","frontmatter":{},"headers":[],"relativePath":"docs/intro-react-native-components.md","filePath":"docs/intro-react-native-components.md"}'),o={name:"docs/intro-react-native-components.md"},p=e("",16),l=[p];function d(r,h,c,k,E,m){return i(),a("div",null,l)}const v=s(o,[["render",d]]);export{u as __pageData,v as default}; diff --git a/vitepress/docs/.vitepress/dist/assets/docs_intro-react.md.DeRGrixp.js b/vitepress/docs/.vitepress/dist/assets/docs_intro-react.md.DeRGrixp.js new file mode 100644 index 0000000..71d68fd --- /dev/null +++ b/vitepress/docs/.vitepress/dist/assets/docs_intro-react.md.DeRGrixp.js @@ -0,0 +1,238 @@ +import{_ as s,c as i,o as a,a4 as n}from"./chunks/framework.nQaBHiNx.js";const c=JSON.parse('{"title":"Fundamentos do React","description":"Para entender totalmente o React Native, você precisa de uma base sólida em React. Esta breve introdução ao React pode ajudá-lo a começar ou se atualizar.","frontmatter":{"id":"intro-react","title":"Fundamentos do React","description":"Para entender totalmente o React Native, você precisa de uma base sólida em React. Esta breve introdução ao React pode ajudá-lo a começar ou se atualizar."},"headers":[],"relativePath":"docs/intro-react.md","filePath":"docs/intro-react.md"}'),t={name:"docs/intro-react.md"},e=n(`

Fundamentos do React

React Native é executado em React, uma popular biblioteca de código aberto para construção de interfaces de usuário com JavaScript. Para aproveitar ao máximo o React Native, é útil entender o próprio React. Esta seção pode ajudá-lo a começar ou servir como um curso de atualização.

Vamos cobrir os principais conceitos por trás do React:

  • componentes
  • JSX
  • adereços
  • estado

Se você quiser se aprofundar, recomendamos que você verifique a documentação oficial do React.

Seu primeiro componente

O restante desta introdução ao React usa gatos em seus exemplos: criaturas amigáveis ​​e acessíveis que precisam de nomes e de um café para trabalhar. Aqui está seu primeiro componente Cat:

jsx
import React from 'react';
+import {Text} from 'react-native';
+
+const Cat = () => {
+  return <Text>Hello, I am your cat!</Text>;
+};
+
+export default Cat;

Veja como fazer isso: Para definir seu componente Cat, primeiro use o import do JavaScript para importar o componente principal Text do React e React Native:

tsx
import React from 'react';
+import {Text} from 'react-native';

Seu componente começa como uma função:

tsx
const Cat = () => {};

Você pode pensar nos componentes como projetos. Tudo o que um componente de função retorna é renderizado como um elemento React. Os elementos React permitem descrever o que você deseja ver na tela.

Aqui o componente Cat irá renderizar um elemento <Text>:

tsx
const Cat = () => {
+  return <Text>Hello, I am your cat!</Text>;
+};

Você pode exportar seu componente de função com export default do JavaScript para uso em todo o seu aplicativo da seguinte forma:

tsx
const Cat = () => {
+  return <Text>Hello, I am your cat!</Text>;
+};
+
+export default Cat;

Esta é uma das muitas maneiras de exportar seu componente. Este tipo de exportação funciona bem com o Snack Player. No entanto, dependendo da estrutura de arquivos do seu aplicativo, pode ser necessário usar uma convenção diferente. Este post de dicas sobre importações e exportações de JavaScript pode ajudar.

Agora dê uma olhada mais de perto na declaração return. <Text>Olá, sou seu gato!</Text> está usando um tipo de sintaxe JavaScript que torna a escrita de elementos conveniente: JSX.

JSX

React e React Native usam JSX, uma sintaxe que permite escrever elementos dentro do JavaScript como: <Text>Olá, sou seu gato!</Text>. A documentação do React tem um guia completo para JSX que você pode consultar para saber ainda mais. Como JSX é JavaScript, você pode usar variáveis ​​dentro dele. Aqui você está declarando um nome para o gato, name, e incorporando-o com chaves dentro de <Text>.

jsx
import React from 'react';
+import {Text} from 'react-native';
+
+const Cat = () => {
+  const name = 'Maru';
+  return <Text>Hello, I am {name}!</Text>;
+};
+
+export default Cat;

Qualquer expressão JavaScript funcionará entre chaves, incluindo chamadas de função como {getFullName("Rum", "Tum", "Tugger")}:

jsx
import React from 'react';
+import {Text} from 'react-native';
+
+const getFullName = (firstName, secondName, thirdName) => {
+  return firstName + ' ' + secondName + ' ' + thirdName;
+};
+
+const Cat = () => {
+  return <Text>Hello, I am {getFullName('Rum', 'Tum', 'Tugger')}!</Text>;
+};
+
+export default Cat;
tsx
import React from 'react';
+import {Text} from 'react-native';
+
+const getFullName = (
+  firstName: string,
+  secondName: string,
+  thirdName: string,
+) => {
+  return firstName + ' ' + secondName + ' ' + thirdName;
+};
+
+const Cat = () => {
+  return <Text>Hello, I am {getFullName('Rum', 'Tum', 'Tugger')}!</Text>;
+};
+
+export default Cat;

Você pode pensar nas chaves como a criação de um portal para a funcionalidade JS em seu JSX!

Como JSX está incluído na biblioteca React, ele não funcionará se você não tiver import React from 'react' no topo do seu arquivo!

Componentes personalizados

Você já conheceu Componentes principais do React Native. O React permite aninhar esses componentes uns dentro dos outros para criar novos componentes. Esses componentes aninhados e reutilizáveis ​​estão no centro do paradigma React.

Por exemplo, você pode aninhar Text e TextInput dentro de um View abaixo, e o React Native irá renderizá-los juntos:

jsx
import React from 'react';
+import {Text, TextInput, View} from 'react-native';
+
+const Cat = () => {
+  return (
+    <View>
+      <Text>Hello, I am...</Text>
+      <TextInput
+        style={{
+          height: 40,
+          borderColor: 'gray',
+          borderWidth: 1,
+        }}
+        defaultValue="Name me!"
+      />
+    </View>
+  );
+};
+
+export default Cat;

Notas do desenvolvedor

Web Se você está familiarizado com desenvolvimento web, <View> e <Text> podem lembrá-lo de HTML! Você pode pensar nelas como as tags <div> e <p> de desenvolvimento de aplicativos.

Android No Android, você normalmente coloca suas visualizações dentro de LinearLayout, FrameLayout, RelativeLayout, etc. para definir como os filhos da visualização serão organizados na tela. No React Native, View usa Flexbox para o layout de seus filhos. Você pode aprender mais em nosso guia de layout com Flexbox.

Você pode renderizar este componente várias vezes e em vários lugares sem repetir seu código usando <Cat>:

jsx
import React from 'react';
+import {Text, View} from 'react-native';
+
+const Cat = () => {
+  return (
+    <View>
+      <Text>I am also a cat!</Text>
+    </View>
+  );
+};
+
+const Cafe = () => {
+  return (
+    <View>
+      <Text>Welcome!</Text>
+      <Cat />
+      <Cat />
+      <Cat />
+    </View>
+  );
+};
+
+export default Cafe;

Qualquer componente que renderize outros componentes é um componente pai. Aqui, Cafe é o componente pai e cada Cat é um componente filho.

Você pode colocar quantos gatos quiser em seu café. Cada <Cat> renderiza um elemento único – que você pode personalizar com adereços.

Adereços

Props é a abreviação de "propriedades". Os adereços permitem personalizar os componentes do React. Por exemplo, aqui você passa para cada <Cat> um nome diferente para Cat renderizar:

jsx
import React from 'react';
+import {Text, View} from 'react-native';
+
+const Cat = props => {
+  return (
+    <View>
+      <Text>Hello, I am {props.name}!</Text>
+    </View>
+  );
+};
+
+const Cafe = () => {
+  return (
+    <View>
+      <Cat name="Maru" />
+      <Cat name="Jellylorum" />
+      <Cat name="Spot" />
+    </View>
+  );
+};
+
+export default Cafe;
tsx
import React from 'react';
+import {Text, View} from 'react-native';
+
+type CatProps = {
+  name: string;
+};
+
+const Cat = (props: CatProps) => {
+  return (
+    <View>
+      <Text>Hello, I am {props.name}!</Text>
+    </View>
+  );
+};
+
+const Cafe = () => {
+  return (
+    <View>
+      <Cat name="Maru" />
+      <Cat name="Jellylorum" />
+      <Cat name="Spot" />
+    </View>
+  );
+};
+
+export default Cafe;

A maioria dos componentes principais do React Native também pode ser personalizada com acessórios. Por exemplo, ao usar Image, você passa um prop chamado source para definir qual imagem ele mostra:

jsx
import React from 'react';
+import {Text, View, Image} from 'react-native';
+
+const CatApp = () => {
+  return (
+    <View>
+      <Image
+        source={{
+          uri: 'https://reactnative.dev/docs/assets/p_cat1.png',
+        }}
+        style={{width: 200, height: 200}}
+      />
+      <Text>Hello, I am your cat!</Text>
+    </View>
+  );
+};
+
+export default CatApp;

Image tem muitos adereços diferentes, incluindo style, que aceita um objeto JS de pares de propriedade-valor relacionados a design e layout.

Nota

Observe as chaves duplas {{ }} ao redor da largura e altura do style. Em JSX, os valores JavaScript são referenciados com {}. Isso é útil se você estiver passando algo diferente de uma string como adereços, como um array ou número: <Cat food={["fish", "kibble"]} age={2} />. No entanto, objetos JS são também denotados com chaves: {width: 200, height: 200}. Portanto, para passar um objeto JS em JSX, você deve envolver o objeto em outro par de chaves: {{ width: 200, height: 200 }}

Você pode construir muitas coisas com adereços e os componentes principais Text, Image e View! Mas para construir algo interativo, você precisará de estado.

Estado

Embora você possa pensar em props como argumentos usados ​​para configurar como os componentes são renderizados, state é como o armazenamento de dados pessoais de um componente. O estado é útil para lidar com dados que mudam ao longo do tempo ou provenientes da interação do usuário. O estado dá memória aos seus componentes!

Como regra geral, use props para configurar um componente quando ele for renderizado. Use o estado para acompanhar todos os dados do componente que você espera alterar ao longo do tempo.

O exemplo a seguir ocorre em um café para gatos, onde dois gatos famintos estão esperando para serem alimentados. A sua fome, que esperamos que mude com o tempo (ao contrário dos seus nomes), é armazenada como estado. Para alimentar os gatos, pressione seus botões – o que atualizará seu estado.

Você pode adicionar estado a um componente chamando o gancho useState do React. Um Hook é um tipo de função que permite “conectar-se” aos recursos do React. Por exemplo, useState é um gancho que permite adicionar estado aos componentes da função. Você pode aprender mais sobre outros tipos de Hooks na documentação do React.

jsx
import React, {useState} from 'react';
+import {Button, Text, View} from 'react-native';
+
+const Cat = props => {
+  const [isHungry, setIsHungry] = useState(true);
+
+  return (
+    <View>
+      <Text>
+        I am {props.name}, and I am {isHungry ? 'hungry' : 'full'}!
+      </Text>
+      <Button
+        onPress={() => {
+          setIsHungry(false);
+        }}
+        disabled={!isHungry}
+        title={isHungry ? 'Give me some food, please!' : 'Thank you!'}
+      />
+    </View>
+  );
+};
+
+const Cafe = () => {
+  return (
+    <>
+      <Cat name="Munkustrap" />
+      <Cat name="Spot" />
+    </>
+  );
+};
+
+export default Cafe;
tsx
import React, {useState} from 'react';
+import {Button, Text, View} from 'react-native';
+
+type CatProps = {
+  name: string;
+};
+
+const Cat = (props: CatProps) => {
+  const [isHungry, setIsHungry] = useState(true);
+
+  return (
+    <View>
+      <Text>
+        I am {props.name}, and I am {isHungry ? 'hungry' : 'full'}!
+      </Text>
+      <Button
+        onPress={() => {
+          setIsHungry(false);
+        }}
+        disabled={!isHungry}
+        title={isHungry ? 'Give me some food, please!' : 'Thank you!'}
+      />
+    </View>
+  );
+};
+
+const Cafe = () => {
+  return (
+    <>
+      <Cat name="Munkustrap" />
+      <Cat name="Spot" />
+    </>
+  );
+};
+
+export default Cafe;

Primeiro, você desejará importar useState do React assim:

tsx
import React, {useState} from 'react';

Então você declara o estado do componente chamando useState dentro de sua função. Neste exemplo, useState cria uma variável de estado isHungry:

tsx
const Cat = (props: CatProps) => {
+  const [isHungry, setIsHungry] = useState(true);
+  // ...
+};

Você pode usar useState para rastrear qualquer tipo de dados: strings, números, booleanos, arrays, objetos. Por exemplo, você pode monitorar o número de vezes que um gato foi acariciado com const [timesPetted, setTimesPetted] = useState(0)!

Chamar useState faz duas coisas:

  • cria uma “variável de estado” com um valor inicial – neste caso a variável de estado é isHungry e seu valor inicial é true
  • cria uma função para definir o valor dessa variável de estado setIsHungry

Não importa quais nomes você usa. Mas pode ser útil pensar no padrão como [<getter>, <setter>] = useState(<initialValue>).

Em seguida, você adiciona o componente principal Button e atribui a ele uma propriedade onPress:

tsx
<Button
+  onPress={() => {
+    setIsHungry(false);
+  }}
+  //..
+/>

Agora, quando alguém pressiona o botão, onPress será acionado, chamando setIsHungry(false). Isso define a variável de estado isHungry como false. Quando isHungry é falso, a propriedade disabled do Button é definida como true e seu title também muda:

tsx
<Button
+  //..
+  disabled={!isHungry}
+  title={isHungry ? 'Give me some food, please!' : 'Thank you!'}
+/>

Você deve ter notado que embora isHungry seja um const, ele é aparentemente reatribuível! O que está acontecendo é que quando uma função de configuração de estado como setIsHungry é chamada, seu componente será renderizado novamente. Neste caso, a função Cat será executada novamente - e desta vez, useState nos dará o próximo valor de isHungry.

Finalmente, coloque seus gatos dentro de um componente Cafe:

tsx
const Cafe = () => {
+  return (
+    <>
+      <Cat name="Munkustrap" />
+      <Cat name="Spot" />
+    </>
+  );
+};

Veja <> e </> acima? Esses bits de JSX são fragmentos. Os elementos JSX adjacentes devem ser agrupados em uma tag envolvente. Os fragmentos permitem fazer isso sem aninhar um elemento de encapsulamento extra e desnecessário, como View.

Agora que você cobriu os componentes principais do React e do React Native, vamos nos aprofundar em alguns desses componentes principais examinando handling <TextInput>.

`,68),p=[e];function l(h,k,r,d,E,o){return a(),i("div",null,p)}const y=s(t,[["render",l]]);export{c as __pageData,y as default}; diff --git a/vitepress/docs/.vitepress/dist/assets/docs_intro-react.md.DeRGrixp.lean.js b/vitepress/docs/.vitepress/dist/assets/docs_intro-react.md.DeRGrixp.lean.js new file mode 100644 index 0000000..cafb0a5 --- /dev/null +++ b/vitepress/docs/.vitepress/dist/assets/docs_intro-react.md.DeRGrixp.lean.js @@ -0,0 +1 @@ +import{_ as s,c as i,o as a,a4 as n}from"./chunks/framework.nQaBHiNx.js";const c=JSON.parse('{"title":"Fundamentos do React","description":"Para entender totalmente o React Native, você precisa de uma base sólida em React. Esta breve introdução ao React pode ajudá-lo a começar ou se atualizar.","frontmatter":{"id":"intro-react","title":"Fundamentos do React","description":"Para entender totalmente o React Native, você precisa de uma base sólida em React. Esta breve introdução ao React pode ajudá-lo a começar ou se atualizar."},"headers":[],"relativePath":"docs/intro-react.md","filePath":"docs/intro-react.md"}'),t={name:"docs/intro-react.md"},e=n("",68),p=[e];function l(h,k,r,d,E,o){return a(),i("div",null,p)}const y=s(t,[["render",l]]);export{c as __pageData,y as default}; diff --git a/vitepress/docs/.vitepress/dist/assets/docs_introduction.md.WUMOn0xY.js b/vitepress/docs/.vitepress/dist/assets/docs_introduction.md.WUMOn0xY.js new file mode 100644 index 0000000..a45ab7c --- /dev/null +++ b/vitepress/docs/.vitepress/dist/assets/docs_introduction.md.WUMOn0xY.js @@ -0,0 +1 @@ +import{_ as o,c as e,o as a,m as t,a as n}from"./chunks/framework.nQaBHiNx.js";const f=JSON.parse('{"title":"","description":"","frontmatter":{},"headers":[],"relativePath":"docs/introduction.md","filePath":"docs/introduction.md"}'),r={name:"docs/introduction.md"},c=t("h2",{id:"introducao",tabindex:"-1"},[n("Introdução "),t("a",{class:"header-anchor",href:"#introducao","aria-label":'Permalink to "Introdução"'},"​")],-1),d=[c];function s(i,_,l,u,m,p){return a(),e("div",null,d)}const x=o(r,[["render",s]]);export{f as __pageData,x as default}; diff --git a/vitepress/docs/.vitepress/dist/assets/docs_introduction.md.WUMOn0xY.lean.js b/vitepress/docs/.vitepress/dist/assets/docs_introduction.md.WUMOn0xY.lean.js new file mode 100644 index 0000000..a45ab7c --- /dev/null +++ b/vitepress/docs/.vitepress/dist/assets/docs_introduction.md.WUMOn0xY.lean.js @@ -0,0 +1 @@ +import{_ as o,c as e,o as a,m as t,a as n}from"./chunks/framework.nQaBHiNx.js";const f=JSON.parse('{"title":"","description":"","frontmatter":{},"headers":[],"relativePath":"docs/introduction.md","filePath":"docs/introduction.md"}'),r={name:"docs/introduction.md"},c=t("h2",{id:"introducao",tabindex:"-1"},[n("Introdução "),t("a",{class:"header-anchor",href:"#introducao","aria-label":'Permalink to "Introdução"'},"​")],-1),d=[c];function s(i,_,l,u,m,p){return a(),e("div",null,d)}const x=o(r,[["render",s]]);export{f as __pageData,x as default}; diff --git a/vitepress/docs/.vitepress/dist/assets/docs_javascript-environment.md.Bj5yh4uJ.js b/vitepress/docs/.vitepress/dist/assets/docs_javascript-environment.md.Bj5yh4uJ.js new file mode 100644 index 0000000..11e62df --- /dev/null +++ b/vitepress/docs/.vitepress/dist/assets/docs_javascript-environment.md.Bj5yh4uJ.js @@ -0,0 +1 @@ +import{_ as e,c as t,o as r,a4 as a}from"./chunks/framework.nQaBHiNx.js";const m=JSON.parse('{"title":"Ambiente JavaScript","description":"","frontmatter":{},"headers":[],"relativePath":"docs/javascript-environment.md","filePath":"docs/javascript-environment.md"}'),o={name:"docs/javascript-environment.md"},s=a('

Ambiente JavaScript

Tempo de execução JavaScript

Ao usar React Native, você executará seu código JavaScript em até três ambientes:

  • Na maioria dos casos, o React Native usará o Hermes, um mecanismo JavaScript de código aberto otimizado para o React Native.
  • Se o Hermes estiver desativado, o React Native usará JavaScriptCore, o mecanismo JavaScript que alimenta o Safari. Observe que no iOS, JavaScriptCore não usa JIT devido à ausência de memória executável gravável em aplicativos iOS.
  • Ao usar a depuração do Chrome, todo o código JavaScript é executado no próprio Chrome, comunicando-se com o código nativo por meio de WebSockets. O Chrome usa V8 como mecanismo JavaScript.

Embora esses ambientes sejam muito semelhantes, você pode acabar encontrando algumas inconsistências. É melhor evitar depender de especificações de qualquer tempo de execução.

Transformadores de sintaxe JavaScript

Os transformadores de sintaxe tornam a escrita de código mais agradável, permitindo que você use a nova sintaxe JavaScript sem ter que esperar pelo suporte de todos os interpretadores.

O React Native vem com o compilador Babel JavaScript. Verifique a documentação do Babel sobre suas transformações suportadas para obter mais detalhes.

Uma lista completa das transformações habilitadas para React Native pode ser encontrada em @react-native/babel-preset.

TRANSFORMAÇÃOCÓDIGO
ECMAScript 5
Palavras reservadaspromise.catch(function() {...});
Arrow functions<C onPress={() => this.setState({pressed: true})} />
Block scopinglet greeting = 'hi';
Call spreadMath.max(...array);
Classesclass C extends React.Component { render() { return <View />; } }
Computed Propertiesconst key = 'abc'; const obj = {[key]: 10};
Constantsconst answer = 42;
Destructuringconst {isActive, style} = this.props;
for…offor (var num of [1, 2, 3]) {...};
Function Namelet number = x => x;
Literalsconst b = 0b11; const o = 0o7; const u = 'Hello\\u{000A}\\u{0009}!';
Modulesimport React, {Component} from 'react';
Object Concise Methodconst obj = {method() { return 10; }};
Object Short Notationconst name = 'vjeux'; const obj = {name};
Parametersfunction test(x = 'hello', {a, b}, ...args) {}
Rest Paramsfunction(type, ...args) {};
Shorthand Propertiesconst o = {a, b, c};
Sticky Regexconst a = /o+/y;
Template Literalsconst who = 'world'; const str = Hello ${who};
Unicode Regexconst string = 'foo💩bar'; const match = string.match(/foo(.)bar/u);
ECMAScript 2016 (ES7)
Exponentiation Operatorlet x = 10 ** 2;
ECMAScript 2017 (ES8)
Async Functionsasync function doStuffAsync() {const foo = await doOtherStuffAsync();};
Function Trailing Commafunction f(a, b, c,) {};
ECMAScript 2018 (ES9)
Object Spreadconst extended = {...obj, a: 10};
ECMAScript 2019 (ES10)
Optional Catch Bindingtry {throw 0; } catch { doSomethingWhichDoesNotCareAboutTheValueThrown();}
ECMAScript 2020 (ES11)
Dynamic Importsconst package = await import('package'); package.function()
Nullish Coalescing Operatorconst foo = object.foo ?? 'default';
Optional Chainingconst name = obj.user?.name;
ECMAScript 2022 (ES13)
Class Fieldsclass Bork {static a = 'foo'; static b; x = 'bar'; y;}
Proposta da etapa 1
Export Default Fromexport v from 'mod';
Diversos
Babel Templatetemplate(const %%importName%% = require(%%source%%););
Flowfunction foo(x: ?number): string {};
ESM to CJSexport default 42;
JSX<View style={{color: 'red'}} />
Object AssignObject.assign(a, b);
React Display Nameconst bar = createReactClass({});
TypeScriptfunction foo(x: {hello: true, target: 'react native!'}): string {};

Polifills

Muitas funções padrão também estão disponíveis em todos os tempos de execução JavaScript suportados.

ECMAScript 2015 (ES6)

ECMAScript 2016 (ES7)

ECMAScript 2017 (ES8)

Específico

  • __DEV__
',22),d=[s];function n(c,l,i,p,b,h){return r(),t("div",null,d)}const g=e(o,[["render",n]]);export{m as __pageData,g as default}; diff --git a/vitepress/docs/.vitepress/dist/assets/docs_javascript-environment.md.Bj5yh4uJ.lean.js b/vitepress/docs/.vitepress/dist/assets/docs_javascript-environment.md.Bj5yh4uJ.lean.js new file mode 100644 index 0000000..88ffbfe --- /dev/null +++ b/vitepress/docs/.vitepress/dist/assets/docs_javascript-environment.md.Bj5yh4uJ.lean.js @@ -0,0 +1 @@ +import{_ as e,c as t,o as r,a4 as a}from"./chunks/framework.nQaBHiNx.js";const m=JSON.parse('{"title":"Ambiente JavaScript","description":"","frontmatter":{},"headers":[],"relativePath":"docs/javascript-environment.md","filePath":"docs/javascript-environment.md"}'),o={name:"docs/javascript-environment.md"},s=a("",22),d=[s];function n(c,l,i,p,b,h){return r(),t("div",null,d)}const g=e(o,[["render",n]]);export{m as __pageData,g as default}; diff --git a/vitepress/docs/.vitepress/dist/assets/docs_libraries.md.DmT4KVPl.js b/vitepress/docs/.vitepress/dist/assets/docs_libraries.md.DmT4KVPl.js new file mode 100644 index 0000000..9e4f058 --- /dev/null +++ b/vitepress/docs/.vitepress/dist/assets/docs_libraries.md.DmT4KVPl.js @@ -0,0 +1 @@ +import{_ as a,c as e,o as i,a4 as o}from"./chunks/framework.nQaBHiNx.js";const h=JSON.parse('{"title":"Usando bibliotecas","description":"","frontmatter":{},"headers":[],"relativePath":"docs/libraries.md","filePath":"docs/libraries.md"}'),s={name:"docs/libraries.md"},t=o('

Usando bibliotecas

React Native fornece um conjunto de componentes principais e APIs integrados, prontos para uso em seu aplicativo. Você não está limitado aos componentes e APIs incluídos no React Native. React Native tem uma comunidade de milhares de desenvolvedores. Se os componentes principais e as APIs não tiverem o que você procura, você poderá encontrar e instalar uma biblioteca da comunidade para adicionar a funcionalidade ao seu aplicativo.

Selecionando um gerenciador de pacotes

As bibliotecas React Native são normalmente instaladas a partir do npm usando um gerenciador de pacotes Node.js, como npm CLI ou Yarn Classic.

Se você tiver o Node.js instalado em seu computador, então você já tem a CLI npm instalada. Alguns desenvolvedores preferem usar o Yarn Classic para tempos de instalação um pouco mais rápidos e recursos avançados adicionais, como Workspaces. Ambas as ferramentas funcionam muito bem com React Native. Assumiremos o npm no restante deste guia para simplificar a explicação.

DICA

Os termos “biblioteca” e “pacote” são usados indistintamente na comunidade JavaScript.

Instalando uma biblioteca

Para instalar uma biblioteca em seu projeto, navegue até o diretório do projeto em seu terminal e execute o comando de instalação. Vamos tentar isso com react-native-webview:

bash
npm install react-native-webview
bash
yarn add react-native-webview

A biblioteca que instalamos inclui código nativo e precisamos vincular ao nosso aplicativo antes de usá-lo.

Vinculando código nativo no iOS

React Native usa CocoaPods para gerenciar dependências de projetos iOS e a maioria das bibliotecas React Native seguem esta mesma convenção. Se uma biblioteca que você está usando não tiver, consulte o README para obter instruções adicionais. Na maioria dos casos, as instruções a seguir serão aplicadas.

Execute pod install em nosso diretório ios para vinculá-lo ao nosso projeto iOS nativo. Um atalho para fazer isso sem mudar para o diretório ios é executar npx pod-install.

bash
npx pod-install

Quando isso estiver concluído, reconstrua o binário do aplicativo para começar a usar sua nova biblioteca:

bash
npm run ios
bash
yarn ios

Vinculando código nativo no Android

React Native usa Gradle para gerenciar dependências de projetos Android. Depois de instalar uma biblioteca com dependências nativas, você precisará reconstruir o binário do aplicativo para usar sua nova biblioteca:

bash
npm run android
bash
yarn android

Encontrando Bibliotecas

React Native Directory é um banco de dados pesquisável de bibliotecas construídas especificamente para React Native. Este é o primeiro lugar para procurar uma biblioteca para seu aplicativo React Native.

Muitas das bibliotecas que você encontrará no diretório são da React Native Community ou Expo.

As bibliotecas construídas pela comunidade React Native são dirigidas por voluntários e indivíduos em empresas que dependem do React Native. Eles geralmente oferecem suporte a iOS, tvOS, Android, Windows, mas isso varia entre os projetos. Muitas das bibliotecas nesta organização já foram componentes principais e APIs do React Native.

As bibliotecas criadas pela Expo são todas escritas em TypeScript e suportam iOS, Android e react-native-web sempre que possível.

Depois do React Native Directory, o registro npm é o próximo melhor lugar se você não conseguir encontrar uma biblioteca específica para React Native. O registro npm é a fonte definitiva para bibliotecas JavaScript, mas as bibliotecas listadas podem não ser todas compatíveis com React Native. React Native é um dos muitos ambientes de programação JavaScript, incluindo Node.js, navegadores da web, Electron e muito mais, e o npm inclui bibliotecas que funcionam para todos esses ambientes.

Determinando a compatibilidade da biblioteca

Funciona com React Native?

Normalmente, bibliotecas construídas especificamente para outras plataformas não funcionarão com React Native. Os exemplos incluem react-select, que é desenvolvido para a web e tem como alvo específico o react-dom, e rimraf, que é desenvolvido para Node.js e interage com o sistema de arquivos do seu computador. Outras bibliotecas como a lodash usam apenas recursos da linguagem JavaScript e funcionam em qualquer ambiente. Você entenderá isso com o tempo, mas até então a maneira mais fácil de descobrir é tentar você mesmo. Você pode remover pacotes usando npm uninstall se descobrir que ele não funciona no React Native.

Funciona nas plataformas suportadas pelo meu aplicativo?

React Native Directory permite filtrar por compatibilidade de plataforma, como iOS, Android, Web e Windows. Se a biblioteca que você gostaria de usar não estiver listada lá, consulte o README da biblioteca para saber mais.

Funciona com a versão do meu aplicativo React Native?

A versão mais recente de uma biblioteca normalmente é compatível com a versão mais recente do React Native. Se você estiver usando uma versão mais antiga, consulte o README para saber qual versão da biblioteca deve instalar. Você pode instalar uma versão específica da biblioteca executando npm install <library-name>@<version-number>, por exemplo: npm install @react-native-community/netinfo@^2.0.0.

',32),n=[t];function c(r,d,l,p,m,u){return i(),e("div",null,n)}const v=a(s,[["render",c]]);export{h as __pageData,v as default}; diff --git a/vitepress/docs/.vitepress/dist/assets/docs_libraries.md.DmT4KVPl.lean.js b/vitepress/docs/.vitepress/dist/assets/docs_libraries.md.DmT4KVPl.lean.js new file mode 100644 index 0000000..2fadc05 --- /dev/null +++ b/vitepress/docs/.vitepress/dist/assets/docs_libraries.md.DmT4KVPl.lean.js @@ -0,0 +1 @@ +import{_ as a,c as e,o as i,a4 as o}from"./chunks/framework.nQaBHiNx.js";const h=JSON.parse('{"title":"Usando bibliotecas","description":"","frontmatter":{},"headers":[],"relativePath":"docs/libraries.md","filePath":"docs/libraries.md"}'),s={name:"docs/libraries.md"},t=o("",32),n=[t];function c(r,d,l,p,m,u){return i(),e("div",null,n)}const v=a(s,[["render",c]]);export{h as __pageData,v as default}; diff --git a/vitepress/docs/.vitepress/dist/assets/docs_linking-libraries-ios.md.CDTwulNM.js b/vitepress/docs/.vitepress/dist/assets/docs_linking-libraries-ios.md.CDTwulNM.js new file mode 100644 index 0000000..539b8e7 --- /dev/null +++ b/vitepress/docs/.vitepress/dist/assets/docs_linking-libraries-ios.md.CDTwulNM.js @@ -0,0 +1 @@ +import{_ as a,c as e,o,a4 as s}from"./chunks/framework.nQaBHiNx.js";const i="/assets/321053647-821ddb0c-400a-4139-8e72-56f6ed73743c.vAP2jue7.png",c="/assets/321053704-feda8ef3-32b9-484c-8413-23d09d8d08d3.xRS3UhYx.png",t="/assets/321054351-b9a3e3bb-5c9b-43a7-9819-f638fbfa64a9.DYWMGxS_.png",k=JSON.parse('{"title":"Vinculando Bibliotecas","description":"","frontmatter":{},"headers":[],"relativePath":"docs/linking-libraries-ios.md","filePath":"docs/linking-libraries-ios.md"}'),r={name:"docs/linking-libraries-ios.md"},n=s('

Vinculando Bibliotecas

Nem todo aplicativo usa todos os recursos nativos, e incluir o código para suportar todos esses recursos afetaria o tamanho binário... Mas ainda queremos oferecer suporte à adição desses recursos sempre que você precisar deles.

Com isso em mente, expusemos muitos desses recursos como bibliotecas estáticas independentes.

Para a maioria das bibliotecas será tão rápido quanto arrastar dois arquivos, às vezes será necessário um terceiro passo, mas não mais que isso.

Observação

Todas as bibliotecas que enviamos com o React Native ficam na pasta Libraries na raiz do repositório. Alguns deles são JavaScript puro e você só precisa usar o require. Outras bibliotecas também dependem de algum código nativo; nesse caso, você terá que adicionar esses arquivos ao seu aplicativo, caso contrário, o aplicativo gerará um erro assim que você tentar usar a biblioteca.

Aqui estão algumas etapas para vincular suas bibliotecas que contêm código nativo

Vinculação automática

Instale uma biblioteca com dependências nativas:

bash
npm install <library-with-native-dependencies> --save

Informações

O sinalizador --save ou --save-dev é muito importante para esta etapa. React Native vinculará suas bibliotecas com base em dependencies e devDependencies em seu arquivo package.json.

É isso! Na próxima vez que você criar seu aplicativo, o código nativo será vinculado graças ao mecanismo autolinking.

Vinculação manual

Passo 1

Se a biblioteca possuir código nativo, deve haver um arquivo .xcodeproj dentro de sua pasta. Arraste este arquivo para o seu projeto no Xcode (geralmente no grupo Libraries no Xcode);

Passo 2

Clique no arquivo principal do seu projeto (aquele que representa o .xcodeproj) selecione Build Phases e arraste a biblioteca estática da pasta Products dentro da biblioteca que você está importando para Link Binary With Libraries

Etapa 3

Nem toda biblioteca precisará desta etapa, o que você precisa considerar é:

Preciso conhecer o conteúdo da biblioteca em tempo de compilação?

Isso significa que você está usando esta biblioteca no lado nativo ou apenas em JavaScript? Se você estiver usando apenas em JavaScript, está pronto para prosseguir!

Se você precisar chamá-lo do nativo, precisaremos saber os cabeçalhos da biblioteca. Para conseguir isso você deve ir ao arquivo do seu projeto, selecionar Build Settings e procurar por Header Search Paths. Lá você deve incluir o caminho para sua biblioteca. (Esta documentação costumava recomendar o uso de recursive, mas isso não é mais recomendado, pois pode causar falhas sutis de compilação, especialmente com CocoaPods.)

image

',24),d=[n];function l(p,u,m,b,h,v){return o(),e("div",null,d)}const q=a(r,[["render",l]]);export{k as __pageData,q as default}; diff --git a/vitepress/docs/.vitepress/dist/assets/docs_linking-libraries-ios.md.CDTwulNM.lean.js b/vitepress/docs/.vitepress/dist/assets/docs_linking-libraries-ios.md.CDTwulNM.lean.js new file mode 100644 index 0000000..66af2c7 --- /dev/null +++ b/vitepress/docs/.vitepress/dist/assets/docs_linking-libraries-ios.md.CDTwulNM.lean.js @@ -0,0 +1 @@ +import{_ as a,c as e,o,a4 as s}from"./chunks/framework.nQaBHiNx.js";const i="/assets/321053647-821ddb0c-400a-4139-8e72-56f6ed73743c.vAP2jue7.png",c="/assets/321053704-feda8ef3-32b9-484c-8413-23d09d8d08d3.xRS3UhYx.png",t="/assets/321054351-b9a3e3bb-5c9b-43a7-9819-f638fbfa64a9.DYWMGxS_.png",k=JSON.parse('{"title":"Vinculando Bibliotecas","description":"","frontmatter":{},"headers":[],"relativePath":"docs/linking-libraries-ios.md","filePath":"docs/linking-libraries-ios.md"}'),r={name:"docs/linking-libraries-ios.md"},n=s("",24),d=[n];function l(p,u,m,b,h,v){return o(),e("div",null,d)}const q=a(r,[["render",l]]);export{k as __pageData,q as default}; diff --git a/vitepress/docs/.vitepress/dist/assets/docs_metro.md.odTVVPP7.js b/vitepress/docs/.vitepress/dist/assets/docs_metro.md.odTVVPP7.js new file mode 100644 index 0000000..7ef479d --- /dev/null +++ b/vitepress/docs/.vitepress/dist/assets/docs_metro.md.odTVVPP7.js @@ -0,0 +1,38 @@ +import{_ as s,c as i,o as a,a4 as n}from"./chunks/framework.nQaBHiNx.js";const c=JSON.parse('{"title":"Metro","description":"","frontmatter":{},"headers":[],"relativePath":"docs/metro.md","filePath":"docs/metro.md"}'),e={name:"docs/metro.md"},t=n(`

Metro

React Native usa Metro para construir seu código JavaScript e ativos.

Configurando Metro

As opções de configuração do Metro podem ser personalizadas no arquivo metro.config.js do seu projeto. Isso pode exportar:

  • Um objeto (recomendado) que será mesclado com os padrões de configuração interna do Metro.
  • Uma função que será chamada com os padrões de configuração interna do Metro e deverá retornar um objeto de configuração final.

DICA

Consulte Configurando o Metro no site do Metro para obter documentação sobre todas as opções de configuração disponíveis.

No React Native, sua configuração Metro deve estender @react-native/metro-config ou @expo/metro-config. Esses pacotes contêm padrões essenciais necessários para construir e executar aplicativos React Native.

Abaixo está o arquivo metro.config.js padrão em um projeto de modelo React Native:

js
const {getDefaultConfig, mergeConfig} = require('@react-native/metro-config');
+
+/**
+ * Metro configuration
+ * https://facebook.github.io/metro/docs/configuration
+ *
+ * @type {import('metro-config').MetroConfig}
+ */
+const config = {};
+
+module.exports = mergeConfig(getDefaultConfig(__dirname), config);

As opções Metro que você deseja personalizar podem ser feitas dentro do objeto de configuração.

Avançado: usando uma função de configuração

Exportar uma função de configuração é uma opção para você mesmo gerenciar a configuração final – o Metro não aplicará nenhum padrão interno. Este padrão pode ser útil quando for necessário ler o objeto de configuração padrão base do Metro ou definir opções dinamicamente.

INFORMAÇÕES

A partir do @react-native/metro-config 0.72.1, não é mais necessário usar uma função de configuração para acessar a configuração padrão completa. Veja a seção de dicas abaixo.

js
const {getDefaultConfig, mergeConfig} = require('@react-native/metro-config');
+
+module.exports = function (baseConfig) {
+  const defaultConfig = mergeConfig(baseConfig, getDefaultConfig(__dirname));
+  const {resolver: {assetExts, sourceExts}} = defaultConfig;
+
+  return mergeConfig(
+    defaultConfig,
+    {
+      resolver: {
+        assetExts: assetExts.filter(ext => ext !== 'svg'),
+        sourceExts: [...sourceExts, 'svg'],
+      },
+    },
+  );
+};

DICA

Usar uma função de configuração é para casos de uso avançados. Um método mais simples do que o acima, por ex. para personalizar sourceExts, seria ler esses padrões em @react-native/metro-config.

Alternativa

js
const defaultConfig = getDefaultConfig(__dirname);
+ 
+const config = {
+  resolver: {
+    sourceExts: [...defaultConfig.resolver.sourceExts, 'svg'],
+  },
+};
+
+module.exports = mergeConfig(defaultConfig, config);

No entanto!, recomendamos copiar e editar ao substituir esses valores de configuração – colocando a fonte da verdade em seu arquivo de configuração.

✅ Recomendado

js
const config = {
+  resolver: {
+    sourceExts: ['js', 'ts', 'tsx', 'svg'],
+  },
+};
`,15),p=[t];function l(h,k,o,r,d,E){return a(),i("div",null,p)}const u=s(e,[["render",l]]);export{c as __pageData,u as default}; diff --git a/vitepress/docs/.vitepress/dist/assets/docs_metro.md.odTVVPP7.lean.js b/vitepress/docs/.vitepress/dist/assets/docs_metro.md.odTVVPP7.lean.js new file mode 100644 index 0000000..7bf0985 --- /dev/null +++ b/vitepress/docs/.vitepress/dist/assets/docs_metro.md.odTVVPP7.lean.js @@ -0,0 +1 @@ +import{_ as s,c as i,o as a,a4 as n}from"./chunks/framework.nQaBHiNx.js";const c=JSON.parse('{"title":"Metro","description":"","frontmatter":{},"headers":[],"relativePath":"docs/metro.md","filePath":"docs/metro.md"}'),e={name:"docs/metro.md"},t=n("",15),p=[t];function l(h,k,o,r,d,E){return a(),i("div",null,p)}const u=s(e,[["render",l]]);export{c as __pageData,u as default}; diff --git a/vitepress/docs/.vitepress/dist/assets/docs_more-resources.md.D6RVttbW.js b/vitepress/docs/.vitepress/dist/assets/docs_more-resources.md.D6RVttbW.js new file mode 100644 index 0000000..a3cfdb3 --- /dev/null +++ b/vitepress/docs/.vitepress/dist/assets/docs_more-resources.md.D6RVttbW.js @@ -0,0 +1 @@ +import{_ as e,c as a,o,a4 as r}from"./chunks/framework.nQaBHiNx.js";const v=JSON.parse('{"title":"Mais recursos","description":"","frontmatter":{},"headers":[],"relativePath":"docs/more-resources.md","filePath":"docs/more-resources.md"}'),t={name:"docs/more-resources.md"},i=r('

Mais recursos

Sempre há mais para aprender: fluxos de trabalho de desenvolvedores, envio para lojas de aplicativos, internacionalização, segurança e muito mais.

Para onde ir a partir daqui:

Mergulho profundo

IDEs

Recomendamos usar o editor de código VS Code e suas úteis ferramentas React Native.

Plataformas para experimentar

Expo é uma estrutura de ferramentas e serviços para React Native que se concentra em ajudar você a construir, enviar e iterar em seu aplicativo, para usar fluxos de trabalho de implantação de visualização que são populares no desenvolvimento web e para automatizar seus fluxos de trabalho de desenvolvimento. A Expo também torna possível construir aplicativos React Native sem nunca tocar no Xcode ou no Android Studio, e não atrapalha se você quiser usar essas ferramentas.

Ignite é um kit inicial CLI com vários padrões React Native. O mais recente, Ignite Maverick, usa MobX-State-Tree para gerenciamento de estado, React Navigation e outras bibliotecas comuns. Possui geradores para telas, modelos e muito mais, e suporta Expo imediatamente. O Ignite também vem com uma biblioteca de componentes ajustada para designs personalizados, suporte a temas e testes. Se você está procurando uma pilha de tecnologia pré-configurada, o Ignite pode ser perfeito para você.

Aplicativos de exemplo

Experimente os aplicativos do Showcase para ver do que o React Native é capaz! Procurando algo mais prático? Confira este conjunto de aplicativos de exemplo no GitHub. Você pode ver o código-fonte deles – tente executar um em um simulador ou dispositivo.

Encontre, crie e compartilhe seus próprios componentes nativos e TurboModules

React Native tem uma comunidade de milhares de desenvolvedores como você, criando conteúdo, ferramentas, tutoriais – e componentes nativos!

Não consegue encontrar o que procura nos componentes principais? Visite React Native Directory para descobrir o que a comunidade está criando.

Interessado em criar seu próprio componente ou módulo nativo? Criar módulos para seu próprio caso de uso e compartilhá-los com outras pessoas no NPM e GitHub ajuda a expandir o ecossistema e a comunidade React Native! Leia os guias para criar seus próprios módulos nativos (Android, iOS) e componentes nativos (Android, iOS).

',17),s=[i];function n(c,l,d,p,u,m){return o(),a("div",null,s)}const f=e(t,[["render",n]]);export{v as __pageData,f as default}; diff --git a/vitepress/docs/.vitepress/dist/assets/docs_more-resources.md.D6RVttbW.lean.js b/vitepress/docs/.vitepress/dist/assets/docs_more-resources.md.D6RVttbW.lean.js new file mode 100644 index 0000000..c2b4250 --- /dev/null +++ b/vitepress/docs/.vitepress/dist/assets/docs_more-resources.md.D6RVttbW.lean.js @@ -0,0 +1 @@ +import{_ as e,c as a,o,a4 as r}from"./chunks/framework.nQaBHiNx.js";const v=JSON.parse('{"title":"Mais recursos","description":"","frontmatter":{},"headers":[],"relativePath":"docs/more-resources.md","filePath":"docs/more-resources.md"}'),t={name:"docs/more-resources.md"},i=r("",17),s=[i];function n(c,l,d,p,u,m){return o(),a("div",null,s)}const f=e(t,[["render",n]]);export{v as __pageData,f as default}; diff --git a/vitepress/docs/.vitepress/dist/assets/docs_native-components-android.md.D-fmrhIe.js b/vitepress/docs/.vitepress/dist/assets/docs_native-components-android.md.D-fmrhIe.js new file mode 100644 index 0000000..cd2d5e8 --- /dev/null +++ b/vitepress/docs/.vitepress/dist/assets/docs_native-components-android.md.D-fmrhIe.js @@ -0,0 +1,583 @@ +import{_ as s,c as i,o as a,a4 as n}from"./chunks/framework.nQaBHiNx.js";const c=JSON.parse('{"title":"Componentes de IU nativos do Android","description":"","frontmatter":{},"headers":[],"relativePath":"docs/native-components-android.md","filePath":"docs/native-components-android.md"}'),e={name:"docs/native-components-android.md"},p=n(`

Componentes de IU nativos do Android

INFORMAÇÕES

Módulo Nativo e Componentes Nativos são nossas tecnologias estáveis usadas pela arquitetura legada. Eles serão descontinuados no futuro, quando a Nova Arquitetura estiver estável. A nova arquitetura usa Turbo Native Module e Fabric Native Components para obter resultados semelhantes.

Existem muitos widgets de UI nativos prontos para serem usados nos aplicativos mais recentes - alguns deles fazem parte da plataforma, outros estão disponíveis como bibliotecas de terceiros e ainda mais podem estar em uso em seu próprio portfólio. React Native tem vários dos componentes de plataforma mais críticos já empacotados, como ScrollView e TextInput, mas não todos eles, e certamente não aqueles que você mesmo possa ter escrito para um aplicativo anterior. Felizmente, podemos agrupar esses componentes existentes para uma integração perfeita com seu aplicativo React Native.

Assim como o guia do módulo nativo, este também é um guia mais avançado que pressupõe que você esteja familiarizado com a programação do Android SDK. Este guia mostrará como construir um componente de UI nativo, orientando você na implementação de um subconjunto do componente ImageView existente disponível na biblioteca principal do React Native.

Exemplo de ImageView

Neste exemplo, examinaremos os requisitos de implementação para permitir o uso de ImageViews em JavaScript.

As visualizações nativas são criadas e manipuladas estendendo o ViewManager ou, mais comumente, o SimpleViewManager. Um SimpleViewManager é conveniente nesse caso porque aplica propriedades comuns, como cor de fundo, opacidade e layout Flexbox.

Essas subclasses são essencialmente singletons – apenas uma instância de cada é criada pela ponte. Eles enviam visualizações nativas para o NativeViewHierarchyManager, que delega de volta a eles a definição e atualização das propriedades das visualizações conforme necessário. Os ViewManagers também são normalmente os delegados das visualizações, enviando eventos de volta ao JavaScript por meio da ponte.

Para enviar uma view:

  1. Crie a subclasse ViewManager.
  2. Implemente o método createViewInstance
  3. Expor configuradores de propriedades de visualização usando a anotação @ReactProp (ou @ReactPropGroup)
  4. Cadastre o gerenciador em createViewManagers do pacote de aplicações.
  5. Implementar o módulo JavaScript

1. Crie a subclasse ViewManager

Neste exemplo, criamos a classe gerenciadora de visualizações ReactImageManager que estende SimpleViewManager do tipo ReactImageView. ReactImageView é o tipo de objeto controlado pelo gerenciador, esta será a visualização nativa customizada. O nome retornado por getName é usado para fazer referência ao tipo de visualização nativa do JavaScript.

java
public class ReactImageManager extends SimpleViewManager<ReactImageView> {
+
+  public static final String REACT_CLASS = "RCTImageView";
+  ReactApplicationContext mCallerContext;
+
+  public ReactImageManager(ReactApplicationContext reactContext) {
+    mCallerContext = reactContext;
+  }
+
+  @Override
+  public String getName() {
+    return REACT_CLASS;
+  }
+}
kotlin
class ReactImageManager(
+    private val callerContext: ReactApplicationContext
+) : SimpleViewManager<ReactImageView>() {
+
+  override fun getName() = REACT_CLASS
+
+  companion object {
+    const val REACT_CLASS = "RCTImageView"
+  }
+}

2. Implementar o método createViewInstance

As visualizações são criadas no método createViewInstance, a visualização deve ser inicializada em seu estado padrão, quaisquer propriedades serão definidas por meio de uma chamada de acompanhamento para updateView.

java
@Override
+  public ReactImageView createViewInstance(ThemedReactContext context) {
+    return new ReactImageView(context, Fresco.newDraweeControllerBuilder(), null, mCallerContext);
+  }
kotlin
  override fun createViewInstance(context: ThemedReactContext) =
+      ReactImageView(context, Fresco.newDraweeControllerBuilder(), null, callerContext)

3. Exponha os configuradores de propriedades de visualização usando a anotação @ReactProp (ou @ReactPropGroup)

As propriedades que devem ser refletidas em JavaScript precisam ser expostas como método setter anotado com @ReactProp (ou @ReactPropGroup). O método setter deve considerar a visão atualizada (do tipo de visão atual) como primeiro argumento e o valor da propriedade como segundo argumento. O setter deve ser público e não retornar um valor (ou seja, o tipo de retorno deve ser void em Java ou Unit em Kotlin). O tipo de propriedade enviado para JS é determinado automaticamente com base no tipo de argumento de valor do setter. Os seguintes tipos de valores são atualmente suportados (em Java): boolean, int, float, double, String, Boolean, Integer, ReadableArray, ReadableMap. Os tipos correspondentes em Kotlin são Boolean, Int, Float, Double, String, ReadableArray, ReadableMap\`.

A anotação @ReactProp possui um nome de argumento obrigatório do tipo String. O nome atribuído à anotação @ReactProp vinculada ao método setter é usado para referenciar a propriedade no lado JS.

Exceto pelo nome, a anotação @ReactProp pode receber os seguintes argumentos opcionais: defaultBoolean, defaultInt, defaultFloat. Esses argumentos devem ser do tipo correspondente (respectivamente boolean, int, float em Java e Boolean, Int, Float em Kotlin) e o valor fornecido será passado para o método setter caso a propriedade que o setter está referenciando tenha sido removida do componente. Observe que os valores "padrão" são fornecidos apenas para tipos primitivos; caso o setter seja de algum tipo complexo, null será fornecido como valor padrão caso a propriedade correspondente seja removida.

Os requisitos de declaração do setter para métodos anotados com @ReactPropGroup são diferentes dos de @ReactProp. Consulte os documentos da classe de anotação @ReactPropGroup para obter mais informações sobre isso. IMPORTANTE! no ReactJS, atualizar o valor da propriedade resultará na chamada do método setter. Observe que uma das maneiras de atualizar o componente é removendo as propriedades que foram definidas anteriormente. Nesse caso, o método setter também será chamado para notificar o gerenciador de visualização de que a propriedade foi alterada. Nesse caso, o valor "default" será fornecido (para tipos primitivos, o valor "default" pode ser especificado usando argumentos defaultBoolean, defaultFloat, etc. da anotação @ReactProp, para tipos complexos, o setter será chamado com o valor definido como nulo).

java
  @ReactProp(name = "src")
+  public void setSrc(ReactImageView view, @Nullable ReadableArray sources) {
+    view.setSource(sources);
+  }
+
+  @ReactProp(name = "borderRadius", defaultFloat = 0f)
+  public void setBorderRadius(ReactImageView view, float borderRadius) {
+    view.setBorderRadius(borderRadius);
+  }
+
+  @ReactProp(name = ViewProps.RESIZE_MODE)
+  public void setResizeMode(ReactImageView view, @Nullable String resizeMode) {
+    view.setScaleType(ImageResizeMode.toScaleType(resizeMode));
+  }
kotlin
  @ReactProp(name = "src")
+  fun setSrc(view: ReactImageView, sources: ReadableArray?) {
+    view.setSource(sources)
+  }
+
+  @ReactProp(name = "borderRadius", defaultFloat = 0f)
+  override fun setBorderRadius(view: ReactImageView, borderRadius: Float) {
+    view.setBorderRadius(borderRadius)
+  }
+
+  @ReactProp(name = ViewProps.RESIZE_MODE)
+  fun setResizeMode(view: ReactImageView, resizeMode: String?) {
+    view.setScaleType(ImageResizeMode.toScaleType(resizeMode))
+  }

4. Cadastre o ViewManager

A etapa final é registrar o ViewManager na aplicação, isso acontece de forma semelhante aos Módulos Nativos, por meio da função membro do pacote de aplicações createViewManagers.

java
  @Override
+  public List<ViewManager> createViewManagers(
+                            ReactApplicationContext reactContext) {
+    return Arrays.<ViewManager>asList(
+      new ReactImageManager(reactContext)
+    );
+  }
kotlin
  override fun createViewManagers(
+      reactContext: ReactApplicationContext
+  ) = listOf(ReactImageManager(reactContext))

:::

5. Implemente o módulo JavaScript

A etapa final é criar o módulo JavaScript que define a camada de interface entre Java/Kotlin e JavaScript para os usuários de sua nova visualização. É recomendado que você documente a interface do componente neste módulo (por exemplo, usando TypeScript, Flow ou comentários antigos).

tsx
// ImageView.tsx
+
+import {requireNativeComponent} from 'react-native';
+
+/**
+ * Composes \`View\`.
+ *
+ * - src: string
+ * - borderRadius: number
+ * - resizeMode: 'cover' | 'contain' | 'stretch'
+ */
+module.exports = requireNativeComponent('RCTImageView');

A função requireNativeComponent leva o nome da visualização nativa. Observe que se o seu componente precisar fazer algo mais sofisticado (por exemplo, manipulação de eventos personalizados), você deverá agrupar o componente nativo em outro componente React. Isso é ilustrado no exemplo MyCustomView abaixo.

Eventos

Agora sabemos como expor componentes de visualização nativa que podemos controlar livremente a partir de JS, mas como lidamos com eventos do usuário, como pinçar zoom ou panorâmica? Quando ocorre um evento nativo, o código nativo deve emitir um evento para a representação JavaScript da View, e as duas visualizações são vinculadas ao valor retornado do método getId().

java
class MyCustomView extends View {
+   ...
+   public void onReceiveNativeEvent() {
+      WritableMap event = Arguments.createMap();
+      event.putString("message", "MyMessage");
+      ReactContext reactContext = (ReactContext)getContext();
+      reactContext
+          .getJSModule(RCTEventEmitter.class)
+          .receiveEvent(getId(), "topChange", event);
+    }
+}
kotlin
class MyCustomView(context: Context) : View(context) {
+  ...
+  fun onReceiveNativeEvent() {
+    val event = Arguments.createMap().apply {
+      putString("message", "MyMessage")
+    }
+    val reactContext = context as ReactContext
+    reactContext
+        .getJSModule(RCTEventEmitter::class.java)
+        .receiveEvent(id, "topChange", event)
+  }
+}

Para mapear o nome do evento topChange para a propriedade de retorno de chamada onChange em JavaScript, registre-o substituindo o método getExportedCustomBubblingEventTypeConstants em seu ViewManager:

java
public class ReactImageManager extends SimpleViewManager<MyCustomView> {
+    ...
+    public Map getExportedCustomBubblingEventTypeConstants() {
+        return MapBuilder.builder().put(
+            "topChange",
+            MapBuilder.of(
+                "phasedRegistrationNames",
+                MapBuilder.of("bubbled", "onChange")
+            )
+        ).build();
+    }
+}
kotlin
class ReactImageManager : SimpleViewManager<MyCustomView>() {
+  ...
+  override fun getExportedCustomBubblingEventTypeConstants(): Map<String, Any> {
+    return mapOf(
+      "topChange" to mapOf(
+        "phasedRegistrationNames" to mapOf(
+          "bubbled" to "onChange"
+        )
+      )
+    )
+  }
+}

Esse retorno de chamada é invocado com o evento bruto, que normalmente processamos no componente wrapper para criar uma API mais simples:

tsx
// MyCustomView.tsx
+
+class MyCustomView extends React.Component {
+  constructor(props) {
+    super(props);
+    this._onChange = this._onChange.bind(this);
+  }
+  _onChange(event) {
+    if (!this.props.onChangeMessage) {
+      return;
+    }
+    this.props.onChangeMessage(event.nativeEvent.message);
+  }
+  render() {
+    return <RCTMyCustomView {...this.props} onChange={this._onChange} />;
+  }
+}
+MyCustomView.propTypes = {
+  /**
+   * Retorno de chamada que é chamado continuamente quando o usuário arrasta o mapa.
+   */
+  onChangeMessage: PropTypes.func,
+  ...
+};
+
+const RCTMyCustomView = requireNativeComponent(\`RCTMyCustomView\`);

Exemplo de integração com um fragmento Android

Para integrar elementos de UI nativa existentes ao seu aplicativo React Native, pode ser necessário usar Android Fragments para fornecer um controle mais granular sobre seu componente nativo do que retornar uma View do seu ViewManager. Você precisará disso se quiser adicionar lógica personalizada vinculada à sua visualização com a ajuda de métodos de ciclo de vida, como onViewCreated, onPause, onResume. As etapas a seguir mostrarão como fazer isso:

1. Crie um exemplo de visualização personalizada

Primeiro, vamos criar uma classe CustomView que estende FrameLayout (o conteúdo desta visualização pode ser qualquer visualização que você gostaria de renderizar)

java
// substitua pelo seu pacote
+package com.mypackage;
+
+import android.content.Context;
+import android.graphics.Color;
+import android.widget.FrameLayout;
+import android.widget.ImageView;
+import android.widget.TextView;
+
+import androidx.annotation.NonNull;
+
+public class CustomView extends FrameLayout {
+  public CustomView(@NonNull Context context) {
+    super(context);
+    // definir preenchimento e cor de fundo
+    this.setPadding(16,16,16,16);
+    this.setBackgroundColor(Color.parseColor("#5FD3F3"));
+
+    // adicionar visualização de texto padrão
+    TextView text = new TextView(context);
+    text.setText("Welcome to Android Fragments with React Native.");
+    this.addView(text);
+  }
+}
kotlin
// substitua pelo seu pacote
+package com.mypackage
+
+import android.content.Context
+import android.graphics.Color
+import android.widget.FrameLayout
+import android.widget.TextView
+
+class CustomView(context: Context) : FrameLayout(context) {
+  init {
+    // definir preenchimento e cor de fundo
+    setPadding(16,16,16,16)
+    setBackgroundColor(Color.parseColor("#5FD3F3"))
+
+    // adicionar visualização de texto padrão
+    addView(TextView(context).apply {
+      text = "Welcome to Android Fragments with React Native."
+    })
+  }
+}

2. Crie um fragmento

java
// replace with your package
+package com.mypackage;
+
+import android.os.Bundle;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+import androidx.fragment.app.Fragment;
+
+// replace with your view's import
+import com.mypackage.CustomView;
+
+public class MyFragment extends Fragment {
+    CustomView customView;
+
+    @Override
+    public View onCreateView(LayoutInflater inflater, ViewGroup parent, Bundle savedInstanceState) {
+        super.onCreateView(inflater, parent, savedInstanceState);
+        customView = new CustomView(this.getContext());
+        return customView; // this CustomView could be any view that you want to render
+    }
+
+    @Override
+    public void onViewCreated(View view, Bundle savedInstanceState) {
+        super.onViewCreated(view, savedInstanceState);
+        // do any logic that should happen in an \`onCreate\` method, e.g:
+        // customView.onCreate(savedInstanceState);
+    }
+
+    @Override
+    public void onPause() {
+        super.onPause();
+        // do any logic that should happen in an \`onPause\` method
+        // e.g.: customView.onPause();
+    }
+
+    @Override
+    public void onResume() {
+        super.onResume();
+       // do any logic that should happen in an \`onResume\` method
+       // e.g.: customView.onResume();
+    }
+
+    @Override
+    public void onDestroy() {
+        super.onDestroy();
+        // do any logic that should happen in an \`onDestroy\` method
+        // e.g.: customView.onDestroy();
+    }
+}
kt
// substitua pelo seu pacote
+package com.mypackage
+
+import android.os.Bundle
+import android.view.LayoutInflater
+import android.view.View
+import android.view.ViewGroup
+import androidx.fragment.app.Fragment
+
+// substitua pela importação da sua visualização
+import com.mypackage.CustomView
+
+class MyFragment : Fragment() {
+  private lateinit var customView: CustomView
+
+  override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View {
+    super.onCreateView(inflater, container, savedInstanceState)
+    customView = CustomView(requireNotNull(context))
+    return customView // este CustomView pode ser qualquer visualização que você deseja renderizar
+  }
+
+  override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
+    super.onViewCreated(view, savedInstanceState)
+    // faça qualquer lógica que deva acontecer em um método \`onCreate\`, por exemplo:
+    // customView.onCreate(savedInstanceState);
+  }
+
+  override fun onPause() {
+    super.onPause()
+    // faça qualquer lógica que deveria acontecer em um método \`onPause\`
+    // por exemplo: customView.onPause();
+  }
+
+  override fun onResume() {
+    super.onResume()
+    // faz qualquer lógica que deveria acontecer em um método \`onResume\`
+    // por exemplo: customView.onResume();
+  }
+
+  override fun onDestroy() {
+    super.onDestroy()
+    // faça qualquer lógica que deveria acontecer em um método \`onDestroy\`
+    // por exemplo: customView.onDestroy();
+  }
+}

3. Crie a subclasse ViewManager

java
// replace with your package
+package com.mypackage;
+
+import android.view.Choreographer;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.FrameLayout;
+
+import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
+import androidx.fragment.app.FragmentActivity;
+
+import com.facebook.react.bridge.ReactApplicationContext;
+import com.facebook.react.bridge.ReadableArray;
+import com.facebook.react.common.MapBuilder;
+import com.facebook.react.uimanager.annotations.ReactProp;
+import com.facebook.react.uimanager.annotations.ReactPropGroup;
+import com.facebook.react.uimanager.ViewGroupManager;
+import com.facebook.react.uimanager.ThemedReactContext;
+
+import java.util.Map;
+
+public class MyViewManager extends ViewGroupManager<FrameLayout> {
+
+  public static final String REACT_CLASS = "MyViewManager";
+  public final int COMMAND_CREATE = 1;
+  private int propWidth;
+  private int propHeight;
+
+  ReactApplicationContext reactContext;
+
+  public MyViewManager(ReactApplicationContext reactContext) {
+    this.reactContext = reactContext;
+  }
+
+  @Override
+  public String getName() {
+    return REACT_CLASS;
+  }
+
+  /**
+   * Return a FrameLayout which will later hold the Fragment
+   */
+  @Override
+  public FrameLayout createViewInstance(ThemedReactContext reactContext) {
+    return new FrameLayout(reactContext);
+  }
+
+  /**
+   * Map the "create" command to an integer
+   */
+  @Nullable
+  @Override
+  public Map<String, Integer> getCommandsMap() {
+    return MapBuilder.of("create", COMMAND_CREATE);
+  }
+
+  /**
+   * Handle "create" command (called from JS) and call createFragment method
+   */
+  @Override
+  public void receiveCommand(
+    @NonNull FrameLayout root,
+    String commandId,
+    @Nullable ReadableArray args
+  ) {
+    super.receiveCommand(root, commandId, args);
+    int reactNativeViewId = args.getInt(0);
+    int commandIdInt = Integer.parseInt(commandId);
+
+    switch (commandIdInt) {
+      case COMMAND_CREATE:
+        createFragment(root, reactNativeViewId);
+        break;
+      default: {}
+    }
+  }
+
+  @ReactPropGroup(names = {"width", "height"}, customType = "Style")
+  public void setStyle(FrameLayout view, int index, Integer value) {
+    if (index == 0) {
+      propWidth = value;
+    }
+
+    if (index == 1) {
+      propHeight = value;
+    }
+  }
+
+  /**
+   * Replace your React Native view with a custom fragment
+   */
+  public void createFragment(FrameLayout root, int reactNativeViewId) {
+    ViewGroup parentView = (ViewGroup) root.findViewById(reactNativeViewId);
+    setupLayout(parentView);
+
+    final MyFragment myFragment = new MyFragment();
+    FragmentActivity activity = (FragmentActivity) reactContext.getCurrentActivity();
+    activity.getSupportFragmentManager()
+            .beginTransaction()
+            .replace(reactNativeViewId, myFragment, String.valueOf(reactNativeViewId))
+            .commit();
+  }
+
+  public void setupLayout(View view) {
+    Choreographer.getInstance().postFrameCallback(new Choreographer.FrameCallback() {
+      @Override
+      public void doFrame(long frameTimeNanos) {
+        manuallyLayoutChildren(view);
+        view.getViewTreeObserver().dispatchOnGlobalLayout();
+        Choreographer.getInstance().postFrameCallback(this);
+      }
+    });
+  }
+
+  /**
+   * Layout all children properly
+   */
+  public void manuallyLayoutChildren(View view) {
+      // propWidth and propHeight coming from react-native props
+      int width = propWidth;
+      int height = propHeight;
+
+      view.measure(
+              View.MeasureSpec.makeMeasureSpec(width, View.MeasureSpec.EXACTLY),
+              View.MeasureSpec.makeMeasureSpec(height, View.MeasureSpec.EXACTLY));
+
+      view.layout(0, 0, width, height);
+  }
+}
kt
// substitua pelo seu pacote
+package com.mypackage
+
+import android.view.Choreographer
+import android.view.View
+import android.view.ViewGroup
+import android.widget.FrameLayout
+import androidx.fragment.app.FragmentActivity
+import com.facebook.react.bridge.ReactApplicationContext
+import com.facebook.react.bridge.ReadableArray
+import com.facebook.react.uimanager.ThemedReactContext
+import com.facebook.react.uimanager.ViewGroupManager
+import com.facebook.react.uimanager.annotations.ReactPropGroup
+
+class MyViewManager(
+    private val reactContext: ReactApplicationContext
+) : ViewGroupManager<FrameLayout>() {
+  private var propWidth: Int? = null
+  private var propHeight: Int? = null
+
+  override fun getName() = REACT_CLASS
+
+  /**
+   * Retorne um FrameLayout que posteriormente conterá o Fragment
+   */
+  override fun createViewInstance(reactContext: ThemedReactContext) =
+      FrameLayout(reactContext)
+
+  /**
+   * Mapeie o comando "create" para um número inteiro
+   */
+  override fun getCommandsMap() = mapOf("create" to COMMAND_CREATE)
+
+  /**
+   * Lidar com o comando "create" (chamado de JS) e chamar o método createFragment
+   */
+  override fun receiveCommand(
+      root: FrameLayout,
+      commandId: String,
+      args: ReadableArray?
+  ) {
+    super.receiveCommand(root, commandId, args)
+    val reactNativeViewId = requireNotNull(args).getInt(0)
+
+    when (commandId.toInt()) {
+      COMMAND_CREATE -> createFragment(root, reactNativeViewId)
+    }
+  }
+
+  @ReactPropGroup(names = ["width", "height"], customType = "Style")
+  fun setStyle(view: FrameLayout, index: Int, value: Int) {
+    if (index == 0) propWidth = value
+    if (index == 1) propHeight = value
+  }
+
+  /**
+   * Substitua sua visualização React Native por um fragmento personalizado
+   */
+  fun createFragment(root: FrameLayout, reactNativeViewId: Int) {
+    val parentView = root.findViewById<ViewGroup>(reactNativeViewId)
+    setupLayout(parentView)
+
+    val myFragment = MyFragment()
+    val activity = reactContext.currentActivity as FragmentActivity
+    activity.supportFragmentManager
+        .beginTransaction()
+        .replace(reactNativeViewId, myFragment, reactNativeViewId.toString())
+        .commit()
+  }
+
+  fun setupLayout(view: View) {
+    Choreographer.getInstance().postFrameCallback(object: Choreographer.FrameCallback {
+      override fun doFrame(frameTimeNanos: Long) {
+        manuallyLayoutChildren(view)
+        view.viewTreeObserver.dispatchOnGlobalLayout()
+        Choreographer.getInstance().postFrameCallback(this)
+      }
+    })
+  }
+
+  /**
+   * Disponha todas as crianças corretamente
+   */
+  private fun manuallyLayoutChildren(view: View) {
+    // propWidth e propHeight provenientes de adereços nativos de do react
+    val width = requireNotNull(propWidth)
+    val height = requireNotNull(propHeight)
+
+    view.measure(
+        View.MeasureSpec.makeMeasureSpec(width, View.MeasureSpec.EXACTLY),
+        View.MeasureSpec.makeMeasureSpec(height, View.MeasureSpec.EXACTLY))
+
+    view.layout(0, 0, width, height)
+  }
+
+  companion object {
+    private const val REACT_CLASS = "MyViewManager"
+    private const val COMMAND_CREATE = 1
+  }
+}

4. Cadastre o ViewManager

java
// replace with your package
+package com.mypackage;
+
+import com.facebook.react.ReactPackage;
+import com.facebook.react.bridge.ReactApplicationContext;
+import com.facebook.react.uimanager.ViewManager;
+
+import java.util.Arrays;
+import java.util.List;
+
+public class MyPackage implements ReactPackage {
+
+   @Override
+   public List<ViewManager> createViewManagers(ReactApplicationContext reactContext) {
+       return Arrays.<ViewManager>asList(
+            new MyViewManager(reactContext)
+       );
+   }
+
+}
kt
// substitua pelo seu pacote
+package com.mypackage
+
+import com.facebook.react.ReactPackage
+import com.facebook.react.bridge.ReactApplicationContext
+import com.facebook.react.uimanager.ViewManager
+
+class MyPackage : ReactPackage {
+  ...
+  override fun createViewManagers(
+      reactContext: ReactApplicationContext
+  ) = listOf(MyViewManager(reactContext))
+}

5. Registre o Package

java
@Override
+protected List<ReactPackage> getPackages() {
+  List<ReactPackage> packages = new PackageList(this).getPackages();
+  ...
+  packages.add(new MyPackage());
+  return packages;
+}
kt
override fun getPackages() = PackageList(this).packages.apply {
+  add(MyPackage())
+}

6. Implemente o módulo JavaScript

I. Comece com o gerenciador de visualização personalizado:

tsx
// MyViewManager.tsx
+
+import {requireNativeComponent} from 'react-native';
+
+export const MyViewManager =
+  requireNativeComponent('MyViewManager');

II. Em seguida, implemente a View personalizada chamando o método create:

tsx
import React, {useEffect, useRef} from 'react';
+import {
+  PixelRatio,
+  UIManager,
+  findNodeHandle,
+} from 'react-native';
+
+import {MyViewManager} from './my-view-manager';
+
+const createFragment = viewId =>
+  UIManager.dispatchViewManagerCommand(
+    viewId,
+    // estamos chamando o comando 'criar'
+    UIManager.MyViewManager.Commands.create.toString(),
+    [viewId],
+  );
+
+export const MyView = () => {
+  const ref = useRef(null);
+
+  useEffect(() => {
+    const viewId = findNodeHandle(ref.current);
+    createFragment(viewId);
+  }, []);
+
+  return (
+    <MyViewManager
+      style={{
+        // converte dpi em px, fornece a altura desejada
+        height: PixelRatio.getPixelSizeForLayoutSize(200),
+        // converte dpi em px, fornece a largura desejada
+        width: PixelRatio.getPixelSizeForLayoutSize(200),
+      }}
+      ref={ref}
+    />
+  );
+};

Se você deseja expor configuradores de propriedades usando a anotação @ReactProp (ou @ReactPropGroup), consulte o exemplo ImageView acima.

`,57),t=[p];function l(h,k,r,E,d,o){return a(),i("div",null,t)}const y=s(e,[["render",l]]);export{c as __pageData,y as default}; diff --git a/vitepress/docs/.vitepress/dist/assets/docs_native-components-android.md.D-fmrhIe.lean.js b/vitepress/docs/.vitepress/dist/assets/docs_native-components-android.md.D-fmrhIe.lean.js new file mode 100644 index 0000000..400243d --- /dev/null +++ b/vitepress/docs/.vitepress/dist/assets/docs_native-components-android.md.D-fmrhIe.lean.js @@ -0,0 +1 @@ +import{_ as s,c as i,o as a,a4 as n}from"./chunks/framework.nQaBHiNx.js";const c=JSON.parse('{"title":"Componentes de IU nativos do Android","description":"","frontmatter":{},"headers":[],"relativePath":"docs/native-components-android.md","filePath":"docs/native-components-android.md"}'),e={name:"docs/native-components-android.md"},p=n("",57),t=[p];function l(h,k,r,E,d,o){return a(),i("div",null,t)}const y=s(e,[["render",l]]);export{c as __pageData,y as default}; diff --git a/vitepress/docs/.vitepress/dist/assets/docs_native-components-ios.md.y8UW3Fo9.js b/vitepress/docs/.vitepress/dist/assets/docs_native-components-ios.md.y8UW3Fo9.js new file mode 100644 index 0000000..6403b02 --- /dev/null +++ b/vitepress/docs/.vitepress/dist/assets/docs_native-components-ios.md.y8UW3Fo9.js @@ -0,0 +1,336 @@ +import{_ as s,c as i,o as a,a4 as n}from"./chunks/framework.nQaBHiNx.js";const g=JSON.parse('{"title":"Componentes de UI nativos do iOS","description":"","frontmatter":{},"headers":[],"relativePath":"docs/native-components-ios.md","filePath":"docs/native-components-ios.md"}'),e={name:"docs/native-components-ios.md"},p=n(`

Componentes de UI nativos do iOS

INFORMAÇÕES

Módulo Nativo e Componentes Nativos são nossas tecnologias estáveis usadas pela arquitetura legada. Eles serão descontinuados no futuro, quando a Nova Arquitetura estiver estável. A nova arquitetura usa Turbo Native Module e Fabric Native Components para obter resultados semelhantes.

Existem muitos widgets de UI nativos prontos para serem usados nos aplicativos mais recentes - alguns deles fazem parte da plataforma, outros estão disponíveis como bibliotecas de terceiros e ainda mais podem estar em uso em seu próprio portfólio. React Native tem vários dos componentes de plataforma mais críticos já empacotados, como ScrollView e TextInput, mas não todos eles, e certamente não aqueles que você mesmo possa ter escrito para um aplicativo anterior. Felizmente, podemos agrupar esses componentes existentes para uma integração perfeita com seu aplicativo React Native.

Assim como o guia do módulo nativo, este também é um guia mais avançado que pressupõe que você esteja familiarizado com a programação iOS. Este guia mostrará como construir um componente de UI nativo, orientando você na implementação de um subconjunto do componente MapView existente disponível na biblioteca principal do React Native.

Exemplo de MapView para iOS

Digamos que queremos adicionar um mapa interativo ao nosso aplicativo - podemos também usar MKMapView, só precisamos torná-lo utilizável a partir de JavaScript.

As visualizações nativas são criadas e manipuladas por subclasses de RCTViewManager. Essas subclasses são semelhantes em função aos controladores de visualização, mas são essencialmente singletons - apenas uma instância de cada é criada pela ponte. Eles expõem visualizações nativas ao RCTUIManager, que delega a eles a definição e atualização das propriedades das visualizações conforme necessário. Os RCTViewManagers também são normalmente os delegados das visualizações, enviando eventos de volta ao JavaScript por meio da ponte.

Para expor uma visualização, você pode:

  • Subclasse RCTViewManager para criar um gerenciador para seu componente.
  • Adicione a macro do marcador RCT_EXPORT_MODULE().
  • Implemente o método -(UIView *)view.
c
// RNTMapManager.m
+
+#import <MapKit/MapKit.h>
+
+#import <React/RCTViewManager.h>
+
+@interface RNTMapManager : RCTViewManager
+@end
+
+@implementation RNTMapManager
+
+RCT_EXPORT_MODULE(RNTMap)
+
+- (UIView *)view
+{
+  return [[MKMapView alloc] init];
+}
+
+@end

OBSERVAÇÃO

Não tente definir as propriedades frame ou backgroundColor na instância UIView que você expõe por meio do método -view. O React Native substituirá os valores definidos pela sua classe personalizada para corresponder aos adereços de layout do seu componente JavaScript. Se você precisar dessa granularidade de controle, talvez seja melhor agrupar a instância do UIView que você deseja estilizar em outro UIView e retornar o UIView do wrapper. Consulte a edição 2948 para obter mais contexto.

DICA

No exemplo acima, prefixamos nosso nome de classe com RNT. Os prefixos são usados para evitar colisões de nomes com outras estruturas. As estruturas Apple usam prefixos de duas letras e o React Native usa RCT como prefixo. Para evitar colisões de nomes, recomendamos usar um prefixo de três letras diferente de RCT em suas próprias classes.

Então você precisa de um pouco de JavaScript para tornar este um componente React utilizável:

tsx
// MapView.tsx
+
+import {requireNativeComponent} from 'react-native';
+
+// requireNativeComponent resolve automaticamente 'RNTMap' para 'RNTMapManager'
+module.exports = requireNativeComponent('RNTMap');
tsx
// MyApp.tsx
+
+import MapView from './MapView.tsx';
+
+...
+
+render() {
+  return <MapView style={{flex: 1}} />;
+}

Certifique-se de usar RNTMap aqui. Queremos exigir o gerenciador aqui, que irá expor a visão do nosso gerenciador para uso em JavaScript.

OBSERVAÇÃO

Ao renderizar, não se esqueça de esticar a visualização, caso contrário você estará olhando para uma tela em branco.

tsx
  render() {
+    return <MapView style={{flex: 1}} />;
+  }

Este é agora um componente de visualização de mapa nativo totalmente funcional em JavaScript, completo com zoom de pinça e outros suportes a gestos nativos. Ainda não podemos controlá-lo a partir do JavaScript 😦

Propriedades

A primeira coisa que podemos fazer para tornar este componente mais utilizável é conectar algumas propriedades nativas. Digamos que queremos desabilitar o zoom e especificar a região visível. Desativar o zoom é um booleano, então adicionamos esta linha:

c
// RNTMapManager.m
+
+RCT_EXPORT_VIEW_PROPERTY(zoomEnabled, BOOL)

Observe que especificamos explicitamente o tipo como BOOL - React Native usa RCTConvert nos bastidores para converter todos os tipos de tipos de dados diferentes ao falar pela ponte, e valores incorretos mostrarão erros "RedBox" convenientes para que você saiba que há um problema o mais rápido possível . Quando as coisas são simples assim, toda a implementação é feita por esta macro.

Agora, para realmente desabilitar o zoom, definimos a propriedade em JS:

tsx
// MyApp.tsx
+
+<MapView zoomEnabled={false} style={{flex: 1}} />

Para documentar as propriedades (e quais valores elas aceitam) do nosso componente MapView, adicionaremos um componente wrapper e documentaremos a interface com React PropTypes:

tsx
// MapView.tsx
+
+import PropTypes from 'prop-types';
+import React from 'react';
+import {requireNativeComponent} from 'react-native';
+
+class MapView extends React.Component {
+  render() {
+    return <RNTMap {...this.props} />;
+  }
+}
+
+MapView.propTypes = {
+  /**
+   * Um valor booleano que determina se o usuário pode usar pinçar
+   * gestos para aumentar e diminuir o zoom do mapa.
+   */
+  zoomEnabled: PropTypes.bool,
+};
+
+const RNTMap = requireNativeComponent('RNTMap');
+
+module.exports = MapView;

Agora temos um componente wrapper bem documentado para trabalhar.

A seguir, vamos adicionar a propriedade de region mais complexa. Começamos adicionando o código nativo:

c
// RNTMapManager.m
+
+RCT_CUSTOM_VIEW_PROPERTY(region, MKCoordinateRegion, MKMapView)
+{
+  [view setRegion:json ? [RCTConvert MKCoordinateRegion:json] : defaultView.region animated:YES];
+}

Ok, isso é mais complicado do que o caso BOOL que tivemos antes. Agora temos um tipo MKCoordenRegion que precisa de uma função de conversão e temos um código personalizado para que a visualização seja animada quando definirmos a região de JS. Dentro do corpo da função que fornecemos, json refere-se ao valor bruto que foi passado de JS. Há também uma variável de visualização que nos dá acesso à instância de visualização do gerenciador e um defaultView que usamos para redefinir a propriedade de volta ao valor padrão se JS nos enviar um sentinela nulo.

Você pode escrever qualquer função de conversão que desejar para sua visualização - aqui está a implementação de MKCoordenRegion por meio de uma categoria no RCTConvert. Ele usa uma categoria já existente de ReactNative RCTConvert+CoreLocation:

c
// RNTMapManager.m
+
+#import "RCTConvert+Mapkit.h"
c
RCTConvert+Mapkit.h
+#import <MapKit/MapKit.h>
+#import <React/RCTConvert.h>
+#import <CoreLocation/CoreLocation.h>
+#import <React/RCTConvert+CoreLocation.h>
+
+@interface RCTConvert (Mapkit)
+
++ (MKCoordinateSpan)MKCoordinateSpan:(id)json;
++ (MKCoordinateRegion)MKCoordinateRegion:(id)json;
+
+@end
+
+@implementation RCTConvert(MapKit)
+
++ (MKCoordinateSpan)MKCoordinateSpan:(id)json
+{
+  json = [self NSDictionary:json];
+  return (MKCoordinateSpan){
+    [self CLLocationDegrees:json[@"latitudeDelta"]],
+    [self CLLocationDegrees:json[@"longitudeDelta"]]
+  };
+}
+
++ (MKCoordinateRegion)MKCoordinateRegion:(id)json
+{
+  return (MKCoordinateRegion){
+    [self CLLocationCoordinate2D:json],
+    [self MKCoordinateSpan:json]
+  };
+}
+
+@end

Essas funções de conversão são projetadas para processar com segurança qualquer JSON que o JS possa lançar neles, exibindo erros "RedBox" e retornando valores de inicialização padrão quando chaves ausentes ou outros erros do desenvolvedor são encontrados.

Para finalizar o suporte para a propriedade region, precisamos documentá-la em propTypes:

tsx
// MapView.tsx
+
+MapView.propTypes = {
+  /**
+   * Um valor booleano que determina se o usuário pode usar o gesto de pinça
+   * para aumentar e diminuir o zoom do mapa.
+   */
+  zoomEnabled: PropTypes.bool,
+
+  /**
+   * A região a ser exibida pelo mapa.
+   *
+   * A região é definida pelas coordenadas do centro e pela extensão do
+   * coordenadas a serem exibidas.
+   */
+  region: PropTypes.shape({
+    /**
+     * Coordenadas para o centro do mapa.
+     */
+    latitude: PropTypes.number.isRequired,
+    longitude: PropTypes.number.isRequired,
+
+    /**
+     * Distância entre a latitude/longitude mínima e máxima
+     * a ser exibida.
+     */
+    latitudeDelta: PropTypes.number.isRequired,
+    longitudeDelta: PropTypes.number.isRequired,
+  }),
+};
tsx
// MyApp.tsx
+
+render() {
+  const region = {
+    latitude: 37.48,
+    longitude: -122.16,
+    latitudeDelta: 0.1,
+    longitudeDelta: 0.1,
+  };
+  return (
+    <MapView
+      region={region}
+      zoomEnabled={false}
+      style={{flex: 1}}
+    />
+  );
+}

Aqui você pode ver que o formato da região está explícito na documentação JS.

Eventos

Portanto, agora temos um componente de mapa nativo que podemos controlar livremente a partir de JS, mas como lidamos com eventos do usuário, como pinçar zoom ou panorâmica para alterar a região visível?

Até agora, retornamos apenas uma instância MKMapView do método -(UIView *)view do nosso gerente. Não podemos adicionar novas propriedades ao MKMapView, então temos que criar uma nova subclasse do MKMapView que usaremos para nossa View. Podemos então adicionar um retorno de chamada onRegionChange nesta subclasse:

c
// RNTMapView.h
+
+#import <MapKit/MapKit.h>
+
+#import <React/RCTComponent.h>
+
+@interface RNTMapView: MKMapView
+
+@property (nonatomic, copy) RCTBubblingEventBlock onRegionChange;
+
+@end
c
// RNTMapView.m
+
+#import "RNTMapView.h"
+
+@implementation RNTMapView
+
+@end

Observe que todos os RCTBubblingEventBlock devem ser prefixados com on. Em seguida, declare uma propriedade de manipulador de eventos em RNTMapManager, torne-a um delegado para todas as visualizações que expõe e encaminhe eventos para JS chamando o bloco do manipulador de eventos a partir da visualização nativa.

c
// RNTMapManager.m
+
+#import <MapKit/MapKit.h>
+#import <React/RCTViewManager.h>
+
+#import "RNTMapView.h"
+#import "RCTConvert+Mapkit.h"
+
+@interface RNTMapManager : RCTViewManager <MKMapViewDelegate>
+@end
+
+@implementation RNTMapManager
+
+RCT_EXPORT_MODULE()
+
+RCT_EXPORT_VIEW_PROPERTY(zoomEnabled, BOOL)
+RCT_EXPORT_VIEW_PROPERTY(onRegionChange, RCTBubblingEventBlock)
+
+RCT_CUSTOM_VIEW_PROPERTY(region, MKCoordinateRegion, MKMapView)
+{
+  [view setRegion:json ? [RCTConvert MKCoordinateRegion:json] : defaultView.region animated:YES];
+}
+
+- (UIView *)view
+{
+  RNTMapView *map = [RNTMapView new];
+  map.delegate = self;
+  return map;
+}
+
+#pragma mark MKMapViewDelegate
+
+- (void)mapView:(RNTMapView *)mapView regionDidChangeAnimated:(BOOL)animated
+{
+  if (!mapView.onRegionChange) {
+    return;
+  }
+
+  MKCoordinateRegion region = mapView.region;
+  mapView.onRegionChange(@{
+    @"region": @{
+      @"latitude": @(region.center.latitude),
+      @"longitude": @(region.center.longitude),
+      @"latitudeDelta": @(region.span.latitudeDelta),
+      @"longitudeDelta": @(region.span.longitudeDelta),
+    }
+  });
+}
+@end

No método delegado -mapView:regionDidChangeAnimated: o bloco manipulador de eventos é chamado na visualização correspondente com os dados da região. Chamar o bloco do manipulador de eventos onRegionChange resulta na chamada do mesmo suporte de retorno de chamada em JavaScript. Esse retorno de chamada é invocado com o evento bruto, que normalmente processamos no componente wrapper para simplificar a API:

tsx
MapView.tsx
+class MapView extends React.Component {
+  _onRegionChange = event => {
+    if (!this.props.onRegionChange) {
+      return;
+    }
+
+    // processar evento bruto...
+    this.props.onRegionChange(event.nativeEvent);
+  };
+  render() {
+    return (
+      <RNTMap
+        {...this.props}
+        onRegionChange={this._onRegionChange}
+      />
+    );
+  }
+}
+MapView.propTypes = {
+  /**
+   * Retorno de chamada que é chamado continuamente quando o usuário arrasta o mapa.
+   */
+  onRegionChange: PropTypes.func,
+  ...
+};
tsx
// MyApp.tsx
+
+class MyApp extends React.Component {
+  onRegionChange(event) {
+    // Faça coisas com event.region.latitude, etc.
+  }
+
+  render() {
+    const region = {
+      latitude: 37.48,
+      longitude: -122.16,
+      latitudeDelta: 0.1,
+      longitudeDelta: 0.1,
+    };
+    return (
+      <MapView
+        region={region}
+        zoomEnabled={false}
+        onRegionChange={this.onRegionChange}
+      />
+    );
+  }
+}

Lidando com múltiplas visualizações nativas

Uma visualização React Native pode ter mais de uma visualização filha na árvore de visualização, por exemplo.

tsx
<View>
+  <MyNativeView />
+  <MyNativeView />
+  <Button />
+</View>

Neste exemplo, a classe MyNativeView é um wrapper para 'NativeComponente expõe métodos que serão chamados na plataforma iOS.MyNativeViewé definido emMyNativeView.ios.jse contém métodos proxy deNativeComponent\`.

Quando o usuário interage com o componente, como clicar no botão, a backgroundColor de MyNativeView muda. Nesse caso, o UIManager não saberia qual MyNativeView deveria ser tratado e qual deveria mudar backgroundColor. Abaixo você encontrará uma solução para este problema:

tsx
<View>
+  <MyNativeView ref={this.myNativeReference} />
+  <MyNativeView ref={this.myNativeReference2} />
+  <Button
+    onPress={() => {
+      this.myNativeReference.callNativeMethod();
+    }}
+  />
+</View>

Agora, o componente acima tem uma referência a um MyNativeView específico que nos permite usar uma instância específica de MyNativeView. Agora o botão pode controlar qual MyNativeView deve alterar sua cor de fundo. Neste exemplo, vamos supor que callNativeMethod altere backgroundColor.

tsx
MyNativeView.ios.tsx
+class MyNativeView extends React.Component {
+  callNativeMethod = () => {
+    UIManager.dispatchViewManagerCommand(
+      ReactNative.findNodeHandle(this),
+      UIManager.getViewManagerConfig('RNCMyNativeView').Commands
+        .callNativeMethod,
+      [],
+    );
+  };
+
+  render() {
+    return <NativeComponent ref={NATIVE_COMPONENT_REF} />;
+  }
+}

callNativeMethod é nosso método iOS personalizado que, por exemplo, altera o backgroundColor que é exposto por meio de MyNativeView. Este método usa UIManager.dispatchViewManagerCommand que precisa de 3 parâmetros:

  • (nonnull NSNumber \\*)reactTag  -  id da visualização de reação.
  • commandID:(NSInteger)commandID  -  Id do método nativo que deve ser chamado
  • commandArgs:(NSArray<id> \\*)commandArgs  -  Args do método nativo que podemos passar de JS para nativo.
c
// RNCMyNativeViewManager.m
+
+#import <React/RCTViewManager.h>
+#import <React/RCTUIManager.h>
+#import <React/RCTLog.h>
+
+RCT_EXPORT_METHOD(callNativeMethod:(nonnull NSNumber*) reactTag) {
+    [self.bridge.uiManager addUIBlock:^(RCTUIManager *uiManager, NSDictionary<NSNumber *,UIView *> *viewRegistry) {
+        NativeView *view = viewRegistry[reactTag];
+        if (!view || ![view isKindOfClass:[NativeView class]]) {
+            RCTLogError(@"Cannot find NativeView with tag #%@", reactTag);
+            return;
+        }
+        [view callNativeMethod];
+    }];
+
+}

Aqui, o callNativeMethod' é definido no arquivo RNCMyNativeViewManager.me contém apenas um parâmetro que é(nonnull NSNumber*) reactTag. Esta função exportada encontrará uma visualização específica usando addUIBlockque contém o parâmetroviewRegistrye retorna o componente baseado emreactTag\` permitindo chamar o método no componente correto.

Estilos

Como todas as nossas visualizações de reação nativas são subclasses de UIView, a maioria dos atributos de estilo funcionarão como você esperaria imediatamente. Alguns componentes irão querer um estilo padrão, por exemplo UIDatePicker que é um tamanho fixo. Esse estilo padrão é importante para que o algoritmo de layout funcione conforme o esperado, mas também queremos poder substituir o estilo padrão ao usar o componente. DatePickerIOS faz isso agrupando o componente nativo em uma visualização extra, que possui estilo flexível, e usando um estilo fixo (que é gerado com constantes passadas do nativo) no componente nativo interno:

tsx
// DatePickerIOS.ios.tsx
+
+import {UIManager} from 'react-native';
+const RCTDatePickerIOSConsts = UIManager.RCTDatePicker.Constants;
+...
+  render: function() {
+    return (
+      <View style={this.props.style}>
+        <RCTDatePickerIOS
+          ref={DATEPICKER}
+          style={styles.rkDatePickerIOS}
+          ...
+        />
+      </View>
+    );
+  }
+});
+
+const styles = StyleSheet.create({
+  rkDatePickerIOS: {
+    height: RCTDatePickerIOSConsts.ComponentHeight,
+    width: RCTDatePickerIOSConsts.ComponentWidth,
+  },
+});

As constantes RCTDatePickerIOSConsts são exportadas do nativo capturando o quadro real do componente nativo da seguinte forma:

c
// RCTDatePickerManager.m
+
+- (NSDictionary *)constantsToExport
+{
+  UIDatePicker *dp = [[UIDatePicker alloc] init];
+  [dp layoutIfNeeded];
+
+  return @{
+    @"ComponentHeight": @(CGRectGetHeight(dp.frame)),
+    @"ComponentWidth": @(CGRectGetWidth(dp.frame)),
+    @"DatePickerModes": @{
+      @"time": @(UIDatePickerModeTime),
+      @"date": @(UIDatePickerModeDate),
+      @"datetime": @(UIDatePickerModeDateAndTime),
+    }
+  };
+}

Este guia abordou muitos dos aspectos da ponte sobre componentes nativos personalizados, mas há ainda mais que você pode precisar considerar, como ganchos personalizados para inserir e organizar subvisualizações. Se quiser se aprofundar ainda mais, confira o código-fonte de alguns dos componentes implementados.

`,67),l=[p];function t(h,k,o,r,d,E){return a(),i("div",null,l)}const y=s(e,[["render",t]]);export{g as __pageData,y as default}; diff --git a/vitepress/docs/.vitepress/dist/assets/docs_native-components-ios.md.y8UW3Fo9.lean.js b/vitepress/docs/.vitepress/dist/assets/docs_native-components-ios.md.y8UW3Fo9.lean.js new file mode 100644 index 0000000..894dc0a --- /dev/null +++ b/vitepress/docs/.vitepress/dist/assets/docs_native-components-ios.md.y8UW3Fo9.lean.js @@ -0,0 +1 @@ +import{_ as s,c as i,o as a,a4 as n}from"./chunks/framework.nQaBHiNx.js";const g=JSON.parse('{"title":"Componentes de UI nativos do iOS","description":"","frontmatter":{},"headers":[],"relativePath":"docs/native-components-ios.md","filePath":"docs/native-components-ios.md"}'),e={name:"docs/native-components-ios.md"},p=n("",67),l=[p];function t(h,k,o,r,d,E){return a(),i("div",null,l)}const y=s(e,[["render",t]]);export{g as __pageData,y as default}; diff --git a/vitepress/docs/.vitepress/dist/assets/docs_native-debugging.md.BUnmSub-.js b/vitepress/docs/.vitepress/dist/assets/docs_native-debugging.md.BUnmSub-.js new file mode 100644 index 0000000..f9e5c1e --- /dev/null +++ b/vitepress/docs/.vitepress/dist/assets/docs_native-debugging.md.BUnmSub-.js @@ -0,0 +1 @@ +import{_ as o,c as a,o as e,a4 as t}from"./chunks/framework.nQaBHiNx.js";const g=JSON.parse('{"title":"Debug Nativo","description":"","frontmatter":{},"headers":[],"relativePath":"docs/native-debugging.md","filePath":"docs/native-debugging.md"}'),i={name:"docs/native-debugging.md"},s=t('

Debug Nativo

Projetos com somente código nativo

A seção a seguir se aplica apenas a projetos com código nativo exposto. Se você estiver usando o fluxo de trabalho gerenciado da Expo, consulte o guia sobre pré-construção para usar esta API.

Acessando logs nativos

Você pode exibir os logs do console de um aplicativo iOS ou Android usando os seguintes comandos em um terminal enquanto o aplicativo está em execução:

bash
npx react-native log-android
bash
npx react-native log-ios

Você também pode acessá-los por meio de Debug > Open System Log… no iOS Simulator ou executando adb logcat "*:S" ReactNative:V ReactNativeJS:V em um terminal enquanto um aplicativo Android está sendo executado em um dispositivo ou emulador.

INFORMAÇÕES

Se você estiver usando o Expo CLI, os logs do console já aparecerão na mesma saída do terminal que o empacotador.

Depurando código nativo

Ao trabalhar com código nativo, como ao escrever módulos nativos, você pode iniciar o aplicativo no Android Studio ou Xcode e aproveitar as vantagens dos recursos de depuração nativos (configuração de pontos de interrupção etc.), como faria no caso de criar um aplicativo nativo padrão. .

Outra opção é executar seu aplicativo usando a CLI React Native e anexar o depurador nativo do IDE nativo (Android Studio ou Xcode) ao processo.

Android Studio

No Android Studio você pode fazer isso acessando a opção "Run" na barra de menu, clicando em "Attach to Process..." e selecionando o aplicativo React Native em execução.

Xcode

No Xcode clique em "Debug" na barra de menu superior, selecione a opção "Attach to process" e selecione o aplicativo na lista de "Likely Targets".

',14),n=[s];function d(c,r,l,p,u,h){return e(),a("div",null,n)}const m=o(i,[["render",d]]);export{g as __pageData,m as default}; diff --git a/vitepress/docs/.vitepress/dist/assets/docs_native-debugging.md.BUnmSub-.lean.js b/vitepress/docs/.vitepress/dist/assets/docs_native-debugging.md.BUnmSub-.lean.js new file mode 100644 index 0000000..21f9aaa --- /dev/null +++ b/vitepress/docs/.vitepress/dist/assets/docs_native-debugging.md.BUnmSub-.lean.js @@ -0,0 +1 @@ +import{_ as o,c as a,o as e,a4 as t}from"./chunks/framework.nQaBHiNx.js";const g=JSON.parse('{"title":"Debug Nativo","description":"","frontmatter":{},"headers":[],"relativePath":"docs/native-debugging.md","filePath":"docs/native-debugging.md"}'),i={name:"docs/native-debugging.md"},s=t("",14),n=[s];function d(c,r,l,p,u,h){return e(),a("div",null,n)}const m=o(i,[["render",d]]);export{g as __pageData,m as default}; diff --git a/vitepress/docs/.vitepress/dist/assets/docs_native-modules-android.md.BI96nnL8.js b/vitepress/docs/.vitepress/dist/assets/docs_native-modules-android.md.BI96nnL8.js new file mode 100644 index 0000000..edc1ade --- /dev/null +++ b/vitepress/docs/.vitepress/dist/assets/docs_native-modules-android.md.BI96nnL8.js @@ -0,0 +1,506 @@ +import{_ as s,c as i,o as a,a4 as n}from"./chunks/framework.nQaBHiNx.js";const e="/assets/313493455-1a5c12f5-6368-4675-af20-051a7cb2598b.CjOJ3DU1.png",t="/assets/313493538-f05df190-b27f-4511-8554-ee5dc86efcb2.DAi3nME1.png",l="/assets/313495844-578b6da9-b01c-4b00-a7fb-9bd4be45b912.wiOJK8eL.png",p="/assets/313500818-99069c93-a869-4b6e-bb50-b101c0c029ad.C5DJ4UvH.png",m=JSON.parse('{"title":"Módulos nativos do Android","description":"","frontmatter":{},"headers":[],"relativePath":"docs/native-modules-android.md","filePath":"docs/native-modules-android.md"}'),h={name:"docs/native-modules-android.md"},k=n('

Módulos nativos do Android

INFORMAÇÕES

Módulo Nativo e Componentes Nativos são nossas tecnologias estáveis usadas pela arquitetura legada. Eles serão descontinuados no futuro, quando a Nova Arquitetura estiver estável. A nova arquitetura usa Turbo Native Module e Fabric Native Components para obter resultados semelhantes.

Bem-vindo aos Módulos Nativos para Android. Comece lendo a introdução aos módulos nativos para obter uma introdução ao que são os módulos nativos.

Crie um módulo nativo de calendário

No guia a seguir você criará um módulo nativo, CalendarModule, que permitirá acessar APIs de calendário do Android a partir de JavaScript. Ao final, você poderá chamar CalendarModule.createCalendarEvent('Dinner Party', 'My House'); do JavaScript, invocando um método Java/Kotlin que cria um evento de calendário.

Configurar

Para começar, abra o projeto Android em seu aplicativo React Native no Android Studio. Você pode encontrar seu projeto Android aqui em um aplicativo React Native:

Imagem de onde você pode encontrar seu projeto Android

Recomendamos usar o Android Studio para escrever seu código nativo. Android Studio é um IDE desenvolvido para desenvolvimento Android e usá-lo ajudará você a resolver pequenos problemas, como erros de sintaxe de código, rapidamente.

Também recomendamos ativar o Gradle Daemon para acelerar as compilações conforme você itera no código Java/Kotlin.

Crie um arquivo de módulo nativo personalizado

A primeira etapa é criar o arquivo Java/Kotlin (CalendarModule.java ou CalendarModule.kt) dentro da pasta android/app/src/main/java/com/your-app-name/ (a pasta é a mesma para Kotlin e Java). Este arquivo Java/Kotlin conterá sua classe Java/Kotlin do módulo nativo.

Imagem de como adicionar o CalendarModuleClass

Em seguida, adicione o seguinte conteúdo:

java
package com.your-apps-package-name; // substitua o com.your-apps-package-name pelo nome do pacote do seu aplicativo
+import com.facebook.react.bridge.NativeModule;
+import com.facebook.react.bridge.ReactApplicationContext;
+import com.facebook.react.bridge.ReactContext;
+import com.facebook.react.bridge.ReactContextBaseJavaModule;
+import com.facebook.react.bridge.ReactMethod;
+import java.util.Map;
+import java.util.HashMap;
+
+public class CalendarModule extends ReactContextBaseJavaModule {
+   CalendarModule(ReactApplicationContext context) {
+       super(context);
+   }
+}
kotlin
package com.your-apps-package-name; // substitua o com.your-apps-package-name pelo nome do pacote do seu aplicativo
+import com.facebook.react.bridge.NativeModule
+import com.facebook.react.bridge.ReactApplicationContext
+import com.facebook.react.bridge.ReactContext
+import com.facebook.react.bridge.ReactContextBaseJavaModule
+import com.facebook.react.bridge.ReactMethod
+
+class CalendarModule(reactContext: ReactApplicationContext) : ReactContextBaseJavaModule(reactContext) {...}

Como você pode ver, sua classe CalendarModule estende a classe ReactContextBaseJavaModule. Para Android, os módulos nativos Java/Kotlin são escritos como classes que estendem ReactContextBaseJavaModule e implementam a funcionalidade exigida pelo JavaScript.

INFORMAÇÕES

É importante notar que tecnicamente as classes Java/Kotlin só precisam estender a classe BaseJavaModule ou implementar a interface NativeModule para serem consideradas um Módulo Nativo pelo React Native.

No entanto, recomendamos que você use ReactContextBaseJavaModule, conforme mostrado acima. ReactContextBaseJavaModule dá acesso ao ReactApplicationContext (RAC), que é útil para módulos nativos que precisam se conectar a métodos de ciclo de vida de atividade. Usar ReactContextBaseJavaModule também tornará mais fácil tornar seu módulo nativo seguro para tipos no futuro. Para segurança de tipo de módulo nativo, que será lançada em versões futuras, o React Native analisa as especificações JavaScript de cada módulo nativo e gera uma classe base abstrata que estende ReactContextBaseJavaModule.

Nome do módulo

Todos os módulos nativos Java/Kotlin no Android precisam implementar o método getName(). Este método retorna uma string, que representa o nome do módulo nativo. O módulo nativo pode então ser acessado em JavaScript usando seu nome. Por exemplo, no trecho de código abaixo, getName() retorna "CalendarModule".

java
// adicionar ao CalendarModule.java
+@Override
+public String getName() {
+   return "CalendarModule";
+}
kotlin
// adicionar ao CalendarModule.kt
+override fun getName() = "CalendarModule"

O módulo nativo pode então ser acessado em JS assim:

js
const {CalendarModule} = ReactNative.NativeModules;

Exportar um método nativo para JavaScript

Em seguida, você precisará adicionar um método ao seu módulo nativo que criará eventos de calendário e poderá ser invocado em JavaScript. Todos os métodos de módulo nativos destinados a serem invocados a partir de JavaScript devem ser anotados com @ReactMethod.

Configure um método createCalendarEvent() para CalendarModule que pode ser invocado em JS por meio de CalendarModule.createCalendarEvent(). Por enquanto, o método receberá um nome e um local como strings. As opções de tipo de argumento serão abordadas em breve.

java
@ReactMethod
+public void createCalendarEvent(String name, String location) {
+}
kotlin
@ReactMethod fun createCalendarEvent(name: String, location: String) {}

Adicione um log de depuração ao método para confirmar que ele foi invocado quando você o chama do seu aplicativo. Abaixo está um exemplo de como você pode importar e usar a classe Log do pacote de utilitários do Android:

java
import android.util.Log;
+
+@ReactMethod
+public void createCalendarEvent(String name, String location) {
+   Log.d("CalendarModule", "Create event called with name: " + name
+   + " and location: " + location);
+}
kotlin
import android.util.Log
+
+@ReactMethod
+fun createCalendarEvent(name: String, location: String) {
+    Log.d("CalendarModule", "Create event called with name: $name and location: $location")
+}

Depois de concluir a implementação do módulo nativo e conectá-lo em JavaScript, você pode seguir estas etapas para visualizar os logs do seu aplicativo.

Métodos Síncronos

Você pode passar isBlockingSynchronousMethod = true para um método nativo para marcá-lo como um método síncrono.

java
@ReactMethod(isBlockingSynchronousMethod = true)
kotlin
@ReactMethod(isBlockingSynchronousMethod = true)

No momento, não recomendamos isso, pois chamar métodos de forma síncrona pode ter fortes penalidades de desempenho e introduzir bugs relacionados a threading em seus módulos nativos. Além disso, observe que se você optar por ativar isBlockingSynchronousMethod, seu aplicativo não poderá mais usar o depurador do Google Chrome. Isso ocorre porque os métodos síncronos exigem que a VM JS compartilhe memória com o aplicativo. Para o depurador do Google Chrome, o React Native é executado dentro da VM JS no Google Chrome e se comunica de forma assíncrona com os dispositivos móveis por meio de WebSockets.

Registre o módulo (específico para Android)

Depois que um módulo nativo é escrito, ele precisa ser registrado no React Native. Para fazer isso, você precisa adicionar seu módulo nativo a um ReactPackage e registrar o ReactPackage com React Native. Durante a inicialização, o React Native fará um loop em todos os pacotes e, para cada ReactPackage, registrará cada módulo nativo dentro dele.

React Native invoca o método createNativeModules() em um ReactPackage para obter a lista de módulos nativos para registrar. Para Android, se um módulo não for instanciado e retornado em createNativeModules, ele não estará disponível em JavaScript.

Para adicionar seu módulo nativo ao ReactPackage, primeiro crie uma nova classe Java/Kotlin chamada (MyAppPackage.java ou MyAppPackage.kt) que implementa ReactPackage dentro da pasta android/app/src/main/java/com/your-app-name/:

Em seguida, adicione o seguinte conteúdo:

java
package com.your-app-name; // substitua o com.your-app-name pelo nome do seu aplicativo
+
+import com.facebook.react.ReactPackage;
+import com.facebook.react.bridge.NativeModule;
+import com.facebook.react.bridge.ReactApplicationContext;
+import com.facebook.react.uimanager.ViewManager;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+
+public class MyAppPackage implements ReactPackage {
+
+   @Override
+   public List<ViewManager> createViewManagers(ReactApplicationContext reactContext) {
+       return Collections.emptyList();
+   }
+
+   @Override
+   public List<NativeModule> createNativeModules(
+           ReactApplicationContext reactContext) {
+       List<NativeModule> modules = new ArrayList<>();
+
+       modules.add(new CalendarModule(reactContext));
+
+       return modules;
+   }
+
+}
kotlin
package com.your-app-name // substitua o com.your-app-name pelo nome do seu aplicativo
+
+import android.view.View
+import com.facebook.react.ReactPackage
+import com.facebook.react.bridge.NativeModule
+import com.facebook.react.bridge.ReactApplicationContext
+import com.facebook.react.uimanager.ReactShadowNode
+import com.facebook.react.uimanager.ViewManager
+
+class MyAppPackage : ReactPackage {
+
+    override fun createViewManagers(
+        reactContext: ReactApplicationContext
+    ): MutableList<ViewManager<View, ReactShadowNode<*>>> = mutableListOf()
+
+    override fun createNativeModules(
+        reactContext: ReactApplicationContext
+    ): MutableList<NativeModule> = listOf(CalendarModule(reactContext)).toMutableList()
+}

Este arquivo importa o módulo nativo que você criou, CalendarModule. Em seguida, ele instancia CalendarModule dentro da função createNativeModules() e o retorna como uma lista de NativeModules para registrar. Se você adicionar mais módulos nativos posteriormente, também poderá instanciá-los e adicioná-los à lista retornada aqui.

INFORMAÇÕES

É importante notar que esta forma de registrar módulos nativos inicializa avidamente todos os módulos nativos quando o aplicativo é iniciado, o que aumenta o tempo de inicialização de um aplicativo. Você pode usar o TurboReactPackage como alternativa. Em vez de createNativeModules, que retorna uma lista de objetos de módulo nativos instanciados, TurboReactPackage implementa um método getModule(String name, ReactApplicationContext rac) que cria o objeto de módulo nativo, quando necessário. TurboReactPackage é um pouco mais complicado de implementar no momento. Além de implementar um método getModule(), você deve implementar um método getReactModuleInfoProvider(), que retorna uma lista de todos os módulos nativos que o pacote pode instanciar junto com uma função que os instancia, exemplo aqui. Novamente, usar o TurboReactPackage permitirá que seu aplicativo tenha um tempo de inicialização mais rápido, mas atualmente é um pouco complicado de escrever. Portanto, proceda com cuidado se você optar por usar TurboReactPackages.

Para registrar o pacote CalendarModule, você deve adicionar MyAppPackage à lista de pacotes retornados no método getPackages() do ReactNativeHost. Abra seu arquivo MainApplication.java ou MainApplication.kt, que pode ser encontrado no seguinte caminho: android/app/src/main/java/com/your-app-name/.

Localize o método getPackages() do ReactNativeHost e adicione seu pacote à lista de pacotes que getPackages() retorna:

java
@Override
+  protected List<ReactPackage> getPackages() {
+    @SuppressWarnings("UnnecessaryLocalVariable")
+    List<ReactPackage> packages = new PackageList(this).getPackages();
+    // abaixo MyAppPackage é adicionado à lista de pacotes retornados
+    packages.add(new MyAppPackage());
+    return packages;
+  }
kotlin
override fun getPackages(): List<ReactPackage> =
+    PackageList(this).packages.apply {
+        // Pacotes que ainda não podem ser vinculados automaticamente podem ser adicionados manualmente aqui, por exemplo:
+        // packages.add(new MyReactNativePackage());
+        add(MyAppPackage())
+    }

Agora você registrou com sucesso seu módulo nativo para Android!

Teste o que você construiu

Neste ponto, você configurou a estrutura básica para seu módulo nativo no Android. Teste isso acessando o módulo nativo e invocando seu método exportado em JavaScript.

Encontre um local em seu aplicativo onde você gostaria de adicionar uma chamada ao método createCalendarEvent() do módulo nativo. Abaixo está um exemplo de componente, NewModuleButton, que você pode adicionar ao seu aplicativo. Você pode invocar o módulo nativo dentro da função onPress() do NewModuleButton.

jsx
import React from 'react';
+import {NativeModules, Button} from 'react-native';
+
+const NewModuleButton = () => {
+  const onPress = () => {
+    console.log('We will invoke the native module here!');
+  };
+
+  return (
+    <Button
+      title="Click to invoke your native module!"
+      color="#841584"
+      onPress={onPress}
+    />
+  );
+};
+
+export default NewModuleButton;

Para acessar seu módulo nativo a partir de JavaScript, você precisa primeiro importar NativeModules do React Native:

jsx
import {NativeModules} from 'react-native';

Você pode então acessar o módulo nativo CalendarModule fora de NativeModules.

jsx
const {CalendarModule} = NativeModules;

Agora que você tem o módulo nativo CalendarModule disponível, você pode invocar seu método nativo createCalendarEvent(). Abaixo é adicionado ao método onPress() em NewModuleButton:

jsx
const onPress = () => {
+  CalendarModule.createCalendarEvent('testName', 'testLocation');
+};

A etapa final é reconstruir o aplicativo React Native para que você possa ter o código nativo mais recente (com seu novo módulo nativo!) Disponível. Na linha de comando, onde o aplicativo react nativo está localizado, execute o seguinte:

bash
npm run android
bash
yarn android

Construindo enquanto você itera

À medida que você trabalha nesses guias e itera em seu módulo nativo, você precisará fazer uma reconstrução nativa de seu aplicativo para acessar as alterações mais recentes do JavaScript. Isso ocorre porque o código que você está escrevendo fica na parte nativa do seu aplicativo. Embora o empacotador metro do React Native possa observar mudanças no JavaScript e reconstruir instantaneamente para você, ele não fará isso para o código nativo. Portanto, se você quiser testar suas alterações nativas mais recentes, precisará reconstruí-las usando o comando acima.

Recapitulação✨

Agora você deve ser capaz de invocar seu método createCalendarEvent() em seu módulo nativo no aplicativo. No nosso exemplo isso ocorre pressionando o NewModuleButton. Você pode confirmar isso visualizando o log configurado no método createCalendarEvent(). Você pode seguir estas etapas para visualizar os logs do ADB em seu aplicativo. Você deverá então ser capaz de pesquisar sua mensagem Log.d (em nosso exemplo “Criar evento chamado com nome: testName e local: testLocation”) e ver sua mensagem registrada sempre que invocar seu método de módulo nativo.

Imagem dos logs do ADB no Android Studio

Neste ponto, você criou um módulo nativo Android e invocou seu método nativo a partir de JavaScript em seu aplicativo React Native. Você pode continuar lendo para aprender mais sobre coisas como tipos de argumentos disponíveis para um método de módulo nativo e como configurar retornos de chamada e promessas.

Além de um módulo nativo de calendário

Melhor exportação de módulo nativo

Importar seu módulo nativo retirando-o de NativeModules como acima é um pouco complicado.

Para evitar que os consumidores do seu módulo nativo precisem fazer isso sempre que quiserem acessar seu módulo nativo, você pode criar um wrapper JavaScript para o módulo. Crie um novo arquivo JavaScript chamado CalendarModule.js com o seguinte conteúdo:

js
/**
+* Isso expõe o módulo nativo CalendarModule como um módulo JS. Isto tem um
+* função 'createCalendarEvent' que leva os seguintes parâmetros:
+
+* 1. String name: Uma string que representa o nome do evento
+* 2. String location: Uma string que representa a localização do evento
+*/
+import {NativeModules} from 'react-native';
+const {CalendarModule} = NativeModules;
+export default CalendarModule;

Este arquivo JavaScript também se torna um bom local para você adicionar qualquer funcionalidade secundária do JavaScript. Por exemplo, se você usar um sistema de tipos como TypeScript, poderá adicionar anotações de tipo para seu módulo nativo aqui. Embora o React Native ainda não ofereça suporte à segurança de tipo, todo o seu código JS será de tipo seguro. Isso também tornará mais fácil mudar para módulos nativos com segurança de tipo no futuro. Abaixo está um exemplo de adição de segurança de tipo ao CalendarModule:

tsx
/**
+ * Isso expõe o módulo nativo CalendarModule como um módulo JS. Isto tem um
+ * função 'createCalendarEvent' que leva os seguintes parâmetros:
+ *
+ * 1. String name: Uma string que representa o nome do evento
+ * 2. String location: Uma string que representa a localização do evento
+ */
+import {NativeModules} from 'react-native';
+const {CalendarModule} = NativeModules;
+
+interface CalendarInterface {
+  createCalendarEvent(name: string, location: string): void;
+}
+
+export default CalendarModule as CalendarInterface;

Nos seus outros arquivos JavaScript você pode acessar o módulo nativo e invocar seu método assim:

tsx
import CalendarModule from './CalendarModule';
+CalendarModule.createCalendarEvent('foo', 'bar');

INFORMAÇÕES

Isso pressupõe que o local que você está importando CalendarModule esteja na mesma hierarquia que CalendarModule.js. Atualize a importação relativa conforme necessário.

Tipos de argumento

Quando um método de módulo nativo é invocado em JavaScript, o React Native converte os argumentos dos objetos JS em seus objetos análogos Java/Kotlin. Então, por exemplo, se o seu método Java Native Module aceita um double, em JS você precisa chamar o método com um número. React Native cuidará da conversão para você. Abaixo está uma lista dos tipos de argumentos suportados pelos métodos de módulo nativos e os equivalentes JavaScript para os quais eles mapeiam.

JAVAKOTLINJAVASCRIPT
BooleanBoolean?boolean
booleanboolean
DoubleDouble?number
doublenumber
StringStringstring
CallbackCallbackFunction
PromisePromisePromise
ReadableMapReadableMapObject
ReadableArrayReadableArrayArray

INFORMAÇÕES

Os seguintes tipos são atualmente suportados, mas não serão suportados em TurboModules. Evite usá-los:

  • Integer Java/Kotlin -> ?number
  • Float Java/Kotlin -> ?number
  • int Java -> number
  • float Java -> number

Para tipos de argumentos não listados acima, você mesmo precisará lidar com a conversão. Por exemplo, no Android, a conversão de data não é compatível imediatamente. Você mesmo pode lidar com a conversão para o tipo Date dentro do método nativo da seguinte forma:

java
String dateFormat = "yyyy-MM-dd";
+SimpleDateFormat sdf = new SimpleDateFormat(dateFormat);
+Calendar eStartDate = Calendar.getInstance();
+try {
+    eStartDate.setTime(sdf.parse(startDate));
+}
kotlin
val dateFormat = "yyyy-MM-dd"
+val sdf = SimpleDateFormat(dateFormat, Locale.US)
+val eStartDate = Calendar.getInstance()
+try {
+    sdf.parse(startDate)?.let {
+        eStartDate.time = it
+    }
+}

Exportando Constantes

Um módulo nativo pode exportar constantes implementando o método nativo getConstants(), que está disponível em JS. Abaixo você implementará getConstants() e retornará um Map que contém uma constante DEFAULT_EVENT_NAME que você pode acessar em JavaScript:

java
@Override
+public Map<String, Object> getConstants() {
+   final Map<String, Object> constants = new HashMap<>();
+   constants.put("DEFAULT_EVENT_NAME", "New Event");
+   return constants;
+}
kotlin
override fun getConstants(): MutableMap<String, Any> =
+    hashMapOf("DEFAULT_EVENT_NAME" to "New Event")

A constante pode então ser acessada invocando getConstants no módulo nativo em JS:

java
const {DEFAULT_EVENT_NAME} = CalendarModule.getConstants();
+console.log(DEFAULT_EVENT_NAME);
kotlin
const {DEFAULT_EVENT_NAME} = CalendarModule.getConstants();
+console.log(DEFAULT_EVENT_NAME);

Tecnicamente, é possível acessar constantes exportadas em getConstants() diretamente do objeto do módulo nativo. Isso não será mais compatível com TurboModules, por isso encorajamos a comunidade a mudar para a abordagem acima para evitar a migração necessária no futuro.

INFORMAÇÕES

Atualmente, as constantes são exportadas apenas no momento da inicialização, portanto, se você alterar os valores getConstants em tempo de execução, isso não afetará o ambiente JavaScript. Isso mudará com Turbomodules. Com Turbomodules, getConstants() se tornará um método de módulo nativo regular e cada invocação atingirá o lado nativo.

Callbacks

Os módulos nativos também suportam um tipo único de argumento: um retorno de chamada. Retornos de chamada são usados para passar dados de Java/Kotlin para JavaScript para métodos assíncronos. Eles também podem ser usados para executar JavaScript de forma assíncrona do lado nativo.

Para criar um método de módulo nativo com retorno de chamada, primeiro importe a interface Callback e, em seguida, adicione um novo parâmetro ao método de módulo nativo do tipo Callback. Existem algumas nuances nos argumentos de retorno de chamada que em breve serão eliminadas com TurboModules. Primeiro, você só pode ter dois retornos de chamada nos argumentos de sua função – um successCallback e um failedCallback. Além disso, o último argumento para uma chamada de método de módulo nativo, se for uma função, é tratado como sucessCallback, e o penúltimo argumento para uma chamada de método de módulo nativo, se for uma função, é tratado como retorno de chamada de falha.

java
import com.facebook.react.bridge.Callback;
+
+@ReactMethod
+public void createCalendarEvent(String name, String location, Callback callBack) {
+}
kotlin
import com.facebook.react.bridge.Callback
+
+@ReactMethod fun createCalendarEvent(name: String, location: String, callback: Callback) {}

Você pode invocar o retorno de chamada em seu método Java/Kotlin, fornecendo quaisquer dados que deseja passar para JavaScript. Observe que você só pode passar dados serializáveis de código nativo para JavaScript. Se você precisar retornar um objeto nativo, você pode usar WriteableMaps, se precisar usar uma coleção, use WritableArrays. Também é importante destacar que o retorno de chamada não é invocado imediatamente após a conclusão da função nativa. Abaixo do ID de um evento criado em uma chamada anterior é passado para o retorno de chamada.

java
@ReactMethod
+public void createCalendarEvent(String name, String location, Callback callBack) {
+     Integer eventId = ...
+     callBack.invoke(eventId);
+}
kotlin
@ReactMethod
+fun createCalendarEvent(name: String, location: String, callback: Callback) {
+    val eventId = ...
+    callback.invoke(eventId)
+}

Este método pode então ser acessado em JavaScript usando:

tsx
const onPress = () => {
+  CalendarModule.createCalendarEvent(
+    'Party',
+    'My House',
+    eventId => {
+      console.log(\`Created a new event with id \${eventId}\`);
+    },
+  );
+};

Outro detalhe importante a ser observado é que um método de módulo nativo só pode invocar um retorno de chamada uma vez. Isso significa que você pode chamar um retorno de chamada com sucesso ou um retorno de chamada com falha, mas não ambos, e cada retorno de chamada só pode ser invocado no máximo uma vez. Um módulo nativo pode, entretanto, armazenar o retorno de chamada e invocá-lo posteriormente.

Existem duas abordagens para tratamento de erros com retornos de chamada. A primeira é seguir a convenção do Node e tratar o primeiro argumento passado para o retorno de chamada como um objeto de erro.

java
@ReactMethod
+ public void createCalendarEvent(String name, String location, Callback callBack) {
+     Integer eventId = ...
+     callBack.invoke(null, eventId);
+ }
kotlin
@ReactMethod
+fun createCalendarEvent(name: String, location: String, callback: Callback) {
+    val eventId = ...
+    callback.invoke(null, eventId)
+}

Em JavaScript, você pode verificar o primeiro argumento para ver se um erro foi transmitido:

tsx
const onPress = () => {
+  CalendarModule.createCalendarEvent(
+    'testName',
+    'testLocation',
+    (error, eventId) => {
+      if (error) {
+        console.error(\`Error found! \${error}\`);
+      }
+      console.log(\`event id \${eventId} returned\`);
+    },
+  );
+};

Outra opção é usar um retorno de chamada onSuccess e onFailure:

java
@ReactMethod
+public void createCalendarEvent(String name, String location, Callback myFailureCallback, Callback mySuccessCallback) {
+}
kotlin
@ReactMethod
+  fun createCalendarEvent(
+      name: String,
+      location: String,
+      myFailureCallback: Callback,
+      mySuccessCallback: Callback
+  ) {}

Então, em JavaScript, você pode adicionar um retorno de chamada separado para respostas de erro e sucesso:

tsx
const onPress = () => {
+  CalendarModule.createCalendarEvent(
+    'testName',
+    'testLocation',
+    error => {
+      console.error(\`Error found! \${error}\`);
+    },
+    eventId => {
+      console.log(\`event id \${eventId} returned\`);
+    },
+  );
+};

Promises

Módulos nativos também podem cumprir uma promessa, o que pode simplificar seu JavaScript, especialmente ao usar a sintaxe async/await do ES2016. Quando o último parâmetro de um método Java/Kotlin de módulo nativo é uma Promise, seu método JS correspondente retornará um objeto JS Promise.

Refatorar o código acima para usar uma promessa em vez de retornos de chamada é assim:

java
import com.facebook.react.bridge.Promise;
+
+@ReactMethod
+public void createCalendarEvent(String name, String location, Promise promise) {
+    try {
+        Integer eventId = ...
+        promise.resolve(eventId);
+    } catch(Exception e) {
+        promise.reject("Create Event Error", e);
+    }
+}
kotlin
import com.facebook.react.bridge.Promise
+
+@ReactMethod
+fun createCalendarEvent(name: String, location: String, promise: Promise) {
+    try {
+        val eventId = ...
+        promise.resolve(eventId)
+    } catch (e: Throwable) {
+        promise.reject("Create Event Error", e)
+    }
+}

INFORMAÇÕES

Semelhante aos retornos de chamada, um método de módulo nativo pode rejeitar ou resolver uma promessa (mas não ambos) e pode fazer isso no máximo uma vez. Isso significa que você pode chamar um retorno de chamada com sucesso ou um retorno de chamada com falha, mas não ambos, e cada retorno de chamada só pode ser invocado no máximo uma vez. Um módulo nativo pode, entretanto, armazenar o retorno de chamada e invocá-lo posteriormente.

A contraparte JavaScript deste método retorna uma promessa. Isso significa que você pode usar a palavra-chave await dentro de uma função assíncrona para chamá-la e aguardar seu resultado:

tsx
const onSubmit = async () => {
+  try {
+    const eventId = await CalendarModule.createCalendarEvent(
+      'Party',
+      'My House',
+    );
+    console.log(\`Created a new event with id \${eventId}\`);
+  } catch (e) {
+    console.error(e);
+  }
+};

O método rejeitar utiliza diferentes combinações dos seguintes argumentos:

java
String code, String message, WritableMap userInfo, Throwable throwable
kotlin
code: String, message: String, userInfo: WritableMap, throwable: Throwable

Para mais detalhes, você pode encontrar a interface Promise.java aqui. Se userInfo não for fornecido, ReactNative irá defini-lo como nulo. Para o restante dos parâmetros, o React Native usará um valor padrão. O argumento message fornece a mensagem de erro mostrada no topo de uma pilha de chamadas de erro. Abaixo está um exemplo da mensagem de erro mostrada em JavaScript da seguinte chamada rejeitada em Java/Kotlin.

Chamada rejeitada de Java/Kotlin:

java
promise.reject("Create Event error", "Error parsing date", e);
kotlin
promise.reject("Create Event error", "Error parsing date", e)

Mensagem de erro no aplicativo React Native quando a promessa é rejeitada:

Imagem da mensagem de erro

Enviando eventos para JavaScript

Módulos nativos podem sinalizar eventos para JavaScript sem serem invocados diretamente. Por exemplo, você pode sinalizar para o JavaScript um lembrete de que um evento de calendário do aplicativo de calendário nativo do Android ocorrerá em breve. A maneira mais fácil de fazer isso é usar o RCTDeviceEventEmitter que pode ser obtido no ReactContext como no trecho de código abaixo.

java
...
+import com.facebook.react.modules.core.DeviceEventManagerModule;
+import com.facebook.react.bridge.WritableMap;
+import com.facebook.react.bridge.Arguments;
+...
+private void sendEvent(ReactContext reactContext,
+                      String eventName,
+                      @Nullable WritableMap params) {
+ reactContext
+     .getJSModule(DeviceEventManagerModule.RCTDeviceEventEmitter.class)
+     .emit(eventName, params);
+}
+
+private int listenerCount = 0;
+
+@ReactMethod
+public void addListener(String eventName) {
+  if (listenerCount == 0) {
+    // Configure quaisquer ouvintes upstream ou tarefas em segundo plano conforme necessário
+  }
+
+  listenerCount += 1;
+}
+
+@ReactMethod
+public void removeListeners(Integer count) {
+  listenerCount -= count;
+  if (listenerCount == 0) {
+    // Remova ouvintes upstream, interrompa tarefas desnecessárias em segundo plano
+  }
+}
+...
+WritableMap params = Arguments.createMap();
+params.putString("eventProperty", "someValue");
+...
+sendEvent(reactContext, "EventReminder", params);
kotlin
...
+import com.facebook.react.bridge.WritableMap
+import com.facebook.react.bridge.Arguments
+import com.facebook.react.modules.core.DeviceEventManagerModule
+...
+
+private fun sendEvent(reactContext: ReactContext, eventName: String, params: WritableMap?) {
+    reactContext
+      .getJSModule(DeviceEventManagerModule.RCTDeviceEventEmitter::class.java)
+      .emit(eventName, params)
+}
+
+private var listenerCount = 0
+
+@ReactMethod
+fun addListener(eventName: String) {
+  if (listenerCount == 0) {
+    // Configure quaisquer ouvintes upstream ou tarefas em segundo plano conforme necessário
+  }
+
+  listenerCount += 1
+}
+
+@ReactMethod
+fun removeListeners(count: Int) {
+  listenerCount -= count
+  if (listenerCount == 0) {
+    // Remova ouvintes upstream, interrompa tarefas desnecessárias em segundo plano
+  }
+}
+...
+val params = Arguments.createMap().apply {
+    putString("eventProperty", "someValue")
+}
+...
+sendEvent(reactContext, "EventReminder", params)

Os módulos JavaScript podem então se registrar para receber eventos por addListener na classe NativeEventEmitter.

tsx
import {NativeEventEmitter, NativeModules} from 'react-native';
+...
+useEffect(() => {
+    const eventEmitter = new NativeEventEmitter(NativeModules.ToastExample);
+    let eventListener = eventEmitter.addListener('EventReminder', event => {
+      console.log(event.eventProperty) // "algumValor"
+    });
+
+    // Remove o ouvinte depois de desmontado
+    return () => {
+      eventListener.remove();
+    };
+  }, []);

Obtendo o resultado da atividade de startActivityForResult

Você precisará ouvir onActivityResult se quiser obter resultados de uma atividade iniciada com startActivityForResult. Para fazer isso, você deve estender BaseActivityEventListener ou implementar ActivityEventListener. O primeiro é preferido porque é mais resiliente às alterações da API. Então, você precisa registrar o ouvinte no construtor do módulo assim:

java
reactContext.addActivityEventListener(mActivityResultListener);

Agora você pode ouvir onActivityResult implementando o seguinte método:

java
@Override
+public void onActivityResult(
+ final Activity activity,
+ final int requestCode,
+ final int resultCode,
+ final Intent intent) {
+ // Sua lógica aqui
+}
kotlin
override fun onActivityResult(
+    activity: Activity?,
+    requestCode: Int,
+    resultCode: Int,
+    intent: Intent?
+) {
+    // Sua lógica aqui
+}

Vamos implementar um seletor de imagens básico para demonstrar isso. O seletor de imagens irá expor o método pickImage no JavaScript, que retornará o caminho da imagem quando chamado.

java
public class ImagePickerModule extends ReactContextBaseJavaModule {
+
+  private static final int IMAGE_PICKER_REQUEST = 1;
+  private static final String E_ACTIVITY_DOES_NOT_EXIST = "E_ACTIVITY_DOES_NOT_EXIST";
+  private static final String E_PICKER_CANCELLED = "E_PICKER_CANCELLED";
+  private static final String E_FAILED_TO_SHOW_PICKER = "E_FAILED_TO_SHOW_PICKER";
+  private static final String E_NO_IMAGE_DATA_FOUND = "E_NO_IMAGE_DATA_FOUND";
+
+  private Promise mPickerPromise;
+
+  private final ActivityEventListener mActivityEventListener = new BaseActivityEventListener() {
+
+    @Override
+    public void onActivityResult(Activity activity, int requestCode, int resultCode, Intent intent) {
+      if (requestCode == IMAGE_PICKER_REQUEST) {
+        if (mPickerPromise != null) {
+          if (resultCode == Activity.RESULT_CANCELED) {
+            mPickerPromise.reject(E_PICKER_CANCELLED, "Image picker was cancelled");
+          } else if (resultCode == Activity.RESULT_OK) {
+            Uri uri = intent.getData();
+
+            if (uri == null) {
+              mPickerPromise.reject(E_NO_IMAGE_DATA_FOUND, "No image data found");
+            } else {
+              mPickerPromise.resolve(uri.toString());
+            }
+          }
+
+          mPickerPromise = null;
+        }
+      }
+    }
+  };
+
+  ImagePickerModule(ReactApplicationContext reactContext) {
+    super(reactContext);
+
+    // Adicione o ouvinte para \`onActivityResult\`
+    reactContext.addActivityEventListener(mActivityEventListener);
+  }
+
+  @Override
+  public String getName() {
+    return "ImagePickerModule";
+  }
+
+  @ReactMethod
+  public void pickImage(final Promise promise) {
+    Activity currentActivity = getCurrentActivity();
+
+    if (currentActivity == null) {
+      promise.reject(E_ACTIVITY_DOES_NOT_EXIST, "Activity doesn't exist");
+      return;
+    }
+
+    // Armazene a promessa de resolver/rejeitar quando o seletor retornar dados
+    mPickerPromise = promise;
+
+    try {
+      final Intent galleryIntent = new Intent(Intent.ACTION_PICK);
+
+      galleryIntent.setType("image/*");
+
+      final Intent chooserIntent = Intent.createChooser(galleryIntent, "Pick an image");
+
+      currentActivity.startActivityForResult(chooserIntent, IMAGE_PICKER_REQUEST);
+    } catch (Exception e) {
+      mPickerPromise.reject(E_FAILED_TO_SHOW_PICKER, e);
+      mPickerPromise = null;
+    }
+  }
+}
kotlin
class ImagePickerModule(reactContext: ReactApplicationContext) :
+    ReactContextBaseJavaModule(reactContext) {
+
+    private var pickerPromise: Promise? = null
+
+    private val activityEventListener =
+        object : BaseActivityEventListener() {
+            override fun onActivityResult(
+                activity: Activity?,
+                requestCode: Int,
+                resultCode: Int,
+                intent: Intent?
+            ) {
+                if (requestCode == IMAGE_PICKER_REQUEST) {
+                    pickerPromise?.let { promise ->
+                        when (resultCode) {
+                            Activity.RESULT_CANCELED ->
+                                promise.reject(E_PICKER_CANCELLED, "Image picker was cancelled")
+                            Activity.RESULT_OK -> {
+                                val uri = intent?.data
+
+                                uri?.let { promise.resolve(uri.toString())}
+                                    ?: promise.reject(E_NO_IMAGE_DATA_FOUND, "No image data found")
+                            }
+                        }
+
+                        pickerPromise = null
+                    }
+                }
+            }
+        }
+
+    init {
+        reactContext.addActivityEventListener(activityEventListener)
+    }
+
+    override fun getName() = "ImagePickerModule"
+
+    @ReactMethod
+    fun pickImage(promise: Promise) {
+        val activity = currentActivity
+
+        if (activity == null) {
+            promise.reject(E_ACTIVITY_DOES_NOT_EXIST, "Activity doesn't exist")
+            return
+        }
+
+        pickerPromise = promise
+
+        try {
+            val galleryIntent = Intent(Intent.ACTION_PICK).apply { type = "image\\/*" }
+
+            val chooserIntent = Intent.createChooser(galleryIntent, "Pick an image")
+
+            activity.startActivityForResult(chooserIntent, IMAGE_PICKER_REQUEST)
+        } catch (t: Throwable) {
+            pickerPromise?.reject(E_FAILED_TO_SHOW_PICKER, t)
+            pickerPromise = null
+        }
+    }
+
+    companion object {
+        const val IMAGE_PICKER_REQUEST = 1
+        const val E_ACTIVITY_DOES_NOT_EXIST = "E_ACTIVITY_DOES_NOT_EXIST"
+        const val E_PICKER_CANCELLED = "E_PICKER_CANCELLED"
+        const val E_FAILED_TO_SHOW_PICKER = "E_FAILED_TO_SHOW_PICKER"
+        const val E_NO_IMAGE_DATA_FOUND = "E_NO_IMAGE_DATA_FOUND"
+    }
+}

Ouvindo eventos do ciclo de vida

Ouvir os eventos LifeCycle da atividade, como onResume, onPause etc., é muito semelhante a como ActivityEventListener foi implementado. O módulo deve implementar LifecycleEventListener. Então, você precisa registrar um ouvinte no construtor do módulo como:

java
reactContext.addLifecycleEventListener(this);
kotlin
reactContext.addLifecycleEventListener(this)

Agora você pode ouvir os eventos LifeCycle da atividade implementando os seguintes métodos:

java
@Override
+public void onHostResume() {
+   // Activity \`onResume\`
+}
+@Override
+public void onHostPause() {
+   // Activity \`onPause\`
+}
+@Override
+public void onHostDestroy() {
+   // Activity \`onDestroy\`
+}
kotlin
override fun onHostResume() {
+    // Activity \`onResume\`
+}
+
+override fun onHostPause() {
+    // Activity \`onPause\`
+}
+
+override fun onHostDestroy() {
+    // Activity \`onDestroy\`
+}

Threading

Até o momento, no Android, todos os métodos assíncronos do módulo nativo são executados em um thread. Os módulos nativos não devem ter nenhuma suposição sobre em qual thread estão sendo chamados, pois a atribuição atual está sujeita a alterações no futuro. Se uma chamada de bloqueio for necessária, o trabalho pesado deverá ser despachado para um thread de trabalho gerenciado internamente e quaisquer retornos de chamada distribuídos a partir daí.

`,136),d=[k];function r(o,E,c,g,y,u){return a(),i("div",null,d)}const F=s(h,[["render",r]]);export{m as __pageData,F as default}; diff --git a/vitepress/docs/.vitepress/dist/assets/docs_native-modules-android.md.BI96nnL8.lean.js b/vitepress/docs/.vitepress/dist/assets/docs_native-modules-android.md.BI96nnL8.lean.js new file mode 100644 index 0000000..bdcf232 --- /dev/null +++ b/vitepress/docs/.vitepress/dist/assets/docs_native-modules-android.md.BI96nnL8.lean.js @@ -0,0 +1 @@ +import{_ as s,c as i,o as a,a4 as n}from"./chunks/framework.nQaBHiNx.js";const e="/assets/313493455-1a5c12f5-6368-4675-af20-051a7cb2598b.CjOJ3DU1.png",t="/assets/313493538-f05df190-b27f-4511-8554-ee5dc86efcb2.DAi3nME1.png",l="/assets/313495844-578b6da9-b01c-4b00-a7fb-9bd4be45b912.wiOJK8eL.png",p="/assets/313500818-99069c93-a869-4b6e-bb50-b101c0c029ad.C5DJ4UvH.png",m=JSON.parse('{"title":"Módulos nativos do Android","description":"","frontmatter":{},"headers":[],"relativePath":"docs/native-modules-android.md","filePath":"docs/native-modules-android.md"}'),h={name:"docs/native-modules-android.md"},k=n("",136),d=[k];function r(o,E,c,g,y,u){return a(),i("div",null,d)}const F=s(h,[["render",r]]);export{m as __pageData,F as default}; diff --git a/vitepress/docs/.vitepress/dist/assets/docs_native-modules-intro.md.BZ9q-CdX.js b/vitepress/docs/.vitepress/dist/assets/docs_native-modules-intro.md.BZ9q-CdX.js new file mode 100644 index 0000000..fb09b9e --- /dev/null +++ b/vitepress/docs/.vitepress/dist/assets/docs_native-modules-intro.md.BZ9q-CdX.js @@ -0,0 +1 @@ +import{_ as a,c as e,o,a4 as t}from"./chunks/framework.nQaBHiNx.js";const h=JSON.parse('{"title":"Introdução aos módulos nativos","description":"","frontmatter":{},"headers":[],"relativePath":"docs/native-modules-intro.md","filePath":"docs/native-modules-intro.md"}'),i={name:"docs/native-modules-intro.md"},s=t('

Introdução aos módulos nativos

INFORMAÇÕES

Módulo Nativo e Componentes Nativos são nossas tecnologias estáveis usadas pela arquitetura legada. Eles serão descontinuados no futuro, quando a Nova Arquitetura estiver estável. A nova arquitetura usa Turbo Native Module e Fabric Native Components para obter resultados semelhantes.

Às vezes, um aplicativo React Native precisa acessar uma API de plataforma nativa que não está disponível por padrão em JavaScript, por exemplo, as APIs nativas para acessar Apple ou Google Pay. Talvez você queira reutilizar algumas bibliotecas existentes de Objective-C, Swift, Java ou C++ sem ter que reimplementá-las em JavaScript ou escrever algum código multithread de alto desempenho para coisas como processamento de imagens.

O sistema NativeModule expõe instâncias de classes Java/Objective-C/C++ (nativas) para JavaScript (JS) como objetos JS, permitindo assim que você execute código nativo arbitrário de dentro de JS. Embora não esperemos que esse recurso faça parte do processo normal de desenvolvimento, é essencial que ele exista. Se o React Native não exportar uma API nativa que seu aplicativo JS precisa, você mesmo poderá exportá-la!

Configuração do módulo nativo

Existem duas maneiras de escrever um módulo nativo para seu aplicativo React Native:

  1. Diretamente nos projetos iOS/Android do seu aplicativo React Native
  2. Como um pacote NPM que pode ser instalado como uma dependência por seus/outros aplicativos React Native

Este guia primeiro orientará você na implementação de um módulo nativo diretamente em um aplicativo React Native. No entanto, o módulo nativo que você constrói no guia a seguir pode ser distribuído como um pacote NPM. Confira o guia Configurando um Módulo Nativo como um Pacote NPM se você estiver interessado em fazê-lo.

Começando

Nas seções a seguir, orientaremos você em guias sobre como construir um módulo nativo diretamente em um aplicativo React Native. Como pré-requisito, você precisará de um aplicativo React Native para trabalhar. Você pode seguir as etapas aqui para configurar um aplicativo React Native se ainda não tiver um.

Imagine que você deseja acessar as APIs de calendário nativas do iOS/Android a partir do JavaScript em um aplicativo React Native para criar eventos de calendário. React Native não expõe uma API JavaScript para se comunicar com as bibliotecas de calendário nativas. No entanto, por meio de módulos nativos, você pode escrever código nativo que se comunique com APIs de calendário nativas. Então você pode invocar esse código nativo por meio de JavaScript em seu aplicativo React Native.

Nas seções a seguir, você criará um módulo nativo do Calendário para Android e iOS.

',12),r=[s];function n(c,d,u,m,l,v){return o(),e("div",null,r)}const g=a(i,[["render",n]]);export{h as __pageData,g as default}; diff --git a/vitepress/docs/.vitepress/dist/assets/docs_native-modules-intro.md.BZ9q-CdX.lean.js b/vitepress/docs/.vitepress/dist/assets/docs_native-modules-intro.md.BZ9q-CdX.lean.js new file mode 100644 index 0000000..488dc4d --- /dev/null +++ b/vitepress/docs/.vitepress/dist/assets/docs_native-modules-intro.md.BZ9q-CdX.lean.js @@ -0,0 +1 @@ +import{_ as a,c as e,o,a4 as t}from"./chunks/framework.nQaBHiNx.js";const h=JSON.parse('{"title":"Introdução aos módulos nativos","description":"","frontmatter":{},"headers":[],"relativePath":"docs/native-modules-intro.md","filePath":"docs/native-modules-intro.md"}'),i={name:"docs/native-modules-intro.md"},s=t("",12),r=[s];function n(c,d,u,m,l,v){return o(),e("div",null,r)}const g=a(i,[["render",n]]);export{h as __pageData,g as default}; diff --git a/vitepress/docs/.vitepress/dist/assets/docs_native-modules-ios.md.B8RNq7sy.js b/vitepress/docs/.vitepress/dist/assets/docs_native-modules-ios.md.B8RNq7sy.js new file mode 100644 index 0000000..b4c509f --- /dev/null +++ b/vitepress/docs/.vitepress/dist/assets/docs_native-modules-ios.md.B8RNq7sy.js @@ -0,0 +1,217 @@ +import{_ as s,c as a,o as i,a4 as e}from"./chunks/framework.nQaBHiNx.js";const n="/assets/313507258-a79717d3-36f2-41a5-b120-dd2bc51232eb.DP5RsCfL.png",t="/assets/313507304-f06738b3-4be6-4734-8bea-1f87556a0df3.CxBYw3G2.png",o="/assets/313508003-11f8175a-c432-4050-91e5-88b84a5d726b.Dw_qJO7t.png",v=JSON.parse('{"title":"Módulos nativos iOS","description":"","frontmatter":{},"headers":[],"relativePath":"docs/native-modules-ios.md","filePath":"docs/native-modules-ios.md"}'),l={name:"docs/native-modules-ios.md"},p=e('

Módulos nativos iOS

INFORMAÇÕES

Módulo Nativo e Componentes Nativos são nossas tecnologias estáveis usadas pela arquitetura legada. Eles serão descontinuados no futuro, quando a Nova Arquitetura estiver estável. A nova arquitetura usa Turbo Native Module e Fabric Native Components para obter resultados semelhantes.

Bem-vindo aos Módulos Nativos para iOS. Comece lendo a introdução aos módulos nativos para obter uma introdução ao que são os módulos nativos.

Crie um módulo nativo de calendário

No guia a seguir você criará um módulo nativo, CalendarModule, que permitirá acessar APIs de calendário da Apple a partir de JavaScript. No final você poderá chamar CalendarModule.createCalendarEvent('Dinner Party', 'My House'); do JavaScript, invocando um método nativo que cria um evento de calendário.

Configurar

Para começar, abra o projeto iOS em seu aplicativo React Native no Xcode. Você pode encontrar seu projeto iOS aqui em um aplicativo React Native:

Imagem de onde você pode encontrar seu projeto iOS

Recomendamos usar o Xcode para escrever seu código nativo. O Xcode foi desenvolvido para desenvolvimento em iOS e usá-lo ajudará você a resolver rapidamente erros menores, como sintaxe de código.

Crie arquivos de módulo nativos personalizados

A primeira etapa é criar nosso principal cabeçalho de módulo nativo personalizado e arquivos de implementação. Crie um novo arquivo chamado RCTCalendarModule.h

Imagem da criação de um arquivo de módulo nativo personalizado na mesma pasta do AppDelegate

e adicione o seguinte a ele:

cpp
//  RCTCalendarModule.h
+#import <React/RCTBridgeModule.h>
+@interface RCTCalendarModule : NSObject <RCTBridgeModule>
+@end

Você pode usar qualquer nome que corresponda ao módulo nativo que você está construindo. Nomeie a classe RCTCalendarModule, pois você está criando um módulo nativo de calendário. Como ObjC não tem suporte em nível de linguagem para namespaces como Java ou C++, a convenção é acrescentar uma substring ao nome da classe. Pode ser uma abreviatura do nome do seu aplicativo ou do seu infranome. RCT, neste exemplo, refere-se ao React.

Como você pode ver abaixo, a classe CalendarModule implementa o protocolo RCTBridgeModule. Um módulo nativo é uma classe Objective-C que implementa o protocolo RCTBridgeModule.

A seguir, vamos começar a implementar o módulo nativo. Crie o arquivo de implementação correspondente, RCTCalendarModule.m, na mesma pasta e inclua o seguinte conteúdo:

cpp
// RCTCalendarModule.m
+#import "RCTCalendarModule.h"
+
+@implementation RCTCalendarModule
+
+// Para exportar um módulo denominado RCTCalendarModule
+RCT_EXPORT_MODULE();
+
+@end

Nome do módulo

Por enquanto, seu módulo nativo RCTCalendarModule.m inclui apenas um macro RCT_EXPORT_MODULE, que exporta e registra a classe do módulo nativo com React Native. O macro RCT_EXPORT_MODULE também usa um argumento opcional que especifica o nome pelo qual o módulo estará acessível em seu código JavaScript.

Este argumento não é uma string literal. No exemplo abaixo RCT_EXPORT_MODULE(CalendarModuleFoo) é passado, não RCT_EXPORT_MODULE("CalendarModuleFoo").

cpp
// Para exportar um módulo chamado CalendarModuleFoo
+RCT_EXPORT_MODULE(CalendarModuleFoo);

O módulo nativo pode então ser acessado em JS assim:

js
const {CalendarModuleFoo} = ReactNative.NativeModules;

Se você não especificar um nome, o nome do módulo JavaScript corresponderá ao nome da classe Objective-C, com quaisquer prefixos "RCT" ou "RK" removidos.

Vamos seguir o exemplo abaixo e chamar RCT_EXPORT_MODULE sem nenhum argumento. Como resultado, o módulo será exposto ao React Native usando o nome CalendarModule, já que esse é o nome da classe Objective-C, com RCT removido.

cpp
// Sem passar um nome, isso exportará o nome do módulo nativo como o nome da classe Objective-C com “RCT” removido
+RCT_EXPORT_MODULE();

O módulo nativo pode então ser acessado em JS assim:

js
const {CalendarModule} = ReactNative.NativeModules;

Exportar um método nativo para JavaScript

O React Native não exporá nenhum método em um módulo nativo ao JavaScript, a menos que seja explicitamente solicitado. Isso pode ser feito usando o macro RCT_EXPORT_METHOD. Os métodos escritos na macro RCT_EXPORT_METHOD são assíncronos e o tipo de retorno é, portanto, sempre nulo. Para passar um resultado de um método RCT_EXPORT_METHOD para JavaScript você pode usar retornos de chamada ou emitir eventos (abordados abaixo). Vamos configurar um método nativo para nosso módulo nativo CalendarModule usando a macro RCT_EXPORT_METHOD. Chame-o de createCalendarEvent() e, por enquanto, aceite argumentos de nome e localização como strings. As opções de tipo de argumento serão abordadas em breve.

cpp
RCT_EXPORT_METHOD(createCalendarEvent:(NSString *)name location:(NSString *)location)
+{
+}

INFORMAÇÕES

Observe que o macro RCT_EXPORT_METHOD não será necessário com TurboModules, a menos que seu método dependa da conversão de argumentos RCT (veja os tipos de argumentos abaixo). Em última análise, o React Native removerá o RCT_EXPORT_MACRO, por isso desencorajamos as pessoas a usar o RCTConvert. Em vez disso, você pode fazer a conversão do argumento dentro do corpo do método.

Antes de desenvolver a funcionalidade do método createCalendarEvent(), adicione um log de console no método para que você possa confirmar se ele foi invocado a partir de JavaScript em seu aplicativo React Native. Use as APIs RCTLog do React. Vamos importar esse cabeçalho no topo do seu arquivo e adicionar a chamada de log.

c
#import <React/RCTLog.h>
+RCT_EXPORT_METHOD(createCalendarEvent:(NSString *)name location:(NSString *)location)
+{
+ RCTLogInfo(@"Pretending to create an event %@ at %@", name, location);
+}

Métodos Síncronos

Você pode usar RCT_EXPORT_BLOCKING_SYNCHRONOUS_METHOD para criar um método nativo síncrono.

c
RCT_EXPORT_BLOCKING_SYNCHRONOUS_METHOD(getName)
+{
+return [[UIDevice currentDevice] name];
+}

O tipo de retorno deste método deve ser do tipo objeto (id) e ser serializável para JSON. Isso significa que o gancho só pode retornar valores nulos ou JSON (por exemplo, NSNumber, NSString, NSArray, NSDictionary).

No momento, não recomendamos o uso de métodos síncronos, pois chamar métodos de forma síncrona pode causar fortes penalidades de desempenho e introduzir bugs relacionados a threading em seus módulos nativos. Além disso, observe que se você optar por usar RCT_EXPORT_BLOCKING_SYNCHRONOUS_METHOD, seu aplicativo não poderá mais usar o depurador do Google Chrome. Isso ocorre porque os métodos síncronos exigem que a VM JS compartilhe memória com o aplicativo. Para o depurador do Google Chrome, o React Native é executado dentro da VM JS no Google Chrome e se comunica de forma assíncrona com os dispositivos móveis por meio de WebSockets.

Teste o que você construiu

Neste ponto, você configurou a estrutura básica para seu módulo nativo no iOS. Teste isso acessando o módulo nativo e invocando seu método exportado em JavaScript.

Encontre um local em seu aplicativo onde você gostaria de adicionar uma chamada ao método createCalendarEvent() do módulo nativo. Abaixo está um exemplo de componente, NewModuleButton, que você pode adicionar ao seu aplicativo. Você pode invocar o módulo nativo dentro da função onPress() do NewModuleButton.

tsx
import React from 'react';
+import {NativeModules, Button} from 'react-native';
+
+const NewModuleButton = () => {
+  const onPress = () => {
+    console.log('We will invoke the native module here!');
+  };
+
+  return (
+    <Button
+      title="Click to invoke your native module!"
+      color="#841584"
+      onPress={onPress}
+    />
+  );
+};
+
+export default NewModuleButton;

Para acessar seu módulo nativo a partir de JavaScript, você precisa primeiro importar NativeModules do React Native:

tsx
import {NativeModules} from 'react-native';

Você pode então acessar o módulo nativo CalendarModule fora de NativeModules.

tsx
const {CalendarModule} = NativeModules;

Agora que você tem o módulo nativo CalendarModule disponível, você pode invocar seu método nativo createCalendarEvent(). Abaixo é adicionado ao método onPress() em NewModuleButton:

tsx
const onPress = () => {
+  CalendarModule.createCalendarEvent('testName', 'testLocation');
+};

A etapa final é reconstruir o aplicativo React Native para que você possa ter o código nativo mais recente (com seu novo módulo nativo!) Disponível. Na linha de comando, onde o aplicativo react nativo está localizado, execute o seguinte:

bash
npm run ios
bash
yarn ios

Construindo enquanto você itera

À medida que você trabalha nesses guias e itera em seu módulo nativo, você precisará fazer uma reconstrução nativa de seu aplicativo para acessar as alterações mais recentes do JavaScript. Isso ocorre porque o código que você está escrevendo fica na parte nativa do seu aplicativo. Embora o empacotador metro do React Native possa observar mudanças no JavaScript e reconstruir o pacote JS rapidamente para você, ele não fará isso para o código nativo. Portanto, se você quiser testar suas alterações nativas mais recentes, precisará reconstruí-las usando o comando acima.

Recapitulação✨

Agora você deve conseguir invocar seu método createCalendarEvent() em seu módulo nativo em JavaScript. Como você está usando RCTLog na função, você pode confirmar se seu método nativo está sendo invocado ativando o modo de depuração em seu aplicativo e observando o console JS no Chrome ou o depurador de aplicativo móvel Flipper. Você deverá ver seu RCTLogInfo(@"Fingindo criar um evento %@ em %@", nome, local); mensagem cada vez que você invoca o método do módulo nativo.

Imagem dos registros do iOS no Flipper

Neste ponto, você criou um módulo nativo do iOS e invocou um método nele a partir de JavaScript em seu aplicativo React Native. Você pode continuar lendo para aprender mais sobre coisas como quais tipos de argumento seu método de módulo nativo usa e como configurar retornos de chamada e promessas em seu módulo nativo.

Além de um módulo nativo de calendário

Melhor exportação de módulo nativo

Importar seu módulo nativo retirando-o de NativeModules como acima é um pouco complicado.

Para evitar que os consumidores do seu módulo nativo precisem fazer isso sempre que quiserem acessar seu módulo nativo, você pode criar um wrapper JavaScript para o módulo. Crie um novo arquivo JavaScript chamado NativeCalendarModule.js com o seguinte conteúdo:

js
/**
+* Isso expõe o módulo nativo CalendarModule como um módulo JS. Isto tem um
+* função 'createCalendarEvent' que leva os seguintes parâmetros:
+
+* 1. String name: Uma string que representa o nome do evento
+* 2. String location: Uma string que representa a localização do evento
+*/
+import {NativeModules} from 'react-native';
+const {CalendarModule} = NativeModules;
+export default CalendarModule;

Este arquivo JavaScript também se torna um bom local para você adicionar qualquer funcionalidade secundária do JavaScript. Por exemplo, se você usar um sistema de tipos como TypeScript, poderá adicionar anotações de tipo para seu módulo nativo aqui. Embora o React Native ainda não ofereça suporte à segurança de tipo Native to JS, com essas anotações de tipo, todo o seu código JS será de tipo seguro. Essas anotações também facilitarão a mudança para módulos nativos com segurança de tipo no futuro. Abaixo está um exemplo de adição de segurança de tipo ao Módulo Calendário:

js
/**
+ * Isso expõe o módulo nativo CalendarModule como um módulo JS. Isto tem um
+ * função 'createCalendarEvent' que leva os seguintes parâmetros:
+ *
+ * 1. String name: Uma string que representa o nome do evento
+ * 2. String location: Uma string que representa a localização do evento
+ */
+import {NativeModules} from 'react-native';
+const {CalendarModule} = NativeModules;
+interface CalendarInterface {
+  createCalendarEvent(name: string, location: string): void;
+}
+export default CalendarModule as CalendarInterface;

Nos seus outros arquivos JavaScript você pode acessar o módulo nativo e invocar seu método assim:

jsx
import NativeCalendarModule from './NativeCalendarModule';
+NativeCalendarModule.createCalendarEvent('foo', 'bar');

DICA

Observe que isso pressupõe que o local que você está importando CalendarModule está na mesma hierarquia que CalendarModule.js. Atualize a importação relativa conforme necessário.

Tipos de argumento

Quando um método de módulo nativo é invocado em JavaScript, o React Native converte os argumentos dos objetos JS em seus análogos de objetos Objective-C/Swift. Por exemplo, se o seu método Objective-C Native Module aceita um NSNumber, em JS você precisa chamar o método com um número. React Native cuidará da conversão para você. Abaixo está uma lista dos tipos de argumentos suportados pelos métodos de módulo nativos e os equivalentes JavaScript para os quais eles mapeiam.

OBJECTIVE-CJAVASCRIPT
N SStringstring, ?string
BOOLboolean
doublenumber
NSNumber?number
NSArrayArray, ?Array
NSDictionaryObject, ?Object
RCTResponseSenderBlockFunction (success)
RCTResponseSenderBlock, RCTResponseErrorBlockFunction (failure)
RCTPromiseResolveBlock, RCTPromiseRejectBlockPromise

INFORMAÇÕES

Os seguintes tipos são atualmente suportados, mas não serão suportados em TurboModules. Por favor, evite usá-los.

  • Function (failure) -> RCTResponseErrorBlock
  • Number -> NSInteger
  • Number -> CGFloat
  • Number -> float

Para iOS, você também pode escrever métodos de módulo nativos com qualquer tipo de argumento compatível com a classe RCTConvert (consulte RCTConvert para obter detalhes sobre o que é compatível). Todas as funções auxiliares RCTConvert aceitam um valor JSON como entrada e o mapeiam para um tipo ou classe Objective-C nativo.

Exportando Constantes

Um módulo nativo pode exportar constantes substituindo o método nativo constantsToExport(). Abaixo de constantsToExport() é substituído e retorna um Dicionário que contém uma propriedade de nome de evento padrão que você pode acessar em JavaScript da seguinte forma:

c
- (NSDictionary *)constantsToExport
+{
+ return @{ @"DEFAULT_EVENT_NAME": @"New Event" };
+}

A constante pode então ser acessada invocando getConstants() no módulo nativo em JS da seguinte forma:

js
const {DEFAULT_EVENT_NAME} = CalendarModule.getConstants();
+console.log(DEFAULT_EVENT_NAME);

Tecnicamente, é possível acessar constantes exportadas em constantsToExport() diretamente do objeto NativeModule. Isso não será mais compatível com TurboModules, por isso encorajamos a comunidade a mudar para a abordagem acima para evitar a migração necessária no futuro.

INFORMAÇÕES

Observe que as constantes são exportadas apenas no momento da inicialização, portanto, se você alterar os valores de constantsToExport() no tempo de execução, isso não afetará o ambiente JavaScript.

Para iOS, se você substituir constantsToExport() então você também deve implementar +requireMainQueueSetup para que o React Native saiba se seu módulo precisa ser inicializado no thread principal, antes da execução de qualquer código JavaScript. Caso contrário, você verá um aviso de que no futuro seu módulo poderá ser inicializado em um thread em segundo plano, a menos que você desative explicitamente com +requireMainQueueSetup:. Se o seu módulo não requer acesso ao UIKit, você deve responder a +requerMainQueueSetup com NÃO.

Callback

Os módulos nativos também suportam um tipo único de argumento - um retorno de chamada. Retornos de chamada são usados para passar dados de Objective-C para JavaScript para métodos assíncronos. Eles também podem ser usados para executar JS de forma assíncrona do lado nativo.

Para iOS, os retornos de chamada são implementados usando o tipo RCTResponseSenderBlock. Abaixo do parâmetro de retorno de chamada myCallBack é adicionado ao createCalendarEventMethod():

c
RCT_EXPORT_METHOD(createCalendarEvent:(NSString *)title
+                location:(NSString *)location
+                myCallback:(RCTResponseSenderBlock)callback)

Você pode então invocar o retorno de chamada em sua função nativa, fornecendo qualquer resultado que deseja passar para JavaScript em um array. Observe que RCTResponseSenderBlock aceita apenas um argumento - uma matriz de parâmetros a serem passados para o retorno de chamada JavaScript. Abaixo você retornará o ID de um evento criado em uma chamada anterior.

INFORMAÇÕES

É importante destacar que o retorno de chamada não é invocado imediatamente após a conclusão da função nativa – lembre-se que a comunicação é assíncrona.

c
RCT_EXPORT_METHOD(createCalendarEvent:(NSString *)title location:(NSString *)location callback: (RCTResponseSenderBlock)callback)
+{
+ NSInteger eventId = ...
+ callback(@[@(eventId)]);
+
+ RCTLogInfo(@"Pretending to create an event %@ at %@", title, location);
+}

Este método pode então ser acessado em JavaScript usando o seguinte:

tsx
const onSubmit = () => {
+  CalendarModule.createCalendarEvent(
+    'Party',
+    '04-12-2020',
+    eventId => {
+      console.log(\`Created a new event with id \${eventId}\`);
+    },
+  );
+};

Um módulo nativo deve invocar seu retorno de chamada apenas uma vez. No entanto, ele pode armazenar o retorno de chamada e invocá-lo mais tarde. Esse padrão é frequentemente usado para agrupar APIs iOS que exigem delegados — consulte RCTAlertManager para obter um exemplo. Se o retorno de chamada nunca for invocado, alguma memória será vazada.

Existem duas abordagens para tratamento de erros com retornos de chamada. A primeira é seguir a convenção do Node e tratar o primeiro argumento passado para o array de retorno de chamada como um objeto de erro.

c
RCT_EXPORT_METHOD(createCalendarEventCallback:(NSString *)title location:(NSString *)location callback: (RCTResponseSenderBlock)callback)
+{
+  NSNumber *eventId = [NSNumber numberWithInt:123];
+  callback(@[[NSNull null], eventId]);
+}

Em JavaScript, você pode verificar o primeiro argumento para ver se um erro foi transmitido:

tsx
const onPress = () => {
+  CalendarModule.createCalendarEventCallback(
+    'testName',
+    'testLocation',
+    (error, eventId) => {
+      if (error) {
+        console.error(\`Error found! \${error}\`);
+      }
+      console.log(\`event id \${eventId} returned\`);
+    },
+  );
+};

Outra opção é usar dois retornos de chamada separados: onFailure e onSuccess.

c
RCT_EXPORT_METHOD(createCalendarEventCallback:(NSString *)title
+                  location:(NSString *)location
+                  errorCallback: (RCTResponseSenderBlock)errorCallback
+                  successCallback: (RCTResponseSenderBlock)successCallback)
+{
+  @try {
+    NSNumber *eventId = [NSNumber numberWithInt:123];
+    successCallback(@[eventId]);
+  }
+
+  @catch ( NSException *e ) {
+    errorCallback(@[e]);
+  }
+}

Então, em JavaScript, você pode adicionar um retorno de chamada separado para respostas de erro e sucesso:

tsx
const onPress = () => {
+  CalendarModule.createCalendarEventCallback(
+    'testName',
+    'testLocation',
+    error => {
+      console.error(\`Error found! \${error}\`);
+    },
+    eventId => {
+      console.log(\`event id \${eventId} returned\`);
+    },
+  );
+};

Se você deseja passar objetos semelhantes a erros para JavaScript, use RCTMakeError de RCTUtils.h. No momento, isso apenas passa um dicionário em formato de erro para JavaScript, mas o React Native visa gerar automaticamente objetos de erro JavaScript reais no futuro. Você também pode fornecer um argumento RCTResponseErrorBlock, que é usado para retornos de chamada de erro e aceita um NSError \\* object. Observe que este tipo de argumento não será compatível com TurboModules.

Promises

Módulos nativos também podem cumprir uma promessa, o que pode simplificar seu JavaScript, especialmente ao usar a sintaxe async/await do ES2016. Quando o último parâmetro de um método de módulo nativo é RCTPromiseResolveBlock e RCTPromiseRejectBlock, seu método JS correspondente retornará um objeto JS Promise.

Refatorar o código acima para usar uma promessa em vez de retornos de chamada é assim:

c
RCT_EXPORT_METHOD(createCalendarEvent:(NSString *)title
+                 location:(NSString *)location
+                 resolver:(RCTPromiseResolveBlock)resolve
+                 rejecter:(RCTPromiseRejectBlock)reject)
+{
+ NSInteger eventId = createCalendarEvent();
+ if (eventId) {
+    resolve(@(eventId));
+  } else {
+    reject(@"event_failure", @"no event id returned", nil);
+  }
+}

A contraparte JavaScript deste método retorna uma promessa. Isso significa que você pode usar a palavra-chave await dentro de uma função assíncrona para chamá-la e aguardar seu resultado:

tsx
const onSubmit = async () => {
+  try {
+    const eventId = await CalendarModule.createCalendarEvent(
+      'Party',
+      'my house',
+    );
+    console.log(\`Created a new event with id \${eventId}\`);
+  } catch (e) {
+    console.error(e);
+  }
+};

Enviando eventos para JavaScript

Módulos nativos podem sinalizar eventos para o JavaScript sem serem invocados diretamente. Por exemplo, você pode sinalizar para o JavaScript um lembrete de que um evento de calendário do aplicativo de calendário nativo do iOS ocorrerá em breve. A maneira preferida de fazer isso é subclassificar RCTEventEmitter, implementar SupportedEvents e chamar sendEventWithName:

Atualize sua classe de cabeçalho para importar RCTEventEmitter e subclasse RCTEventEmitter:

c
//  CalendarModule.h
+
+#import <React/RCTBridgeModule.h>
+#import <React/RCTEventEmitter.h>
+
+@interface CalendarModule : RCTEventEmitter <RCTBridgeModule>
+@end

O código JavaScript pode assinar esses eventos criando uma nova instância NativeEventEmitter em torno do seu módulo.

Você receberá um aviso se gastar recursos desnecessariamente emitindo um evento enquanto não houver ouvintes. Para evitar isso e otimizar a carga de trabalho do seu módulo (por exemplo, cancelando a assinatura de notificações upstream ou pausando tarefas em segundo plano), você pode substituir startObserving e stopObserving em sua subclasse RCTEventEmitter.

c
@implementation CalendarManager
+{
+  bool hasListeners;
+}
+
+// Será chamado quando o primeiro ouvinte deste módulo for adicionado.
+-(void)startObserving {
+    hasListeners = YES;
+    // Configure quaisquer ouvintes upstream ou tarefas em segundo plano conforme necessário
+}
+
+// Será chamado quando o último ouvinte deste módulo for removido ou no dealloc.
+-(void)stopObserving {
+    hasListeners = NO;
+    // Remove upstream listeners, stop unnecessary background tasks
+}
+
+- (void)calendarEventReminderReceived:(NSNotification *)notification
+{
+  NSString *eventName = notification.userInfo[@"name"];
+  if (hasListeners) {//Só envia eventos se alguém estiver ouvindo
+    [self sendEventWithName:@"EventReminder" body:@{@"name": eventName}];
+  }
+}

Threading

A menos que o módulo nativo forneça sua própria fila de métodos, ele não deve fazer nenhuma suposição sobre em qual thread está sendo chamado. Atualmente, se um módulo nativo não fornecer uma fila de métodos, o React Native criará uma fila GCD separada para ele e invocará seus métodos lá. Observe que este é um detalhe de implementação e pode mudar. Se você quiser fornecer explicitamente uma fila de métodos para um módulo nativo, substitua o método (dispatch_queue_t) methodQueue no módulo nativo. Por exemplo, se for necessário usar uma API iOS somente de thread principal, ele deverá especificar isso por meio de:

c
- (dispatch_queue_t)methodQueue
+{
+  return dispatch_get_main_queue();
+}

Da mesma forma, se uma operação demorar muito para ser concluída, o módulo nativo poderá especificar sua própria fila para executar as operações. Novamente, atualmente o React Native fornecerá uma fila de métodos separada para seu módulo nativo, mas este é um detalhe de implementação no qual você não deve confiar. Se você não fornecer sua própria fila de métodos, no futuro, as operações de longa execução do seu módulo nativo poderão acabar bloqueando a execução de chamadas assíncronas em outros módulos nativos não relacionados. O módulo RCTAsyncLocalStorage aqui, por exemplo, cria sua própria fila para que a fila React não seja bloqueada aguardando um acesso potencialmente lento ao disco.

c
- (dispatch_queue_t)methodQueue
+{
+ return dispatch_queue_create("com.facebook.React.AsyncLocalStorageQueue", DISPATCH_QUEUE_SERIAL);
+}

O methodQueue especificado será compartilhado por todos os métodos do seu módulo. Se apenas um dos seus métodos for de longa duração (ou precisar ser executado em uma fila diferente dos outros por algum motivo), você poderá usar dispatch_async dentro do método para executar o código desse método específico em outra fila, sem afetar os outros:

c
RCT_EXPORT_METHOD(doSomethingExpensive:(NSString *)param callback:(RCTResponseSenderBlock)callback)
+{
+ dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
+   // Call long-running code on background thread
+   ...
+   // You can invoke callback from any thread/queue
+   callback(@[...]);
+ });
+}

Compartilhando filas de despacho entre módulos

O método methodQueue será chamado uma vez quando o módulo for inicializado e então retido pelo React Native, portanto não há necessidade de manter uma referência à fila, a menos que você queira usá-la em seu módulo. No entanto, se desejar compartilhar a mesma fila entre vários módulos, você precisará garantir que retém e retorna a mesma instância de fila para cada um deles.

Injeção de dependência

O React Native criará e inicializará automaticamente quaisquer módulos nativos registrados. No entanto, você pode desejar criar e inicializar suas próprias instâncias de módulo para, por exemplo, injetar dependências.

Você pode fazer isso criando uma classe que implemente o protocolo RCTBridgeDelegate, inicializando um RCTBridge com o delegado como argumento e inicializando um RCTRootView com a ponte inicializada.

c
id<RCTBridgeDelegate> moduleInitialiser = [[classThatImplementsRCTBridgeDelegate alloc] init];
+
+RCTBridge *bridge = [[RCTBridge alloc] initWithDelegate:moduleInitialiser launchOptions:nil];
+
+RCTRootView *rootView = [[RCTRootView alloc]
+                        initWithBridge:bridge
+                            moduleName:kModuleName
+                     initialProperties:nil];

Exportando Swift

Swift não tem suporte para macros, então expor módulos nativos e seus métodos ao JavaScript dentro do React Native requer um pouco mais de configuração. No entanto, funciona relativamente da mesma forma. Digamos que você tenha o mesmo CalendarModule, mas como uma classe Swift:

swift
// CalendarManager.swift
+
+@objc(CalendarManager)
+class CalendarManager: NSObject {
+
+ @objc(addEvent:location:date:)
+ func addEvent(_ name: String, location: String, date: NSNumber) -> Void {
+   // A data está pronta para uso!
+ }
+
+ @objc
+ func constantsToExport() -> [String: Any]! {
+   return ["someKey": "someValue"]
+ }
+
+}

INFORMAÇÕES

É importante usar os modificadores @objc para garantir que a classe e as funções sejam exportadas corretamente para o tempo de execução do Objective-C.

Em seguida, crie um arquivo de implementação privado que registrará as informações necessárias com React Native:

c
// CalendarManagerBridge.m
+#import <React/RCTBridgeModule.h>
+
+@interface RCT_EXTERN_MODULE(CalendarManager, NSObject)
+
+RCT_EXTERN_METHOD(addEvent:(NSString *)name location:(NSString *)location date:(nonnull NSNumber *)date)
+
+@end

Para aqueles que são novos em Swift e Objective-C, sempre que misturar as duas linguagens em um projeto iOS, você também precisará de um arquivo de ponte adicional, conhecido como cabeçalho de ponte, para expor os arquivos de Objective-C ao Swift. O Xcode se oferecerá para criar este arquivo de cabeçalho para você se você adicionar seu arquivo Swift ao seu aplicativo por meio da opção de menu File > New File. Você precisará importar RCTBridgeModule.h neste arquivo de cabeçalho.

c
// CalendarManager-Bridging-Header.h
+#import <React/RCTBridgeModule.h>

Você também pode usar RCT_EXTERN_REMAP_MODULE e _RCT_EXTERN_REMAP_METHOD para alterar o nome JavaScript do módulo ou métodos que você está exportando. Para obter mais informações, consulte RCTBridgeModule.

INFORMAÇÕES

Importante ao criar módulos de terceiros: Bibliotecas estáticas com Swift são suportadas apenas no Xcode 9 e posterior. Para que o projeto Xcode seja compilado quando você usa Swift na biblioteca estática do iOS incluída no módulo, o projeto principal do seu aplicativo deve conter o código Swift e um cabeçalho de ponte em si. Se o projeto do seu aplicativo não contiver nenhum código Swift, uma solução alternativa poderá ser um único arquivo .swift vazio e um cabeçalho de ponte vazio.

Nomes de métodos reservados

invalidate()

Os módulos nativos podem estar em conformidade com o protocolo RCTInvalidating no iOS implementando o método invalidate(). Este método pode ser invocado quando a ponte nativa é invalidada (ou seja: no recarregamento do devmode). Use este mecanismo conforme necessário para fazer a limpeza necessária para seu módulo nativo.

`,138),h=[p];function r(d,k,c,E,u,g){return i(),a("div",null,h)}const y=s(l,[["render",r]]);export{v as __pageData,y as default}; diff --git a/vitepress/docs/.vitepress/dist/assets/docs_native-modules-ios.md.B8RNq7sy.lean.js b/vitepress/docs/.vitepress/dist/assets/docs_native-modules-ios.md.B8RNq7sy.lean.js new file mode 100644 index 0000000..3274d30 --- /dev/null +++ b/vitepress/docs/.vitepress/dist/assets/docs_native-modules-ios.md.B8RNq7sy.lean.js @@ -0,0 +1 @@ +import{_ as s,c as a,o as i,a4 as e}from"./chunks/framework.nQaBHiNx.js";const n="/assets/313507258-a79717d3-36f2-41a5-b120-dd2bc51232eb.DP5RsCfL.png",t="/assets/313507304-f06738b3-4be6-4734-8bea-1f87556a0df3.CxBYw3G2.png",o="/assets/313508003-11f8175a-c432-4050-91e5-88b84a5d726b.Dw_qJO7t.png",v=JSON.parse('{"title":"Módulos nativos iOS","description":"","frontmatter":{},"headers":[],"relativePath":"docs/native-modules-ios.md","filePath":"docs/native-modules-ios.md"}'),l={name:"docs/native-modules-ios.md"},p=e("",138),h=[p];function r(d,k,c,E,u,g){return i(),a("div",null,h)}const y=s(l,[["render",r]]);export{v as __pageData,y as default}; diff --git a/vitepress/docs/.vitepress/dist/assets/docs_native-modules-setup.md.DYhKxXRl.js b/vitepress/docs/.vitepress/dist/assets/docs_native-modules-setup.md.DYhKxXRl.js new file mode 100644 index 0000000..9e9811f --- /dev/null +++ b/vitepress/docs/.vitepress/dist/assets/docs_native-modules-setup.md.DYhKxXRl.js @@ -0,0 +1 @@ +import{_ as a,c as e,o as s,a4 as o}from"./chunks/framework.nQaBHiNx.js";const v=JSON.parse('{"title":"Configuração do pacote NPM de módulos nativos","description":"","frontmatter":{},"headers":[],"relativePath":"docs/native-modules-setup.md","filePath":"docs/native-modules-setup.md"}'),t={name:"docs/native-modules-setup.md"},i=o('

Configuração do pacote NPM de módulos nativos

INFORMAÇÕES

Módulo Nativo e Componentes Nativos são nossas tecnologias estáveis usadas pela arquitetura legada. Eles serão descontinuados no futuro, quando a Nova Arquitetura estiver estável. A nova arquitetura usa Turbo Native Module e Fabric Native Components para obter resultados semelhantes.

Módulos nativos são geralmente distribuídos como pacotes npm, exceto que além do JavaScript usual eles incluirão algum código nativo por plataforma. Para entender mais sobre os pacotes npm, este guia pode ser útil.

Para configurar a estrutura básica do projeto para um módulo nativo, usaremos a ferramenta da comunidade chamada create-react-native-library. Você pode ir mais longe e se aprofundar em como essa biblioteca funciona, mas para nossas necessidades executaremos apenas o script básico:

bash
npx create-react-native-library@latest react-native-awesome-module

Onde react-native-awesome-module é o nome que você gostaria para o novo módulo. Depois de fazer isso, você navegará até a pasta react-native-awesome-module e inicializará o projeto de exemplo executando:

bash
yarn

Quando o bootstrap estiver concluído, você poderá iniciar o aplicativo de exemplo executando um dos seguintes comandos:

bash
yarn example android
bash
yarn example ios

Quando todas as etapas acima forem concluídas, você poderá continuar com os guias de módulos nativos do Android ou módulos nativos do iOS para adicionar algum código.

INFORMAÇÕES

Para uma configuração menos opinativa, dê uma olhada na ferramenta de terceiros create-react-native-module.

',11),n=[i];function r(d,c,l,p,u,h){return s(),e("div",null,n)}const g=a(t,[["render",r]]);export{v as __pageData,g as default}; diff --git a/vitepress/docs/.vitepress/dist/assets/docs_native-modules-setup.md.DYhKxXRl.lean.js b/vitepress/docs/.vitepress/dist/assets/docs_native-modules-setup.md.DYhKxXRl.lean.js new file mode 100644 index 0000000..e9ae18a --- /dev/null +++ b/vitepress/docs/.vitepress/dist/assets/docs_native-modules-setup.md.DYhKxXRl.lean.js @@ -0,0 +1 @@ +import{_ as a,c as e,o as s,a4 as o}from"./chunks/framework.nQaBHiNx.js";const v=JSON.parse('{"title":"Configuração do pacote NPM de módulos nativos","description":"","frontmatter":{},"headers":[],"relativePath":"docs/native-modules-setup.md","filePath":"docs/native-modules-setup.md"}'),t={name:"docs/native-modules-setup.md"},i=o("",11),n=[i];function r(d,c,l,p,u,h){return s(),e("div",null,n)}const g=a(t,[["render",r]]);export{v as __pageData,g as default}; diff --git a/vitepress/docs/.vitepress/dist/assets/docs_navigation.md.C1M6AWCZ.js b/vitepress/docs/.vitepress/dist/assets/docs_navigation.md.C1M6AWCZ.js new file mode 100644 index 0000000..1c72f28 --- /dev/null +++ b/vitepress/docs/.vitepress/dist/assets/docs_navigation.md.C1M6AWCZ.js @@ -0,0 +1 @@ +import{_ as a,c as e,o,a4 as t}from"./chunks/framework.nQaBHiNx.js";const u=JSON.parse('{"title":"Navegando entre telas","description":"","frontmatter":{},"headers":[],"relativePath":"docs/navigation.md","filePath":"docs/navigation.md"}'),i={name:"docs/navigation.md"},n=t('

Navegando entre telas

Os aplicativos móveis raramente são compostos de uma única tela. O gerenciamento da apresentação e da transição entre várias telas normalmente é feito pelo que é conhecido como navegador.

Este guia aponta para os vários componentes de navegação disponíveis no React Native. Se você está começando com a navegação, provavelmente desejará usar o React Navigation. React Navigation fornece uma solução de navegação simples, com a capacidade de apresentar navegação de pilha comum e padrões de navegação com guias no Android e iOS.

Se você estiver integrando o React Native em um aplicativo que já gerencia a navegação nativamente ou procurando uma alternativa ao React Navigation, a biblioteca a seguir fornece navegação nativa em ambas as plataformas: react-native-navigation.

A solução comunitária para navegação é uma biblioteca independente que permite aos desenvolvedores configurar as telas de um aplicativo com algumas linhas de código.

Para uma introdução completa ao React Navigation, siga o Guia de primeiros passos do React Navigation.

React Native Navigation

Conforme afirmado acima, react-native-navigation é outra solução para navegação em aplicativos react nativos. É uma biblioteca que oferece soluções para navegações básicas e avançadas.

Para uma introdução completa ao React Native Navigation, siga o Guia de primeiros passos do React Native Navigation.

',10),r=[n];function s(c,v,d,g,l,p){return o(),e("div",null,r)}const h=a(i,[["render",s]]);export{u as __pageData,h as default}; diff --git a/vitepress/docs/.vitepress/dist/assets/docs_navigation.md.C1M6AWCZ.lean.js b/vitepress/docs/.vitepress/dist/assets/docs_navigation.md.C1M6AWCZ.lean.js new file mode 100644 index 0000000..3de654d --- /dev/null +++ b/vitepress/docs/.vitepress/dist/assets/docs_navigation.md.C1M6AWCZ.lean.js @@ -0,0 +1 @@ +import{_ as a,c as e,o,a4 as t}from"./chunks/framework.nQaBHiNx.js";const u=JSON.parse('{"title":"Navegando entre telas","description":"","frontmatter":{},"headers":[],"relativePath":"docs/navigation.md","filePath":"docs/navigation.md"}'),i={name:"docs/navigation.md"},n=t("",10),r=[n];function s(c,v,d,g,l,p){return o(),e("div",null,r)}const h=a(i,[["render",s]]);export{u as __pageData,h as default}; diff --git a/vitepress/docs/.vitepress/dist/assets/docs_network.md.B8Zp_fLB.js b/vitepress/docs/.vitepress/dist/assets/docs_network.md.B8Zp_fLB.js new file mode 100644 index 0000000..2a4644b --- /dev/null +++ b/vitepress/docs/.vitepress/dist/assets/docs_network.md.B8Zp_fLB.js @@ -0,0 +1,126 @@ +import{_ as s,c as i,o as a,a4 as n}from"./chunks/framework.nQaBHiNx.js";const g=JSON.parse('{"title":"Rede","description":"","frontmatter":{},"headers":[],"relativePath":"docs/network.md","filePath":"docs/network.md"}'),e={name:"docs/network.md"},t=n(`

Rede

Muitos aplicativos móveis precisam carregar recursos de uma URL remota. Você pode querer fazer uma solicitação POST para uma API REST ou pode precisar buscar um pedaço de conteúdo estático de outro servidor.

Usando o Fetch

React Native fornece a API Fetch para suas necessidades de rede. Fetch parecerá familiar se você já usou XMLHttpRequest ou outras APIs de rede antes. Você pode consultar o guia do MDN sobre como usar o Fetch para obter informações adicionais.

Fazendo requisições

Para buscar conteúdo de um URL arbitrário, você pode passar o URL a ser buscado:

js
fetch('https://mywebsite.com/mydata.json');

Fetch também usa um segundo argumento opcional que permite personalizar a solicitação HTTP. Você pode especificar cabeçalhos adicionais ou fazer uma solicitação POST:

js
fetch('https://mywebsite.com/endpoint/', {
+  method: 'POST',
+  headers: {
+    Accept: 'application/json',
+    'Content-Type': 'application/json',
+  },
+  body: JSON.stringify({
+    firstParam: 'yourValue',
+    secondParam: 'yourOtherValue',
+  }),
+});

Dê uma olhada na documentação do Fetch Request para obter uma lista completa de propriedades.

Lidando com a resposta

Os exemplos acima mostram como você pode fazer uma solicitação. Em muitos casos, você desejará fazer algo com a resposta.

A rede é uma operação inerentemente assíncrona. O método Fetch retornará uma Promise que simplifica a escrita de código que funciona de maneira assíncrona:

js
const getMoviesFromApi = () => {
+  return fetch('https://reactnative.dev/movies.json')
+    .then(response => response.json())
+    .then(json => {
+      return json.movies;
+    })
+    .catch(error => {
+      console.error(error);
+    });
+};

Você também pode usar a sintaxe async/await em um aplicativo React Native:

js
const getMoviesFromApiAsync = async () => {
+  try {
+    const response = await fetch(
+      'https://reactnative.dev/movies.json',
+    );
+    const json = await response.json();
+    return json.movies;
+  } catch (error) {
+    console.error(error);
+  }
+};

Não se esqueça de capturar quaisquer erros que possam ser lançados pela busca, caso contrário eles serão descartados silenciosamente.

js
import React, {useEffect, useState} from 'react';
+import {ActivityIndicator, FlatList, Text, View} from 'react-native';
+
+type Movie = {
+  id: string;
+  title: string;
+  releaseYear: string;
+};
+
+const App = () => {
+  const [isLoading, setLoading] = useState(true);
+  const [data, setData] = useState<Movie[]>([]);
+
+  const getMovies = async () => {
+    try {
+      const response = await fetch('https://reactnative.dev/movies.json');
+      const json = await response.json();
+      setData(json.movies);
+    } catch (error) {
+      console.error(error);
+    } finally {
+      setLoading(false);
+    }
+  };
+
+  useEffect(() => {
+    getMovies();
+  }, []);
+
+  return (
+    <View style={{flex: 1, padding: 24}}>
+      {isLoading ? (
+        <ActivityIndicator />
+      ) : (
+        <FlatList
+          data={data}
+          keyExtractor={({id}) => id}
+          renderItem={({item}) => (
+            <Text>
+              {item.title}, {item.releaseYear}
+            </Text>
+          )}
+        />
+      )}
+    </View>
+  );
+};
+
+export default App;

Resposta:

Star Wars, 1977
+Back to the Future, 1985
+The Matrix, 1999
+Inception, 2010
+Interstellar, 2014

Por padrão, o iOS 9.0 ou posterior aplica o App Transport Secruity (ATS). O ATS requer qualquer conexão HTTP para usar HTTPS. Se você precisar buscar em um URL de texto simples (que comece com http), primeiro você precisará adicionar uma exceção ATS. Se você souber antecipadamente a quais domínios precisará acessar, será mais seguro adicionar exceções apenas para esses domínios; se os domínios não forem conhecidos até o tempo de execução, você poderá desativar o ATS completamente. Observe, entretanto, que a partir de janeiro de 2017, a revisão da App Store da Apple exigirá uma justificativa razoável para desativar o ATS. Consulte a documentação da Apple para obter mais informações.

No Android, a partir do nível 28 da API, o tráfego de texto simples também é bloqueado por padrão. Esse comportamento pode ser substituído definindo android:usesCleartextTraffic no arquivo de manifesto do aplicativo.

Usando outras bibliotecas de rede

A API XMLHttpRequest está integrada ao React Native. Isso significa que você pode usar bibliotecas de terceiros, como frisbee ou axios, que dependem dele, ou pode usar a API XMLHttpRequest diretamente, se preferir.

js
const request = new XMLHttpRequest();
+request.onreadystatechange = e => {
+  if (request.readyState !== 4) {
+    return;
+  }
+
+  if (request.status === 200) {
+    console.log('success', request.responseText);
+  } else {
+    console.warn('error');
+  }
+};
+
+request.open('GET', 'https://mywebsite.com/endpoint/');
+request.send();

O modelo de segurança para XMLHttpRequest é diferente do modelo da web, pois não há conceito de CORS em aplicativos nativos.

Suporte WebSocket

React Native também oferece suporte a WebSockets, um protocolo que fornece canais de comunicação full-duplex em uma única conexão TCP.

js
const ws = new WebSocket('ws://host.com/path');
+
+ws.onopen = () => {
+  // conexão aberta
+  ws.send('something'); // envia uma mensagem
+};
+
+ws.onmessage = e => {
+  // uma mensagem foi recebida
+  console.log(e.data);
+};
+
+ws.onerror = e => {
+  // um erro aconteceu
+  console.log(e.message);
+};
+
+ws.onclose = e => {
+  // conexão fechada
+  console.log(e.code, e.reason);
+};

As opções a seguir não estão funcionando atualmente com busca

  • redirect:manual
  • credentials:omit
  • Ter cabeçalhos com o mesmo nome no Android resultará na presença apenas do mais recente. Uma solução temporária pode ser encontrada aqui: https://github.com/facebook/react-native/issues/18837#issuecomment-398779994.
  • A autenticação baseada em cookies é atualmente instável. Você pode ver algumas das questões levantadas aqui: https://github.com/facebook/react-native/issues/23185
  • No mínimo no iOS, quando redirecionado através de um 302, se um cabeçalho Set-Cookie estiver presente, o cookie não será definido corretamente. Como o redirecionamento não pode ser tratado manualmente, isso pode causar um cenário em que ocorrem solicitações infinitas se o redirecionamento for o resultado de uma sessão expirada.

Configurando NSURLSession no iOS

Para alguns aplicativos, pode ser apropriado fornecer um NSURLSessionConfiguration personalizado para o NSURLSession subjacente que é usado para solicitações de rede em um aplicativo React Native em execução no iOS. Por exemplo, pode ser necessário definir uma string de agente de usuário personalizada para todas as solicitações de rede provenientes do aplicativo ou fornecer NSURLSession com um NSURLSessionConfiguration efêmero. A função RCTSetCustomNSURLSessionConfigurationProvider permite tal customização. Lembre-se de adicionar a seguinte importação ao arquivo no qual RCTSetCustomNSURLSessionConfigurationProvider será chamado:

swift
#import <React/RCTHTTPRequestHandler.h>

RCTSetCustomNSURLSessionConfigurationProvider deve ser chamado no início do ciclo de vida do aplicativo para que esteja prontamente disponível quando necessário pelo React, por exemplo:

-(void)application:(__unused UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
+
+  // set RCTSetCustomNSURLSessionConfigurationProvider
+  RCTSetCustomNSURLSessionConfigurationProvider(^NSURLSessionConfiguration *{
+     NSURLSessionConfiguration *configuration = [NSURLSessionConfiguration defaultSessionConfiguration];
+     // configure the session
+     return configuration;
+  });
+
+  // set up React
+  _bridge = [[RCTBridge alloc] initWithDelegate:self launchOptions:launchOptions];
`,37),p=[t];function l(h,k,r,o,d,E){return a(),i("div",null,p)}const y=s(e,[["render",l]]);export{g as __pageData,y as default}; diff --git a/vitepress/docs/.vitepress/dist/assets/docs_network.md.B8Zp_fLB.lean.js b/vitepress/docs/.vitepress/dist/assets/docs_network.md.B8Zp_fLB.lean.js new file mode 100644 index 0000000..4a3b527 --- /dev/null +++ b/vitepress/docs/.vitepress/dist/assets/docs_network.md.B8Zp_fLB.lean.js @@ -0,0 +1 @@ +import{_ as s,c as i,o as a,a4 as n}from"./chunks/framework.nQaBHiNx.js";const g=JSON.parse('{"title":"Rede","description":"","frontmatter":{},"headers":[],"relativePath":"docs/network.md","filePath":"docs/network.md"}'),e={name:"docs/network.md"},t=n("",37),p=[t];function l(h,k,r,o,d,E){return a(),i("div",null,p)}const y=s(e,[["render",l]]);export{g as __pageData,y as default}; diff --git a/vitepress/docs/.vitepress/dist/assets/docs_optimizing-flatlist-configuration.md.CfT25_mU.js b/vitepress/docs/.vitepress/dist/assets/docs_optimizing-flatlist-configuration.md.CfT25_mU.js new file mode 100644 index 0000000..eff5305 --- /dev/null +++ b/vitepress/docs/.vitepress/dist/assets/docs_optimizing-flatlist-configuration.md.CfT25_mU.js @@ -0,0 +1,14 @@ +import{_ as e,c as a,o as s,a4 as i}from"./chunks/framework.nQaBHiNx.js";const k=JSON.parse('{"title":"Otimizando a configuração da Flatlist","description":"","frontmatter":{},"headers":[],"relativePath":"docs/optimizing-flatlist-configuration.md","filePath":"docs/optimizing-flatlist-configuration.md"}'),o={name:"docs/optimizing-flatlist-configuration.md"},t=i(`

Otimizando a configuração da Flatlist

Termos

  • VirtualizedList: O componente por trás do FlatList (implementação do conceito de Lista Virtual do React Native).
  • Consumo de memória: quanta informação sobre sua lista está armazenada na memória, o que pode causar falha no aplicativo.
  • Capacidade de resposta: capacidade do aplicativo de responder às interações. A baixa capacidade de resposta, por exemplo, ocorre quando você toca em um componente e ele espera um pouco para responder, em vez de responder imediatamente conforme o esperado.
  • Áreas em branco: quando VirtualizedList não consegue renderizar seus itens com rapidez suficiente, você pode inserir uma parte de sua lista com componentes não renderizados que aparecem como espaço em branco.
  • Viewport: a área visível do conteúdo que é renderizada em pixels.
  • Window: A área na qual os itens devem ser montados, que geralmente é muito maior que a janela de visualização.

Props

Aqui está uma lista de acessórios que podem ajudar a melhorar o desempenho do FlatList:

removeClippedSubviews

TIPOPADRÃO
BooleanFalse

Se for true, as visualizações que estão fora da viewport serão desanexadas da hierarquia de visualizações nativas.

Prós: Isso reduz o tempo gasto no thread principal e, portanto, reduz o risco de perda de quadros, excluindo visualizações fora da janela de visualização da renderização nativa e das travessias de desenho.

Contras: Esteja ciente de que esta implementação pode ter bugs, como conteúdo ausente (observado principalmente no iOS), especialmente se você estiver fazendo coisas complexas com transformações e/ou posicionamento absoluto. Observe também que isso não economiza memória significativa porque as visualizações não são desalocadas, apenas desanexadas.

maxToRenderPerBatch

TIPOPADRÃO
Number10

É um suporte VirtualizedList que pode ser passado por FlatList. Isso controla a quantidade de itens renderizados por lote, que é o próximo pedaço de itens renderizados em cada pergaminho.

Prós: Definir um número maior significa menos áreas em branco visuais durante a rolagem (aumenta a taxa de preenchimento).

Contras: mais itens por lote significam períodos mais longos de execução de JavaScript, potencialmente bloqueando o processamento de outros eventos, como clicks, prejudicando a capacidade de resposta.

updateCellsBatchingPeriod

TIPOPADRÃO
Number50

Enquanto maxToRenderPerBatch informa a quantidade de itens renderizados por lote, a configuração updateCellsBatchingPeriod informa ao VirtualizedList o atraso em milissegundos entre as renderizações em lote (com que frequência seu componente renderizará os itens em janela).

Prós: combinar esta propriedade com maxToRenderPerBatch dá a você o poder de, por exemplo, renderizar mais itens em um lote menos frequente ou menos itens em um lote mais frequente.

Contras: Lotes menos frequentes podem causar áreas em branco. Lotes mais frequentes podem causar problemas de capacidade de resposta.

initialNumToRender

TIPOPADRÃO
Number10

A quantidade inicial de itens a serem renderizados.

Prós: Defina o número preciso de itens que cobririam a tela de cada dispositivo. Isso pode ser um grande aumento de desempenho para a renderização inicial.

Contras: Definir um initialNumToRender baixo pode causar áreas em branco, especialmente se for muito pequeno para cobrir a janela de visualização na renderização inicial.

windowSize

TIPOPADRÃO
Number21

O número passado aqui é uma unidade de medida onde 1 é equivalente à altura da sua janela de visualização. O valor padrão é 21 (10 viewports acima, 10 abaixo e uma intermediária).

Prós: windowSize maior resultará em menos chance de ver espaços em branco durante a rolagem. Por outro lado, windowSize menor resultará em menos itens montados simultaneamente, economizando memória.

Contras: Para um tamanho de janela maior, você terá mais consumo de memória. Para um tamanho de janela menor, você terá uma chance maior de ver áreas em branco.

Lista de itens

Abaixo estão algumas dicas sobre os componentes dos itens da lista. Eles são o núcleo da sua lista, por isso precisam ser rápidos.

Use componentes básicos

Quanto mais complexos forem seus componentes, mais lento eles serão renderizados. Tente evitar muita lógica e aninhamento nos itens da sua lista. Se você reutiliza muito esse componente de item de lista em seu aplicativo, crie um componente apenas para suas listas grandes e faça-as com o mínimo de lógica e aninhamento possível.

Use componentes leves

Quanto mais pesados forem seus componentes, mais lento eles serão renderizados. Evite imagens pesadas (use uma versão recortada ou miniatura para os itens da lista, o menor possível). Converse com sua equipe de design, use o mínimo possível de efeitos, interações e informações em sua lista. Mostre-os nos detalhes do seu item.

Usar shouldComponentUpdate

Implemente a verificação de atualização em seus componentes. O PureComponent do React implementa um shouldComponentUpdate com comparação superficial. Isso é caro aqui porque precisa verificar todos os seus props. Se você deseja um bom desempenho em nível de bits, crie as regras mais rígidas para os componentes dos itens da lista, verificando apenas os props que podem mudar. Se sua lista for básica o suficiente, você pode até usar

js
shouldComponentUpdate() {
+  return false
+}

Use imagens otimizadas em cache

Você pode usar os pacotes da comunidade (como react-native-fast-image de @DylanVann) para obter imagens com melhor desempenho. Cada imagem na sua lista é uma nova instância de Image(). Quanto mais rápido ele atingir o gancho carregado, mais rápido seu thread JavaScript ficará livre novamente.

Use getItemLayout

Se todos os componentes do item da sua lista tiverem a mesma altura (ou largura, para uma lista horizontal), fornecer a propriedade getItemLayout elimina a necessidade de sua FlatList gerenciar cálculos de layout assíncronos. Esta é uma técnica de otimização muito desejável.

Se seus componentes têm tamanho dinâmico e você realmente precisa de desempenho, pergunte à sua equipe de design se eles podem pensar em um redesenho para ter um melhor desempenho.

Use keyExtractor ou key

Você pode definir o keyExtractor para o seu componente FlatList. Este suporte é usado para armazenamento em cache e como chave React para rastrear a reordenação de itens.

Você também pode usar um prop key em seu componente de item.

Evite função anônima em renderItem

Para componentes funcionais, mova a função renderItem para fora do JSX retornado. Além disso, certifique-se de que ele esteja encapsulado em um gancho useCallback para evitar que seja recriado a cada renderização.

Para componentes de classe, mova a função renderItem para fora da função de renderização, para que ela não se recrie cada vez que a função de renderização for chamada.

jsx
const renderItem = useCallback(({item}) => (
+   <View key={item.key}>
+      <Text>{item.title}</Text>
+   </View>
+ ), []);
+
+return (
+  // ...
+
+  <FlatList data={items} renderItem={renderItem} />;
+  // ...
+);
`,51),n=[t];function r(d,l,p,c,m,h){return s(),a("div",null,n)}const g=e(o,[["render",r]]);export{k as __pageData,g as default}; diff --git a/vitepress/docs/.vitepress/dist/assets/docs_optimizing-flatlist-configuration.md.CfT25_mU.lean.js b/vitepress/docs/.vitepress/dist/assets/docs_optimizing-flatlist-configuration.md.CfT25_mU.lean.js new file mode 100644 index 0000000..3d822fc --- /dev/null +++ b/vitepress/docs/.vitepress/dist/assets/docs_optimizing-flatlist-configuration.md.CfT25_mU.lean.js @@ -0,0 +1 @@ +import{_ as e,c as a,o as s,a4 as i}from"./chunks/framework.nQaBHiNx.js";const k=JSON.parse('{"title":"Otimizando a configuração da Flatlist","description":"","frontmatter":{},"headers":[],"relativePath":"docs/optimizing-flatlist-configuration.md","filePath":"docs/optimizing-flatlist-configuration.md"}'),o={name:"docs/optimizing-flatlist-configuration.md"},t=i("",51),n=[t];function r(d,l,p,c,m,h){return s(),a("div",null,n)}const g=e(o,[["render",r]]);export{k as __pageData,g as default}; diff --git a/vitepress/docs/.vitepress/dist/assets/docs_out-of-tree-platforms.md.Dgy9KTGW.js b/vitepress/docs/.vitepress/dist/assets/docs_out-of-tree-platforms.md.Dgy9KTGW.js new file mode 100644 index 0000000..0447786 --- /dev/null +++ b/vitepress/docs/.vitepress/dist/assets/docs_out-of-tree-platforms.md.Dgy9KTGW.js @@ -0,0 +1,8 @@ +import{_ as a,c as e,o,a4 as t}from"./chunks/framework.nQaBHiNx.js";const k=JSON.parse('{"title":"Plataformas fora da árvore","description":"","frontmatter":{},"headers":[],"relativePath":"docs/out-of-tree-platforms.md","filePath":"docs/out-of-tree-platforms.md"}'),s={name:"docs/out-of-tree-platforms.md"},r=t(`

Plataformas fora da árvore

React Native não é apenas para dispositivos Android e iOS - nossos parceiros e a comunidade mantêm projetos que levam o React Native para outras plataformas, como:

De parceiros

Da comunidade

Criando sua própria plataforma React Native

No momento, o processo de criação de uma plataforma React Native do zero não está muito bem documentado - um dos objetivos da próxima re-arquitetura (Fabric) é facilitar a manutenção de uma plataforma.

Bundling

A partir do React Native 0.57, agora você pode registrar sua plataforma React Native com o empacotador JavaScript do React Native, Metro. Isso significa que você pode passar o --platform example para o pacote npx react-native e ele procurará arquivos JavaScript com o sufixo .example.js.

Para cadastrar sua plataforma no RNPM, o nome do seu módulo deve corresponder a um destes padrões:

  • react-native-example - Ele irá pesquisar todos os módulos de nível superior que começam com react-native-
  • @org/react-native-example - Procurará módulos que começam com react-native- em qualquer escopo
  • @react-native-example/module - Ele pesquisará em todos os módulos sob escopos com nomes começando com @react-native-

Você também deve ter uma entrada em seu package.json assim:

json
{
+  "rnpm": {
+    "haste": {
+      "providesModuleNodeModules": ["react-native-example"],
+      "platforms": ["example"]
+    }
+  }
+}

"providesModuleNodeModules" é uma matriz de módulos que serão adicionados ao caminho de pesquisa do módulo Haste, e "platforms" é uma matriz de sufixos de plataforma que serão adicionados como plataformas válidas.

`,15),i=[r];function n(l,c,d,p,m,u){return o(),e("div",null,i)}const f=a(s,[["render",n]]);export{k as __pageData,f as default}; diff --git a/vitepress/docs/.vitepress/dist/assets/docs_out-of-tree-platforms.md.Dgy9KTGW.lean.js b/vitepress/docs/.vitepress/dist/assets/docs_out-of-tree-platforms.md.Dgy9KTGW.lean.js new file mode 100644 index 0000000..b9e6365 --- /dev/null +++ b/vitepress/docs/.vitepress/dist/assets/docs_out-of-tree-platforms.md.Dgy9KTGW.lean.js @@ -0,0 +1 @@ +import{_ as a,c as e,o,a4 as t}from"./chunks/framework.nQaBHiNx.js";const k=JSON.parse('{"title":"Plataformas fora da árvore","description":"","frontmatter":{},"headers":[],"relativePath":"docs/out-of-tree-platforms.md","filePath":"docs/out-of-tree-platforms.md"}'),s={name:"docs/out-of-tree-platforms.md"},r=t("",15),i=[r];function n(l,c,d,p,m,u){return o(),e("div",null,i)}const f=a(s,[["render",n]]);export{k as __pageData,f as default}; diff --git a/vitepress/docs/.vitepress/dist/assets/docs_performance.md.DQcK4vI4.js b/vitepress/docs/.vitepress/dist/assets/docs_performance.md.DQcK4vI4.js new file mode 100644 index 0000000..fbfe2f6 --- /dev/null +++ b/vitepress/docs/.vitepress/dist/assets/docs_performance.md.DQcK4vI4.js @@ -0,0 +1,11 @@ +import{_ as a,c as e,o,a4 as s}from"./chunks/framework.nQaBHiNx.js";const r="/assets/PerfUtil-38a2ddbf1777887d70563a644c72aa64.Bzv4J9fN.png",g=JSON.parse('{"title":"Visão geral do desempenho","description":"","frontmatter":{},"headers":[],"relativePath":"docs/performance.md","filePath":"docs/performance.md"}'),i={name:"docs/performance.md"},d=s('

Visão geral do desempenho

Um motivo convincente para usar React Native em vez de ferramentas baseadas em WebView é atingir 60 quadros por segundo e uma aparência nativa para seus aplicativos. Sempre que possível, gostaríamos que o React Native fizesse a coisa certa e ajudasse você a se concentrar no seu aplicativo em vez da otimização do desempenho, mas há áreas onde ainda não chegamos lá e outras onde o React Native (semelhante a escrever nativo código diretamente) não pode determinar a melhor maneira de otimizar para você e, portanto, será necessária uma intervenção manual. Tentamos o nosso melhor para oferecer um desempenho de interface de usuário suave por padrão, mas às vezes isso não é possível.

Este guia tem como objetivo ensinar alguns princípios básicos para ajudá-lo a solucionar problemas de desempenho, bem como discutir fontes comuns de problemas e suas soluções sugeridas nesta seção.

O que você precisa saber sobre frames

A geração dos seus avós chamava os filmes de “imagens em movimento” por uma razão: o movimento realista no vídeo é uma ilusão criada pela rápida mudança de imagens estáticas a uma velocidade consistente. Referimo-nos a cada uma dessas imagens como quadros. O número de quadros exibidos a cada segundo tem um impacto direto na aparência suave e realista de um vídeo (ou interface do usuário). Os dispositivos iOS exibem 60 quadros por segundo, o que dá a você e ao sistema de UI cerca de 16,67 ms para realizar todo o trabalho necessário para gerar a imagem estática (quadro) que o usuário verá na tela nesse intervalo. Se você não conseguir fazer o trabalho necessário para gerar esse quadro dentro dos 16,67 ms alocados, você "descartará um quadro" e a IU parecerá sem resposta.

Agora, para confundir um pouco o assunto, abra o menu Dev em seu aplicativo e alterne Show Perf Monitor. Você notará que existem duas taxas de quadros diferentes.

Taxa de quadros JS (thread JavaScript)

Para a maioria dos aplicativos React Native, sua lógica de negócios será executada no thread JavaScript. É aqui que reside o seu aplicativo React, as chamadas de API são feitas, os eventos de toque são processados, etc... As atualizações para visualizações com suporte nativo são agrupadas e enviadas para o lado nativo no final de cada iteração do loop de eventos, antes do prazo do quadro (se tudo correr bem). Se o thread JavaScript não responder a um quadro, ele será considerado um quadro descartado. Por exemplo, se você chamar this.setState no componente raiz de um aplicativo complexo e isso resultar na nova renderização de subárvores de componentes computacionalmente caras, é concebível que isso possa levar 200 ms e resultar na eliminação de 12 quadros. Quaisquer animações controladas por JavaScript pareceriam congelar durante esse período. Se algo demorar mais de 100 ms, o usuário sentirá.

Isso geralmente acontece durante as transições do Navigator: quando você envia uma nova rota, o thread JavaScript precisa renderizar todos os componentes necessários para a cena para enviar os comandos apropriados ao lado nativo para criar as visualizações de apoio. É comum que o trabalho feito aqui ocupe alguns quadros e cause instabilidade porque a transição é controlada pelo thread JavaScript. Às vezes, os componentes farão trabalho adicional no componentDidMount, o que pode resultar em uma segunda falha na transição.

Outro exemplo é responder a toques: se você estiver trabalhando em vários quadros no thread JavaScript, poderá notar um atraso na resposta a TouchableOpacity, por exemplo. Isso ocorre porque a thread JavaScript está ocupada e não pode processar os eventos de toque brutos enviados da thread principal. Como resultado, TouchableOpacity não pode reagir aos eventos de toque e comandar a visualização nativa para ajustar sua opacidade.

Taxa de quadros da UI (thread principal)

Muitas pessoas notaram que o desempenho do NavigatorIOS é melhor do que o Navigator. A razão para isso é que as animações das transições são feitas inteiramente no thread principal e, portanto, não são interrompidas por quedas de quadros no thread JavaScript.

Da mesma forma, você pode rolar para cima e para baixo em um ScrollView quando o thread JavaScript está bloqueado porque o ScrollView reside no thread principal. Os eventos de rolagem são despachados para o thread JS, mas seu recebimento não é necessário para que a rolagem ocorra.

Fontes comuns de problemas de desempenho

Executando em modo de desenvolvimento (dev=true)

O desempenho do thread JavaScript sofre muito quando executado no modo de desenvolvimento. Isso é inevitável: muito mais trabalho precisa ser feito em tempo de execução para fornecer bons avisos e mensagens de erro, como validação de propTypes e várias outras asserções. Sempre certifique-se de testar o desempenho nas compilações de lançamento.

Usando instruções console.log

Ao executar um aplicativo compilado, essas instruções podem causar um grande gargalo na thread JavaScript. Isso inclui chamadas de bibliotecas de depuração, como redux-logger, portanto, certifique-se de removê-las antes de compilar. Você também pode usar este plugin babel que remove todas as chamadas console.*. Você precisa instalá-lo primeiro com npm i babel-plugin-transform-remove-console --save-dev e, em seguida, editar o arquivo .babelrc no diretório do projeto assim:

json
{
+  "env": {
+    "production": {
+      "plugins": ["transform-remove-console"]
+    }
+  }
+}

Isso removerá automaticamente todas as chamadas console.* nas versões de lançamento (produção) do seu projeto.

É recomendado usar o plugin mesmo que nenhuma chamada console.* seja feita em seu projeto. Uma biblioteca terceirizada também poderia ligar para eles.

A renderização inicial do ListView é muito lenta ou o desempenho da rolagem é ruim para listas grandes

Use o novo componente FlatList ou SectionList. Além de simplificar a API, os novos componentes da lista também apresentam melhorias significativas de desempenho, sendo a principal delas o uso quase constante de memória para qualquer número de linhas.

Se sua FlatList estiver com renderização lenta, certifique-se de ter implementado getItemLayout para otimizar a velocidade de renderização, ignorando a medição dos itens renderizados.

JS FPS despenca ao renderizar novamente uma visualização que quase não muda

Se você estiver usando um ListView, deverá fornecer uma função rowHasChanged que pode reduzir muito trabalho, determinando rapidamente se uma linha precisa ou não ser renderizada novamente. Se você estiver usando estruturas de dados imutáveis, isso só precisará ser uma verificação de igualdade de referência.

Da mesma forma, você pode implementar shouldComponentUpdate e indicar as condições exatas sob as quais gostaria que o componente fosse renderizado novamente. Se você escrever componentes puros (onde o valor de retorno da função de renderização depende inteiramente de adereços e estado), poderá aproveitar o PureComponent para fazer isso para você. Mais uma vez, estruturas de dados imutáveis são úteis para manter isso rápido - se você tiver que fazer uma comparação profunda de uma grande lista de objetos, pode ser que a re-renderização de todo o seu componente seja mais rápida e certamente exigiria menos código.

Descartando o FPS do thread JS por causa de muito trabalho no thread JavaScript ao mesmo tempo

As “transições lentas do Navigator” são a manifestação mais comum disso, mas há outras ocasiões em que isso pode acontecer. Usar o InteractionManager pode ser uma boa abordagem, mas se o custo da experiência do usuário for muito alto para atrasar o trabalho durante uma animação, você pode considerar o LayoutAnimation.

A API Animated atualmente calcula cada quadro-chave sob demanda no thread JavaScript, a menos que você defina useNativeDriver: true, enquanto LayoutAnimation aproveita o Core Animation e não é afetado por thread JS e quedas de quadro de thread principal.

Um caso em que usei isso foi para animar em um modal (deslizando de cima para baixo e desaparecendo em uma sobreposição translúcida) enquanto inicializo e talvez receba respostas para várias solicitações de rede, renderizando o conteúdo do modal e atualizando a visualização onde o modal foi aberto. Consulte o guia Animações para obter mais informações sobre como usar o LayoutAnimation.

Ressalvas:

  • LayoutAnimation funciona apenas para animações do tipo "dispare e esqueça" (animações "estáticas") - se for interrompível, você precisará usar o Animated.

Mover uma visualização na tela (rolar, traduzir, girar) elimina o FPS do thread da UI

Isso é especialmente verdadeiro quando você tem texto com fundo transparente posicionado no topo de uma imagem ou qualquer outra situação em que a composição alfa seja necessária para redesenhar a visualização em cada quadro. Você descobrirá que ativar o shouldRasterizeIOS ou o renderToHardwareTextureAndroid pode ajudar significativamente nisso.

Tenha cuidado para não abusar disso ou o uso de memória pode disparar. Analise seu desempenho e uso de memória ao usar esses acessórios. Se você não planeja mais mover uma visualização, desative essa propriedade.

Animar o tamanho de uma imagem reduz o FPS do thread da interface do usuário

No iOS, cada vez que você ajusta a largura ou a altura de um componente de imagem, ele é recortado e dimensionado a partir da imagem original. Isto pode ser muito caro, especialmente para imagens grandes. Em vez disso, use a propriedade de estilo transform: [{scale}] para animar o tamanho. Um exemplo de quando você pode fazer isso é tocar em uma imagem e aumentá-la para tela inteira.

Minha visualização TouchableX não responde muito bem

Às vezes, se fizermos uma ação no mesmo quadro em que estamos ajustando a opacidade ou realce de um componente que está respondendo a um toque, não veremos esse efeito até que a função onPress retorne. Se onPress fizer um setState que resulte em muito trabalho e alguns quadros perdidos, isso poderá ocorrer. Uma solução para isso é agrupar qualquer ação dentro do seu manipulador onPress em requestAnimationFrame:

js
handleOnPress() {
+  requestAnimationFrame(() => {
+    this.doExpensiveAction();
+  });
+}

Transições lentas do navegador

Conforme mencionado acima, as animações do Navigator são controladas pelo thread JavaScript. Imagine a transição de cena "empurrar da direita": a cada quadro, a nova cena é movida da direita para a esquerda, começando fora da tela (digamos em um deslocamento x de 320) e finalmente se estabelecendo quando a cena fica em um deslocamento x de 0. Cada quadro durante esta transição, o thread JavaScript precisa enviar um novo deslocamento x para o thread principal. Se o thread JavaScript estiver bloqueado, ele não poderá fazer isso e, portanto, nenhuma atualização ocorrerá naquele quadro e a animação falhará.

Uma solução para isso é permitir que animações baseadas em JavaScript sejam descarregadas para o thread principal. Se fizéssemos a mesma coisa que no exemplo acima com esta abordagem, poderíamos calcular uma lista de todos os deslocamentos x para a nova cena quando iniciamos a transição e enviá-los para o thread principal para executar de forma otimizada . Agora que o thread JavaScript está livre dessa responsabilidade, não será um grande problema se ele perder alguns quadros durante a renderização da cena - você provavelmente nem notará porque ficará muito distraído com a bela transição.

Resolver isso é um dos principais objetivos da nova biblioteca React Navigation. As visualizações no React Navigation usam componentes nativos e a biblioteca Animated para fornecer animações de 60 FPS que são executadas no thread nativo.

`,46),n=[d];function t(m,c,u,p,l,h){return o(),e("div",null,n)}const q=a(i,[["render",t]]);export{g as __pageData,q as default}; diff --git a/vitepress/docs/.vitepress/dist/assets/docs_performance.md.DQcK4vI4.lean.js b/vitepress/docs/.vitepress/dist/assets/docs_performance.md.DQcK4vI4.lean.js new file mode 100644 index 0000000..5951839 --- /dev/null +++ b/vitepress/docs/.vitepress/dist/assets/docs_performance.md.DQcK4vI4.lean.js @@ -0,0 +1 @@ +import{_ as a,c as e,o,a4 as s}from"./chunks/framework.nQaBHiNx.js";const r="/assets/PerfUtil-38a2ddbf1777887d70563a644c72aa64.Bzv4J9fN.png",g=JSON.parse('{"title":"Visão geral do desempenho","description":"","frontmatter":{},"headers":[],"relativePath":"docs/performance.md","filePath":"docs/performance.md"}'),i={name:"docs/performance.md"},d=s("",46),n=[d];function t(m,c,u,p,l,h){return o(),e("div",null,n)}const q=a(i,[["render",t]]);export{g as __pageData,q as default}; diff --git a/vitepress/docs/.vitepress/dist/assets/docs_platform-specific-code.md.5F505iA3.js b/vitepress/docs/.vitepress/dist/assets/docs_platform-specific-code.md.5F505iA3.js new file mode 100644 index 0000000..723aa2e --- /dev/null +++ b/vitepress/docs/.vitepress/dist/assets/docs_platform-specific-code.md.5F505iA3.js @@ -0,0 +1,44 @@ +import{_ as s,c as a,o as i,a4 as e}from"./chunks/framework.nQaBHiNx.js";const g=JSON.parse('{"title":"Código específico da plataforma","description":"","frontmatter":{},"headers":[],"relativePath":"docs/platform-specific-code.md","filePath":"docs/platform-specific-code.md"}'),n={name:"docs/platform-specific-code.md"},t=e(`

Código específico da plataforma

Ao criar um aplicativo multiplataforma, você desejará reutilizar o máximo de código possível. Podem surgir cenários em que faça sentido que o código seja diferente, por exemplo, você pode querer implementar componentes visuais separados para Android e iOS.

React Native oferece duas maneiras de organizar seu código e separá-lo por plataforma:

  1. Usando o módulo Platform.
  2. Usando extensões de arquivo específicas da plataforma.

Certos componentes podem ter propriedades que funcionam apenas em uma plataforma. Todos esses props são anotados com @platform e possuem um pequeno emblema próximo a eles no site.

Módulo de plataforma

React Native fornece um módulo que detecta a plataforma na qual o aplicativo está sendo executado. Você pode usar a lógica de detecção para implementar código específico da plataforma. Use esta opção quando apenas pequenas partes de um componente forem específicas da plataforma.

jsx
import {Platform, StyleSheet} from 'react-native';
+
+const styles = StyleSheet.create({
+  height: Platform.OS === 'ios' ? 200 : 100,
+});

Platform.OS será ios quando executado em iOS e Android quando executado em Android.

Há também um método Platform.select disponível, que fornece um objeto onde as chaves podem ser 'ios' | 'android' | 'native' | 'default', retorna o valor mais adequado para a plataforma em que você está executando atualmente. Ou seja, se você estiver rodando em um celular, as teclas iOS e Android terão preferência. Se não forem especificadas, a chave nativa será usada e depois a chave padrão.

jsx
import {Platform, StyleSheet} from 'react-native';
+
+const styles = StyleSheet.create({
+  container: {
+    flex: 1,
+    ...Platform.select({
+      ios: {
+        backgroundColor: 'red',
+      },
+      android: {
+        backgroundColor: 'green',
+      },
+      default: {
+        // outras plataformas, web por exemplo
+        backgroundColor: 'blue',
+      },
+    }),
+  },
+});

Isso resultará em um contêiner com flex: 1 em todas as plataformas, uma cor de fundo vermelha no iOS, uma cor de fundo verde no Android e uma cor de fundo azul em outras plataformas.

Como aceita qualquer valor, você também pode usá-lo para retornar componentes específicos da plataforma, como abaixo:

jsx
const Component = Platform.select({
+  ios: () => require('ComponentIOS'),
+  android: () => require('ComponentAndroid'),
+})();
+
+<Component />;
jsx
const Component = Platform.select({
+  native: () => require('ComponentForNative'),
+  default: () => require('ComponentForWeb'),
+})();
+
+<Component />;

Detectando a versão do Android

No Android, o módulo Platform também pode ser usado para detectar a versão da plataforma Android na qual o aplicativo está sendo executado:

jsx
import {Platform} from 'react-native';
+
+if (Platform.Version === 25) {
+  console.log('Running on Nougat!');
+}

Observação

A Version é definida como a versão da API do Android e não como a versão do sistema operacional Android. Para encontrar um mapeamento, consulte o Histórico de versões do Android.

Detectando a versão do iOS

No iOS, a Version é resultado de -[UIDevice systemVersion], que é uma string com a versão atual do sistema operacional. Um exemplo de versão do sistema é "10.3". Por exemplo, para detectar o número da versão principal no iOS:

jsx
import {Platform} from 'react-native';
+
+const majorVersionIOS = parseInt(Platform.Version, 10);
+if (majorVersionIOS <= 9) {
+  console.log('Work around a change in behavior');
+}

Extensões específicas da plataforma

Quando o código específico da plataforma for mais complexo, considere dividir o código em arquivos separados. O React Native detectará quando um arquivo tiver uma extensão .ios. ou .android. e carregará o arquivo de plataforma relevante quando necessário de outros componentes.

Por exemplo, digamos que você tenha os seguintes arquivos em seu projeto:

BigButton.ios.js
+BigButton.android.js

Você pode então importar o componente da seguinte maneira:

jsx
import BigButton from './BigButton';

O React Native selecionará automaticamente o arquivo correto com base na plataforma em execução.

Extensões específicas nativas (ou seja, compartilhamento de código com NodeJS e Web)

Você também pode usar a extensão .native.js quando um módulo precisa ser compartilhado entre NodeJS/Web e React Native, mas não tem diferenças Android/iOS. Isso é especialmente útil para projetos que possuem código comum compartilhado entre React Native e ReactJS.

Por exemplo, digamos que você tenha os seguintes arquivos em seu projeto:

Container.js # obtido por webpack, Rollup ou qualquer outro empacotador da Web
+Container.native.js # obtido pelo empacotador React Native para Android e iOS (Metro)

Você ainda pode importá-lo sem a extensão .native, da seguinte maneira:

jsx
import Container from './Container';

Dica profissional

Configure seu web bundler para ignorar extensões .native.js para evitar código não utilizado em seu pacote de produção, reduzindo assim o tamanho final do pacote.

`,36),p=[t];function l(o,h,d,r,k,c){return i(),a("div",null,p)}const m=s(n,[["render",l]]);export{g as __pageData,m as default}; diff --git a/vitepress/docs/.vitepress/dist/assets/docs_platform-specific-code.md.5F505iA3.lean.js b/vitepress/docs/.vitepress/dist/assets/docs_platform-specific-code.md.5F505iA3.lean.js new file mode 100644 index 0000000..4b671d1 --- /dev/null +++ b/vitepress/docs/.vitepress/dist/assets/docs_platform-specific-code.md.5F505iA3.lean.js @@ -0,0 +1 @@ +import{_ as s,c as a,o as i,a4 as e}from"./chunks/framework.nQaBHiNx.js";const g=JSON.parse('{"title":"Código específico da plataforma","description":"","frontmatter":{},"headers":[],"relativePath":"docs/platform-specific-code.md","filePath":"docs/platform-specific-code.md"}'),n={name:"docs/platform-specific-code.md"},t=e("",36),p=[t];function l(o,h,d,r,k,c){return i(),a("div",null,p)}const m=s(n,[["render",l]]);export{g as __pageData,m as default}; diff --git a/vitepress/docs/.vitepress/dist/assets/docs_profile-hermes.md.CpRwgQSa.js b/vitepress/docs/.vitepress/dist/assets/docs_profile-hermes.md.CpRwgQSa.js new file mode 100644 index 0000000..8ff9137 --- /dev/null +++ b/vitepress/docs/.vitepress/dist/assets/docs_profile-hermes.md.CpRwgQSa.js @@ -0,0 +1,28 @@ +import{_ as s,c as a,o as e,a4 as i}from"./chunks/framework.nQaBHiNx.js";const g=JSON.parse('{"title":"Perfil com Hermes","description":"","frontmatter":{},"headers":[],"relativePath":"docs/profile-hermes.md","filePath":"docs/profile-hermes.md"}'),o={name:"docs/profile-hermes.md"},r=i(`

Perfil com Hermes

Você pode visualizar o desempenho do JavaScript em um aplicativo React Native usando Hermes. Hermes é um mecanismo JavaScript pequeno e leve otimizado para executar React Native (você pode ler mais sobre como usá-lo com React Native aqui). Hermes ajuda a melhorar o desempenho do aplicativo e também expõe maneiras de analisar o desempenho do JavaScript que ele executa.

Nesta seção, você aprenderá como criar o perfil de seu aplicativo React Native em execução no Hermes e como visualizar o perfil usando a guia Desempenho no Chrome DevTools

CUIDADO Certifique-se de ativar o Hermes em seu aplicativo antes de começar!

Siga as instruções abaixo para começar a criar o perfil:

  • Grave um perfil de amostragem Hermes
  • Execute o comando da CLI
  • Abra o perfil baixado no Chrome DevTools

Grave um perfil de amostragem Hermes

Para gravar um perfil de amostragem no menu Dev:

  1. Navegue até o terminal do servidor Metro em execução.
  2. Pressione d para abrir o menu Dev.
  3. Selecione Enable Sampling Profiler.
  4. Execute seu JavaScript em seu aplicativo (pressione botões, etc.)
  5. Abra o menu Dev pressionando d novamente.
  6. Selecione Disable Sampling Profiler para interromper a gravação e salvar o sampler profiler.

Um toast mostrará o local onde o criador de perfil de amostragem foi salvo, geralmente em /data/user/0/com.appName/cache/*.cpuprofile

image

Execute o comando da CLI

Você pode usar a CLI do React Native para converter o perfil de rastreamento Hermes em perfil de rastreamento do Chrome e, em seguida, enviá-lo para sua máquina local usando:

npx react-native profile-hermes [diretorioDestino]

Habilitando mapa de origem

INFORMAÇÕES Você pode ler sobre mapas de origem na página de mapas de origem.

Erros comuns

adb: no devices/emulators found ou adb: device offline

  • Por que isso acontece: A CLI não pode acessar o dispositivo ou emulador (por meio do adb) que você está usando para executar o aplicativo.
  • Como corrigir: Certifique-se de que seu dispositivo/emulador Android esteja conectado e funcionando. O comando só funciona quando pode acessar o adb.

There is no file in the cache/ directory

  • Por que isso acontece: A CLI não consegue encontrar nenhum arquivo .cpuprofile no diretório cache/ do seu aplicativo. Você pode ter esquecido de gravar um perfil do dispositivo.
  • Como corrigir: Siga as instruções para ativar/desativar o criador de perfil do dispositivo.

Erro: your_profile_name.cpuprofile é um arquivo vazio

  • Por que isso acontece: O perfil está vazio, pode ser porque o Hermes não está funcionando corretamente.
  • Como corrigir: Certifique-se de que seu aplicativo esteja rodando na versão mais recente do Hermes.

Abra o perfil baixado no Chrome DevTools

Para abrir o perfil no Chrome DevTools:

  1. Abra o Chrome DevTools.
  2. Selecione a guia Performance.
  3. Clique com o botão direito e escolha Carregar perfil...

image

Como funciona o transformador de perfil Hermes?

O Hermes Sample Profile tem o formato de objeto JSON, enquanto o formato suportado pelo DevTools do Google é JSON Array Format. (Mais informações sobre os formatos podem ser encontradas no documento Trace Event Format)

js
export interface HermesCPUProfile {
+  traceEvents: SharedEventProperties[];
+  samples: HermesSample[];
+  stackFrames: {[key in string]: HermesStackFrame};
+}

O perfil Hermes tem a maior parte de suas informações codificadas nas amostras (samples) e nas propriedades stackFrames. Cada amostra é um instantâneo da pilha de chamadas de função naquele carimbo de data/hora específico, pois cada amostra possui uma propriedade sf que corresponde a uma chamada de função.

js
export interface HermesSample {
+  cpu: string;
+  name: string;
+  ts: string;
+  pid: number;
+  tid: string;
+  weight: string;
+  /**
+   * Irá se referir a um elemento no objeto stackFrames do Perfil Hermes
+   */
+  sf: number;
+  stackFrameData?: HermesStackFrame;
+}

As informações sobre uma chamada de função podem ser encontradas em stackFrames que contém pares chave-objeto, onde a chave é o número sf e o objeto correspondente nos fornece todas as informações relevantes sobre a função, incluindo o número sf de sua função pai. Esse relacionamento pai-filho pode ser rastreado para cima para encontrar as informações de todas as funções em execução em um carimbo de data/hora específico.

js
export interface HermesStackFrame {
+  line: string;
+  column: string;
+  funcLine: string;
+  funcColumn: string;
+  name: string;
+  category: string;
+  /**
+   * Uma função pai pode ou não existir
+   */
+  parent?: number;
+}

Neste ponto, você deve definir mais alguns termos, a saber:

  1. Nós: os objetos correspondentes aos números sf em stackFrames
  2. Nós ativos: os nós que estão atualmente em execução em um carimbo de data/hora específico. Um nó é classificado como em execução se seu número sf estiver na pilha de chamadas de função. Esta pilha de chamadas pode ser obtida a partir do número sf da amostra e rastreada para cima até que os sfs pai estejam disponíveis

As amostras e os stackFrames em conjunto podem então ser usados para gerar todos os eventos de início e término nos carimbos de data/hora correspondentes, em que:

  1. Nós/Eventos iniciais: nós ausentes na pilha de chamadas de função da amostra anterior, mas presentes na amostra atual.
  2. Nós finais/eventos: nós presentes na pilha de chamadas de função da amostra anterior, mas ausentes na amostra atual.

image

Agora você pode construir um flamechart de chamadas de função, pois possui todas as informações da função, incluindo seus carimbos de data e hora de início e término.

O hermes-profile-transformer pode converter qualquer perfil gerado usando Hermes em um formato que pode ser exibido diretamente no Chrome DevTools. Mais informações sobre isso podem ser encontradas em @react-native-community/hermes-profile-transformer.

`,41),n=[r];function t(l,p,h,d,c,k){return e(),a("div",null,n)}const u=s(o,[["render",t]]);export{g as __pageData,u as default}; diff --git a/vitepress/docs/.vitepress/dist/assets/docs_profile-hermes.md.CpRwgQSa.lean.js b/vitepress/docs/.vitepress/dist/assets/docs_profile-hermes.md.CpRwgQSa.lean.js new file mode 100644 index 0000000..ccf8278 --- /dev/null +++ b/vitepress/docs/.vitepress/dist/assets/docs_profile-hermes.md.CpRwgQSa.lean.js @@ -0,0 +1 @@ +import{_ as s,c as a,o as e,a4 as i}from"./chunks/framework.nQaBHiNx.js";const g=JSON.parse('{"title":"Perfil com Hermes","description":"","frontmatter":{},"headers":[],"relativePath":"docs/profile-hermes.md","filePath":"docs/profile-hermes.md"}'),o={name:"docs/profile-hermes.md"},r=i("",41),n=[r];function t(l,p,h,d,c,k){return e(),a("div",null,n)}const u=s(o,[["render",t]]);export{g as __pageData,u as default}; diff --git a/vitepress/docs/.vitepress/dist/assets/docs_profiling.md.t1WkloPk.js b/vitepress/docs/.vitepress/dist/assets/docs_profiling.md.t1WkloPk.js new file mode 100644 index 0000000..2c41124 --- /dev/null +++ b/vitepress/docs/.vitepress/dist/assets/docs_profiling.md.t1WkloPk.js @@ -0,0 +1 @@ +import{_ as e,c as a,o,a4 as r}from"./chunks/framework.nQaBHiNx.js";const h=JSON.parse('{"title":"Perfil","description":"","frontmatter":{},"headers":[],"relativePath":"docs/profiling.md","filePath":"docs/profiling.md"}'),d={name:"docs/profiling.md"},s=r('

Perfil

Use o criador de perfil integrado para obter informações detalhadas sobre o trabalho realizado no thread JavaScript e no thread principal lado a lado. Acesse-o selecionando "Perf Monitor" no menu Debug.

Para iOS, Instruments é uma ferramenta inestimável, e no Android você deve aprender a usar o systrace.

Mas primeiro, certifique-se de que o Modo de Desenvolvimento esteja DESLIGADO! Você deverá ver __DEV__ === false, o aviso em nível de desenvolvimento está DESATIVADO e as otimizações de desempenho estão ATIVADAS nos logs do seu aplicativo.

Outra maneira de criar o perfil do JavaScript é usar o criador de perfil do Chrome durante a depuração. Isso não fornecerá resultados precisos, pois o código está sendo executado no Chrome, mas fornecerá uma ideia geral de onde podem estar os gargalos. Execute o criador de perfil na guia Desempenho do Chrome. Um gráfico em degradê aparecerá em User Timing. Para ver mais detalhes em formato tabular, clique na guia Bottom Up abaixo e selecione DedicatedWorker Thread no menu superior esquerdo.

Criação de perfil de desempenho da interface do Android com systrace

O Android suporta mais de 10 mil telefones diferentes e é generalizado para suportar renderização de software: a arquitetura da estrutura e a necessidade de generalizar para muitos alvos de hardware, infelizmente significam que você recebe menos de graça, em relação ao iOS. Mas às vezes há coisas que você pode melhorar - e muitas vezes não é culpa do código nativo!

O primeiro passo para depurar essa instabilidade é responder à questão fundamental de onde seu tempo está sendo gasto durante cada quadro de 16 ms. Para isso, usaremos uma ferramenta padrão de criação de perfil do Android chamada systrace.

systrace é uma ferramenta de criação de perfil padrão baseada em marcadores do Android (e é instalada quando você instala o pacote de ferramentas da plataforma Android). Os blocos de código perfilados são cercados por marcadores de início/fim que são visualizados em um formato de gráfico colorido. Tanto o Android SDK quanto a estrutura React Native fornecem marcadores padrão que você pode visualizar.

1. Coletando um rastro

Primeiro, conecte um dispositivo que exiba as telas que você deseja investigar ao seu computador via USB e leve-o ao ponto logo antes da navegação/animação que você deseja criar o perfil. Execute o systrace da seguinte maneira:

$ <path_to_android_sdk>/platform-tools/systrace/systrace.py --time=10 -o trace.html sched gfx view -a <your_package_name>

Uma análise rápida deste comando:

  • time é o período de tempo que o rastreamento será coletado em segundos
  • sched, gfx e view são as tags Android SDK (coleções de marcadores) com as quais nos preocupamos: sched fornece informações sobre o que está sendo executado em cada núcleo do seu telefone, gfx fornece informações gráficas, como limites de quadros, e view fornece informações sobre medir, fazer o layout e desenhar passes
  • -a <your_package_name> habilita marcadores específicos do aplicativo, especificamente aqueles integrados à estrutura React Native. your_package_name pode ser encontrado no AndroidManifest.xml do seu aplicativo e se parece com com.example.app

Assim que o rastreamento começar a ser coletado, execute a animação ou interação de seu interesse. No final do rastreamento, o systrace fornecerá um link para o rastreamento que você pode abrir em seu navegador.

2. Lendo o rastreamento

Depois de abrir o rastreamento em seu navegador (de preferência Chrome), você deverá ver algo assim:

image

DICA Use as teclas WASD para guiar e ampliar.

Se o arquivo .html de rastreamento não estiver abrindo corretamente, verifique o seguinte no console do navegador:

image

Como Object.observe foi descontinuado em navegadores recentes, pode ser necessário abrir o arquivo na ferramenta de rastreamento do Google Chrome. Você pode fazer isso:

  • Aba de abertura no chrome chrome://tracing
  • Selecionando load
  • Selecionando o arquivo html gerado a partir do comando anterior.

ATIVAR HIGHLIGHT VSYNC Marque esta caixa de seleção no canto superior direito da tela para destacar os limites do quadro de 16ms: image

Você deverá ver listras de zebra como na imagem acima. Caso contrário, tente criar um perfil em um dispositivo diferente: sabe-se que a Samsung tem problemas para exibir vsyncs, enquanto a série Nexus é geralmente bastante confiável.

3. Encontre o seu processo

Role até ver (parte do) nome do seu pacote. Nesse caso, eu estava criando o perfil de com.facebook.adsmanager, que aparece como book.adsmanager por causa de limites bobos de nomes de threads no kernel.

No lado esquerdo, você verá um conjunto de tópicos que correspondem às linhas da linha do tempo à direita. Existem alguns threads com os quais nos preocupamos para nossos propósitos: o thread de UI (que tem o nome do seu pacote ou o nome Thread de UI), mqt_js e mqt_native_modules. Se você estiver executando o Android 5+, também nos preocupamos com o Render Thread.

  • UI Thread. É aqui que acontece a medida/layout/desenho padrão do Android. O nome do tópico à direita será o nome do seu pacote (no meu caso book.adsmanager) ou UI Thread. Os eventos que você vê neste tópico devem ser parecidos com isto e têm a ver com Choreographer, traversals e DispatchUI: image

  • JS Thread. É aqui que o JavaScript é executado. O nome do thread será mqt_js ou <...> dependendo de quão cooperativo o kernel do seu dispositivo está sendo. Para identificá-lo caso não tenha nome, procure coisas como JSCall, Bridge.executeJSCall, etc: image

  • Native Modules Thread. É aqui que as chamadas do módulo nativo (por exemplo, o UIManager) são executadas. O nome do encadeamento será mqt_native_modules ou <...>. Para identificá-lo neste último caso, procure coisas como NativeCall, callJavaModuleMethod e onBatchComplete: image

  • Bônus: Thread Render. Se estiver usando Android L (5.0) e superior, você também terá uma thread de renderização em seu aplicativo. Esta thread gera os comandos OpenGL reais usados para desenhar sua UI. O nome do thread será RenderThread ou <...>. Para identificá-lo neste último caso, procure coisas como DrawFrame e queueBuffer:

image

Identificando um culpado

Uma animação suave deve ser semelhante a esta:

image

Cada mudança de cor é um quadro – lembre-se que para exibir um quadro, todo o nosso trabalho de UI precisa ser feito até o final desse período de 16 ms. Observe que nenhuma thread está funcionando próximo ao limite do quadro. Uma renderização de aplicativo como essa é renderizada a 60 FPS.

Se você notou um corte, no entanto, poderá ver algo assim:

image

Observe que o thread JS está em execução quase o tempo todo e além dos limites do quadro! Este aplicativo não está renderizando a 60 FPS. Neste caso, o problema está em JS.

Você também pode ver algo assim:

image

Nesse caso, a interface do usuário e as threads de renderização são os que têm trabalho cruzando os limites do quadro. A UI que estamos tentando renderizar em cada quadro está exigindo muito trabalho. Nesse caso, o problema está na renderização das visualizações nativas.

Neste ponto, você terá algumas informações muito úteis para orientar suas próximas etapas.

Resolvendo problemas de JavaScript

Se você identificou um problema de JS, procure pistas no JS específico que está executando. No cenário acima, vemos RCTEventEmitter sendo chamado várias vezes por quadro. Aqui está um zoom do thread JS do rastreamento acima:

image

Isso não parece certo. Por que está sendo chamado com tanta frequência? São realmente eventos diferentes? As respostas a essas perguntas provavelmente dependerão do código do seu produto. E muitas vezes, você vai querer dar uma olhada em shouldComponentUpdate.

Resolvendo problemas de UI nativa

Se você identificou um problema de UI nativa, geralmente há dois cenários:

  • a IU que você está tentando desenhar cada quadro envolve muito trabalho na GPU ou
  • Você está construindo uma nova UI durante a animação/interação (por exemplo, carregando um novo conteúdo durante uma rolagem).

Muito trabalho de GPU

No primeiro cenário, você verá um trace que tem o thread de UI e/ou Thread de Renderização parecido com este:

image

Observe a longa quantidade de tempo gasto no DrawFrame que ultrapassa os limites do quadro. Este é o tempo gasto esperando que a GPU drene seu buffer de comando do quadro anterior.

Para mitigar isso, você deve:

  • investigue usando renderToHardwareTextureAndroid para conteúdo estático e complexo que está sendo animado/transformado (por exemplo, animações de slide/alfa do Navigator)
  • certifique-se de não usar o NeedOffscreenAlphaCompositing, que está desabilitado por padrão, pois aumenta muito a carga por quadro na GPU na maioria dos casos.

Criando novas visualizações no thread da UI

No segundo cenário, você verá algo mais parecido com isto:

image

Observe que primeiro o thread JS pensa um pouco, depois você vê algum trabalho realizado no thread de módulos nativos, seguido por uma travessia cara no thread de UI.

Não há uma maneira rápida de atenuar isso, a menos que você consiga adiar a criação de uma nova IU até depois da interação ou simplifique a IU que está criando. A equipe do React Native está trabalhando em uma solução de nível de infraestrutura para isso que permitirá que novas UI sejam criadas e configuradas fora do thread principal, permitindo que a interação continue sem problemas.

',58),t=[s];function i(c,n,m,p,u,l){return o(),a("div",null,t)}const g=e(d,[["render",i]]);export{h as __pageData,g as default}; diff --git a/vitepress/docs/.vitepress/dist/assets/docs_profiling.md.t1WkloPk.lean.js b/vitepress/docs/.vitepress/dist/assets/docs_profiling.md.t1WkloPk.lean.js new file mode 100644 index 0000000..d7b9f4d --- /dev/null +++ b/vitepress/docs/.vitepress/dist/assets/docs_profiling.md.t1WkloPk.lean.js @@ -0,0 +1 @@ +import{_ as e,c as a,o,a4 as r}from"./chunks/framework.nQaBHiNx.js";const h=JSON.parse('{"title":"Perfil","description":"","frontmatter":{},"headers":[],"relativePath":"docs/profiling.md","filePath":"docs/profiling.md"}'),d={name:"docs/profiling.md"},s=r("",58),t=[s];function i(c,n,m,p,u,l){return o(),a("div",null,t)}const g=e(d,[["render",i]]);export{h as __pageData,g as default}; diff --git a/vitepress/docs/.vitepress/dist/assets/docs_publishing-to-app-store.md.7oRPhMVE.js b/vitepress/docs/.vitepress/dist/assets/docs_publishing-to-app-store.md.7oRPhMVE.js new file mode 100644 index 0000000..c960dc3 --- /dev/null +++ b/vitepress/docs/.vitepress/dist/assets/docs_publishing-to-app-store.md.7oRPhMVE.js @@ -0,0 +1,6 @@ +import{_ as a,c as e,o as i,a4 as s}from"./chunks/framework.nQaBHiNx.js";const o="/assets/321064922-2e21e8bb-a216-416b-9690-09a883198c52.BoFCh8E9.png",g=JSON.parse('{"title":"Publicação na Apple App Store","description":"","frontmatter":{},"headers":[],"relativePath":"docs/publishing-to-app-store.md","filePath":"docs/publishing-to-app-store.md"}'),t={name:"docs/publishing-to-app-store.md"},n=s('

Publicação na Apple App Store

O processo de publicação é igual ao de qualquer outro aplicativo iOS nativo, com algumas considerações adicionais a serem levadas em consideração.

Informações

Se você estiver usando o Expo, leia o guia do Expo para Implantação nas App Stores para criar e enviar seu aplicativo para a Apple App Store. Este guia funciona com qualquer aplicativo React Native para automatizar o processo de implantação.

1. Configurar esquema de liberação

Construir um aplicativo para distribuição na App Store requer o uso do esquema Release no Xcode. Os aplicativos desenvolvidos para Release desativarão automaticamente o menu Dev no aplicativo, o que impedirá que seus usuários acessem inadvertidamente o menu em produção. Ele também agrupará o JavaScript localmente, para que você possa colocar o aplicativo em um dispositivo e testá-lo enquanto não estiver conectado ao computador.

Para configurar seu aplicativo para ser construído usando o esquema Release, vá para Product → Scheme → Edit Scheme. Selecione a guia Run na barra lateral e defina o menu suspenso Build Configuration como Release.

Dicas profissionais

À medida que o tamanho do seu App Bundle aumenta, você pode começar a ver uma tela em branco piscando entre a tela inicial e a exibição da visualização do aplicativo raiz. Se for esse o caso, você pode adicionar o seguinte código a AppDelegate.m para manter sua tela inicial exibida durante a transição.

objective-c
  // Coloque este código depois de "[self.window makeKeyAndVisible]" e antes de "return YES;"
+  UIStoryboard *sb = [UIStoryboard storyboardWithName:@"LaunchScreen" bundle:nil];
+  UIViewController *vc = [sb instantiateInitialViewController];
+  rootView.loadingView = vc.view;

O pacote estático é criado sempre que você direciona um dispositivo físico, mesmo na depuração. Se você quiser economizar tempo, desative a geração de pacotes no Debug adicionando o seguinte ao seu script de shell na fase de construção do Xcode Bundle React Native code and images:

bash
 if [ "\${CONFIGURATION}" == "Debug" ]; then
+  export SKIP_BUNDLING=true
+ fi

2. Construir aplicativo para lançamento

Agora você pode criar seu aplicativo para lançamento tocando em Cmd ⌘ + B ou selecionando ProdutoConstruir na barra de menu. Depois de criado para lançamento, você poderá distribuir o aplicativo para testadores beta e enviá-lo para a App Store.

Informações

Você também pode usar o React Native CLI para realizar esta operação usando a opção --mode com o valor Release (por exemplo, da raiz do seu projeto: npm run ios -- --mode="Release" ou yarn ios --mode Release).

Quando terminar os testes e estiver pronto para publicar na App Store, siga este guia.

  • Inicie seu terminal, navegue até a pasta iOS do seu aplicativo e digite open ..
  • Clique duas vezes em YOUR_APP_NAME.xcworkspace. Deve iniciar o XCode.
  • Clique em ProdutoArquivo. Certifique-se de configurar o dispositivo para "Qualquer dispositivo iOS (arm64)".

Observação

Verifique seu identificador de pacote e certifique-se de que seja exatamente igual ao que você criou nos identificadores no Apple Developer Dashboard.

  • Após a conclusão do arquivo, na janela de arquivo, clique em Distribute App.
  • Clique em App Store Connect agora (se quiser publicar na App Store).
  • Clique em Upload → Certifique-se de que todas as caixas de seleção estejam marcadas, clique em Next.
  • Escolha entre Automatically manage signing e Manually manage signing com base em suas necessidades.
  • Clique em Upload.
  • Agora você pode encontrá-lo na App Store Connect em TestFlight.

Agora preencha as informações necessárias e na seção Build, selecione a build do aplicativo e clique em SaveSubmit For Review.

4. Capturas de tela

A Apple Store exige que você tenha capturas de tela dos dispositivos mais recentes. A referência para tais dispositivos pode ser encontrada aqui. Observe que as capturas de tela para alguns tamanhos de exibição não serão necessárias se forem fornecidas para outros tamanhos.

`,22),r=[n];function p(l,c,d,u,h,k){return i(),e("div",null,r)}const v=a(t,[["render",p]]);export{g as __pageData,v as default}; diff --git a/vitepress/docs/.vitepress/dist/assets/docs_publishing-to-app-store.md.7oRPhMVE.lean.js b/vitepress/docs/.vitepress/dist/assets/docs_publishing-to-app-store.md.7oRPhMVE.lean.js new file mode 100644 index 0000000..ae8de76 --- /dev/null +++ b/vitepress/docs/.vitepress/dist/assets/docs_publishing-to-app-store.md.7oRPhMVE.lean.js @@ -0,0 +1 @@ +import{_ as a,c as e,o as i,a4 as s}from"./chunks/framework.nQaBHiNx.js";const o="/assets/321064922-2e21e8bb-a216-416b-9690-09a883198c52.BoFCh8E9.png",g=JSON.parse('{"title":"Publicação na Apple App Store","description":"","frontmatter":{},"headers":[],"relativePath":"docs/publishing-to-app-store.md","filePath":"docs/publishing-to-app-store.md"}'),t={name:"docs/publishing-to-app-store.md"},n=s("",22),r=[n];function p(l,c,d,u,h,k){return i(),e("div",null,r)}const v=a(t,[["render",p]]);export{g as __pageData,v as default}; diff --git a/vitepress/docs/.vitepress/dist/assets/docs_ram-bundles-inline-requires.md.9rIYNLSr.js b/vitepress/docs/.vitepress/dist/assets/docs_ram-bundles-inline-requires.md.9rIYNLSr.js new file mode 100644 index 0000000..a66bdc2 --- /dev/null +++ b/vitepress/docs/.vitepress/dist/assets/docs_ram-bundles-inline-requires.md.9rIYNLSr.js @@ -0,0 +1,102 @@ +import{_ as s,c as i,o as a,a4 as e}from"./chunks/framework.nQaBHiNx.js";const c=JSON.parse('{"title":"Pacotes de RAM e require inline","description":"","frontmatter":{},"headers":[],"relativePath":"docs/ram-bundles-inline-requires.md","filePath":"docs/ram-bundles-inline-requires.md"}'),n={name:"docs/ram-bundles-inline-requires.md"},l=e(`

Pacotes de RAM e require inline

Se você tiver um aplicativo grande, considere o formato do pacote Random Access Modules (RAM) e o uso de requisitos in-line. Isso é útil para aplicativos que possuem um grande número de telas que talvez nunca sejam abertas durante o uso normal do aplicativo. Geralmente é útil para aplicativos que possuem grandes quantidades de código que não são necessários por um tempo após a inicialização. Por exemplo, o aplicativo inclui telas de perfil complicadas ou recursos menos usados, mas a maioria das sessões envolve apenas a visita à tela principal do aplicativo para atualizações. Podemos otimizar o carregamento do pacote usando o formato RAM e exigindo esses recursos e telas inline (quando são realmente usados).

Carregando JavaScript

Antes que o react-native possa executar o código JS, esse código deve ser carregado na memória e analisado. Com um pacote padrão, se você carregar um pacote de 50 MB, todos os 50 MB deverão ser carregados e analisados antes que qualquer um deles possa ser executado. A otimização por trás dos pacotes de RAM é que você pode carregar apenas a parte dos 50 MB que realmente precisa na inicialização e carregar progressivamente mais do pacote conforme essas seções forem necessárias.

Require Inline

Inline exige atrasar a solicitação de um módulo ou arquivo até que esse arquivo seja realmente necessário. Um exemplo básico seria assim:

jsx
// VeryExpensive.tsx
+
+import React, {Component} from 'react';
+import {Text} from 'react-native';
+// ... importe alguns módulos muito grande
+
+// Você pode querer registrar no nível do arquivo para verificar quando isso está acontecendo
+console.log('VeryExpensive component loaded');
+
+export default class VeryExpensive extends Component {
+  // muito e muito código
+  render() {
+    return <Text>Very Expensive Component</Text>;
+  }
+}
jsx
// Optimized.tsx
+
+import React, {Component} from 'react';
+import {TouchableOpacity, View, Text} from 'react-native';
+
+let VeryExpensive = null;
+
+export default class Optimized extends Component {
+  state = {needsExpensive: false};
+
+  didPress = () => {
+    if (VeryExpensive == null) {
+      VeryExpensive = require('./VeryExpensive').default;
+    }
+
+    this.setState(() => ({
+      needsExpensive: true,
+    }));
+  };
+
+  render() {
+    return (
+      <View style={{marginTop: 20}}>
+        <TouchableOpacity onPress={this.didPress}>
+          <Text>Load</Text>
+        </TouchableOpacity>
+        {this.state.needsExpensive ? <VeryExpensive /> : null}
+      </View>
+    );
+  }
+}

Mesmo sem o formato RAM, as solicitações in-line podem levar a melhorias no tempo de inicialização, porque o código dentro do VeryExpensive.js só será executado quando for necessário pela primeira vez.

Habilite o formato RAM

No iOS, usar o formato RAM criará um único arquivo indexado que reagirá nativamente e carregará um módulo por vez. No Android, por padrão, será criado um conjunto de arquivos para cada módulo. Você pode forçar o Android a criar um único arquivo, como o iOS, mas usar vários arquivos pode ter melhor desempenho e requer menos memória.

Habilite o formato RAM no Xcode editando a fase de construção "Bundle React Native code and images". Antes de ../node_modules/react-native/scripts/react-native-xcode.sh adicione export BUNDLE_COMMAND="ram-bundle":

sh
export BUNDLE_COMMAND="ram-bundle"
+export NODE_BINARY=node
+../node_modules/react-native/scripts/react-native-xcode.sh

No Android, habilite o formato RAM editando seu arquivo android/app/build.gradle. Antes da linha apply from: "../../node_modules/react-native/react.gradle" adicione ou altere o bloco project.ext.react:

project.ext.react = [
+  bundleCommand: "ram-bundle",
+]

Use as seguintes linhas no Android se quiser usar um único arquivo indexado:

projeto.ext.react = [
+   bundleCommand: "ram-bundle",
+   extraPackagerArgs: ["--indexed-ram-bundle"]
+]

INFORMAÇÕES Se você estiver usando o Hermes JS Engine, não deverá ter o recurso de pacotes de RAM ativado. No Hermes, ao carregar o bytecode, o mmap garante que o arquivo inteiro não seja carregado. Usar Hermes com pacotes de RAM pode causar problemas, porque esses mecanismos não são compatíveis entre si.

Configurar pré-carregamento e requisitos embutidos

Agora que temos um pacote de RAM, há sobrecarga para chamar require. require agora precisa enviar uma mensagem pela ponte quando encontrar um módulo que ainda não foi carregado. Isso terá maior impacto na inicialização, porque é onde o maior número de chamadas require provavelmente ocorrerá enquanto o aplicativo carrega o módulo inicial. Felizmente podemos configurar uma parte dos módulos para serem pré-carregados. Para fazer isso, você precisará implementar alguma forma de importação in-line.

Investigando os Módulos Carregados

No seu arquivo raiz (index.(ios|android).js) você pode adicionar o seguinte após as importações iniciais:

js
const modules = require.getModules();
+const moduleIds = Object.keys(modules);
+const loadedModuleNames = moduleIds
+  .filter(moduleId => modules[moduleId].isInitialized)
+  .map(moduleId => modules[moduleId].verboseName);
+const waitingModuleNames = moduleIds
+  .filter(moduleId => !modules[moduleId].isInitialized)
+  .map(moduleId => modules[moduleId].verboseName);
+
+// certifique-se de que os módulos que você espera estarem aguardando, estão realmente esperando
+console.log(
+  'loaded:',
+  loadedModuleNames.length,
+  'waiting:',
+  waitingModuleNames.length,
+);
+
+// pegue este blob de texto e coloque-o em um arquivo chamado packager/modulePaths.js
+console.log(
+  \`module.exports = \${JSON.stringify(
+    loadedModuleNames.sort(),
+    null,
+    2,
+  )};\`,
+);

Ao executar seu aplicativo, você pode olhar no console e ver quantos módulos foram carregados e quantos estão aguardando. Você pode querer ler os moduleNames e ver se há alguma surpresa. Observe que os requisitos inline são invocados na primeira vez que as importações são referenciadas. Talvez seja necessário investigar e refatorar para garantir que apenas os módulos desejados sejam carregados na inicialização. Observe que você pode alterar o objeto Systrace em require para ajudar a depurar requisitos problemáticos.

js
require.Systrace.beginEvent = message => {
+  if (message.includes(problematicModule)) {
+    throw new Error();
+  }
+};

Cada aplicativo é diferente, mas pode fazer sentido carregar apenas os módulos necessários para a primeira tela. Quando estiver satisfeito, coloque a saída de loadModuleNames em um arquivo chamado packager/modulePaths.js.

Atualizando metro.config.js

Agora precisamos atualizar metro.config.js na raiz do projeto para usar nosso arquivo modulePaths.js recém-gerado:

js
const {getDefaultConfig, mergeConfig} = require('@react-native/metro-config');
+const fs = require('fs');
+const path = require('path');
+const modulePaths = require('./packager/modulePaths');
+
+const config = {
+  transformer: {
+    getTransformOptions: () => {
+      const moduleMap = {};
+      modulePaths.forEach(modulePath => {
+        if (fs.existsSync(modulePath)) {
+          moduleMap[path.resolve(modulePath)] = true;
+        }
+      });
+      return {
+        preloadedModules: moduleMap,
+        transform: {inlineRequires: {blockList: moduleMap}},
+      };
+    },
+  },
+};
+
+module.exports = mergeConfig(getDefaultConfig(__dirname), config);

Consulte também Configurando o Metro.

A entrada preloadedModules na configuração indica quais módulos devem ser marcados como pré-carregados ao construir um pacote de RAM. Quando o pacote é carregado, esses módulos são carregados imediatamente, antes mesmo de qualquer requerimento ser executado. A entrada blockList indica que esses módulos não devem ser necessários em linha. Como eles são pré-carregados, não há benefício de desempenho no uso de um require in-line. Na verdade, o JavaScript gerado gasta mais tempo resolvendo a necessidade inline toda vez que as importações são referenciadas.

Teste e meça melhorias

Agora você deve estar pronto para criar seu aplicativo usando o formato RAM e os requisitos embutidos. Certifique-se de medir os tempos de inicialização antes e depois.

`,33),t=[l];function p(h,k,r,o,d,E){return a(),i("div",null,t)}const u=s(n,[["render",p]]);export{c as __pageData,u as default}; diff --git a/vitepress/docs/.vitepress/dist/assets/docs_ram-bundles-inline-requires.md.9rIYNLSr.lean.js b/vitepress/docs/.vitepress/dist/assets/docs_ram-bundles-inline-requires.md.9rIYNLSr.lean.js new file mode 100644 index 0000000..b4c5825 --- /dev/null +++ b/vitepress/docs/.vitepress/dist/assets/docs_ram-bundles-inline-requires.md.9rIYNLSr.lean.js @@ -0,0 +1 @@ +import{_ as s,c as i,o as a,a4 as e}from"./chunks/framework.nQaBHiNx.js";const c=JSON.parse('{"title":"Pacotes de RAM e require inline","description":"","frontmatter":{},"headers":[],"relativePath":"docs/ram-bundles-inline-requires.md","filePath":"docs/ram-bundles-inline-requires.md"}'),n={name:"docs/ram-bundles-inline-requires.md"},l=e("",33),t=[l];function p(h,k,r,o,d,E){return a(),i("div",null,t)}const u=s(n,[["render",p]]);export{c as __pageData,u as default}; diff --git a/vitepress/docs/.vitepress/dist/assets/docs_react-devtools.md.CK7_TSWs.js b/vitepress/docs/.vitepress/dist/assets/docs_react-devtools.md.CK7_TSWs.js new file mode 100644 index 0000000..b7ef651 --- /dev/null +++ b/vitepress/docs/.vitepress/dist/assets/docs_react-devtools.md.CK7_TSWs.js @@ -0,0 +1 @@ +import{_ as e,c as a,o,a4 as t}from"./chunks/framework.nQaBHiNx.js";const s="/assets/309739868-01361acc-6dcc-4519-a990-1e00dd02c666.HXoiJ2NJ.png",r="/assets/309740243-cc8fe788-5dbb-40ee-aceb-aa74e4ed643b.BN1YkZEd.png",i="/assets/ReactDevToolsInspector-fed7286dac8ef8a793245cdd9d3d0f9c.DAvzAGx1.gif",c="/assets/ReactDevToolsConnection-2fcfc362befab4699fd8afceefa5903e.8_VLXZ0K.gif",f=JSON.parse('{"title":"Ferramentas de desenvolvedor React","description":"","frontmatter":{},"headers":[],"relativePath":"docs/react-devtools.md","filePath":"docs/react-devtools.md"}'),d={name:"docs/react-devtools.md"},n=t('

Ferramentas de desenvolvedor React

Você pode usar a versão autônoma do React Developer Tools para depurar a hierarquia de componentes do React. Para usá-lo, instale o pacote react-devtools globalmente:

bash
npm install -g react-devtools
bash
yarn global add react-devtools

Agora execute react-devtools no terminal para iniciar o aplicativo DevTools independente. Ele deve se conectar ao seu simulador em alguns segundos.

bash
react-devtools

image

Informações

Se preferir evitar instalações globais, você pode adicionar react-devtools como uma dependência do projeto. Adicione o pacote react-devtools ao seu projeto usando npm install --save-dev react-devtools e, em seguida, adicione "react-devtools": "react-devtools" à seção de scripts em seu package.json e execute npm run react-devtools da pasta do seu projeto para abrir o DevTools.

Integração com React Native Inspector

Abra o menu Dev e escolha "Toggle Inspector". Isso abrirá uma sobreposição que permite tocar em qualquer elemento da interface do usuário e ver informações sobre ele:

image

No entanto, quando o react-devtools estiver em execução, o Inspector entrará em um modo recolhido e, em vez disso, usará o DevTools como UI principal. Neste modo, clicar em algo no simulador exibirá os componentes relevantes no DevTools:

Você pode escolher "Toggle Inspector" no mesmo menu para sair deste modo.

Depurando o estado do aplicativo

Reactotron é um aplicativo de desktop de código aberto que permite inspecionar o estado do aplicativo Redux ou MobX-State-Tree, bem como visualizar logs personalizados, executar comandos personalizados, como redefinir estado, armazenar e restaurar instantâneos de estado e outros recursos úteis de depuração para React Aplicativos nativos.

Você pode ver as instruções de instalação no README. Se você estiver usando o Expo, aqui está um artigo detalhando como instalar no Expo.

Solução de problemas

Dica

Depois de executar o React DevTools, siga as instruções. Se seu aplicativo estava em execução antes de abrir o React DevTools, pode ser necessário abrir o menu do desenvolvedor para conectá-los.

image

INFORMAÇÕES

Se a conexão com o emulador for problemática (especialmente Android 12), tente executar adb reverse tcp:8097 tcp:8097 em um novo terminal.

',19),l=[n];function p(u,m,v,h,g,b){return o(),a("div",null,l)}const _=e(d,[["render",p]]);export{f as __pageData,_ as default}; diff --git a/vitepress/docs/.vitepress/dist/assets/docs_react-devtools.md.CK7_TSWs.lean.js b/vitepress/docs/.vitepress/dist/assets/docs_react-devtools.md.CK7_TSWs.lean.js new file mode 100644 index 0000000..61ea1dc --- /dev/null +++ b/vitepress/docs/.vitepress/dist/assets/docs_react-devtools.md.CK7_TSWs.lean.js @@ -0,0 +1 @@ +import{_ as e,c as a,o,a4 as t}from"./chunks/framework.nQaBHiNx.js";const s="/assets/309739868-01361acc-6dcc-4519-a990-1e00dd02c666.HXoiJ2NJ.png",r="/assets/309740243-cc8fe788-5dbb-40ee-aceb-aa74e4ed643b.BN1YkZEd.png",i="/assets/ReactDevToolsInspector-fed7286dac8ef8a793245cdd9d3d0f9c.DAvzAGx1.gif",c="/assets/ReactDevToolsConnection-2fcfc362befab4699fd8afceefa5903e.8_VLXZ0K.gif",f=JSON.parse('{"title":"Ferramentas de desenvolvedor React","description":"","frontmatter":{},"headers":[],"relativePath":"docs/react-devtools.md","filePath":"docs/react-devtools.md"}'),d={name:"docs/react-devtools.md"},n=t("",19),l=[n];function p(u,m,v,h,g,b){return o(),a("div",null,l)}const _=e(d,[["render",p]]);export{f as __pageData,_ as default}; diff --git a/vitepress/docs/.vitepress/dist/assets/docs_react-native-gradle-plugin.md.CPNRWRKn.js b/vitepress/docs/.vitepress/dist/assets/docs_react-native-gradle-plugin.md.CPNRWRKn.js new file mode 100644 index 0000000..f8188cf --- /dev/null +++ b/vitepress/docs/.vitepress/dist/assets/docs_react-native-gradle-plugin.md.CPNRWRKn.js @@ -0,0 +1 @@ +import{_ as a,c as e,o as s,a4 as o}from"./chunks/framework.nQaBHiNx.js";const k=JSON.parse('{"title":"Plug-in React Native Gradle","description":"","frontmatter":{},"headers":[],"relativePath":"docs/react-native-gradle-plugin.md","filePath":"docs/react-native-gradle-plugin.md"}'),i={name:"docs/react-native-gradle-plugin.md"},t=o('

Plug-in React Native Gradle

Este guia descreve como configurar o Plugin React Native Gradle (geralmente chamado de RNGP) ao criar seu aplicativo React Native para Android.

Usando o plugin

O plugin React Native Gradle é distribuído como um pacote NPM separado que é instalado automaticamente com react-native.

O plugin já está configurado para novos projetos criados usando npx react-native init. Você não precisa realizar nenhuma etapa extra para instalá-lo se tiver criado seu aplicativo com este comando.

Se você estiver integrando o React Native em um projeto existente, consulte a página correspondente: ela contém instruções específicas sobre como instalar o plugin.

Configurando o plugin

Por padrão, o plugin funcionará pronto para uso com padrões razoáveis. Você deve consultar este guia e personalizar o comportamento somente se precisar.

Para configurar o plugin você pode modificar o bloco react, dentro do seu android/app/build.gradle:

groovy
apply plugin: "com.facebook.react"\n\n/**\n * Este é o bloco de configuração para personalizar seu aplicativo React Native Android.\n * Por padrão você não precisa aplicar nenhuma configuração, apenas descomente as linhas necessárias.\n */\nreact {\n  // A configuração personalizada vai aqui.\n}

Cada chave de configuração é descrita abaixo:

root

Esta é a pasta raiz do seu projeto React Native, ou seja, onde reside o arquivo package.json. O padrão é ... Você pode personalizá-lo da seguinte maneira:

groovy
root = file("../")

reactNativeDir

Esta é a pasta onde reside o pacote react-native. O padrão é ../node_modules/react-native. Se você estiver em um monorepo ou usando um gerenciador de pacotes diferente, você pode usar o ajuste reactNativeDir para sua configuração.

Você pode personalizá-lo da seguinte maneira:

groovy
reactNativeDir = file("../node_modules/react-native")

codegenDir

Esta é a pasta onde reside o pacote react-native-codegen. O padrão é ../node_modules/react-native-codegen. Se você estiver em um monorepo ou usando um gerenciador de pacotes diferente, você pode ajustar codegenDir à sua configuração.

Você pode personalizá-lo da seguinte maneira:

groovy
codegenDir = file("../node_modules/@react-native/codegen")

cliFile

Este é o arquivo de ponto de entrada para o React Native CLI. O padrão é ../node_modules/react-native/cli.js. O arquivo do ponto de entrada é necessário porque o plug-in precisa invocar a CLI para agrupar e criar seu aplicativo.

Se você estiver em um monorepo ou usando um gerenciador de pacotes diferente, você pode ajustar o cliFile à sua configuração. Você pode personalizá-lo da seguinte maneira:

groovy
cliFile = file("../node_modules/react-native/cli.js")

debuggableVariants

Esta é a lista de variantes que podem ser depuradas (consulte a seção usando variantes disponível aqui para obter mais contexto sobre variantes).

Por padrão o plugin considera como debuggableVariants apenas debug, enquanto release não é. Se você tiver outra variantes (como staging, lite, etc.), você precisará ajustar isso de acordo.

As variantes listadas como debuggableVariants não virão com um pacote, então você precisará do Metro para executá-las.

Você pode personalizá-lo da seguinte maneira:

groovy
debuggableVariants = ["liteDebug", "prodDebug"]

nodeExecutableAndArgs

Esta é a lista de comandos e argumentos do nó que devem ser invocados para todos os scripts. Por padrão é [node] mas pode ser personalizado para adicionar sinalizadores extras como segue:

groovy
nodeExecutableAndArgs = ["node"]

bundleCommand

Este é o nome do comando bundle a ser invocado ao criar o pacote para seu aplicativo. Isso é útil se você estiver usando pacotes de RAM. Por padrão é bundle mas pode ser personalizado para adicionar sinalizadores extras como segue:

groovy
bundleCommand = "ram-bundle"

bundleConfig

Este é o caminho para um arquivo de configuração que será passado para bundle --config <file> se fornecido. O padrão é vazio (nenhum arquivo de configuração será proibido). Mais informações sobre o agrupamento de arquivos de configuração podem ser encontradas na documentação da CLI. Pode ser personalizado da seguinte forma:

groovy
bundleConfig = file(../rn-cli.config.js)

bundleAssetName

Este é o nome do arquivo do pacote que deve ser gerado. O padrão é index.android.bundle. Pode ser personalizado da seguinte forma:

groovy
bundleAssetName = "MyApplication.android.bundle"

entryFile

O arquivo de entrada usado para geração de pacote configurável. O padrão é procurar por index.android.js ou index.js. Pode ser personalizado da seguinte forma:

groovy
entryFile = file("../js/MyApplication.android.js")

extraPackagerArgs

Uma lista de sinalizadores extras que serão passados ​​para o comando bundle. A lista de sinalizadores disponíveis está na documentação da CLI. O padrão está vazio. Pode ser personalizado da seguinte forma:

groovy
extraPackagerArgs = []

hermesCommand

O caminho para o comando hermesc (o compilador Hermes). O React Native vem com uma versão do compilador Hermes, então geralmente você não precisará personalizá-lo. O plugin usará o compilador correto para o seu sistema por padrão.

hermesFlags

A lista de sinalizadores a serem passados ​​para hermesc. Por padrão é ["-O", "-output-source-map"]. Você pode personalizá-lo da seguinte maneira

groovy
hermesFlags = ["-O", "-output-source-map"]

Usando sabores e variantes de construção

Ao criar aplicativos Android, talvez você queira usar variações personalizadas para ter versões diferentes do seu aplicativo a partir do mesmo projeto.

Consulte o guia oficial do Android para configurar tipos de compilação personalizados (como staging) ou versões personalizadas (como full, lite , etc.).

Por padrão, novos aplicativos são criados com dois tipos de compilação (debug e release) e sem variações personalizadas.

A combinação de todos os tipos de compilação e todas as variações gera um conjunto de variantes de compilação. Por exemplo, para os tipos de compilação debug/staging/release e ​​full/lite você terá 6 variantes de compilação: fullDebug, fullStaging, fullRelease e ​​assim por diante.

Se você estiver usando variantes personalizadas além de debug e release, você precisa instruir o plugin React Native Gradle especificando quais de suas variantes são depuráveis usando a configuração debuggableVariants da seguinte forma :

diff
apply plugin: "com.facebook.react"\n\nreact {\n+ debuggableVariants = ["fullStaging", "fullDebug"]\n}

Isso é necessário porque o plugin irá ignorar o empacotamento JS para todos os debuggableVariants: você precisará do Metro para executá-los. Por exemplo, se você listar fullStaging em debuggableVariants, não será possível publicá-lo em uma loja, pois faltará o pacote.

O que o plugin está fazendo nos bastidores?

O plugin React Native Gradle é responsável por configurar a construção do seu aplicativo para enviar aplicativos React Native para produção. O plugin também é usado em bibliotecas de terceiros, para executar o Codegen usado para a Nova Arquitetura.

Aqui está um resumo das responsabilidades do plugin:

  • Adiciona uma tarefa createBundle<Variant>JsAndAssets para cada variante não depurável, que é responsável por invocar os comandos bundle, hermesc e compose-source-map.
  • Configura a versão adequada da dependência com.facebook.react:react-android e com.facebook.react:hermes-android, lendo a versão React Native do package.json de react-native .
  • Configura os repositórios Maven adequados (Maven Central, Google Maven Repo, repositório Maven local JSC, etc.) necessários para consumir todas as dependências Maven necessárias.
  • Configura o NDK para permitir a criação de aplicativos que usam a Nova Arquitetura.
  • Configura o buildConfigFields para que você possa saber em tempo de execução se o Hermes ou a Nova Arquitetura estão habilitados.
  • Configura a porta Metro DevServer como um recurso Android para que o aplicativo saiba em qual porta se conectar.
  • Invoca o React Native Codegen se uma biblioteca ou aplicativo estiver usando o Codegen para a nova arquitetura.
',67),n=[t];function r(d,l,p,c,h,u){return s(),e("div",null,n)}const v=a(i,[["render",r]]);export{k as __pageData,v as default}; diff --git a/vitepress/docs/.vitepress/dist/assets/docs_react-native-gradle-plugin.md.CPNRWRKn.lean.js b/vitepress/docs/.vitepress/dist/assets/docs_react-native-gradle-plugin.md.CPNRWRKn.lean.js new file mode 100644 index 0000000..9b80b98 --- /dev/null +++ b/vitepress/docs/.vitepress/dist/assets/docs_react-native-gradle-plugin.md.CPNRWRKn.lean.js @@ -0,0 +1 @@ +import{_ as a,c as e,o as s,a4 as o}from"./chunks/framework.nQaBHiNx.js";const k=JSON.parse('{"title":"Plug-in React Native Gradle","description":"","frontmatter":{},"headers":[],"relativePath":"docs/react-native-gradle-plugin.md","filePath":"docs/react-native-gradle-plugin.md"}'),i={name:"docs/react-native-gradle-plugin.md"},t=o("",67),n=[t];function r(d,l,p,c,h,u){return s(),e("div",null,n)}const v=a(i,[["render",r]]);export{k as __pageData,v as default}; diff --git a/vitepress/docs/.vitepress/dist/assets/docs_running-on-device.md.CXhWyhx3.js b/vitepress/docs/.vitepress/dist/assets/docs_running-on-device.md.CXhWyhx3.js new file mode 100644 index 0000000..24e7d3b --- /dev/null +++ b/vitepress/docs/.vitepress/dist/assets/docs_running-on-device.md.CXhWyhx3.js @@ -0,0 +1 @@ +import{_ as o,c as e,o as i,a4 as a}from"./chunks/framework.nQaBHiNx.js";const _=JSON.parse('{"title":"Executando no dispositivo","description":"","frontmatter":{},"headers":[],"relativePath":"docs/running-on-device.md","filePath":"docs/running-on-device.md"}'),s={name:"docs/running-on-device.md"},t=a('

Executando no dispositivo

É sempre uma boa ideia testar seu aplicativo em um dispositivo real antes de liberá-lo para seus usuários. Este documento irá guiá-lo pelas etapas necessárias para executar seu aplicativo React Native em um dispositivo e prepará-lo para produção.

Informações

Se você usou create-expo-app para configurar seu projeto, você pode executar seu aplicativo em um dispositivo no Expo Go digitalizando o código QR que é exibido quando você executa npm start. Consulte o guia Expo para executar seu projeto em seu dispositivo para obter mais informações.

',4),n=[t];function r(d,c,u,l,p,m){return i(),e("div",null,n)}const g=o(s,[["render",r]]);export{_ as __pageData,g as default}; diff --git a/vitepress/docs/.vitepress/dist/assets/docs_running-on-device.md.CXhWyhx3.lean.js b/vitepress/docs/.vitepress/dist/assets/docs_running-on-device.md.CXhWyhx3.lean.js new file mode 100644 index 0000000..dbebceb --- /dev/null +++ b/vitepress/docs/.vitepress/dist/assets/docs_running-on-device.md.CXhWyhx3.lean.js @@ -0,0 +1 @@ +import{_ as o,c as e,o as i,a4 as a}from"./chunks/framework.nQaBHiNx.js";const _=JSON.parse('{"title":"Executando no dispositivo","description":"","frontmatter":{},"headers":[],"relativePath":"docs/running-on-device.md","filePath":"docs/running-on-device.md"}'),s={name:"docs/running-on-device.md"},t=a("",4),n=[t];function r(d,c,u,l,p,m){return i(),e("div",null,n)}const g=o(s,[["render",r]]);export{_ as __pageData,g as default}; diff --git a/vitepress/docs/.vitepress/dist/assets/docs_running-on-device_android-linux.md.DRwWLWsA.js b/vitepress/docs/.vitepress/dist/assets/docs_running-on-device_android-linux.md.DRwWLWsA.js new file mode 100644 index 0000000..3272a35 --- /dev/null +++ b/vitepress/docs/.vitepress/dist/assets/docs_running-on-device_android-linux.md.DRwWLWsA.js @@ -0,0 +1,17 @@ +import{_ as s,c as i,o as a,a4 as e}from"./chunks/framework.nQaBHiNx.js";const g=JSON.parse('{"title":"Linux (Android)","description":"","frontmatter":{},"headers":[],"relativePath":"docs/running-on-device/android-linux.md","filePath":"docs/running-on-device/android-linux.md"}'),t={name:"docs/running-on-device/android-linux.md"},n=e(`

Linux (Android)

1. Habilite a depuração via USB

A maioria dos dispositivos Android só pode instalar e executar aplicativos baixados do Google Play, por padrão. Você precisará habilitar a depuração USB em seu dispositivo para instalar seu aplicativo durante o desenvolvimento.

Para ativar a depuração USB no seu dispositivo, primeiro você precisa ativar o menu "Opções do desenvolvedor" acessando Settings → About phone → Software information e tocando na linha Build number na parte inferior sete vezes. Você pode então voltar para Settings → Developer options para ativar a "USB debugging".

2. Conecte seu dispositivo via USB

Vamos agora configurar um dispositivo Android para executar nossos projetos React Native. Vá em frente e conecte seu dispositivo via USB à sua máquina de desenvolvimento.

Em seguida, verifique o código do fabricante usando lsusb (no Mac, você deve primeiro instalar o lsusb). lsusb deve gerar algo assim:

bash
$ lsusb
+Bus 002 Device 002: ID 8087:0024 Intel Corp. Integrated Rate Matching Hub
+Bus 002 Device 001: ID 1d6b:0002 Linux Foundation 2.0 root hub
+Bus 001 Device 003: ID 22b8:2e76 Motorola PCS
+Bus 001 Device 002: ID 8087:0024 Intel Corp. Integrated Rate Matching Hub
+Bus 001 Device 001: ID 1d6b:0002 Linux Foundation 2.0 root hub
+Bus 004 Device 001: ID 1d6b:0003 Linux Foundation 3.0 root hub
+Bus 003 Device 001: ID 1d6b:0002 Linux Foundation 2.0 root hub

Estas linhas representam os dispositivos USB atualmente conectados à sua máquina.

Você quer a linha que representa o seu telefone. Em caso de dúvida, tente desconectar o telefone e executar o comando novamente:

bash
$ lsusb
+Bus 002 Device 002: ID 8087:0024 Intel Corp. Integrated Rate Matching Hub
+Bus 002 Device 001: ID 1d6b:0002 Linux Foundation 2.0 root hub
+Bus 001 Device 002: ID 8087:0024 Intel Corp. Integrated Rate Matching Hub
+Bus 001 Device 001: ID 1d6b:0002 Linux Foundation 2.0 root hub
+Bus 004 Device 001: ID 1d6b:0003 Linux Foundation 3.0 root hub
+Bus 003 Device 001: ID 1d6b:0002 Linux Foundation 2.0 root hub

Você verá que após retirar o telefone, a linha que contém o modelo do telefone (“Motorola PCS” neste caso) desapareceu da lista. Esta é a linha com a qual nos preocupamos.

bash
Bus 001 Device 003: ID 22b8:2e76 Motorola PCS

Na linha acima, você deve obter os primeiros quatro dígitos do ID do dispositivo:

bash
22b8:2e76

Neste caso, é 22b8. Esse é o identificador da Motorola.

Você precisará inserir isso nas regras do udev para começar a trabalhar:

bash
echo 'SUBSYSTEM=="usb", ATTR{idVendor}=="22b8", MODE="0666", GROUP="plugdev"' | sudo tee /etc/udev/rules.d/51-android-usb.rules

Certifique-se de substituir 22b8 pelo identificador obtido no comando acima.

Agora verifique se o seu dispositivo está conectado corretamente ao ADB, o Android Debug Bridge, executando adb devices.

bash
$ adb devices
+List of devices attached
+emulator-5554 offline   # Google emulator
+14ed2fcc device         # Dispositivo físico

Ver o device na coluna da direita significa que o dispositivo está conectado. Você deve ter apenas um dispositivo conectado por vez.

3. Execute seu aplicativo

Na raiz do seu projeto, digite o seguinte no prompt de comando para instalar e iniciar seu aplicativo no dispositivo:

bash
npm run android
bash
yarn android

DICA

Você também pode usar o React Native CLI para gerar e executar uma release (por exemplo, da raiz do seu projeto: yarn android --mode release).

Conectando-se ao servidor de desenvolvimento

Você também pode iterar rapidamente em um dispositivo conectando-se ao servidor de desenvolvimento em execução na sua máquina de desenvolvimento. Existem várias maneiras de fazer isso, dependendo se você tem acesso a um cabo USB ou a uma rede Wi-Fi.

Método 1: usando adb reverse (recomendado)

Você pode usar este método se o seu dispositivo estiver executando o Android 5.0 (Lollipop) ou mais recente, tiver a depuração USB ativada e estiver conectado via USB à sua máquina de desenvolvimento.

Execute o seguinte em um prompt de comando:

bash
adb -s <device name> reverse tcp:8081 tcp:8081

Para encontrar o nome do dispositivo, execute o seguinte comando adb:

bash
adb devices

Agora você pode ativar o recarregamento ao vivo no Dev Menu. Seu aplicativo será recarregado sempre que seu código JavaScript for alterado.

Método 2: conectar via Wi-Fi

Você também pode se conectar ao servidor de desenvolvimento por Wi-Fi. Primeiro, você precisará instalar o aplicativo em seu dispositivo usando um cabo USB, mas depois de fazer isso, você poderá depurar sem fio seguindo estas instruções. Você precisará do endereço IP atual da sua máquina de desenvolvimento antes de continuar.

Abra um terminal e digite /sbin/ifconfig para encontrar o endereço IP da sua máquina.

  1. Certifique-se de que seu laptop e telefone estejam na mesma rede Wi-Fi.
  2. Abra seu aplicativo React Native em seu dispositivo.
  3. Você verá uma tela vermelha com um erro. Tudo bem. As etapas a seguir corrigirão isso.
  4. Abra o menu de desenvolvimento do aplicativo.
  5. Vá para Dev Settings → Debug server host & port for device.
  6. Digite o endereço IP da sua máquina e a porta do servidor de desenvolvimento local (por exemplo, 10.0.1.1:8081).
  7. Volte ao Dev Menu e selecione Reload JS.

Agora você pode ativar o recarregamento ao vivo no Dev Menu. Seu aplicativo será recarregado sempre que seu código JavaScript for alterado.

Construindo seu aplicativo para produção

Você construiu um ótimo aplicativo usando React Native e agora está ansioso para lançá-lo na Play Store. O processo é igual ao de qualquer outro aplicativo Android nativo, com algumas considerações adicionais a serem levadas em consideração. Siga o guia para gerar um APK assinado para saber mais.

`,42),h=[n];function p(l,o,k,d,r,F){return a(),i("div",null,h)}const u=s(t,[["render",p]]);export{g as __pageData,u as default}; diff --git a/vitepress/docs/.vitepress/dist/assets/docs_running-on-device_android-linux.md.DRwWLWsA.lean.js b/vitepress/docs/.vitepress/dist/assets/docs_running-on-device_android-linux.md.DRwWLWsA.lean.js new file mode 100644 index 0000000..e80e80e --- /dev/null +++ b/vitepress/docs/.vitepress/dist/assets/docs_running-on-device_android-linux.md.DRwWLWsA.lean.js @@ -0,0 +1 @@ +import{_ as s,c as i,o as a,a4 as e}from"./chunks/framework.nQaBHiNx.js";const g=JSON.parse('{"title":"Linux (Android)","description":"","frontmatter":{},"headers":[],"relativePath":"docs/running-on-device/android-linux.md","filePath":"docs/running-on-device/android-linux.md"}'),t={name:"docs/running-on-device/android-linux.md"},n=e("",42),h=[n];function p(l,o,k,d,r,F){return a(),i("div",null,h)}const u=s(t,[["render",p]]);export{g as __pageData,u as default}; diff --git a/vitepress/docs/.vitepress/dist/assets/docs_running-on-device_android-mac-os.md.CaJ567kc.js b/vitepress/docs/.vitepress/dist/assets/docs_running-on-device_android-mac-os.md.CaJ567kc.js new file mode 100644 index 0000000..ad18330 --- /dev/null +++ b/vitepress/docs/.vitepress/dist/assets/docs_running-on-device_android-mac-os.md.CaJ567kc.js @@ -0,0 +1,4 @@ +import{_ as a,c as e,o as i,a4 as s}from"./chunks/framework.nQaBHiNx.js";const m=JSON.parse('{"title":"Mac OS (Android)","description":"","frontmatter":{},"headers":[],"relativePath":"docs/running-on-device/android-mac-os.md","filePath":"docs/running-on-device/android-mac-os.md"}'),o={name:"docs/running-on-device/android-mac-os.md"},t=s(`

Mac OS (Android)

1. Habilite a depuração via USB

A maioria dos dispositivos Android só pode instalar e executar aplicativos baixados do Google Play, por padrão. Você precisará habilitar a depuração USB em seu dispositivo para instalar seu aplicativo durante o desenvolvimento.

Para ativar a depuração USB no seu dispositivo, primeiro você precisa ativar o menu "Developer options" acessando Settings → About phone → Software information e tocando na linha Build number na parte inferior sete vezes. Você pode então voltar para Settings → Developer options para ativar a "USB debugging".

2. Conecte seu dispositivo via USB

Vamos agora configurar um dispositivo Android para executar nossos projetos React Native. Vá em frente e conecte seu dispositivo via USB à sua máquina de desenvolvimento.

Agora verifique se o seu dispositivo está conectado corretamente ao ADB, o Android Debug Bridge, executando adb devices.

bash
$ adb devices
+List of devices attached
+emulator-5554 offline   # Google emulator
+14ed2fcc device         # Physical device

Ver o device na coluna da direita significa que o dispositivo está conectado. Você deve ter apenas um dispositivo conectado por vez.

OBSERVAÇÃO

Se você vê unauthorized na lista, precisará executar adb reverse tcp:8081 tcp:8081 e pressionar permitir depuração USB no dispositivo.

3. Execute seu aplicativo

Da raiz do seu projeto; digite o seguinte no prompt de comando para instalar e iniciar seu aplicativo no dispositivo:

bash
npm run android
bash
yarn android

DICA

Você também pode usar o React Native CLI para gerar e executar uma versão build (por exemplo, da raiz do seu projeto: yarn android --mode release).

Conectando-se ao servidor de desenvolvimento

Você também pode iterar rapidamente em um dispositivo conectando-se ao servidor de desenvolvimento em execução na sua máquina de desenvolvimento. Existem várias maneiras de fazer isso, dependendo se você tem acesso a um cabo USB ou a uma rede Wi-Fi.

Método 1: usando adb reverse (recomendado)

Você pode usar este método se o seu dispositivo estiver executando o Android 5.0 (Lollipop) ou mais recente, tiver a depuração USB ativada e estiver conectado via USB à sua máquina de desenvolvimento.

Execute o seguinte em um prompt de comando:

bash
adb -s <device name> reverse tcp:8081 tcp:8081

Para encontrar o nome do dispositivo, execute o seguinte comando adb:

bash
adb devices

Agora você pode ativar o recarregamento ao vivo no menu Dev. Seu aplicativo será recarregado sempre que seu código JavaScript for alterado.

Método 2: conectar via Wi-Fi

Você também pode se conectar ao servidor de desenvolvimento por Wi-Fi. Primeiro, você precisará instalar o aplicativo em seu dispositivo usando um cabo USB, mas depois de fazer isso, você poderá depurar sem fio seguindo estas instruções. Você precisará do endereço IP atual da sua máquina de desenvolvimento antes de continuar.

Você pode encontrar o endereço IP em System Settings (ou System Preferences) → Network.

  1. Certifique-se de que seu laptop e telefone estejam na mesma rede Wi-Fi.
  2. Abra seu aplicativo React Native em seu dispositivo.
  3. Você verá uma tela vermelha com um erro, tudo bem. As etapas a seguir corrigirão isso.
  4. Abra o menu de desenvolvimento do aplicativo.
  5. Vá para Dev Settings → Debug server host & port for device. 6.Digite o endereço IP da sua máquina e a porta do servidor de desenvolvimento local (por exemplo, 10.0.1.1:8081).
  6. Volte ao Dev Menu e selecione Reload JS.

Agora você pode ativar o recarregamento ao vivo no menu Dev. Seu aplicativo será recarregado sempre que seu código JavaScript for alterado.

Construindo seu aplicativo para produção

Você construiu um ótimo aplicativo usando React Native e agora está ansioso para lançá-lo na Play Store. O processo é igual ao de qualquer outro aplicativo Android nativo, com algumas considerações adicionais a serem levadas em consideração. Siga o guia para gerar um APK assinado para saber mais.

`,30),d=[t];function n(r,p,c,l,u,h){return i(),e("div",null,d)}const g=a(o,[["render",n]]);export{m as __pageData,g as default}; diff --git a/vitepress/docs/.vitepress/dist/assets/docs_running-on-device_android-mac-os.md.CaJ567kc.lean.js b/vitepress/docs/.vitepress/dist/assets/docs_running-on-device_android-mac-os.md.CaJ567kc.lean.js new file mode 100644 index 0000000..59ec494 --- /dev/null +++ b/vitepress/docs/.vitepress/dist/assets/docs_running-on-device_android-mac-os.md.CaJ567kc.lean.js @@ -0,0 +1 @@ +import{_ as a,c as e,o as i,a4 as s}from"./chunks/framework.nQaBHiNx.js";const m=JSON.parse('{"title":"Mac OS (Android)","description":"","frontmatter":{},"headers":[],"relativePath":"docs/running-on-device/android-mac-os.md","filePath":"docs/running-on-device/android-mac-os.md"}'),o={name:"docs/running-on-device/android-mac-os.md"},t=s("",30),d=[t];function n(r,p,c,l,u,h){return i(),e("div",null,d)}const g=a(o,[["render",n]]);export{m as __pageData,g as default}; diff --git a/vitepress/docs/.vitepress/dist/assets/docs_running-on-device_android-windows.md.CdtSsrGE.js b/vitepress/docs/.vitepress/dist/assets/docs_running-on-device_android-windows.md.CdtSsrGE.js new file mode 100644 index 0000000..90f2984 --- /dev/null +++ b/vitepress/docs/.vitepress/dist/assets/docs_running-on-device_android-windows.md.CdtSsrGE.js @@ -0,0 +1,4 @@ +import{_ as a,c as e,o as i,a4 as s}from"./chunks/framework.nQaBHiNx.js";const m=JSON.parse('{"title":"Windows (Android)","description":"","frontmatter":{},"headers":[],"relativePath":"docs/running-on-device/android-windows.md","filePath":"docs/running-on-device/android-windows.md"}'),o={name:"docs/running-on-device/android-windows.md"},t=s(`

Windows (Android)

1. Habilite a depuração via USB

A maioria dos dispositivos Android só pode instalar e executar aplicativos baixados do Google Play, por padrão. Você precisará habilitar a depuração USB em seu dispositivo para instalar seu aplicativo durante o desenvolvimento.

Para ativar a depuração USB no seu dispositivo, primeiro você precisa ativar o menu "Opções do desenvolvedor" acessando Settings → About phone → Software information e tocando na linha Build number na parte inferior sete vezes. Você pode então voltar para Settings → Developer options para ativar a "depuração USB".

2. Conecte seu dispositivo via USB

Vamos agora configurar um dispositivo Android para executar nossos projetos React Native. Vá em frente e conecte seu dispositivo via USB à sua máquina de desenvolvimento.

Agora verifique se o seu dispositivo está conectado corretamente ao ADB, o Android Debug Bridge, executando adb devices.

bash
$ adb devices
+List of devices attached
+emulator-5554 offline   # Google emulator
+14ed2fcc device         # Physical device

Ver o dispositivo na coluna da direita significa que o dispositivo está conectado. Você deve ter apenas um dispositivo conectado por vez.

3. Execute seu aplicativo

Na raiz do seu projeto, execute o seguinte no prompt de comando para instalar e iniciar seu aplicativo no dispositivo:

bash
npm run android
bash
yarn android

DICA

Você também pode usar o React Native CLI para gerar e executar uma release build (por exemplo, da raiz do seu projeto: yarn android --mode release).

Conectando-se ao servidor de desenvolvimento

Você também pode iterar rapidamente em um dispositivo conectando-se ao servidor de desenvolvimento em execução na sua máquina de desenvolvimento. Existem várias maneiras de fazer isso, dependendo se você tem acesso a um cabo USB ou a uma rede Wi-Fi.

Método 1: usando adb reverse (recomendado)

Você pode usar este método se o seu dispositivo estiver executando o Android 5.0 (Lollipop) ou mais recente, tiver a depuração USB ativada e estiver conectado via USB à sua máquina de desenvolvimento.

Execute o seguinte em um prompt de comando:

bash
adb -s <device name> reverse tcp:8081 tcp:8081

Para encontrar o nome do dispositivo, execute o seguinte comando adb:

bash
adb devices

Agora você pode ativar o recarregamento ao vivo no Dev Menu. Seu aplicativo será recarregado sempre que seu código JavaScript for alterado.

Método 2: conectar via Wi-Fi

Você também pode se conectar ao servidor de desenvolvimento por Wi-Fi. Primeiro, você precisará instalar o aplicativo em seu dispositivo usando um cabo USB, mas depois de fazer isso, você poderá depurar sem fio seguindo estas instruções. Você precisará do endereço IP atual da sua máquina de desenvolvimento antes de continuar.

Abra o prompt de comando e digite ipconfig para encontrar o endereço IP da sua máquina (mais informações).

  1. Certifique-se de que seu laptop e telefone estejam na mesma rede Wi-Fi.
  2. Abra seu aplicativo React Native em seu dispositivo.
  3. Você verá uma tela vermelha com um erro. Tudo bem. As etapas a seguir corrigirão isso.
  4. Abra o menu de Dev Menu.
  5. Vá para Dev Settings → Debug server host & port for device.
  6. Digite o endereço IP da sua máquina e a porta do servidor de desenvolvimento local (por exemplo, 10.0.1.1:8081).
  7. Volte ao Dev Menu e selecione Reload JS.

Agora você pode ativar o recarregamento ao vivo no Dev Menu. Seu aplicativo será recarregado sempre que seu código JavaScript for alterado.

Construindo seu aplicativo para produção

Você construiu um ótimo aplicativo usando React Native e agora está ansioso para lançá-lo na Play Store. O processo é igual ao de qualquer outro aplicativo Android nativo, com algumas considerações adicionais a serem levadas em consideração. Siga o guia para gerar um APK assinado para saber mais.

`,29),n=[t];function d(r,p,l,c,u,h){return i(),e("div",null,n)}const g=a(o,[["render",d]]);export{m as __pageData,g as default}; diff --git a/vitepress/docs/.vitepress/dist/assets/docs_running-on-device_android-windows.md.CdtSsrGE.lean.js b/vitepress/docs/.vitepress/dist/assets/docs_running-on-device_android-windows.md.CdtSsrGE.lean.js new file mode 100644 index 0000000..bb78d59 --- /dev/null +++ b/vitepress/docs/.vitepress/dist/assets/docs_running-on-device_android-windows.md.CdtSsrGE.lean.js @@ -0,0 +1 @@ +import{_ as a,c as e,o as i,a4 as s}from"./chunks/framework.nQaBHiNx.js";const m=JSON.parse('{"title":"Windows (Android)","description":"","frontmatter":{},"headers":[],"relativePath":"docs/running-on-device/android-windows.md","filePath":"docs/running-on-device/android-windows.md"}'),o={name:"docs/running-on-device/android-windows.md"},t=s("",29),n=[t];function d(r,p,l,c,u,h){return i(),e("div",null,n)}const g=a(o,[["render",d]]);export{m as __pageData,g as default}; diff --git a/vitepress/docs/.vitepress/dist/assets/docs_running-on-device_ios-macos.md.R_Mogg6l.js b/vitepress/docs/.vitepress/dist/assets/docs_running-on-device_ios-macos.md.R_Mogg6l.js new file mode 100644 index 0000000..20f54ae --- /dev/null +++ b/vitepress/docs/.vitepress/dist/assets/docs_running-on-device_ios-macos.md.R_Mogg6l.js @@ -0,0 +1 @@ +import{_ as e,c as o,o as a,a4 as i}from"./chunks/framework.nQaBHiNx.js";const s="/assets/291728755-273dca85-faa0-47ae-91df-cadf50a8d93c.85Xk1nI_.png",r="/assets/291729573-749ebf4e-e79c-40ba-aba4-d53d68980d2e.DjW8FgZr.png",t="/assets/291729726-29d54dfe-1e52-4825-a725-72ef104637f6.Dml7mBnh.png",d="/assets/291731440-2a8a10d3-4846-4c5a-8596-b4fcd74b8557.BdPjwJSF.png",_=JSON.parse('{"title":"Mac OS (iOS)","description":"","frontmatter":{},"headers":[],"relativePath":"docs/running-on-device/ios-macos.md","filePath":"docs/running-on-device/ios-macos.md"}'),c={name:"docs/running-on-device/ios-macos.md"},n=i('

Mac OS (iOS)

1. Conecte seu dispositivo via USB

Conecte seu dispositivo iOS ao Mac usando um cabo USB para Lightning. Navegue até a pasta ios em seu projeto e abra o arquivo .xcodeproj ou, se estiver usando CocoaPods, abra .xcworkspace, dentro dele usando o Xcode.

Se esta for a primeira vez que você executa um aplicativo em seu dispositivo iOS, talvez seja necessário registrar seu dispositivo para desenvolvimento. Abra o menu Product na barra de menu do Xcode e vá para Destination. Procure e selecione seu dispositivo na lista. O Xcode registrará seu dispositivo para desenvolvimento.

2. Configure a assinatura de código

Registre-se para obter uma conta de desenvolvedor Apple, caso ainda não tenha uma.

Selecione seu projeto no Xcode Project Navigator e, em seguida, selecione seu destino principal (deve ter o mesmo nome do seu projeto). Procure a aba “General”. Vá para "Signing" e certifique-se de que sua conta ou equipe de desenvolvedor Apple esteja selecionada no menu suspenso Equipe. Faça o mesmo para o alvo de testes (termina com Tests e está abaixo do seu alvo principal).

Repita esta etapa para o destino Testes em seu projeto.

image

3. Crie e execute seu aplicativo

Se tudo estiver configurado corretamente, seu dispositivo será listado como destino de compilação na barra de ferramentas do Xcode e também aparecerá no painel Dispositivos (Shift ⇧ + Cmd ⌘ + 2). Agora você pode pressionar o botão Build and run (Cmd ⌘ + R) ou selecionar Run no menu Product. Seu aplicativo será iniciado em seu dispositivo em breve.

image

DICA

Se você tiver algum problema, consulte os documentos da Apple Como iniciar seu aplicativo em um dispositivo.

Conectando-se ao servidor de desenvolvimento

Você também pode iterar rapidamente em um dispositivo usando o servidor de desenvolvimento. Você só precisa estar na mesma rede Wi-Fi do seu computador. Agite seu dispositivo para abrir o Dev Menu e ative o Live Reload. Seu aplicativo será recarregado sempre que seu código JavaScript for alterado.

image

Solução de problemas

DICA

Se você tiver algum problema, certifique-se de que seu Mac e seu dispositivo estejam na mesma rede e possam se comunicar. Muitas redes sem fio abertas com portais cativos são configuradas para impedir que dispositivos alcancem outros dispositivos na rede. Você pode usar o recurso Personal Hotspot do seu dispositivo neste caso. Você também pode compartilhar sua conexão de Internet (Wi-Fi/Ethernet) do seu Mac para o seu dispositivo via USB e conectar-se ao empacotador através deste túnel para velocidades de transferência muito altas.

Ao tentar se conectar ao servidor de desenvolvimento, você poderá receber uma tela vermelha com um erro dizendo:

DICA

A conexão com http://localhost:8081/debugger-proxy?role=client expirou. Você está executando o proxy do nó? Se você estiver executando no dispositivo, verifique se possui o endereço IP correto em RCTWebSocketExecutor.m.

Para resolver este problema verifique os seguintes pontos.

1. Rede Wi-Fi.

Certifique-se de que seu laptop e telefone estejam na mesma rede Wi-Fi.

2. Endereço IP

Certifique-se de que o script de construção detectou o endereço IP da sua máquina corretamente (por exemplo, 10.0.1.123).

image

Abra a aba Report Navigator, selecione o último Build e pesquise IP= seguido de um endereço IP. O endereço IP incorporado no aplicativo deve corresponder ao endereço IP da sua máquina.

Construindo seu aplicativo para produção

Você construiu um ótimo aplicativo usando React Native e agora está ansioso para lançá-lo na App Store. O processo é igual ao de qualquer outro aplicativo iOS nativo, com algumas considerações adicionais a serem levadas em consideração. Siga o guia de publicação na Apple App Store para saber mais.

',29),p=[n];function u(l,m,v,g,h,b){return a(),o("div",null,p)}const q=e(c,[["render",u]]);export{_ as __pageData,q as default}; diff --git a/vitepress/docs/.vitepress/dist/assets/docs_running-on-device_ios-macos.md.R_Mogg6l.lean.js b/vitepress/docs/.vitepress/dist/assets/docs_running-on-device_ios-macos.md.R_Mogg6l.lean.js new file mode 100644 index 0000000..0b5a9d3 --- /dev/null +++ b/vitepress/docs/.vitepress/dist/assets/docs_running-on-device_ios-macos.md.R_Mogg6l.lean.js @@ -0,0 +1 @@ +import{_ as e,c as o,o as a,a4 as i}from"./chunks/framework.nQaBHiNx.js";const s="/assets/291728755-273dca85-faa0-47ae-91df-cadf50a8d93c.85Xk1nI_.png",r="/assets/291729573-749ebf4e-e79c-40ba-aba4-d53d68980d2e.DjW8FgZr.png",t="/assets/291729726-29d54dfe-1e52-4825-a725-72ef104637f6.Dml7mBnh.png",d="/assets/291731440-2a8a10d3-4846-4c5a-8596-b4fcd74b8557.BdPjwJSF.png",_=JSON.parse('{"title":"Mac OS (iOS)","description":"","frontmatter":{},"headers":[],"relativePath":"docs/running-on-device/ios-macos.md","filePath":"docs/running-on-device/ios-macos.md"}'),c={name:"docs/running-on-device/ios-macos.md"},n=i("",29),p=[n];function u(l,m,v,g,h,b){return a(),o("div",null,p)}const q=e(c,[["render",u]]);export{_ as __pageData,q as default}; diff --git a/vitepress/docs/.vitepress/dist/assets/docs_running-on-simulator-ios.md.HAs3yTdi.js b/vitepress/docs/.vitepress/dist/assets/docs_running-on-simulator-ios.md.HAs3yTdi.js new file mode 100644 index 0000000..8ffb475 --- /dev/null +++ b/vitepress/docs/.vitepress/dist/assets/docs_running-on-simulator-ios.md.HAs3yTdi.js @@ -0,0 +1 @@ +import{_ as i,c as s,o as a,a4 as e}from"./chunks/framework.nQaBHiNx.js";const v=JSON.parse('{"title":"Executando no Simulador","description":"","frontmatter":{},"headers":[],"relativePath":"docs/running-on-simulator-ios.md","filePath":"docs/running-on-simulator-ios.md"}'),o={name:"docs/running-on-simulator-ios.md"},t=e('

Executando no Simulador

Iniciando o simulador

Depois de inicializar seu projeto React Native, você pode executar o seguinte comando dentro do diretório do projeto recém-criado.

bash
npm run ios
bash
yarn ios

Se tudo estiver configurado corretamente, você deverá ver seu novo aplicativo em execução no Simulador iOS em breve.

Especificando um dispositivo

Você pode especificar o dispositivo que o simulador deve executar com o sinalizador --simulator, seguido pelo nome do dispositivo como uma string. O padrão é "iPhone 14". Se desejar executar seu aplicativo em um iPhone SE (3ª geração), execute o seguinte comando:

bash
npm run ios -- --simulator="iPhone SE (3rd generation)"
bash
yarn ios --simulator "iPhone SE (3rd generation)"

Os nomes dos dispositivos correspondem à lista de dispositivos disponíveis no Xcode. Você pode verificar seus dispositivos disponíveis executando xcrun simctl list devices no console.

Especificando uma versão do dispositivo

Se você tiver várias versões do iOS instaladas, também precisará especificar a versão apropriada. Por exemplo. Para executar seu aplicativo em um iPhone 14 Pro (16.0), execute o seguinte comando:

bash
npm run ios -- --simulator="iPhone 14 Pro (16.0)"
bash
yarn ios --simulator "iPhone 14 Pro (16.0)"

Especificando um UDID

Você pode especificar o UDID do dispositivo retornado do comando xcrun simctl list devices. Por exemplo. Para executar seu aplicativo com UDID AAAAAAAA-AAAA-AAAA-AAAA-AAAAAAAAAAAA execute o seguinte comando:

bash
npm run ios -- --udid="AAAAAAAA-AAAA-AAAA-AAAA-AAAAAAAAAAAA"
bash
yarn ios --udid "AAAAAAAA-AAAA-AAAA-AAAA-AAAAAAAAAAAA"
',15),n=[t];function d(p,l,c,r,h,u){return a(),s("div",null,n)}const g=i(o,[["render",d]]);export{v as __pageData,g as default}; diff --git a/vitepress/docs/.vitepress/dist/assets/docs_running-on-simulator-ios.md.HAs3yTdi.lean.js b/vitepress/docs/.vitepress/dist/assets/docs_running-on-simulator-ios.md.HAs3yTdi.lean.js new file mode 100644 index 0000000..6a8170a --- /dev/null +++ b/vitepress/docs/.vitepress/dist/assets/docs_running-on-simulator-ios.md.HAs3yTdi.lean.js @@ -0,0 +1 @@ +import{_ as i,c as s,o as a,a4 as e}from"./chunks/framework.nQaBHiNx.js";const v=JSON.parse('{"title":"Executando no Simulador","description":"","frontmatter":{},"headers":[],"relativePath":"docs/running-on-simulator-ios.md","filePath":"docs/running-on-simulator-ios.md"}'),o={name:"docs/running-on-simulator-ios.md"},t=e("",15),n=[t];function d(p,l,c,r,h,u){return a(),s("div",null,n)}const g=i(o,[["render",d]]);export{v as __pageData,g as default}; diff --git a/vitepress/docs/.vitepress/dist/assets/docs_security.md.DrXA_4lZ.js b/vitepress/docs/.vitepress/dist/assets/docs_security.md.DrXA_4lZ.js new file mode 100644 index 0000000..7107642 --- /dev/null +++ b/vitepress/docs/.vitepress/dist/assets/docs_security.md.DrXA_4lZ.js @@ -0,0 +1 @@ +import{_ as e,c as a,o,a4 as r}from"./chunks/framework.nQaBHiNx.js";const i="data:image/svg+xml;base64,PHN2ZyBpZD0iY2hhcnQiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIgdmlld0JveD0iMCAwIDI4MyAxOTUiPjxkZWZzPjxzdHlsZT4uY2xzLTF7ZmlsbDojOTdhYWQ4O30uY2xzLTIsLmNscy0ze2ZpbGw6bm9uZTtzdHJva2UtbWl0ZXJsaW1pdDoxMDt9LmNscy0ye3N0cm9rZTojZDIzYzZmO30uY2xzLTN7c3Ryb2tlOiM1OTcxYjU7c3Ryb2tlLXdpZHRoOjJweDt9LmNscy00LC5jbHMtNXtmb250LXNpemU6MTJweDtmb250LWZhbWlseTotYXBwbGUtc3lzdGVtLCBCbGlua01hY1N5c3RlbUZvbnQsICdTZWdvZSBVSScsIEhlbHZldGljYSwgQXJpYWwsIHNhbnMtc2VyaWYsICdBcHBsZSBDb2xvciBFbW9qaScsICdTZWdvZSBVSSBFbW9qaScsICdTZWdvZSBVSSBTeW1ib2wnO2ZvbnQtd2VpZ2h0OjYwMDt9LmNscy00e2ZpbGw6I2QyM2M2Zjt9LmNscy01e2ZpbGw6IzM3NGQ5Yzt9PC9zdHlsZT48L2RlZnM+PHBhdGggY2xhc3M9ImNscy0xIiBkPSJNNDksMTU5QzE1NSwxNDksMjUwLDI2LDI1MCwyNlYxNTkiLz48cGF0aCBjbGFzcz0iY2xzLTIiIGQ9Ik01MC4yLDI4LjY4QzQ5LjUsMTY5LjUsMTY2LjUsMTU0LjUsMjUwLjUsMTU3LjUiLz48cG9seWxpbmUgY2xhc3M9ImNscy0zIiBwb2ludHM9IjI1MCAxNjAgNTAgMTYwIDUwIDI2Ii8+PHRleHQgY2xhc3M9ImNscy00IiB0cmFuc2Zvcm09InRyYW5zbGF0ZSg0MC42NiAxNTguNzEpIHJvdGF0ZSgtOTApIj5saWtlbGlob29kIG9mIGEgYnJlYWNoPC90ZXh0Pjx0ZXh0IGNsYXNzPSJjbHMtNSIgdHJhbnNmb3JtPSJ0cmFuc2xhdGUoNTIuNDMgMTc1LjIzKSI+ZWZmb3J0IGludmVzdGVkIGluIHNlY3VyaXR5PC90ZXh0Pjwvc3ZnPg==",s="/assets/d_security_deep-linking.C1poVAy4.svg",t="/assets/298200622-2dd8fd0b-c69c-41c3-a787-87e4f7ffe95c.GYWIUQtH.png",b=JSON.parse('{"title":"Segurança","description":"","frontmatter":{},"headers":[],"relativePath":"docs/security.md","filePath":"docs/security.md"}'),n={name:"docs/security.md"},d=r('

Segurança

A segurança é frequentemente negligenciada ao criar aplicativos. É verdade que é impossível construir software que seja completamente impenetrável – ainda temos que inventar uma fechadura completamente impenetrável (afinal, os cofres dos bancos ainda são arrombados). No entanto, a probabilidade de ser vítima de um ataque malicioso ou de ser exposto a uma vulnerabilidade de segurança é inversamente proporcional ao esforço que você está disposto a fazer para proteger seu aplicativo contra tal eventualidade. Embora um cadeado comum possa ser arrombado, ainda é muito mais difícil de passar do que um gancho de armário!

Neste guia, você aprenderá sobre as práticas recomendadas para armazenamento de informações confidenciais, autenticação, segurança de rede e ferramentas que ajudarão você a proteger seu aplicativo. Esta não é uma lista de verificação prévia – é um catálogo de opções, cada uma das quais ajudará a proteger ainda mais seu aplicativo e seus usuários.

Probabilidade de violação x esforço investido em segurança

Armazenando informações confidenciais

Nunca armazene chaves de API confidenciais no código do seu aplicativo. Qualquer coisa incluída no seu código pode ser acessada em texto simples por qualquer pessoa que inspecione o pacote de aplicativos. Ferramentas como react-native-dotenv e react-native-config são ótimas para adicionar variáveis específicas do ambiente, como endpoints de API, mas não devem ser confundidas com variáveis de ambiente do lado do servidor, que muitas vezes podem conter segredos e chaves de API.

Se você precisar de uma chave de API ou um segredo para acessar algum recurso do seu aplicativo, a maneira mais segura de lidar com isso seria construir uma camada de orquestração entre o seu aplicativo e o recurso. Esta poderia ser uma função sem servidor (por exemplo, usando AWS Lambda ou Google Cloud Functions) que pode encaminhar a solicitação com a chave ou segredo de API necessário. Os segredos no código do lado do servidor não podem ser acessados pelos consumidores da API da mesma forma que os segredos no código do seu aplicativo.

Para dados persistentes do usuário, escolha o tipo certo de armazenamento com base em sua sensibilidade. À medida que seu aplicativo é usado, muitas vezes você encontrará a necessidade de salvar dados no dispositivo, seja para oferecer suporte ao uso off-line do seu aplicativo, reduzir solicitações de rede ou salvar o token de acesso do usuário entre sessões para que eles não precisem voltar. -autenticar cada vez que usarem o aplicativo.

Persistente versus não persistente – os dados persistentes são gravados no disco do dispositivo, o que permite que os dados sejam lidos pelo seu aplicativo durante a inicialização do aplicativo, sem a necessidade de fazer outra solicitação de rede para buscá-los ou solicitar ao usuário que os insira novamente. Mas isso também pode tornar esses dados mais vulneráveis ao acesso de invasores. Os dados não persistentes nunca são gravados no disco — portanto, não há dados para acessar!

Armazenamento assíncrono

Async Storage é um módulo mantido pela comunidade para React Native que fornece um armazenamento de chave-valor assíncrono e não criptografado. O armazenamento assíncrono não é compartilhado entre aplicativos: cada aplicativo possui seu próprio ambiente sandbox e não tem acesso aos dados de outros aplicativos.

USE ARMAZENAMENTO ASSYNC QUANDO...NÃO USE ARMAZENAMENTO ASSINCRONO PARA...
Persistência de dados não confidenciais em execuções de aplicativosArmazenamento de tokens
Estado Redux persistenteSegredos
Estado GraphQL persistente
Armazenando variáveis globais em todo o aplicativo

Notas do desenvolvedor

Async Storage é o equivalente React Native do armazenamento local da web

Armazenamento seguro

O React Native não vem com nenhuma forma de armazenar dados confidenciais. No entanto, existem soluções pré-existentes para plataformas Android e iOS.

iOS - Serviços de chaveiro

O Keychain Services permite armazenar com segurança pequenos pedaços de informações confidenciais para o usuário. Este é o local ideal para armazenar certificados, tokens, senhas e qualquer outra informação confidencial que não pertença ao armazenamento assíncrono.

Android - Preferências compartilhadas seguras

Shared Preferences são o equivalente Android para um armazenamento de dados de valor-chave persistente. Os dados em Preferências compartilhadas não são criptografados por padrão, mas Encrypted Shared Preferences agrupam a classe Shared Preferences para Android e criptografam automaticamente chaves e valores.

Android - armazenamento de chaves

O sistema Android Keystore permite armazenar chaves criptográficas em um contêiner para dificultar a extração do dispositivo.

Para usar os serviços iOS Keychain ou Android Secure Shared Preferences, você mesmo pode escrever uma ponte ou usar uma biblioteca que os agrupa para você e fornece uma API unificada por sua conta e risco. Algumas bibliotecas a serem consideradas:

INFORMAÇÕES

Esteja atento ao armazenamento ou exposição involuntária de informações confidenciais. Isso pode acontecer acidentalmente, por exemplo, salvando dados de formulário confidenciais em estado redux e persistindo toda a árvore de estado no armazenamento assíncrono. Ou enviar tokens de usuários e informações pessoais para um serviço de monitoramento de aplicativos como Sentry ou Crashlytics.

Os aplicativos móveis têm uma vulnerabilidade única que não existe na web: links diretos. Deep linking é uma forma de enviar dados diretamente para um aplicativo nativo de uma fonte externa. Um link direto se parece com app:// onde app é o esquema do seu aplicativo e qualquer coisa após // pode ser usada internamente para lidar com a solicitação.

Por exemplo, se você estivesse criando um aplicativo de comércio eletrônico, poderia usar app://products/1 para criar um link direto para seu aplicativo e abrir a página de detalhes do produto com ID 1. Você pode pensar nesses tipos de URLs em na web, mas com uma distinção crucial:

Links diretos não são seguros e você nunca deve enviar informações confidenciais neles.

A razão pela qual os links diretos não são seguros é porque não existe um método centralizado de registro de esquemas de URL. Como desenvolvedor de aplicativos, você pode usar praticamente qualquer esquema de URL de sua escolha, configurando-o no Xcode para iOS ou adicionando uma intenção no Android.

Não há nada que impeça um aplicativo malicioso de sequestrar seu link direto, registrando-se também no mesmo esquema e obtendo acesso aos dados que seu link contém. Enviar algo como app://products/1 não é prejudicial, mas enviar tokens é uma preocupação de segurança.

Quando o sistema operacional tiver dois ou mais aplicativos para escolher ao abrir um link, o Android mostrará ao usuário uma caixa de diálogo de desambiguação e solicitará que ele escolha qual aplicativo usar para abrir o link. No entanto, no iOS, o sistema operacional fará a escolha por você, então o usuário ficará felizmente inconsciente. A Apple tomou medidas para resolver esse problema em versões posteriores do iOS (iOS 11), onde instituiu o princípio de ordem de chegada, embora essa vulnerabilidade ainda possa ser explorada de diferentes maneiras, sobre as quais você pode ler mais aqui. O uso de links universais permitirá vincular o conteúdo do seu aplicativo com segurança no iOS.

OAuth2 e redirecionamentos

O protocolo de autenticação OAuth2 é incrivelmente popular hoje em dia, considerado o protocolo mais completo e seguro que existe. O protocolo OpenID Connect também se baseia nisso. No OAuth2, o usuário é solicitado a se autenticar por meio de terceiros. Após a conclusão bem-sucedida, esse terceiro redireciona de volta para o aplicativo solicitante com um código de verificação que pode ser trocado por um JWT – um JSON Web Token. JWT é um padrão aberto para transmissão segura de informações entre partes na web.

Na web, essa etapa de redirecionamento é segura, porque os URLs na web são garantidos como exclusivos. Isso não é verdade para aplicativos porque, como mencionado anteriormente, não existe um método centralizado de registro de esquemas de URL! Para resolver esta questão de segurança, uma verificação adicional deve ser adicionada na forma de PKCE.

PKCE, pronunciado “Pixy”, significa Proof of Key Code Exchange e é uma extensão da especificação OAuth 2. Isso envolve adicionar uma camada adicional de segurança que verifica se as solicitações de autenticação e troca de tokens vêm do mesmo cliente. PKCE usa o algoritmo de hash criptográfico SHA 256. SHA 256 cria uma “assinatura” exclusiva para um texto ou arquivo de qualquer tamanho, mas é:

  • Sempre o mesmo comprimento, independentemente do arquivo de entrada
  • Garantido para produzir sempre o mesmo resultado para a mesma entrada
  • Uma maneira (ou seja, você não pode fazer engenharia reversa para revelar a entrada original)

Agora você tem dois valores:

  • code_verifier - uma grande string aleatória gerada pelo cliente
  • code_challenge - o SHA 256 do code_verifier

Durante a solicitação inicial /authorize, o cliente também envia o code_challenge para o code_verifier que mantém na memória. Após a solicitação de autorização retornar corretamente, o cliente também envia o code_verifier que foi usado para gerar o code_challenge. O IDP calculará então o code_challenge, verificará se ele corresponde ao que foi definido na primeira solicitação /authorize e enviará o token de acesso apenas se os valores corresponderem.

Isso garante que apenas o aplicativo que acionou o fluxo de autorização inicial poderá trocar com êxito o código de verificação por um JWT. Portanto, mesmo que um aplicativo malicioso obtenha acesso ao código de verificação, ele será inútil por si só. Para ver isso em ação, confira este exemplo.

Uma biblioteca a ser considerada para OAuth nativo é react-native-app-auth. React-native-app-auth é um SDK para comunicação com provedores OAuth2. Ele agrupa as bibliotecas nativas AppAuth-iOS e AppAuth-Android e pode oferecer suporte a PKCE.

INFORMAÇÃO

React-native-app-auth pode oferecer suporte a PKCE somente se seu provedor de identidade oferecer suporte.

image

Segurança de rede

Suas APIs devem sempre usar criptografia SSL. A criptografia SSL protege contra a leitura dos dados solicitados em texto simples entre o momento em que saem do servidor e antes de chegarem ao cliente. Você saberá que o endpoint é seguro porque começa com https:// em vez de http://.

SSL Pinning

O uso de endpoints https ainda pode deixar seus dados vulneráveis à interceptação. Com https, o cliente só confiará no servidor se puder fornecer um certificado válido assinado por uma autoridade de certificação confiável pré-instalada no cliente. Um invasor pode tirar vantagem disso instalando um certificado CA raiz malicioso no dispositivo do usuário, para que o cliente confie em todos os certificados assinados pelo invasor. Portanto, confiar apenas em certificados ainda pode deixá-lo vulnerável a um ataque man-in-the-middle.

A SSL Pinning é uma técnica que pode ser usada no lado do cliente para evitar esse ataque. Ele funciona incorporando (ou fixando) uma lista de certificados confiáveis ao cliente durante o desenvolvimento, de modo que apenas as solicitações assinadas com um dos certificados confiáveis serão aceitas e quaisquer certificados autoassinados não serão aceitos.

INFORMAÇÃO

Ao usar o SSL Pinnig, você deve estar atento à expiração do certificado. Os certificados expiram a cada 1-2 anos e, quando isso acontecer, precisarão ser atualizados no aplicativo e também no servidor. Assim que o certificado no servidor for atualizado, todos os aplicativos com o certificado antigo incorporado deixarão de funcionar.

Resumo

Não existe uma maneira infalível de lidar com a segurança, mas com esforço consciente e diligência, é possível reduzir significativamente a probabilidade de uma violação de segurança em seu aplicativo. Invista em segurança proporcional à sensibilidade dos dados armazenados em sua aplicação, ao número de usuários e aos danos que um hacker pode causar ao obter acesso à sua conta. E lembre-se: é significativamente mais difícil acessar informações que nunca foram solicitadas.

',52),c=[d];function m(l,u,p,v,h,f){return o(),a("div",null,c)}const q=e(n,[["render",m]]);export{b as __pageData,q as default}; diff --git a/vitepress/docs/.vitepress/dist/assets/docs_security.md.DrXA_4lZ.lean.js b/vitepress/docs/.vitepress/dist/assets/docs_security.md.DrXA_4lZ.lean.js new file mode 100644 index 0000000..225e7f0 --- /dev/null +++ b/vitepress/docs/.vitepress/dist/assets/docs_security.md.DrXA_4lZ.lean.js @@ -0,0 +1 @@ +import{_ as e,c as a,o,a4 as r}from"./chunks/framework.nQaBHiNx.js";const i="data:image/svg+xml;base64,PHN2ZyBpZD0iY2hhcnQiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIgdmlld0JveD0iMCAwIDI4MyAxOTUiPjxkZWZzPjxzdHlsZT4uY2xzLTF7ZmlsbDojOTdhYWQ4O30uY2xzLTIsLmNscy0ze2ZpbGw6bm9uZTtzdHJva2UtbWl0ZXJsaW1pdDoxMDt9LmNscy0ye3N0cm9rZTojZDIzYzZmO30uY2xzLTN7c3Ryb2tlOiM1OTcxYjU7c3Ryb2tlLXdpZHRoOjJweDt9LmNscy00LC5jbHMtNXtmb250LXNpemU6MTJweDtmb250LWZhbWlseTotYXBwbGUtc3lzdGVtLCBCbGlua01hY1N5c3RlbUZvbnQsICdTZWdvZSBVSScsIEhlbHZldGljYSwgQXJpYWwsIHNhbnMtc2VyaWYsICdBcHBsZSBDb2xvciBFbW9qaScsICdTZWdvZSBVSSBFbW9qaScsICdTZWdvZSBVSSBTeW1ib2wnO2ZvbnQtd2VpZ2h0OjYwMDt9LmNscy00e2ZpbGw6I2QyM2M2Zjt9LmNscy01e2ZpbGw6IzM3NGQ5Yzt9PC9zdHlsZT48L2RlZnM+PHBhdGggY2xhc3M9ImNscy0xIiBkPSJNNDksMTU5QzE1NSwxNDksMjUwLDI2LDI1MCwyNlYxNTkiLz48cGF0aCBjbGFzcz0iY2xzLTIiIGQ9Ik01MC4yLDI4LjY4QzQ5LjUsMTY5LjUsMTY2LjUsMTU0LjUsMjUwLjUsMTU3LjUiLz48cG9seWxpbmUgY2xhc3M9ImNscy0zIiBwb2ludHM9IjI1MCAxNjAgNTAgMTYwIDUwIDI2Ii8+PHRleHQgY2xhc3M9ImNscy00IiB0cmFuc2Zvcm09InRyYW5zbGF0ZSg0MC42NiAxNTguNzEpIHJvdGF0ZSgtOTApIj5saWtlbGlob29kIG9mIGEgYnJlYWNoPC90ZXh0Pjx0ZXh0IGNsYXNzPSJjbHMtNSIgdHJhbnNmb3JtPSJ0cmFuc2xhdGUoNTIuNDMgMTc1LjIzKSI+ZWZmb3J0IGludmVzdGVkIGluIHNlY3VyaXR5PC90ZXh0Pjwvc3ZnPg==",s="/assets/d_security_deep-linking.C1poVAy4.svg",t="/assets/298200622-2dd8fd0b-c69c-41c3-a787-87e4f7ffe95c.GYWIUQtH.png",b=JSON.parse('{"title":"Segurança","description":"","frontmatter":{},"headers":[],"relativePath":"docs/security.md","filePath":"docs/security.md"}'),n={name:"docs/security.md"},d=r("",52),c=[d];function m(l,u,p,v,h,f){return o(),a("div",null,c)}const q=e(n,[["render",m]]);export{b as __pageData,q as default}; diff --git a/vitepress/docs/.vitepress/dist/assets/docs_signed-apk-android.md.B206yoTk.js b/vitepress/docs/.vitepress/dist/assets/docs_signed-apk-android.md.B206yoTk.js new file mode 100644 index 0000000..45aabb9 --- /dev/null +++ b/vitepress/docs/.vitepress/dist/assets/docs_signed-apk-android.md.B206yoTk.js @@ -0,0 +1,39 @@ +import{_ as a,c as e,o as s,a4 as o}from"./chunks/framework.nQaBHiNx.js";const m=JSON.parse('{"title":"Publicação na Google Play Store","description":"","frontmatter":{},"headers":[],"relativePath":"docs/signed-apk-android.md","filePath":"docs/signed-apk-android.md"}'),i={name:"docs/signed-apk-android.md"},n=o(`

Publicação na Google Play Store

O Android exige que todos os aplicativos sejam assinados digitalmente com um certificado antes de serem instalados. Para distribuir seu aplicativo Android pela Google Play Store, ele precisa ser assinado com uma chave de versão que deverá ser usada em todas as atualizações futuras. Desde 2017, o Google Play pode gerenciar versões de assinatura automaticamente graças à funcionalidade App Signing by Google Play . No entanto, antes de o binário do seu aplicativo ser carregado no Google Play, ele precisa ser assinado com uma chave de upload. A página Assinando seus aplicativos na documentação para desenvolvedores Android descreve o tópico em detalhes. Este guia aborda resumidamente o processo, bem como lista as etapas necessárias para empacotar o pacote JavaScript.

INFORMAÇÃO

Se você estiver usando a Expo, leia o guia da Expo para Implantação nas App Stores para criar e enviar seu aplicativo para a Google Play Store. Este guia funciona com qualquer aplicativo React Native para automatizar o processo de implantação.

Gerando uma chave de upload

Você pode gerar uma chave de assinatura privada usando keytool.

Windows

No Windows keytool deve ser executado em C:\\Program Files\\Java\\jdkx.x.x_x\\bin, como administrador.

bash
keytool -genkeypair -v -storetype PKCS12 -keystore my-upload-key.keystore -alias my-key-alias -keyalg RSA -keysize 2048 -validity 10000

Este comando solicita senhas para o keystore e a chave para os campos "Distinguished Name" da sua chave. Em seguida, ele gera o keystore como um arquivo chamado my-upload-key.keystore.

O keystore contém uma única chave, válida por 10.000 dias. O alias é um nome que você usará posteriormente ao assinar seu aplicativo, portanto, lembre-se de anotar o alias.

Mac OS

No macOS, se você não tiver certeza de onde está a pasta bin do JDK, execute o seguinte comando para localizá-la:

bash
/usr/libexec/java_home

Ele gerará o diretório do JDK, que será parecido com isto:

bash
/Library/Java/JavaVirtualMachines/jdkX.X.X_XXX.jdk/Contents/Home

Navegue até esse diretório usando o comando cd /your/jdk/path e use o comando keytool com permissão sudo conforme mostrado abaixo.

bash
sudo keytool -genkey -v -keystore my-upload-key.keystore -alias my-key-alias -keyalg RSA -keysize 2048 -validity 10000

ATENÇÃO

Lembre-se de manter o arquivo keystore privado. Caso você tenha perdido a chave de upload ou ela tenha sido comprometida, siga estas instruções.

Configurando variáveis ​​Gradle

  1. Coloque o arquivo my-upload-key.keystore no diretório android/app na pasta do seu projeto.
  2. Edite o arquivo ~/.gradle/gradle.properties ou android/gradle.properties e adicione o seguinte (substitua ***** pela senha correta do keystore, alias e senha da chave),
MYAPP_UPLOAD_STORE_FILE=my-upload-key.keystore
+MYAPP_UPLOAD_KEY_ALIAS=my-key-alias
+MYAPP_UPLOAD_STORE_PASSWORD=*****
+MYAPP_UPLOAD_KEY_PASSWORD=*****

Essas serão variáveis ​​globais do Gradle, que poderemos usar posteriormente em nossa configuração do Gradle para assinar nosso aplicativo.

Nota sobre o uso do git

Salvar as variáveis ​​Gradle acima em ~/.gradle/gradle.properties em vez de android/gradle.properties impede que elas sejam registradas no git. Talvez seja necessário criar o arquivo ~/.gradle/gradle.properties no diretório inicial do usuário antes de adicionar as variáveis.

Nota sobre segurança

Se você não deseja armazenar suas senhas em texto simples e estiver executando o macOS, você também pode [armazenar suas credenciais no aplicativo Keychain Access](https://pilloxa.gitlab.io/posts/safer-passwords-in- grau/). Então você pode pular as duas últimas linhas em ~/.gradle/gradle.properties.

Adicionando configuração de assinatura à configuração Gradle do seu aplicativo

A última etapa de configuração que precisa ser feita é configurar as compilações de versão para serem assinadas usando a chave de upload. Edite o arquivo android/app/build.gradle na pasta do seu projeto e adicione a configuração de assinatura,

...
+android {
+    ...
+    defaultConfig { ... }
+    signingConfigs {
+        release {
+            if (project.hasProperty('MYAPP_UPLOAD_STORE_FILE')) {
+                storeFile file(MYAPP_UPLOAD_STORE_FILE)
+                storePassword MYAPP_UPLOAD_STORE_PASSWORD
+                keyAlias MYAPP_UPLOAD_KEY_ALIAS
+                keyPassword MYAPP_UPLOAD_KEY_PASSWORD
+            }
+        }
+    }
+    buildTypes {
+        release {
+            ...
+            signingConfig signingConfigs.release
+        }
+    }
+}
+...

Gerando uma release AAB

Execute o seguinte comando em um terminal:

bash
npx react-native build-android --mode=release

Este comando usa o bundleRelease do Gradle que agrupa todo o JavaScript necessário para executar seu aplicativo no AAB (Android App Bundle). Se você precisar alterar a forma como o pacote JavaScript e/ou os recursos drawable são agrupados (por exemplo, se você alterou os nomes de arquivos/pastas padrão ou a estrutura geral do projeto), dê uma olhada em android/app/build.gradle para ver como você pode atualizá-lo para refletir essas alterações.

INFORMAÇÃO

Certifique-se de que gradle.properties não inclua org.gradle.configureondemand=true, pois isso fará com que a compilação de lançamento ignore o agrupamento de JS e ativos no binário do aplicativo.

O AAB gerado pode ser encontrado em android/app/build/outputs/bundle/release/app-release.aab e está pronto para ser carregado no Google Play.

Para que o Google Play aceite o formato AAB, a assinatura de aplicativos do Google Play precisa ser configurada para seu aplicativo no Google Play Console. Se você estiver atualizando um aplicativo existente que não usa a assinatura de aplicativos do Google Play, consulte a seção de migração para aprender como realizar essa alteração na configuração.

Testando a versão de lançamento do seu aplicativo

Antes de enviar a versão de lançamento para a Play Store, teste-a completamente. Primeiro desinstale qualquer versão anterior do aplicativo que você já instalou. Instale-o no dispositivo usando o seguinte comando na raiz do projeto:

bash
npm run android -- --mode="release"
bash
yarn android --mode release

Observe que --mode release só está disponível se você configurou a assinatura conforme descrito acima.

Você pode encerrar qualquer instância do bundler em execução, já que toda a estrutura e o código JavaScript estão agrupados nos ativos do APK.

Publicação em outras lojas

Por padrão, o APK gerado possui o código nativo para as arquiteturas de CPU x86, x86_64, ARMv7a e ARM64-v8a. Isso facilita o compartilhamento de APKs executados em quase todos os dispositivos Android. No entanto, isso tem a desvantagem de que haverá algum código nativo não utilizado em qualquer dispositivo, levando a APKs desnecessariamente maiores.

Você pode criar um APK para cada CPU adicionando a seguinte linha em seu arquivo android/app/build.gradle:

android {
+
+    splits {
+        abi {
+            reset()
+            enable true
+            universalApk false
+            include "armeabi-v7a", "arm64-v8a", "x86", "x86_64"
+        }
+    }
+
+}

Faça upload desses arquivos para mercados que oferecem suporte à segmentação por dispositivo, como Amazon AppStore ou F-Droid, e os usuários obterão automaticamente o APK apropriado. Se você quiser fazer upload para outros mercados, como APKFiles, que não suportam vários APKs para um único aplicativo, altere a linha universalApk false para true para crie o APK universal padrão com binários para ambas as CPUs.

Observe que você também terá que configurar códigos de versão distintos, conforme sugerido nesta página do site oficial da Documentação do Android.

Habilitando o Proguard para reduzir o tamanho do APK (opcional)

Proguard é uma ferramenta que pode reduzir ligeiramente o tamanho do APK. Isso é feito removendo partes do bytecode React Native Java (e suas dependências) que seu aplicativo não está usando.

Importante

Certifique-se de testar completamente seu aplicativo se você ativou o Proguard. O Proguard geralmente requer configuração específica para cada biblioteca nativa que você está usando. Consulte app/proguard-rules.pro.

Para ativar o Proguard, edite android/app/build.gradle:

/**
+ * Execute o Proguard para reduzir o bytecode Java em compilações de lançamento.
+ */
+def enableProguardInReleaseBuilds = true

Migrando aplicativos antigos do Android React Native para usar o App Signing do Google Play

Se você estiver migrando da versão anterior do React Native, é provável que seu aplicativo não use o recurso App Signing by Google Play. Recomendamos que você habilite isso para aproveitar recursos como a divisão automática de aplicativos. Para migrar da forma antiga de assinatura, você precisa começar gerando nova chave de upload e, em seguida, substituindo a configuração de assinatura de lançamento em android/app/build.gradle para usar o chave de upload em vez da de lançamento (consulte a seção sobre adicionando configuração de assinatura ao gradle). Feito isso, siga as instruções do site de ajuda do Google Play para enviar sua chave de versão original ao Google Play.

Permissões padrão

Por padrão, a permissão INTERNET é adicionada ao seu aplicativo Android, pois praticamente todos os aplicativos a utilizam. A permissão SYSTEM_ALERT_WINDOW é adicionada ao seu APK Android no modo de depuração, mas será removida na produção.

`,54),r=[n];function p(t,d,l,c,u,h){return s(),e("div",null,r)}const v=a(i,[["render",p]]);export{m as __pageData,v as default}; diff --git a/vitepress/docs/.vitepress/dist/assets/docs_signed-apk-android.md.B206yoTk.lean.js b/vitepress/docs/.vitepress/dist/assets/docs_signed-apk-android.md.B206yoTk.lean.js new file mode 100644 index 0000000..15d9978 --- /dev/null +++ b/vitepress/docs/.vitepress/dist/assets/docs_signed-apk-android.md.B206yoTk.lean.js @@ -0,0 +1 @@ +import{_ as a,c as e,o as s,a4 as o}from"./chunks/framework.nQaBHiNx.js";const m=JSON.parse('{"title":"Publicação na Google Play Store","description":"","frontmatter":{},"headers":[],"relativePath":"docs/signed-apk-android.md","filePath":"docs/signed-apk-android.md"}'),i={name:"docs/signed-apk-android.md"},n=o("",54),r=[n];function p(t,d,l,c,u,h){return s(),e("div",null,r)}const v=a(i,[["render",p]]);export{m as __pageData,v as default}; diff --git a/vitepress/docs/.vitepress/dist/assets/docs_sourcemaps.md.05e838l-.js b/vitepress/docs/.vitepress/dist/assets/docs_sourcemaps.md.05e838l-.js new file mode 100644 index 0000000..dee5aca --- /dev/null +++ b/vitepress/docs/.vitepress/dist/assets/docs_sourcemaps.md.05e838l-.js @@ -0,0 +1,15 @@ +import{_ as a,c as s,o as i,a4 as e}from"./chunks/framework.nQaBHiNx.js";const u=JSON.parse('{"title":"Mapas de origem","description":"","frontmatter":{},"headers":[],"relativePath":"docs/sourcemaps.md","filePath":"docs/sourcemaps.md"}'),n={name:"docs/sourcemaps.md"},t=e(`

Mapas de origem

Os mapas de origem permitem mapear um arquivo transformado de volta ao arquivo de origem original. O objetivo principal dos mapas de origem é ajudar na depuração e na investigação de problemas de compilações de lançamento.

Sem os mapas de origem, ao encontrar um erro na compilação da versão, você verá um stacktrace como:

bash
TypeError: Cannot read property 'data' of undefined
+  at anonymous(app:///index.android.bundle:1:4277021)
+  at call(native)
+  at p(app:///index.android.bundle:1:227785)

Com os mapas de origem gerados, um stacktrace incluirá o caminho, o nome do arquivo e o número da linha do arquivo de origem original:

bash
TypeError: Cannot read property 'data' of undefined
+  at anonymous(src/modules/notifications/Permission.js:15:requestNotificationPermission)
+  at call(native)
+  at p(node_modules/regenerator-runtime/runtime.js:64:Generator)

Isso permite que você faça a triagem de problemas de lançamento usando um stacktrace decifrável.

Siga as instruções abaixo para começar a usar os mapas de origem.

Habilitar mapas de origem no Android

Hermes

INFORMAÇÕES

Os mapas de origem são criados no modo Release por padrão, a menos que hermesFlagsRelease não esteja definido. Nesse caso, os mapas de origem terão que ser habilitados.

Para fazer isso, certifique-se de que o seguinte esteja definido no arquivo Android/app/build.gradle do seu aplicativo.

js
project.ext.react = [
+    enableHermes: true,
+    hermesFlagsRelease: ["-O", "-output-source-map"], // mais qualquer sinalizador necessário para definir isso fora do padrão
+]

Se feito corretamente, você deverá ver o local de saída do mapa de origem durante a saída da compilação Metro.

Writing bundle output to:, android/app/build/generated/assets/react/release/index.android.bundle
+Writing sourcemap output to:, android/app/build/intermediates/sourcemaps/react/release/index.android.bundle.packager.map

As compilações de desenvolvimento não produzem um pacote configurável e, portanto, já possuem símbolos, mas se a compilação de desenvolvimento estiver empacotada, você pode usar hermesFlagsDebug como acima para habilitar mapas de origem.

Habilitar mapas de origem no iOS

Os mapas de origem estão desabilitados por padrão. Para habilitá-los é necessário definir uma variável de ambiente SOURCEMAP_FILE.

Para fazer isso, dentro do Xcode vá para a fase de construção - "Bundle React Native code and images".

Na parte superior do arquivo, próximo às outras exportações, adicione uma entrada para SOURCEMAP_FILE ao local e nome preferidos. Como abaixo:

export SOURCEMAP_FILE="$(pwd)/../main.jsbundle.map";
+
+export NODE_BINARY=node
+../node_modules/react-native/scripts/react-native-xcode.sh

Se feito corretamente, você deverá ver o local de saída do mapa de origem durante a saída da compilação Metro.

Writing bundle output to:, Build/Intermediates.noindex/ArchiveIntermediates/application/BuildProductsPath/Release-iphoneos/main.jsbundle
+Writing sourcemap output to:, Build/Intermediates.noindex/ArchiveIntermediates/application/BuildProductsPath/Release-iphoneos/main.jsbundle.map

Simbolização Manual

INFORMAÇÕES

Você pode ler sobre a simbolização manual de um rastreamento de pilha na página de simbolização.

`,25),o=[t];function p(l,r,d,h,k,c){return i(),s("div",null,o)}const g=a(n,[["render",p]]);export{u as __pageData,g as default}; diff --git a/vitepress/docs/.vitepress/dist/assets/docs_sourcemaps.md.05e838l-.lean.js b/vitepress/docs/.vitepress/dist/assets/docs_sourcemaps.md.05e838l-.lean.js new file mode 100644 index 0000000..e6481aa --- /dev/null +++ b/vitepress/docs/.vitepress/dist/assets/docs_sourcemaps.md.05e838l-.lean.js @@ -0,0 +1 @@ +import{_ as a,c as s,o as i,a4 as e}from"./chunks/framework.nQaBHiNx.js";const u=JSON.parse('{"title":"Mapas de origem","description":"","frontmatter":{},"headers":[],"relativePath":"docs/sourcemaps.md","filePath":"docs/sourcemaps.md"}'),n={name:"docs/sourcemaps.md"},t=e("",25),o=[t];function p(l,r,d,h,k,c){return i(),s("div",null,o)}const g=a(n,[["render",p]]);export{u as __pageData,g as default}; diff --git a/vitepress/docs/.vitepress/dist/assets/docs_speeding-ci-builds.md.ZHm8lsYC.js b/vitepress/docs/.vitepress/dist/assets/docs_speeding-ci-builds.md.ZHm8lsYC.js new file mode 100644 index 0000000..29c9dd1 --- /dev/null +++ b/vitepress/docs/.vitepress/dist/assets/docs_speeding-ci-builds.md.ZHm8lsYC.js @@ -0,0 +1,11 @@ +import{_ as a,c as e,o as i,a4 as s}from"./chunks/framework.nQaBHiNx.js";const k=JSON.parse('{"title":"Acelerando as compilações de CI","description":"","frontmatter":{},"headers":[],"relativePath":"docs/speeding-ci-builds.md","filePath":"docs/speeding-ci-builds.md"}'),o={name:"docs/speeding-ci-builds.md"},n=s(`

Acelerando as compilações de CI

Você ou sua empresa podem ter configurado um ambiente de Integração Contínua (CI) para testar seu aplicativo React Native.

Um serviço de CI rápido é importante por 2 motivos:

  • Quanto mais tempo as máquinas de CI ficam em execução, mais elas custam.
  • Quanto mais tempo os trabalhos de CI levarem para serem executados, maior será o ciclo de desenvolvimento.

Portanto, é importante tentar minimizar o tempo que o ambiente de CI gasta construindo o React Native.

Desative o Flipper para iOS

Flipper é uma ferramenta de depuração fornecida por padrão com React Native, para ajudar os desenvolvedores a depurar e criar o perfil de seus aplicativos React Native. No entanto, o Flipper não é necessário no CI: é muito improvável que você ou um de seus colegas precise depurar o aplicativo criado no ambiente de CI.

Para aplicativos iOS, o Flipper é construído toda vez que a estrutura React Native é construída e pode levar algum tempo para ser construída, e esse é o tempo que você pode economizar.

A partir do React Native 0.71, introduzimos um novo sinalizador no Podfile do modelo: o sinalizador NO_FLIPPER.

Por padrão, o sinalizador NO_FLIPPER não está definido, portanto o Flipper será incluído por padrão em seu aplicativo.

Você pode especificar NO_FLIPPER=1 ao instalar seus pods iOS, para instruir o React Native a não instalar o Flipper. Normalmente, o comando ficaria assim:

# da pasta raiz do projeto react native
+NO_FLIPPER=1 bundle exec pod install --project-directory=ios

Adicione este comando em seu ambiente de CI para ignorar a instalação das dependências do Flipper e, assim, economizar tempo e dinheiro.

Lidar com dependências transitivas

Seu aplicativo pode estar usando algumas bibliotecas que dependem dos pods do Flipper. Se for esse o seu caso, desabilitar o flipper com o sinalizador NO_FLIPPER pode não ser suficiente: seu aplicativo pode falhar na construção neste caso.

A maneira correta de lidar com esse caso é adicionar uma configuração personalizada para react native, instruindo o aplicativo a instalar corretamente a dependência transitiva. Para conseguir isso:

  • Se ainda não o fez, crie um novo arquivo chamado react-native.config.js.
  • Exclua explicitamente a dependência transitiva das dependências quando o sinalizador estiver ativado.

Por exemplo, a biblioteca react-native-flipper é uma biblioteca adicional que depende do Flipper. Se o seu aplicativo usa isso, você precisa excluí-lo das dependências. Seu react-native.config.js ficaria assim:

js
// react-native.config.js
+
+module.exports = {
+  // outros campos
+  dependencies: {
+    ...(process.env.NO_FLIPPER
+      ? {'react-native-flipper': {platforms: {ios: null}}}
+      : {}),
+  },
+};
`,19),t=[n];function p(r,l,d,c,h,u){return i(),e("div",null,t)}const v=a(o,[["render",p]]);export{k as __pageData,v as default}; diff --git a/vitepress/docs/.vitepress/dist/assets/docs_speeding-ci-builds.md.ZHm8lsYC.lean.js b/vitepress/docs/.vitepress/dist/assets/docs_speeding-ci-builds.md.ZHm8lsYC.lean.js new file mode 100644 index 0000000..29c9dd1 --- /dev/null +++ b/vitepress/docs/.vitepress/dist/assets/docs_speeding-ci-builds.md.ZHm8lsYC.lean.js @@ -0,0 +1,11 @@ +import{_ as a,c as e,o as i,a4 as s}from"./chunks/framework.nQaBHiNx.js";const k=JSON.parse('{"title":"Acelerando as compilações de CI","description":"","frontmatter":{},"headers":[],"relativePath":"docs/speeding-ci-builds.md","filePath":"docs/speeding-ci-builds.md"}'),o={name:"docs/speeding-ci-builds.md"},n=s(`

Acelerando as compilações de CI

Você ou sua empresa podem ter configurado um ambiente de Integração Contínua (CI) para testar seu aplicativo React Native.

Um serviço de CI rápido é importante por 2 motivos:

  • Quanto mais tempo as máquinas de CI ficam em execução, mais elas custam.
  • Quanto mais tempo os trabalhos de CI levarem para serem executados, maior será o ciclo de desenvolvimento.

Portanto, é importante tentar minimizar o tempo que o ambiente de CI gasta construindo o React Native.

Desative o Flipper para iOS

Flipper é uma ferramenta de depuração fornecida por padrão com React Native, para ajudar os desenvolvedores a depurar e criar o perfil de seus aplicativos React Native. No entanto, o Flipper não é necessário no CI: é muito improvável que você ou um de seus colegas precise depurar o aplicativo criado no ambiente de CI.

Para aplicativos iOS, o Flipper é construído toda vez que a estrutura React Native é construída e pode levar algum tempo para ser construída, e esse é o tempo que você pode economizar.

A partir do React Native 0.71, introduzimos um novo sinalizador no Podfile do modelo: o sinalizador NO_FLIPPER.

Por padrão, o sinalizador NO_FLIPPER não está definido, portanto o Flipper será incluído por padrão em seu aplicativo.

Você pode especificar NO_FLIPPER=1 ao instalar seus pods iOS, para instruir o React Native a não instalar o Flipper. Normalmente, o comando ficaria assim:

# da pasta raiz do projeto react native
+NO_FLIPPER=1 bundle exec pod install --project-directory=ios

Adicione este comando em seu ambiente de CI para ignorar a instalação das dependências do Flipper e, assim, economizar tempo e dinheiro.

Lidar com dependências transitivas

Seu aplicativo pode estar usando algumas bibliotecas que dependem dos pods do Flipper. Se for esse o seu caso, desabilitar o flipper com o sinalizador NO_FLIPPER pode não ser suficiente: seu aplicativo pode falhar na construção neste caso.

A maneira correta de lidar com esse caso é adicionar uma configuração personalizada para react native, instruindo o aplicativo a instalar corretamente a dependência transitiva. Para conseguir isso:

  • Se ainda não o fez, crie um novo arquivo chamado react-native.config.js.
  • Exclua explicitamente a dependência transitiva das dependências quando o sinalizador estiver ativado.

Por exemplo, a biblioteca react-native-flipper é uma biblioteca adicional que depende do Flipper. Se o seu aplicativo usa isso, você precisa excluí-lo das dependências. Seu react-native.config.js ficaria assim:

js
// react-native.config.js
+
+module.exports = {
+  // outros campos
+  dependencies: {
+    ...(process.env.NO_FLIPPER
+      ? {'react-native-flipper': {platforms: {ios: null}}}
+      : {}),
+  },
+};
`,19),t=[n];function p(r,l,d,c,h,u){return i(),e("div",null,t)}const v=a(o,[["render",p]]);export{k as __pageData,v as default}; diff --git a/vitepress/docs/.vitepress/dist/assets/docs_style.md.q_o4n3Pn.js b/vitepress/docs/.vitepress/dist/assets/docs_style.md.q_o4n3Pn.js new file mode 100644 index 0000000..79bece8 --- /dev/null +++ b/vitepress/docs/.vitepress/dist/assets/docs_style.md.q_o4n3Pn.js @@ -0,0 +1,29 @@ +import{_ as s,c as i,o as a,a4 as e}from"./chunks/framework.nQaBHiNx.js";const g=JSON.parse('{"title":"Estilo","description":"","frontmatter":{},"headers":[],"relativePath":"docs/style.md","filePath":"docs/style.md"}'),t={name:"docs/style.md"},n=e(`

Estilo

Com React Native, você estiliza seu aplicativo usando JavaScript. Todos os componentes principais aceitam um estilo chamado prop. Os nomes e valores dos estilos geralmente correspondem ao modo como o CSS funciona na web, exceto que os nomes são escritos em camel case, por exemplo. backgroundColor em vez de background-color.

A propriedade style pode ser um objeto JavaScript simples e antigo. Isso é o que normalmente usamos como código de exemplo. Você também pode passar uma matriz de estilos - o último estilo da matriz tem precedência, portanto você pode usar isso para herdar estilos.

À medida que um componente cresce em complexidade, geralmente é mais fácil usar StyleSheet.create para definir vários estilos em um só lugar. Aqui está um exemplo:

jsx
import React from 'react';
+import {StyleSheet, Text, View} from 'react-native';
+
+const LotsOfStyles = () => {
+  return (
+    <View style={styles.container}>
+      <Text style={styles.red}>just red</Text>
+      <Text style={styles.bigBlue}>just bigBlue</Text>
+      <Text style={[styles.bigBlue, styles.red]}>bigBlue, then red</Text>
+      <Text style={[styles.red, styles.bigBlue]}>red, then bigBlue</Text>
+    </View>
+  );
+};
+
+const styles = StyleSheet.create({
+  container: {
+    marginTop: 50,
+  },
+  bigBlue: {
+    color: 'blue',
+    fontWeight: 'bold',
+    fontSize: 30,
+  },
+  red: {
+    color: 'red',
+  },
+});
+
+export default LotsOfStyles;

image

Um padrão comum é fazer com que seu componente aceite um suporte de style que, por sua vez, é usado para estilizar subcomponentes. Você pode usar isso para fazer com que os estilos "casquem" da mesma forma que fazem no CSS.

Existem muito mais maneiras de personalizar o estilo do texto. Confira a referência do componente Texto para uma lista completa.

Agora você pode deixar seu texto lindo. O próximo passo para se tornar um especialista em estilo é aprender como controlar o tamanho dos componentes.

Problemas conhecidos

  • react-native#29308: Em alguns casos, o React Native não corresponde ao modo como o CSS funciona na web, por exemplo, a área de toque nunca ultrapassa os limites da visualização pai e no Android a margem negativa não é suportada.
`,11),l=[n];function p(h,k,o,r,d,E){return a(),i("div",null,l)}const y=s(t,[["render",p]]);export{g as __pageData,y as default}; diff --git a/vitepress/docs/.vitepress/dist/assets/docs_style.md.q_o4n3Pn.lean.js b/vitepress/docs/.vitepress/dist/assets/docs_style.md.q_o4n3Pn.lean.js new file mode 100644 index 0000000..cc7c1ee --- /dev/null +++ b/vitepress/docs/.vitepress/dist/assets/docs_style.md.q_o4n3Pn.lean.js @@ -0,0 +1 @@ +import{_ as s,c as i,o as a,a4 as e}from"./chunks/framework.nQaBHiNx.js";const g=JSON.parse('{"title":"Estilo","description":"","frontmatter":{},"headers":[],"relativePath":"docs/style.md","filePath":"docs/style.md"}'),t={name:"docs/style.md"},n=e("",11),l=[n];function p(h,k,o,r,d,E){return a(),i("div",null,l)}const y=s(t,[["render",p]]);export{g as __pageData,y as default}; diff --git a/vitepress/docs/.vitepress/dist/assets/docs_symbolication.md.C65zpAiS.js b/vitepress/docs/.vitepress/dist/assets/docs_symbolication.md.C65zpAiS.js new file mode 100644 index 0000000..57fabad --- /dev/null +++ b/vitepress/docs/.vitepress/dist/assets/docs_symbolication.md.C65zpAiS.js @@ -0,0 +1,6 @@ +import{_ as s,c as i,o as a,a4 as e}from"./chunks/framework.nQaBHiNx.js";const m=JSON.parse('{"title":"Simbolizando um rastreamento de pilha","description":"","frontmatter":{},"headers":[],"relativePath":"docs/symbolication.md","filePath":"docs/symbolication.md"}'),t={name:"docs/symbolication.md"},n=e(`

Simbolizando um rastreamento de pilha

Se um aplicativo React Native lançar uma exceção não tratada em uma compilação de lançamento, a saída poderá ficar ofuscada e difícil de ler:

bash
07-15 10:58:25.820 18979 18998 E AndroidRuntime: FATAL EXCEPTION: mqt_native_modules
+07-15 10:58:25.820 18979 18998 E AndroidRuntime: Process: com.awesomeproject, PID: 18979 07-15 10:58:25.820 18979 18998 E AndroidRuntime: com.facebook.react.common.JavascriptException: Failed, js engine: hermes, stack:
+07-15 10:58:25.820 18979 18998 E AndroidRuntime: p@1:132161
+07-15 10:58:25.820 18979 18998 E AndroidRuntime: p@1:132084
+07-15 10:58:25.820 18979 18998 E AndroidRuntime: f@1:131854
+07-15 10:58:25.820 18979 18998 E AndroidRuntime: anonymous@1:131119

As seções como p@1:132161 são nomes de funções reduzidos e deslocamentos de bytecode. Para depurar o problema, você deve traduzi-lo em nome de arquivo, linha e função: AwesomeProject/App.js:54:initializeMap. Isso é conhecido como simbolização. Você pode simbolizar nomes de funções minificados e bytecode como acima, passando metro-symbolicate um mapa de origem gerado e o rastreamento de pilha.

INFORMAÇÃO

O pacote metro-symbolicate é instalado por padrão no projeto de modelo React Native ao configurar seu ambiente de desenvolvimento.

De um arquivo contendo o stacktrace:

bash
npx metro-symbolicate android/app/build/generated/sourcemaps/react/release/index.android.bundle.map < stacktrace.txt

Diretamente do adb logcat:

bash
adb logcat -d | npx metro-symbolicate android/app/build/generated/sourcemaps/react/release/index.android.bundle.map

Isso transformará cada nome de função minificado e deslocamento como p@1:132161 no nome real do arquivo e da função AwesomeProject/App.js:54:initializeMap.

Notas sobre mapas de origem

  • Vários mapas de origem podem ser gerados pelo processo de construção. Certifique-se de usar aquele no local mostrado nos exemplos.
  • Certifique-se de que o mapa de origem usado corresponda ao commit exato do aplicativo com falha. Pequenas alterações no código-fonte podem causar grandes diferenças nos deslocamentos.
  • Se o metro-symbolicate sair imediatamente com sucesso, certifique-se de que a entrada venha de um pipe ou redirecionamento e não de um terminal.
`,12),h=[n];function l(p,o,k,d,r,F){return a(),i("div",null,h)}const g=s(t,[["render",l]]);export{m as __pageData,g as default}; diff --git a/vitepress/docs/.vitepress/dist/assets/docs_symbolication.md.C65zpAiS.lean.js b/vitepress/docs/.vitepress/dist/assets/docs_symbolication.md.C65zpAiS.lean.js new file mode 100644 index 0000000..099d7eb --- /dev/null +++ b/vitepress/docs/.vitepress/dist/assets/docs_symbolication.md.C65zpAiS.lean.js @@ -0,0 +1 @@ +import{_ as s,c as i,o as a,a4 as e}from"./chunks/framework.nQaBHiNx.js";const m=JSON.parse('{"title":"Simbolizando um rastreamento de pilha","description":"","frontmatter":{},"headers":[],"relativePath":"docs/symbolication.md","filePath":"docs/symbolication.md"}'),t={name:"docs/symbolication.md"},n=e("",12),h=[n];function l(p,o,k,d,r,F){return a(),i("div",null,h)}const g=s(t,[["render",l]]);export{m as __pageData,g as default}; diff --git a/vitepress/docs/.vitepress/dist/assets/docs_testing-overview.md.By6FslrL.js b/vitepress/docs/.vitepress/dist/assets/docs_testing-overview.md.By6FslrL.js new file mode 100644 index 0000000..d994607 --- /dev/null +++ b/vitepress/docs/.vitepress/dist/assets/docs_testing-overview.md.By6FslrL.js @@ -0,0 +1,49 @@ +import{_ as e,c as s,o as a,a4 as i}from"./chunks/framework.nQaBHiNx.js";const t="/assets/diagram_testing.D4maG0bg.svg",o="data:image/svg+xml,%3csvg%20xmlns='http://www.w3.org/2000/svg'%20viewBox='0%200%201700%20300'%3e%3cdefs%3e%3cstyle%3e.cls-1{fill:%2397aad8}.cls-2{fill:%23338846}.cls-3{fill:%23fff}%3c/style%3e%3c/defs%3e%3cg%20id='unit_tests'%20data-name='unit%20tests'%3e%3crect%20class='cls-1'%20x='617.1'%20y='95.47'%20width='95.24'%20height='95.24'%20rx='19.76'/%3e%3cg%20id='check'%3e%3ccircle%20class='cls-2'%20cx='624.67'%20cy='187.38'%20r='29.61'/%3e%3cpath%20class='cls-3'%20d='M634.69%20167.08l7%202.62-15.23%2033.58-21.47-10.5%206.08-4.08%2012.27%204.44%2011.35-26.06z'/%3e%3c/g%3e%3crect%20class='cls-1'%20x='736.34'%20y='95.47'%20width='95.24'%20height='95.24'%20rx='19.76'/%3e%3cg%20id='check-2'%20data-name='check'%3e%3ccircle%20class='cls-2'%20cx='747.35'%20cy='187.38'%20r='29.61'/%3e%3cpath%20class='cls-3'%20d='M757.37%20167.08l7%202.62-15.23%2033.58-21.47-10.5%206.08-4.08%2012.27%204.44%2011.35-26.06z'/%3e%3c/g%3e%3crect%20class='cls-1'%20x='375.19'%20y='95.47'%20width='95.24'%20height='95.24'%20rx='19.76'/%3e%3cg%20id='check-3'%20data-name='check'%3e%3ccircle%20class='cls-2'%20cx='382.76'%20cy='187.38'%20r='29.61'/%3e%3cpath%20class='cls-3'%20d='M392.78%20167.08l7%202.62-15.23%2033.58-21.47-10.5%206.08-4.08%2012.27%204.44%2011.35-26.06z'/%3e%3c/g%3e%3crect%20class='cls-1'%20x='494.42'%20y='95.47'%20width='95.24'%20height='95.24'%20rx='19.76'/%3e%3cg%20id='check-4'%20data-name='check'%3e%3ccircle%20class='cls-2'%20cx='505.44'%20cy='187.38'%20r='29.61'/%3e%3cpath%20class='cls-3'%20d='M515.46%20167.08l7%202.62-15.23%2033.58-21.47-10.5%206.08-4.08%2012.27%204.44%2011.35-26.06z'/%3e%3c/g%3e%3crect%20class='cls-1'%20x='133.28'%20y='95.47'%20width='95.24'%20height='95.24'%20rx='19.76'/%3e%3cg%20id='check-5'%20data-name='check'%3e%3ccircle%20class='cls-2'%20cx='140.85'%20cy='187.38'%20r='29.61'/%3e%3cpath%20class='cls-3'%20d='M150.87%20167.08l6.99%202.62-15.23%2033.58-21.46-10.5%206.08-4.08%2012.26%204.44%2011.36-26.06z'/%3e%3c/g%3e%3crect%20class='cls-1'%20x='252.51'%20y='95.47'%20width='95.24'%20height='95.24'%20rx='19.76'/%3e%3cg%20id='check-6'%20data-name='check'%3e%3ccircle%20class='cls-2'%20cx='263.53'%20cy='187.38'%20r='29.61'/%3e%3cpath%20class='cls-3'%20d='M273.54%20167.08l7%202.62-15.23%2033.58-21.47-10.5%206.09-4.08%2012.26%204.44%2011.35-26.06z'/%3e%3c/g%3e%3crect%20class='cls-1'%20x='1094.48'%20y='97'%20width='95.24'%20height='95.24'%20rx='19.76'/%3e%3cg%20id='check-7'%20data-name='check'%3e%3ccircle%20class='cls-2'%20cx='1105.49'%20cy='188.92'%20r='29.61'/%3e%3cpath%20class='cls-3'%20d='M1115.51%20168.62l7%202.62-15.23%2033.58-21.47-10.5%206.08-4.08%2012.27%204.43%2011.35-26.05z'/%3e%3c/g%3e%3crect%20class='cls-1'%20x='1213.71'%20y='95.47'%20width='95.24'%20height='95.24'%20rx='19.76'/%3e%3cg%20id='check-8'%20data-name='check'%3e%3ccircle%20class='cls-2'%20cx='1224.73'%20cy='187.38'%20r='29.61'/%3e%3cpath%20class='cls-3'%20d='M1234.74%20167.08l7%202.62-15.23%2033.58-21.47-10.5%206.09-4.08%2012.26%204.44%2011.35-26.06z'/%3e%3c/g%3e%3crect%20class='cls-1'%20x='1332.94'%20y='97'%20width='95.24'%20height='95.24'%20rx='19.76'/%3e%3cg%20id='check-9'%20data-name='check'%3e%3ccircle%20class='cls-2'%20cx='1343.96'%20cy='188.92'%20r='29.61'/%3e%3cpath%20class='cls-3'%20d='M1353.97%20168.62l7%202.62-15.23%2033.58-21.46-10.5%206.08-4.08%2012.27%204.43%2011.34-26.05z'/%3e%3c/g%3e%3crect%20class='cls-1'%20x='1452.18'%20y='95.47'%20width='95.24'%20height='95.24'%20rx='19.76'/%3e%3cg%20id='check-10'%20data-name='check'%3e%3ccircle%20class='cls-2'%20cx='1463.19'%20cy='187.38'%20r='29.61'/%3e%3cpath%20class='cls-3'%20d='M1473.21%20167.08l7%202.62-15.23%2033.58-21.47-10.5%206.08-4.08%2012.27%204.44%2011.35-26.06z'/%3e%3c/g%3e%3crect%20x='855.08'%20y='95.47'%20width='95.24'%20height='95.24'%20rx='19.76'%20fill='%23ee76ab'/%3e%3cg%20id='check-11'%20data-name='check'%3e%3ccircle%20cx='866.58'%20cy='187.38'%20r='29.61'%20fill='%23a21732'/%3e%3cpath%20class='cls-3'%20d='M874.85%20173.97h9.77l-12.78%2015.56%2010.15%209.4-7.52%204.51-8.64-9.52-10.15%206.77h-7.8l14.57-11.98-10.71-10.83%209.01-1.87%205.5%208.83%208.6-10.87z'/%3e%3c/g%3e%3crect%20class='cls-1'%20x='975.25'%20y='95.47'%20width='95.24'%20height='95.24'%20rx='19.76'/%3e%3cg%20id='check-12'%20data-name='check'%3e%3ccircle%20class='cls-2'%20cx='985.32'%20cy='187.38'%20r='29.61'/%3e%3cpath%20class='cls-3'%20d='M995.34%20167.08l7%202.62-15.23%2033.58-21.47-10.5%206.08-4.08%2012.27%204.44%2011.35-26.06z'/%3e%3c/g%3e%3c/g%3e%3c/svg%3e",n="data:image/svg+xml,%3csvg%20xmlns='http://www.w3.org/2000/svg'%20viewBox='0%200%201700%20300'%3e%3cdefs%3e%3cstyle%3e.cls-1{fill:%2397aad8}.cls-2{fill:%23d5e2f5}.cls-3{fill:%23338846}.cls-4{fill:%23fff}.cls-6{fill:%23f8c8dd}%3c/style%3e%3c/defs%3e%3cg%20id='integration_tests'%20data-name='integration%20tests'%3e%3cg%20id='test'%3e%3crect%20class='cls-1'%20x='634.51'%20y='64.58'%20width='415.75'%20height='165.21'%20rx='23.45'/%3e%3crect%20class='cls-2'%20x='679.13'%20y='99.56'%20width='95.24'%20height='95.24'%20rx='19.76'/%3e%3crect%20class='cls-2'%20x='794.77'%20y='99.56'%20width='95.24'%20height='95.24'%20rx='19.76'/%3e%3crect%20class='cls-2'%20x='910.41'%20y='99.56'%20width='95.24'%20height='95.24'%20rx='19.76'/%3e%3c/g%3e%3cg%20id='check'%3e%3ccircle%20class='cls-3'%20cx='641.9'%20cy='224.42'%20r='29.61'/%3e%3cpath%20class='cls-4'%20d='M651.92%20204.11l7%202.62-15.23%2033.58-21.47-10.5%206.08-4.08%2012.27%204.44%2011.35-26.06z'/%3e%3c/g%3e%3cg%20id='test-2'%20data-name='test'%3e%3crect%20class='cls-1'%20x='127.03'%20y='64.58'%20width='415.75'%20height='165.21'%20rx='23.45'/%3e%3crect%20class='cls-2'%20x='171.65'%20y='99.56'%20width='95.24'%20height='95.24'%20rx='19.76'/%3e%3crect%20class='cls-2'%20x='287.29'%20y='99.56'%20width='95.24'%20height='95.24'%20rx='19.76'/%3e%3crect%20class='cls-2'%20x='402.93'%20y='99.56'%20width='95.24'%20height='95.24'%20rx='19.76'/%3e%3c/g%3e%3cg%20id='check-2'%20data-name='check'%3e%3ccircle%20class='cls-3'%20cx='134.42'%20cy='224.42'%20r='29.61'/%3e%3cpath%20class='cls-4'%20d='M144.44%20204.11l7%202.62-15.23%2033.58-21.47-10.5%206.08-4.08%2012.27%204.44%2011.35-26.06z'/%3e%3c/g%3e%3cg%20id='test-3'%20data-name='test'%3e%3crect%20x='1142.33'%20y='64.58'%20width='415.75'%20height='165.21'%20rx='23.45'%20fill='%23ee76ab'/%3e%3crect%20class='cls-6'%20x='1186.94'%20y='99.56'%20width='95.24'%20height='95.24'%20rx='19.76'/%3e%3crect%20class='cls-6'%20x='1302.58'%20y='99.56'%20width='95.24'%20height='95.24'%20rx='19.76'/%3e%3crect%20class='cls-6'%20x='1418.22'%20y='99.56'%20width='95.24'%20height='95.24'%20rx='19.76'/%3e%3c/g%3e%3cg%20id='check-3'%20data-name='check'%3e%3ccircle%20cx='1149.38'%20cy='224.21'%20r='29.61'%20fill='%23a21732'/%3e%3cpath%20class='cls-4'%20d='M1157.64%20210.8h9.77l-12.77%2015.57%2010.14%209.39-7.51%204.51-8.65-9.51-10.14%206.76h-7.8l14.56-11.98-10.71-10.82%209.02-1.88%205.5%208.83%208.59-10.87z'/%3e%3c/g%3e%3c/g%3e%3c/svg%3e",r="data:image/svg+xml,%3csvg%20xmlns='http://www.w3.org/2000/svg'%20viewBox='0%200%201700%20400'%3e%3cdefs%3e%3cstyle%3e.cls-3{fill:%23fff}.cls-8,.cls-9{stroke-miterlimit:10}.cls-6{fill:%23d5e2f5}.cls-8,.cls-9{stroke-width:3px}.cls-10,.cls-8{fill:%23f8c8dd}.cls-8,.cls-9{stroke:%237b1619}.cls-9{fill:none}.cls-11{fill:%23d23c6f}%3c/style%3e%3c/defs%3e%3cg%20id='component_tests'%20data-name='component%20tests'%3e%3cg%20id='component'%3e%3crect%20x='121.85'%20y='103.65'%20width='436.01'%20height='104.38'%20rx='19.76'%20transform='rotate(-6.55%20339.814%20155.852)'%20fill='%2397aad8'/%3e%3cg%20id='check'%3e%3ccircle%20cx='135.42'%20cy='229.09'%20r='27.6'%20fill='%23338846'/%3e%3cpath%20class='cls-3'%20d='M144.75%20210.18l6.53%202.44-14.19%2031.29-20.01-9.79%205.67-3.8%2011.43%204.14%2010.57-24.28z'/%3e%3c/g%3e%3cg%20id='finger'%20stroke-miterlimit='10'%20stroke='%23374d9c'%3e%3cpath%20d='M527.09%20307.73a1664.21%201664.21%200%2000-82-160.65c-4.72-8.13-13-17.49-21.63-13.85-2.9%201.21-5%203.74-6.8%206.34-9.23%2013.7-10.64%2031.49-7.43%2047.69s10.59%2031.23%2017.9%2046l49.78%20100.89'%20stroke-width='4'%20fill='%23fff'/%3e%3cpath%20d='M423.47%20133.23c-2.9%201.21-5%203.74-6.8%206.34a52%2052%200%2000-7.8%2019.42c9.75%2024.55%2019.88%2044.56%2036.23%2036.81%2013.36-6.33%2012.45-19.61%206.73-37q-3.34-5.86-6.73-11.71c-4.72-8.09-12.96-17.5-21.63-13.86z'%20stroke-width='3'%20fill='%23d5e2f5'/%3e%3c/g%3e%3cg%20id='tap'%3e%3cpath%20class='cls-6'%20d='M452.63%20104.87l35.11-36.66%2012.48%2029.64-40.57%2023.41-7.02-16.39zM467.39%20132.42l44.53-6.48-3.9%2026.52-37.45-3.32-3.18-16.72zM387.1%20132.42l-43.69-6.48v19.5l43.69-6.24v-6.78zM383.98%20152.46l-44.12%2021.84%209.02%2018.73%2038.22-28.07-3.12-12.5zM387.1%20189.91l-30.42%2024.18%2015.21%2019.21%2023.01-35.8-7.8-7.59z'/%3e%3c/g%3e%3c/g%3e%3cg%20id='component-2'%20data-name='component'%3e%3crect%20x='1129.76'%20y='84.19'%20width='436.01'%20height='104.38'%20rx='19.76'%20transform='rotate(-6.55%201347.764%20136.383)'%20fill='%237b1619'/%3e%3cg%20id='finger-2'%20data-name='finger'%3e%3cpath%20class='cls-3'%20d='M1535%20288.26a1660.71%201660.71%200%2000-82-160.64c-4.72-8.13-13-17.5-21.62-13.86-2.9%201.22-5%203.74-6.8%206.35-9.24%2013.69-10.64%2031.48-7.44%2047.69s10.59%2031.22%2017.9%2046q24.9%2050.44%2049.79%20100.88'/%3e%3cpath%20class='cls-8'%20d='M1431.38%20113.76c-2.9%201.22-5%203.74-6.8%206.35a52%2052%200%2000-7.8%2019.41c9.75%2024.56%2019.88%2044.57%2036.23%2036.82%2013.36-6.34%2012.45-19.61%206.73-37q-3.35-5.87-6.74-11.71c-4.72-8.14-12.95-17.51-21.62-13.87z'/%3e%3cpath%20class='cls-9'%20d='M1535%20288.26a1660.71%201660.71%200%2000-82-160.64c-4.72-8.13-13-17.5-21.62-13.86-2.9%201.22-5%203.74-6.8%206.35-9.24%2013.69-10.64%2031.48-7.44%2047.69s10.59%2031.22%2017.9%2046q24.9%2050.44%2049.79%20100.88'/%3e%3c/g%3e%3cg%20id='tap-2'%20data-name='tap'%3e%3cpath%20class='cls-10'%20d='M1460.54%2085.41l35.1-36.67%2012.49%2029.65-40.57%2023.4-7.02-16.38zM1475.29%20112.95l44.54-6.48-3.9%2026.52-37.45-3.31-3.19-16.73zM1395.01%20112.95l-43.69-6.48v19.5l43.69-6.24v-6.78zM1391.89%20132.99l-44.13%2021.85%209.02%2018.72%2038.23-28.07-3.12-12.5zM1395.01%20170.44l-30.43%2024.18%2015.22%2019.22%2023.01-35.81-7.8-7.59z'/%3e%3c/g%3e%3cg%20id='check-2'%20data-name='check'%3e%3ccircle%20class='cls-11'%20cx='1143.71'%20cy='209.26'%20r='27.6'/%3e%3cpath%20class='cls-3'%20d='M1151.41%20196.76h9.1l-11.9%2014.5%209.45%208.76-7%204.2-8.06-8.87-9.45%206.31h-7.26l13.56-11.17-9.98-10.08%208.41-1.75%205.12%208.23%208.01-10.13z'/%3e%3c/g%3e%3c/g%3e%3cg%20id='component-3'%20data-name='component'%3e%3crect%20x='625.8'%20y='87.47'%20width='436.01'%20height='104.38'%20rx='19.76'%20transform='rotate(-6.55%20843.766%20139.63)'%20fill='%23ee76ab'/%3e%3cg%20id='finger-3'%20data-name='finger'%3e%3cpath%20class='cls-3'%20d='M1031.05%20291.55a1663.13%201663.13%200%2000-82-160.65c-4.72-8.13-13-17.49-21.62-13.86-2.9%201.22-5%203.74-6.8%206.35-9.24%2013.69-10.65%2031.49-7.44%2047.69s10.59%2031.23%2017.9%2046L980.88%20318'/%3e%3cpath%20class='cls-8'%20d='M927.43%20117c-2.9%201.22-5%203.74-6.8%206.35a52.2%2052.2%200%2000-7.81%2019.42c9.76%2024.55%2019.89%2044.56%2036.24%2036.81%2013.36-6.33%2012.45-19.61%206.72-37q-3.35-5.87-6.73-11.71c-4.72-8.1-12.96-17.46-21.62-13.87z'/%3e%3cpath%20class='cls-9'%20d='M1031.05%20291.55a1663.13%201663.13%200%2000-82-160.65c-4.72-8.13-13-17.49-21.62-13.86-2.9%201.22-5%203.74-6.8%206.35-9.24%2013.69-10.65%2031.49-7.44%2047.69s10.59%2031.23%2017.9%2046L980.88%20318'/%3e%3c/g%3e%3cg%20id='check-3'%20data-name='check'%3e%3ccircle%20class='cls-11'%20cx='639.76'%20cy='212.54'%20r='27.6'/%3e%3cpath%20class='cls-3'%20d='M647.46%20200.05h9.1l-11.91%2014.5%209.46%208.75-7%204.2-8.06-8.86-9.45%206.3h-7.27l13.57-11.16-9.98-10.09%208.4-1.75%205.13%208.23%208.01-10.12z'/%3e%3c/g%3e%3c/g%3e%3c/g%3e%3c/svg%3e",c="data:image/svg+xml,%3csvg%20xmlns='http://www.w3.org/2000/svg'%20viewBox='0%200%201700%20500'%3e%3cdefs%3e%3cstyle%3e.cls-1{fill:%2397aad8}.cls-2{fill:%23fff}.cls-3{fill:%23d5e2f5}.cls-4{fill:%235971b5}.cls-6{fill:%23ee76ab}.cls-7{fill:%23f8c8dd;stroke:%23d23c6f;stroke-miterlimit:10}.cls-8{fill:%23d23c6f}%3c/style%3e%3c/defs%3e%3cg%20id='snapshot'%3e%3crect%20class='cls-1'%20x='96.64'%20y='82'%20width='710.79'%20height='321.65'%20rx='19.09'/%3e%3cpath%20class='cls-2'%20d='M126.17%20112.28h258.38v258.38H126.17zM519.66%20112.28h258.38v258.38H519.66z'/%3e%3crect%20class='cls-3'%20x='138.67'%20y='124.93'%20width='231.82'%20height='200.19'%20rx='7.25'/%3e%3cpath%20class='cls-4'%20d='M363.24%20125.43a6.75%206.75%200%20016.75%206.75v185.68a6.76%206.76%200%2001-6.75%206.76H145.92a6.76%206.76%200%2001-6.75-6.76V132.18a6.75%206.75%200%20016.75-6.75h217.32m0-1H145.92a7.76%207.76%200%2000-7.75%207.75v185.68a7.77%207.77%200%20007.75%207.76h217.32a7.76%207.76%200%20007.75-7.76V132.18a7.75%207.75%200%2000-7.75-7.75z'/%3e%3cpath%20class='cls-1'%20d='M159.41%20144.09h68.69v180.52h-68.69zM236.72%20144.09h119.16v61.4H236.72zM236.72%20210.77h119.16v14.25H236.72zM236.72%20230.3h119.16v14.25H236.72zM236.72%20249.83h119.16v14.25H236.72zM236.72%20269.37h119.16v34.18H236.72zM236.72%20308.83h119.16v14.25H236.72z'/%3e%3crect%20class='cls-3'%20x='532.94'%20y='124.93'%20width='231.82'%20height='200.19'%20rx='7.25'/%3e%3cpath%20class='cls-4'%20d='M757.51%20125.43a6.75%206.75%200%20016.75%206.75v185.68a6.76%206.76%200%2001-6.75%206.76H540.19a6.76%206.76%200%2001-6.75-6.76V132.18a6.75%206.75%200%20016.75-6.75h217.32m0-1H540.19a7.75%207.75%200%2000-7.75%207.75v185.68a7.76%207.76%200%20007.75%207.76h217.32a7.77%207.77%200%20007.75-7.76V132.18a7.76%207.76%200%2000-7.75-7.75z'/%3e%3cpath%20class='cls-1'%20d='M553.68%20144.09h68.69v180.52h-68.69zM630.99%20144.09h119.16v61.4H630.99zM630.99%20210.77h119.16v14.25H630.99zM630.99%20230.3h119.16v14.25H630.99zM630.99%20249.83h119.16v14.25H630.99zM630.99%20269.37h119.16v34.18H630.99zM630.99%20308.83h119.16v14.25H630.99z'/%3e%3cg%20id='check'%3e%3ccircle%20cx='114.12'%20cy='419.45'%20r='48.61'%20fill='%23338846'/%3e%3cpath%20class='cls-2'%20d='M130.56%20386.13l11.49%204.3-25%2055.12-35.24-17.24%209.99-6.7%2020.13%207.29%2018.63-42.77z'/%3e%3c/g%3e%3crect%20class='cls-6'%20x='894.97'%20y='82'%20width='710.79'%20height='321.65'%20rx='19.09'/%3e%3cpath%20class='cls-2'%20d='M924.5%20112.28h258.38v258.38H924.5z'/%3e%3crect%20class='cls-7'%20x='937.5'%20y='125.43'%20width='230.82'%20height='199.19'%20rx='6.75'/%3e%3cpath%20class='cls-2'%20d='M1317.99%20112.28h258.38v258.38h-258.38z'/%3e%3cpath%20class='cls-6'%20d='M957.74%20144.09h68.69v180.52h-68.69zM1035.05%20144.09h119.16v61.4h-119.16zM1035.05%20210.77h119.16v14.25h-119.16zM1035.05%20230.3h119.16v14.25h-119.16zM1035.05%20249.83h119.16v14.25h-119.16zM1035.05%20269.37h119.16v34.18h-119.16zM1035.05%20308.83h119.16v14.25h-119.16z'/%3e%3cg%20id='check-2'%20data-name='check'%3e%3crect%20class='cls-7'%20x='1331.77'%20y='125.43'%20width='230.82'%20height='199.19'%20rx='6.75'/%3e%3cpath%20class='cls-8'%20d='M1352.01%20144.09h68.69v180.52h-68.69z'/%3e%3cpath%20class='cls-6'%20d='M1429.32%20210.77h119.16v14.25h-119.16zM1429.32%20230.3h119.16v14.25h-119.16zM1429.32%20249.83h119.16v14.25h-119.16z'/%3e%3cpath%20class='cls-8'%20d='M1429.32%20269.37h119.16v34.18h-119.16z'/%3e%3cpath%20class='cls-6'%20d='M1429.32%20308.83h119.16v14.25h-119.16z'/%3e%3ccircle%20cx='912.39'%20cy='419.26'%20r='48.61'%20fill='%23a21732'/%3e%3cpath%20class='cls-2'%20d='M925.95%20397.25h16.04l-20.97%2025.54%2016.65%2015.42-12.33%207.41L911.15%20430l-16.65%2011.1h-12.8l23.9-19.67-17.58-17.76%2014.8-3.08%209.02%2014.49%2014.11-17.83z'/%3e%3c/g%3e%3c/g%3e%3c/svg%3e",l="/assets/p_tests-e2e.zzEG5Lpm.svg",x=JSON.parse('{"title":"Teste","description":"","frontmatter":{},"headers":[],"relativePath":"docs/testing-overview.md","filePath":"docs/testing-overview.md"}'),d={name:"docs/testing-overview.md"},p=i('

Teste

À medida que sua base de código se expande, pequenos erros e casos extremos que você não espera podem se transformar em falhas maiores. Bugs levam a uma experiência ruim do usuário e, em última análise, a perdas de negócios. Uma maneira de evitar uma programação frágil é testar seu código antes de liberá-lo.

Neste guia, abordaremos diferentes maneiras automatizadas de garantir que seu aplicativo funcione conforme o esperado, desde análises estáticas até testes completos.

image

Por que testar

Somos humanos e os humanos cometem erros. O teste é importante porque ajuda a descobrir esses erros e verifica se seu código está funcionando. Talvez ainda mais importante, o teste garante que seu código continue funcionando no futuro à medida que você adiciona novos recursos, refatora os existentes ou atualiza dependências importantes do seu projeto.

Há mais valor em testar do que você imagina. Uma das melhores maneiras de corrigir um bug em seu código é escrever um teste com falha que o exponha. Então, quando você corrige o bug e executa novamente o teste, se ele passar, significa que o bug foi corrigido, nunca reintroduzido na base de código.

Os testes também podem servir como documentação para novas pessoas ingressando na sua equipe. Para pessoas que nunca viram uma base de código antes, a leitura de testes pode ajudá-las a entender como funciona o código existente.

Por último, mas não menos importante, testes mais automatizados significam menos tempo gasto com controle de qualidade manual, liberando um tempo valioso.

Análise Estática

O primeiro passo para melhorar a qualidade do seu código é começar a usar ferramentas de análise estática. A análise estática verifica se há erros em seu código enquanto você o escreve, mas sem executar nenhum código.

  • Os linters analisam o código para detectar erros comuns, como código não utilizado, e para ajudar a evitar armadilhas, para sinalizar proibições do guia de estilo, como usar tabulações em vez de espaços (ou vice-versa, dependendo da sua configuração).
  • A verificação de tipo garante que a construção que você está passando para uma função corresponde ao que a função foi projetada para aceitar, evitando passar uma string para uma função de contagem que espera um número, por exemplo.

React Native vem com duas dessas ferramentas configuradas imediatamente: ESLint para linting e TypeScript para verificação de tipo.

Escrevendo código testável

Para começar com os testes, primeiro você precisa escrever um código que seja testável. Considere um processo de fabricação de aeronave – antes de qualquer modelo decolar para mostrar que todos os seus sistemas complexos funcionam bem juntos, peças individuais são testadas para garantir que são seguras e funcionam corretamente. Por exemplo, as asas são testadas dobrando-as sob carga extrema; as peças do motor são testadas quanto à sua durabilidade; o pára-brisa é testado contra impacto simulado de pássaros.

O software é semelhante. Em vez de escrever seu programa inteiro em um arquivo enorme com muitas linhas de código, você escreve seu código em vários módulos pequenos que podem ser testados mais detalhadamente do que se você testasse o todo montado. Dessa forma, escrever código testável está interligado com escrever código limpo e modular.

Para tornar seu aplicativo mais testável, comece separando a parte de visualização do seu aplicativo – seus componentes React – da lógica de negócios e do estado do aplicativo (independentemente de você usar Redux, MobX ou outras soluções). Dessa forma, você pode manter seus testes de lógica de negócios – que não devem depender de seus componentes React – independentes dos próprios componentes, cujo trabalho é principalmente renderizar a UI do seu aplicativo!

Teoricamente, você poderia ir tão longe a ponto de remover toda a lógica e a busca de dados de seus componentes. Desta forma, seus componentes seriam exclusivamente dedicados à renderização. Seu estado seria totalmente independente de seus componentes. A lógica do seu aplicativo funcionaria sem nenhum componente React!

Informação

Incentivamos você a explorar ainda mais o tópico de código testável em outros recursos de aprendizagem.

Escrevendo testes

Depois de escrever o código testável, é hora de escrever alguns testes reais! O modelo padrão do React Native vem com a estrutura de teste Jest. Ele inclui uma predefinição adaptada a esse ambiente para que você possa ser produtivo sem ajustar a configuração e as simulações imediatamente. Falaremos mais sobre simulações em breve. Você pode usar o Jest para escrever todos os tipos de testes apresentados neste guia.

Se você faz desenvolvimento orientado a testes, na verdade você escreve os testes primeiro! Dessa forma, é dada a testabilidade do seu código.

Estruturando Testes

Seus testes devem ser curtos e, idealmente, testar apenas uma coisa. Vamos começar com um exemplo de teste de unidade escrito com Jest:

js
it('given a date in the past, colorForDueDate() returns red', () => {
+  expect(colorForDueDate('2000-10-20')).toBe('red');
+});

O teste é descrito pela string passada para a função it. Tome muito cuidado ao escrever a descrição para que fique claro o que está sendo testado. Faça o seu melhor para cobrir o seguinte:

  • Dado - alguma pré-condição
  • Quando - alguma ação executada pela função que você está testando
  • Então - o resultado esperado

Isso também é conhecido como AAA (organizar, agir, afirmar (tradução de: Arrange, Act, Assert).

Jest oferece uma função de descrição/describe para ajudar a estruturar seus testes. Use describe para agrupar todos os testes que pertencem a uma funcionalidade. As descrições podem ser aninhadas, se você precisar. Outras funções que você normalmente usará são beforeEach ou beforeAll, que você pode usar para configurar os objetos que está testando. Leia mais na referência da API Jest.

Se o seu teste tiver muitas etapas ou muitas expectativas, você provavelmente desejará dividi-lo em várias etapas menores. Além disso, certifique-se de que seus testes sejam completamente independentes um do outro. Cada teste em seu conjunto deve ser executável por si só, sem primeiro executar algum outro teste. Por outro lado, se você executar todos os seus testes juntos, o primeiro teste não deverá influenciar o resultado do segundo.

Por último, como desenvolvedores, gostamos quando nosso código funciona bem e não trava. Com os testes, isso geralmente acontece ao contrário. Pense em um teste reprovado como uma coisa boa! Quando um teste falha, muitas vezes significa que algo não está certo. Isso lhe dá a oportunidade de corrigir o problema antes que ele afete os usuários.

Testes Unitários

Os testes unitários cobrem as menores partes do código, como funções ou classes individuais.

Quando o objeto que está sendo testado tiver alguma dependência, muitas vezes você precisará "mockar" ela, conforme descrito no próximo parágrafo.

A grande vantagem dos testes unitários é que eles são rápidos de escrever e executar. Portanto, à medida que você trabalha, você obtém feedback rápido sobre se seus testes estão sendo aprovados. Jest ainda tem a opção de executar continuamente testes relacionados ao código que você está editando: modo Watch.

image

Mock

Às vezes, quando seus objetos testados têm dependências externas, você vai querer “mockar eles”. “Mocking” é quando você substitui alguma dependência do seu código pela sua própria implementação.

Informação

Geralmente, usar objetos reais em seus testes é melhor do que usar mocks, mas há situações em que isso não é possível. Por exemplo: quando seu teste de unidade JS depende de um módulo nativo escrito em Java ou Objective-C.

Imagine que você está escrevendo um aplicativo que mostra o clima atual em sua cidade e está usando algum serviço externo ou outra dependência que fornece informações meteorológicas. Se o serviço informar que está chovendo, você deseja mostrar uma imagem com uma nuvem chuvosa. Você não quer chamar esse serviço em seus testes porque:

  • Poderia tornar os testes lentos e instáveis (devido às solicitações de rede envolvidas)
  • O serviço pode retornar dados diferentes toda vez que você executa o teste
  • Serviços de terceiros podem ficar offline quando você realmente precisa executar testes!

Portanto, você pode fornecer uma implementação simulada do serviço, substituindo efetivamente milhares de linhas de código e alguns termômetros conectados à Internet!

Informação

Jest vem com suporte para simulação desde o nível de função até a simulação em nível de módulo.

Testes de Integração

Ao escrever sistemas de software maiores, suas partes individuais precisam interagir umas com as outras. Em testes unitários, se sua unidade depender de outra, às vezes você acabará mockando a dependência, substituindo-a por uma falsa.

Nos testes de integração, unidades individuais reais são combinadas (da mesma forma que no seu aplicativo) e testadas em conjunto para garantir que sua cooperação funcione conforme o esperado. Isso não quer dizer que a simulação não aconteça aqui: você ainda precisará de simulações (por exemplo, para simular a comunicação com um serviço meteorológico), mas precisará muito menos delas do que em testes unitários.

Informações

Observe que a terminologia sobre o que significa teste de integração nem sempre é consistente. Além disso, a linha entre o que é um teste de unidade e o que é um teste de integração pode nem sempre ser clara. Para este guia, seu teste se enquadra em "teste de integração" se:

  • Combina vários módulos do seu aplicativo conforme descrito acima
  • Usa um sistema externo
  • Faz uma chamada de rede para outro aplicativo (como a API do serviço meteorológico)
  • Qualquer tipo de E/S de arquivo ou banco de dados

image

Testes de Componentes

Os componentes React são responsáveis por renderizar seu aplicativo e os usuários interagirão diretamente com sua saída. Mesmo que a lógica de negócios do seu aplicativo tenha alta cobertura de testes e esteja correta, sem testes de componentes você ainda poderá entregar uma UI quebrada aos seus usuários. Os testes de componentes podem se enquadrar nos testes de unidade e de integração, mas como são uma parte essencial do React Native, iremos abordá-los separadamente.

Para testar os componentes do React, há duas coisas que você pode querer testar:

  • Interação: para garantir que o componente se comporte corretamente quando interagido por um usuário (por exemplo, quando o usuário pressiona um botão)
  • Renderização: para garantir que a saída de renderização do componente usada pelo React esteja correta (por exemplo, a aparência e o posicionamento do botão na UI)

Por exemplo, se você tiver um botão que possui um ouvinte onPress, você deseja testar se o botão aparece corretamente e se o toque no botão é manipulado corretamente pelo componente.

Existem várias bibliotecas que podem ajudá-lo a testá-los:

  • O Test Renderer do React, desenvolvido junto com seu núcleo, fornece um renderizador React que pode ser usado para renderizar componentes React em objetos JavaScript puros, sem depender do DOM ou de um ambiente móvel nativo.
  • A biblioteca de testes React Native é baseada no renderizador de teste do React e adiciona fireEvent e APIs de consulta descritas no próximo parágrafo.

Informações

Os testes de componentes são apenas testes de JavaScript executados no ambiente Node.js. Eles não levam em consideração nenhum código iOS, Android ou outro código de plataforma que suporte os componentes React Native. Conclui-se que eles não podem lhe dar 100% de confiança de que tudo funciona para o usuário. Se houver um bug no código do iOS ou Android, eles não o encontrarão.

image

Testando interações do usuário

Além de renderizar algumas UI, seus componentes lidam com eventos como onChangeText para TextInput ou onPress para Button. Eles também podem conter outras funções e retornos de chamada de eventos. Considere o seguinte exemplo:

jsx
function GroceryShoppingList() {
+  const [groceryItem, setGroceryItem] = useState('');
+  const [items, setItems] = useState<string[]>([]);
+
+  const addNewItemToShoppingList = useCallback(() => {
+    setItems([groceryItem, ...items]);
+    setGroceryItem('');
+  }, [groceryItem, items]);
+
+  return (
+    <>
+      <TextInput
+        value={groceryItem}
+        placeholder="Enter grocery item"
+        onChangeText={text => setGroceryItem(text)}
+      />
+      <Button
+        title="Add the item to list"
+        onPress={addNewItemToShoppingList}
+      />
+      {items.map(item => (
+        <Text key={item}>{item}</Text>
+      ))}
+    </>
+  );
+}

Ao testar as interações do usuário, teste o componente da perspectiva do usuário – o que há na página? O que muda quando interagido?

Como regra geral, prefira usar coisas que os usuários possam ver ou ouvir:

Por outro lado, você deve evitar:

  • fazendo afirmações sobre adereços de componentes ou estado
  • consultas testID

Evite testar detalhes de implementação como adereços ou estado - embora esses testes funcionem, eles não são orientados para como os usuários irão interagir com o componente e tendem a quebrar por refatoração (por exemplo, quando você deseja renomear algumas coisas ou reescrever um componente de classe usando ganchos ).

Informações

Os componentes da classe React são especialmente propensos a testar detalhes de sua implementação, como estado interno, adereços ou manipuladores de eventos. Para evitar testar detalhes de implementação, prefira usar componentes de função com Hooks, o que torna mais difícil confiar nos componentes internos.

Bibliotecas de teste de componentes, como React Native Testing Library, facilitam a escrita de testes centrados no usuário por meio da escolha cuidadosa das APIs fornecidas. O exemplo a seguir usa os métodos fireEvent, changeText e press que simulam um usuário interagindo com o componente e uma função de consulta getAllByText que encontra nós Text correspondentes na saída renderizada.

jsx
test('given empty GroceryShoppingList, user can add an item to it', () => {
+  const {getByPlaceholderText, getByText, getAllByText} = render(
+    <GroceryShoppingList />,
+  );
+
+  fireEvent.changeText(
+    getByPlaceholderText('Enter grocery item'),
+    'banana',
+  );
+  fireEvent.press(getByText('Add the item to list'));
+
+  const bananaElements = getAllByText('banana');
+  expect(bananaElements).toHaveLength(1); // expect 'banana' to be on the list
+});

Este exemplo não está testando como alguns estados mudam quando você chama uma função. Ele testa o que acontece quando um usuário altera o texto no TextInput e pressiona o Button!

Testando saída renderizada

O teste instantâneo é um tipo avançado de teste habilitado pelo Jest. É uma ferramenta muito poderosa e de baixo nível, por isso é aconselhável atenção redobrada ao utilizá-la.

Um "instantâneo de componente" é uma string semelhante a JSX criada por um serializador React personalizado integrado ao Jest. Este serializador permite que Jest traduza árvores de componentes React em strings legíveis por humanos. Dito de outra forma: um snapshot de componente é uma representação textual da saída de renderização do seu componente gerada durante uma execução de teste. Pode ser assim:

jsx
<Text
+  style={
+    Object {
+      "fontSize": 20,
+      "textAlign": "center",
+    }
+  }>
+  Welcome to React Native!
+</Text>

Com o teste de instantâneo, normalmente você primeiro implementa seu componente e depois executa o teste de instantâneo. O teste de instantâneo cria um instantâneo e o salva em um arquivo em seu repositório como um instantâneo de referência. O arquivo é então confirmado e verificado durante a revisão do código. Quaisquer alterações futuras na saída de renderização do componente alterarão seu instantâneo, o que fará com que o teste falhe. Em seguida, você precisa atualizar o instantâneo de referência armazenado para que o teste seja aprovado. Essa mudança novamente precisa ser comprometida e revisada.

Os instantâneos têm vários pontos fracos:

  • Para você, como desenvolvedor ou revisor, pode ser difícil dizer se uma alteração no snapshot é intencional ou se é evidência de um bug. Instantâneos especialmente grandes podem rapidamente tornar-se difíceis de compreender e o seu valor acrescentado torna-se baixo.
  • Quando o instantâneo é criado, nesse ponto ele é considerado correto, mesmo no caso em que a saída renderizada esteja realmente errada.
  • Quando um instantâneo falha, é tentador atualizá-lo usando a opção --updateSnapshot sem tomar o devido cuidado para investigar se a mudança é esperada. Uma certa dose de disciplina do desenvolvedor é, portanto, necessária.

Os instantâneos em si não garantem que a lógica de renderização do seu componente esteja correta, eles são apenas bons para proteger contra mudanças inesperadas e para verificar se os componentes na árvore React em teste recebem os acessórios esperados (estilos e etc.).

Recomendamos que você use apenas snapshots pequenos (consulte a regra de não usar snapshots grandes). Se você quiser testar uma mudança entre dois estados de componentes React, use snapshot-diff. Em caso de dúvida, prefira expectativas explícitas conforme descrito no parágrafo anterior.

image

Testes ponta a ponta

Nos testes ponta a ponta (E2E), você verifica se seu aplicativo está funcionando conforme o esperado em um dispositivo (ou simulador/emulador) da perspectiva do usuário.

Isso é feito criando seu aplicativo na configuração de lançamento e executando os testes nele. Nos testes E2E, você não pensa mais em componentes React, APIs React Native, Redux ou qualquer lógica de negócio. Esse não é o propósito dos testes E2E e eles nem sequer estão acessíveis para você durante os testes E2E.

Em vez disso, as bibliotecas de teste E2E permitem que você encontre e controle elementos na tela do seu aplicativo: por exemplo, você pode tocar em botões ou inserir texto em TextInputs da mesma forma que um usuário real faria. Depois, você pode fazer afirmações sobre se um determinado elemento existe ou não na tela do aplicativo, se está visível ou não, que texto ele contém e assim por diante.

Os testes E2E oferecem a maior confiança possível de que parte do seu aplicativo está funcionando. As compensações incluem:

  • Escrevê-los consome mais tempo em comparação com outros tipos de testes
  • Eles são mais lentos para correr
  • Eles são mais propensos a instabilidade (um teste "instável" é um teste que passa aleatoriamente e falha sem qualquer alteração no código)

Tente cobrir as partes vitais do seu aplicativo com testes E2E: fluxo de autenticação, funcionalidades principais, pagamentos, etc. Use testes JS mais rápidos para as partes não vitais do seu aplicativo. Quanto mais testes você adicionar, maior será sua confiança, mas também mais tempo você gastará para mantê-los e executá-los. Considere as vantagens e desvantagens e decida o que é melhor para você.

Existem várias ferramentas de teste E2E disponíveis: na comunidade React Native, Detox é uma estrutura popular porque é adaptada para aplicativos React Native. Outra biblioteca popular no espaço de aplicativos iOS e Android é Appium ou Maestro.

image

Resumo

Esperamos que você tenha gostado de ler e aprendido algo com este guia. Há muitas maneiras de testar seus aplicativos. Pode ser difícil decidir o que usar no início. No entanto, acreditamos que tudo fará sentido quando você começar a adicionar testes ao seu incrível aplicativo React Native. Então, o que você está esperando? Aumente sua cobertura!

',93),h=[p];function u(m,k,g,E,v,f){return a(),s("div",null,h)}const b=e(d,[["render",u]]);export{x as __pageData,b as default}; diff --git a/vitepress/docs/.vitepress/dist/assets/docs_testing-overview.md.By6FslrL.lean.js b/vitepress/docs/.vitepress/dist/assets/docs_testing-overview.md.By6FslrL.lean.js new file mode 100644 index 0000000..42bca21 --- /dev/null +++ b/vitepress/docs/.vitepress/dist/assets/docs_testing-overview.md.By6FslrL.lean.js @@ -0,0 +1 @@ +import{_ as e,c as s,o as a,a4 as i}from"./chunks/framework.nQaBHiNx.js";const t="/assets/diagram_testing.D4maG0bg.svg",o="data:image/svg+xml,%3csvg%20xmlns='http://www.w3.org/2000/svg'%20viewBox='0%200%201700%20300'%3e%3cdefs%3e%3cstyle%3e.cls-1{fill:%2397aad8}.cls-2{fill:%23338846}.cls-3{fill:%23fff}%3c/style%3e%3c/defs%3e%3cg%20id='unit_tests'%20data-name='unit%20tests'%3e%3crect%20class='cls-1'%20x='617.1'%20y='95.47'%20width='95.24'%20height='95.24'%20rx='19.76'/%3e%3cg%20id='check'%3e%3ccircle%20class='cls-2'%20cx='624.67'%20cy='187.38'%20r='29.61'/%3e%3cpath%20class='cls-3'%20d='M634.69%20167.08l7%202.62-15.23%2033.58-21.47-10.5%206.08-4.08%2012.27%204.44%2011.35-26.06z'/%3e%3c/g%3e%3crect%20class='cls-1'%20x='736.34'%20y='95.47'%20width='95.24'%20height='95.24'%20rx='19.76'/%3e%3cg%20id='check-2'%20data-name='check'%3e%3ccircle%20class='cls-2'%20cx='747.35'%20cy='187.38'%20r='29.61'/%3e%3cpath%20class='cls-3'%20d='M757.37%20167.08l7%202.62-15.23%2033.58-21.47-10.5%206.08-4.08%2012.27%204.44%2011.35-26.06z'/%3e%3c/g%3e%3crect%20class='cls-1'%20x='375.19'%20y='95.47'%20width='95.24'%20height='95.24'%20rx='19.76'/%3e%3cg%20id='check-3'%20data-name='check'%3e%3ccircle%20class='cls-2'%20cx='382.76'%20cy='187.38'%20r='29.61'/%3e%3cpath%20class='cls-3'%20d='M392.78%20167.08l7%202.62-15.23%2033.58-21.47-10.5%206.08-4.08%2012.27%204.44%2011.35-26.06z'/%3e%3c/g%3e%3crect%20class='cls-1'%20x='494.42'%20y='95.47'%20width='95.24'%20height='95.24'%20rx='19.76'/%3e%3cg%20id='check-4'%20data-name='check'%3e%3ccircle%20class='cls-2'%20cx='505.44'%20cy='187.38'%20r='29.61'/%3e%3cpath%20class='cls-3'%20d='M515.46%20167.08l7%202.62-15.23%2033.58-21.47-10.5%206.08-4.08%2012.27%204.44%2011.35-26.06z'/%3e%3c/g%3e%3crect%20class='cls-1'%20x='133.28'%20y='95.47'%20width='95.24'%20height='95.24'%20rx='19.76'/%3e%3cg%20id='check-5'%20data-name='check'%3e%3ccircle%20class='cls-2'%20cx='140.85'%20cy='187.38'%20r='29.61'/%3e%3cpath%20class='cls-3'%20d='M150.87%20167.08l6.99%202.62-15.23%2033.58-21.46-10.5%206.08-4.08%2012.26%204.44%2011.36-26.06z'/%3e%3c/g%3e%3crect%20class='cls-1'%20x='252.51'%20y='95.47'%20width='95.24'%20height='95.24'%20rx='19.76'/%3e%3cg%20id='check-6'%20data-name='check'%3e%3ccircle%20class='cls-2'%20cx='263.53'%20cy='187.38'%20r='29.61'/%3e%3cpath%20class='cls-3'%20d='M273.54%20167.08l7%202.62-15.23%2033.58-21.47-10.5%206.09-4.08%2012.26%204.44%2011.35-26.06z'/%3e%3c/g%3e%3crect%20class='cls-1'%20x='1094.48'%20y='97'%20width='95.24'%20height='95.24'%20rx='19.76'/%3e%3cg%20id='check-7'%20data-name='check'%3e%3ccircle%20class='cls-2'%20cx='1105.49'%20cy='188.92'%20r='29.61'/%3e%3cpath%20class='cls-3'%20d='M1115.51%20168.62l7%202.62-15.23%2033.58-21.47-10.5%206.08-4.08%2012.27%204.43%2011.35-26.05z'/%3e%3c/g%3e%3crect%20class='cls-1'%20x='1213.71'%20y='95.47'%20width='95.24'%20height='95.24'%20rx='19.76'/%3e%3cg%20id='check-8'%20data-name='check'%3e%3ccircle%20class='cls-2'%20cx='1224.73'%20cy='187.38'%20r='29.61'/%3e%3cpath%20class='cls-3'%20d='M1234.74%20167.08l7%202.62-15.23%2033.58-21.47-10.5%206.09-4.08%2012.26%204.44%2011.35-26.06z'/%3e%3c/g%3e%3crect%20class='cls-1'%20x='1332.94'%20y='97'%20width='95.24'%20height='95.24'%20rx='19.76'/%3e%3cg%20id='check-9'%20data-name='check'%3e%3ccircle%20class='cls-2'%20cx='1343.96'%20cy='188.92'%20r='29.61'/%3e%3cpath%20class='cls-3'%20d='M1353.97%20168.62l7%202.62-15.23%2033.58-21.46-10.5%206.08-4.08%2012.27%204.43%2011.34-26.05z'/%3e%3c/g%3e%3crect%20class='cls-1'%20x='1452.18'%20y='95.47'%20width='95.24'%20height='95.24'%20rx='19.76'/%3e%3cg%20id='check-10'%20data-name='check'%3e%3ccircle%20class='cls-2'%20cx='1463.19'%20cy='187.38'%20r='29.61'/%3e%3cpath%20class='cls-3'%20d='M1473.21%20167.08l7%202.62-15.23%2033.58-21.47-10.5%206.08-4.08%2012.27%204.44%2011.35-26.06z'/%3e%3c/g%3e%3crect%20x='855.08'%20y='95.47'%20width='95.24'%20height='95.24'%20rx='19.76'%20fill='%23ee76ab'/%3e%3cg%20id='check-11'%20data-name='check'%3e%3ccircle%20cx='866.58'%20cy='187.38'%20r='29.61'%20fill='%23a21732'/%3e%3cpath%20class='cls-3'%20d='M874.85%20173.97h9.77l-12.78%2015.56%2010.15%209.4-7.52%204.51-8.64-9.52-10.15%206.77h-7.8l14.57-11.98-10.71-10.83%209.01-1.87%205.5%208.83%208.6-10.87z'/%3e%3c/g%3e%3crect%20class='cls-1'%20x='975.25'%20y='95.47'%20width='95.24'%20height='95.24'%20rx='19.76'/%3e%3cg%20id='check-12'%20data-name='check'%3e%3ccircle%20class='cls-2'%20cx='985.32'%20cy='187.38'%20r='29.61'/%3e%3cpath%20class='cls-3'%20d='M995.34%20167.08l7%202.62-15.23%2033.58-21.47-10.5%206.08-4.08%2012.27%204.44%2011.35-26.06z'/%3e%3c/g%3e%3c/g%3e%3c/svg%3e",n="data:image/svg+xml,%3csvg%20xmlns='http://www.w3.org/2000/svg'%20viewBox='0%200%201700%20300'%3e%3cdefs%3e%3cstyle%3e.cls-1{fill:%2397aad8}.cls-2{fill:%23d5e2f5}.cls-3{fill:%23338846}.cls-4{fill:%23fff}.cls-6{fill:%23f8c8dd}%3c/style%3e%3c/defs%3e%3cg%20id='integration_tests'%20data-name='integration%20tests'%3e%3cg%20id='test'%3e%3crect%20class='cls-1'%20x='634.51'%20y='64.58'%20width='415.75'%20height='165.21'%20rx='23.45'/%3e%3crect%20class='cls-2'%20x='679.13'%20y='99.56'%20width='95.24'%20height='95.24'%20rx='19.76'/%3e%3crect%20class='cls-2'%20x='794.77'%20y='99.56'%20width='95.24'%20height='95.24'%20rx='19.76'/%3e%3crect%20class='cls-2'%20x='910.41'%20y='99.56'%20width='95.24'%20height='95.24'%20rx='19.76'/%3e%3c/g%3e%3cg%20id='check'%3e%3ccircle%20class='cls-3'%20cx='641.9'%20cy='224.42'%20r='29.61'/%3e%3cpath%20class='cls-4'%20d='M651.92%20204.11l7%202.62-15.23%2033.58-21.47-10.5%206.08-4.08%2012.27%204.44%2011.35-26.06z'/%3e%3c/g%3e%3cg%20id='test-2'%20data-name='test'%3e%3crect%20class='cls-1'%20x='127.03'%20y='64.58'%20width='415.75'%20height='165.21'%20rx='23.45'/%3e%3crect%20class='cls-2'%20x='171.65'%20y='99.56'%20width='95.24'%20height='95.24'%20rx='19.76'/%3e%3crect%20class='cls-2'%20x='287.29'%20y='99.56'%20width='95.24'%20height='95.24'%20rx='19.76'/%3e%3crect%20class='cls-2'%20x='402.93'%20y='99.56'%20width='95.24'%20height='95.24'%20rx='19.76'/%3e%3c/g%3e%3cg%20id='check-2'%20data-name='check'%3e%3ccircle%20class='cls-3'%20cx='134.42'%20cy='224.42'%20r='29.61'/%3e%3cpath%20class='cls-4'%20d='M144.44%20204.11l7%202.62-15.23%2033.58-21.47-10.5%206.08-4.08%2012.27%204.44%2011.35-26.06z'/%3e%3c/g%3e%3cg%20id='test-3'%20data-name='test'%3e%3crect%20x='1142.33'%20y='64.58'%20width='415.75'%20height='165.21'%20rx='23.45'%20fill='%23ee76ab'/%3e%3crect%20class='cls-6'%20x='1186.94'%20y='99.56'%20width='95.24'%20height='95.24'%20rx='19.76'/%3e%3crect%20class='cls-6'%20x='1302.58'%20y='99.56'%20width='95.24'%20height='95.24'%20rx='19.76'/%3e%3crect%20class='cls-6'%20x='1418.22'%20y='99.56'%20width='95.24'%20height='95.24'%20rx='19.76'/%3e%3c/g%3e%3cg%20id='check-3'%20data-name='check'%3e%3ccircle%20cx='1149.38'%20cy='224.21'%20r='29.61'%20fill='%23a21732'/%3e%3cpath%20class='cls-4'%20d='M1157.64%20210.8h9.77l-12.77%2015.57%2010.14%209.39-7.51%204.51-8.65-9.51-10.14%206.76h-7.8l14.56-11.98-10.71-10.82%209.02-1.88%205.5%208.83%208.59-10.87z'/%3e%3c/g%3e%3c/g%3e%3c/svg%3e",r="data:image/svg+xml,%3csvg%20xmlns='http://www.w3.org/2000/svg'%20viewBox='0%200%201700%20400'%3e%3cdefs%3e%3cstyle%3e.cls-3{fill:%23fff}.cls-8,.cls-9{stroke-miterlimit:10}.cls-6{fill:%23d5e2f5}.cls-8,.cls-9{stroke-width:3px}.cls-10,.cls-8{fill:%23f8c8dd}.cls-8,.cls-9{stroke:%237b1619}.cls-9{fill:none}.cls-11{fill:%23d23c6f}%3c/style%3e%3c/defs%3e%3cg%20id='component_tests'%20data-name='component%20tests'%3e%3cg%20id='component'%3e%3crect%20x='121.85'%20y='103.65'%20width='436.01'%20height='104.38'%20rx='19.76'%20transform='rotate(-6.55%20339.814%20155.852)'%20fill='%2397aad8'/%3e%3cg%20id='check'%3e%3ccircle%20cx='135.42'%20cy='229.09'%20r='27.6'%20fill='%23338846'/%3e%3cpath%20class='cls-3'%20d='M144.75%20210.18l6.53%202.44-14.19%2031.29-20.01-9.79%205.67-3.8%2011.43%204.14%2010.57-24.28z'/%3e%3c/g%3e%3cg%20id='finger'%20stroke-miterlimit='10'%20stroke='%23374d9c'%3e%3cpath%20d='M527.09%20307.73a1664.21%201664.21%200%2000-82-160.65c-4.72-8.13-13-17.49-21.63-13.85-2.9%201.21-5%203.74-6.8%206.34-9.23%2013.7-10.64%2031.49-7.43%2047.69s10.59%2031.23%2017.9%2046l49.78%20100.89'%20stroke-width='4'%20fill='%23fff'/%3e%3cpath%20d='M423.47%20133.23c-2.9%201.21-5%203.74-6.8%206.34a52%2052%200%2000-7.8%2019.42c9.75%2024.55%2019.88%2044.56%2036.23%2036.81%2013.36-6.33%2012.45-19.61%206.73-37q-3.34-5.86-6.73-11.71c-4.72-8.09-12.96-17.5-21.63-13.86z'%20stroke-width='3'%20fill='%23d5e2f5'/%3e%3c/g%3e%3cg%20id='tap'%3e%3cpath%20class='cls-6'%20d='M452.63%20104.87l35.11-36.66%2012.48%2029.64-40.57%2023.41-7.02-16.39zM467.39%20132.42l44.53-6.48-3.9%2026.52-37.45-3.32-3.18-16.72zM387.1%20132.42l-43.69-6.48v19.5l43.69-6.24v-6.78zM383.98%20152.46l-44.12%2021.84%209.02%2018.73%2038.22-28.07-3.12-12.5zM387.1%20189.91l-30.42%2024.18%2015.21%2019.21%2023.01-35.8-7.8-7.59z'/%3e%3c/g%3e%3c/g%3e%3cg%20id='component-2'%20data-name='component'%3e%3crect%20x='1129.76'%20y='84.19'%20width='436.01'%20height='104.38'%20rx='19.76'%20transform='rotate(-6.55%201347.764%20136.383)'%20fill='%237b1619'/%3e%3cg%20id='finger-2'%20data-name='finger'%3e%3cpath%20class='cls-3'%20d='M1535%20288.26a1660.71%201660.71%200%2000-82-160.64c-4.72-8.13-13-17.5-21.62-13.86-2.9%201.22-5%203.74-6.8%206.35-9.24%2013.69-10.64%2031.48-7.44%2047.69s10.59%2031.22%2017.9%2046q24.9%2050.44%2049.79%20100.88'/%3e%3cpath%20class='cls-8'%20d='M1431.38%20113.76c-2.9%201.22-5%203.74-6.8%206.35a52%2052%200%2000-7.8%2019.41c9.75%2024.56%2019.88%2044.57%2036.23%2036.82%2013.36-6.34%2012.45-19.61%206.73-37q-3.35-5.87-6.74-11.71c-4.72-8.14-12.95-17.51-21.62-13.87z'/%3e%3cpath%20class='cls-9'%20d='M1535%20288.26a1660.71%201660.71%200%2000-82-160.64c-4.72-8.13-13-17.5-21.62-13.86-2.9%201.22-5%203.74-6.8%206.35-9.24%2013.69-10.64%2031.48-7.44%2047.69s10.59%2031.22%2017.9%2046q24.9%2050.44%2049.79%20100.88'/%3e%3c/g%3e%3cg%20id='tap-2'%20data-name='tap'%3e%3cpath%20class='cls-10'%20d='M1460.54%2085.41l35.1-36.67%2012.49%2029.65-40.57%2023.4-7.02-16.38zM1475.29%20112.95l44.54-6.48-3.9%2026.52-37.45-3.31-3.19-16.73zM1395.01%20112.95l-43.69-6.48v19.5l43.69-6.24v-6.78zM1391.89%20132.99l-44.13%2021.85%209.02%2018.72%2038.23-28.07-3.12-12.5zM1395.01%20170.44l-30.43%2024.18%2015.22%2019.22%2023.01-35.81-7.8-7.59z'/%3e%3c/g%3e%3cg%20id='check-2'%20data-name='check'%3e%3ccircle%20class='cls-11'%20cx='1143.71'%20cy='209.26'%20r='27.6'/%3e%3cpath%20class='cls-3'%20d='M1151.41%20196.76h9.1l-11.9%2014.5%209.45%208.76-7%204.2-8.06-8.87-9.45%206.31h-7.26l13.56-11.17-9.98-10.08%208.41-1.75%205.12%208.23%208.01-10.13z'/%3e%3c/g%3e%3c/g%3e%3cg%20id='component-3'%20data-name='component'%3e%3crect%20x='625.8'%20y='87.47'%20width='436.01'%20height='104.38'%20rx='19.76'%20transform='rotate(-6.55%20843.766%20139.63)'%20fill='%23ee76ab'/%3e%3cg%20id='finger-3'%20data-name='finger'%3e%3cpath%20class='cls-3'%20d='M1031.05%20291.55a1663.13%201663.13%200%2000-82-160.65c-4.72-8.13-13-17.49-21.62-13.86-2.9%201.22-5%203.74-6.8%206.35-9.24%2013.69-10.65%2031.49-7.44%2047.69s10.59%2031.23%2017.9%2046L980.88%20318'/%3e%3cpath%20class='cls-8'%20d='M927.43%20117c-2.9%201.22-5%203.74-6.8%206.35a52.2%2052.2%200%2000-7.81%2019.42c9.76%2024.55%2019.89%2044.56%2036.24%2036.81%2013.36-6.33%2012.45-19.61%206.72-37q-3.35-5.87-6.73-11.71c-4.72-8.1-12.96-17.46-21.62-13.87z'/%3e%3cpath%20class='cls-9'%20d='M1031.05%20291.55a1663.13%201663.13%200%2000-82-160.65c-4.72-8.13-13-17.49-21.62-13.86-2.9%201.22-5%203.74-6.8%206.35-9.24%2013.69-10.65%2031.49-7.44%2047.69s10.59%2031.23%2017.9%2046L980.88%20318'/%3e%3c/g%3e%3cg%20id='check-3'%20data-name='check'%3e%3ccircle%20class='cls-11'%20cx='639.76'%20cy='212.54'%20r='27.6'/%3e%3cpath%20class='cls-3'%20d='M647.46%20200.05h9.1l-11.91%2014.5%209.46%208.75-7%204.2-8.06-8.86-9.45%206.3h-7.27l13.57-11.16-9.98-10.09%208.4-1.75%205.13%208.23%208.01-10.12z'/%3e%3c/g%3e%3c/g%3e%3c/g%3e%3c/svg%3e",c="data:image/svg+xml,%3csvg%20xmlns='http://www.w3.org/2000/svg'%20viewBox='0%200%201700%20500'%3e%3cdefs%3e%3cstyle%3e.cls-1{fill:%2397aad8}.cls-2{fill:%23fff}.cls-3{fill:%23d5e2f5}.cls-4{fill:%235971b5}.cls-6{fill:%23ee76ab}.cls-7{fill:%23f8c8dd;stroke:%23d23c6f;stroke-miterlimit:10}.cls-8{fill:%23d23c6f}%3c/style%3e%3c/defs%3e%3cg%20id='snapshot'%3e%3crect%20class='cls-1'%20x='96.64'%20y='82'%20width='710.79'%20height='321.65'%20rx='19.09'/%3e%3cpath%20class='cls-2'%20d='M126.17%20112.28h258.38v258.38H126.17zM519.66%20112.28h258.38v258.38H519.66z'/%3e%3crect%20class='cls-3'%20x='138.67'%20y='124.93'%20width='231.82'%20height='200.19'%20rx='7.25'/%3e%3cpath%20class='cls-4'%20d='M363.24%20125.43a6.75%206.75%200%20016.75%206.75v185.68a6.76%206.76%200%2001-6.75%206.76H145.92a6.76%206.76%200%2001-6.75-6.76V132.18a6.75%206.75%200%20016.75-6.75h217.32m0-1H145.92a7.76%207.76%200%2000-7.75%207.75v185.68a7.77%207.77%200%20007.75%207.76h217.32a7.76%207.76%200%20007.75-7.76V132.18a7.75%207.75%200%2000-7.75-7.75z'/%3e%3cpath%20class='cls-1'%20d='M159.41%20144.09h68.69v180.52h-68.69zM236.72%20144.09h119.16v61.4H236.72zM236.72%20210.77h119.16v14.25H236.72zM236.72%20230.3h119.16v14.25H236.72zM236.72%20249.83h119.16v14.25H236.72zM236.72%20269.37h119.16v34.18H236.72zM236.72%20308.83h119.16v14.25H236.72z'/%3e%3crect%20class='cls-3'%20x='532.94'%20y='124.93'%20width='231.82'%20height='200.19'%20rx='7.25'/%3e%3cpath%20class='cls-4'%20d='M757.51%20125.43a6.75%206.75%200%20016.75%206.75v185.68a6.76%206.76%200%2001-6.75%206.76H540.19a6.76%206.76%200%2001-6.75-6.76V132.18a6.75%206.75%200%20016.75-6.75h217.32m0-1H540.19a7.75%207.75%200%2000-7.75%207.75v185.68a7.76%207.76%200%20007.75%207.76h217.32a7.77%207.77%200%20007.75-7.76V132.18a7.76%207.76%200%2000-7.75-7.75z'/%3e%3cpath%20class='cls-1'%20d='M553.68%20144.09h68.69v180.52h-68.69zM630.99%20144.09h119.16v61.4H630.99zM630.99%20210.77h119.16v14.25H630.99zM630.99%20230.3h119.16v14.25H630.99zM630.99%20249.83h119.16v14.25H630.99zM630.99%20269.37h119.16v34.18H630.99zM630.99%20308.83h119.16v14.25H630.99z'/%3e%3cg%20id='check'%3e%3ccircle%20cx='114.12'%20cy='419.45'%20r='48.61'%20fill='%23338846'/%3e%3cpath%20class='cls-2'%20d='M130.56%20386.13l11.49%204.3-25%2055.12-35.24-17.24%209.99-6.7%2020.13%207.29%2018.63-42.77z'/%3e%3c/g%3e%3crect%20class='cls-6'%20x='894.97'%20y='82'%20width='710.79'%20height='321.65'%20rx='19.09'/%3e%3cpath%20class='cls-2'%20d='M924.5%20112.28h258.38v258.38H924.5z'/%3e%3crect%20class='cls-7'%20x='937.5'%20y='125.43'%20width='230.82'%20height='199.19'%20rx='6.75'/%3e%3cpath%20class='cls-2'%20d='M1317.99%20112.28h258.38v258.38h-258.38z'/%3e%3cpath%20class='cls-6'%20d='M957.74%20144.09h68.69v180.52h-68.69zM1035.05%20144.09h119.16v61.4h-119.16zM1035.05%20210.77h119.16v14.25h-119.16zM1035.05%20230.3h119.16v14.25h-119.16zM1035.05%20249.83h119.16v14.25h-119.16zM1035.05%20269.37h119.16v34.18h-119.16zM1035.05%20308.83h119.16v14.25h-119.16z'/%3e%3cg%20id='check-2'%20data-name='check'%3e%3crect%20class='cls-7'%20x='1331.77'%20y='125.43'%20width='230.82'%20height='199.19'%20rx='6.75'/%3e%3cpath%20class='cls-8'%20d='M1352.01%20144.09h68.69v180.52h-68.69z'/%3e%3cpath%20class='cls-6'%20d='M1429.32%20210.77h119.16v14.25h-119.16zM1429.32%20230.3h119.16v14.25h-119.16zM1429.32%20249.83h119.16v14.25h-119.16z'/%3e%3cpath%20class='cls-8'%20d='M1429.32%20269.37h119.16v34.18h-119.16z'/%3e%3cpath%20class='cls-6'%20d='M1429.32%20308.83h119.16v14.25h-119.16z'/%3e%3ccircle%20cx='912.39'%20cy='419.26'%20r='48.61'%20fill='%23a21732'/%3e%3cpath%20class='cls-2'%20d='M925.95%20397.25h16.04l-20.97%2025.54%2016.65%2015.42-12.33%207.41L911.15%20430l-16.65%2011.1h-12.8l23.9-19.67-17.58-17.76%2014.8-3.08%209.02%2014.49%2014.11-17.83z'/%3e%3c/g%3e%3c/g%3e%3c/svg%3e",l="/assets/p_tests-e2e.zzEG5Lpm.svg",x=JSON.parse('{"title":"Teste","description":"","frontmatter":{},"headers":[],"relativePath":"docs/testing-overview.md","filePath":"docs/testing-overview.md"}'),d={name:"docs/testing-overview.md"},p=i("",93),h=[p];function u(m,k,g,E,v,f){return a(),s("div",null,h)}const b=e(d,[["render",u]]);export{x as __pageData,b as default}; diff --git a/vitepress/docs/.vitepress/dist/assets/docs_the-new-architecture_landing-page.md.CiPTxvE2.js b/vitepress/docs/.vitepress/dist/assets/docs_the-new-architecture_landing-page.md.CiPTxvE2.js new file mode 100644 index 0000000..d6014d0 --- /dev/null +++ b/vitepress/docs/.vitepress/dist/assets/docs_the-new-architecture_landing-page.md.CiPTxvE2.js @@ -0,0 +1,74 @@ +import{_ as i,c as e,o as t,a4 as s,m as a}from"./chunks/framework.nQaBHiNx.js";const n="/assets/async-on-layout.BrDeWvQE.gif",r="/assets/sync-use-layout-effect.DiHT__9B.gif",o="/assets/legacy-renderer.-pdigmji.gif",l="/assets/react18-renderer.J5U3e7Q-.gif",p="/assets/with-transitions.BF9oM46H.gif",h="/assets/without-transitions.lHrdMMJM.gif",B=JSON.parse('{"title":"Sobre a Nova Arquitetura","description":"","frontmatter":{},"headers":[],"relativePath":"docs/the-new-architecture/landing-page.md","filePath":"docs/the-new-architecture/landing-page.md"}'),d={name:"docs/the-new-architecture/landing-page.md"},k=s(`

Sobre a Nova Arquitetura

Informações

Se você está procurando os guias da Nova Arquitetura, eles foram transferidos para o grupo de trabalho.

Desde 2018, a equipe do React Native vem redesenhando os principais componentes internos do React Native para permitir que os desenvolvedores criem experiências de maior qualidade. Em 2024, esta versão do React Native foi comprovada em escala e potencializa aplicativos de produção da Meta.

O termo Nova Arquitetura refere-se tanto à nova arquitetura de framework quanto ao trabalho para trazê-la para o código aberto.

A nova arquitetura está disponível para aceitação experimental a partir do React Native 0.68 com melhorias contínuas em cada liberação. A equipe agora está trabalhando para tornar esta a experiência padrão para o ecossistema de código aberto React Native.

Por que uma nova arquitetura?

Depois de muitos anos construindo com React Native, a equipe identificou um conjunto de limitações que impediam os desenvolvedores de criar certas experiências com alto nível de polimento. Essas limitações foram fundamentais para o design existente do framework, então a Nova Arquitetura começou como um investimento no futuro do React Native.

A Nova Arquitetura desbloqueia capacidades e melhorias que eram impossíveis na arquitetura legada.

Layout e efeitos síncronos

Construir experiências de UI adaptáveis ​​geralmente requer medir o tamanho e a posição de suas visualizações e ajustar o layout.

Hoje, você usaria o evento onLayout para obter as informações de layout de uma visualização e fazer quaisquer ajustes. No entanto, as atualizações de estado dentro do retorno de chamada onLayout podem ser aplicadas após pintar a renderização anterior. Isso significa que os usuários podem ver estados intermediários ou saltos visuais entre a renderização do layout inicial e a resposta às medições do layout.

Com a Nova Arquitetura, podemos evitar totalmente esse problema com acesso síncrono às informações de layout e atualizações devidamente programadas, de modo que nenhum estado intermediário fique visível para os usuários.

Exemplo: renderizando uma dica de ferramenta

Medir e colocar uma dica de ferramenta acima de uma visualização nos permite mostrar o que a renderização síncrona desbloqueia. A dica de ferramenta precisa saber a posição de sua visualização de destino para determinar onde ela deve ser renderizada.

Na arquitetura atual, usamos onLayout para obter as medidas da visualização e então atualizar o posicionamento da dica de ferramenta com base em onde a visualização está.

jsx
function ViewWithTooltip() {
+  // ...
+  // Pegamos as informações do layout e passamos para o ToolTip se posicionar
+  const onLayout = React.useCallback(event => {
+    targetRef.current?.measureInWindow((x, y, width, height) => {
+      // Não é garantido que esta atualização de estado seja executada no mesmo commit
+      // Isso resulta em um "salto" visual conforme a dica de ferramenta se reposiciona
+      setTargetRect({x, y, width, height});
+    });
+  }, []);
+
+  return (
+    <>
+      <View ref={targetRef} onLayout={onLayout}>
+        <Text>Some content that renders a tooltip above</Text>
+      </View>
+      <Tooltip targetRect={targetRect} />
+    </>
+  );
+}

Com a Nova Arquitetura, podemos usar useLayoutEffect para medir e aplicar atualizações de layout de forma síncrona em um único commit, evitando o "salto" visual.

jsx
function ViewWithTooltip() {
+  // ...
+
+  useLayoutEffect(() => {
+    // A medição e atualização de estado para \`targetRect\` acontece em um único commit
+    // permitindo que o ToolTip se posicione sem pinturas intermediárias
+    targetRef.current?.measureInWindow((x, y, width, height) => {
+      setTargetRect({x, y, width, height});
+    });
+  }, [setTargetRect]);
+
+  return (
+    <>
+      <View ref={targetRef}>
+        <Text>Some content that renders a tooltip above</Text>
+      </View>
+      <Tooltip targetRect={targetRect} />
+    </>
+  );
+}
`,18),c=a("div",{className:"two-images"},[a("figure",null,[a("img",{src:n,class:"rounded-shadow",alt:"Uma visualização que se move para os cantos da viewport e para o centro com uma dica de ferramenta renderizada acima ou abaixo dela. A dica de ferramenta é renderizada após um pequeno atraso após a visualização se mover"}),a("figcaption",null," Medição e renderização assíncrona da dica de ferramenta. ")]),a("figure",null,[a("img",{src:r,class:"rounded-shadow",alt:"Uma visualização que está se movendo para os cantos da janela de visualização e centralizada com uma dica de ferramenta renderizada acima ou abaixo dela. A visualização e a dica se movem em uníssono."}),a("figcaption",null," Medição síncrona e renderização da dica de ferramenta. ")])],-1),u=s('

Suporte para renderização e recursos simultâneos

A nova arquitetura suporta renderização simultânea e recursos fornecidos no React 18 e além. Agora você pode usar recursos como Suspense para busca de dados, Transições e outras novas APIs React em seu código React Native, adaptando ainda mais as bases de código e os conceitos entre o desenvolvimento web e React nativo.

O renderizador simultâneo também traz melhorias prontas para uso, como lote automático, que reduz novas renderizações no React.

Com a nova arquitetura, você obterá lotes automáticos com o renderizador React 18.

Neste exemplo, um controle deslizante especifica quantos blocos serão renderizados. Arrastar o controle deslizante de 0 a 1000 iniciará uma rápida sucessão de atualizações de estado e novas renderizações.

Ao comparar os renderizadores para o mesmo código, você pode notar visualmente que o renderizador fornece uma UI mais suave, com menos atualizações intermediárias da UI. As atualizações de estado de manipuladores de eventos nativos, como este componente Slider nativo, agora são agrupadas em lote.

',6),E=a("div",{className:"two-images"},[a("figure",null,[a("img",{src:o,class:"rounded-shadow",alt:"Uma visualização que se move para os cantos da viewport e para o centro com uma dica de ferramenta renderizada acima ou abaixo dela. A dica de ferramenta é renderizada após um pequeno atraso após a visualização se mover"}),a("figcaption",null," Renderizando atualizações de estado frequentes com renderizador legado. ")]),a("figure",null,[a("img",{src:l,class:"rounded-shadow",alt:"Uma visualização que está se movendo para os cantos da janela de visualização e centralizada com uma dica de ferramenta renderizada acima ou abaixo dela. A visualização e a dica se movem em uníssono."}),a("figcaption",null," Renderizando atualizações de estado frequentes com o renderizador React 18. ")])],-1),m=s(`

Novos recursos simultâneos, como Transições, permitem expressar a prioridade das atualizações da IU. Marcar uma atualização como de prioridade mais baixa informa ao React que ele pode "interromper" a renderização da atualização para lidar com atualizações de prioridade mais alta para garantir uma experiência de usuário responsiva onde for importante.

Exemplo: Usando startTransition

Podemos aproveitar o exemplo anterior para mostrar como as transições podem interromper a renderização em andamento para lidar com uma atualização de estado mais recente.

Envolvemos a atualização do estado do número do bloco com startTransition para indicar que a renderização dos blocos pode ser interrompida. startTransition também fornece um sinalizador isPending para nos informar quando a transição for concluída.

jsx
function TileSlider({value, onValueChange}) {
+  const [isPending, startTransition] = useTransition();
+
+  return (
+    <>
+      <View>
+        <Text>
+          Render {value} Tiles
+        </Text>
+        <ActivityIndicator animating={isPending} />
+      </View>
+      <Slider
+        value={1}
+        minimumValue={1}
+        maximumValue={1000}
+        step={1}
+        onValueChange={newValue => {
+          startTransition(() => {
+            onValueChange(newValue);
+          });
+        }}
+      />
+    </>
+  );
+}
+
+function ManyTiles() {
+  const [value, setValue] = useState(1);
+  const tiles = generateTileViews(value);
+  return (
+      <TileSlider onValueChange={setValue} value={value} />
+      <View>
+        {tiles}
+      </View>
+  )
+}

Você notará que com as atualizações frequentes em uma transição, o React renderiza menos estados intermediários porque ele deixa de renderizar o estado assim que ele se torna obsoleto. Em comparação, sem transições, mais estados intermediários são renderizados. Ambos os exemplos ainda usam lote automático. Ainda assim, as transições dão ainda mais poder aos desenvolvedores para agrupar renderizações em andamento.

`,6),g=a("div",{className:"two-images"},[a("figure",null,[a("img",{src:p,class:"rounded-shadow"}),a("figcaption",null," Renderização de blocos com transições para interromper renderizações em andamento de estado obsoleto. ")]),a("figure",null,[a("img",{src:h,class:"rounded-shadow"}),a("figcaption",null," Renderizar blocos sem marcá-los como transição. ")])],-1),y=s('

JavaScript rápido/interface nativa

A Nova Arquitetura remove a ponte assíncrona entre JavaScript e nativo e a substitui pela Interface JavaScript (JSI). JSI é uma interface que permite ao JavaScript manter uma referência a um objeto C++ e vice-versa. Com uma referência de memória, você pode invocar métodos diretamente sem custos de serialização.

JSI permite que VisionCamera, uma biblioteca de câmeras popular para React Native, processe quadros em tempo real. Os buffers de quadros típicos têm 10 MB, o que equivale a aproximadamente 1 GB de dados por segundo, dependendo da taxa de quadros. Em comparação com os custos de serialização da ponte, o JSI lida com essa quantidade de dados de interface com facilidade. JSI pode expor outros tipos complexos baseados em instâncias, como bancos de dados, imagens, amostras de áudio, etc.

A adoção de JSI na Nova Arquitetura remove essa classe de trabalho de serialização de toda interoperabilidade JavaScript nativa. Isso inclui inicializar e renderizar novamente os componentes principais nativos, como View e Text. Você pode ler mais sobre nossa investigação em desempenho de renderização na Nova Arquitetura e nos benchmarks aprimorados que medimos.

Saber mais

Para conseguir isso, a Nova Arquitetura teve que refatorar várias partes da infraestrutura React Native. Para saber mais sobre o refatorador e outros benefícios que ele traz, confira a documentação no grupo de trabalho Nova Arquitetura.

O que posso esperar ao ativar a Nova Arquitetura?

Embora a Nova Arquitetura habilite esses recursos e melhorias, habilitar a Nova Arquitetura para seu aplicativo ou biblioteca pode não melhorar imediatamente o desempenho ou a experiência do usuário.

Por exemplo, seu código pode precisar de refatoração para aproveitar novos recursos, como efeitos de layout síncronos ou recursos simultâneos. Embora o JSI minimize a sobrecarga entre o JavaScript e a memória nativa, a serialização de dados pode não ter sido um gargalo para o desempenho do seu aplicativo.

Habilitar a Nova Arquitetura em seu aplicativo ou biblioteca é optar pelo futuro do React Native.

A equipe está pesquisando e desenvolvendo ativamente novos recursos que a Nova Arquitetura desbloqueia. Por exemplo, o alinhamento da web é uma área ativa de exploração na Meta que será enviada para o ecossistema de código aberto React Native.

Você pode acompanhar e contribuir em nosso repositório dedicado discussões e propostas.

Devo usar a Nova Arquitetura hoje?

Hoje, a Nova Arquitetura é considerada experimental e continuamos a refinar a compatibilidade com versões anteriores para uma melhor experiência de adoção.

A equipe planeja habilitar a Nova Arquitetura por padrão em uma próxima versão do React Native até o final de 2024.

Nossa orientação é a seguinte

  • Para a maioria dos aplicativos de produção, não recomendamos ativar a Nova Arquitetura hoje. Esperar pelo lançamento oficial oferecerá a melhor experiência.
  • Se você mantém uma biblioteca React Native, recomendamos habilitá-la e verificar se seus casos de uso estão cobertos. Você pode encontrar as instruções aqui.

Habilite a nova arquitetura

Se você estiver interessado em usar a experiência da Nova Arquitetura como dogfood, você pode encontrar instruções em nosso grupo de trabalho dedicado. O grupo de trabalho da Nova Arquitetura é um espaço dedicado para suporte e coordenação para a adoção da Nova Arquitetura e onde a equipe publica atualizações regulares.

',20),v=[k,c,u,E,m,g,y];function F(f,b,q,A,C,_){return t(),e("div",null,v)}const x=i(d,[["render",F]]);export{B as __pageData,x as default}; diff --git a/vitepress/docs/.vitepress/dist/assets/docs_the-new-architecture_landing-page.md.CiPTxvE2.lean.js b/vitepress/docs/.vitepress/dist/assets/docs_the-new-architecture_landing-page.md.CiPTxvE2.lean.js new file mode 100644 index 0000000..2dad1fb --- /dev/null +++ b/vitepress/docs/.vitepress/dist/assets/docs_the-new-architecture_landing-page.md.CiPTxvE2.lean.js @@ -0,0 +1 @@ +import{_ as i,c as e,o as t,a4 as s,m as a}from"./chunks/framework.nQaBHiNx.js";const n="/assets/async-on-layout.BrDeWvQE.gif",r="/assets/sync-use-layout-effect.DiHT__9B.gif",o="/assets/legacy-renderer.-pdigmji.gif",l="/assets/react18-renderer.J5U3e7Q-.gif",p="/assets/with-transitions.BF9oM46H.gif",h="/assets/without-transitions.lHrdMMJM.gif",B=JSON.parse('{"title":"Sobre a Nova Arquitetura","description":"","frontmatter":{},"headers":[],"relativePath":"docs/the-new-architecture/landing-page.md","filePath":"docs/the-new-architecture/landing-page.md"}'),d={name:"docs/the-new-architecture/landing-page.md"},k=s("",18),c=a("div",{className:"two-images"},[a("figure",null,[a("img",{src:n,class:"rounded-shadow",alt:"Uma visualização que se move para os cantos da viewport e para o centro com uma dica de ferramenta renderizada acima ou abaixo dela. A dica de ferramenta é renderizada após um pequeno atraso após a visualização se mover"}),a("figcaption",null," Medição e renderização assíncrona da dica de ferramenta. ")]),a("figure",null,[a("img",{src:r,class:"rounded-shadow",alt:"Uma visualização que está se movendo para os cantos da janela de visualização e centralizada com uma dica de ferramenta renderizada acima ou abaixo dela. A visualização e a dica se movem em uníssono."}),a("figcaption",null," Medição síncrona e renderização da dica de ferramenta. ")])],-1),u=s("",6),E=a("div",{className:"two-images"},[a("figure",null,[a("img",{src:o,class:"rounded-shadow",alt:"Uma visualização que se move para os cantos da viewport e para o centro com uma dica de ferramenta renderizada acima ou abaixo dela. A dica de ferramenta é renderizada após um pequeno atraso após a visualização se mover"}),a("figcaption",null," Renderizando atualizações de estado frequentes com renderizador legado. ")]),a("figure",null,[a("img",{src:l,class:"rounded-shadow",alt:"Uma visualização que está se movendo para os cantos da janela de visualização e centralizada com uma dica de ferramenta renderizada acima ou abaixo dela. A visualização e a dica se movem em uníssono."}),a("figcaption",null," Renderizando atualizações de estado frequentes com o renderizador React 18. ")])],-1),m=s("",6),g=a("div",{className:"two-images"},[a("figure",null,[a("img",{src:p,class:"rounded-shadow"}),a("figcaption",null," Renderização de blocos com transições para interromper renderizações em andamento de estado obsoleto. ")]),a("figure",null,[a("img",{src:h,class:"rounded-shadow"}),a("figcaption",null," Renderizar blocos sem marcá-los como transição. ")])],-1),y=s("",20),v=[k,c,u,E,m,g,y];function F(f,b,q,A,C,_){return t(),e("div",null,v)}const x=i(d,[["render",F]]);export{B as __pageData,x as default}; diff --git a/vitepress/docs/.vitepress/dist/assets/docs_timers.md.OY67ndDu.js b/vitepress/docs/.vitepress/dist/assets/docs_timers.md.OY67ndDu.js new file mode 100644 index 0000000..04b0044 --- /dev/null +++ b/vitepress/docs/.vitepress/dist/assets/docs_timers.md.OY67ndDu.js @@ -0,0 +1,7 @@ +import{_ as e,c as a,o as s,a4 as o}from"./chunks/framework.nQaBHiNx.js";const k=JSON.parse('{"title":"Temporizadores","description":"","frontmatter":{},"headers":[],"relativePath":"docs/timers.md","filePath":"docs/timers.md"}'),i={name:"docs/timers.md"},t=o(`

Temporizadores

Os temporizadores são uma parte importante de um aplicativo e o React Native implementa os temporizadores do navegador.

Temporizadores

  • setTimeout, clearTimeout
  • setInterval, clearInterval
  • setImmediate, clearImmediate
  • requestAnimationFrame, cancelAnimationFrame

requestAnimationFrame(fn) não é o mesmo que setTimeout(fn, 0) - o primeiro será acionado depois que todos os quadros forem liberados, enquanto o último será acionado o mais rápido possível (mais de 1000x por segundo em um iPhone 5S).

setImmediate é executado no final do bloco de execução JavaScript atual, logo antes de enviar a resposta em lote de volta ao nativo. Observe que se você chamar setImmediate dentro de um retorno de chamada setImmediate, ele será executado imediatamente, não retornará ao nativo no meio.

A implementação do Promise usa setImmediate como implementação de assincronicidade.

OBSERVAÇÃO Ao depurar no Android, se os tempos entre o depurador e o dispositivo variaram; coisas como animação, comportamento de eventos, etc., podem não funcionar corretamente ou os resultados podem não ser precisos. Corrija isso executando adb shell "date date +%m%d%H%M%Y.%S%3N" em sua máquina depuradora. O acesso root é necessário para uso em dispositivos reais.

Gerenciador de interação

Uma razão pela qual aplicativos nativos bem construídos parecem tão suaves é que evitam operações caras durante interações e animações. No React Native, atualmente temos uma limitação de que há apenas um único thread de execução JS, mas você pode usar o InteractionManager para garantir que o trabalho de longa execução seja programado para começar após a conclusão de quaisquer interações/animações.

Os aplicativos podem agendar tarefas para execução após interações como o seguinte:

js
InteractionManager.runAfterInteractions(() => {
+  // ...tarefa síncrona de longa duração...
+});

Compare isso com outras alternativas de agendamento:

  • requestAnimationFrame(): para código que anima uma visualização ao longo do tempo.
  • setImmediate/setTimeout/setInterval(): execute o código mais tarde, observe que isso pode atrasar as animações.
  • runAfterInteractions(): executa o código posteriormente, sem atrasar as animações ativas.

O sistema de tratamento de toque considera um ou mais toques ativos como uma 'interação' e atrasará os retornos de chamada runAfterInteractions() até que todos os toques tenham terminado ou sejam cancelados.

O InteractionManager também permite que aplicativos registrem animações criando um 'identificador' de interação no início da animação e limpando-o após a conclusão:

js
const handle = InteractionManager.createInteractionHandle();
+// executar animação... (as tarefas \`runAfterInteractions\` estão na fila)
+// mais tarde, na conclusão da animação:
+InteractionManager.clearInteractionHandle(handle);
+// tarefas enfileiradas serão executadas se todos os identificadores forem apagados
`,17),n=[t];function r(d,c,l,p,m,u){return s(),a("div",null,n)}const g=e(i,[["render",r]]);export{k as __pageData,g as default}; diff --git a/vitepress/docs/.vitepress/dist/assets/docs_timers.md.OY67ndDu.lean.js b/vitepress/docs/.vitepress/dist/assets/docs_timers.md.OY67ndDu.lean.js new file mode 100644 index 0000000..fb70c02 --- /dev/null +++ b/vitepress/docs/.vitepress/dist/assets/docs_timers.md.OY67ndDu.lean.js @@ -0,0 +1 @@ +import{_ as e,c as a,o as s,a4 as o}from"./chunks/framework.nQaBHiNx.js";const k=JSON.parse('{"title":"Temporizadores","description":"","frontmatter":{},"headers":[],"relativePath":"docs/timers.md","filePath":"docs/timers.md"}'),i={name:"docs/timers.md"},t=o("",17),n=[t];function r(d,c,l,p,m,u){return s(),a("div",null,n)}const g=e(i,[["render",r]]);export{k as __pageData,g as default}; diff --git a/vitepress/docs/.vitepress/dist/assets/docs_troubleshooting.md.CsjZzp3G.js b/vitepress/docs/.vitepress/dist/assets/docs_troubleshooting.md.CsjZzp3G.js new file mode 100644 index 0000000..0b4fea1 --- /dev/null +++ b/vitepress/docs/.vitepress/dist/assets/docs_troubleshooting.md.CsjZzp3G.js @@ -0,0 +1,9 @@ +import{_ as a,c as e,o as s,a4 as o}from"./chunks/framework.nQaBHiNx.js";const m=JSON.parse('{"title":"Solução de problemas","description":"","frontmatter":{},"headers":[],"relativePath":"docs/troubleshooting.md","filePath":"docs/troubleshooting.md"}'),i={name:"docs/troubleshooting.md"},t=o(`

Solução de problemas

Estes são alguns problemas comuns que você pode encontrar ao configurar o React Native. Se você encontrar algo que não esteja listado aqui, tente pesquisar o problema no GitHub.

Porta já em uso (Port already in use)

O empacotador Metro é executado na porta 8081. Se outro processo já estiver usando essa porta, você poderá encerrar esse processo ou alterar a porta que o empacotador usa.

Encerrando um processo na porta 8081

Execute o seguinte comando para encontrar o ID do processo que está escutando na porta 8081:

bash
sudo lsof -i :8081

Em seguida, execute o seguinte para encerrar o processo:

bash
kill -9 <PID>

No Windows você pode encontrar o processo usando a porta 8081 usando o Monitor de Recursos e interrompê-lo usando o Gerenciador de Tarefas.

Usando uma porta diferente de 8081

Você pode configurar o bundler para usar uma porta diferente de 8081 usando o parâmetro port, na raiz da execução do seu projeto:

bash
npm start -- --port=8088
bash
yarn start --port 8088

Você também precisará atualizar seus aplicativos para carregar o pacote JavaScript da nova porta. Se estiver executando no dispositivo do Xcode, você pode fazer isso atualizando as ocorrências de 8081 para a porta escolhida no arquivo ios/__App_Name__.xcodeproj/project.pbxproj.

Erro de bloqueio NPM

Se você encontrar um erro como npm WARN locking Error: EACCES ao usar o React Native CLI, tente executar o seguinte:

bash
sudo chown -R $USER ~/.npm
+sudo chown -R $USER /usr/local/lib/node_modules

Bibliotecas ausentes para React

Se você adicionou React Native manualmente ao seu projeto, certifique-se de ter incluído todas as dependências relevantes que está usando, como RCTText.xcodeproj, RCTImage.xcodeproj. Em seguida, os binários criados por essas dependências devem ser vinculados ao binário do seu aplicativo. Use a seção Linked Frameworks and Binaries nas configurações do projeto Xcode. Etapas mais detalhadas estão aqui: Vinculando Bibliotecas.

Se você estiver usando CocoaPods, verifique se adicionou React junto com as subespecificações ao Podfile. Por exemplo, se você estivesse usando as APIs <Text />, <Image /> e fetch(), você precisaria adicioná-las em seu Podfile:

pod 'React', :path => '../node_modules/react-native', :subspecs => [
+  'RCTText',
+  'RCTImage',
+  'RCTNetwork',
+  'RCTWebSocket',
+]

Em seguida, certifique-se de ter executado pod install e de que um diretório Pods/ tenha sido criado em seu projeto com o React instalado. CocoaPods irá instruí-lo a usar o arquivo .xcworkspace gerado daqui em diante para poder usar essas dependências instaladas.

React Native não compila ao ser usado como CocoaPod

Existe um plugin CocoaPods chamado cocoapods-fix-react-native que lida com qualquer possível pós-correção do código-fonte devido a diferenças ao usar um gerenciador de dependências.

Lista de argumentos muito longa: falha na expansão do cabeçalho recursivo

Nas configurações de construção do projeto, User Search Header Paths e Header Search Paths são duas configurações que especificam onde o Xcode deve procurar os arquivos de cabeçalho #import especificados no código. Para pods, CocoaPods usa uma matriz padrão de pastas específicas para procurar. Verifique se essa configuração específica não foi substituída e se nenhuma das pastas configuradas é muito grande. Se uma das pastas for grande, o Xcode tentará pesquisar recursivamente o diretório inteiro e gerará o erro acima em algum momento.

Para reverter as configurações de compilação dos User Search Header PathseHeader Search Paths\` para seus padrões definidos pelo CocoaPods - selecione a entrada no painel Build Settings e clique em excluir. Isso removerá a substituição personalizada e retornará aos padrões do CocoaPod.

Não há transportes disponíveis

React Native implementa um polyfill para WebSockets. Esses polyfills são inicializados como parte do módulo react-native que você inclui em seu aplicativo por meio do import React from 'react'. Se você carregar outro módulo que requer WebSockets, como Firebase, certifique-se de carregá-lo/solicitá-lo após o React Native:

jsx
import React from 'react';
+import Firebase from 'firebase';

Exceção sem resposta do comando Shell

Se você encontrar uma exceção ShellCommandUnresponsiveException como:

Execution failed for task ':app:installDebug'.
+  com.android.builder.testing.api.DeviceException: com.android.ddmlib.ShellCommandUnresponsiveException

Tente fazer o downgrade da sua versão do Gradle para 1.2.3 em android/build.gradle.

inicialização travada do react-native

Se você tiver problemas em que a execução do npx react-native init trava em seu sistema, tente executá-lo novamente no modo detalhado e consulte #2797 para causas comuns:

bash
npx react-native init --verbose

Quando você está depurando um processo ou precisa saber um pouco mais sobre o erro que está sendo gerado, você pode querer usar a opção detalhada para gerar mais logs e informações para resolver seu problema.

Execute o seguinte comando no diretório raiz do seu projeto.

npm
bash
npm run android -- --verbose
yarn
bash
yarn android --verbose

Não é possível iniciar o gerenciador de pacotes react-native (no Linux)

Caso 1: Erro "código":"ENOSPC","errno":"ENOSPC"

Problema causado pelo número de diretórios que o inotify (usado pelo watchman no Linux) pode monitorar. Para resolver isso, execute este comando na janela do seu terminal:

bash
echo fs.inotify.max_user_watches=582222 | sudo tee -a /etc/sysctl.conf && sudo sysctl -p

Error: spawnSync ./gradlew EACCES

Se você tiver um problema em que a execução do npm run android ou yarn android no macOS gera o erro acima, tente executar o comando sudo chmod +x android/gradlew para tornar os arquivos gradlew em executáveis.

`,49),r=[t];function n(d,p,c,l,h,u){return s(),e("div",null,r)}const g=a(i,[["render",n]]);export{m as __pageData,g as default}; diff --git a/vitepress/docs/.vitepress/dist/assets/docs_troubleshooting.md.CsjZzp3G.lean.js b/vitepress/docs/.vitepress/dist/assets/docs_troubleshooting.md.CsjZzp3G.lean.js new file mode 100644 index 0000000..e4c2add --- /dev/null +++ b/vitepress/docs/.vitepress/dist/assets/docs_troubleshooting.md.CsjZzp3G.lean.js @@ -0,0 +1 @@ +import{_ as a,c as e,o as s,a4 as o}from"./chunks/framework.nQaBHiNx.js";const m=JSON.parse('{"title":"Solução de problemas","description":"","frontmatter":{},"headers":[],"relativePath":"docs/troubleshooting.md","filePath":"docs/troubleshooting.md"}'),i={name:"docs/troubleshooting.md"},t=o("",49),r=[t];function n(d,p,c,l,h,u){return s(),e("div",null,r)}const g=a(i,[["render",n]]);export{m as __pageData,g as default}; diff --git a/vitepress/docs/.vitepress/dist/assets/docs_typescript.md.DgYzLLD4.js b/vitepress/docs/.vitepress/dist/assets/docs_typescript.md.DgYzLLD4.js new file mode 100644 index 0000000..430d264 --- /dev/null +++ b/vitepress/docs/.vitepress/dist/assets/docs_typescript.md.DgYzLLD4.js @@ -0,0 +1,94 @@ +import{_ as s,c as i,o as a,a4 as n}from"./chunks/framework.nQaBHiNx.js";const g=JSON.parse('{"title":"Usando TypeScript","description":"","frontmatter":{},"headers":[],"relativePath":"docs/typescript.md","filePath":"docs/typescript.md"}'),t={name:"docs/typescript.md"},e=n(`

Usando TypeScript

TypeScript é uma linguagem que estende JavaScript adicionando definições de tipo. Novos projetos React Native são direcionados ao TypeScript por padrão, mas também oferecem suporte a JavaScript e Flow.

Introdução ao TypeScript

Novos projetos criados pela CLI React Native ou modelos populares como Ignite usarão TypeScript por padrão.

O TypeScript também pode ser usado com o Expo, que mantém modelos TypeScript, ou solicitará que você instale e configure automaticamente o TypeScript quando um arquivo .ts ou .tsx for adicionado ao seu projeto.

bash
npx create-expo-app --template

Adicionando TypeScript a um projeto existente

  1. Adicione plug-ins TypeScript, tipos e ESLint ao seu projeto.
bash
npm install -D @tsconfig/react-native @types/jest @types/react @types/react-test-renderer typescript
bash
yarn add --dev @tsconfig/react-native @types/jest @types/react @types/react-test-renderer typescript

OBSERVAÇÃO

Este comando adiciona a versão mais recente de cada dependência. As versões podem precisar ser alteradas para corresponder aos pacotes existentes usados pelo seu projeto. Você pode usar uma ferramenta como React Native Upgrade Helper para ver as versões fornecidas pelo React Native.

  1. Adicione um arquivo de configuração TypeScript. Crie um tsconfig.json na raiz do seu projeto:
json
{
+  "extends": "@tsconfig/react-native/tsconfig.json"
+}
  1. Renomeie um arquivo JavaScript para *.tsx

ATENÇÃO

Você deve deixar o arquivo de ponto de entrada ./index.js como está, caso contrário, poderá ter problemas ao agrupar uma construção de produção.

  1. Execute o yarn tsc para verificar o tipo de seus novos arquivos TypeScript.

Usando JavaScript em vez de TypeScript

O React Native padroniza novos aplicativos para TypeScript, mas JavaScript ainda pode ser usado. Arquivos com extensão .jsx são tratados como JavaScript em vez de TypeScript e não serão verificados. Módulos JavaScript ainda podem ser importados por módulos TypeScript, junto com o inverso.

Como funcionam o TypeScript e o React Native

Pronto para uso, os códigos TypeScript são transformados pelo Babel durante o empacotamento. Recomendamos que você use o compilador TypeScript apenas para verificação de tipo. Este é o comportamento padrão do tsc para aplicativos recém-criados. Se você tiver código TypeScript existente sendo portado para React Native, há uma ou duas advertências ao usar Babel em vez de TypeScript.

Qual é a aparência do React Native + TypeScript

Você pode fornecer uma interface para Props e State de um componente React via React.Component<Props, State> que fornecerá verificação de tipo e preenchimento automático do editor ao trabalhar com esse componente em JSX.

tsx
// components/Hello.tsx
+
+import React from 'react';
+import {Button, StyleSheet, Text, View} from 'react-native';
+
+export type Props = {
+  name: string;
+  baseEnthusiasmLevel?: number;
+};
+
+const Hello: React.FC<Props> = ({
+  name,
+  baseEnthusiasmLevel = 0,
+}) => {
+  const [enthusiasmLevel, setEnthusiasmLevel] = React.useState(
+    baseEnthusiasmLevel,
+  );
+
+  const onIncrement = () =>
+    setEnthusiasmLevel(enthusiasmLevel + 1);
+  const onDecrement = () =>
+    setEnthusiasmLevel(
+      enthusiasmLevel > 0 ? enthusiasmLevel - 1 : 0,
+    );
+
+  const getExclamationMarks = (numChars: number) =>
+    numChars > 0 ? Array(numChars + 1).join('!') : '';
+
+  return (
+    <View style={styles.container}>
+      <Text style={styles.greeting}>
+        Hello {name}
+        {getExclamationMarks(enthusiasmLevel)}
+      </Text>
+      <View>
+        <Button
+          title="Increase enthusiasm"
+          accessibilityLabel="increment"
+          onPress={onIncrement}
+          color="blue"
+        />
+        <Button
+          title="Decrease enthusiasm"
+          accessibilityLabel="decrement"
+          onPress={onDecrement}
+          color="red"
+        />
+      </View>
+    </View>
+  );
+};
+
+const styles = StyleSheet.create({
+  container: {
+    flex: 1,
+    alignItems: 'center',
+    justifyContent: 'center',
+  },
+  greeting: {
+    fontSize: 20,
+    fontWeight: 'bold',
+    margin: 16,
+  },
+});
+
+export default Hello;

Você pode explorar mais a sintaxe no playground TypeScript.

Onde encontrar conselhos úteis

Usando aliases de caminho personalizados com TypeScript

Para usar aliases de caminho personalizados com TypeScript, você precisa definir os aliases de caminho para funcionarem tanto no Babel quanto no TypeScript. Veja como:

  1. Edite seu tsconfig.json para ter seus mapeamentos de caminho personalizados. Defina qualquer coisa na raiz de src para estar disponível sem nenhuma referência de caminho anterior e permita que qualquer arquivo de teste seja acessado usando tests/File.tsx:
{
+  "extends": "@tsconfig/react-native/tsconfig.json"
+  "extends": "@tsconfig/react-native/tsconfig.json",
+  "compilerOptions": {
+    "baseUrl": ".",
+    "paths": {
+      "*": ["src/*"],
+      "tests": ["tests/*"],
+      "@components/*": ["src/components/*"],
+    },
+  }
+}

Adicione babel-plugin-module-resolver como um pacote de desenvolvimento ao seu projeto:

bash
npm install --save-dev babel-plugin-module-resolver
bash
yarn add --dev babel-plugin-module-resolver

Por fim, configure seu babel.config.js (observe que a sintaxe do seu babel.config.js é diferente do seu tsconfig.json):

json
{
+  presets: ['module:metro-react-native-babel-preset'],
+  plugins: [ 
+    [ 
+        'module-resolver', 
+        { 
+          root: ['./src'], 
+          extensions: ['.ios.js', '.android.js', '.js', '.ts', '.tsx', '.json'], 
+          alias: { 
+          tests: ['./tests/'], 
+          "@components": "./src/components", 
+        } 
+      } 
+    ] 
+  ] 
+}
`,33),p=[e];function l(h,k,r,o,d,c){return a(),i("div",null,p)}const y=s(t,[["render",l]]);export{g as __pageData,y as default}; diff --git a/vitepress/docs/.vitepress/dist/assets/docs_typescript.md.DgYzLLD4.lean.js b/vitepress/docs/.vitepress/dist/assets/docs_typescript.md.DgYzLLD4.lean.js new file mode 100644 index 0000000..5cc64c7 --- /dev/null +++ b/vitepress/docs/.vitepress/dist/assets/docs_typescript.md.DgYzLLD4.lean.js @@ -0,0 +1 @@ +import{_ as s,c as i,o as a,a4 as n}from"./chunks/framework.nQaBHiNx.js";const g=JSON.parse('{"title":"Usando TypeScript","description":"","frontmatter":{},"headers":[],"relativePath":"docs/typescript.md","filePath":"docs/typescript.md"}'),t={name:"docs/typescript.md"},e=n("",33),p=[e];function l(h,k,r,o,d,c){return a(),i("div",null,p)}const y=s(t,[["render",l]]);export{g as __pageData,y as default}; diff --git a/vitepress/docs/.vitepress/dist/assets/docs_upgrading.md.gMgWgGeT.js b/vitepress/docs/.vitepress/dist/assets/docs_upgrading.md.gMgWgGeT.js new file mode 100644 index 0000000..5be905e --- /dev/null +++ b/vitepress/docs/.vitepress/dist/assets/docs_upgrading.md.gMgWgGeT.js @@ -0,0 +1,24 @@ +import{_ as a,c as e,o as s,a4 as o}from"./chunks/framework.nQaBHiNx.js";const v=JSON.parse('{"title":"Atualizando para novas versões","description":"","frontmatter":{},"headers":[],"relativePath":"docs/upgrading.md","filePath":"docs/upgrading.md"}'),i={name:"docs/upgrading.md"},t=o(`

Atualizando para novas versões

A atualização para novas versões do React Native lhe dará acesso a mais APIs, visualizações, ferramentas de desenvolvedor e outras vantagens. A atualização requer um pouco de esforço, mas tentamos torná-la simples para você.

Projetos de expo

Atualizar seu projeto Expo para uma nova versão do React Native requer a atualização das versões dos pacotes react-native, react e expo em seu arquivo package.json. Expo fornece um comando de atualização para lidar com a atualização dessas e de quaisquer outras dependências conhecidas para você. Consulte o passo a passo de atualização do Expo SDK para obter informações atualizadas sobre como atualizar seu projeto.

Projetos React Native

Como os projetos típicos do React Native são essencialmente compostos de um projeto Android, um projeto iOS e um projeto JavaScript, a atualização pode ser bastante complicada. Atualmente, existem duas maneiras de atualizar seu projeto React Native: usando React Native CLI ou manualmente com Upgrade Helper.

CLI React Native

O React Native CLI vem com o comando upgrade que fornece uma operação de uma etapa para atualizar os arquivos de origem com um mínimo de conflitos. Ele usa internamente o projeto rn-diff-purge para descobrir quais arquivos precisam ser criados, removidos ou modificados.

1. Execute o comando upgrade

DICA

O comando upgrade funciona em cima do Git usando git apply com mesclagem de 3 vias, portanto é necessário usar o Git para que isso funcione, se você não usa o Git, mas ainda deseja usar esta solução, você pode verificar como fazer isso na seção Solução de problemas nesta página.

Execute o seguinte comando para iniciar o processo de atualização para a versão mais recente:

bash
npx react-native upgrade

Você pode especificar uma versão do React Native passando um argumento, por exemplo. para atualizar para 0.61.0-rc.0 execute:

bash
npx react-native upgrade 0.61.0-rc.0

O projeto é atualizado usando git apply com mesclagem de 3 vias, pode acontecer que você precise resolver alguns conflitos após terminar.

2. Resolva os conflitos

Os arquivos em conflito incluem delimitadores que deixam bem claro de onde vêm as alterações. Por exemplo:

13B07F951A680F5B00A75B9A /* Release */ = {
+  isa = XCBuildConfiguration;
+  buildSettings = {
+    ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
+<<<<<<< ours
+    CODE_SIGN_IDENTITY = "iPhone Developer";
+    FRAMEWORK_SEARCH_PATHS = (
+      "$(inherited)",
+      "$(PROJECT_DIR)/HockeySDK.embeddedframework",
+      "$(PROJECT_DIR)/HockeySDK-iOS/HockeySDK.embeddedframework",
+    );
+=======
+    CURRENT_PROJECT_VERSION = 1;
+>>>>>>> theirs
+    HEADER_SEARCH_PATHS = (
+      "$(inherited)",
+      /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/include,
+      "$(SRCROOT)/../node_modules/react-native/React/**",
+      "$(SRCROOT)/../node_modules/react-native-code-push/ios/CodePush/**",
+    );

Você pode pensar em "ours" como "sua equipe" e "theirs" como "a equipe de desenvolvimento do React Native".

Ajudante de atualização

O Upgrade Helper é uma ferramenta da web para ajudá-lo na atualização de seus aplicativos, fornecendo o conjunto completo de alterações que ocorrem entre duas versões. Ele também mostra comentários sobre arquivos específicos para ajudar a entender por que essa alteração é necessária.

1. Selecione as versões

Primeiro você precisa selecionar para qual versão deseja atualizar; por padrão, as versões principais mais recentes são selecionadas. Após selecionar você pode clicar no botão "Mostre-me como atualizar".

DICA

as principais atualizações mostrarão uma seção de "useful content" (conteúdo útil) na parte superior com links para ajudá-lo durante a atualização.

2. Atualizar dependências

O primeiro arquivo que aparece é o package.json, é bom atualizar as dependências que estão aparecendo nele. Por exemplo, se react-native e react aparecerem como alterações, você poderá instalá-lo em seu projeto executando yarn add:

bash
# {{VERSION}} e {{REACT_VERSION}} são as versões de lançamento mostradas na comparação
+yarn add react-native@{{VERSION}}
+yarn add react@{{REACT_VERSION}}

3. Atualize seus arquivos de projeto

A nova versão pode conter atualizações para outros arquivos que são gerados quando você executa o npx react-native init. Esses arquivos são listados após package.json na página do Upgrade Helper. Se não houver outras alterações, você só precisará reconstruir o projeto para continuar o desenvolvimento.

Caso haja alterações, você pode atualizá-las manualmente, copiando e colando as alterações na página ou pode fazer isso com o comando de atualização React Native CLI executando:

bash
npx react-native upgrade

Isso verificará seus arquivos em relação ao modelo mais recente e executará o seguinte:

  • Se houver um novo arquivo no modelo, ele será criado.
  • Se um arquivo no modelo for idêntico ao seu arquivo, ele será ignorado.
  • Se um arquivo em seu projeto for diferente do modelo, você será avisado; você tem opções para manter seu arquivo ou substituí-lo pela versão do modelo.

INFORMAÇÕES

Algumas atualizações não serão feitas automaticamente com o React Native CLI e requerem trabalho manual, por exemplo. 0.28 a 0.29 ou 0.56 a 0.57. Certifique-se de verificar as notas de versão ao atualizar para poder identificar quaisquer alterações manuais que seu projeto específico possa exigir.

Solução de problemas

Quero atualizar com React Native CLI, mas não uso Git

Embora seu projeto não precise ser gerenciado pelo sistema de versionamento Git - você pode usar Mercurial, SVN ou nada - você ainda precisará instalar o Git em seu sistema para usar o npx react-native upgrade. O Git também precisará estar disponível no PATH. Se o seu projeto não usa Git, inicialize-o e faça o commit:

bash
git init # Inicialize um repositório Git
+git add . # Prepare todos os arquivos atuais
+git commit -m "Upgrade react-native" # Salva os arquivos atuais em um commit

Depois de terminar a atualização, você pode remover o diretório .git.

Fiz todas as alterações, mas meu aplicativo ainda usa uma versão antiga

Esses tipos de erros geralmente estão relacionados ao cache, é recomendado instalar o react-native-clean-project para limpar todo o cache do seu projeto e então você pode executá-lo novamente.

`,41),n=[t];function r(p,l,c,d,u,h){return s(),e("div",null,n)}const g=a(i,[["render",r]]);export{v as __pageData,g as default}; diff --git a/vitepress/docs/.vitepress/dist/assets/docs_upgrading.md.gMgWgGeT.lean.js b/vitepress/docs/.vitepress/dist/assets/docs_upgrading.md.gMgWgGeT.lean.js new file mode 100644 index 0000000..91ead2d --- /dev/null +++ b/vitepress/docs/.vitepress/dist/assets/docs_upgrading.md.gMgWgGeT.lean.js @@ -0,0 +1 @@ +import{_ as a,c as e,o as s,a4 as o}from"./chunks/framework.nQaBHiNx.js";const v=JSON.parse('{"title":"Atualizando para novas versões","description":"","frontmatter":{},"headers":[],"relativePath":"docs/upgrading.md","filePath":"docs/upgrading.md"}'),i={name:"docs/upgrading.md"},t=o("",41),n=[t];function r(p,l,c,d,u,h){return s(),e("div",null,n)}const g=a(i,[["render",r]]);export{v as __pageData,g as default}; diff --git a/vitepress/docs/.vitepress/dist/assets/docs_using-a-listview.md.ChEZh-qr.js b/vitepress/docs/.vitepress/dist/assets/docs_using-a-listview.md.ChEZh-qr.js new file mode 100644 index 0000000..e9227b8 --- /dev/null +++ b/vitepress/docs/.vitepress/dist/assets/docs_using-a-listview.md.ChEZh-qr.js @@ -0,0 +1,91 @@ +import{_ as s,c as i,o as a,a4 as n}from"./chunks/framework.nQaBHiNx.js";const c=JSON.parse('{"title":"Usando List View","description":"","frontmatter":{},"headers":[],"relativePath":"docs/using-a-listview.md","filePath":"docs/using-a-listview.md"}'),h={name:"docs/using-a-listview.md"},t=n(`

Usando List View

React Native fornece um conjunto de componentes para apresentar listas de dados. Geralmente, você desejará usar FlatList ou SectionList.

O componente FlatList exibe uma lista de rolagem de dados alterados, mas estruturados de forma semelhante. FlatList funciona bem para longas listas de dados, onde o número de itens pode mudar com o tempo. Ao contrário do ScrollView mais genérico, o FlatList renderiza apenas os elementos que estão sendo exibidos na tela no momento, e não todos os elementos de uma vez.

O componente FlatList requer dois props: data e renderItem. data é a fonte de informações da lista. renderItem pega um item da fonte e retorna um componente formatado para renderizar.

Este exemplo cria uma FlatList básica de dados codificados. Cada item nas propriedades de dados é renderizado como um componente Text. O componente FlatListBasics renderiza FlatList e todos os componentes Text.

jsx
import React from 'react';
+import {FlatList, StyleSheet, Text, View} from 'react-native';
+
+const styles = StyleSheet.create({
+  container: {
+    flex: 1,
+    paddingTop: 22,
+  },
+  item: {
+    padding: 10,
+    fontSize: 18,
+    height: 44,
+  },
+});
+
+const FlatListBasics = () => {
+  return (
+    <View style={styles.container}>
+      <FlatList
+        data={[
+          {key: 'Devin'},
+          {key: 'Dan'},
+          {key: 'Dominic'},
+          {key: 'Jackson'},
+          {key: 'James'},
+          {key: 'Joel'},
+          {key: 'John'},
+          {key: 'Jillian'},
+          {key: 'Jimmy'},
+          {key: 'Julie'},
+        ]}
+        renderItem={({item}) => <Text style={styles.item}>{item.key}</Text>}
+      />
+    </View>
+  );
+};
+
+export default FlatListBasics;

image

Se você deseja renderizar um conjunto de dados divididos em seções lógicas, talvez com cabeçalhos de seção, semelhante ao UITableViews no iOS, então um SectionList é o caminho a percorrer.

jsx
import React from 'react';
+import {SectionList, StyleSheet, Text, View} from 'react-native';
+
+const styles = StyleSheet.create({
+  container: {
+    flex: 1,
+    paddingTop: 22,
+  },
+  sectionHeader: {
+    paddingTop: 2,
+    paddingLeft: 10,
+    paddingRight: 10,
+    paddingBottom: 2,
+    fontSize: 14,
+    fontWeight: 'bold',
+    backgroundColor: 'rgba(247,247,247,1.0)',
+  },
+  item: {
+    padding: 10,
+    fontSize: 18,
+    height: 44,
+  },
+});
+
+const SectionListBasics = () => {
+  return (
+    <View style={styles.container}>
+      <SectionList
+        sections={[
+          {title: 'D', data: ['Devin', 'Dan', 'Dominic']},
+          {
+            title: 'J',
+            data: [
+              'Jackson',
+              'James',
+              'Jillian',
+              'Jimmy',
+              'Joel',
+              'John',
+              'Julie',
+            ],
+          },
+        ]}
+        renderItem={({item}) => <Text style={styles.item}>{item}</Text>}
+        renderSectionHeader={({section}) => (
+          <Text style={styles.sectionHeader}>{section.title}</Text>
+        )}
+        keyExtractor={item => \`basicListEntry-\${item}\`}
+      />
+    </View>
+  );
+};
+
+export default SectionListBasics;

image

Um dos usos mais comuns de uma exibição de lista é exibir dados que você busca em um servidor. Para fazer isso, você precisará aprender sobre redes no React Native.

`,11),l=[t];function k(p,e,E,d,r,g){return a(),i("div",null,l)}const o=s(h,[["render",k]]);export{c as __pageData,o as default}; diff --git a/vitepress/docs/.vitepress/dist/assets/docs_using-a-listview.md.ChEZh-qr.lean.js b/vitepress/docs/.vitepress/dist/assets/docs_using-a-listview.md.ChEZh-qr.lean.js new file mode 100644 index 0000000..6c8d9c0 --- /dev/null +++ b/vitepress/docs/.vitepress/dist/assets/docs_using-a-listview.md.ChEZh-qr.lean.js @@ -0,0 +1 @@ +import{_ as s,c as i,o as a,a4 as n}from"./chunks/framework.nQaBHiNx.js";const c=JSON.parse('{"title":"Usando List View","description":"","frontmatter":{},"headers":[],"relativePath":"docs/using-a-listview.md","filePath":"docs/using-a-listview.md"}'),h={name:"docs/using-a-listview.md"},t=n("",11),l=[t];function k(p,e,E,d,r,g){return a(),i("div",null,l)}const o=s(h,[["render",k]]);export{c as __pageData,o as default}; diff --git a/vitepress/docs/.vitepress/dist/assets/docs_using-a-scrollview.md.DX0O7WVS.js b/vitepress/docs/.vitepress/dist/assets/docs_using-a-scrollview.md.DX0O7WVS.js new file mode 100644 index 0000000..392bb66 --- /dev/null +++ b/vitepress/docs/.vitepress/dist/assets/docs_using-a-scrollview.md.DX0O7WVS.js @@ -0,0 +1,46 @@ +import{_ as s,c as i,o as a,a4 as n}from"./chunks/framework.nQaBHiNx.js";const y=JSON.parse('{"title":"Usando um ScrollView","description":"","frontmatter":{},"headers":[],"relativePath":"docs/using-a-scrollview.md","filePath":"docs/using-a-scrollview.md"}'),l={name:"docs/using-a-scrollview.md"},h=n(`

Usando um ScrollView

O ScrollView é um contêiner de rolagem genérico que pode conter vários componentes e visualizações. Os itens roláveis podem ser heterogêneos e você pode rolar vertical e horizontalmente (definindo a propriedade horizontal).

Este exemplo cria um ScrollView vertical com imagens e texto misturados.

jsx
import React from 'react';
+import {Image, ScrollView, Text} from 'react-native';
+
+const logo = {
+  uri: 'https://reactnative.dev/img/tiny_logo.png',
+  width: 64,
+  height: 64,
+};
+
+const App = () => (
+  <ScrollView>
+    <Text style={{fontSize: 96}}>Scroll me plz</Text>
+    <Image source={logo} />
+    <Image source={logo} />
+    <Image source={logo} />
+    <Image source={logo} />
+    <Image source={logo} />
+    <Text style={{fontSize: 96}}>If you like</Text>
+    <Image source={logo} />
+    <Image source={logo} />
+    <Image source={logo} />
+    <Image source={logo} />
+    <Image source={logo} />
+    <Text style={{fontSize: 96}}>Scrolling down</Text>
+    <Image source={logo} />
+    <Image source={logo} />
+    <Image source={logo} />
+    <Image source={logo} />
+    <Image source={logo} />
+    <Text style={{fontSize: 96}}>What's the best</Text>
+    <Image source={logo} />
+    <Image source={logo} />
+    <Image source={logo} />
+    <Image source={logo} />
+    <Image source={logo} />
+    <Text style={{fontSize: 96}}>Framework around?</Text>
+    <Image source={logo} />
+    <Image source={logo} />
+    <Image source={logo} />
+    <Image source={logo} />
+    <Image source={logo} />
+    <Text style={{fontSize: 80}}>React Native</Text>
+  </ScrollView>
+);
+
+export default App;

ScrollViews pode ser configurado para permitir a paginação através de visualizações usando gestos de deslizar com os props pagingEnabled. Deslizar horizontalmente entre visualizações também pode ser implementado no Android usando o componente ViewPager.

No iOS, um ScrollView com um único item pode ser usado para permitir ao usuário ampliar o conteúdo. Configure os props maximumZoomScale e minimumZoomScale e seu usuário poderá usar gestos de pinçar e expandir para aumentar e diminuir o zoom.

O ScrollView funciona melhor para apresentar um pequeno número de coisas de tamanho limitado. Todos os elementos e visualizações de um ScrollView são renderizados, mesmo que não sejam mostrados na tela no momento. Se você tiver uma longa lista de itens que não cabem na tela, você deve usar uma FlatList. Então, vamos aprender sobre as visualizações de lista a seguir.

`,7),t=[h];function k(p,e,E,r,g,d){return a(),i("div",null,t)}const F=s(l,[["render",k]]);export{y as __pageData,F as default}; diff --git a/vitepress/docs/.vitepress/dist/assets/docs_using-a-scrollview.md.DX0O7WVS.lean.js b/vitepress/docs/.vitepress/dist/assets/docs_using-a-scrollview.md.DX0O7WVS.lean.js new file mode 100644 index 0000000..62c39b5 --- /dev/null +++ b/vitepress/docs/.vitepress/dist/assets/docs_using-a-scrollview.md.DX0O7WVS.lean.js @@ -0,0 +1 @@ +import{_ as s,c as i,o as a,a4 as n}from"./chunks/framework.nQaBHiNx.js";const y=JSON.parse('{"title":"Usando um ScrollView","description":"","frontmatter":{},"headers":[],"relativePath":"docs/using-a-scrollview.md","filePath":"docs/using-a-scrollview.md"}'),l={name:"docs/using-a-scrollview.md"},h=n("",7),t=[h];function k(p,e,E,r,g,d){return a(),i("div",null,t)}const F=s(l,[["render",k]]);export{y as __pageData,F as default}; diff --git a/vitepress/docs/.vitepress/dist/assets/docs_using-hermes.md.BML4G3i2.js b/vitepress/docs/.vitepress/dist/assets/docs_using-hermes.md.BML4G3i2.js new file mode 100644 index 0000000..8d46ca3 --- /dev/null +++ b/vitepress/docs/.vitepress/dist/assets/docs_using-hermes.md.BML4G3i2.js @@ -0,0 +1,20 @@ +import{_ as a,c as e,o as s,a4 as i}from"./chunks/framework.nQaBHiNx.js";const o="/assets/312113267-388b181e-16bd-4444-a586-8efcfe5e5da4.Bzix7piI.png",t="/assets/312120479-2e3ad0ad-158e-44f9-9380-766c60734ef3.xCg6zAM_.png",n="/assets/312123307-6526427d-5ece-4ed1-b980-a84cfb4b2ff1.D4k-Dzkc.png",r="/assets/312123621-2ed9b518-98c0-4a67-85f2-5524997c72d9.Clk86AQj.png",d="/assets/312123846-8e11055e-5ac9-4da6-a9da-cd4d854a3779.DkRh_3BN.png",C=JSON.parse('{"title":"Usando o Hermes","description":"","frontmatter":{},"headers":[],"relativePath":"docs/using-hermes.md","filePath":"docs/using-hermes.md"}'),p={name:"docs/using-hermes.md"},l=i('

Usando o Hermes

Hermes é um mecanismo JavaScript de código aberto otimizado para React Native. Para muitos aplicativos, o uso do Hermes resultará em melhor tempo de inicialização, menor uso de memória e tamanho menor do aplicativo quando comparado ao JavaScriptCore. Hermes é usado por padrão pelo React Native e nenhuma configuração adicional é necessária para habilitá-lo.

Pacote Hermes

React Native vem com uma versão integrada do Hermes. Estaremos construindo uma versão do Hermes para você sempre que lançarmos uma nova versão do React Native. Isso garantirá que você esteja consumindo uma versão do Hermes totalmente compatível com a versão do React Native que você está usando.

Historicamente, tivemos problemas ao combinar versões do Hermes com versões do React Native. Isso elimina totalmente esse problema e oferece aos usuários um mecanismo JS compatível com a versão específica do React Native.

Esta mudança é totalmente transparente para os usuários do React Native. Você ainda pode desativar o Hermes usando o comando descrito nesta página. Você pode ler mais sobre a implementação técnica nesta página.

Confirmando que Hermes está em uso

Se você criou recentemente um novo aplicativo do zero, deverá ver se o Hermes está ativado na visualização de boas-vindas:

image

Uma variável global HermesInternal estará disponível em JavaScript que pode ser usada para verificar se o Hermes está em uso:

js
const isHermes = () => !!global.HermesInternal;

CUIDADO

Se você estiver usando uma forma não padrão de carregar o pacote JS, é possível que a variável HermesInternal esteja disponível, mas você não esteja usando o bytecode pré-compilado altamente otimizado. Confirme se você está usando o arquivo .hbc e também compare o antes/depois conforme detalhado abaixo.

Para ver os benefícios do Hermes, tente fazer uma versão build/implantação do seu aplicativo para comparar. Por exemplo; da raiz do seu projeto:

Android

bash
npm run android -- --mode="release"
bash
yarn android --mode release

iOS

bash
npm run ios -- --mode="Release"
bash
yarn ios --mode Release

Isso compilará o JavaScript em bytecode durante o tempo de construção, o que melhorará a velocidade de inicialização do seu aplicativo no dispositivo.

Depurando JS no Hermes usando DevTools do Google Chrome

Hermes oferece suporte ao depurador do Chrome implementando o protocolo do inspetor do Chrome. Isso significa que as ferramentas do Chrome podem ser usadas para depurar diretamente o JavaScript em execução no Hermes, em um emulador ou em um dispositivo físico real.

INFORMAÇÕES

Observe que isso é muito diferente da "Depuração remota de JS" do menu de desenvolvimento no aplicativo documentado na seção Depuração, que na verdade executa o código JS no V8 do Chrome em sua máquina de desenvolvimento (laptop ou desktop).

O Chrome se conecta ao Hermes em execução no dispositivo via Metro, então você precisa saber onde o Metro está ouvindo. Normalmente, isso estará em localhost:8081, mas é configurável. Ao executar o yarn start, o endereço é gravado em stdout na inicialização.

Depois de saber onde o servidor Metro está escutando, você pode conectar-se ao Chrome seguindo as seguintes etapas:

  1. Navegue para chrome://inspect em uma instância do navegador Chrome.
  2. Use o botão Configure... para adicionar o endereço do servidor Metro (normalmente localhost:8081 conforme descrito acima).
  1. Agora você deve ver um alvo "Hermes React Native" com um link "inspecionar" que pode ser usado para abrir o depurador. Se você não vir o link “inspect”, certifique-se de que o servidor Metro esteja em execução.
  1. Agora você pode usar as ferramentas de depuração do Chrome. Por exemplo, para fazer um ponto de interrupção na próxima vez que algum JavaScript for executado, clique no botão de pausa e acione uma ação em seu aplicativo que faria com que o JavaScript fosse executado.

Habilitando Hermes em versões mais antigas do React Native

Hermes é o mecanismo padrão no React Native 0.70. Esta seção explica como habilitar o Hermes em versões mais antigas do React Native. Primeiro, certifique-se de usar pelo menos a versão 0.60.4 do React Native para habilitar o Hermes no Android ou 0.64 do React Native para habilitar o Hermes no iOS.

Se você já possui um aplicativo baseado em uma versão anterior do React Native, você terá que atualizá-lo primeiro. Consulte Atualizando para novas versões do React Native para saber como fazer isso. Depois de atualizar o aplicativo, certifique-se de que tudo funciona antes de tentar mudar para o Hermes.

NOTA PARA COMPATIBILIDADE REACT NATIVE

Cada lançamento da Hermes é direcionado a uma versão RN específica. A regra é sempre seguir rigorosamente os lançamentos do Hermes. A incompatibilidade de versão pode resultar na falha instantânea de seus aplicativos na pior das hipóteses.

NOTA PARA USUÁRIOS DO WINDOWS

Hermes requer Microsoft Visual C++ 2015 Redistributable.

Android

Edite seu arquivo android/gradle.properties e certifique-se de que hermesEnabled seja verdadeiro:

# Use esta propriedade para ativar ou desativar o mecanismo Hermes JS.
+# Se definido como falso, você usará JSC.
+hermesEnabled=true

OBSERVAÇÃO

Esta propriedade foi adicionada no React Native 0.71. Se você não conseguir encontrá-lo em seu arquivo gradle.properties, consulte a documentação da versão correspondente do React Native que você está usando.

Além disso, se estiver usando o ProGuard, você precisará adicionar estas regras em proguard-rules.pro:

-keep class com.facebook.hermes.unicode.** { *; }
+-keep class com.facebook.jni.** { *; }

A seguir, se você já criou seu aplicativo pelo menos uma vez, limpe a compilação:

bash
cd android && ./gradlew clean

É isso! Agora você deve conseguir desenvolver e implantar seu aplicativo normalmente:

bash
npm run android
bash
yarn android

iOS

Desde o React Native 0.64, o Hermes também roda em iOS. Para habilitar o Hermes para iOS, edite seu arquivo ios/Podfile e faça a alteração ilustrada abaixo:

   use_react_native!(
+     :path => config[:reactNativePath],
+     # to enable hermes on iOS, change \`false\` to \`true\` and then install pods
+     # By default, Hermes is disabled on Old Architecture, and enabled on New Architecture.
+     # You can enable/disable it manually by replacing \`flags[:hermes_enabled]\` with \`true\` or \`false\`.
+-    :hermes_enabled => flags[:hermes_enabled],
++    :hermes_enabled => true
+   )

Por padrão, você usará Hermes se estiver na Nova Arquitetura. Ao especificar um valor como true ou false, você pode ativar/desativar o Hermes como desejar.

Depois de configurá-lo, você pode instalar os pods Hermes com:

bash
cd ios && pod install

É isso! Agora você deve conseguir desenvolver e implantar seu aplicativo normalmente:

bash
npm run ios
bash
yarn ios

Voltando para JavaScriptCore

React Native também oferece suporte ao uso de JavaScriptCore como mecanismo JavaScript. Siga estas instruções para cancelar o Hermes.

Android

Edite seu arquivo android/gradle.properties e mude hermesEnabled de volta para false:

# Use esta propriedade para ativar ou desativar o mecanismo Hermes JS.
+# Se definido como false, você usará JSC.
+hermesEnabled=false

iOS

Edite seu arquivo ios/Podfile e faça a alteração ilustrada abaixo:

   use_react_native!(
+     :path => config[:reactNativePath],
+     # Hermes agora está habilitado por padrão. Desative definindo este sinalizador como false.
+     # As próximas versões do React Native podem contar com get_default_flags(), mas
+     # deixamos isso explícito aqui para auxiliar no processo de atualização do React Native.
+     :hermes_enabled => flags[:hermes_enabled],
+     :hermes_enabled => false,
+   )
`,61),c=[l];function h(m,u,v,g,k,b){return s(),e("div",null,c)}const y=a(p,[["render",h]]);export{C as __pageData,y as default}; diff --git a/vitepress/docs/.vitepress/dist/assets/docs_using-hermes.md.BML4G3i2.lean.js b/vitepress/docs/.vitepress/dist/assets/docs_using-hermes.md.BML4G3i2.lean.js new file mode 100644 index 0000000..8d35f52 --- /dev/null +++ b/vitepress/docs/.vitepress/dist/assets/docs_using-hermes.md.BML4G3i2.lean.js @@ -0,0 +1 @@ +import{_ as a,c as e,o as s,a4 as i}from"./chunks/framework.nQaBHiNx.js";const o="/assets/312113267-388b181e-16bd-4444-a586-8efcfe5e5da4.Bzix7piI.png",t="/assets/312120479-2e3ad0ad-158e-44f9-9380-766c60734ef3.xCg6zAM_.png",n="/assets/312123307-6526427d-5ece-4ed1-b980-a84cfb4b2ff1.D4k-Dzkc.png",r="/assets/312123621-2ed9b518-98c0-4a67-85f2-5524997c72d9.Clk86AQj.png",d="/assets/312123846-8e11055e-5ac9-4da6-a9da-cd4d854a3779.DkRh_3BN.png",C=JSON.parse('{"title":"Usando o Hermes","description":"","frontmatter":{},"headers":[],"relativePath":"docs/using-hermes.md","filePath":"docs/using-hermes.md"}'),p={name:"docs/using-hermes.md"},l=i("",61),c=[l];function h(m,u,v,g,k,b){return s(),e("div",null,c)}const y=a(p,[["render",h]]);export{C as __pageData,y as default}; diff --git a/vitepress/docs/.vitepress/dist/assets/index.md.O8eZyTNG.js b/vitepress/docs/.vitepress/dist/assets/index.md.O8eZyTNG.js new file mode 100644 index 0000000..c2ee9cf --- /dev/null +++ b/vitepress/docs/.vitepress/dist/assets/index.md.O8eZyTNG.js @@ -0,0 +1 @@ +import{_ as a,c as e,o as i,a4 as o}from"./chunks/framework.nQaBHiNx.js";const p=JSON.parse('{"title":"Documentação em português do React Native 0.72","description":"","frontmatter":{"title":"Documentação em português do React Native 0.72","lang":"pt-BR"},"headers":[],"relativePath":"index.md","filePath":"index.md"}'),l={name:"index.md"},t=o('

Documentação em português do React Native 0.72

Básico

Configuração do ambiente

Workflow

UI & Interação

Debugging

Testando

Performance

JavaScript Runtime

Módulos Nativos

Componentes Nativos

Guias Android e iOS

Experimental

',25),r=[t];function n(s,d,h,c,m,u){return i(),e("div",null,r)}const g=a(l,[["render",n]]);export{p as __pageData,g as default}; diff --git a/vitepress/docs/.vitepress/dist/assets/index.md.O8eZyTNG.lean.js b/vitepress/docs/.vitepress/dist/assets/index.md.O8eZyTNG.lean.js new file mode 100644 index 0000000..bdfe3a3 --- /dev/null +++ b/vitepress/docs/.vitepress/dist/assets/index.md.O8eZyTNG.lean.js @@ -0,0 +1 @@ +import{_ as a,c as e,o as i,a4 as o}from"./chunks/framework.nQaBHiNx.js";const p=JSON.parse('{"title":"Documentação em português do React Native 0.72","description":"","frontmatter":{"title":"Documentação em português do React Native 0.72","lang":"pt-BR"},"headers":[],"relativePath":"index.md","filePath":"index.md"}'),l={name:"index.md"},t=o("",25),r=[t];function n(s,d,h,c,m,u){return i(),e("div",null,r)}const g=a(l,[["render",n]]);export{p as __pageData,g as default}; diff --git a/vitepress/docs/.vitepress/dist/assets/legacy-renderer.-pdigmji.gif b/vitepress/docs/.vitepress/dist/assets/legacy-renderer.-pdigmji.gif new file mode 100644 index 0000000..75f4149 Binary files /dev/null and b/vitepress/docs/.vitepress/dist/assets/legacy-renderer.-pdigmji.gif differ diff --git a/vitepress/docs/.vitepress/dist/assets/p_tests-e2e.zzEG5Lpm.svg b/vitepress/docs/.vitepress/dist/assets/p_tests-e2e.zzEG5Lpm.svg new file mode 100644 index 0000000..08bb956 --- /dev/null +++ b/vitepress/docs/.vitepress/dist/assets/p_tests-e2e.zzEG5Lpm.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/vitepress/docs/.vitepress/dist/assets/react18-renderer.J5U3e7Q-.gif b/vitepress/docs/.vitepress/dist/assets/react18-renderer.J5U3e7Q-.gif new file mode 100644 index 0000000..c3ef44c Binary files /dev/null and b/vitepress/docs/.vitepress/dist/assets/react18-renderer.J5U3e7Q-.gif differ diff --git a/vitepress/docs/.vitepress/dist/assets/style.DPoWOshB.css b/vitepress/docs/.vitepress/dist/assets/style.DPoWOshB.css new file mode 100644 index 0000000..31f2174 --- /dev/null +++ b/vitepress/docs/.vitepress/dist/assets/style.DPoWOshB.css @@ -0,0 +1 @@ +:root{--vp-c-white: #ffffff;--vp-c-black: #000000;--vp-c-neutral: var(--vp-c-black);--vp-c-neutral-inverse: var(--vp-c-white)}.dark{--vp-c-neutral: var(--vp-c-white);--vp-c-neutral-inverse: var(--vp-c-black)}:root{--vp-c-gray-1: #dddde3;--vp-c-gray-2: #e4e4e9;--vp-c-gray-3: #ebebef;--vp-c-gray-soft: rgba(142, 150, 170, .14);--vp-c-indigo-1: #3451b2;--vp-c-indigo-2: #3a5ccc;--vp-c-indigo-3: #5672cd;--vp-c-indigo-soft: rgba(100, 108, 255, .14);--vp-c-purple-1: #6f42c1;--vp-c-purple-2: #7e4cc9;--vp-c-purple-3: #8e5cd9;--vp-c-purple-soft: rgba(159, 122, 234, .14);--vp-c-green-1: #18794e;--vp-c-green-2: #299764;--vp-c-green-3: #30a46c;--vp-c-green-soft: rgba(16, 185, 129, .14);--vp-c-yellow-1: #915930;--vp-c-yellow-2: #946300;--vp-c-yellow-3: #9f6a00;--vp-c-yellow-soft: rgba(234, 179, 8, .14);--vp-c-red-1: #b8272c;--vp-c-red-2: #d5393e;--vp-c-red-3: #e0575b;--vp-c-red-soft: rgba(244, 63, 94, .14);--vp-c-sponsor: #db2777}.dark{--vp-c-gray-1: #515c67;--vp-c-gray-2: #414853;--vp-c-gray-3: #32363f;--vp-c-gray-soft: rgba(101, 117, 133, .16);--vp-c-indigo-1: #a8b1ff;--vp-c-indigo-2: #5c73e7;--vp-c-indigo-3: #3e63dd;--vp-c-indigo-soft: rgba(100, 108, 255, .16);--vp-c-purple-1: #c8abfa;--vp-c-purple-2: #a879e6;--vp-c-purple-3: #8e5cd9;--vp-c-purple-soft: rgba(159, 122, 234, .16);--vp-c-green-1: #3dd68c;--vp-c-green-2: #30a46c;--vp-c-green-3: #298459;--vp-c-green-soft: rgba(16, 185, 129, .16);--vp-c-yellow-1: #f9b44e;--vp-c-yellow-2: #da8b17;--vp-c-yellow-3: #a46a0a;--vp-c-yellow-soft: rgba(234, 179, 8, .16);--vp-c-red-1: #f66f81;--vp-c-red-2: #f14158;--vp-c-red-3: #b62a3c;--vp-c-red-soft: rgba(244, 63, 94, .16)}:root{--vp-c-bg: #ffffff;--vp-c-bg-alt: #f6f6f7;--vp-c-bg-elv: #ffffff;--vp-c-bg-soft: #f6f6f7}.dark{--vp-c-bg: #1b1b1f;--vp-c-bg-alt: #161618;--vp-c-bg-elv: #202127;--vp-c-bg-soft: #202127}:root{--vp-c-border: #c2c2c4;--vp-c-divider: #e2e2e3;--vp-c-gutter: #e2e2e3}.dark{--vp-c-border: #3c3f44;--vp-c-divider: #2e2e32;--vp-c-gutter: #000000}:root{--vp-c-text-1: rgba(60, 60, 67);--vp-c-text-2: rgba(60, 60, 67, .78);--vp-c-text-3: rgba(60, 60, 67, .56)}.dark{--vp-c-text-1: rgba(255, 255, 245, .86);--vp-c-text-2: rgba(235, 235, 245, .6);--vp-c-text-3: rgba(235, 235, 245, .38)}:root{--vp-c-default-1: var(--vp-c-gray-1);--vp-c-default-2: var(--vp-c-gray-2);--vp-c-default-3: var(--vp-c-gray-3);--vp-c-default-soft: var(--vp-c-gray-soft);--vp-c-brand-1: var(--vp-c-indigo-1);--vp-c-brand-2: var(--vp-c-indigo-2);--vp-c-brand-3: var(--vp-c-indigo-3);--vp-c-brand-soft: var(--vp-c-indigo-soft);--vp-c-brand: var(--vp-c-brand-1);--vp-c-tip-1: var(--vp-c-brand-1);--vp-c-tip-2: var(--vp-c-brand-2);--vp-c-tip-3: var(--vp-c-brand-3);--vp-c-tip-soft: var(--vp-c-brand-soft);--vp-c-note-1: var(--vp-c-brand-1);--vp-c-note-2: var(--vp-c-brand-2);--vp-c-note-3: var(--vp-c-brand-3);--vp-c-note-soft: var(--vp-c-brand-soft);--vp-c-success-1: var(--vp-c-green-1);--vp-c-success-2: var(--vp-c-green-2);--vp-c-success-3: var(--vp-c-green-3);--vp-c-success-soft: var(--vp-c-green-soft);--vp-c-important-1: var(--vp-c-purple-1);--vp-c-important-2: var(--vp-c-purple-2);--vp-c-important-3: var(--vp-c-purple-3);--vp-c-important-soft: var(--vp-c-purple-soft);--vp-c-warning-1: var(--vp-c-yellow-1);--vp-c-warning-2: var(--vp-c-yellow-2);--vp-c-warning-3: var(--vp-c-yellow-3);--vp-c-warning-soft: var(--vp-c-yellow-soft);--vp-c-danger-1: var(--vp-c-red-1);--vp-c-danger-2: var(--vp-c-red-2);--vp-c-danger-3: var(--vp-c-red-3);--vp-c-danger-soft: var(--vp-c-red-soft);--vp-c-caution-1: var(--vp-c-red-1);--vp-c-caution-2: var(--vp-c-red-2);--vp-c-caution-3: var(--vp-c-red-3);--vp-c-caution-soft: var(--vp-c-red-soft)}:root{--vp-font-family-base: "Chinese Quotes", "Inter var", "Inter", ui-sans-serif, system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Helvetica, Arial, "Noto Sans", sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji";--vp-font-family-mono: ui-monospace, SFMono-Regular, "SF Mono", Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace}:root{--vp-shadow-1: 0 1px 2px rgba(0, 0, 0, .04), 0 1px 2px rgba(0, 0, 0, .06);--vp-shadow-2: 0 3px 12px rgba(0, 0, 0, .07), 0 1px 4px rgba(0, 0, 0, .07);--vp-shadow-3: 0 12px 32px rgba(0, 0, 0, .1), 0 2px 6px rgba(0, 0, 0, .08);--vp-shadow-4: 0 14px 44px rgba(0, 0, 0, .12), 0 3px 9px rgba(0, 0, 0, .12);--vp-shadow-5: 0 18px 56px rgba(0, 0, 0, .16), 0 4px 12px rgba(0, 0, 0, .16)}:root{--vp-z-index-footer: 10;--vp-z-index-local-nav: 20;--vp-z-index-nav: 30;--vp-z-index-layout-top: 40;--vp-z-index-backdrop: 50;--vp-z-index-sidebar: 60}@media (min-width: 960px){:root{--vp-z-index-sidebar: 25}}:root{--vp-layout-max-width: 1440px}:root{--vp-header-anchor-symbol: "#"}:root{--vp-code-line-height: 1.7;--vp-code-font-size: .875em;--vp-code-color: var(--vp-c-brand-1);--vp-code-link-color: var(--vp-c-brand-1);--vp-code-link-hover-color: var(--vp-c-brand-2);--vp-code-bg: var(--vp-c-default-soft);--vp-code-block-color: var(--vp-c-text-2);--vp-code-block-bg: var(--vp-c-bg-alt);--vp-code-block-divider-color: var(--vp-c-gutter);--vp-code-lang-color: var(--vp-c-text-3);--vp-code-line-highlight-color: var(--vp-c-default-soft);--vp-code-line-number-color: var(--vp-c-text-3);--vp-code-line-diff-add-color: var(--vp-c-success-soft);--vp-code-line-diff-add-symbol-color: var(--vp-c-success-1);--vp-code-line-diff-remove-color: var(--vp-c-danger-soft);--vp-code-line-diff-remove-symbol-color: var(--vp-c-danger-1);--vp-code-line-warning-color: var(--vp-c-warning-soft);--vp-code-line-error-color: var(--vp-c-danger-soft);--vp-code-copy-code-border-color: var(--vp-c-divider);--vp-code-copy-code-bg: var(--vp-c-bg-soft);--vp-code-copy-code-hover-border-color: var(--vp-c-divider);--vp-code-copy-code-hover-bg: var(--vp-c-bg);--vp-code-copy-code-active-text: var(--vp-c-text-2);--vp-code-copy-copied-text-content: "Copied";--vp-code-tab-divider: var(--vp-code-block-divider-color);--vp-code-tab-text-color: var(--vp-c-text-2);--vp-code-tab-bg: var(--vp-code-block-bg);--vp-code-tab-hover-text-color: var(--vp-c-text-1);--vp-code-tab-active-text-color: var(--vp-c-text-1);--vp-code-tab-active-bar-color: var(--vp-c-brand-1)}:root{--vp-button-brand-border: transparent;--vp-button-brand-text: var(--vp-c-white);--vp-button-brand-bg: var(--vp-c-brand-3);--vp-button-brand-hover-border: transparent;--vp-button-brand-hover-text: var(--vp-c-white);--vp-button-brand-hover-bg: var(--vp-c-brand-2);--vp-button-brand-active-border: transparent;--vp-button-brand-active-text: var(--vp-c-white);--vp-button-brand-active-bg: var(--vp-c-brand-1);--vp-button-alt-border: transparent;--vp-button-alt-text: var(--vp-c-text-1);--vp-button-alt-bg: var(--vp-c-default-3);--vp-button-alt-hover-border: transparent;--vp-button-alt-hover-text: var(--vp-c-text-1);--vp-button-alt-hover-bg: var(--vp-c-default-2);--vp-button-alt-active-border: transparent;--vp-button-alt-active-text: var(--vp-c-text-1);--vp-button-alt-active-bg: var(--vp-c-default-1);--vp-button-sponsor-border: var(--vp-c-text-2);--vp-button-sponsor-text: var(--vp-c-text-2);--vp-button-sponsor-bg: transparent;--vp-button-sponsor-hover-border: var(--vp-c-sponsor);--vp-button-sponsor-hover-text: var(--vp-c-sponsor);--vp-button-sponsor-hover-bg: transparent;--vp-button-sponsor-active-border: var(--vp-c-sponsor);--vp-button-sponsor-active-text: var(--vp-c-sponsor);--vp-button-sponsor-active-bg: transparent}:root{--vp-custom-block-font-size: 14px;--vp-custom-block-code-font-size: 13px;--vp-custom-block-info-border: transparent;--vp-custom-block-info-text: var(--vp-c-text-1);--vp-custom-block-info-bg: var(--vp-c-default-soft);--vp-custom-block-info-code-bg: var(--vp-c-default-soft);--vp-custom-block-note-border: transparent;--vp-custom-block-note-text: var(--vp-c-text-1);--vp-custom-block-note-bg: var(--vp-c-default-soft);--vp-custom-block-note-code-bg: var(--vp-c-default-soft);--vp-custom-block-tip-border: transparent;--vp-custom-block-tip-text: var(--vp-c-text-1);--vp-custom-block-tip-bg: var(--vp-c-tip-soft);--vp-custom-block-tip-code-bg: var(--vp-c-tip-soft);--vp-custom-block-important-border: transparent;--vp-custom-block-important-text: var(--vp-c-text-1);--vp-custom-block-important-bg: var(--vp-c-important-soft);--vp-custom-block-important-code-bg: var(--vp-c-important-soft);--vp-custom-block-warning-border: transparent;--vp-custom-block-warning-text: var(--vp-c-text-1);--vp-custom-block-warning-bg: var(--vp-c-warning-soft);--vp-custom-block-warning-code-bg: var(--vp-c-warning-soft);--vp-custom-block-danger-border: transparent;--vp-custom-block-danger-text: var(--vp-c-text-1);--vp-custom-block-danger-bg: var(--vp-c-danger-soft);--vp-custom-block-danger-code-bg: var(--vp-c-danger-soft);--vp-custom-block-caution-border: transparent;--vp-custom-block-caution-text: var(--vp-c-text-1);--vp-custom-block-caution-bg: var(--vp-c-caution-soft);--vp-custom-block-caution-code-bg: var(--vp-c-caution-soft);--vp-custom-block-details-border: var(--vp-custom-block-info-border);--vp-custom-block-details-text: var(--vp-custom-block-info-text);--vp-custom-block-details-bg: var(--vp-custom-block-info-bg);--vp-custom-block-details-code-bg: var(--vp-custom-block-info-code-bg)}:root{--vp-input-border-color: var(--vp-c-border);--vp-input-bg-color: var(--vp-c-bg-alt);--vp-input-switch-bg-color: var(--vp-c-default-soft)}:root{--vp-nav-height: 64px;--vp-nav-bg-color: var(--vp-c-bg);--vp-nav-screen-bg-color: var(--vp-c-bg);--vp-nav-logo-height: 24px}.hide-nav{--vp-nav-height: 0px}.hide-nav .VPSidebar{--vp-nav-height: 22px}:root{--vp-local-nav-bg-color: var(--vp-c-bg)}:root{--vp-sidebar-width: 272px;--vp-sidebar-bg-color: var(--vp-c-bg-alt)}:root{--vp-backdrop-bg-color: rgba(0, 0, 0, .6)}:root{--vp-home-hero-name-color: var(--vp-c-brand-1);--vp-home-hero-name-background: transparent;--vp-home-hero-image-background-image: none;--vp-home-hero-image-filter: none}:root{--vp-badge-info-border: transparent;--vp-badge-info-text: var(--vp-c-text-2);--vp-badge-info-bg: var(--vp-c-default-soft);--vp-badge-tip-border: transparent;--vp-badge-tip-text: var(--vp-c-tip-1);--vp-badge-tip-bg: var(--vp-c-tip-soft);--vp-badge-warning-border: transparent;--vp-badge-warning-text: var(--vp-c-warning-1);--vp-badge-warning-bg: var(--vp-c-warning-soft);--vp-badge-danger-border: transparent;--vp-badge-danger-text: var(--vp-c-danger-1);--vp-badge-danger-bg: var(--vp-c-danger-soft)}:root{--vp-carbon-ads-text-color: var(--vp-c-text-1);--vp-carbon-ads-poweredby-color: var(--vp-c-text-2);--vp-carbon-ads-bg-color: var(--vp-c-bg-soft);--vp-carbon-ads-hover-text-color: var(--vp-c-brand-1);--vp-carbon-ads-hover-poweredby-color: var(--vp-c-text-1)}:root{--vp-local-search-bg: var(--vp-c-bg);--vp-local-search-result-bg: var(--vp-c-bg);--vp-local-search-result-border: var(--vp-c-divider);--vp-local-search-result-selected-bg: var(--vp-c-bg);--vp-local-search-result-selected-border: var(--vp-c-brand-1);--vp-local-search-highlight-bg: var(--vp-c-brand-1);--vp-local-search-highlight-text: var(--vp-c-neutral-inverse)}@media (prefers-reduced-motion: reduce){*,:before,:after{animation-delay:-1ms!important;animation-duration:1ms!important;animation-iteration-count:1!important;background-attachment:initial!important;scroll-behavior:auto!important;transition-duration:0s!important;transition-delay:0s!important}}*,:before,:after{box-sizing:border-box}html{line-height:1.4;font-size:16px;-webkit-text-size-adjust:100%}html.dark{color-scheme:dark}body{margin:0;width:100%;min-width:320px;min-height:100vh;line-height:24px;font-family:var(--vp-font-family-base);font-size:16px;font-weight:400;color:var(--vp-c-text-1);background-color:var(--vp-c-bg);font-synthesis:style;text-rendering:optimizeLegibility;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}main{display:block}h1,h2,h3,h4,h5,h6{margin:0;line-height:24px;font-size:16px;font-weight:400}p{margin:0}strong,b{font-weight:600}a,area,button,[role=button],input,label,select,summary,textarea{touch-action:manipulation}a{color:inherit;text-decoration:inherit}ol,ul{list-style:none;margin:0;padding:0}blockquote{margin:0}pre,code,kbd,samp{font-family:var(--vp-font-family-mono)}img,svg,video,canvas,audio,iframe,embed,object{display:block}figure{margin:0}img,video{max-width:100%;height:auto}button,input,optgroup,select,textarea{border:0;padding:0;line-height:inherit;color:inherit}button{padding:0;font-family:inherit;background-color:transparent;background-image:none}button:enabled,[role=button]:enabled{cursor:pointer}button:focus,button:focus-visible{outline:1px dotted;outline:4px auto -webkit-focus-ring-color}button:focus:not(:focus-visible){outline:none!important}input:focus,textarea:focus,select:focus{outline:none}table{border-collapse:collapse}input{background-color:transparent}input:-ms-input-placeholder,textarea:-ms-input-placeholder{color:var(--vp-c-text-3)}input::-ms-input-placeholder,textarea::-ms-input-placeholder{color:var(--vp-c-text-3)}input::placeholder,textarea::placeholder{color:var(--vp-c-text-3)}input::-webkit-outer-spin-button,input::-webkit-inner-spin-button{-webkit-appearance:none;margin:0}input[type=number]{-moz-appearance:textfield}textarea{resize:vertical}select{-webkit-appearance:none}fieldset{margin:0;padding:0}h1,h2,h3,h4,h5,h6,li,p{overflow-wrap:break-word}vite-error-overlay{z-index:9999}mjx-container{display:inline-block;margin:auto 2px -2px}mjx-container>svg{display:inline-block;margin:auto}[class^=vpi-],[class*=" vpi-"],.vp-icon{width:1em;height:1em}[class^=vpi-].bg,[class*=" vpi-"].bg,.vp-icon.bg{background-size:100% 100%;background-color:transparent}[class^=vpi-]:not(.bg),[class*=" vpi-"]:not(.bg),.vp-icon:not(.bg){-webkit-mask:var(--icon) no-repeat;mask:var(--icon) no-repeat;-webkit-mask-size:100% 100%;mask-size:100% 100%;background-color:currentColor;color:inherit}.vpi-align-left{--icon: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' fill='none' stroke='currentColor' stroke-linecap='round' stroke-linejoin='round' stroke-width='2' viewBox='0 0 24 24'%3E%3Cpath d='M21 6H3M15 12H3M17 18H3'/%3E%3C/svg%3E")}.vpi-arrow-right,.vpi-arrow-down,.vpi-arrow-left,.vpi-arrow-up{--icon: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' fill='none' stroke='currentColor' stroke-linecap='round' stroke-linejoin='round' stroke-width='2' viewBox='0 0 24 24'%3E%3Cpath d='M5 12h14M12 5l7 7-7 7'/%3E%3C/svg%3E")}.vpi-chevron-right,.vpi-chevron-down,.vpi-chevron-left,.vpi-chevron-up{--icon: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' fill='none' stroke='currentColor' stroke-linecap='round' stroke-linejoin='round' stroke-width='2' viewBox='0 0 24 24'%3E%3Cpath d='m9 18 6-6-6-6'/%3E%3C/svg%3E")}.vpi-chevron-down,.vpi-arrow-down{transform:rotate(90deg)}.vpi-chevron-left,.vpi-arrow-left{transform:rotate(180deg)}.vpi-chevron-up,.vpi-arrow-up{transform:rotate(-90deg)}.vpi-square-pen{--icon: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' fill='none' stroke='currentColor' stroke-linecap='round' stroke-linejoin='round' stroke-width='2' viewBox='0 0 24 24'%3E%3Cpath d='M12 3H5a2 2 0 0 0-2 2v14a2 2 0 0 0 2 2h14a2 2 0 0 0 2-2v-7'/%3E%3Cpath d='M18.375 2.625a2.121 2.121 0 1 1 3 3L12 15l-4 1 1-4Z'/%3E%3C/svg%3E")}.vpi-plus{--icon: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' fill='none' stroke='currentColor' stroke-linecap='round' stroke-linejoin='round' stroke-width='2' viewBox='0 0 24 24'%3E%3Cpath d='M5 12h14M12 5v14'/%3E%3C/svg%3E")}.vpi-sun{--icon: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' fill='none' stroke='currentColor' stroke-linecap='round' stroke-linejoin='round' stroke-width='2' viewBox='0 0 24 24'%3E%3Ccircle cx='12' cy='12' r='4'/%3E%3Cpath d='M12 2v2M12 20v2M4.93 4.93l1.41 1.41M17.66 17.66l1.41 1.41M2 12h2M20 12h2M6.34 17.66l-1.41 1.41M19.07 4.93l-1.41 1.41'/%3E%3C/svg%3E")}.vpi-moon{--icon: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' fill='none' stroke='currentColor' stroke-linecap='round' stroke-linejoin='round' stroke-width='2' viewBox='0 0 24 24'%3E%3Cpath d='M12 3a6 6 0 0 0 9 9 9 9 0 1 1-9-9Z'/%3E%3C/svg%3E")}.vpi-more-horizontal{--icon: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' fill='none' stroke='currentColor' stroke-linecap='round' stroke-linejoin='round' stroke-width='2' viewBox='0 0 24 24'%3E%3Ccircle cx='12' cy='12' r='1'/%3E%3Ccircle cx='19' cy='12' r='1'/%3E%3Ccircle cx='5' cy='12' r='1'/%3E%3C/svg%3E")}.vpi-languages{--icon: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' fill='none' stroke='currentColor' stroke-linecap='round' stroke-linejoin='round' stroke-width='2' viewBox='0 0 24 24'%3E%3Cpath d='m5 8 6 6M4 14l6-6 2-3M2 5h12M7 2h1M22 22l-5-10-5 10M14 18h6'/%3E%3C/svg%3E")}.vpi-heart{--icon: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' fill='none' stroke='currentColor' stroke-linecap='round' stroke-linejoin='round' stroke-width='2' viewBox='0 0 24 24'%3E%3Cpath d='M19 14c1.49-1.46 3-3.21 3-5.5A5.5 5.5 0 0 0 16.5 3c-1.76 0-3 .5-4.5 2-1.5-1.5-2.74-2-4.5-2A5.5 5.5 0 0 0 2 8.5c0 2.3 1.5 4.05 3 5.5l7 7Z'/%3E%3C/svg%3E")}.vpi-search{--icon: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' fill='none' stroke='currentColor' stroke-linecap='round' stroke-linejoin='round' stroke-width='2' viewBox='0 0 24 24'%3E%3Ccircle cx='11' cy='11' r='8'/%3E%3Cpath d='m21 21-4.3-4.3'/%3E%3C/svg%3E")}.vpi-layout-list{--icon: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' fill='none' stroke='currentColor' stroke-linecap='round' stroke-linejoin='round' stroke-width='2' viewBox='0 0 24 24'%3E%3Crect width='7' height='7' x='3' y='3' rx='1'/%3E%3Crect width='7' height='7' x='3' y='14' rx='1'/%3E%3Cpath d='M14 4h7M14 9h7M14 15h7M14 20h7'/%3E%3C/svg%3E")}.vpi-delete{--icon: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' fill='none' stroke='currentColor' stroke-linecap='round' stroke-linejoin='round' stroke-width='2' viewBox='0 0 24 24'%3E%3Cpath d='M20 5H9l-7 7 7 7h11a2 2 0 0 0 2-2V7a2 2 0 0 0-2-2ZM18 9l-6 6M12 9l6 6'/%3E%3C/svg%3E")}.vpi-corner-down-left{--icon: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' fill='none' stroke='currentColor' stroke-linecap='round' stroke-linejoin='round' stroke-width='2' viewBox='0 0 24 24'%3E%3Cpath d='m9 10-5 5 5 5'/%3E%3Cpath d='M20 4v7a4 4 0 0 1-4 4H4'/%3E%3C/svg%3E")}:root{--vp-icon-copy: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' fill='none' stroke='rgba(128,128,128,1)' stroke-linecap='round' stroke-linejoin='round' stroke-width='2' viewBox='0 0 24 24'%3E%3Crect width='8' height='4' x='8' y='2' rx='1' ry='1'/%3E%3Cpath d='M16 4h2a2 2 0 0 1 2 2v14a2 2 0 0 1-2 2H6a2 2 0 0 1-2-2V6a2 2 0 0 1 2-2h2'/%3E%3C/svg%3E");--vp-icon-copied: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' fill='none' stroke='rgba(128,128,128,1)' stroke-linecap='round' stroke-linejoin='round' stroke-width='2' viewBox='0 0 24 24'%3E%3Crect width='8' height='4' x='8' y='2' rx='1' ry='1'/%3E%3Cpath d='M16 4h2a2 2 0 0 1 2 2v14a2 2 0 0 1-2 2H6a2 2 0 0 1-2-2V6a2 2 0 0 1 2-2h2'/%3E%3Cpath d='m9 14 2 2 4-4'/%3E%3C/svg%3E")}.vpi-social-discord{--icon: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cpath d='M20.317 4.37a19.791 19.791 0 0 0-4.885-1.515.074.074 0 0 0-.079.037c-.21.375-.444.864-.608 1.25a18.27 18.27 0 0 0-5.487 0 12.64 12.64 0 0 0-.617-1.25.077.077 0 0 0-.079-.037A19.736 19.736 0 0 0 3.677 4.37a.07.07 0 0 0-.032.027C.533 9.046-.32 13.58.099 18.057a.082.082 0 0 0 .031.057 19.9 19.9 0 0 0 5.993 3.03.078.078 0 0 0 .084-.028c.462-.63.874-1.295 1.226-1.994a.076.076 0 0 0-.041-.106 13.107 13.107 0 0 1-1.872-.892.077.077 0 0 1-.008-.128 10.2 10.2 0 0 0 .372-.292.074.074 0 0 1 .077-.01c3.928 1.793 8.18 1.793 12.062 0a.074.074 0 0 1 .078.01c.12.098.246.198.373.292a.077.077 0 0 1-.006.127 12.299 12.299 0 0 1-1.873.892.077.077 0 0 0-.041.107c.36.698.772 1.362 1.225 1.993a.076.076 0 0 0 .084.028 19.839 19.839 0 0 0 6.002-3.03.077.077 0 0 0 .032-.054c.5-5.177-.838-9.674-3.549-13.66a.061.061 0 0 0-.031-.03zM8.02 15.33c-1.183 0-2.157-1.085-2.157-2.419 0-1.333.956-2.419 2.157-2.419 1.21 0 2.176 1.096 2.157 2.42 0 1.333-.956 2.418-2.157 2.418zm7.975 0c-1.183 0-2.157-1.085-2.157-2.419 0-1.333.955-2.419 2.157-2.419 1.21 0 2.176 1.096 2.157 2.42 0 1.333-.946 2.418-2.157 2.418Z'/%3E%3C/svg%3E")}.vpi-social-facebook{--icon: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cpath d='M9.101 23.691v-7.98H6.627v-3.667h2.474v-1.58c0-4.085 1.848-5.978 5.858-5.978.401 0 .955.042 1.468.103a8.68 8.68 0 0 1 1.141.195v3.325a8.623 8.623 0 0 0-.653-.036 26.805 26.805 0 0 0-.733-.009c-.707 0-1.259.096-1.675.309a1.686 1.686 0 0 0-.679.622c-.258.42-.374.995-.374 1.752v1.297h3.919l-.386 2.103-.287 1.564h-3.246v8.245C19.396 23.238 24 18.179 24 12.044c0-6.627-5.373-12-12-12s-12 5.373-12 12c0 5.628 3.874 10.35 9.101 11.647Z'/%3E%3C/svg%3E")}.vpi-social-github{--icon: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cpath d='M12 .297c-6.63 0-12 5.373-12 12 0 5.303 3.438 9.8 8.205 11.385.6.113.82-.258.82-.577 0-.285-.01-1.04-.015-2.04-3.338.724-4.042-1.61-4.042-1.61C4.422 18.07 3.633 17.7 3.633 17.7c-1.087-.744.084-.729.084-.729 1.205.084 1.838 1.236 1.838 1.236 1.07 1.835 2.809 1.305 3.495.998.108-.776.417-1.305.76-1.605-2.665-.3-5.466-1.332-5.466-5.93 0-1.31.465-2.38 1.235-3.22-.135-.303-.54-1.523.105-3.176 0 0 1.005-.322 3.3 1.23.96-.267 1.98-.399 3-.405 1.02.006 2.04.138 3 .405 2.28-1.552 3.285-1.23 3.285-1.23.645 1.653.24 2.873.12 3.176.765.84 1.23 1.91 1.23 3.22 0 4.61-2.805 5.625-5.475 5.92.42.36.81 1.096.81 2.22 0 1.606-.015 2.896-.015 3.286 0 .315.21.69.825.57C20.565 22.092 24 17.592 24 12.297c0-6.627-5.373-12-12-12'/%3E%3C/svg%3E")}.vpi-social-instagram{--icon: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cpath d='M7.03.084c-1.277.06-2.149.264-2.91.563a5.874 5.874 0 0 0-2.124 1.388 5.878 5.878 0 0 0-1.38 2.127C.321 4.926.12 5.8.064 7.076.008 8.354-.005 8.764.001 12.023c.007 3.259.021 3.667.083 4.947.061 1.277.264 2.149.563 2.911.308.789.72 1.457 1.388 2.123a5.872 5.872 0 0 0 2.129 1.38c.763.295 1.636.496 2.913.552 1.278.056 1.689.069 4.947.063 3.257-.007 3.668-.021 4.947-.082 1.28-.06 2.147-.265 2.91-.563a5.881 5.881 0 0 0 2.123-1.388 5.881 5.881 0 0 0 1.38-2.129c.295-.763.496-1.636.551-2.912.056-1.28.07-1.69.063-4.948-.006-3.258-.02-3.667-.081-4.947-.06-1.28-.264-2.148-.564-2.911a5.892 5.892 0 0 0-1.387-2.123 5.857 5.857 0 0 0-2.128-1.38C19.074.322 18.202.12 16.924.066 15.647.009 15.236-.006 11.977 0 8.718.008 8.31.021 7.03.084m.14 21.693c-1.17-.05-1.805-.245-2.228-.408a3.736 3.736 0 0 1-1.382-.895 3.695 3.695 0 0 1-.9-1.378c-.165-.423-.363-1.058-.417-2.228-.06-1.264-.072-1.644-.08-4.848-.006-3.204.006-3.583.061-4.848.05-1.169.246-1.805.408-2.228.216-.561.477-.96.895-1.382a3.705 3.705 0 0 1 1.379-.9c.423-.165 1.057-.361 2.227-.417 1.265-.06 1.644-.072 4.848-.08 3.203-.006 3.583.006 4.85.062 1.168.05 1.804.244 2.227.408.56.216.96.475 1.382.895.421.42.681.817.9 1.378.165.422.362 1.056.417 2.227.06 1.265.074 1.645.08 4.848.005 3.203-.006 3.583-.061 4.848-.051 1.17-.245 1.805-.408 2.23-.216.56-.477.96-.896 1.38a3.705 3.705 0 0 1-1.378.9c-.422.165-1.058.362-2.226.418-1.266.06-1.645.072-4.85.079-3.204.007-3.582-.006-4.848-.06m9.783-16.192a1.44 1.44 0 1 0 1.437-1.442 1.44 1.44 0 0 0-1.437 1.442M5.839 12.012a6.161 6.161 0 1 0 12.323-.024 6.162 6.162 0 0 0-12.323.024M8 12.008A4 4 0 1 1 12.008 16 4 4 0 0 1 8 12.008'/%3E%3C/svg%3E")}.vpi-social-linkedin{--icon: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cpath d='M20.447 20.452h-3.554v-5.569c0-1.328-.027-3.037-1.852-3.037-1.853 0-2.136 1.445-2.136 2.939v5.667H9.351V9h3.414v1.561h.046c.477-.9 1.637-1.85 3.37-1.85 3.601 0 4.267 2.37 4.267 5.455v6.286zM5.337 7.433a2.062 2.062 0 0 1-2.063-2.065 2.064 2.064 0 1 1 2.063 2.065zm1.782 13.019H3.555V9h3.564v11.452zM22.225 0H1.771C.792 0 0 .774 0 1.729v20.542C0 23.227.792 24 1.771 24h20.451C23.2 24 24 23.227 24 22.271V1.729C24 .774 23.2 0 22.222 0h.003z'/%3E%3C/svg%3E")}.vpi-social-mastodon{--icon: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cpath d='M23.268 5.313c-.35-2.578-2.617-4.61-5.304-5.004C17.51.242 15.792 0 11.813 0h-.03c-3.98 0-4.835.242-5.288.309C3.882.692 1.496 2.518.917 5.127.64 6.412.61 7.837.661 9.143c.074 1.874.088 3.745.26 5.611.118 1.24.325 2.47.62 3.68.55 2.237 2.777 4.098 4.96 4.857 2.336.792 4.849.923 7.256.38.265-.061.527-.132.786-.213.585-.184 1.27-.39 1.774-.753a.057.057 0 0 0 .023-.043v-1.809a.052.052 0 0 0-.02-.041.053.053 0 0 0-.046-.01 20.282 20.282 0 0 1-4.709.545c-2.73 0-3.463-1.284-3.674-1.818a5.593 5.593 0 0 1-.319-1.433.053.053 0 0 1 .066-.054c1.517.363 3.072.546 4.632.546.376 0 .75 0 1.125-.01 1.57-.044 3.224-.124 4.768-.422.038-.008.077-.015.11-.024 2.435-.464 4.753-1.92 4.989-5.604.008-.145.03-1.52.03-1.67.002-.512.167-3.63-.024-5.545zm-3.748 9.195h-2.561V8.29c0-1.309-.55-1.976-1.67-1.976-1.23 0-1.846.79-1.846 2.35v3.403h-2.546V8.663c0-1.56-.617-2.35-1.848-2.35-1.112 0-1.668.668-1.67 1.977v6.218H4.822V8.102c0-1.31.337-2.35 1.011-3.12.696-.77 1.608-1.164 2.74-1.164 1.311 0 2.302.5 2.962 1.498l.638 1.06.638-1.06c.66-.999 1.65-1.498 2.96-1.498 1.13 0 2.043.395 2.74 1.164.675.77 1.012 1.81 1.012 3.12z'/%3E%3C/svg%3E")}.vpi-social-npm{--icon: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cpath d='M1.763 0C.786 0 0 .786 0 1.763v20.474C0 23.214.786 24 1.763 24h20.474c.977 0 1.763-.786 1.763-1.763V1.763C24 .786 23.214 0 22.237 0zM5.13 5.323l13.837.019-.009 13.836h-3.464l.01-10.382h-3.456L12.04 19.17H5.113z'/%3E%3C/svg%3E")}.vpi-social-slack{--icon: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cpath d='M5.042 15.165a2.528 2.528 0 0 1-2.52 2.523A2.528 2.528 0 0 1 0 15.165a2.527 2.527 0 0 1 2.522-2.52h2.52v2.52zm1.271 0a2.527 2.527 0 0 1 2.521-2.52 2.527 2.527 0 0 1 2.521 2.52v6.313A2.528 2.528 0 0 1 8.834 24a2.528 2.528 0 0 1-2.521-2.522v-6.313zM8.834 5.042a2.528 2.528 0 0 1-2.521-2.52A2.528 2.528 0 0 1 8.834 0a2.528 2.528 0 0 1 2.521 2.522v2.52H8.834zm0 1.271a2.528 2.528 0 0 1 2.521 2.521 2.528 2.528 0 0 1-2.521 2.521H2.522A2.528 2.528 0 0 1 0 8.834a2.528 2.528 0 0 1 2.522-2.521h6.312zm10.122 2.521a2.528 2.528 0 0 1 2.522-2.521A2.528 2.528 0 0 1 24 8.834a2.528 2.528 0 0 1-2.522 2.521h-2.522V8.834zm-1.268 0a2.528 2.528 0 0 1-2.523 2.521 2.527 2.527 0 0 1-2.52-2.521V2.522A2.527 2.527 0 0 1 15.165 0a2.528 2.528 0 0 1 2.523 2.522v6.312zm-2.523 10.122a2.528 2.528 0 0 1 2.523 2.522A2.528 2.528 0 0 1 15.165 24a2.527 2.527 0 0 1-2.52-2.522v-2.522h2.52zm0-1.268a2.527 2.527 0 0 1-2.52-2.523 2.526 2.526 0 0 1 2.52-2.52h6.313A2.527 2.527 0 0 1 24 15.165a2.528 2.528 0 0 1-2.522 2.523h-6.313z'/%3E%3C/svg%3E")}.vpi-social-twitter,.vpi-social-x{--icon: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cpath d='M18.901 1.153h3.68l-8.04 9.19L24 22.846h-7.406l-5.8-7.584-6.638 7.584H.474l8.6-9.83L0 1.154h7.594l5.243 6.932ZM17.61 20.644h2.039L6.486 3.24H4.298Z'/%3E%3C/svg%3E")}.vpi-social-youtube{--icon: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cpath d='M23.498 6.186a3.016 3.016 0 0 0-2.122-2.136C19.505 3.545 12 3.545 12 3.545s-7.505 0-9.377.505A3.017 3.017 0 0 0 .502 6.186C0 8.07 0 12 0 12s0 3.93.502 5.814a3.016 3.016 0 0 0 2.122 2.136c1.871.505 9.376.505 9.376.505s7.505 0 9.377-.505a3.015 3.015 0 0 0 2.122-2.136C24 15.93 24 12 24 12s0-3.93-.502-5.814zM9.545 15.568V8.432L15.818 12l-6.273 3.568z'/%3E%3C/svg%3E")}.visually-hidden{position:absolute;width:1px;height:1px;white-space:nowrap;clip:rect(0 0 0 0);clip-path:inset(50%);overflow:hidden}.custom-block{border:1px solid transparent;border-radius:8px;padding:16px 16px 8px;line-height:24px;font-size:var(--vp-custom-block-font-size);color:var(--vp-c-text-2)}.custom-block.info{border-color:var(--vp-custom-block-info-border);color:var(--vp-custom-block-info-text);background-color:var(--vp-custom-block-info-bg)}.custom-block.info a,.custom-block.info code{color:var(--vp-c-brand-1)}.custom-block.info a:hover,.custom-block.info a:hover>code{color:var(--vp-c-brand-2)}.custom-block.info code{background-color:var(--vp-custom-block-info-code-bg)}.custom-block.note{border-color:var(--vp-custom-block-note-border);color:var(--vp-custom-block-note-text);background-color:var(--vp-custom-block-note-bg)}.custom-block.note a,.custom-block.note code{color:var(--vp-c-brand-1)}.custom-block.note a:hover,.custom-block.note a:hover>code{color:var(--vp-c-brand-2)}.custom-block.note code{background-color:var(--vp-custom-block-note-code-bg)}.custom-block.tip{border-color:var(--vp-custom-block-tip-border);color:var(--vp-custom-block-tip-text);background-color:var(--vp-custom-block-tip-bg)}.custom-block.tip a,.custom-block.tip code{color:var(--vp-c-tip-1)}.custom-block.tip a:hover,.custom-block.tip a:hover>code{color:var(--vp-c-tip-2)}.custom-block.tip code{background-color:var(--vp-custom-block-tip-code-bg)}.custom-block.important{border-color:var(--vp-custom-block-important-border);color:var(--vp-custom-block-important-text);background-color:var(--vp-custom-block-important-bg)}.custom-block.important a,.custom-block.important code{color:var(--vp-c-important-1)}.custom-block.important a:hover,.custom-block.important a:hover>code{color:var(--vp-c-important-2)}.custom-block.important code{background-color:var(--vp-custom-block-important-code-bg)}.custom-block.warning{border-color:var(--vp-custom-block-warning-border);color:var(--vp-custom-block-warning-text);background-color:var(--vp-custom-block-warning-bg)}.custom-block.warning a,.custom-block.warning code{color:var(--vp-c-warning-1)}.custom-block.warning a:hover,.custom-block.warning a:hover>code{color:var(--vp-c-warning-2)}.custom-block.warning code{background-color:var(--vp-custom-block-warning-code-bg)}.custom-block.danger{border-color:var(--vp-custom-block-danger-border);color:var(--vp-custom-block-danger-text);background-color:var(--vp-custom-block-danger-bg)}.custom-block.danger a,.custom-block.danger code{color:var(--vp-c-danger-1)}.custom-block.danger a:hover,.custom-block.danger a:hover>code{color:var(--vp-c-danger-2)}.custom-block.danger code{background-color:var(--vp-custom-block-danger-code-bg)}.custom-block.caution{border-color:var(--vp-custom-block-caution-border);color:var(--vp-custom-block-caution-text);background-color:var(--vp-custom-block-caution-bg)}.custom-block.caution a,.custom-block.caution code{color:var(--vp-c-caution-1)}.custom-block.caution a:hover,.custom-block.caution a:hover>code{color:var(--vp-c-caution-2)}.custom-block.caution code{background-color:var(--vp-custom-block-caution-code-bg)}.custom-block.details{border-color:var(--vp-custom-block-details-border);color:var(--vp-custom-block-details-text);background-color:var(--vp-custom-block-details-bg)}.custom-block.details a{color:var(--vp-c-brand-1)}.custom-block.details a:hover,.custom-block.details a:hover>code{color:var(--vp-c-brand-2)}.custom-block.details code{background-color:var(--vp-custom-block-details-code-bg)}.custom-block-title{font-weight:600}.custom-block p+p{margin:8px 0}.custom-block.details summary{margin:0 0 8px;font-weight:700;cursor:pointer;-webkit-user-select:none;user-select:none}.custom-block.details summary+p{margin:8px 0}.custom-block a{color:inherit;font-weight:600;text-decoration:underline;text-underline-offset:2px;transition:opacity .25s}.custom-block a:hover{opacity:.75}.custom-block code{font-size:var(--vp-custom-block-code-font-size)}.custom-block.custom-block th,.custom-block.custom-block blockquote>p{font-size:var(--vp-custom-block-font-size);color:inherit}.dark .vp-code span{color:var(--shiki-dark, inherit)}html:not(.dark) .vp-code span{color:var(--shiki-light, inherit)}.vp-code-group{margin-top:16px}.vp-code-group .tabs{position:relative;display:flex;margin-right:-24px;margin-left:-24px;padding:0 12px;background-color:var(--vp-code-tab-bg);overflow-x:auto;overflow-y:hidden;box-shadow:inset 0 -1px var(--vp-code-tab-divider)}@media (min-width: 640px){.vp-code-group .tabs{margin-right:0;margin-left:0;border-radius:8px 8px 0 0}}.vp-code-group .tabs input{position:fixed;opacity:0;pointer-events:none}.vp-code-group .tabs label{position:relative;display:inline-block;border-bottom:1px solid transparent;padding:0 12px;line-height:48px;font-size:14px;font-weight:500;color:var(--vp-code-tab-text-color);white-space:nowrap;cursor:pointer;transition:color .25s}.vp-code-group .tabs label:after{position:absolute;right:8px;bottom:-1px;left:8px;z-index:1;height:2px;border-radius:2px;content:"";background-color:transparent;transition:background-color .25s}.vp-code-group label:hover{color:var(--vp-code-tab-hover-text-color)}.vp-code-group input:checked+label{color:var(--vp-code-tab-active-text-color)}.vp-code-group input:checked+label:after{background-color:var(--vp-code-tab-active-bar-color)}.vp-code-group div[class*=language-],.vp-block{display:none;margin-top:0!important;border-top-left-radius:0!important;border-top-right-radius:0!important}.vp-code-group div[class*=language-].active,.vp-block.active{display:block}.vp-block{padding:20px 24px}.vp-doc h1,.vp-doc h2,.vp-doc h3,.vp-doc h4,.vp-doc h5,.vp-doc h6{position:relative;font-weight:600;outline:none}.vp-doc h1{letter-spacing:-.02em;line-height:40px;font-size:28px}.vp-doc h2{margin:48px 0 16px;border-top:1px solid var(--vp-c-divider);padding-top:24px;letter-spacing:-.02em;line-height:32px;font-size:24px}.vp-doc h3{margin:32px 0 0;letter-spacing:-.01em;line-height:28px;font-size:20px}.vp-doc .header-anchor{position:absolute;top:0;left:0;margin-left:-.87em;font-weight:500;-webkit-user-select:none;user-select:none;opacity:0;text-decoration:none;transition:color .25s,opacity .25s}.vp-doc .header-anchor:before{content:var(--vp-header-anchor-symbol)}.vp-doc h1:hover .header-anchor,.vp-doc h1 .header-anchor:focus,.vp-doc h2:hover .header-anchor,.vp-doc h2 .header-anchor:focus,.vp-doc h3:hover .header-anchor,.vp-doc h3 .header-anchor:focus,.vp-doc h4:hover .header-anchor,.vp-doc h4 .header-anchor:focus,.vp-doc h5:hover .header-anchor,.vp-doc h5 .header-anchor:focus,.vp-doc h6:hover .header-anchor,.vp-doc h6 .header-anchor:focus{opacity:1}@media (min-width: 768px){.vp-doc h1{letter-spacing:-.02em;line-height:40px;font-size:32px}}.vp-doc h2 .header-anchor{top:24px}.vp-doc p,.vp-doc summary{margin:16px 0}.vp-doc p{line-height:28px}.vp-doc blockquote{margin:16px 0;border-left:2px solid var(--vp-c-divider);padding-left:16px;transition:border-color .5s}.vp-doc blockquote>p{margin:0;font-size:16px;color:var(--vp-c-text-2);transition:color .5s}.vp-doc a{font-weight:500;color:var(--vp-c-brand-1);text-decoration:underline;text-underline-offset:2px;transition:color .25s,opacity .25s}.vp-doc a:hover{color:var(--vp-c-brand-2)}.vp-doc strong{font-weight:600}.vp-doc ul,.vp-doc ol{padding-left:1.25rem;margin:16px 0}.vp-doc ul{list-style:disc}.vp-doc ol{list-style:decimal}.vp-doc li+li{margin-top:8px}.vp-doc li>ol,.vp-doc li>ul{margin:8px 0 0}.vp-doc table{display:block;border-collapse:collapse;margin:20px 0;overflow-x:auto}.vp-doc tr{background-color:var(--vp-c-bg);border-top:1px solid var(--vp-c-divider);transition:background-color .5s}.vp-doc tr:nth-child(2n){background-color:var(--vp-c-bg-soft)}.vp-doc th,.vp-doc td{border:1px solid var(--vp-c-divider);padding:8px 16px}.vp-doc th{text-align:left;font-size:14px;font-weight:600;color:var(--vp-c-text-2);background-color:var(--vp-c-bg-soft)}.vp-doc td{font-size:14px}.vp-doc hr{margin:16px 0;border:none;border-top:1px solid var(--vp-c-divider)}.vp-doc .custom-block{margin:16px 0}.vp-doc .custom-block p{margin:8px 0;line-height:24px}.vp-doc .custom-block p:first-child{margin:0}.vp-doc .custom-block div[class*=language-]{margin:8px 0;border-radius:8px}.vp-doc .custom-block div[class*=language-] code{font-weight:400;background-color:transparent}.vp-doc .custom-block .vp-code-group .tabs{margin:0;border-radius:8px 8px 0 0}.vp-doc :not(pre,h1,h2,h3,h4,h5,h6)>code{font-size:var(--vp-code-font-size);color:var(--vp-code-color)}.vp-doc :not(pre)>code{border-radius:4px;padding:3px 6px;background-color:var(--vp-code-bg);transition:color .25s,background-color .5s}.vp-doc a>code{color:var(--vp-code-link-color)}.vp-doc a:hover>code{color:var(--vp-code-link-hover-color)}.vp-doc h1>code,.vp-doc h2>code,.vp-doc h3>code{font-size:.9em}.vp-doc div[class*=language-],.vp-block{position:relative;margin:16px -24px;background-color:var(--vp-code-block-bg);overflow-x:auto;transition:background-color .5s}@media (min-width: 640px){.vp-doc div[class*=language-],.vp-block{border-radius:8px;margin:16px 0}}@media (max-width: 639px){.vp-doc li div[class*=language-]{border-radius:8px 0 0 8px}}.vp-doc div[class*=language-]+div[class*=language-],.vp-doc div[class$=-api]+div[class*=language-],.vp-doc div[class*=language-]+div[class$=-api]>div[class*=language-]{margin-top:-8px}.vp-doc [class*=language-] pre,.vp-doc [class*=language-] code{direction:ltr;text-align:left;white-space:pre;word-spacing:normal;word-break:normal;word-wrap:normal;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-hyphens:none;-moz-hyphens:none;-ms-hyphens:none;hyphens:none}.vp-doc [class*=language-] pre{position:relative;z-index:1;margin:0;padding:20px 0;background:transparent;overflow-x:auto}.vp-doc [class*=language-] code{display:block;padding:0 24px;width:fit-content;min-width:100%;line-height:var(--vp-code-line-height);font-size:var(--vp-code-font-size);color:var(--vp-code-block-color);transition:color .5s}.vp-doc [class*=language-] code .highlighted{background-color:var(--vp-code-line-highlight-color);transition:background-color .5s;margin:0 -24px;padding:0 24px;width:calc(100% + 48px);display:inline-block}.vp-doc [class*=language-] code .highlighted.error{background-color:var(--vp-code-line-error-color)}.vp-doc [class*=language-] code .highlighted.warning{background-color:var(--vp-code-line-warning-color)}.vp-doc [class*=language-] code .diff{transition:background-color .5s;margin:0 -24px;padding:0 24px;width:calc(100% + 48px);display:inline-block}.vp-doc [class*=language-] code .diff:before{position:absolute;left:10px}.vp-doc [class*=language-] .has-focused-lines .line:not(.has-focus){filter:blur(.095rem);opacity:.4;transition:filter .35s,opacity .35s}.vp-doc [class*=language-] .has-focused-lines .line:not(.has-focus){opacity:.7;transition:filter .35s,opacity .35s}.vp-doc [class*=language-]:hover .has-focused-lines .line:not(.has-focus){filter:blur(0);opacity:1}.vp-doc [class*=language-] code .diff.remove{background-color:var(--vp-code-line-diff-remove-color);opacity:.7}.vp-doc [class*=language-] code .diff.remove:before{content:"-";color:var(--vp-code-line-diff-remove-symbol-color)}.vp-doc [class*=language-] code .diff.add{background-color:var(--vp-code-line-diff-add-color)}.vp-doc [class*=language-] code .diff.add:before{content:"+";color:var(--vp-code-line-diff-add-symbol-color)}.vp-doc div[class*=language-].line-numbers-mode{padding-left:32px}.vp-doc .line-numbers-wrapper{position:absolute;top:0;bottom:0;left:0;z-index:3;border-right:1px solid var(--vp-code-block-divider-color);padding-top:20px;width:32px;text-align:center;font-family:var(--vp-font-family-mono);line-height:var(--vp-code-line-height);font-size:var(--vp-code-font-size);color:var(--vp-code-line-number-color);transition:border-color .5s,color .5s}.vp-doc [class*=language-]>button.copy{direction:ltr;position:absolute;top:12px;right:12px;z-index:3;border:1px solid var(--vp-code-copy-code-border-color);border-radius:4px;width:40px;height:40px;background-color:var(--vp-code-copy-code-bg);opacity:0;cursor:pointer;background-image:var(--vp-icon-copy);background-position:50%;background-size:20px;background-repeat:no-repeat;transition:border-color .25s,background-color .25s,opacity .25s}.vp-doc [class*=language-]:hover>button.copy,.vp-doc [class*=language-]>button.copy:focus{opacity:1}.vp-doc [class*=language-]>button.copy:hover,.vp-doc [class*=language-]>button.copy.copied{border-color:var(--vp-code-copy-code-hover-border-color);background-color:var(--vp-code-copy-code-hover-bg)}.vp-doc [class*=language-]>button.copy.copied,.vp-doc [class*=language-]>button.copy:hover.copied{border-radius:0 4px 4px 0;background-color:var(--vp-code-copy-code-hover-bg);background-image:var(--vp-icon-copied)}.vp-doc [class*=language-]>button.copy.copied:before,.vp-doc [class*=language-]>button.copy:hover.copied:before{position:relative;top:-1px;transform:translate(calc(-100% - 1px));display:flex;justify-content:center;align-items:center;border:1px solid var(--vp-code-copy-code-hover-border-color);border-right:0;border-radius:4px 0 0 4px;padding:0 10px;width:fit-content;height:40px;text-align:center;font-size:12px;font-weight:500;color:var(--vp-code-copy-code-active-text);background-color:var(--vp-code-copy-code-hover-bg);white-space:nowrap;content:var(--vp-code-copy-copied-text-content)}.vp-doc [class*=language-]>span.lang{position:absolute;top:2px;right:8px;z-index:2;font-size:12px;font-weight:500;color:var(--vp-code-lang-color);transition:color .4s,opacity .4s}.vp-doc [class*=language-]:hover>button.copy+span.lang,.vp-doc [class*=language-]>button.copy:focus+span.lang{opacity:0}.vp-doc .VPTeamMembers{margin-top:24px}.vp-doc .VPTeamMembers.small.count-1 .container{margin:0!important;max-width:calc((100% - 24px)/2)!important}.vp-doc .VPTeamMembers.small.count-2 .container,.vp-doc .VPTeamMembers.small.count-3 .container{max-width:100%!important}.vp-doc .VPTeamMembers.medium.count-1 .container{margin:0!important;max-width:calc((100% - 24px)/2)!important}:is(.vp-external-link-icon,.vp-doc a[href*="://"],.vp-doc a[target=_blank]):not(.no-icon):after{display:inline-block;margin-top:-1px;margin-left:4px;width:11px;height:11px;background:currentColor;color:var(--vp-c-text-3);flex-shrink:0;--icon: url("data:image/svg+xml, %3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' %3E%3Cpath d='M0 0h24v24H0V0z' fill='none' /%3E%3Cpath d='M9 5v2h6.59L4 18.59 5.41 20 17 8.41V15h2V5H9z' /%3E%3C/svg%3E");-webkit-mask-image:var(--icon);mask-image:var(--icon)}.vp-external-link-icon:after{content:""}.external-link-icon-enabled :is(.vp-doc a[href*="://"],.vp-doc a[target=_blank]):after{content:"";color:currentColor}.vp-sponsor{border-radius:16px;overflow:hidden}.vp-sponsor.aside{border-radius:12px}.vp-sponsor-section+.vp-sponsor-section{margin-top:4px}.vp-sponsor-tier{margin:0 0 4px!important;text-align:center;letter-spacing:1px!important;line-height:24px;width:100%;font-weight:600;color:var(--vp-c-text-2);background-color:var(--vp-c-bg-soft)}.vp-sponsor.normal .vp-sponsor-tier{padding:13px 0 11px;font-size:14px}.vp-sponsor.aside .vp-sponsor-tier{padding:9px 0 7px;font-size:12px}.vp-sponsor-grid+.vp-sponsor-tier{margin-top:4px}.vp-sponsor-grid{display:flex;flex-wrap:wrap;gap:4px}.vp-sponsor-grid.xmini .vp-sponsor-grid-link{height:64px}.vp-sponsor-grid.xmini .vp-sponsor-grid-image{max-width:64px;max-height:22px}.vp-sponsor-grid.mini .vp-sponsor-grid-link{height:72px}.vp-sponsor-grid.mini .vp-sponsor-grid-image{max-width:96px;max-height:24px}.vp-sponsor-grid.small .vp-sponsor-grid-link{height:96px}.vp-sponsor-grid.small .vp-sponsor-grid-image{max-width:96px;max-height:24px}.vp-sponsor-grid.medium .vp-sponsor-grid-link{height:112px}.vp-sponsor-grid.medium .vp-sponsor-grid-image{max-width:120px;max-height:36px}.vp-sponsor-grid.big .vp-sponsor-grid-link{height:184px}.vp-sponsor-grid.big .vp-sponsor-grid-image{max-width:192px;max-height:56px}.vp-sponsor-grid[data-vp-grid="2"] .vp-sponsor-grid-item{width:calc((100% - 4px)/2)}.vp-sponsor-grid[data-vp-grid="3"] .vp-sponsor-grid-item{width:calc((100% - 4px * 2) / 3)}.vp-sponsor-grid[data-vp-grid="4"] .vp-sponsor-grid-item{width:calc((100% - 12px)/4)}.vp-sponsor-grid[data-vp-grid="5"] .vp-sponsor-grid-item{width:calc((100% - 16px)/5)}.vp-sponsor-grid[data-vp-grid="6"] .vp-sponsor-grid-item{width:calc((100% - 4px * 5) / 6)}.vp-sponsor-grid-item{flex-shrink:0;width:100%;background-color:var(--vp-c-bg-soft);transition:background-color .25s}.vp-sponsor-grid-item:hover{background-color:var(--vp-c-default-soft)}.vp-sponsor-grid-item:hover .vp-sponsor-grid-image{filter:grayscale(0) invert(0)}.vp-sponsor-grid-item.empty:hover{background-color:var(--vp-c-bg-soft)}.dark .vp-sponsor-grid-item:hover{background-color:var(--vp-c-white)}.dark .vp-sponsor-grid-item.empty:hover{background-color:var(--vp-c-bg-soft)}.vp-sponsor-grid-link{display:flex}.vp-sponsor-grid-box{display:flex;justify-content:center;align-items:center;width:100%}.vp-sponsor-grid-image{max-width:100%;filter:grayscale(1);transition:filter .25s}.dark .vp-sponsor-grid-image{filter:grayscale(1) invert(1)}.VPBadge{display:inline-block;margin-left:2px;border:1px solid transparent;border-radius:12px;padding:0 10px;line-height:22px;font-size:12px;font-weight:500;transform:translateY(-2px)}.VPBadge.small{padding:0 6px;line-height:18px;font-size:10px;transform:translateY(-8px)}.VPDocFooter .VPBadge{display:none}.vp-doc h1>.VPBadge{margin-top:4px;vertical-align:top}.vp-doc h2>.VPBadge{margin-top:3px;padding:0 8px;vertical-align:top}.vp-doc h3>.VPBadge{vertical-align:middle}.vp-doc h4>.VPBadge,.vp-doc h5>.VPBadge,.vp-doc h6>.VPBadge{vertical-align:middle;line-height:18px}.VPBadge.info{border-color:var(--vp-badge-info-border);color:var(--vp-badge-info-text);background-color:var(--vp-badge-info-bg)}.VPBadge.tip{border-color:var(--vp-badge-tip-border);color:var(--vp-badge-tip-text);background-color:var(--vp-badge-tip-bg)}.VPBadge.warning{border-color:var(--vp-badge-warning-border);color:var(--vp-badge-warning-text);background-color:var(--vp-badge-warning-bg)}.VPBadge.danger{border-color:var(--vp-badge-danger-border);color:var(--vp-badge-danger-text);background-color:var(--vp-badge-danger-bg)}.VPBackdrop[data-v-c79a1216]{position:fixed;top:0;right:0;bottom:0;left:0;z-index:var(--vp-z-index-backdrop);background:var(--vp-backdrop-bg-color);transition:opacity .5s}.VPBackdrop.fade-enter-from[data-v-c79a1216],.VPBackdrop.fade-leave-to[data-v-c79a1216]{opacity:0}.VPBackdrop.fade-leave-active[data-v-c79a1216]{transition-duration:.25s}@media (min-width: 1280px){.VPBackdrop[data-v-c79a1216]{display:none}}.NotFound[data-v-f87ff6e4]{padding:64px 24px 96px;text-align:center}@media (min-width: 768px){.NotFound[data-v-f87ff6e4]{padding:96px 32px 168px}}.code[data-v-f87ff6e4]{line-height:64px;font-size:64px;font-weight:600}.title[data-v-f87ff6e4]{padding-top:12px;letter-spacing:2px;line-height:20px;font-size:20px;font-weight:700}.divider[data-v-f87ff6e4]{margin:24px auto 18px;width:64px;height:1px;background-color:var(--vp-c-divider)}.quote[data-v-f87ff6e4]{margin:0 auto;max-width:256px;font-size:14px;font-weight:500;color:var(--vp-c-text-2)}.action[data-v-f87ff6e4]{padding-top:20px}.link[data-v-f87ff6e4]{display:inline-block;border:1px solid var(--vp-c-brand-1);border-radius:16px;padding:3px 16px;font-size:14px;font-weight:500;color:var(--vp-c-brand-1);transition:border-color .25s,color .25s}.link[data-v-f87ff6e4]:hover{border-color:var(--vp-c-brand-2);color:var(--vp-c-brand-2)}.root[data-v-b933a997]{position:relative;z-index:1}.nested[data-v-b933a997]{padding-right:16px;padding-left:16px}.outline-link[data-v-b933a997]{display:block;line-height:32px;font-size:14px;font-weight:400;color:var(--vp-c-text-2);white-space:nowrap;overflow:hidden;text-overflow:ellipsis;transition:color .5s}.outline-link[data-v-b933a997]:hover,.outline-link.active[data-v-b933a997]{color:var(--vp-c-text-1);transition:color .25s}.outline-link.nested[data-v-b933a997]{padding-left:13px}.VPDocAsideOutline[data-v-935f8a84]{display:none}.VPDocAsideOutline.has-outline[data-v-935f8a84]{display:block}.content[data-v-935f8a84]{position:relative;border-left:1px solid var(--vp-c-divider);padding-left:16px;font-size:13px;font-weight:500}.outline-marker[data-v-935f8a84]{position:absolute;top:32px;left:-1px;z-index:0;opacity:0;width:2px;border-radius:2px;height:18px;background-color:var(--vp-c-brand-1);transition:top .25s cubic-bezier(0,1,.5,1),background-color .5s,opacity .25s}.outline-title[data-v-935f8a84]{line-height:32px;font-size:14px;font-weight:600}.VPDocAside[data-v-3f215769]{display:flex;flex-direction:column;flex-grow:1}.spacer[data-v-3f215769]{flex-grow:1}.VPDocAside[data-v-3f215769] .spacer+.VPDocAsideSponsors,.VPDocAside[data-v-3f215769] .spacer+.VPDocAsideCarbonAds{margin-top:24px}.VPDocAside[data-v-3f215769] .VPDocAsideSponsors+.VPDocAsideCarbonAds{margin-top:16px}.VPLastUpdated[data-v-7e05ebdb]{line-height:24px;font-size:14px;font-weight:500;color:var(--vp-c-text-2)}@media (min-width: 640px){.VPLastUpdated[data-v-7e05ebdb]{line-height:32px;font-size:14px;font-weight:500}}.VPDocFooter[data-v-09de1c0f]{margin-top:64px}.edit-info[data-v-09de1c0f]{padding-bottom:18px}@media (min-width: 640px){.edit-info[data-v-09de1c0f]{display:flex;justify-content:space-between;align-items:center;padding-bottom:14px}}.edit-link-button[data-v-09de1c0f]{display:flex;align-items:center;border:0;line-height:32px;font-size:14px;font-weight:500;color:var(--vp-c-brand-1);transition:color .25s}.edit-link-button[data-v-09de1c0f]:hover{color:var(--vp-c-brand-2)}.edit-link-icon[data-v-09de1c0f]{margin-right:8px}.prev-next[data-v-09de1c0f]{border-top:1px solid var(--vp-c-divider);padding-top:24px;display:grid;grid-row-gap:8px}@media (min-width: 640px){.prev-next[data-v-09de1c0f]{grid-template-columns:repeat(2,1fr);grid-column-gap:16px}}.pager-link[data-v-09de1c0f]{display:block;border:1px solid var(--vp-c-divider);border-radius:8px;padding:11px 16px 13px;width:100%;height:100%;transition:border-color .25s}.pager-link[data-v-09de1c0f]:hover{border-color:var(--vp-c-brand-1)}.pager-link.next[data-v-09de1c0f]{margin-left:auto;text-align:right}.desc[data-v-09de1c0f]{display:block;line-height:20px;font-size:12px;font-weight:500;color:var(--vp-c-text-2)}.title[data-v-09de1c0f]{display:block;line-height:20px;font-size:14px;font-weight:500;color:var(--vp-c-brand-1);transition:color .25s}.VPDoc[data-v-39a288b8]{padding:32px 24px 96px;width:100%}@media (min-width: 768px){.VPDoc[data-v-39a288b8]{padding:48px 32px 128px}}@media (min-width: 960px){.VPDoc[data-v-39a288b8]{padding:48px 32px 0}.VPDoc:not(.has-sidebar) .container[data-v-39a288b8]{display:flex;justify-content:center;max-width:992px}.VPDoc:not(.has-sidebar) .content[data-v-39a288b8]{max-width:752px}}@media (min-width: 1280px){.VPDoc .container[data-v-39a288b8]{display:flex;justify-content:center}.VPDoc .aside[data-v-39a288b8]{display:block}}@media (min-width: 1440px){.VPDoc:not(.has-sidebar) .content[data-v-39a288b8]{max-width:784px}.VPDoc:not(.has-sidebar) .container[data-v-39a288b8]{max-width:1104px}}.container[data-v-39a288b8]{margin:0 auto;width:100%}.aside[data-v-39a288b8]{position:relative;display:none;order:2;flex-grow:1;padding-left:32px;width:100%;max-width:256px}.left-aside[data-v-39a288b8]{order:1;padding-left:unset;padding-right:32px}.aside-container[data-v-39a288b8]{position:fixed;top:0;padding-top:calc(var(--vp-nav-height) + var(--vp-layout-top-height, 0px) + var(--vp-doc-top-height, 0px) + 48px);width:224px;height:100vh;overflow-x:hidden;overflow-y:auto;scrollbar-width:none}.aside-container[data-v-39a288b8]::-webkit-scrollbar{display:none}.aside-curtain[data-v-39a288b8]{position:fixed;bottom:0;z-index:10;width:224px;height:32px;background:linear-gradient(transparent,var(--vp-c-bg) 70%)}.aside-content[data-v-39a288b8]{display:flex;flex-direction:column;min-height:calc(100vh - (var(--vp-nav-height) + var(--vp-layout-top-height, 0px) + 48px));padding-bottom:32px}.content[data-v-39a288b8]{position:relative;margin:0 auto;width:100%}@media (min-width: 960px){.content[data-v-39a288b8]{padding:0 32px 128px}}@media (min-width: 1280px){.content[data-v-39a288b8]{order:1;margin:0;min-width:640px}}.content-container[data-v-39a288b8]{margin:0 auto}.VPDoc.has-aside .content-container[data-v-39a288b8]{max-width:688px}.VPButton[data-v-cad61b99]{display:inline-block;border:1px solid transparent;text-align:center;font-weight:600;white-space:nowrap;transition:color .25s,border-color .25s,background-color .25s}.VPButton[data-v-cad61b99]:active{transition:color .1s,border-color .1s,background-color .1s}.VPButton.medium[data-v-cad61b99]{border-radius:20px;padding:0 20px;line-height:38px;font-size:14px}.VPButton.big[data-v-cad61b99]{border-radius:24px;padding:0 24px;line-height:46px;font-size:16px}.VPButton.brand[data-v-cad61b99]{border-color:var(--vp-button-brand-border);color:var(--vp-button-brand-text);background-color:var(--vp-button-brand-bg)}.VPButton.brand[data-v-cad61b99]:hover{border-color:var(--vp-button-brand-hover-border);color:var(--vp-button-brand-hover-text);background-color:var(--vp-button-brand-hover-bg)}.VPButton.brand[data-v-cad61b99]:active{border-color:var(--vp-button-brand-active-border);color:var(--vp-button-brand-active-text);background-color:var(--vp-button-brand-active-bg)}.VPButton.alt[data-v-cad61b99]{border-color:var(--vp-button-alt-border);color:var(--vp-button-alt-text);background-color:var(--vp-button-alt-bg)}.VPButton.alt[data-v-cad61b99]:hover{border-color:var(--vp-button-alt-hover-border);color:var(--vp-button-alt-hover-text);background-color:var(--vp-button-alt-hover-bg)}.VPButton.alt[data-v-cad61b99]:active{border-color:var(--vp-button-alt-active-border);color:var(--vp-button-alt-active-text);background-color:var(--vp-button-alt-active-bg)}.VPButton.sponsor[data-v-cad61b99]{border-color:var(--vp-button-sponsor-border);color:var(--vp-button-sponsor-text);background-color:var(--vp-button-sponsor-bg)}.VPButton.sponsor[data-v-cad61b99]:hover{border-color:var(--vp-button-sponsor-hover-border);color:var(--vp-button-sponsor-hover-text);background-color:var(--vp-button-sponsor-hover-bg)}.VPButton.sponsor[data-v-cad61b99]:active{border-color:var(--vp-button-sponsor-active-border);color:var(--vp-button-sponsor-active-text);background-color:var(--vp-button-sponsor-active-bg)}html:not(.dark) .VPImage.dark[data-v-8426fc1a]{display:none}.dark .VPImage.light[data-v-8426fc1a]{display:none}.VPHero[data-v-303bb580]{margin-top:calc((var(--vp-nav-height) + var(--vp-layout-top-height, 0px)) * -1);padding:calc(var(--vp-nav-height) + var(--vp-layout-top-height, 0px) + 48px) 24px 48px}@media (min-width: 640px){.VPHero[data-v-303bb580]{padding:calc(var(--vp-nav-height) + var(--vp-layout-top-height, 0px) + 80px) 48px 64px}}@media (min-width: 960px){.VPHero[data-v-303bb580]{padding:calc(var(--vp-nav-height) + var(--vp-layout-top-height, 0px) + 80px) 64px 64px}}.container[data-v-303bb580]{display:flex;flex-direction:column;margin:0 auto;max-width:1152px}@media (min-width: 960px){.container[data-v-303bb580]{flex-direction:row}}.main[data-v-303bb580]{position:relative;z-index:10;order:2;flex-grow:1;flex-shrink:0}.VPHero.has-image .container[data-v-303bb580]{text-align:center}@media (min-width: 960px){.VPHero.has-image .container[data-v-303bb580]{text-align:left}}@media (min-width: 960px){.main[data-v-303bb580]{order:1;width:calc((100% / 3) * 2)}.VPHero.has-image .main[data-v-303bb580]{max-width:592px}}.name[data-v-303bb580],.text[data-v-303bb580]{max-width:392px;letter-spacing:-.4px;line-height:40px;font-size:32px;font-weight:700;white-space:pre-wrap}.VPHero.has-image .name[data-v-303bb580],.VPHero.has-image .text[data-v-303bb580]{margin:0 auto}.name[data-v-303bb580]{color:var(--vp-home-hero-name-color)}.clip[data-v-303bb580]{background:var(--vp-home-hero-name-background);-webkit-background-clip:text;background-clip:text;-webkit-text-fill-color:var(--vp-home-hero-name-color)}@media (min-width: 640px){.name[data-v-303bb580],.text[data-v-303bb580]{max-width:576px;line-height:56px;font-size:48px}}@media (min-width: 960px){.name[data-v-303bb580],.text[data-v-303bb580]{line-height:64px;font-size:56px}.VPHero.has-image .name[data-v-303bb580],.VPHero.has-image .text[data-v-303bb580]{margin:0}}.tagline[data-v-303bb580]{padding-top:8px;max-width:392px;line-height:28px;font-size:18px;font-weight:500;white-space:pre-wrap;color:var(--vp-c-text-2)}.VPHero.has-image .tagline[data-v-303bb580]{margin:0 auto}@media (min-width: 640px){.tagline[data-v-303bb580]{padding-top:12px;max-width:576px;line-height:32px;font-size:20px}}@media (min-width: 960px){.tagline[data-v-303bb580]{line-height:36px;font-size:24px}.VPHero.has-image .tagline[data-v-303bb580]{margin:0}}.actions[data-v-303bb580]{display:flex;flex-wrap:wrap;margin:-6px;padding-top:24px}.VPHero.has-image .actions[data-v-303bb580]{justify-content:center}@media (min-width: 640px){.actions[data-v-303bb580]{padding-top:32px}}@media (min-width: 960px){.VPHero.has-image .actions[data-v-303bb580]{justify-content:flex-start}}.action[data-v-303bb580]{flex-shrink:0;padding:6px}.image[data-v-303bb580]{order:1;margin:-76px -24px -48px}@media (min-width: 640px){.image[data-v-303bb580]{margin:-108px -24px -48px}}@media (min-width: 960px){.image[data-v-303bb580]{flex-grow:1;order:2;margin:0;min-height:100%}}.image-container[data-v-303bb580]{position:relative;margin:0 auto;width:320px;height:320px}@media (min-width: 640px){.image-container[data-v-303bb580]{width:392px;height:392px}}@media (min-width: 960px){.image-container[data-v-303bb580]{display:flex;justify-content:center;align-items:center;width:100%;height:100%;transform:translate(-32px,-32px)}}.image-bg[data-v-303bb580]{position:absolute;top:50%;left:50%;border-radius:50%;width:192px;height:192px;background-image:var(--vp-home-hero-image-background-image);filter:var(--vp-home-hero-image-filter);transform:translate(-50%,-50%)}@media (min-width: 640px){.image-bg[data-v-303bb580]{width:256px;height:256px}}@media (min-width: 960px){.image-bg[data-v-303bb580]{width:320px;height:320px}}[data-v-303bb580] .image-src{position:absolute;top:50%;left:50%;max-width:192px;max-height:192px;transform:translate(-50%,-50%)}@media (min-width: 640px){[data-v-303bb580] .image-src{max-width:256px;max-height:256px}}@media (min-width: 960px){[data-v-303bb580] .image-src{max-width:320px;max-height:320px}}.VPFeature[data-v-a3976bdc]{display:block;border:1px solid var(--vp-c-bg-soft);border-radius:12px;height:100%;background-color:var(--vp-c-bg-soft);transition:border-color .25s,background-color .25s}.VPFeature.link[data-v-a3976bdc]:hover{border-color:var(--vp-c-brand-1)}.box[data-v-a3976bdc]{display:flex;flex-direction:column;padding:24px;height:100%}.box[data-v-a3976bdc]>.VPImage{margin-bottom:20px}.icon[data-v-a3976bdc]{display:flex;justify-content:center;align-items:center;margin-bottom:20px;border-radius:6px;background-color:var(--vp-c-default-soft);width:48px;height:48px;font-size:24px;transition:background-color .25s}.title[data-v-a3976bdc]{line-height:24px;font-size:16px;font-weight:600}.details[data-v-a3976bdc]{flex-grow:1;padding-top:8px;line-height:24px;font-size:14px;font-weight:500;color:var(--vp-c-text-2)}.link-text[data-v-a3976bdc]{padding-top:8px}.link-text-value[data-v-a3976bdc]{display:flex;align-items:center;font-size:14px;font-weight:500;color:var(--vp-c-brand-1)}.link-text-icon[data-v-a3976bdc]{margin-left:6px}.VPFeatures[data-v-a6181336]{position:relative;padding:0 24px}@media (min-width: 640px){.VPFeatures[data-v-a6181336]{padding:0 48px}}@media (min-width: 960px){.VPFeatures[data-v-a6181336]{padding:0 64px}}.container[data-v-a6181336]{margin:0 auto;max-width:1152px}.items[data-v-a6181336]{display:flex;flex-wrap:wrap;margin:-8px}.item[data-v-a6181336]{padding:8px;width:100%}@media (min-width: 640px){.item.grid-2[data-v-a6181336],.item.grid-4[data-v-a6181336],.item.grid-6[data-v-a6181336]{width:50%}}@media (min-width: 768px){.item.grid-2[data-v-a6181336],.item.grid-4[data-v-a6181336]{width:50%}.item.grid-3[data-v-a6181336],.item.grid-6[data-v-a6181336]{width:calc(100% / 3)}}@media (min-width: 960px){.item.grid-4[data-v-a6181336]{width:25%}}.container[data-v-82d4af08]{margin:auto;width:100%;max-width:1280px;padding:0 24px}@media (min-width: 640px){.container[data-v-82d4af08]{padding:0 48px}}@media (min-width: 960px){.container[data-v-82d4af08]{width:100%;padding:0 64px}}.vp-doc[data-v-82d4af08] .VPHomeSponsors,.vp-doc[data-v-82d4af08] .VPTeamPage{margin-left:var(--vp-offset, calc(50% - 50vw) );margin-right:var(--vp-offset, calc(50% - 50vw) )}.vp-doc[data-v-82d4af08] .VPHomeSponsors h2{border-top:none;letter-spacing:normal}.vp-doc[data-v-82d4af08] .VPHomeSponsors a,.vp-doc[data-v-82d4af08] .VPTeamPage a{text-decoration:none}.VPHome[data-v-686f80a6]{margin-bottom:96px}@media (min-width: 768px){.VPHome[data-v-686f80a6]{margin-bottom:128px}}.VPContent[data-v-1428d186]{flex-grow:1;flex-shrink:0;margin:var(--vp-layout-top-height, 0px) auto 0;width:100%}.VPContent.is-home[data-v-1428d186]{width:100%;max-width:100%}.VPContent.has-sidebar[data-v-1428d186]{margin:0}@media (min-width: 960px){.VPContent[data-v-1428d186]{padding-top:var(--vp-nav-height)}.VPContent.has-sidebar[data-v-1428d186]{margin:var(--vp-layout-top-height, 0px) 0 0;padding-left:var(--vp-sidebar-width)}}@media (min-width: 1440px){.VPContent.has-sidebar[data-v-1428d186]{padding-right:calc((100vw - var(--vp-layout-max-width)) / 2);padding-left:calc((100vw - var(--vp-layout-max-width)) / 2 + var(--vp-sidebar-width))}}.VPFooter[data-v-e315a0ad]{position:relative;z-index:var(--vp-z-index-footer);border-top:1px solid var(--vp-c-gutter);padding:32px 24px;background-color:var(--vp-c-bg)}.VPFooter.has-sidebar[data-v-e315a0ad]{display:none}.VPFooter[data-v-e315a0ad] a{text-decoration-line:underline;text-underline-offset:2px;transition:color .25s}.VPFooter[data-v-e315a0ad] a:hover{color:var(--vp-c-text-1)}@media (min-width: 768px){.VPFooter[data-v-e315a0ad]{padding:32px}}.container[data-v-e315a0ad]{margin:0 auto;max-width:var(--vp-layout-max-width);text-align:center}.message[data-v-e315a0ad],.copyright[data-v-e315a0ad]{line-height:24px;font-size:14px;font-weight:500;color:var(--vp-c-text-2)}.VPLocalNavOutlineDropdown[data-v-d2ecc192]{padding:12px 20px 11px}@media (min-width: 960px){.VPLocalNavOutlineDropdown[data-v-d2ecc192]{padding:12px 36px 11px}}.VPLocalNavOutlineDropdown button[data-v-d2ecc192]{display:block;font-size:12px;font-weight:500;line-height:24px;color:var(--vp-c-text-2);transition:color .5s;position:relative}.VPLocalNavOutlineDropdown button[data-v-d2ecc192]:hover{color:var(--vp-c-text-1);transition:color .25s}.VPLocalNavOutlineDropdown button.open[data-v-d2ecc192]{color:var(--vp-c-text-1)}.icon[data-v-d2ecc192]{display:inline-block;vertical-align:middle;margin-left:2px;font-size:14px;transform:rotate(0);transition:transform .25s}@media (min-width: 960px){.VPLocalNavOutlineDropdown button[data-v-d2ecc192]{font-size:14px}.icon[data-v-d2ecc192]{font-size:16px}}.open>.icon[data-v-d2ecc192]{transform:rotate(90deg)}.items[data-v-d2ecc192]{position:absolute;top:40px;right:16px;left:16px;display:grid;gap:1px;border:1px solid var(--vp-c-border);border-radius:8px;background-color:var(--vp-c-gutter);max-height:calc(var(--vp-vh, 100vh) - 86px);overflow:hidden auto;box-shadow:var(--vp-shadow-3)}@media (min-width: 960px){.items[data-v-d2ecc192]{right:auto;left:calc(var(--vp-sidebar-width) + 32px);width:320px}}.header[data-v-d2ecc192]{background-color:var(--vp-c-bg-soft)}.top-link[data-v-d2ecc192]{display:block;padding:0 16px;line-height:48px;font-size:14px;font-weight:500;color:var(--vp-c-brand-1)}.outline[data-v-d2ecc192]{padding:8px 0;background-color:var(--vp-c-bg-soft)}.flyout-enter-active[data-v-d2ecc192]{transition:all .2s ease-out}.flyout-leave-active[data-v-d2ecc192]{transition:all .15s ease-in}.flyout-enter-from[data-v-d2ecc192],.flyout-leave-to[data-v-d2ecc192]{opacity:0;transform:translateY(-16px)}.VPLocalNav[data-v-a6f0e41e]{position:sticky;top:0;left:0;z-index:var(--vp-z-index-local-nav);border-bottom:1px solid var(--vp-c-gutter);padding-top:var(--vp-layout-top-height, 0px);width:100%;background-color:var(--vp-local-nav-bg-color)}.VPLocalNav.fixed[data-v-a6f0e41e]{position:fixed}@media (min-width: 960px){.VPLocalNav[data-v-a6f0e41e]{top:var(--vp-nav-height)}.VPLocalNav.has-sidebar[data-v-a6f0e41e]{padding-left:var(--vp-sidebar-width)}.VPLocalNav.empty[data-v-a6f0e41e]{display:none}}@media (min-width: 1280px){.VPLocalNav[data-v-a6f0e41e]{display:none}}@media (min-width: 1440px){.VPLocalNav.has-sidebar[data-v-a6f0e41e]{padding-left:calc((100vw - var(--vp-layout-max-width)) / 2 + var(--vp-sidebar-width))}}.container[data-v-a6f0e41e]{display:flex;justify-content:space-between;align-items:center}.menu[data-v-a6f0e41e]{display:flex;align-items:center;padding:12px 24px 11px;line-height:24px;font-size:12px;font-weight:500;color:var(--vp-c-text-2);transition:color .5s}.menu[data-v-a6f0e41e]:hover{color:var(--vp-c-text-1);transition:color .25s}@media (min-width: 768px){.menu[data-v-a6f0e41e]{padding:0 32px}}@media (min-width: 960px){.menu[data-v-a6f0e41e]{display:none}}.menu-icon[data-v-a6f0e41e]{margin-right:8px;font-size:14px}.VPOutlineDropdown[data-v-a6f0e41e]{padding:12px 24px 11px}@media (min-width: 768px){.VPOutlineDropdown[data-v-a6f0e41e]{padding:12px 32px 11px}}.VPSwitch[data-v-1d5665e3]{position:relative;border-radius:11px;display:block;width:40px;height:22px;flex-shrink:0;border:1px solid var(--vp-input-border-color);background-color:var(--vp-input-switch-bg-color);transition:border-color .25s!important}.VPSwitch[data-v-1d5665e3]:hover{border-color:var(--vp-c-brand-1)}.check[data-v-1d5665e3]{position:absolute;top:1px;left:1px;width:18px;height:18px;border-radius:50%;background-color:var(--vp-c-neutral-inverse);box-shadow:var(--vp-shadow-1);transition:transform .25s!important}.icon[data-v-1d5665e3]{position:relative;display:block;width:18px;height:18px;border-radius:50%;overflow:hidden}.icon[data-v-1d5665e3] [class^=vpi-]{position:absolute;top:3px;left:3px;width:12px;height:12px;color:var(--vp-c-text-2)}.dark .icon[data-v-1d5665e3] [class^=vpi-]{color:var(--vp-c-text-1);transition:opacity .25s!important}.sun[data-v-d1f28634]{opacity:1}.moon[data-v-d1f28634],.dark .sun[data-v-d1f28634]{opacity:0}.dark .moon[data-v-d1f28634]{opacity:1}.dark .VPSwitchAppearance[data-v-d1f28634] .check{transform:translate(18px)}.VPNavBarAppearance[data-v-e6aabb21]{display:none}@media (min-width: 1280px){.VPNavBarAppearance[data-v-e6aabb21]{display:flex;align-items:center}}.VPMenuGroup+.VPMenuLink[data-v-43f1e123]{margin:12px -12px 0;border-top:1px solid var(--vp-c-divider);padding:12px 12px 0}.link[data-v-43f1e123]{display:block;border-radius:6px;padding:0 12px;line-height:32px;font-size:14px;font-weight:500;color:var(--vp-c-text-1);white-space:nowrap;transition:background-color .25s,color .25s}.link[data-v-43f1e123]:hover{color:var(--vp-c-brand-1);background-color:var(--vp-c-default-soft)}.link.active[data-v-43f1e123]{color:var(--vp-c-brand-1)}.VPMenuGroup[data-v-69e747b5]{margin:12px -12px 0;border-top:1px solid var(--vp-c-divider);padding:12px 12px 0}.VPMenuGroup[data-v-69e747b5]:first-child{margin-top:0;border-top:0;padding-top:0}.VPMenuGroup+.VPMenuGroup[data-v-69e747b5]{margin-top:12px;border-top:1px solid var(--vp-c-divider)}.title[data-v-69e747b5]{padding:0 12px;line-height:32px;font-size:14px;font-weight:600;color:var(--vp-c-text-2);white-space:nowrap;transition:color .25s}.VPMenu[data-v-e7ea1737]{border-radius:12px;padding:12px;min-width:128px;border:1px solid var(--vp-c-divider);background-color:var(--vp-c-bg-elv);box-shadow:var(--vp-shadow-3);transition:background-color .5s;max-height:calc(100vh - var(--vp-nav-height));overflow-y:auto}.VPMenu[data-v-e7ea1737] .group{margin:0 -12px;padding:0 12px 12px}.VPMenu[data-v-e7ea1737] .group+.group{border-top:1px solid var(--vp-c-divider);padding:11px 12px 12px}.VPMenu[data-v-e7ea1737] .group:last-child{padding-bottom:0}.VPMenu[data-v-e7ea1737] .group+.item{border-top:1px solid var(--vp-c-divider);padding:11px 16px 0}.VPMenu[data-v-e7ea1737] .item{padding:0 16px;white-space:nowrap}.VPMenu[data-v-e7ea1737] .label{flex-grow:1;line-height:28px;font-size:12px;font-weight:500;color:var(--vp-c-text-2);transition:color .5s}.VPMenu[data-v-e7ea1737] .action{padding-left:24px}.VPFlyout[data-v-b6c34ac9]{position:relative}.VPFlyout[data-v-b6c34ac9]:hover{color:var(--vp-c-brand-1);transition:color .25s}.VPFlyout:hover .text[data-v-b6c34ac9]{color:var(--vp-c-text-2)}.VPFlyout:hover .icon[data-v-b6c34ac9]{fill:var(--vp-c-text-2)}.VPFlyout.active .text[data-v-b6c34ac9]{color:var(--vp-c-brand-1)}.VPFlyout.active:hover .text[data-v-b6c34ac9]{color:var(--vp-c-brand-2)}.VPFlyout:hover .menu[data-v-b6c34ac9],.button[aria-expanded=true]+.menu[data-v-b6c34ac9]{opacity:1;visibility:visible;transform:translateY(0)}.button[aria-expanded=false]+.menu[data-v-b6c34ac9]{opacity:0;visibility:hidden;transform:translateY(0)}.button[data-v-b6c34ac9]{display:flex;align-items:center;padding:0 12px;height:var(--vp-nav-height);color:var(--vp-c-text-1);transition:color .5s}.text[data-v-b6c34ac9]{display:flex;align-items:center;line-height:var(--vp-nav-height);font-size:14px;font-weight:500;color:var(--vp-c-text-1);transition:color .25s}.option-icon[data-v-b6c34ac9]{margin-right:0;font-size:16px}.text-icon[data-v-b6c34ac9]{margin-left:4px;font-size:14px}.icon[data-v-b6c34ac9]{font-size:20px;transition:fill .25s}.menu[data-v-b6c34ac9]{position:absolute;top:calc(var(--vp-nav-height) / 2 + 20px);right:0;opacity:0;visibility:hidden;transition:opacity .25s,visibility .25s,transform .25s}.VPSocialLink[data-v-eee4e7cb]{display:flex;justify-content:center;align-items:center;width:36px;height:36px;color:var(--vp-c-text-2);transition:color .5s}.VPSocialLink[data-v-eee4e7cb]:hover{color:var(--vp-c-text-1);transition:color .25s}.VPSocialLink[data-v-eee4e7cb]>svg,.VPSocialLink[data-v-eee4e7cb]>[class^=vpi-social-]{width:20px;height:20px;fill:currentColor}.VPSocialLinks[data-v-7bc22406]{display:flex;justify-content:center}.VPNavBarExtra[data-v-d0bd9dde]{display:none;margin-right:-12px}@media (min-width: 768px){.VPNavBarExtra[data-v-d0bd9dde]{display:block}}@media (min-width: 1280px){.VPNavBarExtra[data-v-d0bd9dde]{display:none}}.trans-title[data-v-d0bd9dde]{padding:0 24px 0 12px;line-height:32px;font-size:14px;font-weight:700;color:var(--vp-c-text-1)}.item.appearance[data-v-d0bd9dde],.item.social-links[data-v-d0bd9dde]{display:flex;align-items:center;padding:0 12px}.item.appearance[data-v-d0bd9dde]{min-width:176px}.appearance-action[data-v-d0bd9dde]{margin-right:-2px}.social-links-list[data-v-d0bd9dde]{margin:-4px -8px}.VPNavBarHamburger[data-v-e5dd9c1c]{display:flex;justify-content:center;align-items:center;width:48px;height:var(--vp-nav-height)}@media (min-width: 768px){.VPNavBarHamburger[data-v-e5dd9c1c]{display:none}}.container[data-v-e5dd9c1c]{position:relative;width:16px;height:14px;overflow:hidden}.VPNavBarHamburger:hover .top[data-v-e5dd9c1c]{top:0;left:0;transform:translate(4px)}.VPNavBarHamburger:hover .middle[data-v-e5dd9c1c]{top:6px;left:0;transform:translate(0)}.VPNavBarHamburger:hover .bottom[data-v-e5dd9c1c]{top:12px;left:0;transform:translate(8px)}.VPNavBarHamburger.active .top[data-v-e5dd9c1c]{top:6px;transform:translate(0) rotate(225deg)}.VPNavBarHamburger.active .middle[data-v-e5dd9c1c]{top:6px;transform:translate(16px)}.VPNavBarHamburger.active .bottom[data-v-e5dd9c1c]{top:6px;transform:translate(0) rotate(135deg)}.VPNavBarHamburger.active:hover .top[data-v-e5dd9c1c],.VPNavBarHamburger.active:hover .middle[data-v-e5dd9c1c],.VPNavBarHamburger.active:hover .bottom[data-v-e5dd9c1c]{background-color:var(--vp-c-text-2);transition:top .25s,background-color .25s,transform .25s}.top[data-v-e5dd9c1c],.middle[data-v-e5dd9c1c],.bottom[data-v-e5dd9c1c]{position:absolute;width:16px;height:2px;background-color:var(--vp-c-text-1);transition:top .25s,background-color .5s,transform .25s}.top[data-v-e5dd9c1c]{top:0;left:0;transform:translate(0)}.middle[data-v-e5dd9c1c]{top:6px;left:0;transform:translate(8px)}.bottom[data-v-e5dd9c1c]{top:12px;left:0;transform:translate(4px)}.VPNavBarMenuLink[data-v-42ef59de]{display:flex;align-items:center;padding:0 12px;line-height:var(--vp-nav-height);font-size:14px;font-weight:500;color:var(--vp-c-text-1);transition:color .25s}.VPNavBarMenuLink.active[data-v-42ef59de],.VPNavBarMenuLink[data-v-42ef59de]:hover{color:var(--vp-c-brand-1)}.VPNavBarMenu[data-v-7f418b0f]{display:none}@media (min-width: 768px){.VPNavBarMenu[data-v-7f418b0f]{display:flex}}/*! @docsearch/css 3.6.0 | MIT License | © Algolia, Inc. and contributors | https://docsearch.algolia.com */:root{--docsearch-primary-color:#5468ff;--docsearch-text-color:#1c1e21;--docsearch-spacing:12px;--docsearch-icon-stroke-width:1.4;--docsearch-highlight-color:var(--docsearch-primary-color);--docsearch-muted-color:#969faf;--docsearch-container-background:rgba(101,108,133,.8);--docsearch-logo-color:#5468ff;--docsearch-modal-width:560px;--docsearch-modal-height:600px;--docsearch-modal-background:#f5f6f7;--docsearch-modal-shadow:inset 1px 1px 0 0 hsla(0,0%,100%,.5),0 3px 8px 0 #555a64;--docsearch-searchbox-height:56px;--docsearch-searchbox-background:#ebedf0;--docsearch-searchbox-focus-background:#fff;--docsearch-searchbox-shadow:inset 0 0 0 2px var(--docsearch-primary-color);--docsearch-hit-height:56px;--docsearch-hit-color:#444950;--docsearch-hit-active-color:#fff;--docsearch-hit-background:#fff;--docsearch-hit-shadow:0 1px 3px 0 #d4d9e1;--docsearch-key-gradient:linear-gradient(-225deg,#d5dbe4,#f8f8f8);--docsearch-key-shadow:inset 0 -2px 0 0 #cdcde6,inset 0 0 1px 1px #fff,0 1px 2px 1px rgba(30,35,90,.4);--docsearch-key-pressed-shadow:inset 0 -2px 0 0 #cdcde6,inset 0 0 1px 1px #fff,0 1px 1px 0 rgba(30,35,90,.4);--docsearch-footer-height:44px;--docsearch-footer-background:#fff;--docsearch-footer-shadow:0 -1px 0 0 #e0e3e8,0 -3px 6px 0 rgba(69,98,155,.12)}html[data-theme=dark]{--docsearch-text-color:#f5f6f7;--docsearch-container-background:rgba(9,10,17,.8);--docsearch-modal-background:#15172a;--docsearch-modal-shadow:inset 1px 1px 0 0 #2c2e40,0 3px 8px 0 #000309;--docsearch-searchbox-background:#090a11;--docsearch-searchbox-focus-background:#000;--docsearch-hit-color:#bec3c9;--docsearch-hit-shadow:none;--docsearch-hit-background:#090a11;--docsearch-key-gradient:linear-gradient(-26.5deg,#565872,#31355b);--docsearch-key-shadow:inset 0 -2px 0 0 #282d55,inset 0 0 1px 1px #51577d,0 2px 2px 0 rgba(3,4,9,.3);--docsearch-key-pressed-shadow:inset 0 -2px 0 0 #282d55,inset 0 0 1px 1px #51577d,0 1px 1px 0 rgba(3,4,9,.30196078431372547);--docsearch-footer-background:#1e2136;--docsearch-footer-shadow:inset 0 1px 0 0 rgba(73,76,106,.5),0 -4px 8px 0 rgba(0,0,0,.2);--docsearch-logo-color:#fff;--docsearch-muted-color:#7f8497}.DocSearch-Button{align-items:center;background:var(--docsearch-searchbox-background);border:0;border-radius:40px;color:var(--docsearch-muted-color);cursor:pointer;display:flex;font-weight:500;height:36px;justify-content:space-between;margin:0 0 0 16px;padding:0 8px;-webkit-user-select:none;user-select:none}.DocSearch-Button:active,.DocSearch-Button:focus,.DocSearch-Button:hover{background:var(--docsearch-searchbox-focus-background);box-shadow:var(--docsearch-searchbox-shadow);color:var(--docsearch-text-color);outline:none}.DocSearch-Button-Container{align-items:center;display:flex}.DocSearch-Search-Icon{stroke-width:1.6}.DocSearch-Button .DocSearch-Search-Icon{color:var(--docsearch-text-color)}.DocSearch-Button-Placeholder{font-size:1rem;padding:0 12px 0 6px}.DocSearch-Button-Keys{display:flex;min-width:calc(40px + .8em)}.DocSearch-Button-Key{align-items:center;background:var(--docsearch-key-gradient);border-radius:3px;box-shadow:var(--docsearch-key-shadow);color:var(--docsearch-muted-color);display:flex;height:18px;justify-content:center;margin-right:.4em;position:relative;padding:0 0 2px;border:0;top:-1px;width:20px}.DocSearch-Button-Key--pressed{transform:translate3d(0,1px,0);box-shadow:var(--docsearch-key-pressed-shadow)}@media (max-width:768px){.DocSearch-Button-Keys,.DocSearch-Button-Placeholder{display:none}}.DocSearch--active{overflow:hidden!important}.DocSearch-Container,.DocSearch-Container *{box-sizing:border-box}.DocSearch-Container{background-color:var(--docsearch-container-background);height:100vh;left:0;position:fixed;top:0;width:100vw;z-index:200}.DocSearch-Container a{text-decoration:none}.DocSearch-Link{-webkit-appearance:none;-moz-appearance:none;appearance:none;background:none;border:0;color:var(--docsearch-highlight-color);cursor:pointer;font:inherit;margin:0;padding:0}.DocSearch-Modal{background:var(--docsearch-modal-background);border-radius:6px;box-shadow:var(--docsearch-modal-shadow);flex-direction:column;margin:60px auto auto;max-width:var(--docsearch-modal-width);position:relative}.DocSearch-SearchBar{display:flex;padding:var(--docsearch-spacing) var(--docsearch-spacing) 0}.DocSearch-Form{align-items:center;background:var(--docsearch-searchbox-focus-background);border-radius:4px;box-shadow:var(--docsearch-searchbox-shadow);display:flex;height:var(--docsearch-searchbox-height);margin:0;padding:0 var(--docsearch-spacing);position:relative;width:100%}.DocSearch-Input{-webkit-appearance:none;-moz-appearance:none;appearance:none;background:transparent;border:0;color:var(--docsearch-text-color);flex:1;font:inherit;font-size:1.2em;height:100%;outline:none;padding:0 0 0 8px;width:80%}.DocSearch-Input::placeholder{color:var(--docsearch-muted-color);opacity:1}.DocSearch-Input::-webkit-search-cancel-button,.DocSearch-Input::-webkit-search-decoration,.DocSearch-Input::-webkit-search-results-button,.DocSearch-Input::-webkit-search-results-decoration{display:none}.DocSearch-LoadingIndicator,.DocSearch-MagnifierLabel,.DocSearch-Reset{margin:0;padding:0}.DocSearch-MagnifierLabel,.DocSearch-Reset{align-items:center;color:var(--docsearch-highlight-color);display:flex;justify-content:center}.DocSearch-Container--Stalled .DocSearch-MagnifierLabel,.DocSearch-LoadingIndicator{display:none}.DocSearch-Container--Stalled .DocSearch-LoadingIndicator{align-items:center;color:var(--docsearch-highlight-color);display:flex;justify-content:center}@media screen and (prefers-reduced-motion:reduce){.DocSearch-Reset{animation:none;-webkit-appearance:none;-moz-appearance:none;appearance:none;background:none;border:0;border-radius:50%;color:var(--docsearch-icon-color);cursor:pointer;right:0;stroke-width:var(--docsearch-icon-stroke-width)}}.DocSearch-Reset{animation:fade-in .1s ease-in forwards;-webkit-appearance:none;-moz-appearance:none;appearance:none;background:none;border:0;border-radius:50%;color:var(--docsearch-icon-color);cursor:pointer;padding:2px;right:0;stroke-width:var(--docsearch-icon-stroke-width)}.DocSearch-Reset[hidden]{display:none}.DocSearch-Reset:hover{color:var(--docsearch-highlight-color)}.DocSearch-LoadingIndicator svg,.DocSearch-MagnifierLabel svg{height:24px;width:24px}.DocSearch-Cancel{display:none}.DocSearch-Dropdown{max-height:calc(var(--docsearch-modal-height) - var(--docsearch-searchbox-height) - var(--docsearch-spacing) - var(--docsearch-footer-height));min-height:var(--docsearch-spacing);overflow-y:auto;overflow-y:overlay;padding:0 var(--docsearch-spacing);scrollbar-color:var(--docsearch-muted-color) var(--docsearch-modal-background);scrollbar-width:thin}.DocSearch-Dropdown::-webkit-scrollbar{width:12px}.DocSearch-Dropdown::-webkit-scrollbar-track{background:transparent}.DocSearch-Dropdown::-webkit-scrollbar-thumb{background-color:var(--docsearch-muted-color);border:3px solid var(--docsearch-modal-background);border-radius:20px}.DocSearch-Dropdown ul{list-style:none;margin:0;padding:0}.DocSearch-Label{font-size:.75em;line-height:1.6em}.DocSearch-Help,.DocSearch-Label{color:var(--docsearch-muted-color)}.DocSearch-Help{font-size:.9em;margin:0;-webkit-user-select:none;user-select:none}.DocSearch-Title{font-size:1.2em}.DocSearch-Logo a{display:flex}.DocSearch-Logo svg{color:var(--docsearch-logo-color);margin-left:8px}.DocSearch-Hits:last-of-type{margin-bottom:24px}.DocSearch-Hits mark{background:none;color:var(--docsearch-highlight-color)}.DocSearch-HitsFooter{color:var(--docsearch-muted-color);display:flex;font-size:.85em;justify-content:center;margin-bottom:var(--docsearch-spacing);padding:var(--docsearch-spacing)}.DocSearch-HitsFooter a{border-bottom:1px solid;color:inherit}.DocSearch-Hit{border-radius:4px;display:flex;padding-bottom:4px;position:relative}@media screen and (prefers-reduced-motion:reduce){.DocSearch-Hit--deleting{transition:none}}.DocSearch-Hit--deleting{opacity:0;transition:all .25s linear}@media screen and (prefers-reduced-motion:reduce){.DocSearch-Hit--favoriting{transition:none}}.DocSearch-Hit--favoriting{transform:scale(0);transform-origin:top center;transition:all .25s linear;transition-delay:.25s}.DocSearch-Hit a{background:var(--docsearch-hit-background);border-radius:4px;box-shadow:var(--docsearch-hit-shadow);display:block;padding-left:var(--docsearch-spacing);width:100%}.DocSearch-Hit-source{background:var(--docsearch-modal-background);color:var(--docsearch-highlight-color);font-size:.85em;font-weight:600;line-height:32px;margin:0 -4px;padding:8px 4px 0;position:sticky;top:0;z-index:10}.DocSearch-Hit-Tree{color:var(--docsearch-muted-color);height:var(--docsearch-hit-height);opacity:.5;stroke-width:var(--docsearch-icon-stroke-width);width:24px}.DocSearch-Hit[aria-selected=true] a{background-color:var(--docsearch-highlight-color)}.DocSearch-Hit[aria-selected=true] mark{text-decoration:underline}.DocSearch-Hit-Container{align-items:center;color:var(--docsearch-hit-color);display:flex;flex-direction:row;height:var(--docsearch-hit-height);padding:0 var(--docsearch-spacing) 0 0}.DocSearch-Hit-icon{height:20px;width:20px}.DocSearch-Hit-action,.DocSearch-Hit-icon{color:var(--docsearch-muted-color);stroke-width:var(--docsearch-icon-stroke-width)}.DocSearch-Hit-action{align-items:center;display:flex;height:22px;width:22px}.DocSearch-Hit-action svg{display:block;height:18px;width:18px}.DocSearch-Hit-action+.DocSearch-Hit-action{margin-left:6px}.DocSearch-Hit-action-button{-webkit-appearance:none;-moz-appearance:none;appearance:none;background:none;border:0;border-radius:50%;color:inherit;cursor:pointer;padding:2px}svg.DocSearch-Hit-Select-Icon{display:none}.DocSearch-Hit[aria-selected=true] .DocSearch-Hit-Select-Icon{display:block}.DocSearch-Hit-action-button:focus,.DocSearch-Hit-action-button:hover{background:#0003;transition:background-color .1s ease-in}@media screen and (prefers-reduced-motion:reduce){.DocSearch-Hit-action-button:focus,.DocSearch-Hit-action-button:hover{transition:none}}.DocSearch-Hit-action-button:focus path,.DocSearch-Hit-action-button:hover path{fill:#fff}.DocSearch-Hit-content-wrapper{display:flex;flex:1 1 auto;flex-direction:column;font-weight:500;justify-content:center;line-height:1.2em;margin:0 8px;overflow-x:hidden;position:relative;text-overflow:ellipsis;white-space:nowrap;width:80%}.DocSearch-Hit-title{font-size:.9em}.DocSearch-Hit-path{color:var(--docsearch-muted-color);font-size:.75em}.DocSearch-Hit[aria-selected=true] .DocSearch-Hit-action,.DocSearch-Hit[aria-selected=true] .DocSearch-Hit-icon,.DocSearch-Hit[aria-selected=true] .DocSearch-Hit-path,.DocSearch-Hit[aria-selected=true] .DocSearch-Hit-text,.DocSearch-Hit[aria-selected=true] .DocSearch-Hit-title,.DocSearch-Hit[aria-selected=true] .DocSearch-Hit-Tree,.DocSearch-Hit[aria-selected=true] mark{color:var(--docsearch-hit-active-color)!important}@media screen and (prefers-reduced-motion:reduce){.DocSearch-Hit-action-button:focus,.DocSearch-Hit-action-button:hover{background:#0003;transition:none}}.DocSearch-ErrorScreen,.DocSearch-NoResults,.DocSearch-StartScreen{font-size:.9em;margin:0 auto;padding:36px 0;text-align:center;width:80%}.DocSearch-Screen-Icon{color:var(--docsearch-muted-color);padding-bottom:12px}.DocSearch-NoResults-Prefill-List{display:inline-block;padding-bottom:24px;text-align:left}.DocSearch-NoResults-Prefill-List ul{display:inline-block;padding:8px 0 0}.DocSearch-NoResults-Prefill-List li{list-style-position:inside;list-style-type:"» "}.DocSearch-Prefill{-webkit-appearance:none;-moz-appearance:none;appearance:none;background:none;border:0;border-radius:1em;color:var(--docsearch-highlight-color);cursor:pointer;display:inline-block;font-size:1em;font-weight:700;padding:0}.DocSearch-Prefill:focus,.DocSearch-Prefill:hover{outline:none;text-decoration:underline}.DocSearch-Footer{align-items:center;background:var(--docsearch-footer-background);border-radius:0 0 8px 8px;box-shadow:var(--docsearch-footer-shadow);display:flex;flex-direction:row-reverse;flex-shrink:0;height:var(--docsearch-footer-height);justify-content:space-between;padding:0 var(--docsearch-spacing);position:relative;-webkit-user-select:none;user-select:none;width:100%;z-index:300}.DocSearch-Commands{color:var(--docsearch-muted-color);display:flex;list-style:none;margin:0;padding:0}.DocSearch-Commands li{align-items:center;display:flex}.DocSearch-Commands li:not(:last-of-type){margin-right:.8em}.DocSearch-Commands-Key{align-items:center;background:var(--docsearch-key-gradient);border-radius:2px;box-shadow:var(--docsearch-key-shadow);display:flex;height:18px;justify-content:center;margin-right:.4em;padding:0 0 1px;color:var(--docsearch-muted-color);border:0;width:20px}.DocSearch-VisuallyHiddenForAccessibility{clip:rect(0 0 0 0);clip-path:inset(50%);height:1px;overflow:hidden;position:absolute;white-space:nowrap;width:1px}@media (max-width:768px){:root{--docsearch-spacing:10px;--docsearch-footer-height:40px}.DocSearch-Dropdown{height:100%}.DocSearch-Container{height:100vh;height:-webkit-fill-available;height:calc(var(--docsearch-vh, 1vh)*100);position:absolute}.DocSearch-Footer{border-radius:0;bottom:0;position:absolute}.DocSearch-Hit-content-wrapper{display:flex;position:relative;width:80%}.DocSearch-Modal{border-radius:0;box-shadow:none;height:100vh;height:-webkit-fill-available;height:calc(var(--docsearch-vh, 1vh)*100);margin:0;max-width:100%;width:100%}.DocSearch-Dropdown{max-height:calc(var(--docsearch-vh, 1vh)*100 - var(--docsearch-searchbox-height) - var(--docsearch-spacing) - var(--docsearch-footer-height))}.DocSearch-Cancel{-webkit-appearance:none;-moz-appearance:none;appearance:none;background:none;border:0;color:var(--docsearch-highlight-color);cursor:pointer;display:inline-block;flex:none;font:inherit;font-size:1em;font-weight:500;margin-left:var(--docsearch-spacing);outline:none;overflow:hidden;padding:0;-webkit-user-select:none;user-select:none;white-space:nowrap}.DocSearch-Commands,.DocSearch-Hit-Tree{display:none}}@keyframes fade-in{0%{opacity:0}to{opacity:1}}[class*=DocSearch]{--docsearch-primary-color: var(--vp-c-brand-1);--docsearch-highlight-color: var(--docsearch-primary-color);--docsearch-text-color: var(--vp-c-text-1);--docsearch-muted-color: var(--vp-c-text-2);--docsearch-searchbox-shadow: none;--docsearch-searchbox-background: transparent;--docsearch-searchbox-focus-background: transparent;--docsearch-key-gradient: transparent;--docsearch-key-shadow: none;--docsearch-modal-background: var(--vp-c-bg-soft);--docsearch-footer-background: var(--vp-c-bg)}.dark [class*=DocSearch]{--docsearch-modal-shadow: none;--docsearch-footer-shadow: none;--docsearch-logo-color: var(--vp-c-text-2);--docsearch-hit-background: var(--vp-c-default-soft);--docsearch-hit-color: var(--vp-c-text-2);--docsearch-hit-shadow: none}.DocSearch-Button{display:flex;justify-content:center;align-items:center;margin:0;padding:0;width:48px;height:55px;background:transparent;transition:border-color .25s}.DocSearch-Button:hover{background:transparent}.DocSearch-Button:focus{outline:1px dotted;outline:5px auto -webkit-focus-ring-color}.DocSearch-Button:focus:not(:focus-visible){outline:none!important}@media (min-width: 768px){.DocSearch-Button{justify-content:flex-start;border:1px solid transparent;border-radius:8px;padding:0 10px 0 12px;width:100%;height:40px;background-color:var(--vp-c-bg-alt)}.DocSearch-Button:hover{border-color:var(--vp-c-brand-1);background:var(--vp-c-bg-alt)}}.DocSearch-Button .DocSearch-Button-Container{display:flex;align-items:center}.DocSearch-Button .DocSearch-Search-Icon{position:relative;width:16px;height:16px;color:var(--vp-c-text-1);fill:currentColor;transition:color .5s}.DocSearch-Button:hover .DocSearch-Search-Icon{color:var(--vp-c-text-1)}@media (min-width: 768px){.DocSearch-Button .DocSearch-Search-Icon{top:1px;margin-right:8px;width:14px;height:14px;color:var(--vp-c-text-2)}}.DocSearch-Button .DocSearch-Button-Placeholder{display:none;margin-top:2px;padding:0 16px 0 0;font-size:13px;font-weight:500;color:var(--vp-c-text-2);transition:color .5s}.DocSearch-Button:hover .DocSearch-Button-Placeholder{color:var(--vp-c-text-1)}@media (min-width: 768px){.DocSearch-Button .DocSearch-Button-Placeholder{display:inline-block}}.DocSearch-Button .DocSearch-Button-Keys{direction:ltr;display:none;min-width:auto}@media (min-width: 768px){.DocSearch-Button .DocSearch-Button-Keys{display:flex;align-items:center}}.DocSearch-Button .DocSearch-Button-Key{display:block;margin:2px 0 0;border:1px solid var(--vp-c-divider);border-right:none;border-radius:4px 0 0 4px;padding-left:6px;min-width:0;width:auto;height:22px;line-height:22px;font-family:var(--vp-font-family-base);font-size:12px;font-weight:500;transition:color .5s,border-color .5s}.DocSearch-Button .DocSearch-Button-Key+.DocSearch-Button-Key{border-right:1px solid var(--vp-c-divider);border-left:none;border-radius:0 4px 4px 0;padding-left:2px;padding-right:6px}.DocSearch-Button .DocSearch-Button-Key:first-child{font-size:0!important}.DocSearch-Button .DocSearch-Button-Key:first-child:after{content:"Ctrl";font-size:12px;letter-spacing:normal;color:var(--docsearch-muted-color)}.mac .DocSearch-Button .DocSearch-Button-Key:first-child:after{content:"⌘"}.DocSearch-Button .DocSearch-Button-Key:first-child>*{display:none}.DocSearch-Search-Icon{--icon: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' stroke-width='1.6' viewBox='0 0 20 20'%3E%3Cpath fill='none' stroke='currentColor' stroke-linecap='round' stroke-linejoin='round' d='m14.386 14.386 4.088 4.088-4.088-4.088A7.533 7.533 0 1 1 3.733 3.733a7.533 7.533 0 0 1 10.653 10.653z'/%3E%3C/svg%3E")}.VPNavBarSearch{display:flex;align-items:center}@media (min-width: 768px){.VPNavBarSearch{flex-grow:1;padding-left:24px}}@media (min-width: 960px){.VPNavBarSearch{padding-left:32px}}.dark .DocSearch-Footer{border-top:1px solid var(--vp-c-divider)}.DocSearch-Form{border:1px solid var(--vp-c-brand-1);background-color:var(--vp-c-white)}.dark .DocSearch-Form{background-color:var(--vp-c-default-soft)}.DocSearch-Screen-Icon>svg{margin:auto}.VPNavBarSocialLinks[data-v-0394ad82]{display:none}@media (min-width: 1280px){.VPNavBarSocialLinks[data-v-0394ad82]{display:flex;align-items:center}}.title[data-v-ab179fa1]{display:flex;align-items:center;border-bottom:1px solid transparent;width:100%;height:var(--vp-nav-height);font-size:16px;font-weight:600;color:var(--vp-c-text-1);transition:opacity .25s}@media (min-width: 960px){.title[data-v-ab179fa1]{flex-shrink:0}.VPNavBarTitle.has-sidebar .title[data-v-ab179fa1]{border-bottom-color:var(--vp-c-divider)}}[data-v-ab179fa1] .logo{margin-right:8px;height:var(--vp-nav-logo-height)}.VPNavBarTranslations[data-v-88af2de4]{display:none}@media (min-width: 1280px){.VPNavBarTranslations[data-v-88af2de4]{display:flex;align-items:center}}.title[data-v-88af2de4]{padding:0 24px 0 12px;line-height:32px;font-size:14px;font-weight:700;color:var(--vp-c-text-1)}.VPNavBar[data-v-19c990f1]{position:relative;height:var(--vp-nav-height);pointer-events:none;white-space:nowrap;transition:background-color .5s}.VPNavBar.has-local-nav[data-v-19c990f1]{background-color:var(--vp-nav-bg-color)}@media (min-width: 960px){.VPNavBar.has-local-nav[data-v-19c990f1]{background-color:transparent}.VPNavBar[data-v-19c990f1]:not(.has-sidebar):not(.top){background-color:var(--vp-nav-bg-color)}}.wrapper[data-v-19c990f1]{padding:0 8px 0 24px}@media (min-width: 768px){.wrapper[data-v-19c990f1]{padding:0 32px}}@media (min-width: 960px){.VPNavBar.has-sidebar .wrapper[data-v-19c990f1]{padding:0}}.container[data-v-19c990f1]{display:flex;justify-content:space-between;margin:0 auto;max-width:calc(var(--vp-layout-max-width) - 64px);height:var(--vp-nav-height);pointer-events:none}.container>.title[data-v-19c990f1],.container>.content[data-v-19c990f1]{pointer-events:none}.container[data-v-19c990f1] *{pointer-events:auto}@media (min-width: 960px){.VPNavBar.has-sidebar .container[data-v-19c990f1]{max-width:100%}}.title[data-v-19c990f1]{flex-shrink:0;height:calc(var(--vp-nav-height) - 1px);transition:background-color .5s}@media (min-width: 960px){.VPNavBar.has-sidebar .title[data-v-19c990f1]{position:absolute;top:0;left:0;z-index:2;padding:0 32px;width:var(--vp-sidebar-width);height:var(--vp-nav-height);background-color:transparent}}@media (min-width: 1440px){.VPNavBar.has-sidebar .title[data-v-19c990f1]{padding-left:max(32px,calc((100% - (var(--vp-layout-max-width) - 64px)) / 2));width:calc((100% - (var(--vp-layout-max-width) - 64px)) / 2 + var(--vp-sidebar-width) - 32px)}}.content[data-v-19c990f1]{flex-grow:1}@media (min-width: 960px){.VPNavBar.has-sidebar .content[data-v-19c990f1]{position:relative;z-index:1;padding-right:32px;padding-left:var(--vp-sidebar-width)}}@media (min-width: 1440px){.VPNavBar.has-sidebar .content[data-v-19c990f1]{padding-right:calc((100vw - var(--vp-layout-max-width)) / 2 + 32px);padding-left:calc((100vw - var(--vp-layout-max-width)) / 2 + var(--vp-sidebar-width))}}.content-body[data-v-19c990f1]{display:flex;justify-content:flex-end;align-items:center;height:var(--vp-nav-height);transition:background-color .5s}@media (min-width: 960px){.VPNavBar:not(.top) .content-body[data-v-19c990f1]{position:relative;background-color:var(--vp-nav-bg-color)}.VPNavBar:not(.has-sidebar):not(.top) .content-body[data-v-19c990f1]{background-color:transparent}}@media (max-width: 767px){.content-body[data-v-19c990f1]{column-gap:.5rem}}.menu+.translations[data-v-19c990f1]:before,.menu+.appearance[data-v-19c990f1]:before,.menu+.social-links[data-v-19c990f1]:before,.translations+.appearance[data-v-19c990f1]:before,.appearance+.social-links[data-v-19c990f1]:before{margin-right:8px;margin-left:8px;width:1px;height:24px;background-color:var(--vp-c-divider);content:""}.menu+.appearance[data-v-19c990f1]:before,.translations+.appearance[data-v-19c990f1]:before{margin-right:16px}.appearance+.social-links[data-v-19c990f1]:before{margin-left:16px}.social-links[data-v-19c990f1]{margin-right:-8px}.divider[data-v-19c990f1]{width:100%;height:1px}@media (min-width: 960px){.VPNavBar.has-sidebar .divider[data-v-19c990f1]{padding-left:var(--vp-sidebar-width)}}@media (min-width: 1440px){.VPNavBar.has-sidebar .divider[data-v-19c990f1]{padding-left:calc((100vw - var(--vp-layout-max-width)) / 2 + var(--vp-sidebar-width))}}.divider-line[data-v-19c990f1]{width:100%;height:1px;transition:background-color .5s}.VPNavBar.has-local-nav .divider-line[data-v-19c990f1]{background-color:var(--vp-c-gutter)}@media (min-width: 960px){.VPNavBar:not(.top) .divider-line[data-v-19c990f1]{background-color:var(--vp-c-gutter)}.VPNavBar:not(.has-sidebar):not(.top) .divider[data-v-19c990f1]{background-color:var(--vp-c-gutter)}}.VPNavScreenAppearance[data-v-2d7af913]{display:flex;justify-content:space-between;align-items:center;border-radius:8px;padding:12px 14px 12px 16px;background-color:var(--vp-c-bg-soft)}.text[data-v-2d7af913]{line-height:24px;font-size:12px;font-weight:500;color:var(--vp-c-text-2)}.VPNavScreenMenuLink[data-v-05f27b2a]{display:block;border-bottom:1px solid var(--vp-c-divider);padding:12px 0 11px;line-height:24px;font-size:14px;font-weight:500;color:var(--vp-c-text-1);transition:border-color .25s,color .25s}.VPNavScreenMenuLink[data-v-05f27b2a]:hover{color:var(--vp-c-brand-1)}.VPNavScreenMenuGroupLink[data-v-19976ae1]{display:block;margin-left:12px;line-height:32px;font-size:14px;font-weight:400;color:var(--vp-c-text-1);transition:color .25s}.VPNavScreenMenuGroupLink[data-v-19976ae1]:hover{color:var(--vp-c-brand-1)}.VPNavScreenMenuGroupSection[data-v-8133b170]{display:block}.title[data-v-8133b170]{line-height:32px;font-size:13px;font-weight:700;color:var(--vp-c-text-2);transition:color .25s}.VPNavScreenMenuGroup[data-v-ff6087d4]{border-bottom:1px solid var(--vp-c-divider);height:48px;overflow:hidden;transition:border-color .5s}.VPNavScreenMenuGroup .items[data-v-ff6087d4]{visibility:hidden}.VPNavScreenMenuGroup.open .items[data-v-ff6087d4]{visibility:visible}.VPNavScreenMenuGroup.open[data-v-ff6087d4]{padding-bottom:10px;height:auto}.VPNavScreenMenuGroup.open .button[data-v-ff6087d4]{padding-bottom:6px;color:var(--vp-c-brand-1)}.VPNavScreenMenuGroup.open .button-icon[data-v-ff6087d4]{transform:rotate(45deg)}.button[data-v-ff6087d4]{display:flex;justify-content:space-between;align-items:center;padding:12px 4px 11px 0;width:100%;line-height:24px;font-size:14px;font-weight:500;color:var(--vp-c-text-1);transition:color .25s}.button[data-v-ff6087d4]:hover{color:var(--vp-c-brand-1)}.button-icon[data-v-ff6087d4]{transition:transform .25s}.group[data-v-ff6087d4]:first-child{padding-top:0}.group+.group[data-v-ff6087d4],.group+.item[data-v-ff6087d4]{padding-top:4px}.VPNavScreenTranslations[data-v-858fe1a4]{height:24px;overflow:hidden}.VPNavScreenTranslations.open[data-v-858fe1a4]{height:auto}.title[data-v-858fe1a4]{display:flex;align-items:center;font-size:14px;font-weight:500;color:var(--vp-c-text-1)}.icon[data-v-858fe1a4]{font-size:16px}.icon.lang[data-v-858fe1a4]{margin-right:8px}.icon.chevron[data-v-858fe1a4]{margin-left:4px}.list[data-v-858fe1a4]{padding:4px 0 0 24px}.link[data-v-858fe1a4]{line-height:32px;font-size:13px;color:var(--vp-c-text-1)}.VPNavScreen[data-v-cc5739dd]{position:fixed;top:calc(var(--vp-nav-height) + var(--vp-layout-top-height, 0px) + 1px);right:0;bottom:0;left:0;padding:0 32px;width:100%;background-color:var(--vp-nav-screen-bg-color);overflow-y:auto;transition:background-color .5s;pointer-events:auto}.VPNavScreen.fade-enter-active[data-v-cc5739dd],.VPNavScreen.fade-leave-active[data-v-cc5739dd]{transition:opacity .25s}.VPNavScreen.fade-enter-active .container[data-v-cc5739dd],.VPNavScreen.fade-leave-active .container[data-v-cc5739dd]{transition:transform .25s ease}.VPNavScreen.fade-enter-from[data-v-cc5739dd],.VPNavScreen.fade-leave-to[data-v-cc5739dd]{opacity:0}.VPNavScreen.fade-enter-from .container[data-v-cc5739dd],.VPNavScreen.fade-leave-to .container[data-v-cc5739dd]{transform:translateY(-8px)}@media (min-width: 768px){.VPNavScreen[data-v-cc5739dd]{display:none}}.container[data-v-cc5739dd]{margin:0 auto;padding:24px 0 96px;max-width:288px}.menu+.translations[data-v-cc5739dd],.menu+.appearance[data-v-cc5739dd],.translations+.appearance[data-v-cc5739dd]{margin-top:24px}.menu+.social-links[data-v-cc5739dd]{margin-top:16px}.appearance+.social-links[data-v-cc5739dd]{margin-top:16px}.VPNav[data-v-ae24b3ad]{position:relative;top:var(--vp-layout-top-height, 0px);left:0;z-index:var(--vp-z-index-nav);width:100%;pointer-events:none;transition:background-color .5s}@media (min-width: 960px){.VPNav[data-v-ae24b3ad]{position:fixed}}.VPSidebarItem.level-0[data-v-93e7e794]{padding-bottom:24px}.VPSidebarItem.collapsed.level-0[data-v-93e7e794]{padding-bottom:10px}.item[data-v-93e7e794]{position:relative;display:flex;width:100%}.VPSidebarItem.collapsible>.item[data-v-93e7e794]{cursor:pointer}.indicator[data-v-93e7e794]{position:absolute;top:6px;bottom:6px;left:-17px;width:2px;border-radius:2px;transition:background-color .25s}.VPSidebarItem.level-2.is-active>.item>.indicator[data-v-93e7e794],.VPSidebarItem.level-3.is-active>.item>.indicator[data-v-93e7e794],.VPSidebarItem.level-4.is-active>.item>.indicator[data-v-93e7e794],.VPSidebarItem.level-5.is-active>.item>.indicator[data-v-93e7e794]{background-color:var(--vp-c-brand-1)}.link[data-v-93e7e794]{display:flex;align-items:center;flex-grow:1}.text[data-v-93e7e794]{flex-grow:1;padding:4px 0;line-height:24px;font-size:14px;transition:color .25s}.VPSidebarItem.level-0 .text[data-v-93e7e794]{font-weight:700;color:var(--vp-c-text-1)}.VPSidebarItem.level-1 .text[data-v-93e7e794],.VPSidebarItem.level-2 .text[data-v-93e7e794],.VPSidebarItem.level-3 .text[data-v-93e7e794],.VPSidebarItem.level-4 .text[data-v-93e7e794],.VPSidebarItem.level-5 .text[data-v-93e7e794]{font-weight:500;color:var(--vp-c-text-2)}.VPSidebarItem.level-0.is-link>.item>.link:hover .text[data-v-93e7e794],.VPSidebarItem.level-1.is-link>.item>.link:hover .text[data-v-93e7e794],.VPSidebarItem.level-2.is-link>.item>.link:hover .text[data-v-93e7e794],.VPSidebarItem.level-3.is-link>.item>.link:hover .text[data-v-93e7e794],.VPSidebarItem.level-4.is-link>.item>.link:hover .text[data-v-93e7e794],.VPSidebarItem.level-5.is-link>.item>.link:hover .text[data-v-93e7e794]{color:var(--vp-c-brand-1)}.VPSidebarItem.level-0.has-active>.item>.text[data-v-93e7e794],.VPSidebarItem.level-1.has-active>.item>.text[data-v-93e7e794],.VPSidebarItem.level-2.has-active>.item>.text[data-v-93e7e794],.VPSidebarItem.level-3.has-active>.item>.text[data-v-93e7e794],.VPSidebarItem.level-4.has-active>.item>.text[data-v-93e7e794],.VPSidebarItem.level-5.has-active>.item>.text[data-v-93e7e794],.VPSidebarItem.level-0.has-active>.item>.link>.text[data-v-93e7e794],.VPSidebarItem.level-1.has-active>.item>.link>.text[data-v-93e7e794],.VPSidebarItem.level-2.has-active>.item>.link>.text[data-v-93e7e794],.VPSidebarItem.level-3.has-active>.item>.link>.text[data-v-93e7e794],.VPSidebarItem.level-4.has-active>.item>.link>.text[data-v-93e7e794],.VPSidebarItem.level-5.has-active>.item>.link>.text[data-v-93e7e794]{color:var(--vp-c-text-1)}.VPSidebarItem.level-0.is-active>.item .link>.text[data-v-93e7e794],.VPSidebarItem.level-1.is-active>.item .link>.text[data-v-93e7e794],.VPSidebarItem.level-2.is-active>.item .link>.text[data-v-93e7e794],.VPSidebarItem.level-3.is-active>.item .link>.text[data-v-93e7e794],.VPSidebarItem.level-4.is-active>.item .link>.text[data-v-93e7e794],.VPSidebarItem.level-5.is-active>.item .link>.text[data-v-93e7e794]{color:var(--vp-c-brand-1)}.caret[data-v-93e7e794]{display:flex;justify-content:center;align-items:center;margin-right:-7px;width:32px;height:32px;color:var(--vp-c-text-3);cursor:pointer;transition:color .25s;flex-shrink:0}.item:hover .caret[data-v-93e7e794]{color:var(--vp-c-text-2)}.item:hover .caret[data-v-93e7e794]:hover{color:var(--vp-c-text-1)}.caret-icon[data-v-93e7e794]{font-size:18px;transform:rotate(90deg);transition:transform .25s}.VPSidebarItem.collapsed .caret-icon[data-v-93e7e794]{transform:rotate(0)}.VPSidebarItem.level-1 .items[data-v-93e7e794],.VPSidebarItem.level-2 .items[data-v-93e7e794],.VPSidebarItem.level-3 .items[data-v-93e7e794],.VPSidebarItem.level-4 .items[data-v-93e7e794],.VPSidebarItem.level-5 .items[data-v-93e7e794]{border-left:1px solid var(--vp-c-divider);padding-left:16px}.VPSidebarItem.collapsed .items[data-v-93e7e794]{display:none}.VPSidebar[data-v-575e6a36]{position:fixed;top:var(--vp-layout-top-height, 0px);bottom:0;left:0;z-index:var(--vp-z-index-sidebar);padding:32px 32px 96px;width:calc(100vw - 64px);max-width:320px;background-color:var(--vp-sidebar-bg-color);opacity:0;box-shadow:var(--vp-c-shadow-3);overflow-x:hidden;overflow-y:auto;transform:translate(-100%);transition:opacity .5s,transform .25s ease;overscroll-behavior:contain}.VPSidebar.open[data-v-575e6a36]{opacity:1;visibility:visible;transform:translate(0);transition:opacity .25s,transform .5s cubic-bezier(.19,1,.22,1)}.dark .VPSidebar[data-v-575e6a36]{box-shadow:var(--vp-shadow-1)}@media (min-width: 960px){.VPSidebar[data-v-575e6a36]{padding-top:var(--vp-nav-height);width:var(--vp-sidebar-width);max-width:100%;background-color:var(--vp-sidebar-bg-color);opacity:1;visibility:visible;box-shadow:none;transform:translate(0)}}@media (min-width: 1440px){.VPSidebar[data-v-575e6a36]{padding-left:max(32px,calc((100% - (var(--vp-layout-max-width) - 64px)) / 2));width:calc((100% - (var(--vp-layout-max-width) - 64px)) / 2 + var(--vp-sidebar-width) - 32px)}}@media (min-width: 960px){.curtain[data-v-575e6a36]{position:sticky;top:-64px;left:0;z-index:1;margin-top:calc(var(--vp-nav-height) * -1);margin-right:-32px;margin-left:-32px;height:var(--vp-nav-height);background-color:var(--vp-sidebar-bg-color)}}.nav[data-v-575e6a36]{outline:0}.group+.group[data-v-575e6a36]{border-top:1px solid var(--vp-c-divider);padding-top:10px}@media (min-width: 960px){.group[data-v-575e6a36]{padding-top:10px;width:calc(var(--vp-sidebar-width) - 64px)}}.VPSkipLink[data-v-0f60ec36]{top:8px;left:8px;padding:8px 16px;z-index:999;border-radius:8px;font-size:12px;font-weight:700;text-decoration:none;color:var(--vp-c-brand-1);box-shadow:var(--vp-shadow-3);background-color:var(--vp-c-bg)}.VPSkipLink[data-v-0f60ec36]:focus{height:auto;width:auto;clip:auto;clip-path:none}@media (min-width: 1280px){.VPSkipLink[data-v-0f60ec36]{top:14px;left:16px}}.Layout[data-v-5d98c3a5]{display:flex;flex-direction:column;min-height:100vh}.VPHomeSponsors[data-v-3d121b4a]{border-top:1px solid var(--vp-c-gutter);padding-top:88px!important}.VPHomeSponsors[data-v-3d121b4a]{margin:96px 0}@media (min-width: 768px){.VPHomeSponsors[data-v-3d121b4a]{margin:128px 0}}.VPHomeSponsors[data-v-3d121b4a]{padding:0 24px}@media (min-width: 768px){.VPHomeSponsors[data-v-3d121b4a]{padding:0 48px}}@media (min-width: 960px){.VPHomeSponsors[data-v-3d121b4a]{padding:0 64px}}.container[data-v-3d121b4a]{margin:0 auto;max-width:1152px}.love[data-v-3d121b4a]{margin:0 auto;width:fit-content;font-size:28px;color:var(--vp-c-text-3)}.icon[data-v-3d121b4a]{display:inline-block}.message[data-v-3d121b4a]{margin:0 auto;padding-top:10px;max-width:320px;text-align:center;line-height:24px;font-size:16px;font-weight:500;color:var(--vp-c-text-2)}.sponsors[data-v-3d121b4a]{padding-top:32px}.action[data-v-3d121b4a]{padding-top:40px;text-align:center}.VPTeamPage[data-v-7c57f839]{margin:96px 0}@media (min-width: 768px){.VPTeamPage[data-v-7c57f839]{margin:128px 0}}.VPHome .VPTeamPageTitle[data-v-7c57f839-s]{border-top:1px solid var(--vp-c-gutter);padding-top:88px!important}.VPTeamPageSection+.VPTeamPageSection[data-v-7c57f839-s],.VPTeamMembers+.VPTeamPageSection[data-v-7c57f839-s]{margin-top:64px}.VPTeamMembers+.VPTeamMembers[data-v-7c57f839-s]{margin-top:24px}@media (min-width: 768px){.VPTeamPageTitle+.VPTeamPageSection[data-v-7c57f839-s]{margin-top:16px}.VPTeamPageSection+.VPTeamPageSection[data-v-7c57f839-s],.VPTeamMembers+.VPTeamPageSection[data-v-7c57f839-s]{margin-top:96px}}.VPTeamMembers[data-v-7c57f839-s]{padding:0 24px}@media (min-width: 768px){.VPTeamMembers[data-v-7c57f839-s]{padding:0 48px}}@media (min-width: 960px){.VPTeamMembers[data-v-7c57f839-s]{padding:0 64px}}.VPTeamPageTitle[data-v-bf2cbdac]{padding:48px 32px;text-align:center}@media (min-width: 768px){.VPTeamPageTitle[data-v-bf2cbdac]{padding:64px 48px 48px}}@media (min-width: 960px){.VPTeamPageTitle[data-v-bf2cbdac]{padding:80px 64px 48px}}.title[data-v-bf2cbdac]{letter-spacing:0;line-height:44px;font-size:36px;font-weight:500}@media (min-width: 768px){.title[data-v-bf2cbdac]{letter-spacing:-.5px;line-height:56px;font-size:48px}}.lead[data-v-bf2cbdac]{margin:0 auto;max-width:512px;padding-top:12px;line-height:24px;font-size:16px;font-weight:500;color:var(--vp-c-text-2)}@media (min-width: 768px){.lead[data-v-bf2cbdac]{max-width:592px;letter-spacing:.15px;line-height:28px;font-size:20px}}.VPTeamPageSection[data-v-b1a88750]{padding:0 32px}@media (min-width: 768px){.VPTeamPageSection[data-v-b1a88750]{padding:0 48px}}@media (min-width: 960px){.VPTeamPageSection[data-v-b1a88750]{padding:0 64px}}.title[data-v-b1a88750]{position:relative;margin:0 auto;max-width:1152px;text-align:center;color:var(--vp-c-text-2)}.title-line[data-v-b1a88750]{position:absolute;top:16px;left:0;width:100%;height:1px;background-color:var(--vp-c-divider)}.title-text[data-v-b1a88750]{position:relative;display:inline-block;padding:0 24px;letter-spacing:0;line-height:32px;font-size:20px;font-weight:500;background-color:var(--vp-c-bg)}.lead[data-v-b1a88750]{margin:0 auto;max-width:480px;padding-top:12px;text-align:center;line-height:24px;font-size:16px;font-weight:500;color:var(--vp-c-text-2)}.members[data-v-b1a88750]{padding-top:40px}.VPTeamMembersItem[data-v-f3fa364a]{display:flex;flex-direction:column;gap:2px;border-radius:12px;width:100%;height:100%;overflow:hidden}.VPTeamMembersItem.small .profile[data-v-f3fa364a]{padding:32px}.VPTeamMembersItem.small .data[data-v-f3fa364a]{padding-top:20px}.VPTeamMembersItem.small .avatar[data-v-f3fa364a]{width:64px;height:64px}.VPTeamMembersItem.small .name[data-v-f3fa364a]{line-height:24px;font-size:16px}.VPTeamMembersItem.small .affiliation[data-v-f3fa364a]{padding-top:4px;line-height:20px;font-size:14px}.VPTeamMembersItem.small .desc[data-v-f3fa364a]{padding-top:12px;line-height:20px;font-size:14px}.VPTeamMembersItem.small .links[data-v-f3fa364a]{margin:0 -16px -20px;padding:10px 0 0}.VPTeamMembersItem.medium .profile[data-v-f3fa364a]{padding:48px 32px}.VPTeamMembersItem.medium .data[data-v-f3fa364a]{padding-top:24px;text-align:center}.VPTeamMembersItem.medium .avatar[data-v-f3fa364a]{width:96px;height:96px}.VPTeamMembersItem.medium .name[data-v-f3fa364a]{letter-spacing:.15px;line-height:28px;font-size:20px}.VPTeamMembersItem.medium .affiliation[data-v-f3fa364a]{padding-top:4px;font-size:16px}.VPTeamMembersItem.medium .desc[data-v-f3fa364a]{padding-top:16px;max-width:288px;font-size:16px}.VPTeamMembersItem.medium .links[data-v-f3fa364a]{margin:0 -16px -12px;padding:16px 12px 0}.profile[data-v-f3fa364a]{flex-grow:1;background-color:var(--vp-c-bg-soft)}.data[data-v-f3fa364a]{text-align:center}.avatar[data-v-f3fa364a]{position:relative;flex-shrink:0;margin:0 auto;border-radius:50%;box-shadow:var(--vp-shadow-3)}.avatar-img[data-v-f3fa364a]{position:absolute;top:0;right:0;bottom:0;left:0;border-radius:50%;object-fit:cover}.name[data-v-f3fa364a]{margin:0;font-weight:600}.affiliation[data-v-f3fa364a]{margin:0;font-weight:500;color:var(--vp-c-text-2)}.org.link[data-v-f3fa364a]{color:var(--vp-c-text-2);transition:color .25s}.org.link[data-v-f3fa364a]:hover{color:var(--vp-c-brand-1)}.desc[data-v-f3fa364a]{margin:0 auto}.desc[data-v-f3fa364a] a{font-weight:500;color:var(--vp-c-brand-1);text-decoration-style:dotted;transition:color .25s}.links[data-v-f3fa364a]{display:flex;justify-content:center;height:56px}.sp-link[data-v-f3fa364a]{display:flex;justify-content:center;align-items:center;text-align:center;padding:16px;font-size:14px;font-weight:500;color:var(--vp-c-sponsor);background-color:var(--vp-c-bg-soft);transition:color .25s,background-color .25s}.sp .sp-link.link[data-v-f3fa364a]:hover,.sp .sp-link.link[data-v-f3fa364a]:focus{outline:none;color:var(--vp-c-white);background-color:var(--vp-c-sponsor)}.sp-icon[data-v-f3fa364a]{margin-right:8px;font-size:16px}.VPTeamMembers.small .container[data-v-6cb0dbc4]{grid-template-columns:repeat(auto-fit,minmax(224px,1fr))}.VPTeamMembers.small.count-1 .container[data-v-6cb0dbc4]{max-width:276px}.VPTeamMembers.small.count-2 .container[data-v-6cb0dbc4]{max-width:576px}.VPTeamMembers.small.count-3 .container[data-v-6cb0dbc4]{max-width:876px}.VPTeamMembers.medium .container[data-v-6cb0dbc4]{grid-template-columns:repeat(auto-fit,minmax(256px,1fr))}@media (min-width: 375px){.VPTeamMembers.medium .container[data-v-6cb0dbc4]{grid-template-columns:repeat(auto-fit,minmax(288px,1fr))}}.VPTeamMembers.medium.count-1 .container[data-v-6cb0dbc4]{max-width:368px}.VPTeamMembers.medium.count-2 .container[data-v-6cb0dbc4]{max-width:760px}.container[data-v-6cb0dbc4]{display:grid;gap:24px;margin:0 auto;max-width:1152px}:root{--vp-font-family-base: "Montserrat"}.one-image{padding:1em 0;width:100%;text-align:center}.one-image img{width:100%;margin:0 auto;max-width:500px}.one-image figcaption{font-style:italic;padding:1em 0;font-size:.9em}.rounded-shadow{border-radius:8px;box-shadow:#32325d40 0 50px 100px -20px,#0000004d 0 30px 60px -30px}.two-images{display:flex;align-items:flex;justify-content:space-between}.two-images figure{width:50%}.two-images figcaption{font-size:.8em;padding:1em;text-align:center}.two-images img{width:90%;margin:0 auto;max-width:250px}.VPLocalSearchBox[data-v-43c4f204]{position:fixed;z-index:100;top:0;right:0;bottom:0;left:0;display:flex}.backdrop[data-v-43c4f204]{position:absolute;top:0;right:0;bottom:0;left:0;background:var(--vp-backdrop-bg-color);transition:opacity .5s}.shell[data-v-43c4f204]{position:relative;padding:12px;margin:64px auto;display:flex;flex-direction:column;gap:16px;background:var(--vp-local-search-bg);width:min(100vw - 60px,900px);height:min-content;max-height:min(100vh - 128px,900px);border-radius:6px}@media (max-width: 767px){.shell[data-v-43c4f204]{margin:0;width:100vw;height:100vh;max-height:none;border-radius:0}}.search-bar[data-v-43c4f204]{border:1px solid var(--vp-c-divider);border-radius:4px;display:flex;align-items:center;padding:0 12px;cursor:text}@media (max-width: 767px){.search-bar[data-v-43c4f204]{padding:0 8px}}.search-bar[data-v-43c4f204]:focus-within{border-color:var(--vp-c-brand-1)}.local-search-icon[data-v-43c4f204]{display:block;font-size:18px}.navigate-icon[data-v-43c4f204]{display:block;font-size:14px}.search-icon[data-v-43c4f204]{margin:8px}@media (max-width: 767px){.search-icon[data-v-43c4f204]{display:none}}.search-input[data-v-43c4f204]{padding:6px 12px;font-size:inherit;width:100%}@media (max-width: 767px){.search-input[data-v-43c4f204]{padding:6px 4px}}.search-actions[data-v-43c4f204]{display:flex;gap:4px}@media (any-pointer: coarse){.search-actions[data-v-43c4f204]{gap:8px}}@media (min-width: 769px){.search-actions.before[data-v-43c4f204]{display:none}}.search-actions button[data-v-43c4f204]{padding:8px}.search-actions button[data-v-43c4f204]:not([disabled]):hover,.toggle-layout-button.detailed-list[data-v-43c4f204]{color:var(--vp-c-brand-1)}.search-actions button.clear-button[data-v-43c4f204]:disabled{opacity:.37}.search-keyboard-shortcuts[data-v-43c4f204]{font-size:.8rem;opacity:75%;display:flex;flex-wrap:wrap;gap:16px;line-height:14px}.search-keyboard-shortcuts span[data-v-43c4f204]{display:flex;align-items:center;gap:4px}@media (max-width: 767px){.search-keyboard-shortcuts[data-v-43c4f204]{display:none}}.search-keyboard-shortcuts kbd[data-v-43c4f204]{background:#8080801a;border-radius:4px;padding:3px 6px;min-width:24px;display:inline-block;text-align:center;vertical-align:middle;border:1px solid rgba(128,128,128,.15);box-shadow:0 2px 2px #0000001a}.results[data-v-43c4f204]{display:flex;flex-direction:column;gap:6px;overflow-x:hidden;overflow-y:auto;overscroll-behavior:contain}.result[data-v-43c4f204]{display:flex;align-items:center;gap:8px;border-radius:4px;transition:none;line-height:1rem;border:solid 2px var(--vp-local-search-result-border);outline:none}.result>div[data-v-43c4f204]{margin:12px;width:100%;overflow:hidden}@media (max-width: 767px){.result>div[data-v-43c4f204]{margin:8px}}.titles[data-v-43c4f204]{display:flex;flex-wrap:wrap;gap:4px;position:relative;z-index:1001;padding:2px 0}.title[data-v-43c4f204]{display:flex;align-items:center;gap:4px}.title.main[data-v-43c4f204]{font-weight:500}.title-icon[data-v-43c4f204]{opacity:.5;font-weight:500;color:var(--vp-c-brand-1)}.title svg[data-v-43c4f204]{opacity:.5}.result.selected[data-v-43c4f204]{--vp-local-search-result-bg: var(--vp-local-search-result-selected-bg);border-color:var(--vp-local-search-result-selected-border)}.excerpt-wrapper[data-v-43c4f204]{position:relative}.excerpt[data-v-43c4f204]{opacity:75%;pointer-events:none;max-height:140px;overflow:hidden;position:relative;opacity:.5;margin-top:4px}.result.selected .excerpt[data-v-43c4f204]{opacity:1}.excerpt[data-v-43c4f204] *{font-size:.8rem!important;line-height:130%!important}.titles[data-v-43c4f204] mark,.excerpt[data-v-43c4f204] mark{background-color:var(--vp-local-search-highlight-bg);color:var(--vp-local-search-highlight-text);border-radius:2px;padding:0 2px}.excerpt[data-v-43c4f204] .vp-code-group .tabs{display:none}.excerpt[data-v-43c4f204] .vp-code-group div[class*=language-]{border-radius:8px!important}.excerpt-gradient-bottom[data-v-43c4f204]{position:absolute;bottom:-1px;left:0;width:100%;height:8px;background:linear-gradient(transparent,var(--vp-local-search-result-bg));z-index:1000}.excerpt-gradient-top[data-v-43c4f204]{position:absolute;top:-1px;left:0;width:100%;height:8px;background:linear-gradient(var(--vp-local-search-result-bg),transparent);z-index:1000}.result.selected .titles[data-v-43c4f204],.result.selected .title-icon[data-v-43c4f204]{color:var(--vp-c-brand-1)!important}.no-results[data-v-43c4f204]{font-size:.9rem;text-align:center;padding:12px}svg[data-v-43c4f204]{flex:none} diff --git a/vitepress/docs/.vitepress/dist/assets/sync-use-layout-effect.DiHT__9B.gif b/vitepress/docs/.vitepress/dist/assets/sync-use-layout-effect.DiHT__9B.gif new file mode 100644 index 0000000..2075d6a Binary files /dev/null and b/vitepress/docs/.vitepress/dist/assets/sync-use-layout-effect.DiHT__9B.gif differ diff --git a/vitepress/docs/.vitepress/dist/assets/with-transitions.BF9oM46H.gif b/vitepress/docs/.vitepress/dist/assets/with-transitions.BF9oM46H.gif new file mode 100644 index 0000000..8d85d34 Binary files /dev/null and b/vitepress/docs/.vitepress/dist/assets/with-transitions.BF9oM46H.gif differ diff --git a/vitepress/docs/.vitepress/dist/assets/without-transitions.lHrdMMJM.gif b/vitepress/docs/.vitepress/dist/assets/without-transitions.lHrdMMJM.gif new file mode 100644 index 0000000..3e42e58 Binary files /dev/null and b/vitepress/docs/.vitepress/dist/assets/without-transitions.lHrdMMJM.gif differ diff --git a/vitepress/docs/.vitepress/dist/docs/accessibility.html b/vitepress/docs/.vitepress/dist/docs/accessibility.html new file mode 100644 index 0000000..4841346 --- /dev/null +++ b/vitepress/docs/.vitepress/dist/docs/accessibility.html @@ -0,0 +1,108 @@ + + + + + + Acessibilidade | React Native 0.72 + + + + + + + + + + + + + + + + +
Skip to content

Acessibilidade

Tanto o Android quanto o iOS fornecem APIs para integração de aplicativos com tecnologias assistivas, como os leitores de tela incluídos VoiceOver (iOS) e TalkBack (Android). React Native possui APIs complementares que permitem que seu aplicativo acomode todos os usuários.

INFORMAÇÕES Android e iOS diferem ligeiramente em suas abordagens e, portanto, as implementações do React Native podem variar de acordo com a plataforma.

Propriedades de acessibilidade

accessible

Quando verdadeiro, indica que a visualização é um elemento de acessibilidade. Quando uma visualização é um elemento de acessibilidade, ela agrupa seus filhos em um único componente selecionável. Por padrão, todos os elementos tocáveis estão acessíveis.

No Android, a propriedade access={true} para uma visualização react-native será traduzida em focusable={true} nativo.

tsx
<View accessible={true}>
+  <Text>texto um</Text>
+  <Text>texto dois</Text>
+</View>

No exemplo acima, o foco de acessibilidade está disponível apenas na visualização pai com a propriedade acessível, e não individualmente para 'texto um' e 'texto dois'.

accessibilityLabel

Quando uma visualização é marcada como acessível, é uma boa prática definir um accessibilityLabel na visualização, para que as pessoas que usam o VoiceOver ou o TalkBack saibam qual elemento selecionaram. Um leitor de tela verbalizará esta string quando o elemento associado for selecionado.

Para usar, defina a propriedade accessibilityLabel como uma string personalizada em sua View, Text ou Touchable:

tsx
<TouchableOpacity
+  accessible={true}
+  accessibilityLabel="Tap me!"
+  onPress={onPress}>
+  <View style={styles.button}>
+    <Text style={styles.buttonText}>Press me!</Text>
+  </View>
+</TouchableOpacity>

No exemplo acima, o accessLabel no elemento TouchableOpacity seria padronizado como "Press me!". O rótulo é construído concatenando todos os filhos do nó Text separados por espaços.

accessibilityLabelledBy [Android]

Uma referência a outro elemento nativeID usado para criar formulários complexos. O valor de acessibilidadeLabelledBy deve corresponder ao nativeID do elemento relacionado:

jsx
<View>
+  <Text nativeID="formLabel">Label for Input Field</Text>
+  <TextInput
+    accessibilityLabel="input"
+    accessibilityLabelledBy="formLabel"
+  />
+</View>

No exemplo acima, o leitor de tela anuncia Input, Edit Box for Label for Input Field ao focar no TextInput.

accessibilityHint

Uma dica de acessibilidade pode ser usada para fornecer contexto adicional ao usuário sobre o resultado da ação quando isso não estiver claro apenas no rótulo de acessibilidade.

Forneça à propriedade acessibilidadeHint uma string personalizada em sua View, Text ou Touchable:

jsx
<TouchableOpacity
+  accessible={true}
+  accessibilityLabel="Go back"
+  accessibilityHint="Navigates to the previous screen"
+  onPress={onPress}>
+  <View style={styles.button}>
+    <Text style={styles.buttonText}>Back</Text>
+  </View>
+</TouchableOpacity>

iOS

No exemplo acima, o VoiceOver lerá a dica após o rótulo, se o usuário tiver as dicas habilitadas nas configurações do VoiceOver do dispositivo. Leia mais sobre as diretrizes para acessibilidadeHint nos documentos do desenvolvedor iOS

Android

No exemplo acima, o TalkBack lerá a dica após o rótulo. No momento, as dicas não podem ser desativadas no Android.

accessibilityLanguage [iOS]

Ao usar a propriedade accessibilityLanguage, o leitor de tela entenderá qual idioma usar ao ler o label, o value e o hint. O valor da string fornecido deve seguir a especificação BCP 47.

tsx
<View
+  accessible={true}
+  accessibilityLabel="Pizza"
+  accessibilityLanguage="it-IT">
+  <Text>🍕</Text>
+</View>

acessibilidadeIgnoresInvertColors [iOS]

A inversão das cores da tela é um recurso de acessibilidade disponível no iOS e iPadOS para pessoas com daltonismo, baixa visão ou deficiência visual. Se houver uma visualização que você não deseja inverter quando esta configuração estiver ativada, possivelmente uma foto, defina esta propriedade como verdadeira.

accessibilityLiveRegion [Android]

Quando os componentes mudam dinamicamente, queremos que o TalkBack alerte o usuário final. Isso é possível graças à propriedade accessibilityLiveRegion. Pode ser definido como none, polite e assertive:

  • none Os serviços de acessibilidade não devem anunciar alterações nesta visão.
  • polite serviços de acessibilidade educados devem anunciar mudanças nesta visão.
  • assertive Os serviços de acessibilidade devem interromper o discurso em curso para anunciar imediatamente alterações nesta visão.
tsx
<TouchableWithoutFeedback onPress={addOne}>
+  <View style={styles.embedded}>
+    <Text>Click me</Text>
+  </View>
+</TouchableWithoutFeedback>
+<Text accessibilityLiveRegion="polite">
+  Clicked {count} times
+</Text>

No exemplo acima, o método addOne altera a contagem (count} da variável de estado. Quando TouchableWithoutFeedback é acionado, o TalkBack lê o texto na visualização Texto devido à sua propriedade accessibilityLiveRegion="polite".

accessibilityRole

accessibilityRole comunica a finalidade de um componente ao usuário de tecnologia assistiva.

accessibilityRole pode ser um dos seguintes:

  • adjustable Usado quando um elemento pode ser "ajustado" (por exemplo, um controle deslizante).
  • alert Usado quando um elemento contém texto importante a ser apresentado ao usuário.
  • button Usado quando o elemento deve ser tratado como um botão.
  • checkbox Usado quando um elemento representa uma caixa de seleção que pode ser marcada, desmarcada ou ter um estado misto de marcado.
  • combobox Usado quando um elemento representa uma caixa de combinação, que permite ao usuário selecionar entre diversas opções.
  • header Usado quando um elemento atua como cabeçalho para uma seção de conteúdo (por exemplo, o título de uma barra de navegação).
  • image Usado quando o elemento deve ser tratado como uma imagem. Pode ser combinado com um botão ou link.
  • imagebutton Utilizado quando o elemento deve ser tratado como um botão e também é uma imagem.
  • keyboardkey Usado quando o elemento atua como uma tecla do teclado.
  • link Usado quando o elemento deve ser tratado como um link.
  • menu Usado quando o componente é um menu de opções.
  • menubar Usada quando um componente é um contêiner de vários menus.
  • menuitem Usado para representar um item dentro de um menu.
  • none Usado quando o elemento não tem função.
  • progressbar Usado para representar um componente que indica o progresso de uma tarefa.
  • radio Usado para representar um botão de opção.
  • radiogroup Usado para representar um grupo de botões de opção.
  • scrollbar Usada para representar uma barra de rolagem.
  • search Usado quando um elemento de campo de texto também deve ser tratado como um campo de pesquisa.
  • spinbutton Usado para representar um botão que abre uma lista de opções.
  • summary Usado quando um elemento pode ser usado para fornecer um resumo rápido das condições atuais no aplicativo quando ele é iniciado pela primeira vez.
  • switch Usado para representar um switch que pode ser ligado e desligado.
  • tab Usado para representar uma guia.
  • tablist Usado para representar uma lista de guias.
  • text Usado quando o elemento deve ser tratado como texto estático que não pode ser alterado.
  • timer Usado para representar um timer.
  • togglebutton Usado para representar um botão de alternância. Deve ser usado com acessibilidadeState marcado para indicar se o botão está ativado ou desativado.
  • toolbar Usada para representar uma barra de ferramentas (um contêiner de botões de ação ou componentes).
  • grid Usado com ScrollView, VirtualizedList, FlatList ou SectionList para representar uma grade. Adiciona anúncios de entrada/saída da grade ao GridView do Android.

accessibilityState

Descreve o estado atual de um componente para o usuário de tecnologia assistiva.

acessibilidadeState é um objeto. Ele contém os seguintes campos:

NOMEDESCRIÇÃOTIPOOBRIGATÓRIO
disabledIndica se o elemento está desabilitado ou não.booleanNão
selectedIndica se um elemento selecionável está selecionado ou não.booleanNão
checkedIndica o estado de um elemento verificável. Este campo pode receber uma string booleana ou "mista" para representar caixas de seleção mistas.boolean ou 'mixed'Não
busyIndica se um elemento está ocupado ou não.booleanNão
expandedIndica se um elemento expansível está atualmente expandido ou recolhido.booleanNão

Para usar, defina accessibilityState como um objeto com uma definição específica.

accessibilityValue

Representa o valor atual de um componente. Pode ser uma descrição textual do valor de um componente ou, para componentes baseados em intervalo, como controles deslizantes e barras de progresso, contém informações de intervalo (mínimo, atual e máximo).

accessibilityValue é um objeto. Ele contém os seguintes campos:

NOMEDESCRIÇÃOTIPONECESSÁRIO
minO valor mínimo do intervalo deste componente.integerObrigatório se now estiver definido.
maxO valor máximo do intervalo deste componente.integerObrigatório se now estiver definido.
nowO valor atual do intervalo deste componente.integerNão
textUma descrição textual do valor deste componente. Substituirá min, now e max se definido.integerNão

accessibilityViewIsModal [iOS]

Um valor booleano que indica se o VoiceOver deve ignorar os elementos nas visualizações que são irmãos do receptor.

Por exemplo, em uma janela que contém visualizações irmãs A e B, definir accessibilityViewIsModal como true na visualização B faz com que o VoiceOver ignore os elementos na visualização A. Por outro lado, se a visualização B contiver uma visualização filha C e você definir accessibilityViewIsModal como true na visualização C, o VoiceOver não ignora os elementos da visualização A.

accessibilityElementsHidden [iOS]

Um valor booleano que indica se os elementos de acessibilidade contidos neste elemento de acessibilidade estão ocultos.

Por exemplo, em uma janela que contém visualizações irmãs A e B, definir accessibilityElementsHidden como verdadeiro na visualização B faz com que o VoiceOver ignore os elementos na visualização B. Isso é semelhante à propriedade Android importantForAccessibility="no-hide-descendants".

aria-valuemax

Representa o valor máximo para componentes baseados em intervalo, como controles deslizantes e barras de progresso.

aria-valuemin

Representa o valor mínimo para componentes baseados em intervalo, como controles deslizantes e barras de progresso.

aria-valuenow

Representa o valor atual para componentes baseados em intervalo, como controles deslizantes e barras de progresso.

aria-valuetext

Representa a descrição textual do componente.

aria-busy

Indica que um elemento está sendo modificado e que as tecnologias assistivas podem querer esperar até que as alterações sejam concluídas antes de informar o usuário sobre a atualização.

TIPOPADRÃO
booleanfalse

aria-checked

Indica o estado de um elemento verificável. Este campo pode receber uma string booleana ou "mista" para representar caixas de seleção mistas.

TIPOPADRÃO
boolean, 'mixed'false

aria-disabled

Indica que o elemento é perceptível, mas desabilitado, portanto não é editável ou operável de outra forma.

TIPOPADRÃO
booleanfalse

aria-expanded

Indica se um elemento expansível está atualmente expandido ou recolhido.

TIPOPADRÃO
booleanfalse

aria-hidden

Indica se os elementos de acessibilidade contidos neste elemento de acessibilidade estão ocultos.

Por exemplo, numa janela que contém vistas irmãs A e B, definir aria-hidden como verdadeiro na vista B faz com que o VoiceOver ignore os elementos na vista B.

TIPOPADRÃO
booleanfalse

aria-label

Define um valor de string que rotula um elemento interativo.

TIPO
string

aria-labelledby [Android]

Identifica o elemento que rotula o elemento ao qual é aplicado. O valor de aria-labelledby deve corresponder ao nativeID do elemento relacionado:

jsx
<View>
+  <Text nativeID="formLabel">Label for Input Field</Text>
+  <TextInput aria-label="input" aria-labelledby="formLabel" />
+</View>
TIPO
string

aria-live [Android]

Indica que um elemento será atualizado e descreve os tipos de atualizações que os agentes de usuário, as tecnologias assistivas e o usuário podem esperar da região ativa.

  • off Os serviços de acessibilidade não devem anunciar alterações nesta visualização.
  • polite Os serviços de acessibilidade devem anunciar alterações nesta visão.
  • assertive Os serviços de acessibilidade devem interromper o discurso em curso para anunciar imediatamente alterações nesta visão.
TIPOPADRÃO
enum('assertive', 'off', 'polite')'off'

aria-modal [iOS]

Valor booleano que indica se o VoiceOver deve ignorar os elementos nas visualizações que são irmãos do receptor.

TIPOPADRÃO
booleanfalse

aria-selected

Indica se um elemento selecionável está selecionado ou não.

TIPO
boolean

importantForAccessibility [Android]

No caso de dois componentes de UI sobrepostos com o mesmo pai, o foco de acessibilidade padrão pode ter um comportamento imprevisível. A propriedade importantForAccessibility resolverá isso controlando se uma visualização dispara eventos de acessibilidade e se é reportada aos serviços de acessibilidade. Pode ser definido como auto, yes, no e no-hide-descendants (o último valor forçará os serviços de acessibilidade a ignorar o componente e todos os seus filhos).

jsx
<View style={styles.container}>
+  <View
+    style={[styles.layout, {backgroundColor: 'green'}]}
+    importantForAccessibility="yes">
+    <Text>First layout</Text>
+  </View>
+  <View
+    style={[styles.layout, {backgroundColor: 'yellow'}]}
+    importantForAccessibility="no-hide-descendants">
+    <Text>Second layout</Text>
+  </View>
+</View>

No exemplo acima, o layout yellow e seus descendentes são completamente invisíveis para o TalkBack e todos os outros serviços de acessibilidade. Assim, podemos usar visualizações sobrepostas com o mesmo pai sem confundir o TalkBack.

onAccessibilityEscape [iOS]

Atribua esta propriedade a uma função personalizada que será chamada quando alguém realizar o gesto de "escape", que é um gesto em forma de Z com dois dedos. Uma função de escape deve voltar hierarquicamente na interface do usuário. Isso pode significar subir ou voltar em uma hierarquia de navegação ou descartar uma interface de usuário modal. Se o elemento selecionado não tiver uma função onAccessibilityEscape, o sistema tentará percorrer a hierarquia de visualizações até encontrar uma visualização que tenha ou piscar para indicar que não foi possível encontrar uma.

onAccessibilityTap

Use esta propriedade para atribuir uma função personalizada a ser chamada quando alguém ativar um elemento acessível tocando duas vezes nele enquanto estiver selecionado.

onMagicTap [iOS]

Atribua esta propriedade a uma função personalizada que será chamada quando alguém realizar o gesto de "toque mágico", que é um toque duplo com dois dedos. Uma função de toque mágico deve executar a ação mais relevante que um usuário pode realizar em um componente. No aplicativo Telefone do iPhone, um toque mágico atende uma chamada ou encerra a atual. Se o elemento selecionado não tiver uma função onMagicTap, o sistema percorrerá a hierarquia de visualizações até encontrar uma visualização que tenha.

role

role comunica a finalidade de um componente e tem precedência sobre a propriedade accessRole.

a função pode ser uma das seguintes:

  • alert Usado quando um elemento contém texto importante a ser apresentado ao usuário.
  • button Usado quando o elemento deve ser tratado como um botão.
  • checkbox Usado quando um elemento representa uma caixa de seleção que pode ser marcada, desmarcada ou ter um estado misto de marcado.
  • combobox Usado quando um elemento representa uma caixa de combinação, que permite ao usuário selecionar entre diversas opções.
  • grid Usado com ScrollView, VirtualizedList, FlatList ou SectionList para representar uma grade. Adiciona os anúncios de entrada/saída da grade ao GridView do Android.
  • heading Usado quando um elemento atua como cabeçalho para uma seção de conteúdo (por exemplo, o título de uma barra de navegação).
  • img Usado quando o elemento deve ser tratado como uma imagem. Pode ser combinado com um botão ou link, por exemplo.
  • link Usado quando o elemento deve ser tratado como um link.
  • list Usado para identificar uma lista de itens.
  • menu Usado quando o componente é um menu de opções.
  • menubar Usada quando um componente é um contêiner de vários menus.
  • menuitem Usado para representar um item dentro de um menu.
  • none Usado quando o elemento não tem função.
  • presentation Usado quando o elemento não tem função.
  • progressbar Usado para representar um componente que indica o progresso de uma tarefa.
  • radio Usado para representar um botão de opção.
  • radiogroup Usado para representar um grupo de botões de opção.
  • scrollbar Usada para representar uma barra de rolagem.
  • searchbox Usado quando o elemento do campo de texto também deve ser tratado como um campo de pesquisa.
  • slider Usado quando um elemento pode ser "ajustado" (por exemplo, um controle deslizante).
  • spinbutton Usado para representar um botão que abre uma lista de opções.
  • summary Usado quando um elemento pode ser usado para fornecer um resumo rápido das condições atuais no aplicativo quando ele é iniciado pela primeira vez.
  • switch Usado para representar um switch que pode ser ligado e desligado.
  • tab Usado para representar uma guia.
  • tablist Usado para representar uma lista de guias.
  • timer Usado para representar um timer.
  • toolbar Usada para representar uma barra de ferramentas (um contêiner de botões de ação ou componentes).

Ações de acessibilidade

As ações de acessibilidade permitem que a tecnologia assistiva invoque programaticamente a(s) ação(ões) de um componente. Para apoiar ações de acessibilidade, um componente deve fazer duas coisas:

  • Defina a lista de ações suportadas por meio da propriedade accessibilityActions.
  • Implemente uma função onAccessibilityAction para lidar com solicitações de ação.

A propriedade accessibilityActions deve conter uma lista de objetos de ação. Cada objeto de ação deve conter os seguintes campos:

NOMETIPOOBRIGATÓRIO
namestringSim
labelstringNão

As ações representam ações padrão, como clicar em um botão ou ajustar um controle deslizante, ou ações personalizadas específicas de um determinado componente, como excluir uma mensagem de email. O campo name é obrigatório para ações padrão e personalizadas, mas o label é opcional para ações padrão.

Ao adicionar suporte para ações padrão, o name deve ser um dos seguintes:

  • 'magicTap' - apenas iOS - Enquanto o foco do VoiceOver está no componente ou dentro dele, o usuário toca duas vezes com dois dedos.
  • 'escape' - apenas iOS - Enquanto o foco do VoiceOver está no componente ou dentro dele, o usuário executou um gesto de esfregar com dois dedos (esquerda, direita, esquerda).
  • 'activate' - Ativa o componente. Este deve realizar a mesma ação com ou sem tecnologia assistiva. Ativado quando um usuário de leitor de tela toca duas vezes no componente.
  • 'increment' - Incrementa um componente ajustável. No iOS, o VoiceOver gera essa ação quando o componente tem a função de ‘ajustável’ e o usuário coloca o foco nele e desliza para cima. No Android, o TalkBack gera essa ação quando o usuário coloca o foco de acessibilidade no componente e pressiona o botão de aumentar volume.
  • 'decrement' - Diminui um componente ajustável. No iOS, o VoiceOver gera essa ação quando o componente tem a função de ‘ajustável’ e o usuário coloca o foco nele e desliza para baixo. No Android, o TalkBack gera essa ação quando o usuário coloca o foco de acessibilidade no componente e pressiona o botão de diminuir volume.
  • 'longpress' - somente Android - Esta ação é gerada quando o usuário coloca o foco de acessibilidade no componente, depois dá um toque duplo e mantém um dedo na tela. Este deve realizar a mesma ação com ou sem tecnologia assistiva.

O campo label é opcional para ações padrão e muitas vezes não é utilizado por tecnologias assistivas. Para ações customizadas, é uma string localizada contendo uma descrição da ação a ser apresentada ao usuário.

Para lidar com solicitações de ação, um componente deve implementar uma função onAccessibilityAction. O único argumento para esta função é um evento contendo o nome da ação a ser executada. O exemplo abaixo do RNTester mostra como criar um componente que define e trata diversas ações customizadas.

jsx
<View
+  accessible={true}
+  accessibilityActions={[
+    {name: 'cut', label: 'cut'},
+    {name: 'copy', label: 'copy'},
+    {name: 'paste', label: 'paste'},
+  ]}
+  onAccessibilityAction={event => {
+    switch (event.nativeEvent.actionName) {
+      case 'cut':
+        Alert.alert('Alert', 'cut action success');
+        break;
+      case 'copy':
+        Alert.alert('Alert', 'copy action success');
+        break;
+      case 'paste':
+        Alert.alert('Alert', 'paste action success');
+        break;
+    }
+  }}
+/>

Verificando se um leitor de tela está ativado

A API AccessibilityInfo permite determinar se um leitor de tela está ativo ou não. Consulte a documentação do AccessibilityInfo para obter detalhes.

Envio de eventos de acessibilidade Android [Android]

Às vezes é útil acionar um evento de acessibilidade em um componente de UI (ou seja, quando uma visualização personalizada aparece em uma tela ou define o foco de acessibilidade para uma visualização). O módulo UIManager nativo expõe um método 'sendAccessibilityEvent' para esta finalidade. São necessários dois argumentos: uma tag de visualização e um tipo de evento. Os tipos de eventos suportados são typeWindowStateChanged, typeViewFocused e typeViewClicked.

jsx
import {Platform, UIManager, findNodeHandle} from 'react-native';
+
+if (Platform.OS === 'android') {
+  UIManager.sendAccessibilityEvent(
+    findNodeHandle(this),
+    UIManager.AccessibilityEventTypes.typeViewFocused,
+  );
+}

Testando o suporte do TalkBack [Android]

Para ativar o TalkBack, acesse o aplicativo Configurações em seu dispositivo ou emulador Android. Toque em Acessibilidade e depois em TalkBack. Alterne a opção "Usar serviço" para ativá-lo ou desativá-lo.

Os emuladores Android não têm o TalkBack instalado por padrão. Você pode instalar o TalkBack no seu emulador através da Google Play Store. Certifique-se de escolher um emulador com a Google Play Store instalada. Eles estão disponíveis no Android Studio.

Você pode usar o atalho da tecla de volume para alternar o TalkBack. Para ativar o atalho da tecla de volume, vá para o aplicativo Configurações e, em seguida, Acessibilidade. Na parte superior, ative o atalho da tecla de volume.

Para usar o atalho da tecla de volume, pressione ambas as teclas de volume por 3 segundos para iniciar uma ferramenta de acessibilidade.

Além disso, se preferir, você pode alternar o TalkBack por meio da linha de comando com:

# desabilitado
+adb shell settings put secure enabled_accessibility_services com.android.talkback/com.google.android.marvin.talkback.TalkBackService
+
+# habilitado
+adb shell settings put secure enabled_accessibility_services com.google.android.marvin.talkback/com.google.android.marvin.talkback.TalkBackService

Testando o suporte do VoiceOver [iOS]

Para ativar o VoiceOver em seu dispositivo iOS ou iPadOS, acesse o aplicativo Ajustes, toque em Geral e em Acessibilidade. Lá você encontrará muitas ferramentas disponíveis para as pessoas permitirem que seus dispositivos sejam mais utilizáveis, incluindo VoiceOver. Para ativar o VoiceOver, toque em VoiceOver em “Visão” e alterne o botão que aparece na parte superior.

Na parte inferior das configurações de acessibilidade, há um “Atalho de acessibilidade”. Você pode usar isso para alternar o VoiceOver clicando três vezes no botão Início.

O VoiceOver não está disponível por meio do simulador, mas você pode usar o Accessibility Inspector do Xcode para usar o macOS VoiceOver por meio de um aplicativo. Observe que é sempre melhor testar com um dispositivo, pois o VoiceOver do macOS pode resultar em experiências variadas.

Recursos adicionais

+ + + + \ No newline at end of file diff --git a/vitepress/docs/.vitepress/dist/docs/animations.html b/vitepress/docs/.vitepress/dist/docs/animations.html new file mode 100644 index 0000000..b179602 --- /dev/null +++ b/vitepress/docs/.vitepress/dist/docs/animations.html @@ -0,0 +1,417 @@ + + + + + + Animações | React Native 0.72 + + + + + + + + + + + + + + + + +
Skip to content

Animações

As animações são muito importantes para criar uma ótima experiência do usuário. Objetos estacionários devem superar a inércia à medida que começam a se mover. Objetos em movimento têm impulso e raramente param imediatamente. As animações permitem transmitir movimentos fisicamente verossímeis em sua interface.

React Native fornece dois sistemas de animação complementares: Animated para controle granular e interativo de valores específicos e LayoutAnimation para transações de layout global animadas.

Animated API

A API Animated foi projetada para expressar de forma concisa uma ampla variedade de padrões interessantes de animação e interação com muito desempenho. Animated concentra-se em relacionamentos declarativos entre entradas e saídas, com transformações configuráveis entre elas e métodos de start/stop para controlar a execução da animação baseada em tempo.

Animated exporta seis tipos de componentes animáveis: View, Text, Image, ScrollView, FlatList e SectionList, mas você também pode criar o seu próprio usando Animated.createAnimatedComponent().

Por exemplo, uma visualização de contêiner que aparece gradualmente quando é montada pode ter esta aparência:

tsx
import React, {useRef, useEffect} from 'react';
+import {Animated, Text, View} from 'react-native';
+import type {PropsWithChildren} from 'react';
+import type {ViewStyle} from 'react-native';
+
+type FadeInViewProps = PropsWithChildren<{style: ViewStyle}>;
+
+const FadeInView: React.FC<FadeInViewProps> = props => {
+  const fadeAnim = useRef(new Animated.Value(0)).current; // Valor inicial para opacidade: 0
+
+  useEffect(() => {
+    Animated.timing(fadeAnim, {
+      toValue: 1,
+      duration: 10000,
+      useNativeDriver: true,
+    }).start();
+  }, [fadeAnim]);
+
+  return (
+    <Animated.View // View especial animável
+      style={{
+        ...props.style,
+        opacity: fadeAnim, // Vincular opacidade ao valor animado
+      }}>
+      {props.children}
+    </Animated.View>
+  );
+};
+
+// Você pode então usar seu `FadeInView` no lugar de um `View` em seus componentes:
+export default () => {
+  return (
+    <View
+      style={{
+        flex: 1,
+        alignItems: 'center',
+        justifyContent: 'center',
+      }}>
+      <FadeInView
+        style={{
+          width: 250,
+          height: 50,
+          backgroundColor: 'powderblue',
+        }}>
+        <Text style={{fontSize: 28, textAlign: 'center', margin: 10}}>
+          Fading in
+        </Text>
+      </FadeInView>
+    </View>
+  );
+};

image

Vamos analisar o que está acontecendo aqui. No construtor FadeInView, um novo Animated.Value chamado fadeAnim é inicializado como parte do estado. A propriedade de opacidade na View é mapeada para esse valor animado. Nos bastidores, o valor numérico é extraído e usado para definir a opacidade.

Quando o componente é montado, a opacidade é definida como 0. Em seguida, uma animação de atenuação é iniciada no valor animado fadeAnim, que atualizará todos os seus mapeamentos dependentes (neste caso, apenas a opacidade) em cada quadro à medida que o valor for animado para o valor final de 1.

Isso é feito de maneira otimizada e mais rápida do que chamar setState e renderizar novamente. Como toda a configuração é declarativa, poderemos implementar otimizações adicionais que serializam a configuração e executam a animação em um thread de alta prioridade.

Configurando animações

As animações são altamente configuráveis. Funções de atenuação personalizadas e predefinidas, atrasos, durações, fatores de decaimento, constantes de mola e muito mais podem ser ajustados dependendo do tipo de animação.

Animated fornece vários tipos de animação, sendo o mais comumente usado Animated.timing(). Ele suporta a animação de um valor ao longo do tempo usando uma das várias funções de atenuação predefinidas, ou você pode usar a sua própria. As funções de atenuação são normalmente usadas em animação para transmitir aceleração e desaceleração graduais de objetos.

Por padrão, o tempo usará uma curva easyInOut que transmite aceleração gradual até a velocidade máxima e termina desacelerando gradualmente até parar. Você pode especificar uma função de atenuação diferente passando um parâmetro de easing. A durationpersonalizada ou mesmo umdelay` antes do início da animação também é suportada.

Por exemplo, se quisermos criar uma animação de 2 segundos de um objeto que recua ligeiramente antes de se mover para sua posição final:

js
Animated.timing(this.state.xPosition, {
+  toValue: 100,
+  easing: Easing.back(),
+  duration: 2000,
+  useNativeDriver: true,
+}).start();

Dê uma olhada na seção Configurando animações da referência da API animada para saber mais sobre todos os parâmetros de configuração suportados pelas animações integradas.

Compondo animações

As animações podem ser combinadas e reproduzidas em sequência ou em paralelo. As animações sequenciais podem ser reproduzidas imediatamente após o término da animação anterior ou podem começar após um atraso especificado. A API Animated fornece vários métodos, como sequence() e delay(), cada um dos quais usa uma matriz de animações para ser executado e chama automaticamente start()/stop() conforme necessário.

Por exemplo, a animação a seguir para e depois retorna enquanto gira em paralelo:

jsx
Animated.sequence([
+  // decair, então o spring começa e gira
+  Animated.decay(position, {
+    // desce até parar
+    velocity: {x: gestureState.vx, y: gestureState.vy}, // velocidade da liberação do gesto
+    deceleration: 0.997,
+    useNativeDriver: true,
+  }),
+  Animated.parallel([
+    // após a decadência, em paralelo:
+    Animated.spring(position, {
+      toValue: {x: 0, y: 0}, // voltar para começar
+      useNativeDriver: true,
+    }),
+    Animated.timing(twirl, {
+      // e girar
+      toValue: 360,
+      useNativeDriver: true,
+    }),
+  ]),
+]).start(); // iniciar o grupo de sequência

Se uma animação for parada ou interrompida, todas as outras animações do grupo também serão interrompidas. Animated.parallel tem uma opção stopTogether que pode ser definida como false para desabilitar isso.

Você pode encontrar uma lista completa de métodos de composição na seção Compondo animações da referência da API Animated.

Combinando valores animados

Você pode combinar dois valores animados por meio de adição, multiplicação, divisão ou módulo para criar um novo valor animado.

Existem alguns casos em que um valor animado precisa inverter outro valor animado para cálculo. Um exemplo é inverter uma escala (2x -> 0,5x):

jsx
const a = new Animated.Value(1);
+const b = Animated.divide(1, a);
+
+Animated.spring(a, {
+  toValue: 2,
+  useNativeDriver: true,
+}).start();

Interpolação

Cada propriedade pode ser executada primeiro por meio de uma interpolação. Uma interpolação mapeia intervalos de entrada para intervalos de saída, normalmente usando uma interpolação linear, mas também oferece suporte a funções de atenuação. Por padrão, ele extrapolará a curva além dos intervalos fornecidos, mas você também poderá limitar o valor de saída.

Um mapeamento básico para converter um intervalo de 0-1 em um intervalo de 0-100 seria:

js
value.interpolate({
+  inputRange: [0, 1],
+  outputRange: [0, 100],
+});

Por exemplo, você pode querer pensar em seu Animated.Value como indo de 0 a 1, mas anime a posição de 150px para 0px e a opacidade de 0 a 1. Isso pode ser feito modificando o style do exemplo acima, assim:

jsx
  style={{
+    opacity: this.state.fadeAnim, // Vincula diretamente
+    transform: [{
+      translateY: this.state.fadeAnim.interpolate({
+        inputRange: [0, 1],
+        outputRange: [150, 0]  // 0 : 150, 0.5 : 75, 1 : 0
+      }),
+    }],
+  }}

interpolate() também suporta vários segmentos de intervalo, o que é útil para definir zonas mortas e outros truques úteis. Por exemplo, para obter um relacionamento de negação em -300 que vai para 0 em -100, depois volta para 1 em 0 e depois volta para zero em 100 seguido por uma zona morta que permanece em 0 para tudo além disso, você poderia fazer:

js
value.interpolate({
+  inputRange: [-300, -100, 0, 100, 101],
+  outputRange: [300, 0, 1, 0, 0],
+});

O que seria mapeado assim:

Input | Output
+------|-------
+  -400|    450
+  -300|    300
+  -200|    150
+  -100|      0
+   -50|    0.5
+     0|      1
+    50|    0.5
+   100|      0
+   101|      0
+   200|      0

interpolate() também suporta mapeamento para strings, permitindo animar cores e também valores com unidades. Por exemplo, se você quiser animar uma rotação você poderia fazer:

js
value.interpolate({
+  inputRange: [0, 360],
+  outputRange: ['0deg', '360deg'],
+});

interpolate() também suporta funções de atenuação arbitrárias, muitas das quais já estão implementadas no módulo Easing. interpolate() também possui comportamento configurável para extrapolar o outputRange. Você pode definir a extrapolação definindo as opções extrapolate, extrapolateLeft ou extrapolateRight. O valor padrão é extend, mas você pode usar clamp para evitar que o valor de saída exceda outputRange.

Rastreando valores dinâmicos

Os valores animados também podem rastrear outros valores definindo toValue de uma animação como outro valor animado em vez de um número simples. Por exemplo, uma animação "Chat Heads" como a usada pelo Messenger no Android poderia ser implementada com um spring() fixado em outro valor animado, ou com timing() e uma duration de 0 para rastreamento rígido. Também podem ser compostos com interpolações:

jsx
Animated.spring(follower, {toValue: leader}).start();
+Animated.timing(opacity, {
+  toValue: pan.x.interpolate({
+    inputRange: [0, 300],
+    outputRange: [1, 0],
+    useNativeDriver: true,
+  }),
+}).start();

Os valores animados do leader e do follower seriam implementados usando Animated.ValueXY(). ValueXY é uma maneira prática de lidar com interações 2D, como panorâmica ou arrastamento. É um wrapper básico que contém duas instâncias de Animated.Value e algumas funções auxiliares que as chamam, tornando ValueXY um substituto imediato para Value em muitos casos. Isso nos permite rastrear os valores de x e y no exemplo acima.

Gestos de rastreamento

Gestos, como movimento panorâmico ou rolagem, e outros eventos podem ser mapeados diretamente para valores animados usando Animated.event. Isto é feito com uma sintaxe de mapa estruturada para que os valores possam ser extraídos de objetos de eventos complexos. O primeiro nível é uma matriz para permitir o mapeamento entre vários argumentos, e essa matriz contém objetos aninhados.

Por exemplo, ao trabalhar com gestos de rolagem horizontal, você faria o seguinte para mapear event.nativeEvent.contentOffset.x para scrollX (um Animated.Value):

jsx
 onScroll={Animated.event(
+   // scrollX = e.nativeEvent.contentOffset.x
+   [{nativeEvent: {
+        contentOffset: {
+          x: scrollX
+        }
+      }
+    }]
+ )}

O exemplo a seguir implementa um carrossel de rolagem horizontal onde os indicadores de posição de rolagem são animados usando o Animated.event usado no ScrollView

ScrollView com exemplo de evento animado

jsx
import React, {useRef} from 'react';
+import {
+  SafeAreaView,
+  ScrollView,
+  Text,
+  StyleSheet,
+  View,
+  ImageBackground,
+  Animated,
+  useWindowDimensions,
+} from 'react-native';
+
+const images = new Array(6).fill(
+  'https://images.unsplash.com/photo-1556740749-887f6717d7e4',
+);
+
+const App = () => {
+  const scrollX = useRef(new Animated.Value(0)).current;
+
+  const {width: windowWidth} = useWindowDimensions();
+
+  return (
+    <SafeAreaView style={styles.container}>
+      <View style={styles.scrollContainer}>
+        <ScrollView
+          horizontal={true}
+          pagingEnabled
+          showsHorizontalScrollIndicator={false}
+          onScroll={Animated.event([
+            {
+              nativeEvent: {
+                contentOffset: {
+                  x: scrollX,
+                },
+              },
+            },
+          ])}
+          scrollEventThrottle={1}>
+          {images.map((image, imageIndex) => {
+            return (
+              <View style={{width: windowWidth, height: 250}} key={imageIndex}>
+                <ImageBackground source={{uri: image}} style={styles.card}>
+                  <View style={styles.textContainer}>
+                    <Text style={styles.infoText}>
+                      {'Image - ' + imageIndex}
+                    </Text>
+                  </View>
+                </ImageBackground>
+              </View>
+            );
+          })}
+        </ScrollView>
+        <View style={styles.indicatorContainer}>
+          {images.map((image, imageIndex) => {
+            const width = scrollX.interpolate({
+              inputRange: [
+                windowWidth * (imageIndex - 1),
+                windowWidth * imageIndex,
+                windowWidth * (imageIndex + 1),
+              ],
+              outputRange: [8, 16, 8],
+              extrapolate: 'clamp',
+            });
+            return (
+              <Animated.View
+                key={imageIndex}
+                style={[styles.normalDot, {width}]}
+              />
+            );
+          })}
+        </View>
+      </View>
+    </SafeAreaView>
+  );
+};
+
+const styles = StyleSheet.create({
+  container: {
+    flex: 1,
+    alignItems: 'center',
+    justifyContent: 'center',
+  },
+  scrollContainer: {
+    height: 300,
+    alignItems: 'center',
+    justifyContent: 'center',
+  },
+  card: {
+    flex: 1,
+    marginVertical: 4,
+    marginHorizontal: 16,
+    borderRadius: 5,
+    overflow: 'hidden',
+    alignItems: 'center',
+    justifyContent: 'center',
+  },
+  textContainer: {
+    backgroundColor: 'rgba(0,0,0, 0.7)',
+    paddingHorizontal: 24,
+    paddingVertical: 8,
+    borderRadius: 5,
+  },
+  infoText: {
+    color: 'white',
+    fontSize: 16,
+    fontWeight: 'bold',
+  },
+  normalDot: {
+    height: 8,
+    width: 8,
+    borderRadius: 4,
+    backgroundColor: 'silver',
+    marginHorizontal: 4,
+  },
+  indicatorContainer: {
+    flexDirection: 'row',
+    alignItems: 'center',
+    justifyContent: 'center',
+  },
+});
+
+export default App;

image

Ao usar o PanResponder, você pode usar o código a seguir para extrair as posições x e y de gestureState.dx e gestureState.dy. Usamos um null na primeira posição do array, pois estamos interessados apenas no segundo argumento passado para o manipulador PanResponder, que é o gestureState.

jsx
onPanResponderMove={Animated.event(
+  [null, // ignora o evento nativo
+  // extraia dx e dy do gestureState
+  // como 'pan.x = gestureState.dx, pan.y = gestureState.dy'
+  {dx: pan.x, dy: pan.y}
+])}

PanResponder com exemplo de evento animado

jsx
import React, {useRef} from 'react';
+import {Animated, View, StyleSheet, PanResponder, Text} from 'react-native';
+
+const App = () => {
+  const pan = useRef(new Animated.ValueXY()).current;
+  const panResponder = useRef(
+    PanResponder.create({
+      onMoveShouldSetPanResponder: () => true,
+      onPanResponderMove: Animated.event([null, {dx: pan.x, dy: pan.y}]),
+      onPanResponderRelease: () => {
+        Animated.spring(pan, {
+          toValue: {x: 0, y: 0},
+          useNativeDriver: true,
+        }).start();
+      },
+    }),
+  ).current;
+
+  return (
+    <View style={styles.container}>
+      <Text style={styles.titleText}>Drag & Release this box!</Text>
+      <Animated.View
+        style={{
+          transform: [{translateX: pan.x}, {translateY: pan.y}],
+        }}
+        {...panResponder.panHandlers}>
+        <View style={styles.box} />
+      </Animated.View>
+    </View>
+  );
+};
+
+const styles = StyleSheet.create({
+  container: {
+    flex: 1,
+    alignItems: 'center',
+    justifyContent: 'center',
+  },
+  titleText: {
+    fontSize: 14,
+    lineHeight: 24,
+    fontWeight: 'bold',
+  },
+  box: {
+    height: 150,
+    width: 150,
+    backgroundColor: 'blue',
+    borderRadius: 5,
+  },
+});
+
+export default App;

image

Respondendo ao valor atual da animação

Você pode perceber que não há uma maneira clara de ler o valor atual durante a animação. Isso ocorre porque o valor só pode ser conhecido no tempo de execução nativo devido a otimizações. Se você precisar executar JavaScript em resposta ao valor atual, existem duas abordagens:

  • spring.stopAnimation(callback) interromperá a animação e invocará o retorno de chamada com o valor final. Isto é útil ao fazer transições de gestos.
  • spring.addListener(callback) invocará o retorno de chamada de forma assíncrona enquanto a animação estiver em execução, fornecendo um valor recente. Isso é útil para acionar mudanças de estado, por exemplo, encaixar um bobble em uma nova opção conforme o usuário o arrasta para mais perto, porque essas mudanças de estado maiores são menos sensíveis a alguns quadros de atraso em comparação com gestos contínuos como o movimento panorâmico, que precisa ser executado a 60 fps.

Animated foi projetado para ser totalmente serializável para que as animações possam ser executadas com alto desempenho, independentemente do loop de eventos normal do JavaScript. Isso influencia a API, então tenha isso em mente quando parecer um pouco mais complicado fazer algo em comparação com um sistema totalmente síncrono. Confira Animated.Value.addListener como uma forma de contornar algumas dessas limitações, mas use-o com moderação, pois pode ter implicações de desempenho no futuro.

Usando o driver nativo

A API Animated foi projetada para ser serializável. Ao usar o driver nativo, enviamos tudo sobre a animação para o nativo antes de iniciá-la, permitindo que o código nativo execute a animação no thread da UI sem ter que passar pela ponte em cada quadro. Depois que a animação for iniciada, o thread JS poderá ser bloqueado sem afetar a animação.

O uso do driver nativo para animações normais pode ser feito definindo useNativeDriver: true na configuração da animação ao iniciá-la. Animações sem uma propriedade useNativeDriver serão padronizadas como false por motivos legados, mas emitirão um aviso (e erro de verificação de digitação no TypeScript).

js
Animated.timing(this.state.animatedValue, {
+  toValue: 1,
+  duration: 500,
+  useNativeDriver: true, // <-- Seta isso como true
+}).start();

Os valores animados são compatíveis apenas com um driver, portanto, se você usar o driver nativo ao iniciar uma animação em um valor, certifique-se de que cada animação nesse valor também use o driver nativo.

O driver nativo também funciona com Animated.event. Isso é especialmente útil para animações que seguem a posição de rolagem, pois sem o driver nativo, a animação sempre executará um quadro atrás do gesto devido à natureza assíncrona do React Native.

jsx
<Animated.ScrollView // <-- Use o wrapper ScrollView animado
+  scrollEventThrottle={1} // <--Use 1 aqui para garantir que nenhum evento seja perdido
+  onScroll={Animated.event(
+    [
+      {
+        nativeEvent: {
+          contentOffset: {y: this.state.animatedValue},
+        },
+      },
+    ],
+    {useNativeDriver: true}, // <-- Seta isso como true
+  )}>
+  {content}
+</Animated.ScrollView>

Você pode ver o driver nativo em ação executando o aplicativo RNTester e carregando o exemplo animado nativo. Você também pode dar uma olhada no código-fonte para saber como esses exemplos foram produzidos.

Ressalvas

Nem tudo o que você pode fazer com o Animated é atualmente compatível com o driver nativo. A principal limitação é que você só pode animar propriedades que não sejam de layout: coisas como transformation e opacity funcionarão, mas Flexbox e propriedades de posição não. Ao usar Animated.event, ele funcionará apenas com eventos diretos e não com eventos "borbulhantes". Isso significa que ele não funciona com PanResponder, mas funciona com coisas como ScrollView#onScroll.

Quando uma animação está em execução, ela pode impedir que os componentes VirtualizedList renderizem mais linhas. Se você precisar executar uma animação longa ou em loop enquanto o usuário percorre uma lista, você pode usar isInteraction: false na configuração da sua animação para evitar esse problema.

Tenha em mente

Ao usar estilos de transformação, como rotateY, rotateX e outros, certifique-se de que a perspectiva do estilo de transformação esteja em vigor. No momento, algumas animações podem não ser renderizadas no Android sem ele. Exemplo abaixo.

jsx
<Animated.View
+  style={{
+    transform: [
+      {scale: this.state.scale},
+      {rotateY: this.state.rotateY},
+      {perspective: 1000}, // sem esta linha esta animação não será renderizada no Android enquanto funciona bem no iOS
+    ],
+  }}
+/>

Exemplos adicionais

O aplicativo RNTester possui vários exemplos de Animated em uso:

API LayoutAnimation

LayoutAnimation permite configurar globalmente, criar e atualizar animações que serão usadas para todas as visualizações no próximo ciclo de renderização/layout. Isto é útil para fazer atualizações de layout do Flexbox sem se preocupar em medir ou calcular propriedades específicas para animá-las diretamente, e é especialmente útil quando alterações de layout podem afetar ancestrais, por exemplo, uma expansão "veja mais" que também aumenta o tamanho do pai e empurra para baixo a linha abaixo, o que de outra forma exigiria coordenação explícita entre os componentes para animá-los todos em sincronia.

Observe que, embora o LayoutAnimation seja muito poderoso e possa ser bastante útil, ele fornece muito menos controle do que o Animated e outras bibliotecas de animação, portanto, talvez seja necessário usar outra abordagem se não conseguir que o LayoutAnimation faça o que deseja.

Observe que para que isso funcione no Android, você precisa definir os seguintes sinalizadores via UIManager:

java
UIManager.setLayoutAnimationEnabledExperimental(true);
jsx
import React from 'react';
+import {
+  NativeModules,
+  LayoutAnimation,
+  Text,
+  TouchableOpacity,
+  StyleSheet,
+  View,
+} from 'react-native';
+
+const {UIManager} = NativeModules;
+
+UIManager.setLayoutAnimationEnabledExperimental &&
+  UIManager.setLayoutAnimationEnabledExperimental(true);
+
+export default class App extends React.Component {
+  state = {
+    w: 100,
+    h: 100,
+  };
+
+  _onPress = () => {
+    // Animate the update
+    LayoutAnimation.spring();
+    this.setState({w: this.state.w + 15, h: this.state.h + 15});
+  };
+
+  render() {
+    return (
+      <View style={styles.container}>
+        <View
+          style={[styles.box, {width: this.state.w, height: this.state.h}]}
+        />
+        <TouchableOpacity onPress={this._onPress}>
+          <View style={styles.button}>
+            <Text style={styles.buttonText}>Press me!</Text>
+          </View>
+        </TouchableOpacity>
+      </View>
+    );
+  }
+}
+
+const styles = StyleSheet.create({
+  container: {
+    flex: 1,
+    alignItems: 'center',
+    justifyContent: 'center',
+  },
+  box: {
+    width: 200,
+    height: 200,
+    backgroundColor: 'red',
+  },
+  button: {
+    backgroundColor: 'black',
+    paddingHorizontal: 20,
+    paddingVertical: 15,
+    marginTop: 15,
+  },
+  buttonText: {
+    color: '#fff',
+    fontWeight: 'bold',
+  },
+});

image

Este exemplo usa um valor predefinido, você pode personalizar as animações conforme necessário, consulte LayoutAnimation.js para obter mais informações.

Notas Adicionais

requestAnimationFrame

requestAnimationFrame é um polyfill do navegador com o qual você deve estar familiarizado. Ele aceita uma função como seu único argumento e chama essa função antes da próxima repintura. É um elemento essencial para animações que sustenta todas as APIs de animação baseadas em JavaScript. Em geral, você não precisa chamar isso sozinho - as APIs de animação gerenciarão as atualizações de quadros para você.

setNativeProps

Conforme mencionado na seção Manipulação Direta, setNativeProps nos permite modificar propriedades de componentes com suporte nativo (componentes que são realmente apoiados por visualizações nativas, ao contrário dos componentes compostos) diretamente, sem ter que setState renderizar novamente a hierarquia de componentes.

Poderíamos usar isso no exemplo Rebound para atualizar a escala - isso pode ser útil se o componente que estamos atualizando estiver profundamente aninhado e não tiver sido otimizado com shouldComponentUpdate.

Se você encontrar suas animações com queda de quadros (desempenho abaixo de 60 quadros por segundo), use setNativeProps ou shouldComponentUpdate para otimizá-las. Ou você pode executar as animações no thread da UI em vez do thread JavaScript com a opção useNativeDriver. Você também pode adiar qualquer trabalho computacional intensivo até que as animações sejam concluídas, usando o InteractionManager. Você pode monitorar a taxa de quadros usando a ferramenta "FPS Monitor" do menu de desenvolvimento do aplicativo.

+ + + + \ No newline at end of file diff --git a/vitepress/docs/.vitepress/dist/docs/app-extensions.html b/vitepress/docs/.vitepress/dist/docs/app-extensions.html new file mode 100644 index 0000000..1034827 --- /dev/null +++ b/vitepress/docs/.vitepress/dist/docs/app-extensions.html @@ -0,0 +1,27 @@ + + + + + + Extensões de aplicativos | React Native 0.72 + + + + + + + + + + + + + + + + +
Skip to content

Extensões de aplicativos

As extensões de aplicativo permitem fornecer funcionalidade e conteúdo personalizados fora do aplicativo principal. Existem diferentes tipos de extensões de aplicativos no iOS, e todas elas são abordadas no Guia de programação de extensões de aplicativos. Neste guia, abordaremos brevemente como você pode aproveitar as vantagens das extensões de aplicativos no iOS.

Uso de memória em extensões

Como essas extensões são carregadas fora da sandbox normal do aplicativo, é altamente provável que várias dessas extensões de aplicativo sejam carregadas simultaneamente. Como seria de esperar, essas extensões têm pequenos limites de uso de memória. Tenha isso em mente ao desenvolver suas extensões de aplicativo. É sempre altamente recomendável testar seu aplicativo em um dispositivo real, ainda mais ao desenvolver extensões de aplicativo: com muita frequência, os desenvolvedores descobrem que sua extensão funciona bem no simulador iOS, apenas para receber relatórios de usuários de que sua extensão não está carregando em dispositivos reais.

É altamente recomendável que você assista à palestra de Conrad Kramer sobre Uso de memória em extensões para saber mais sobre esse tópico.

Widget Today

O limite de memória de um widget Hoje é de 16 MB. Acontece que as implementações do widget Today usando React Native podem não funcionar de maneira confiável porque o uso de memória tende a ser muito alto. Você pode saber se o widget Today está excedendo o limite de memória se exibir a mensagem 'Não é possível carregar':

image

Sempre teste suas extensões de aplicativo em um dispositivo real, mas esteja ciente de que isso pode não ser suficiente, especialmente ao lidar com o widget Today. As compilações configuradas para depuração têm maior probabilidade de exceder os limites de memória, enquanto as compilações configuradas para versão não falham imediatamente. É altamente recomendável que você use Instrumentos do Xcode para analisar seu uso de memória no mundo real, pois é muito provável que sua compilação configurada para lançamento está muito próxima do limite de 16 MB. Em situações como essas, você pode ultrapassar rapidamente o limite de 16 MB executando operações comuns, como buscar dados de uma API.

Para experimentar os limites das implementações do widget React Native Today, tente estender o projeto de exemplo em react-native-today-widget.

Outras extensões de aplicativos

Outros tipos de extensões de aplicativo têm limites de memória maiores que o widget Today. Por exemplo, as extensões de teclado personalizado são limitadas a 48 MB e as extensões de compartilhamento são limitadas a 120 MB. Implementar essas extensões de aplicativo com React Native é mais viável. Um exemplo de prova de conceito é react-native-ios-share-extension.

+ + + + \ No newline at end of file diff --git a/vitepress/docs/.vitepress/dist/docs/build-speed.html b/vitepress/docs/.vitepress/dist/docs/build-speed.html new file mode 100644 index 0000000..970787f --- /dev/null +++ b/vitepress/docs/.vitepress/dist/docs/build-speed.html @@ -0,0 +1,79 @@ + + + + + + Acelerando sua fase de construção | React Native 0.72 + + + + + + + + + + + + + + + + +
Skip to content

Acelerando sua fase de construção

Construir seu aplicativo React Native pode ser caro e levar vários minutos do tempo dos desenvolvedores. Isso pode ser problemático à medida que seu projeto cresce e geralmente em organizações maiores com vários desenvolvedores React Native.

Para mitigar esse impacto no desempenho, esta página compartilha algumas sugestões sobre como melhorar o tempo de construção.

INFORMAÇÕES

Se você notar um tempo de construção mais lento com a nova arquitetura no Android, recomendamos atualizar para o React Native 0.71

Crie apenas uma ABI durante o desenvolvimento (somente Android)

Ao construir seu aplicativo Android localmente, por padrão você constrói todas as 4 interfaces binárias de aplicativo (ABIs): armeabi-v7a, arm64-v8a, x86 e x86_64.

No entanto, você provavelmente não precisará compilar todos eles se estiver compilando localmente e testando seu emulador ou em um dispositivo físico.

Isso deve reduzir o tempo de construção nativo em um fator de aproximadamente 75%.

Se estiver usando o React Native CLI, você pode adicionar o sinalizador --active-arch-only ao comando run-Android. Este sinalizador garantirá que a ABI correta seja obtida no emulador em execução ou no telefone conectado. Para confirmar se essa abordagem está funcionando bem, você verá uma mensagem como info Detected Architectures arm64-v8a no console.

bash
$ yarn react-native run-android --active-arch-only
+
+[ ... ]
+info Running jetifier to migrate libraries to AndroidX. You can disable it using "--no-jetifier" flag.
+Jetifier found 1037 file(s) to forward-jetify. Using 32 workers...
+info JS server already running.
+info Detected architectures arm64-v8a
+info Installing the app...

Este mecanismo depende da propriedade reactNativeArchitectures do Gradle.

Portanto, se você estiver compilando diretamente com o Gradle na linha de comando e sem a CLI, poderá especificar a ABI que deseja compilar da seguinte maneira:

bash
$ ./gradlew :app:assembleDebug -PreactNativeArchitectures=x86,x86_64

Isso pode ser útil se você deseja construir seu aplicativo Android em um CI e usar uma matriz para paralelizar a construção das diferentes arquiteturas.

Se desejar, você também pode substituir esse valor localmente, usando o arquivo gradle.properties que você possui na pasta de nível superior do seu projeto:

bash
# Use esta propriedade para especificar qual arquitetura você deseja construir.
+# Você também pode substituí-lo na CLI usando
+# ./gradlew <task> -PreactNativeArchitectures=x86_64
+reactNativeArchitectures=armeabi-v7a,arm64-v8a,x86,x86_64

Depois de criar uma versão de lançamento do seu aplicativo, não se esqueça de remover esses sinalizadores, pois deseja criar um pacote apk/app que funcione para todas as ABIs e não apenas para aquela que você está usando em seu fluxo de trabalho de desenvolvimento diário.

Use um cache do compilador

Se você estiver executando compilações nativas frequentes (C++ ou Objective-C), poderá se beneficiar do uso de um cache do compilador.

Especificamente, você pode usar dois tipos de caches: caches de compilador local e caches de compilador distribuídos.

Caches locais

INFORMAÇÕES

As instruções a seguir funcionarão para Android e iOS. Se você estiver criando apenas aplicativos Android, você deve estar pronto. Se você também estiver criando aplicativos iOS, siga as instruções na seção Configuração específica do XCode abaixo.

Sugerimos usar o ccache para armazenar em cache a compilação de suas compilações nativas. O Ccache funciona agrupando os compiladores C++, armazenando os resultados da compilação e ignorando a compilação se um resultado intermediário da compilação tiver sido originalmente armazenado.

Para instalá-lo, você pode seguir as instruções oficiais de instalação.

No macOS, podemos instalar o ccache com brew install ccache. Depois de instalado, você pode configurá-lo da seguinte maneira para armazenar em cache os resultados da compilação do NDK:

bash
ln -s $(which ccache) /usr/local/bin/gcc
+ln -s $(which ccache) /usr/local/bin/g++
+ln -s $(which ccache) /usr/local/bin/cc
+ln -s $(which ccache) /usr/local/bin/c++
+ln -s $(which ccache) /usr/local/bin/clang
+ln -s $(which ccache) /usr/local/bin/clang++

Isso criará links simbólicos para o ccache dentro do /usr/local/bin/ que são chamados de gcc, g++ e assim por diante.

Isso funciona desde que /usr/local/bin/ venha primeiro que /usr/bin/ dentro de sua variável $PATH, que é o padrão.

Você pode verificar se funciona usando o comando which:

bash
$ which gcc
+/usr/local/bin/gcc

Se o resultado for /usr/local/bin/gcc, então você está efetivamente chamando o ccache, que agrupará as chamadas do gcc.

CUIDADO

Observe que esta configuração do ccache afetará todas as compilações que você está executando em sua máquina, não apenas aquelas relacionadas ao React Native. Use-o por sua conta e risco. Se você não conseguir instalar/compilar outro software, esse pode ser o motivo. Se for esse o caso, você pode remover o link simbólico criado com:

bash
unlink /usr/local/bin/gcc
+unlink /usr/local/bin/g++
+unlink /usr/local/bin/cc
+unlink /usr/local/bin/c++
+unlink /usr/local/bin/clang
+unlink /usr/local/bin/clang++

para reverter sua máquina ao status original e usar os compiladores padrão.

Você pode então fazer duas compilações limpas (por exemplo, no Android você pode primeiro executar o yarn react-native run-android, excluir a pasta android/app/build e executar o primeiro comando mais uma vez). Você notará que a segunda compilação foi muito mais rápida que a primeira (deve levar segundos em vez de minutos). Durante a construção, você pode verificar se o ccache funciona corretamente e verificar a taxa de acertos/erros do cache ccache -s

bash
$ ccache -s
+Summary:
+  Hits:             196 /  3068 (6.39 %)
+    Direct:           0 /  3068 (0.00 %)
+    Preprocessed:   196 /  3068 (6.39 %)
+  Misses:          2872
+    Direct:        3068
+    Preprocessed:  2872
+  Uncacheable:        1
+Primary storage:
+  Hits:             196 /  6136 (3.19 %)
+  Misses:          5940
+  Cache size (GB): 0.60 / 20.00 (3.00 %)

Observe que o ccache agrega as estatísticas de todas as compilações. Você pode usar ccache --zero-stats para redefini-los antes de uma compilação para verificar a taxa de acertos do cache.

Se precisar limpar seu cache, você pode fazer isso com ccache --clear

Configuração específica do XCode

Para garantir que o ccache funcione corretamente com iOS e XCode, você precisa seguir algumas etapas extras:

  1. Você deve alterar a forma como o Xcode e o xcodebuild chamam o comando do compilador. Por padrão eles usam caminhos totalmente especificados para os binários do compilador, portanto os links simbólicos instalados em /usr/local/bin não serão usados. Você pode configurar o Xcode para usar nomes relativos para os compiladores usando qualquer uma destas duas opções:
  • Variáveis de ambiente prefixadas na linha de comando se você usar uma linha de comando direta: CLANG=clang CLANGPLUSPLUS=clang++ LD=clang LDPLUSPLUS=clang++ xcodebuild <resto da linha de comando do xcodebuild>
  • Uma seção post_install em seu ios/Podfile que altera o compilador em seu espaço de trabalho Xcode durante a etapa de instalação do pod:
  post_install do |installer|
+    react_native_post_install(installer)
+
+    # ...possibly other post_install items here
+
+    installer.pods_project.targets.each do |target|
+      target.build_configurations.each do |config|
+        # Using the un-qualified names means you can swap in different implementations, for example ccache
+        config.build_settings["CC"] = "clang"
+        config.build_settings["LD"] = "clang"
+        config.build_settings["CXX"] = "clang++"
+        config.build_settings["LDPLUSPLUS"] = "clang++"
+      end
+    end
+
+    __apply_Xcode_12_5_M1_post_install_workaround(installer)
+  end
  1. Você precisa de uma configuração de ccache que permita um certo nível de negligência e comportamento de cache, de modo que o ccache registre ocorrências de cache durante as compilações do Xcode. As variáveis de configuração do ccache que são diferentes do padrão são as seguintes se configuradas pela variável de ambiente:
bash
export CCACHE_SLOPPINESS=clang_index_store,file_stat_matches,include_file_ctime,include_file_mtime,ivfsoverlay,pch_defines,modules,system_headers,time_macros
+export CCACHE_FILECLONE=true
+export CCACHE_DEPEND=true
+export CCACHE_INODECACHE=true

O mesmo pode ser configurado em um arquivo ccache.conf ou qualquer outro mecanismo fornecido pelo ccache. Mais sobre isso pode ser encontrado no manual oficial do ccache.

Usando esta abordagem em um IC

Ccache usa a pasta /Users/$USER/Library/Caches/ccache no macOS para armazenar o cache. Portanto, você pode salvar e restaurar a pasta correspondente também no CI para acelerar suas compilações.

No entanto, há algumas coisas que você deve estar ciente:

  1. No CI, recomendamos fazer uma compilação totalmente limpa, para evitar problemas de cache envenenado. Se você seguir a abordagem mencionada no parágrafo anterior, poderá paralelizar a construção nativa em 4 ABIs diferentes e provavelmente não precisará do ccache no CI.

  2. O ccache depende de carimbos de data/hora para calcular uma ocorrência no cache. Isso não funciona bem no CI, pois os arquivos são baixados novamente a cada execução do CI. Para superar isso, você precisará usar a opção de conteúdo compiler_check, que depende do hash do conteúdo do arquivo.

Caches distribuídos

Semelhante aos caches locais, você pode considerar o uso de um cache distribuído para suas compilações nativas. Isso pode ser especificamente útil em organizações maiores que fazem compilações nativas frequentes.

Recomendamos usar sccache para conseguir isso. Seguimos o início rápido da compilação distribuída do sccache para obter instruções sobre como configurar e usar esta ferramenta.

+ + + + \ No newline at end of file diff --git a/vitepress/docs/.vitepress/dist/docs/building-for-tv.html b/vitepress/docs/.vitepress/dist/docs/building-for-tv.html new file mode 100644 index 0000000..959873c --- /dev/null +++ b/vitepress/docs/.vitepress/dist/docs/building-for-tv.html @@ -0,0 +1,117 @@ + + + + + + Construção para dispositivos de TV | React Native 0.72 + + + + + + + + + + + + + + + + +
Skip to content

Construção para dispositivos de TV

O suporte a dispositivos de TV foi implementado com a intenção de fazer com que os aplicativos React Native existentes funcionem na Apple TV e Android TV, com poucas ou nenhuma alteração necessária no código JavaScript dos aplicativos.

Android TV

Mudanças de compilação

  • Camada nativa: para executar o projeto React Native na Android TV, certifique-se de fazer as seguintes alterações em AndroidManifest.xml:
xml
  <!-- Adicione uma imagem de banner personalizada para exibir como ícone do iniciador do Android TV -->
+ <application
+  ...
+  android:banner="@drawable/tv_banner"
+  >
+    ...
+    <intent-filter>
+      ...
+      <!-- Necessário para criar corretamente uma intenção de lançamento ao executar no Android TV -->
+      <category android:name="android.intent.category.LEANBACK_LAUNCHER"/>
+    </intent-filter>
+    ...
+  </application>
  • Camada JavaScript: suporte para Android TV foi adicionado a Platform.android.js. Você pode verificar se o código está sendo executado na Android TV fazendo:
jsx
const Platform = require('Platform');
+const running_on_android_tv = Platform.isTV;

Mudanças de código

  • Acesso a controles touchs: ao executar no Android TV, a estrutura do Android aplicará automaticamente um esquema de navegação direcional com base na posição relativa dos elementos focáveis em suas visualizações. O mixin Touchable tem código adicionado para detectar mudanças de foco e usar métodos existentes para estilizar os componentes corretamente e iniciar as ações adequadas quando a visualização é selecionada usando o controle remoto da TV, então TouchableWithoutFeedback, TouchableHighlight, TouchableOpacity e TouchableNativeFeedback funcionarão conforme esperado. Em particular:

    • onFocus será executado quando a visualização tocável entrar em foco
    • onBlur será executado quando a visualização tocável ficar fora de foco
    • onPress será executado quando a visualização tocável for realmente selecionada pressionando o botão "selecionar" no controle remoto da TV.
  • Entrada de controle remoto/teclado de TV: uma nova classe nativa, ReactAndroidTVRootViewHelper, configura manipuladores de eventos importantes para eventos remotos de TV. Quando ocorrem eventos remotos de TV, esta classe dispara um evento JS. Este evento será captado por instâncias do objeto JavaScript TVEventHandler. O código do aplicativo que precisa implementar o tratamento personalizado de eventos remotos de TV pode criar uma instância de TVEventHandler e escutar esses eventos, como no código a seguir:

js
const TVEventHandler = require('TVEventHandler');
+
+class Game2048 extends React.Component {
+  _tvEventHandler: any;
+
+  _enableTVEventHandler() {
+    this._tvEventHandler = new TVEventHandler();
+    this._tvEventHandler.enable(this, function (cmp, evt) {
+      if (evt && evt.eventType === 'right') {
+        cmp.setState({board: cmp.state.board.move(2)});
+      } else if (evt && evt.eventType === 'up') {
+        cmp.setState({board: cmp.state.board.move(1)});
+      } else if (evt && evt.eventType === 'left') {
+        cmp.setState({board: cmp.state.board.move(0)});
+      } else if (evt && evt.eventType === 'down') {
+        cmp.setState({board: cmp.state.board.move(3)});
+      } else if (evt && evt.eventType === 'playPause') {
+        cmp.restartGame();
+      }
+    });
+  }
+
+  _disableTVEventHandler() {
+    if (this._tvEventHandler) {
+      this._tvEventHandler.disable();
+      delete this._tvEventHandler;
+    }
+  }
+
+  componentDidMount() {
+    this._enableTVEventHandler();
+  }
+
+  componentWillUnmount() {
+    this._disableTVEventHandler();
+  }
+}
  • Suporte ao Dev Menu: No emulador, cmd-M abrirá o Dev Menu, semelhante ao Android. Para acessá-lo em um dispositivo Android TV real, pressione o botão de menu ou pressione longamente o botão de avanço rápido no controle remoto. (Por favor, não agite o dispositivo Android TV, isso não funcionará 😃)

Problemas conhecidos:

  • Os componentes TextInput não funcionam por enquanto (ou seja, eles não podem receber o foco automaticamente, veja este comentário).
    • No entanto, é possível usar um ref para acionar manualmente inputRef.current.focus().
    • Você pode agrupar sua entrada dentro de um componente TouchableWithoutFeedback e acionar o foco no evento onFocus desse touch. Isto permite abrir o teclado através das teclas de seta.
    • O teclado pode redefinir seu estado após cada pressionamento de tecla (isso só pode acontecer dentro do emulador do Android TV).
  • O conteúdo dos componentes Modal não pode receber foco, consulte este comentário para obter detalhes.

tvOS

Descontinuado

Em vez disso, use react-native-tvos. Para obter detalhes, verifique a postagem do blog da versão 0.62.

Alterações de compilação

  • Camada nativa: todos os projetos React Native Xcode agora têm alvos de construção da Apple TV, com nomes terminando na string '-tvOS'.
  • react-native init: Novos projetos React Native criados com react-native init terão o destino Apple TV criado automaticamente em seus projetos XCode.
  • Camada JavaScript: suporte para Apple TV foi adicionado a Platform.ios.js. Você pode verificar se o código está sendo executado na AppleTV fazendo
js
const Platform = require('Platform');
+const running_on_tv = Platform.isTV;
+
+// Se você quiser ser mais específico e detectar apenas dispositivos rodando tvOS
+// (mas sem dispositivos Android TV) você pode usar:
+const running_on_apple_tv = Platform.isTVOS;

Mudanças de código

  • Suporte geral para tvOS: alterações específicas da Apple TV no código nativo são todas agrupadas pela definição TARGET_OS_TV. Isso inclui alterações para suprimir APIs que não são suportadas no tvOS (por exemplo, visualizações da web, controles deslizantes, interruptores, barra de status, etc.) e alterações para oferecer suporte à entrada do usuário a partir do controle remoto ou teclado da TV.

  • Base de código comum: como tvOS e iOS compartilham a maior parte do código Objective-C e JavaScript em comum, a maior parte da documentação para iOS se aplica igualmente ao tvOS.

  • Acesso a controles touch: Ao executar no Apple TV, a classe de visualização nativa é RCTTVView, que possui métodos adicionais para fazer uso do mecanismo de foco tvOS. O mixin Touchable tem código adicionado para detectar mudanças de foco e usar métodos existentes para estilizar os componentes corretamente e iniciar as ações adequadas quando a visualização é selecionada usando o controle remoto da TV, então TouchableWithoutFeedback, TouchableHighlight e TouchableOpacity funcionarão conforme esperado. Em particular:

    • onFocus será executado quando a visualização tocável entrar em foco
    • onBlur será executado quando a visualização tocável ficar fora de foco
    • onPress será executado quando a visualização tocável for realmente selecionada pressionando o botão "selecionar" no controle remoto da TV.
  • Entrada de controle remoto/teclado de TV: uma nova classe nativa, RCTTVRemoteHandler, configura reconhecedores de gestos para eventos remotos de TV. Quando ocorrem eventos remotos de TV, esta classe dispara notificações que são captadas por RCTTVNavigationEventEmitter (uma subclasse de RCTEventEmitter), que dispara um evento JS. Este evento será captado por instâncias do objeto JavaScript TVEventHandler. O código do aplicativo que precisa implementar o tratamento personalizado de eventos remotos de TV pode criar uma instância de TVEventHandler e escutar esses eventos, como no código a seguir:

js
const TVEventHandler = require('TVEventHandler');
+
+class Game2048 extends React.Component {
+  _tvEventHandler: any;
+
+  _enableTVEventHandler() {
+    this._tvEventHandler = new TVEventHandler();
+    this._tvEventHandler.enable(this, function (cmp, evt) {
+      if (evt && evt.eventType === 'right') {
+        cmp.setState({board: cmp.state.board.move(2)});
+      } else if (evt && evt.eventType === 'up') {
+        cmp.setState({board: cmp.state.board.move(1)});
+      } else if (evt && evt.eventType === 'left') {
+        cmp.setState({board: cmp.state.board.move(0)});
+      } else if (evt && evt.eventType === 'down') {
+        cmp.setState({board: cmp.state.board.move(3)});
+      } else if (evt && evt.eventType === 'playPause') {
+        cmp.restartGame();
+      }
+    });
+  }
+
+  _disableTVEventHandler() {
+    if (this._tvEventHandler) {
+      this._tvEventHandler.disable();
+      delete this._tvEventHandler;
+    }
+  }
+
+  componentDidMount() {
+    this._enableTVEventHandler();
+  }
+
+  componentWillUnmount() {
+    this._disableTVEventHandler();
+  }
+}
  • Suporte ao Dev Menu: No simulador, cmd-D abrirá o Dev Menu, semelhante ao iOS. Para acessá-lo em um dispositivo Apple TV real, pressione longamente o botão reproduzir/pausar no controle remoto. (Por favor, não agite o dispositivo Apple TV, isso não funcionará 😃)

  • Animações remotas de TV: o código nativo RCTTVView implementa animações de paralaxe recomendadas pela Apple para ajudar a guiar o olho enquanto o usuário navega pelas visualizações. As animações podem ser desativadas ou ajustadas com novas propriedades de visualização opcionais.

  • Navegação de retorno com o botão de menu do controle remoto da TV: o componente BackHandler, originalmente escrito para oferecer suporte ao botão de retorno do Android, agora também oferece suporte à navegação de retorno na Apple TV usando o botão de menu no controle remoto da TV.

  • Comportamento do TabBarIOS: o componente TabBarIOS envolve a API UITabBar nativa, que funciona de maneira diferente no Apple TV. Para evitar a nova renderização instável da barra de guias no tvOS (consulte esta issue), o item selecionado da barra de guias só pode ser definido a partir de JavaScript na renderização inicial e é controlado depois disso pelo usuário por meio de código nativo.

Problemas conhecidos

  • Rolagem ListView: O problema pode ser contornado definindo removeClippedSubviews como false em ListView e componentes semelhantes. Para mais discussão sobre este assunto, consulte este PR.
+ + + + \ No newline at end of file diff --git a/vitepress/docs/.vitepress/dist/docs/colors.html b/vitepress/docs/.vitepress/dist/docs/colors.html new file mode 100644 index 0000000..b3e4c7c --- /dev/null +++ b/vitepress/docs/.vitepress/dist/docs/colors.html @@ -0,0 +1,27 @@ + + + + + + Referência de Cores | React Native 0.72 + + + + + + + + + + + + + + + + +
Skip to content

Referência de Cores

Os componentes do React Native são estilizados usando JavaScript. As propriedades de cores geralmente correspondem ao modo como o CSS funciona na web. Guias gerais sobre o uso de cores em cada plataforma podem ser encontrados abaixo:

APIs de cores

React Native possui diversas APIs de cores projetadas para permitir que você aproveite ao máximo o design da sua plataforma e as preferências do usuário.

  • PlatformColor permite fazer referência ao sistema de cores da plataforma.
  • DynamicColorIOS é específico para iOS e permite especificar quais cores devem ser usadas no modo claro ou escuro.

Representações de cores

Vermelho Verde Azul (RGB)

React Native suporta rgb() e rgba() em notação hexadecimal e funcional:

  • '#f0f' (#rgb)
  • '#ff00ff' (#rrggbb)
  • '#f0ff' (#rgba)
  • '#ff00ff00' (#rrggbbaa)
  • 'rgb(255, 0, 255)'
  • 'rgb(255 0 255)'
  • 'rgb(255, 0, 255, 1,0)'
  • 'rgba(255 0 255/1,0)'

Tonalidade Saturação Iluminação (HSL)

React Native suporta hsl() e hsla() em notação funcional:

  • 'hsl(360, 100%, 100%)'
  • 'hsl(360 100% 100%)'
  • 'hsla(360, 100%, 100%, 1,0)'
  • 'hsla(360 100% 100% / 1,0)'

Matiz Brancura Escuridão (HWB)

React Native suporta hwb() em notação funcional:

  • 'hwb(0, 0%, 100%)'
  • 'hwb(360, 100%, 100%)'
  • 'hwb(0 0% 0%)'
  • 'hwb(70 50% 0%)'

Informações de cor

React Native também suporta cores como valores int (no modo de cores RGB):

  • 0xff00ff00 (0xrrggbbaa)

CUIDADO

Isso pode parecer semelhante à representação de cores do Android, mas no Android os valores são armazenados no modo de cores SRGB (0xaarrggbb).

Cores nomeadas

No React Native você também pode usar strings de nomes de cores como valores.

INFORMAÇÕES

React Native suporta apenas nomes de cores em minúsculas. Nomes de cores em letras maiúsculas não são suportados.

transparent

Este é um atalho para rgba(0,0,0,0), igual ao CSS3.

Palavras-chave das cores

A implementação de cores nomeadas segue a especificação CSS3/SVG

  • aliceblue (#f0f8ff)
  • antiquewhite (#faebd7)
  • aqua (#00ffff)
  • aquamarine (#7fffd4)
  • azure (#f0ffff)
  • beige (#f5f5dc)
  • bisque (#ffe4c4)
  • black (#000000)
  • blanchedalmond (#ffebcd)
  • blue (#0000ff)
  • blueviolet (#8a2be2)
  • brown (#a52a2a)
  • burlywood (#deb887)
  • cadetblue (#5f9ea0)
  • chartreuse (#7fff00)
  • chocolate (#d2691e)
  • coral (#ff7f50)
  • cornflowerblue (#6495ed)
  • cornsilk (#fff8dc)
  • crimson (#dc143c)
  • cyan (#00ffff)
  • darkblue (#00008b)
  • darkcyan (#008b8b)
  • darkgoldenrod (#b8860b)
  • darkgray (#a9a9a9)
  • darkgreen (#006400)
  • darkgrey (#a9a9a9)
  • darkkhaki (#bdb76b)
  • darkmagenta (#8b008b)
  • darkolivegreen (#556b2f)
  • darkorange (#ff8c00)
  • darkorchid (#9932cc)
  • darkred (#8b0000)
  • darksalmon (#e9967a)
  • darkseagreen (#8fbc8f)
  • darkslateblue (#483d8b)
  • darkslategrey (#2f4f4f)
  • darkturquoise (#00ced1)
  • darkviolet (#9400d3)
  • deeppink (#ff1493)
  • deepskyblue (#00bfff)
  • dimgray (#696969)
  • dimgrey (#696969)
  • dodgerblue (#1e90ff)
  • firebrick (#b22222)
  • floralwhite (#fffaf0)
  • forestgreen (#228b22)
  • fuchsia (#ff00ff)
  • gainsboro (#dcdcdc)
  • ghostwhite (#f8f8ff)
  • gold (#ffd700)
  • goldenrod (#daa520)
  • gray (#808080)
  • green (#008000)
  • greenyellow (#adff2f)
  • grey (#808080)
  • honeydew (#f0fff0)
  • hotpink (#ff69b4)
  • indianred (#cd5c5c)
  • indigo (#4b0082)
  • ivory (#fffff0)
  • khaki (#f0e68c)
  • lavender (#e6e6fa)
  • lavenderblush (#fff0f5)
  • lawngreen (#7cfc00)
  • lemonchiffon (#fffacd)
  • lightblue (#add8e6)
  • lightcoral (#f08080)
  • lightcyan (#e0ffff)
  • lightgoldenrodyellow (#fafad2)
  • lightgray (#d3d3d3)
  • lightgreen (#90ee90)
  • lightgrey (#d3d3d3)
  • lightpink (#ffb6c1)
  • lightsalmon (#ffa07a)
  • lightseagreen (#20b2aa)
  • lightskyblue (#87cefa)
  • lightslategrey (#778899)
  • lightsteelblue (#b0c4de)
  • lightyellow (#ffffe0)
  • lime (#00ff00)
  • limegreen (#32cd32)
  • linen (#faf0e6)
  • magenta (#ff00ff)
  • maroon (#800000)
  • mediumaquamarine (#66cdaa)
  • mediumblue (#0000cd)
  • mediumorchid (#ba55d3)
  • mediumpurple (#9370db)
  • mediumseagreen (#3cb371)
  • mediumslateblue (#7b68ee)
  • mediumspringgreen (#00fa9a)
  • mediumturquoise (#48d1cc)
  • mediumvioletred (#c71585)
  • midnightblue (#191970)
  • mintcream (#f5fffa)
  • mistyrose (#ffe4e1)
  • moccasin (#ffe4b5)
  • navajowhite (#ffdead)
  • navy (#000080)
  • oldlace (#fdf5e6)
  • olive (#808000)
  • olivedrab (#6b8e23)
  • orange (#ffa500)
  • orangered (#ff4500)
  • orchid (#da70d6)
  • palegoldenrod (#eee8aa)
  • palegreen (#98fb98)
  • paleturquoise (#afeeee)
  • palevioletred (#db7093)
  • papayawhip (#ffefd5)
  • peachpuff (#ffdab9)
  • peru (#cd853f)
  • pink (#ffc0cb)
  • plum (#dda0dd)
  • powderblue (#b0e0e6)
  • purple (#800080)
  • rebeccapurple (#663399)
  • red (#ff0000)
  • rosybrown (#bc8f8f)
  • royalblue (#4169e1)
  • saddlebrown (#8b4513)
  • salmon (#fa8072)
  • sandybrown (#f4a460)
  • seagreen (#2e8b57)
  • seashell (#fff5ee)
  • sienna (#a0522d)
  • silver (#c0c0c0)
  • skyblue (#87ceeb)
  • slateblue (#6a5acd)
  • slategray (#708090)
  • snow (#fffafa)
  • springgreen (#00ff7f)
  • steelblue (#4682b4)
  • tan (#d2b48c)
  • teal (#008080)
  • thistle (#d8bfd8)
  • tomato (#ff6347)
  • turquoise (#40e0d0)
  • violet (#ee82ee)
  • wheat (#f5deb3)
  • white (#ffffff)
  • whitesmoke (#f5f5f5)
  • yellow (#ffff00)
  • yellowgreen (#9acd32)
+ + + + \ No newline at end of file diff --git a/vitepress/docs/.vitepress/dist/docs/communication-android.html b/vitepress/docs/.vitepress/dist/docs/communication-android.html new file mode 100644 index 0000000..8237a62 --- /dev/null +++ b/vitepress/docs/.vitepress/dist/docs/communication-android.html @@ -0,0 +1,71 @@ + + + + + + Comunicação entre nativo e React Native | React Native 0.72 + + + + + + + + + + + + + + + + +
Skip to content

Comunicação entre nativo e React Native

Em Guia de integração com aplicativos existentes e Guia de componentes de UI nativos aprendemos como incorporar o React Native em um componente nativo e vice-versa. Quando misturamos componentes nativos e React Native, eventualmente encontraremos a necessidade de comunicação entre esses dois mundos. Algumas maneiras de conseguir isso já foram mencionadas em outros guias. Este artigo resume as técnicas disponíveis.

Introdução

O React Native é inspirado no React, então a ideia básica do fluxo de informações é semelhante. O fluxo no React é unidirecional. Mantemos uma hierarquia de componentes, na qual cada componente depende apenas de seu pai e de seu próprio estado interno. Fazemos isso com propriedades: os dados são passados ​​de um pai para seus filhos de cima para baixo. Se um componente ancestral depende do estado de seu descendente, deve-se transmitir um retorno de chamada a ser usado pelo descendente para atualizar o ancestral.

O mesmo conceito se aplica ao React Native. Contanto que estejamos construindo nosso aplicativo exclusivamente dentro da estrutura, podemos direcioná-lo com propriedades e retornos de chamada. Mas, quando misturamos componentes React Native e nativos, precisamos de alguns mecanismos específicos entre linguagens que nos permitam passar informações entre eles.

Propriedades

As propriedades são a forma mais direta de comunicação entre componentes. Portanto, precisamos de uma maneira de passar propriedades tanto de nativo para React Native quanto de React Native para nativo.

Passando propriedades de Native para React Native

Você pode passar propriedades para o aplicativo React Native fornecendo uma implementação personalizada de ReactActivityDelegate em sua atividade principal. Esta implementação deve substituir getLaunchOptions para retornar um Bundle com as propriedades desejadas.

java
public class MainActivity extends ReactActivity {
+  @Override
+  protected ReactActivityDelegate createReactActivityDelegate() {
+    return new ReactActivityDelegate(this, getMainComponentName()) {
+      @Override
+      protected Bundle getLaunchOptions() {
+        Bundle initialProperties = new Bundle();
+        ArrayList<String> imageList = new ArrayList<String>(Arrays.asList(
+                "https://dummyimage.com/600x400/ffffff/000000.png",
+                "https://dummyimage.com/600x400/000000/ffffff.png"
+        ));
+        initialProperties.putStringArrayList("images", imageList);
+        return initialProperties;
+      }
+    };
+  }
+}
kotlin
class MainActivity : ReactActivity() {
+    override fun createReactActivityDelegate(): ReactActivityDelegate {
+        return object : ReactActivityDelegate(this, mainComponentName) {
+            override fun getLaunchOptions(): Bundle {
+                val imageList = arrayListOf("https://dummyimage.com/600x400/ffffff/000000.png", "https://dummyimage.com/600x400/000000/ffffff.png")
+                val initialProperties = Bundle().apply { putStringArrayList("images", imageList) }
+                return initialProperties
+            }
+        }
+    }
+}
tsx
import React from 'react';
+import {View, Image} from 'react-native';
+
+export default class ImageBrowserApp extends React.Component {
+  renderImage(imgURI) {
+    return <Image source={{uri: imgURI}} />;
+  }
+  render() {
+    return <View>{this.props.images.map(this.renderImage)}</View>;
+  }
+}

ReactRootView fornece uma propriedade de leitura e gravação appProperties. Depois que appProperties for definido, o aplicativo React Native será renderizado novamente com novas propriedades. A atualização só é realizada quando as novas propriedades atualizadas diferem das anteriores.

java
Bundle updatedProps = mReactRootView.getAppProperties();
+ArrayList<String> imageList = new ArrayList<String>(Arrays.asList(
+        "https://dummyimage.com/600x400/ff0000/000000.png",
+        "https://dummyimage.com/600x400/ffffff/ff0000.png"
+));
+updatedProps.putStringArrayList("images", imageList);
+
+mReactRootView.setAppProperties(updatedProps);
kotlin
var updatedProps: Bundle = reactRootView.getAppProperties()
+var imageList = arrayListOf("https://dummyimage.com/600x400/ff0000/000000.png", "https://dummyimage.com/600x400/ffffff/ff0000.png")

Não há problema em atualizar propriedades a qualquer momento. No entanto, as atualizações devem ser realizadas no thread principal. Você usa o getter em qualquer thread.

Não há como atualizar apenas algumas propriedades por vez. Sugerimos que você o crie em seu próprio wrapper.

Nota

Atualmente, a função JS componentWillUpdateProps do componente RN de nível superior não será chamada após uma atualização de prop. No entanto, você pode acessar os novos adereços na função componentDidMount.

Passando propriedades do React Native para Native

O problema de exposição de propriedades de componentes nativos é abordado em detalhes neste artigo. Resumindo, as propriedades que devem ser refletidas em JavaScript precisam ser expostas como um método setter anotado com @ReactProp e, em seguida, usá-las no React Native como se o componente fosse um componente React Native comum.

Limites de propriedades

A principal desvantagem das propriedades entre linguagens é que elas não suportam retornos de chamada, o que nos permitiria lidar com ligações de dados de baixo para cima. Imagine que você tem uma pequena visualização RN que deseja remover da visualização pai nativa como resultado de uma ação JS. Não há como fazer isso com adereços, pois as informações precisariam ir de baixo para cima.

Embora tenhamos uma variedade de retornos de chamada entre linguagens (descritos aqui), esses retornos de chamada nem sempre são o que precisamos. O principal problema é que eles não devem ser passados ​​como propriedades. Em vez disso, esse mecanismo nos permite acionar uma ação nativa de JS e manipular o resultado dessa ação em JS.

Outras formas de interação entre idiomas (eventos e módulos nativos)

Conforme declarado no capítulo anterior, o uso de propriedades apresenta algumas limitações. Às vezes, as propriedades não são suficientes para conduzir a lógica do nosso aplicativo e precisamos de uma solução que dê mais flexibilidade. Este capítulo cobre outras técnicas de comunicação disponíveis no React Native. Eles podem ser usados ​​para comunicação interna (entre JS e camadas nativas no RN), bem como para comunicação externa (entre RN e a parte 'nativa pura' do seu aplicativo).

React Native permite que você execute chamadas de função em vários idiomas. Você pode executar código nativo personalizado de JS e vice-versa. Infelizmente, dependendo do lado em que trabalhamos, alcançamos o mesmo objetivo de maneiras diferentes. Para nativo - usamos mecanismo de eventos para agendar a execução de uma função manipuladora em JS, enquanto para React Native chamamos diretamente métodos exportados por módulos nativos.

Chamando funções React Native a partir de nativos (eventos)

Os eventos são descritos em detalhes neste artigo. Observe que o uso de eventos não nos dá garantias sobre o tempo de execução, pois o evento é tratado em um thread separado.

Os eventos são poderosos porque nos permitem alterar os componentes do React Native sem precisar de uma referência a eles. No entanto, existem algumas armadilhas nas quais você pode cair ao usá-los:

  • Como os eventos podem ser enviados de qualquer lugar, eles podem introduzir dependências do tipo espaguete em seu projeto.
  • Os eventos compartilham namespace, o que significa que você pode encontrar algumas colisões de nomes. As colisões não serão detectadas estaticamente, o que as torna difíceis de depurar.
  • Se você usar várias instâncias do mesmo componente React Native e quiser distingui-las da perspectiva do seu evento, provavelmente precisará introduzir identificadores e passá-los junto com os eventos (você pode usar o reactTag da visualização nativa como um identificador).

Chamando funções nativas do React Native (módulos nativos)

Módulos nativos são classes Java/Kotlin disponíveis em JS. Normalmente, uma instância de cada módulo é criada por ponte JS. Eles podem exportar funções e constantes arbitrárias para React Native. Eles foram abordados em detalhes neste artigo.

Aviso

Todos os módulos nativos compartilham o mesmo namespace. Cuidado com colisões de nomes ao criar novos.

+ + + + \ No newline at end of file diff --git a/vitepress/docs/.vitepress/dist/docs/communication-ios.html b/vitepress/docs/.vitepress/dist/docs/communication-ios.html new file mode 100644 index 0000000..637b5ff --- /dev/null +++ b/vitepress/docs/.vitepress/dist/docs/communication-ios.html @@ -0,0 +1,80 @@ + + + + + + Comunicação entre nativo e React Native | React Native 0.72 + + + + + + + + + + + + + + + + +
Skip to content

Comunicação entre nativo e React Native

Em [Guia de integração com aplicativos existentes](integração com aplicativos existentes) e Guia de componentes de UI nativos aprendemos como incorporar o React Native em um componente nativo e vice-versa. Quando misturamos componentes nativos e React Native, eventualmente encontraremos a necessidade de comunicação entre esses dois mundos. Algumas maneiras de conseguir isso já foram mencionadas em outros guias. Este artigo resume as técnicas disponíveis.

Introdução

O React Native é inspirado no React, então a ideia básica do fluxo de informações é semelhante. O fluxo no React é unidirecional. Mantemos uma hierarquia de componentes, na qual cada componente depende apenas de seu pai e de seu próprio estado interno. Fazemos isso com propriedades: os dados são passados ​​de um pai para seus filhos de cima para baixo. Se um componente ancestral depende do estado de seu descendente, deve-se transmitir um retorno de chamada a ser usado pelo descendente para atualizar o ancestral.

O mesmo conceito se aplica ao React Native. Contanto que estejamos construindo nosso aplicativo exclusivamente dentro da estrutura, podemos direcioná-lo com propriedades e retornos de chamada. Mas, quando misturamos componentes React Native e nativos, precisamos de alguns mecanismos específicos entre linguagens que nos permitam passar informações entre eles.

Propriedades

As propriedades são a forma mais direta de comunicação entre componentes. Portanto, precisamos de uma maneira de passar propriedades tanto de nativo para React Native quanto de React Native para nativo.

Passando propriedades de Native para React Native

Para incorporar uma visualização React Native em um componente nativo, usamos RCTRootView. RCTRootView é um UIView que contém um aplicativo React Native. Ele também fornece uma interface entre o lado nativo e o aplicativo hospedado.

RCTRootView possui um inicializador que permite passar propriedades arbitrárias para o aplicativo React Native. O parâmetro initialProperties deve ser uma instância de NSDictionary. O dicionário é convertido internamente em um objeto JSON que o componente JS de nível superior pode referenciar.

objective-c
NSArray *imageList = @[@"https://dummyimage.com/600x400/ffffff/000000.png",
+                       @"https://dummyimage.com/600x400/000000/ffffff.png"];
+
+NSDictionary *props = @{@"images" : imageList};
+
+RCTRootView *rootView = [[RCTRootView alloc] initWithBridge:bridge
+                                                 moduleName:@"ImageBrowserApp"
+                                          initialProperties:props];
tsx
import React from 'react';
+import {View, Image} from 'react-native';
+
+export default class ImageBrowserApp extends React.Component {
+  renderImage(imgURI) {
+    return <Image source={{uri: imgURI}} />;
+  }
+  render() {
+    return <View>{this.props.images.map(this.renderImage)}</View>;
+  }
+}

RCTRootView também fornece uma propriedade de leitura e gravação appProperties. Depois que appProperties for definido, o aplicativo React Native será renderizado novamente com novas propriedades. A atualização só é realizada quando as novas propriedades atualizadas diferem das anteriores.

objective-c
NSArray *imageList = @[@"https://dummyimage.com/600x400/ff0000/000000.png",
+                       @"https://dummyimage.com/600x400/ffffff/ff0000.png"];
+
+rootView.appProperties = @{@"images" : imageList};

Não há problema em atualizar propriedades a qualquer momento. No entanto, as atualizações devem ser realizadas no thread principal. Você usa o getter em qualquer thread.

Observação

Atualmente, há um problema conhecido em que, ao definir appProperties durante a inicialização da ponte, a alteração pode ser perdida. Consulte https://github.com/facebook/react-native/issues/20115 para obter mais informações.

Não há como atualizar apenas algumas propriedades por vez. Sugerimos que você o crie em seu próprio wrapper.

Passando propriedades do React Native para Native

O problema de exposição de propriedades de componentes nativos é abordado em detalhes neste artigo. Resumindo, exporte propriedades com a macro RCT_CUSTOM_VIEW_PROPERTY em seu componente nativo personalizado e, em seguida, use-as no React Native como se o componente fosse um componente React Native comum.

Limites de propriedades

A principal desvantagem das propriedades entre linguagens é que elas não suportam retornos de chamada, o que nos permitiria lidar com ligações de dados de baixo para cima. Imagine que você tem uma pequena visualização RN que deseja remover da visualização pai nativa como resultado de uma ação JS. Não há como fazer isso com adereços, pois as informações precisariam ir de baixo para cima.

Embora tenhamos uma variedade de retornos de chamada entre idiomas (descritos aqui), esses retornos de chamada nem sempre são o que precisamos. O principal problema é que eles não devem ser passados ​​como propriedades. Em vez disso, esse mecanismo nos permite acionar uma ação nativa de JS e manipular o resultado dessa ação em JS.

Outras formas de interação entre linguagens (eventos e módulos nativos)

Conforme declarado no capítulo anterior, o uso de propriedades apresenta algumas limitações. Às vezes, as propriedades não são suficientes para conduzir a lógica do nosso aplicativo e precisamos de uma solução que dê mais flexibilidade. Este capítulo cobre outras técnicas de comunicação disponíveis no React Native. Eles podem ser usados ​​para comunicação interna (entre JS e camadas nativas no RN), bem como para comunicação externa (entre RN e a parte 'nativa pura' do seu aplicativo).

React Native permite que você execute chamadas de função em vários idiomas. Você pode executar código nativo personalizado de JS e vice-versa. Infelizmente, dependendo do lado em que trabalhamos, alcançamos o mesmo objetivo de maneiras diferentes. Para nativo - usamos mecanismo de eventos para agendar a execução de uma função manipuladora em JS, enquanto para React Native chamamos diretamente métodos exportados por módulos nativos.

Chamando funções React Native a partir de nativos (eventos)

Os eventos são descritos detalhadamente neste artigo. Observe que o uso de eventos não nos dá garantias sobre o tempo de execução, pois o evento é tratado em um thread separado.

Os eventos são poderosos porque nos permitem alterar os componentes do React Native sem precisar de uma referência a eles. No entanto, existem algumas armadilhas nas quais você pode cair ao usá-los:

  • Como os eventos podem ser enviados de qualquer lugar, eles podem introduzir dependências do tipo espaguete em seu projeto.
  • Os eventos compartilham namespace, o que significa que você pode encontrar algumas colisões de nomes. As colisões não serão detectadas estaticamente, o que as torna difíceis de depurar.
  • Se você usar várias instâncias do mesmo componente React Native e quiser distingui-las da perspectiva do seu evento, provavelmente precisará introduzir identificadores e passá-los junto com os eventos (você pode usar o reactTag da visualização nativa como um identificador).

O padrão comum que usamos ao incorporar nativo no React Native é tornar o RCTViewManager do componente nativo um delegado para as visualizações, enviando eventos de volta ao JavaScript por meio da ponte. Isso mantém as chamadas de eventos relacionadas em um só lugar.

Chamando funções nativas do React Native (módulos nativos)

Módulos nativos são classes Objective-C disponíveis em JS. Normalmente, uma instância de cada módulo é criada por ponte JS. Eles podem exportar funções e constantes arbitrárias para React Native. Eles foram abordados em detalhes neste artigo.

O fato de os módulos nativos serem singletons limita o mecanismo no contexto de incorporação. Digamos que temos um componente React Native incorporado em uma visualização nativa e queremos atualizar a visualização pai nativa. Usando o mecanismo de módulo nativo, exportaríamos uma função que não apenas recebe os argumentos esperados, mas também um identificador da visão nativa pai. O identificador seria usado para recuperar uma referência à visualização pai a ser atualizada. Dito isto, precisaríamos manter um mapeamento dos identificadores para as visualizações nativas no módulo.

Embora esta solução seja complexa, ela é usada em RCTUIManager, que é uma classe interna do React Native que gerencia todas as visualizações do React Native.

Módulos nativos também podem ser usados ​​para expor bibliotecas nativas existentes ao JS. A biblioteca de geolocalização é um exemplo vivo da ideia.

Cuidado

Todos os módulos nativos compartilham o mesmo namespace. Cuidado com colisões de nomes ao criar novos.

Fluxo de cálculo de layout

Ao integrar o nativo e o React Native, também precisamos de uma maneira de consolidar dois sistemas de layout diferentes. Esta seção aborda problemas comuns de layout e fornece uma breve descrição dos mecanismos para resolvê-los.

Layout de um componente nativo incorporado no React Native

Este caso é abordado neste artigo. Para resumir, como todas as nossas visualizações de react nativas são subclasses de UIView, a maioria dos atributos de estilo e tamanho funcionarão como você esperaria imediatamente.

Layout de um componente React Native incorporado no nativo

React Native com tamanho fixo

O cenário geral é quando temos um aplicativo React Native com tamanho fixo, que é conhecido pelo lado nativo. Em particular, uma visualização React Native em tela inteira se enquadra neste caso. Se quisermos uma visualização raiz menor, podemos definir explicitamente o quadro do RTRRootView.

Por exemplo, para criar um aplicativo RN com 200 pixels (lógicos) de altura e largura da visualização de hospedagem ampla, poderíamos fazer:

objective-c
- (void)viewDidLoad
+{
+  [...]
+  RCTRootView *rootView = [[RCTRootView alloc] initWithBridge:bridge
+                                                   moduleName:appName
+                                            initialProperties:props];
+  rootView.frame = CGRectMake(0, 0, self.view.width, 200);
+  [self.view addSubview:rootView];
+}

Quando temos uma visualização raiz de tamanho fixo, precisamos respeitar seus limites no lado JS. Em outras palavras, precisamos garantir que o conteúdo do React Native possa estar contido na visualização raiz de tamanho fixo. A maneira mais fácil de garantir isso é usar o layout Flexbox. Se você usar posicionamento absoluto e os componentes do React estiverem visíveis fora dos limites da visualização raiz, você obterá sobreposição com visualizações nativas, fazendo com que alguns recursos se comportem de forma inesperada. Por exemplo, 'TouchableHighlight' não destacará seus toques fora dos limites da visualização raiz.

Não há problema em atualizar dinamicamente o tamanho da visualização raiz, redefinindo sua propriedade de quadro. React Native cuidará do layout do conteúdo.

React Native com tamanho flexível

Em alguns casos, gostaríamos de renderizar conteúdo de tamanho inicialmente desconhecido. Digamos que o tamanho será definido dinamicamente em JS. Temos duas soluções para este problema.

  1. Você pode agrupar sua visualização React Native em um componente ScrollView. Isso garante que seu conteúdo estará sempre disponível e não se sobreporá às visualizações nativas.
  2. React Native permite determinar, em JS, o tamanho do aplicativo RN e fornecê-lo ao proprietário da hospedagem RCTRootView. O proprietário é então responsável por reorganizar as subvisualizações e manter a IU consistente. Conseguimos isso com os modos de flexibilidade do RCTRootView.

RCTRootView suporta 4 modos de flexibilidade de tamanhos diferentes:

objective-c
typedef NS_ENUM(NSInteger, RCTRootViewSizeFlexibility) {
+  RCTRootViewSizeFlexibilityNone = 0,
+  RCTRootViewSizeFlexibilityWidth,
+  RCTRootViewSizeFlexibilityHeight,
+  RCTRootViewSizeFlexibilityWidthAndHeight,
+};

RCTRootViewSizeFlexibilityNone é o valor padrão, o que torna fixo o tamanho da visualização raiz (mas ainda pode ser atualizado com setFrame:). Os outros três modos nos permitem rastrear as atualizações de tamanho do conteúdo do React Native. Por exemplo, definir o modo como RCTRootViewSizeFlexibilityHeight fará com que o React Native meça a altura do conteúdo e passe essa informação de volta ao delegado de RCTRootView. Uma ação arbitrária pode ser executada dentro do delegado, incluindo a configuração do quadro da visualização raiz, para que o conteúdo se ajuste. O delegado é chamado somente quando o tamanho do conteúdo é alterado.

Cuidado

Tornar uma dimensão flexível em JS e nativo leva a um comportamento indefinido. Por exemplo - não torne flexível a largura de um componente React de nível superior (com flexbox) enquanto estiver usando RCTRootViewSizeFlexibilityWidth na hospedagem RCTRootView.

Vejamos um exemplo.

objective-c
- (instancetype)initWithFrame:(CGRect)frame
+{
+  [...]
+
+  _rootView = [[RCTRootView alloc] initWithBridge:bridge
+  moduleName:@"FlexibilityExampleApp"
+  initialProperties:@{}];
+
+  _rootView.delegate = self;
+  _rootView.sizeFlexibility = RCTRootViewSizeFlexibilityHeight;
+  _rootView.frame = CGRectMake(0, 0, self.frame.size.width, 0);
+}
+
+#pragma mark - RCTRootViewDelegate
+- (void)rootViewDidChangeIntrinsicSize:(RCTRootView *)rootView
+{
+  CGRect newFrame = rootView.frame;
+  newFrame.size = rootView.intrinsicContentSize;
+
+  rootView.frame = newFrame;
+}

No exemplo, temos uma visualização FlexibleSizeExampleView que contém uma visualização raiz. Criamos a visualização raiz, inicializamos e definimos o delegado. O delegado cuidará das atualizações de tamanho. Em seguida, definimos a flexibilidade de tamanho da visualização raiz para RCTRootViewSizeFlexibilityHeight, o que significa que o método rootViewDidChangeIntrinsicSize: será chamado toda vez que o conteúdo do React Native mudar sua altura. Finalmente, definimos a largura e a posição da visualização raiz. Observe que definimos a altura também, mas isso não tem efeito, pois tornamos a altura dependente de RN.

Você pode verificar o código-fonte completo do exemplo aqui.

Não há problema em alterar dinamicamente o modo de flexibilidade de tamanho da visualização raiz. Alterar o modo de flexibilidade de uma visualização raiz agendará um recálculo do layout e o método delegado rootViewDidChangeIntrinsicSize: será chamado assim que o tamanho do conteúdo for conhecido.

Observação

O cálculo do layout do React Native é executado em um thread separado, enquanto as atualizações da visualização da UI nativa são feitas no thread principal. Isso pode causar inconsistências temporárias na interface do usuário entre o nativo e o React Native. Este é um problema conhecido e nossa equipe está trabalhando na sincronização de atualizações de IU provenientes de diferentes fontes.

Observação

O React Native não executa nenhum cálculo de layout até que a visualização raiz se torne uma subvisão de algumas outras visualizações. Se você deseja ocultar a visualização React Native até que suas dimensões sejam conhecidas, adicione a visualização raiz como uma subvisualização e torne-a inicialmente oculta (use a propriedade hidden de UIView). Em seguida, altere sua visibilidade no método delegado.

+ + + + \ No newline at end of file diff --git a/vitepress/docs/.vitepress/dist/docs/debugging.html b/vitepress/docs/.vitepress/dist/docs/debugging.html new file mode 100644 index 0000000..7d7ca1a --- /dev/null +++ b/vitepress/docs/.vitepress/dist/docs/debugging.html @@ -0,0 +1,33 @@ + + + + + + Noções básicas de depuração | React Native 0.72 + + + + + + + + + + + + + + + + +
Skip to content

Noções básicas de depuração

Acessando o menu de desenvolvimento

React Native fornece um menu de desenvolvedor no aplicativo que oferece várias opções de depuração. Você pode acessar o Menu Dev agitando seu dispositivo ou por meio de atalhos de teclado:

  • Simulador iOS: Cmd ⌘ + D (ou Dispositivo > Agitar)
  • Emuladores Android: Cmd ⌘ + M (macOS) ou Ctrl + M (Windows e Linux)

Alternativamente, para dispositivos e emuladores Android, você pode executar adb shell input keyevent 82 em seu terminal.

image

OBSERVAÇÃO

O menu Dev está desabilitado em compilações de lançamento (produção).

LogBox

Erros e avisos em builds de desenvolvimento são exibidos no LogBox dentro do seu aplicativo.

OBSERVAÇÃO

LogBox está desabilitado em compilações de lançamento (produção).

Erros e avisos do console

Os erros e avisos do console são exibidos como notificações na tela com um emblema vermelho ou amarelo e o número de erros ou avisos no console, respectivamente. Para visualizar um erro ou avisos do console, toque na notificação para visualizar as informações em tela cheia sobre o log e para paginar todos os logs no console.

Essas notificações podem ser ocultadas usando LogBox.ignoreAllLogs(). Isso é útil ao fazer demonstrações de produtos, por exemplo. Além disso, as notificações podem ser ocultadas por log por meio de LogBox.ignoreLogs(). Isto é útil quando há um aviso frequente que não pode ser corrigido, como aqueles em uma dependência de terceiros.

INFORMAÇÕES

Ignore os logs como último recurso e crie uma tarefa para corrigir quaisquer logs que sejam ignorados.

jsx
import {LogBox} from 'react-native';
+
+// Ignorar notificação de log por mensagem:
+LogBox.ignoreLogs(['Warning: ...']);
+
+// Ignore todas as notificações de log:
+LogBox.ignoreAllLogs();

Erros não tratados

Erros de JavaScript não tratados, marcado como undefined is not a function, abrirão automaticamente um erro LogBox em tela inteira com a origem do erro. Esses erros são dispensáveis e minimizáveis para que você possa ver o estado do seu aplicativo quando esses erros ocorrem, mas sempre devem ser resolvidos.

Erros de sintaxe

Quando ocorre um erro de sintaxe, o erro LogBox em tela cheia será aberto automaticamente com o rastreamento de pilha e a localização do erro de sintaxe. Este erro não pode ser descartado porque representa uma execução inválida de JavaScript que deve ser corrigida antes de continuar com seu aplicativo. Para descartar esses erros, corrija o erro de sintaxe e salve para descartar automaticamente (com Atualização Rápida habilitada) ou Cmd ⌘/Ctrl + R para recarregar (com Atualização Rápida desabilitada).

Ferramentas para desenvolvedores do Chrome

Para depurar o código JavaScript no Chrome, selecione "Open Debugger" no menu Dev. Isso abrirá uma nova guia em http://localhost:8081/debugger-ui.

A partir daqui, selecione More Tools → Developer Tools no menu do Chrome para abrir o Chrome DevTools. Alternativamente, você pode usar o atalho ⌥ Option + Cmd ⌘ + I (macOS) / Ctrl + Shift + I (Windows e Linux).

  • Se você é novo no Chrome DevTools, recomendamos aprender sobre as guias Console e Fontes nos documentos.
  • Você pode querer habilitar Pause on Caught Exceptions para uma melhor experiência de depuração.

INFORMAÇÕES

A extensão React Developer Tools Chrome não funciona com React Native, mas você pode usar sua versão independente. Leia esta seção para saber como.

DICA

No Android, se os tempos entre o depurador e o dispositivo variarem, coisas como animações e comportamento de eventos poderão não funcionar corretamente. Isso pode ser corrigido executando adb shell "date date +%m%d%H%M%Y.%S%3N". O acesso root é necessário se estiver usando um dispositivo físico.

Depuração em um dispositivo físico

Informações

Se você estiver usando Expo CLI, isso já está configurado para você.

Android

Em dispositivos Android 5.0+ conectados via USB, você pode usar a ferramenta de linha de comando adb para configurar o encaminhamento de porta do dispositivo para o seu computador:

bash
adb reverse tcp:8081 tcp:8081

Como alternativa, selecione “Configurações” no menu Dev e atualize a configuração “Host do servidor de depuração para dispositivo” para corresponder ao endereço IP do seu computador.

iOS

Em dispositivos iOS, abra o arquivo RCTWebSocketExecutor.mm e altere "localhost" para o endereço IP do seu computador e selecione "Debug JS Remotely" no menu Dev.

Observação

Se você tiver algum problema, pode ser que uma de suas extensões do Chrome esteja interagindo de maneira inesperada com o depurador. Tente desabilitar todas as suas extensões e reativá-las uma por uma até encontrar a extensão problemática.

Avançado: depuração usando um depurador JavaScript personalizado

Para usar um depurador JavaScript personalizado no lugar das Ferramentas de desenvolvedor do Chrome, defina a variável de ambiente REACT_DEBUGGER como um comando que iniciará seu depurador personalizado. Você pode então selecionar "Open Debugger" no menu Dev para iniciar a depuração.

O depurador receberá uma lista de todas as raízes do projeto, separadas por um espaço. Por exemplo, se você definir REACT_DEBUGGER="node /path/to/launchDebugger.js --port 2345 --type ReactNative", então o comando node /path/to/launchDebugger.js --port 2345 --type ReactNative /path/to/reactNative/app será usado para iniciar seu depurador.

Observação

Os comandos do depurador personalizado executados dessa maneira devem ser processos de curta duração e não devem produzir mais de 200 kilobytes de saída.

Ferramentas para desenvolvedores Safari

Você pode usar o Safari para depurar a versão iOS do seu aplicativo sem precisar ativar "Depurar JS remotamente".

  • Em um dispositivo físico, vá para: Settings → Safari → Advanced → Make sure "Web Inspector" is turned on (esta etapa não é necessária no Simulador)
  • No seu Mac, ative o menu Desenvolver no Safari: Settings... (or Preferences...) → Advanced → Select "Show Develop menu in menu bar"
  • Selecione o JSContext do seu aplicativo: Develop → Simulator (or other device) → JSContext
  • O Web Inspector do Safari deve abrir, contendo um console e um depurador

Embora os mapas de origem possam não estar habilitados por padrão, você pode seguir este guia ou vídeo para habilitá-los e definir pontos de interrupção nos locais certos no código-fonte.

No entanto, sempre que o aplicativo é recarregado (usando recarregamento ao vivo ou recarregando manualmente), um novo JSContext é criado. Escolher "Mostrar automaticamente inspetores da Web para JSContexts" evita que você tenha que selecionar manualmente o JSContext mais recente.

Monitor de desempenho

Você pode ativar uma sobreposição de desempenho para ajudá-lo a depurar problemas de desempenho selecionando "Perf Monitor" no menu Dev.

+ + + + \ No newline at end of file diff --git a/vitepress/docs/.vitepress/dist/docs/direct-manipulation.html b/vitepress/docs/.vitepress/dist/docs/direct-manipulation.html new file mode 100644 index 0000000..7a0c265 --- /dev/null +++ b/vitepress/docs/.vitepress/dist/docs/direct-manipulation.html @@ -0,0 +1,290 @@ + + + + + + Manipulação Direta | React Native 0.72 + + + + + + + + + + + + + + + + +
Skip to content

Manipulação Direta

Às vezes é necessário fazer alterações diretamente em um componente sem usar state/props para acionar uma nova renderização de toda a subárvore. Ao usar React no navegador, por exemplo, às vezes você precisa modificar diretamente um nó DOM, e o mesmo se aplica a visualizações em aplicativos móveis. setNativeProps é o equivalente React Native para definir propriedades diretamente em um nó DOM.

ATENÇÃO

Use setNativeProps quando a nova renderização frequentemente criar um gargalo de desempenho!

A manipulação direta não será uma ferramenta que você utiliza com frequência. Normalmente, você o usará apenas para criar animações contínuas para evitar a sobrecarga de renderizar a hierarquia de componentes e reconciliar muitas visualizações.

setNativeProps é imperativo e armazena o estado na camada nativa (DOM, UIView, etc.) e não nos componentes do React, o que torna seu código mais difícil de compreender.

Antes de usá-lo, tente resolver seu problema com setState e shouldComponentUpdate.

setNativeProps com TouchableOpacity

TouchableOpacity usa setNativeProps internamente para atualizar a opacidade de seu filho componente:

tsx
const viewRef = useRef<View>();
+const setOpacityTo = useCallback(value => {
+  // Redigido: código relacionado à animação
+  viewRef.current.setNativeProps({
+    opacity: value,
+  });
+}, []);

Isso nos permite escrever o código a seguir e saber que a criança terá sua opacidade atualizada em resposta aos toques, sem que a criança tenha conhecimento desse fato ou exija quaisquer alterações em sua implementação:

tsx
<TouchableOpacity onPress={handlePress}>
+  <View>
+    <Text>Press me!</Text>
+  </View>
+</TouchableOpacity>

Vamos imaginar que setNativeProps não estava disponível. Uma maneira de implementá-lo com essa restrição é armazenar o valor de opacidade no estado e, em seguida, atualizar esse valor sempre que onPress for acionado:

tsx
const [buttonOpacity, setButtonOpacity] = useState(1);
+return (
+  <TouchableOpacity
+    onPressIn={() => setButtonOpacity(0.5)}
+    onPressOut={() => setButtonOpacity(1)}>
+    <View style={{opacity: buttonOpacity}}>
+      <Text>Press me!</Text>
+    </View>
+  </TouchableOpacity>
+);

Isso é computacionalmente intensivo em comparação com o exemplo original - o React precisa renderizar novamente a hierarquia de componentes cada vez que a opacidade muda, mesmo que outras propriedades da visualização e de seus filhos não tenham mudado. Normalmente, essa sobrecarga não é uma preocupação, mas ao executar animações contínuas e responder a gestos, otimizar criteriosamente seus componentes pode melhorar a fidelidade de suas animações.

Se você observar a implementação de setNativeProps em NativeMethodsMixin, você notará que é um wrapper em torno de RCTUIManager.updateView - esta é exatamente a mesma chamada de função que resulta da nova renderização - consulte [receiveComponent in ReactNativeBaseComponent](https://github.com/facebook/react-native /blob/fb2ec1ea47c53c2e7b873acb1cb46192ac74274e/Libraries/Renderer/oss/ReactNativeRenderer-prod.js#L5793-L5813).

Componentes compostos e setNativeProps

Os componentes compostos não são apoiados por uma visualização nativa, portanto você não pode chamar setNativeProps neles. Considere este exemplo:

jsx
import React from 'react';
+import {Text, TouchableOpacity, View} from 'react-native';
+
+const MyButton = props => (
+  <View style={{marginTop: 50}}>
+    <Text>{props.label}</Text>
+  </View>
+);
+
+const App = () => (
+  <TouchableOpacity>
+    <MyButton label="Press me!" />
+  </TouchableOpacity>
+);
+
+export default App;
tsx
import React from 'react';
+import {Text, TouchableOpacity, View} from 'react-native';
+
+const MyButton = (props: {label: string}) => (
+  <View style={{marginTop: 50}}>
+    <Text>{props.label}</Text>
+  </View>
+);
+
+const App = () => (
+  <TouchableOpacity>
+    <MyButton label="Press me!" />
+  </TouchableOpacity>
+);
+
+export default App;

Se você executar isso, verá imediatamente este erro: "Touchable child must either be native or forward setNativeProps to a native component" (O filho tocável deve ser nativo ou encaminhar setNativeProps para um componente nativo. Isso ocorre porque MyButton não é apoiado diretamente por uma visualização nativa cuja opacidade deve ser definida. Você pode pensar assim: se você definir um componente com createReactClass você não esperaria ser capaz de definir um suporte de estilo nele e fazer isso funcionar - você precisaria passar o suporte de estilo para um filho, a menos que você esteja agrupando um componente nativo. Da mesma forma, encaminharemos setNativeProps para um componente filho com suporte nativo.

Encaminha setNativeProps para um filho

Como o método setNativeProps existe em qualquer referência a um componente View, é suficiente encaminhar uma referência em seu componente personalizado para um dos componentes <View /> que ele renderiza. Isso significa que uma chamada para setNativeProps no componente personalizado terá o mesmo efeito como se você chamasse setNativeProps no próprio componente View encapsulado.

js
import React from 'react';
+import {Text, TouchableOpacity, View} from 'react-native';
+
+const MyButton = React.forwardRef((props, ref) => (
+  <View {...props} ref={ref} style={{marginTop: 50}}>
+    <Text>{props.label}</Text>
+  </View>
+));
+
+const App = () => (
+  <TouchableOpacity>
+    <MyButton label="Press me!" />
+  </TouchableOpacity>
+);
+
+export default App;
tsx
import React from 'react';
+import {Text, TouchableOpacity, View} from 'react-native';
+
+const MyButton = React.forwardRef<View, {label: string}>((props, ref) => (
+  <View {...props} ref={ref} style={{marginTop: 50}}>
+    <Text>{props.label}</Text>
+  </View>
+));
+
+const App = () => (
+  <TouchableOpacity>
+    <MyButton label="Press me!" />
+  </TouchableOpacity>
+);
+
+export default App;

Agora você pode usar MyButton dentro de TouchableOpacity!

Você deve ter notado que passamos todos os adereços para a visualização filha usando {...props}. A razão para isso é que TouchableOpacity é na verdade um componente composto e, portanto, além de depender de setNativeProps em seu filho, também requer que o filho execute o tratamento de toque. Para fazer isso, ele passa vários adereços que chamam de volta para o componente TouchableOpacity. TouchableHighlight, por outro lado, é apoiado por uma visão nativa e requer apenas que implementemos setNativeProps.

setNativeProps para editar o valor TextInput

Outro caso de uso muito comum de setNativeProps é editar o valor do TextInput. A propriedade controlled do TextInput às vezes pode descartar caracteres quando o bufferDelay está baixo e o usuário digita muito rapidamente. Alguns desenvolvedores preferem ignorar totalmente esta propriedade e, em vez disso, usar setNativeProps para manipular diretamente o valor TextInput quando necessário. Por exemplo, o código a seguir demonstra a edição da entrada quando você toca em um botão:

jsx
import React from 'react';
+import {useCallback, useRef} from 'react';
+import {
+  StyleSheet,
+  TextInput,
+  Text,
+  TouchableOpacity,
+  View,
+} from 'react-native';
+
+const App = () => {
+  const inputRef = useRef(null);
+  const editText = useCallback(() => {
+    inputRef.current.setNativeProps({text: 'Edited Text'});
+  }, []);
+
+  return (
+    <View style={styles.container}>
+      <TextInput ref={inputRef} style={styles.input} />
+      <TouchableOpacity onPress={editText}>
+        <Text>Edit text</Text>
+      </TouchableOpacity>
+    </View>
+  );
+};
+
+const styles = StyleSheet.create({
+  container: {
+    flex: 1,
+    alignItems: 'center',
+    justifyContent: 'center',
+  },
+  input: {
+    height: 50,
+    width: 200,
+    marginHorizontal: 20,
+    borderWidth: 1,
+    borderColor: '#ccc',
+  },
+});
+
+export default App;
tsx
import React from 'react';
+import {useCallback, useRef} from 'react';
+import {
+  StyleSheet,
+  TextInput,
+  Text,
+  TouchableOpacity,
+  View,
+} from 'react-native';
+
+const App = () => {
+  const inputRef = useRef<TextInput>(null);
+  const editText = useCallback(() => {
+    inputRef.current?.setNativeProps({text: 'Edited Text'});
+  }, []);
+
+  return (
+    <View style={styles.container}>
+      <TextInput ref={inputRef} style={styles.input} />
+      <TouchableOpacity onPress={editText}>
+        <Text>Edit text</Text>
+      </TouchableOpacity>
+    </View>
+  );
+};
+
+const styles = StyleSheet.create({
+  container: {
+    flex: 1,
+    alignItems: 'center',
+    justifyContent: 'center',
+  },
+  input: {
+    height: 50,
+    width: 200,
+    marginHorizontal: 20,
+    borderWidth: 1,
+    borderColor: '#ccc',
+  },
+});
+
+export default App;

Você pode usar o método clear para limpar o TextInput que limpa o texto de entrada atual usando a mesma abordagem.

Evitando conflitos com a função render

Se você atualizar uma propriedade que também é gerenciada pela função de renderização, poderá acabar com alguns bugs imprevisíveis e confusos porque sempre que o componente for renderizado novamente e essa propriedade mudar, qualquer valor que tenha sido definido anteriormente em setNativeProps será completamente ignorado e substituído.

setNativeProps e shouldComponentUpdate

Ao aplicar de forma inteligente shouldComponentUpdate, você pode evitar a sobrecarga desnecessária envolvida na reconciliação de subárvores de componentes inalteradas a ponto de ter um desempenho suficiente, basta usar setState em vez de setNativeProps.

Outros métodos nativos

Os métodos descritos aqui estão disponíveis na maioria dos componentes padrão fornecidos pelo React Native. Observe, entretanto, que eles não estão disponíveis em componentes compostos que não sejam diretamente apoiados por uma visualização nativa. Geralmente, isso incluirá a maioria dos componentes definidos em seu próprio aplicativo.

measure(callback)

Determina a localização na tela, largura e altura na janela de visualização da view fornecida e retorna os valores por meio de um retorno de chamada assíncrono. Se for bem-sucedido, o retorno de chamada será chamado com os seguintes argumentos:

  • x
  • y
  • width
  • height
  • pageX
  • pageY

Observe que essas medidas não estarão disponíveis até que a renderização seja concluída no modo nativo. Se você precisar das medidas o mais rápido possível e não precisar de pageX e pageY, considere usar a propriedade onLayout.

Além disso, a largura e a altura retornadas por measure() são a largura e a altura do componente na janela de visualização. Se você precisar do tamanho real do componente, considere usar a propriedade onLayout.

measureInWindow(callback)

Determina a localização da visualização fornecida na janela e retorna os valores por meio de um retorno de chamada assíncrono. Se a visualização raiz do React estiver incorporada em outra visualização nativa, isso fornecerá as coordenadas absolutas. Se for bem-sucedido, o retorno de chamada será chamado com os seguintes argumentos:

  • x
  • y
  • width
  • height

measureLayout(relativeToNativeComponentRef, onSuccess, onFail)

Como measure(), mas mede a visualização relativa a um ancestral, especificado com a referência relativeToNativeComponentRef. Isso significa que as coordenadas retornadas são relativas à origem x, y da visão ancestral.

Observação

Este método também pode ser chamado com um manipulador relativeToNativeNode (em vez de referência), mas esta variante está obsoleta.

jsx
import React, {useEffect, useRef, useState} from 'react';
+import {Text, View, StyleSheet} from 'react-native';
+
+const App = () => {
+  const textContainerRef = useRef(null);
+  const textRef = useRef(null);
+  const [measure, setMeasure] = useState(null);
+
+  useEffect(() => {
+    if (textRef.current && textContainerRef.current) {
+      textRef.current.measureLayout(
+        textContainerRef.current,
+        (left, top, width, height) => {
+          setMeasure({left, top, width, height});
+        },
+      );
+    }
+  }, [measure]);
+
+  return (
+    <View style={styles.container}>
+      <View ref={textContainerRef} style={styles.textContainer}>
+        <Text ref={textRef}>Where am I? (relative to the text container)</Text>
+      </View>
+      <Text style={styles.measure}>{JSON.stringify(measure)}</Text>
+    </View>
+  );
+};
+
+const styles = StyleSheet.create({
+  container: {
+    flex: 1,
+    justifyContent: 'center',
+  },
+  textContainer: {
+    backgroundColor: '#61dafb',
+    justifyContent: 'center',
+    alignItems: 'center',
+    padding: 12,
+  },
+  measure: {
+    textAlign: 'center',
+    padding: 12,
+  },
+});
+
+export default App;
tsx
import React, {useEffect, useRef, useState} from 'react';
+import {Text, View, StyleSheet} from 'react-native';
+
+type Measurements = {
+  left: number;
+  top: number;
+  width: number;
+  height: number;
+};
+
+const App = () => {
+  const textContainerRef = useRef<View>(null);
+  const textRef = useRef<Text>(null);
+  const [measure, setMeasure] = useState<Measurements | null>(null);
+
+  useEffect(() => {
+    if (textRef.current && textContainerRef.current) {
+      textRef.current?.measureLayout(
+        textContainerRef.current,
+        (left, top, width, height) => {
+          setMeasure({left, top, width, height});
+        },
+        () => {
+          console.error('measurement failed');
+        },
+      );
+    }
+  }, [measure]);
+
+  return (
+    <View style={styles.container}>
+      <View ref={textContainerRef} style={styles.textContainer}>
+        <Text ref={textRef}>Where am I? (relative to the text container)</Text>
+      </View>
+      <Text style={styles.measure}>{JSON.stringify(measure)}</Text>
+    </View>
+  );
+};
+
+const styles = StyleSheet.create({
+  container: {
+    flex: 1,
+    justifyContent: 'center',
+  },
+  textContainer: {
+    backgroundColor: '#61dafb',
+    justifyContent: 'center',
+    alignItems: 'center',
+    padding: 12,
+  },
+  measure: {
+    textAlign: 'center',
+    padding: 12,
+  },
+});
+
+export default App;

focus()

Solicita foco para a entrada ou visualização fornecida. O comportamento exato acionado dependerá da plataforma e do tipo de visualização.

blur()

Remove o foco de uma entrada ou visualização. Este é o oposto de focus().

+ + + + \ No newline at end of file diff --git a/vitepress/docs/.vitepress/dist/docs/environment-setup.html b/vitepress/docs/.vitepress/dist/docs/environment-setup.html new file mode 100644 index 0000000..9742395 --- /dev/null +++ b/vitepress/docs/.vitepress/dist/docs/environment-setup.html @@ -0,0 +1,33 @@ + + + + + + Configurando o ambiente de desenvolvimento | React Native 0.72 + + + + + + + + + + + + + + + + +
Skip to content

Configurando o ambiente de desenvolvimento

Esta página te ajudará a instalar e construir seu primeiro aplicativo React Native.

Se você é novo no desenvolvimento móvel, a maneira mais fácil de começar é com o Expo Go. Expo é um conjunto de ferramentas e serviços construídos em torno do React Native e, embora tenha muitos recursos, o recurso mais relevante para nós no momento é que você pode escrever um aplicativo React Native em minutos. Você só precisará de uma versão recente do Node.js e de um telefone ou emulador. Se quiser experimentar o React Native diretamente em seu navegador antes de instalar qualquer ferramenta, você pode experimentar o Snack.

Se você já está familiarizado com o desenvolvimento móvel, você pode querer usar o React Native CLI. Requer Xcode ou Android Studio para começar. Se você já tiver uma dessas ferramentas instalada, poderá colocá-la em funcionamento em alguns minutos. Se eles não estiverem instalados, você deverá gastar cerca de uma hora instalando-os e configurando-os.

Expo Go Início Rápido

Execute o seguinte comando para criar um novo projeto React Native chamado "AwesomeProject":

bash
npx create-expo-app AwesomeProject
+
+cd AwesomeProject
+npx expo start
bash
yarn create expo-app AwesomeProject
+
+cd AwesomeProject
+yarn expo start

Isso iniciará um servidor de desenvolvimento para você.

Executando seu aplicativo React Native

Instale o aplicativo Expo Go em seu telefone iOS ou Android e conecte-se à mesma rede sem fio do seu computador. No Android, use o aplicativo Expo Go para escanear o código QR do seu terminal para abrir seu projeto. No iOS, use o leitor de código QR integrado do aplicativo iOS Camera padrão.

React Native CLI Início Rápido

Siga estas instruções se precisar criar código nativo em seu projeto. Por exemplo, se você estiver integrando o React Native em um aplicativo existente ou se executou o "prebuild" do Expo para gerar o código nativo do seu projeto, você precisará desta seção.

As instruções são um pouco diferentes dependendo do seu sistema operacional de desenvolvimento e se você deseja começar a desenvolver para iOS ou Android. Se você deseja desenvolver para Android e iOS, tudo bem - você pode escolher um para começar, já que a configuração é um pouco diferente.

macOS

Windows

Linux

+ + + + \ No newline at end of file diff --git a/vitepress/docs/.vitepress/dist/docs/environment-setup/linux/android.html b/vitepress/docs/.vitepress/dist/docs/environment-setup/linux/android.html new file mode 100644 index 0000000..c218571 --- /dev/null +++ b/vitepress/docs/.vitepress/dist/docs/environment-setup/linux/android.html @@ -0,0 +1,33 @@ + + + + + + Instalando dependências | React Native 0.72 + + + + + + + + + + + + + + + + + + +
Skip to content

Instalando dependências

Você precisará do Node, da interface de linha de comando React Native, de um JDK e do Android Studio.

Embora você possa usar qualquer editor de sua escolha para desenvolver seu aplicativo, você precisará instalar o Android Studio para configurar as ferramentas necessárias para construir seu aplicativo React Native para Android.

Node

Siga as instruções de instalação da sua distribuição Linux para instalar o Node 18 ou mais recente.

Kit de desenvolvimento do Java

Atualmente, o React Native recomenda a versão 17 do Java SE Development Kit (JDK). Você pode encontrar problemas ao usar versões superiores do JDK. Você pode baixar e instalar o OpenJDK do AdoptOpenJDK ou do seu empacotador de sistema.

Ambiente de desenvolvimento Android

Configurar seu ambiente de desenvolvimento pode ser um tanto entediante se você for novo no desenvolvimento Android. Se você já estiver familiarizado com o desenvolvimento Android, talvez seja necessário configurar algumas coisas. Em ambos os casos, certifique-se de seguir cuidadosamente as próximas etapas.

1. Instale o Android Studio

Baixe e instale o Android Studio. No assistente de instalação do Android Studio, certifique-se de que as caixas ao lado de todos os itens a seguir estejam marcadas:

  • SDK Android
  • Android SDK Platform
  • Android Virtual Device

Em seguida, clique em “Next” para instalar todos esses componentes.

Nota

Se as caixas de seleção estiverem esmaecidas, você terá a chance de instalar esses componentes mais tarde.

Depois que a configuração for finalizada e a tela de boas-vindas for exibida, prossiga para a próxima etapa.

2. Instale o Android SDK

O Android Studio instala o Android SDK mais recente por padrão. Construir um aplicativo React Native com código nativo, no entanto, requer o SDK do Android 13 (Tiramisu) em particular. SDKs Android adicionais podem ser instalados por meio do SDK Manager no Android Studio.

Para fazer isso, abra o Android Studio, clique no botão "Configure" e selecione "SDK Manager".

Nota

O SDK Manager também pode ser encontrado na caixa de diálogo "Settings" do Android Studio, em Languages & Frameworks → Android SDK.

Selecione a guia "SDK Platforms" no SDK Manager e marque a caixa ao lado de "Show Package Details" no canto inferior direito. Procure e expanda a entrada Android 13 (Tiramisu) e certifique-se de que os seguintes itens estejam marcados:

  • Android SDK Platform 33
  • Intel x86 Atom_64 System Image ou Google APIs Intel x86 Atom System Image

Em seguida, selecione a guia "SDK Tools" e marque a caixa ao lado de "Show Package Details" aqui também. Procure e expanda a entrada "Android SDK Build-Tools" e certifique-se de que 33.0.0 esteja selecionado.

Por fim, clique em “Apply” para baixar e instalar o Android SDK e ferramentas de construção relacionadas.

  1. Configure a variável de ambiente ANDROID_HOME As ferramentas React Native requerem a configuração de algumas variáveis de ambiente para construir aplicativos com código nativo.

Adicione as seguintes linhas ao seu arquivo de configuração $HOME/.bash_profile ou $HOME/.bashrc (se você estiver usando zsh, então ~/.zprofile ou ~/.zshrc):

export ANDROID_HOME=$HOME/Android/Sdk
+export PATH=$PATH:$ANDROID_HOME/emulator
+export PATH=$PATH:$ANDROID_HOME/platform-tools

Usando outro Shell

.bash_profile é específico do bash. Se estiver usando outro shell, você precisará editar o arquivo de configuração específico do shell apropriado.

Digite source $HOME/.bash_profile para bash ou source $HOME/.zprofile para carregar a configuração em seu shell atual. Verifique se ANDROID_HOME foi configurado executando echo $ANDROID_HOME e os diretórios apropriados foram adicionados ao seu caminho executando echo $PATH.

Caminho do Android

Certifique-se de usar o caminho correto do Android SDK. Você pode encontrar a localização real do SDK na caixa de diálogo "Settings" do Android Studio, em Languages & Frameworks → Android SDK.

Watchman

Siga o guia de instalação do Watchman para compilar e instalar o Watchman a partir do código-fonte.

Sobre o Watchman

Watchman é uma ferramenta do Facebook para observar mudanças no sistema de arquivos. É altamente recomendável que você o instale para obter melhor desempenho e maior compatibilidade em certos casos extremos (tradução: você pode conseguir sobreviver sem instalar isso, mas sua milhagem pode variar; instalar isso agora pode evitar dores de cabeça mais tarde).

Interface de linha de comando nativa do React

React Native possui uma interface de linha de comando integrada. Em vez de instalar e gerenciar uma versão específica da CLI globalmente, recomendamos que você acesse a versão atual em tempo de execução usando npx, que acompanha o Node.js. Com npx react-native <command>, a versão estável atual da CLI será baixada e executada no momento em que o comando for executado.

Criando um novo aplicativo

Atenção

Se você instalou anteriormente um pacote global react-native-cli, remova-o, pois pode causar problemas inesperados:

bash
npm desinstalar -g react-native-cli @react-native-community/cli

React Native possui uma interface de linha de comando integrada, que você pode usar para gerar um novo projeto. Você pode acessá-lo sem instalar nada globalmente usando o npx, que acompanha o Node.js. Vamos criar um novo projeto React Native chamado "AwesomeProject":

bash
npx react-native@latest init AwesomeProject

Isso não é necessário se você estiver integrando o React Native em um aplicativo existente, se você "expulsou" da Expo ou se estiver adicionando suporte Android a um projeto React Native existente (consulte Integração com aplicativos existentes). Você também pode usar uma CLI de terceiros para iniciar seu aplicativo React Native, como Ignite CLI.

[Opcional] Usando uma versão ou modelo específico

Se quiser iniciar um novo projeto com uma versão específica do React Native, você pode usar o argumento --version:

bash
npx react-native@X.XX.X init AwesomeProject --version X.XX.X

Você também pode iniciar um projeto com um modelo React Native personalizado com o argumento --template.

Preparando o dispositivo Android

Você precisará de um dispositivo Android para executar seu aplicativo React Native para Android. Pode ser um dispositivo Android físico ou, mais comumente, você pode usar um dispositivo virtual Android que permite emular um dispositivo Android em seu computador.

De qualquer forma, você precisará preparar o dispositivo para executar aplicativos Android para desenvolvimento.

Usando um dispositivo físico

Se você tiver um dispositivo Android físico, poderá usá-lo para desenvolvimento no lugar de um AVD, conectando-o ao computador usando um cabo USB e seguindo as instruções aqui.

Usando um dispositivo virtual

Se você usar o Android Studio para abrir ./AwesomeProject/android, poderá ver a lista de dispositivos virtuais Android (AVDs) disponíveis abrindo o "AVD Manager" no Android Studio. Procure um ícone parecido com este:

image

Se você instalou recentemente o Android Studio, provavelmente precisará criar um novo AVD. Selecione "Create Virtual Device...", escolha qualquer telefone da lista e clique em "Next" e selecione a imagem Tiramisu API nível 33.

Aceleração de VM

Recomendamos configurar a aceleração de VM em seu sistema para melhorar o desempenho. Depois de seguir essas instruções, volte para o AVD Manager.

Clique em "Next" e depois em "Finish" para criar seu AVD. Neste ponto, você poderá clicar no botão de triângulo verde próximo ao seu AVD para iniciá-lo e, em seguida, prosseguir para a próxima etapa.

Executando seu aplicativo React Native

Etapa 1: iniciar o Metro

Metro é a ferramenta de construção JavaScript para React Native. Para iniciar o servidor de desenvolvimento Metro, execute o seguinte na pasta do projeto:

bash
npm start
+# ou
+yarn start

OBSERVAÇÃO

Se você estiver familiarizado com desenvolvimento web, o Metro é semelhante a empacotadores como Vite e webpack, mas foi projetado de ponta a ponta para React Native. Por exemplo, Metro usa Babel para transformar sintaxe como JSX em JavaScript executável.

Etapa 2: inicie seu aplicativo

Deixe o Metro Bundler rodar em seu próprio terminal. Abra um novo terminal dentro da pasta do projeto React Native. Execute o seguinte:

bash
npm run android
bash
yarn android

Se tudo estiver configurado corretamente, você deverá ver seu novo aplicativo em execução no emulador do Android em breve.

Essa é uma maneira de executar seu aplicativo: você também pode executá-lo diretamente no Android Studio.

Ajuda

Se você não conseguir fazer isso funcionar, consulte a página Solução de problemas.

Modificando seu aplicativo

Agora que você executou o aplicativo com sucesso, vamos modificá-lo.

  • Abra App.tsx no editor de texto de sua preferência e edite algumas linhas.
  • Pressione a tecla R duas vezes ou selecione Reload no menu Dev (Ctrl + M) para ver suas alterações!

É isso!

Parabéns! Você executou e modificou com sucesso seu primeiro aplicativo React Native.

image

E agora?

  • Se você deseja adicionar este novo código React Native a um aplicativo existente, consulte o guia de integração.

Se você estiver curioso para saber mais sobre o React Native, confira a Introdução ao React Native.

+ + + + \ No newline at end of file diff --git a/vitepress/docs/.vitepress/dist/docs/environment-setup/mac-os/android.html b/vitepress/docs/.vitepress/dist/docs/environment-setup/mac-os/android.html new file mode 100644 index 0000000..cbd9734 --- /dev/null +++ b/vitepress/docs/.vitepress/dist/docs/environment-setup/mac-os/android.html @@ -0,0 +1,35 @@ + + + + + + Android | React Native 0.72 + + + + + + + + + + + + + + + + + +
Skip to content

Android

Instalando dependências

Você precisará do Node, do Watchman, da interface de linha de comando React Native, de um JDK e do Android Studio.

Embora você possa usar qualquer editor de sua escolha para desenvolver seu aplicativo, você precisará instalar o Android Studio para configurar as ferramentas necessárias para criar seu aplicativo React Native para Android.

Node & Watchman

Recomendamos instalar o Node e o Watchman usando o Homebrew. Execute os seguintes comandos em um Terminal após instalar o Homebrew:

bash
brew install node
+brew install watchman

Se você já instalou o Node em seu sistema, certifique-se de que seja o Node 18 ou mais recente.

Watchman é uma ferramenta do Facebook para observar mudanças no sistema de arquivos. É altamente recomendável instalá-lo para melhor desempenho.

kit de desenvolvimento do Java

Recomendamos instalar a distribuição OpenJDK chamada Azul Zulu usando Homebrew. Execute os seguintes comandos em um Terminal após instalar o Homebrew:

bash
brew tap homebrew/cask-versions
+brew install --cask zulu17
+
+# Obtenha o caminho para onde o cask foi instalado para clicar duas vezes no instalador
+brew info --cask zulu17

Depois de instalar o JDK, atualize sua variável de ambiente JAVA_HOME. Se você usou as etapas acima, o JDK provavelmente estará em /Library/Java/JavaVirtualMachines/zulu-17.jdk/Contents/Home

A distribuição Zulu OpenJDK oferece JDKs para Macs Intel e M1. Isso garantirá que suas compilações sejam mais rápidas em Macs M1 em comparação com o uso de um JDK baseado em Intel.

Se você já instalou o JDK em seu sistema, recomendamos o JDK 17. Você pode encontrar problemas ao usar versões superiores do JDK.

1. Instale o Android Studio

Baixe e instale o Android Studio. No assistente de instalação do Android Studio, certifique-se de que as caixas ao lado de todos os itens a seguir estejam marcadas:

SDK AndroidPlataforma Android SDKDispositivo virtual Android

Em seguida, clique em "Next" para instalar todos esses componentes.

Nota

Se as caixas de seleção estiverem esmaecidas, você terá a chance de instalar esses componentes mais tarde.

Depois que a configuração for finalizada e a tela de boas-vindas for exibida, prossiga para a próxima etapa.

2. Instale o Android SDK

O Android Studio instala o Android SDK mais recente por padrão. Construir um aplicativo React Native com código nativo, no entanto, requer o SDK do Android 13 (Tiramisu) em particular. SDKs Android adicionais podem ser instalados por meio do SDK Manager no Android Studio.

Para fazer isso, abra o Android Studio, clique no botão "More Actions" e selecione "SDK Manager".

image

Nota

O SDK Manager também pode ser encontrado na caixa de diálogo "Settings" do Android Studio, em Languages & Frameworks → Android SDK.

Selecione a guia "Plataformas SDK" no SDK Manager e marque a caixa ao lado de "Mostrar detalhes do pacote" no canto inferior direito. Procure e expanda a entrada Android 13 (Tiramisu) e certifique-se de que os seguintes itens estejam marcados:

  • Plataforma Android SDK 33
  • Imagem do sistema Intel x86 Atom_64 ou Google APIs Intel x86 Atom System Image ou (para Apple M1 Silicon) Google APIs ARM 64 v8a System Image

Em seguida, selecione a guia "SDK Tools" e marque a caixa ao lado de "Show Package Details" aqui também. Procure e expanda a entrada "Android SDK Build-Tools" e certifique-se de que 33.0.0 esteja selecionado.

Por fim, clique em “Apply” para baixar e instalar o Android SDK e ferramentas de construção relacionadas.

  1. Configure a variável de ambiente ANDROID_HOME As ferramentas React Native requerem a configuração de algumas variáveis de ambiente para construir aplicativos com código nativo.

Adicione as seguintes linhas ao seu arquivo de configuração ~/.zprofile ou ~/.zshrc (se você estiver usando bash, então ~/.bash_profile ou ~/.bashrc):

bash
export ANDROID_HOME=$HOME/Library/Android/sdk
+export PATH=$PATH:$ANDROID_HOME/emulator
+export PATH=$PATH:$ANDROID_HOME/platform-tools

Execute source ~/.zprofile (ou source ~/.bash_profile para bash) para carregar a configuração em seu shell atual. Verifique se ANDROID_HOME foi configurado executando echo $ANDROID_HOME e os diretórios apropriados foram adicionados ao seu caminho executando echo $PATH.

Atenção

Certifique-se de usar o caminho correto do Android SDK. Você pode encontrar a localização real do SDK na caixa de diálogo "Settings" do Languages & Frameworks → Android SDK.

Interface de linha de comando nativa do React

React Native possui uma interface de linha de comando integrada. Em vez de instalar e gerenciar uma versão específica da CLI globalmente, recomendamos que você acesse a versão atual em tempo de execução usando npx, que acompanha o Node.js. Com npx react-native <command>, a versão estável atual da CLI será baixada e executada no momento em que o comando for executado.

Criando um novo aplicativo

Atenção

Se você instalou anteriormente um pacote global react-native-cli, remova-o, pois pode causar problemas inesperados:

bash
npm uninstall -g react-native-cli @react-native-community/cli

React Native possui uma interface de linha de comando integrada, que você pode usar para gerar um novo projeto. Você pode acessá-lo sem instalar nada globalmente usando o npx, que acompanha o Node.js. Vamos criar um novo projeto React Native chamado "AwesomeProject":

bash
npx react-native@latest init AwesomeProject

Isso não é necessário se você estiver integrando o React Native em um aplicativo existente, se você "expulsou" da Expo ou se estiver adicionando suporte Android a um projeto React Native existente (consulte Integração com aplicativos existentes). Você também pode usar uma CLI de terceiros para iniciar seu aplicativo React Native, como Ignite CLI.

[Opcional] Usando uma versão ou modelo específico

Se quiser iniciar um novo projeto com uma versão específica do React Native, você pode usar o argumento --version:

bash
npx react-native@X.XX.X init AwesomeProject --version X.XX.X

Você também pode iniciar um projeto com um modelo React Native personalizado com o argumento --template.

Preparando o dispositivo Android

Você precisará de um dispositivo Android para executar seu aplicativo React Native para Android. Pode ser um dispositivo Android físico ou, mais comumente, você pode usar um dispositivo virtual Android que permite emular um dispositivo Android em seu computador.

De qualquer forma, você precisará preparar o dispositivo para executar aplicativos Android para desenvolvimento.

Usando um dispositivo físico

Se você tiver um dispositivo Android físico, poderá usá-lo para desenvolvimento no lugar de um AVD, conectando-o ao computador usando um cabo USB e seguindo as instruções aqui.

Usando um dispositivo virtual

Se você usar o Android Studio para abrir ./AwesomeProject/android, poderá ver a lista de dispositivos virtuais Android (AVDs) disponíveis abrindo o "AVD Manager" no Android Studio. Procure um ícone parecido com este:

image

Se você instalou recentemente o Android Studio, provavelmente precisará criar um novo AVD. Selecione "Create Virtual Device...", escolha qualquer telefone da lista e clique em "Next" e selecione a imagem Tiramisu API nível 33.

Clique em “Next” e depois em “Finish” para criar seu AVD. Neste ponto, você poderá clicar no botão de triângulo verde próximo ao seu AVD para iniciá-lo e, em seguida, prosseguir para a próxima etapa.

Executando seu aplicativo React Native

Etapa 1: iniciar o Metro

Metro é a ferramenta de construção JavaScript para React Native. Para iniciar o servidor de desenvolvimento Metro, execute o seguinte na pasta do projeto:

bash
npm start
bash
yarn start

OBSERVAÇÃO

Se você estiver familiarizado com desenvolvimento web, o Metro é semelhante a empacotadores como Vite e webpack, mas foi projetado de ponta a ponta para React Native. Por exemplo, Metro usa Babel para transformar sintaxe como JSX em JavaScript executável.

Step 2: Inicie sua aplicação

bash
npm run android
bash
yarn android

Se tudo estiver configurado corretamente, você deverá ver seu novo aplicativo em execução no emulador do Android em breve.

image

Essa é uma maneira de executar seu aplicativo: você também pode executá-lo diretamente no Android Studio.

Nota

Se você não conseguir fazer isso funcionar, consulte a página Solução de problemas.

Modificando seu aplicativo

Agora que você executou o aplicativo com sucesso, vamos modificá-lo.

  • Abra App.tsx no editor de texto de sua preferência e edite algumas linhas.
  • Pressione a tecla R duas vezes ou selecione Reload no menu Dev (Cmd ⌘ + M) para ver suas alterações!

É isso!

Parabéns! Você executou e modificou com sucesso seu primeiro aplicativo React Native.

image

E agora?

  • Se você deseja adicionar este novo código React Native a um aplicativo existente, consulte o guia de integração.

Se você estiver curioso para saber mais sobre o React Native, confira a Introdução ao React Native.

+ + + + \ No newline at end of file diff --git a/vitepress/docs/.vitepress/dist/docs/environment-setup/mac-os/ios.html b/vitepress/docs/.vitepress/dist/docs/environment-setup/mac-os/ios.html new file mode 100644 index 0000000..07ec99d --- /dev/null +++ b/vitepress/docs/.vitepress/dist/docs/environment-setup/mac-os/ios.html @@ -0,0 +1,30 @@ + + + + + + iOS | React Native 0.72 + + + + + + + + + + + + + + + + + +
Skip to content

iOS

Instalando dependências

Você precisará de Node, Watchman, interface de linha de comando React Native, Xcode e CocoaPods.

Embora você possa usar qualquer editor de sua escolha para desenvolver seu aplicativo, você precisará instalar o Xcode para configurar as ferramentas necessárias para construir seu aplicativo React Native para iOS.

Node e Watchman

Recomendamos instalar o Node e o Watchman usando o Homebrew. Execute os seguintes comandos em um Terminal após instalar o Homebrew:

bash
brew install node
+brew install watchman

Se você já instalou o Node em seu sistema, certifique-se de que seja o Node 18 ou mais recente.

Watchman é uma ferramenta do Facebook para observar mudanças no sistema de arquivos. É altamente recomendável instalá-lo para melhor desempenho.

Xcode

A maneira mais fácil de instalar o Xcode é através da Mac App Store. A instalação do Xcode também instalará o Simulador iOS e todas as ferramentas necessárias para construir seu aplicativo iOS.

Se você já instalou o Xcode em seu sistema, certifique-se de que seja a versão 10 ou mais recente.

Ferramentas de linha de comando

Você também precisará instalar as ferramentas de linha de comando do Xcode. Abra o Xcode e escolha Settings... (ou Preferences...) no menu Xcode. Vá para o painel Locais e instale as ferramentas selecionando a versão mais recente no menu suspenso Ferramentas de linha de comando.

image

Instalando um simulador iOS no Xcode

Para instalar um simulador, abra Xcode > Settings... (ou Preferences...) e selecione a aba Platforms (ou Components). Selecione um simulador com a versão correspondente do iOS que você deseja usar.

Se você estiver usando o Xcode versão 14.0 ou superior para instalar um simulador, abra Xcode > Settings > Platforms, clique no ícone "+" e selecione a opção iOS….

CocoaPods

CocoaPods é um dos sistemas de gerenciamento de dependências disponíveis para iOS. CocoaPods é uma gem Ruby. Você pode instalar CocoaPods usando a versão do Ruby fornecida com a versão mais recente do macOS.

Para obter mais informações, visite o guia de primeiros passos do CocoaPods.

Interface de linha de comando nativa do React

React Native possui uma interface de linha de comando integrada. Em vez de instalar e gerenciar uma versão específica da CLI globalmente, recomendamos que você acesse a versão atual em tempo de execução usando npx, que acompanha o Node.js. Com npx react-native <command>, a versão estável atual da CLI será baixada e executada no momento em que o comando for executado.

Criando um novo aplicativo

Atenção!

Se você instalou anteriormente o pacote global react-native-cli, remova-o, pois pode causar problemas inesperados:

bash
npm uninstall -g react-native-cli @react-native-community/cli

Você pode usar a interface de linha de comando integrada do React Native para gerar um novo projeto. Vamos criar um novo projeto React Native chamado "AwesomeProject":

bash
npx react-native@latest init AwesomeProject

Isso não é necessário se você estiver integrando o React Native em um aplicativo existente, se você "expulsou" da Expo ou se estiver adicionando suporte a iOS ao projeto React Native existente (consulte Integração com aplicativos existentes). Você também pode usar uma CLI de terceiros para iniciar seu aplicativo React Native, como Ignite CLI.

INFORMAÇÕES

Se você estiver tendo problemas com o iOS, tente reinstalar as dependências executando:

  • cd ios para navegar até a pasta ios.
  • bundle install para instalar o Bundler
  • bundle exec pod install para instalar as dependências do iOS gerenciadas pelo CocoaPods.

[Opcional] Usando uma versão ou modelo específico

Se quiser iniciar um novo projeto com uma versão específica do React Native, você pode usar o argumento --version:

bash
npx react-native@X.XX.X init AwesomeProject --version X.XX.X

Você também pode iniciar um projeto com um modelo React Native personalizado com o argumento --template.

Nota

Se o comando acima estiver falhando, você pode ter uma versão antiga do react-native ou react-native-cli instalada globalmente no seu PC. Tente desinstalar o cli e execute-o usando npx.

[Opcional] Configurando seu ambiente

A partir do React Native versão 0.69, é possível configurar o ambiente Xcode usando o arquivo .xcode.env fornecido pelo template.

O arquivo .xcode.env contém uma variável de ambiente para exportar o caminho para o executável do node na variável NODE_BINARY. Esta é a abordagem sugerida para dissociar a infraestrutura de construção da versão do sistema do node. Você deve customizar esta variável com seu próprio caminho ou seu próprio gerenciador de versão de node, se for diferente do padrão.

Além disso, é possível adicionar qualquer outra variável de ambiente e originar o arquivo .xcode.env nas fases do script de construção. Caso você precise executar um script que requeira algum ambiente específico, esta é a abordagem sugerida: permite desacoplar as fases de construção de um ambiente específico.

INFORMAÇÕES

Se você já estiver usando NVM (um comando que ajuda a instalar e alternar entre versões do Node.js) e zsh, você pode querer mover o código que inicializa o NVM de seu ~/.zshrc para um arquivo ~/.zshenv para ajudar o Xcode a encontre seu executável Node:

bash
export NVM_DIR="$HOME/.nvm"
+[ -s "$NVM_DIR/nvm.sh" ] && \. "$NVM_DIR/nvm.sh"  # Isso carrega o nvm

Você também pode querer garantir que toda a "fase de construção do script de shell" do seu projeto Xcode esteja usando /bin/zsh como seu shell.

Executando seu aplicativo React Native

Etapa 1: iniciar o Metro

Metro é a ferramenta de construção JavaScript para React Native. Para iniciar o servidor de desenvolvimento Metro, execute o seguinte na pasta do projeto:

bash
npm start
bash
yarn start

OBSERVAÇÃO

Se você estiver familiarizado com desenvolvimento web, o Metro é semelhante a empacotadores como Vite e webpack, mas foi projetado de ponta a ponta para React Native. Por exemplo, Metro usa Babel para transformar sintaxe como JSX em JavaScript executável.

Etapa 2: inicie seu aplicativo

Deixe o Metro Bundler rodar em seu próprio terminal. Abra um novo terminal dentro da pasta do projeto React Native. Execute o seguinte:

bash
npm run ios
bash
yarn ios

Você deverá ver seu novo aplicativo em execução no iOS Simulator em breve.

image

Esta é uma maneira de executar seu aplicativo. Você também pode executá-lo diretamente no Xcode.

Ajuda

Se você não conseguir fazer isso funcionar, consulte a página Solução de problemas.

Executando em um dispositivo

O comando acima executará automaticamente seu aplicativo no iOS Simulator por padrão. Se você deseja executar o aplicativo em um dispositivo iOS físico real, siga as instruções aqui.

Modificando seu aplicativo

Agora que você executou o aplicativo com sucesso, vamos modificá-lo.

  • Abra App.tsx no editor de texto de sua preferência e edite algumas linhas.
  • Pressione Cmd ⌘ + R no seu simulador iOS para recarregar o aplicativo e ver suas alterações!

É isso!

Parabéns! Você executou e modificou com sucesso seu primeiro aplicativo React Native.

image

E agora?

  • Se você deseja adicionar este novo código React Native a um aplicativo existente, consulte o guia de integração.

Se você estiver curioso para saber mais sobre o React Native, confira a Introdução ao React Native.

+ + + + \ No newline at end of file diff --git a/vitepress/docs/.vitepress/dist/docs/environment-setup/windows/android.html b/vitepress/docs/.vitepress/dist/docs/environment-setup/windows/android.html new file mode 100644 index 0000000..4d082d1 --- /dev/null +++ b/vitepress/docs/.vitepress/dist/docs/environment-setup/windows/android.html @@ -0,0 +1,29 @@ + + + + + + Instalando dependências | React Native 0.72 + + + + + + + + + + + + + + + + + + +
Skip to content

Instalando dependências

Você precisará do Node, da interface de linha de comando React Native, de um JDK e do Android Studio.

Embora você possa usar qualquer editor de sua escolha para desenvolver seu aplicativo, você precisará instalar o Android Studio para configurar as ferramentas necessárias para criar seu aplicativo React Native para Android.

Node, JDK

Recomendamos instalar o Node via Chocolatey, um popular gerenciador de pacotes para Windows.

Recomenda-se usar uma versão LTS do Node. Se você quiser alternar entre versões diferentes, você pode instalar o Node via nvm-windows, um gerenciador de versões do Node para Windows.

React Native também requer Java SE Development Kit (JDK), que também pode ser instalado usando Chocolatey.

Abra um prompt de comando do administrador (clique com o botão direito em prompt de comando e selecione "Executar como administrador") e execute o seguinte comando:

bash
choco install -y nodejs-lts microsoft-openjdk17

Se você já instalou o Node em seu sistema, certifique-se de que seja o Node 18 ou mais recente. Se você já possui um JDK em seu sistema, recomendamos o JDK17. Você pode encontrar problemas ao usar versões superiores do JDK.

Node

Você pode encontrar opções de instalação adicionais na página de downloads do Nodehttps://nodejs.org/en/download/.

Java Development Kit

Se estiver usando a versão mais recente do Java Development Kit, você precisará alterar a versão Gradle do seu projeto para que ele possa reconhecer o JDK. Você pode fazer isso acessando {pasta raiz do projeto}\android\gradle\wrapper\gradle-wrapper.properties e alterando o valor DistributionUrl para atualizar a versão Gradle. Você pode conferir aqui os últimos lançamentos do Gradle.

Ambiente de desenvolvimento Android

Configurar seu ambiente de desenvolvimento pode ser um tanto entediante se você for novo no desenvolvimento Android. Se você já estiver familiarizado com o desenvolvimento Android, talvez seja necessário configurar algumas coisas. Em ambos os casos, certifique-se de seguir cuidadosamente as próximas etapas.

1. Instale o Android Studio

Baixe e instale o Android Studio. No assistente de instalação do Android Studio, certifique-se de que as caixas ao lado de todos os itens a seguir estejam marcadas:

  • SDK Android
  • Plataforma Android SDK
  • Dispositivo Virtual Android
  • Se você ainda não estiver usando Hyper-V: Performance (Intel ® HAXM) (Veja aqui para AMD ou Hyper-V)

Em seguida, clique em “Next” para instalar todos esses componentes.

Nota

Se as caixas de seleção estiverem esmaecidas, você terá a chance de instalar esses componentes mais tarde.

Depois que a configuração for finalizada e a tela de boas-vindas for exibida, prossiga para a próxima etapa.

2. Instale o Android SDK

O Android Studio instala o Android SDK mais recente por padrão. Construir um aplicativo React Native com código nativo, no entanto, requer o SDK do Android 13 (Tiramisu) em particular. SDKs Android adicionais podem ser instalados por meio do SDK Manager no Android Studio.

Para fazer isso, abra o Android Studio, clique no botão "More Actions" e selecione "SDK Manager".

image

Nota

O SDK Manager também pode ser encontrado na caixa de diálogo "Settings" do Android Studio, em Languages & Frameworks → Android SDK.

Selecione a guia "SDK Platforms" no SDK Manager e marque a caixa ao lado de "Show Package Details" no canto inferior direito. Procure e expanda a entrada Android 13 (Tiramisu) e certifique-se de que os seguintes itens estejam marcados:

  • Plataforma Android SDK 33
  • Intel x86 Atom_64 System Image ou Google APIs Intel x86 Atom System Image

Em seguida, selecione a guia "SDK Tools" e marque a caixa ao lado de "Show Package Details" aqui também. Procure e expanda a entrada Android SDK Build-Tools e certifique-se de que 33.0.0 esteja selecionado.

Por fim, clique em "Apply" para baixar e instalar o Android SDK e ferramentas de construção relacionadas.

  1. Configure a variável de ambiente ANDROID_HOME As ferramentas React Native requerem a configuração de algumas variáveis de ambiente para construir aplicativos com código nativo.

  2. Abra o Painel de Controle do Windows.

  3. Clique em Contas de usuário e clique em Contas de usuário novamente

  4. Clique em Alterar minhas variáveis de ambiente

  5. Clique em Novo... para criar uma nova variável de usuário ANDROID_HOME que aponta para o caminho para seu Android SDK:

image

O SDK é instalado, por padrão, no seguinte local:

%LOCALAPPDATA%\Android\Sdk

Você pode encontrar a localização real do SDK na caixa de diálogo "Settings" do Android Studio, em Languages & Frameworks → Android SDK.

Abra uma nova janela do prompt de comando para garantir que a nova variável de ambiente seja carregada antes de prosseguir para a próxima etapa.

  1. Abra o PowerShell

  2. Copie e cole *Get-ChildItem -Path Env:* no PowerShell

  3. Verifique se ANDROID_HOME foi adicionado

  4. Adicione ferramentas de plataforma ao Path

  5. Abra o Painel de Controle do Windows.

  6. Clique em Contas de usuário e clique em Contas de usuário novamente

  7. Clique em Alterar minhas variáveis de ambiente

  8. Selecione a variável Caminho.

  9. Clique em Editar.

  10. Clique em Novo e adicione o caminho para ferramentas de plataforma à lista.

O local padrão para esta pasta é:

%LOCALAPPDATA%\Android\Sdk\platform-tools

Interface de linha de comando nativa do React

React Native possui uma interface de linha de comando integrada. Em vez de instalar e gerenciar uma versão específica da CLI globalmente, recomendamos que você acesse a versão atual em tempo de execução usando npx, que acompanha o Node.js. Com npx react-native <command>, a versão estável atual da CLI será baixada e executada no momento em que o comando for executado.

Criando um novo aplicativo

Atenção

Se você instalou anteriormente o pacote global react-native-cli, remova-o, pois pode causar problemas inesperados:

npm desinstalar -g react-native-cli @react-native-community/cli

React Native possui uma interface de linha de comando integrada, que você pode usar para gerar um novo projeto. Você pode acessá-lo sem instalar nada globalmente usando o npx, que acompanha o Node.js. Vamos criar um novo projeto React Native chamado "AwesomeProject":

bash
npx react-native@latest init AwesomeProject

Isso não é necessário se você estiver integrando o React Native em um aplicativo existente, se você "expulsou" da Expo ou se estiver adicionando suporte Android a um projeto React Native existente (consulte Integração com aplicativos existentes). Você também pode usar uma CLI de terceiros para iniciar seu aplicativo React Native, como Ignite CLI.

[Opcional] Usando uma versão ou modelo específico

Se quiser iniciar um novo projeto com uma versão específica do React Native, você pode usar o argumento --version:

npx react-native@X.XX.X init AwesomeProject --versão X.XX.X

Você também pode iniciar um projeto com um modelo React Native personalizado com o argumento --template.

Preparando o dispositivo Android

Você precisará de um dispositivo Android para executar seu aplicativo React Native para Android. Pode ser um dispositivo Android físico ou, mais comumente, você pode usar um dispositivo virtual Android que permite emular um dispositivo Android em seu computador.

De qualquer forma, você precisará preparar o dispositivo para executar aplicativos Android para desenvolvimento.

Usando um dispositivo físico

Se você tiver um dispositivo Android físico, poderá usá-lo para desenvolvimento no lugar de um AVD, conectando-o ao computador usando um cabo USB e seguindo as instruções aqui.

Usando um dispositivo virtual

Se você usar o Android Studio para abrir ./AwesomeProject/android, poderá ver a lista de dispositivos virtuais Android (AVDs) disponíveis abrindo o "AVD Manager" no Android Studio. Procure um ícone parecido com este:

image

Se você instalou recentemente o Android Studio, provavelmente precisará criar um novo AVD. Selecione "Create Virtual Device...", escolha qualquer telefone da lista e clique em "Next" e selecione a imagem Tiramisu API nível 33.

Nota

Se você não possui o HAXM instalado, clique em "Install HAXM" ou siga estas instruções para configurá-lo e volte para o AVD Manager.

Clique em “Next” e depois em “Finish” para criar seu AVD. Neste ponto, você poderá clicar no botão de triângulo verde próximo ao seu AVD para iniciá-lo e, em seguida, prosseguir para a próxima etapa.

Executando seu aplicativo React Native

Etapa 1: iniciar o Metro

Metro é a ferramenta de construção JavaScript para React Native. Para iniciar o servidor de desenvolvimento Metro, execute o seguinte na pasta do projeto:

bash
npm start
bash
yarn start

OBSERVAÇÃO

Se você estiver familiarizado com desenvolvimento web, o Metro é semelhante a empacotadores como Vite e webpack, mas foi projetado de ponta a ponta para React Native. Por exemplo, Metro usa Babel para transformar sintaxe como JSX em JavaScript executável.

Etapa 2: inicie seu aplicativo

Deixe o Metro Bundler rodar em seu próprio terminal. Abra um novo terminal dentro da pasta do projeto React Native. Execute o seguinte:

bash
npm run android
bash
yarn android

Se tudo configurou tudo corretamente, você deverá ver seu novo aplicativo em execução no emulador do Android em breve.

image

Essa é uma maneira de executar seu aplicativo: você também pode executá-lo diretamente no Android Studio.

Ajuda

Se você não conseguir fazer isso funcionar, consulte a página Solução de problemas.

Modificando seu aplicativo

Agora que você executou o aplicativo com sucesso, vamos modificá-lo.

  • Abra App.tsx no editor de texto de sua preferência e edite algumas linhas.
  • Pressione a tecla R duas vezes ou selecione "Reload" no menu Dev (Ctrl + M) para ver suas alterações!

É isso!

Parabéns! Você executou e modificou com sucesso seu primeiro aplicativo React Native.

image

E agora?

  • Se você deseja adicionar este novo código React Native a um aplicativo existente, consulte o guia de integração.

Se você estiver curioso para saber mais sobre o React Native, confira a Introdução ao React Native.

+ + + + \ No newline at end of file diff --git a/vitepress/docs/.vitepress/dist/docs/fast-refresh.html b/vitepress/docs/.vitepress/dist/docs/fast-refresh.html new file mode 100644 index 0000000..2461b3e --- /dev/null +++ b/vitepress/docs/.vitepress/dist/docs/fast-refresh.html @@ -0,0 +1,27 @@ + + + + + + Atualização rápida | React Native 0.72 + + + + + + + + + + + + + + + + +
Skip to content

Atualização rápida

Fast Refresh é um recurso do React Native que permite obter feedback quase instantâneo sobre alterações em seus componentes React. A atualização rápida está habilitada por padrão e você pode alternar "Enable Fast Refresh" no menu React Native Dev. Com a Atualização rápida ativada, a maioria das edições deve ficar visível em um ou dois segundos.

Como funciona

  • Se você editar um módulo que exporta apenas componentes React, o Fast Refresh atualizará o código apenas para esse módulo e renderizará novamente seu componente. Você pode editar qualquer coisa nesse arquivo, incluindo estilos, lógica de renderização, manipuladores de eventos ou efeitos.
  • Se você editar um módulo com exportações que não sejam componentes do React, o Fast Refresh executará novamente esse módulo e os outros módulos que o importam. Portanto, se Button.js e Modal.js importarem Theme.js, a edição de Theme.js atualizará ambos os componentes.
  • Finalmente, se você editar um arquivo importado por módulos fora da árvore React, o Fast Refresh voltará a fazer uma recarga completa. Você pode ter um arquivo que renderiza um componente React, mas também exporta um valor que é importado por um componente não React. Por exemplo, talvez seu componente também exporte uma constante e um módulo utilitário não React a importe. Nesse caso, considere migrar a constante para um arquivo separado e importá-la para ambos os arquivos. Isso reativará o funcionamento do Fast Refresh. Outros casos geralmente podem ser resolvidos de maneira semelhante.

Resiliência a erros

Se você cometer um erro de sintaxe durante uma sessão de atualização rápida, poderá corrigi-lo e salvar o arquivo novamente. A caixa vermelha desaparecerá. Módulos com erros de sintaxe são impedidos de serem executados, portanto você não precisará recarregar o aplicativo.

Se você cometer um erro de tempo de execução durante a inicialização do módulo (por exemplo, digitando Style.create em vez de StyleSheet.create), a sessão de atualização rápida continuará depois que o erro for corrigido. A caixa vermelha desaparecerá e o módulo será atualizado.

Se você cometer um erro que leve a um erro de tempo de execução dentro do seu componente, a sessão de atualização rápida também continuará após a correção do erro. Nesse caso, o React remontará seu aplicativo usando o código atualizado.

Se você tiver limites de erro em seu aplicativo (o que é uma boa ideia para falhas normais na produção), eles tentarão renderizar novamente na próxima edição após uma caixa vermelha. Nesse sentido, ter um limite de erro pode impedir que você seja sempre expulso da tela raiz do aplicativo. No entanto, lembre-se de que os limites de erro não devem ser muito granulares. Eles são usados pelo React em produção e devem sempre ser projetados intencionalmente.

Limitações

O Fast Refresh tenta preservar o estado React local no componente que você está editando, mas somente se for seguro fazê-lo. Aqui estão alguns motivos pelos quais você pode ver o estado local sendo redefinido a cada edição de um arquivo:

  • O estado local não é preservado para componentes de classe (apenas componentes de função e Hooks preservam o estado).
  • O módulo que você está editando pode ter outras exportações além de um componente React.
  • Às vezes, um módulo exportaria o resultado da chamada de um componente de ordem superior como createNavigationContainer(MyScreen). Se o componente retornado for uma classe, o estado será redefinido.

No longo prazo, à medida que mais da sua base de código se move para componentes de função e ganchos, você pode esperar que o estado seja preservado em mais casos.

Dicas

  • A atualização rápida preserva o estado local do React nos componentes de função (e hooks) por padrão.
  • Às vezes, você pode querer forçar a redefinição do estado e a remontagem de um componente. Por exemplo, isso pode ser útil se você estiver ajustando uma animação que só acontece na montagem. Para fazer isso, você pode adicionar // @refresh reset em qualquer lugar do arquivo que está editando. Esta diretiva é local para o arquivo e instrui o Fast Refresh a remontar os componentes definidos nesse arquivo em cada edição.

Atualização rápida e ganchos

Quando possível, a Atualização Rápida tenta preservar o estado do seu componente entre as edições. Em particular, useState e useRef preservam seus valores anteriores, desde que você não altere seus argumentos ou a ordem das chamadas do Hook.

Ganchos com dependências — como useEffect, useMemo e useCallback — sempre serão atualizados durante o Fast Refresh. Sua lista de dependências será ignorada enquanto a atualização rápida estiver acontecendo.

Por exemplo, quando você edita useMemo(() => x * 2, [x]) para useMemo(() => x * 10, [x]), ele será executado novamente mesmo que x (a dependência) não tenha mudado. Se o React não fizesse isso, sua edição não seria refletida na tela!

Às vezes, isso pode levar a resultados inesperados. Por exemplo, mesmo um useEffect com uma matriz vazia de dependências ainda seria executado novamente uma vez durante a Atualização Rápida. No entanto, escrever código resiliente a uma nova execução ocasional de useEffect é uma boa prática, mesmo sem o Fast Refresh. Isso torna mais fácil para você introduzir posteriormente novas dependências nele.

+ + + + \ No newline at end of file diff --git a/vitepress/docs/.vitepress/dist/docs/flexbox.html b/vitepress/docs/.vitepress/dist/docs/flexbox.html new file mode 100644 index 0000000..6776a34 --- /dev/null +++ b/vitepress/docs/.vitepress/dist/docs/flexbox.html @@ -0,0 +1,1347 @@ + + + + + + Layout com Flexbox | React Native 0.72 + + + + + + + + + + + + + + + + +
Skip to content

Layout com Flexbox

Um componente pode especificar o layout de seus filhos usando o algoritmo Flexbox. Flexbox foi projetado para fornecer um layout consistente em diferentes tamanhos de tela.

Normalmente, você usará uma combinação de flexDirection, alignItems e justifyContent para obter o layout correto.

CUIDADO

O Flexbox funciona no React Native da mesma maneira que no CSS na web, com algumas exceções. Os padrões são diferentes, com flexDirection padronizando para coluna em vez de linha, alignContent padronizando para flex-start em vez de stretch, flexShrink padronizando para 0 em vez de 1, o parâmetro flex suportando apenas um único número.

Flex

flex definirá como seus itens irão “preencher” o espaço disponível ao longo de seu eixo principal. O espaço será dividido de acordo com a propriedade flex de cada elemento.

No exemplo a seguir, as visualizações vermelha, laranja e verde são todas filhas na visualização do contêiner que possui flex: 1 definido. A visualização vermelha usa flex: 1 , a visualização laranja usa flex: 2 e a visualização verde usa flex: 3. 1+2+3 = 6, o que significa que a visualização vermelha obterá 1/6 do espaço, a laranja 2/6 do espaço e a verde 3/6 do espaço.

jsx
import React from 'react';
+import {StyleSheet, View} from 'react-native';
+
+const Flex = () => {
+  return (
+    <View
+      style={[
+        styles.container,
+        {
+          // Tente definir `flexDirection` como `"row"`.
+          flexDirection: 'column',
+        },
+      ]}>
+      <View style={{flex: 1, backgroundColor: 'red'}} />
+      <View style={{flex: 2, backgroundColor: 'darkorange'}} />
+      <View style={{flex: 3, backgroundColor: 'green'}} />
+    </View>
+  );
+};
+
+const styles = StyleSheet.create({
+  container: {
+    flex: 1,
+    padding: 20,
+  },
+});
+
+export default Flex;

image

Direção flexível

flexDirection controla a direção na qual os filhos de um nó são dispostos. Isso também é conhecido como eixo principal. O eixo transversal é o eixo perpendicular ao eixo principal, ou o eixo no qual as linhas de quebra são dispostas.

  • column (valor padrão) Alinhe os filhos de cima para baixo. Se o empacotamento estiver ativado, a próxima linha começará à direita do primeiro item na parte superior do contêiner.
  • row Alinhe os filhos da esquerda para a direita. Se o empacotamento estiver ativado, a próxima linha começará no primeiro item à esquerda do contêiner.
  • column-reverse Alinhe os filhos de baixo para cima. Se o empacotamento estiver ativado, a próxima linha começará à direita do primeiro item na parte inferior do contêiner.
  • row-reverse Alinha os filhos da direita para a esquerda. Se o empacotamento estiver ativado, a próxima linha começará no primeiro item à direita do contêiner.

Você pode aprender mais aqui.

jsx
import React, {useState} from 'react';
+import {StyleSheet, Text, TouchableOpacity, View} from 'react-native';
+import type {PropsWithChildren} from 'react';
+
+const FlexDirectionBasics = () => {
+  const [flexDirection, setflexDirection] = useState('column');
+
+  return (
+    <PreviewLayout
+      label="flexDirection"
+      values={['column', 'row', 'row-reverse', 'column-reverse']}
+      selectedValue={flexDirection}
+      setSelectedValue={setflexDirection}>
+      <View style={[styles.box, {backgroundColor: 'powderblue'}]} />
+      <View style={[styles.box, {backgroundColor: 'skyblue'}]} />
+      <View style={[styles.box, {backgroundColor: 'steelblue'}]} />
+    </PreviewLayout>
+  );
+};
+
+type PreviewLayoutProps = PropsWithChildren<{
+  label: string;
+  values: string[];
+  selectedValue: string;
+  setSelectedValue: (value: string) => void;
+}>;
+
+const PreviewLayout = ({
+  label,
+  children,
+  values,
+  selectedValue,
+  setSelectedValue,
+}: PreviewLayoutProps) => (
+  <View style={{padding: 10, flex: 1}}>
+    <Text style={styles.label}>{label}</Text>
+    <View style={styles.row}>
+      {values.map(value => (
+        <TouchableOpacity
+          key={value}
+          onPress={() => setSelectedValue(value)}
+          style={[styles.button, selectedValue === value && styles.selected]}>
+          <Text
+            style={[
+              styles.buttonLabel,
+              selectedValue === value && styles.selectedLabel,
+            ]}>
+            {value}
+          </Text>
+        </TouchableOpacity>
+      ))}
+    </View>
+    <View style={[styles.container, {[label]: selectedValue}]}>{children}</View>
+  </View>
+);
+
+const styles = StyleSheet.create({
+  container: {
+    flex: 1,
+    marginTop: 8,
+    backgroundColor: 'aliceblue',
+  },
+  box: {
+    width: 50,
+    height: 50,
+  },
+  row: {
+    flexDirection: 'row',
+    flexWrap: 'wrap',
+  },
+  button: {
+    paddingHorizontal: 8,
+    paddingVertical: 6,
+    borderRadius: 4,
+    backgroundColor: 'oldlace',
+    alignSelf: 'flex-start',
+    marginHorizontal: '1%',
+    marginBottom: 6,
+    minWidth: '48%',
+    textAlign: 'center',
+  },
+  selected: {
+    backgroundColor: 'coral',
+    borderWidth: 0,
+  },
+  buttonLabel: {
+    fontSize: 12,
+    fontWeight: '500',
+    color: 'coral',
+  },
+  selectedLabel: {
+    color: 'white',
+  },
+  label: {
+    textAlign: 'center',
+    marginBottom: 10,
+    fontSize: 24,
+  },
+});
+
+export default FlexDirectionBasics;

image

Direção do layout

A direção do layout especifica a direção na qual os filhos e o texto em uma hierarquia devem ser dispostos. A direção do layout também afeta a que ponto o início e o fim da borda se referem. Por padrão, o React Native apresenta a direção do layout LTR. Neste modo, o início refere-se à esquerda e o fim refere-se à direita.

  • LTR (valor padrão) O texto e os filhos são dispostos da esquerda para a direita. A margem e o preenchimento aplicados ao início de um elemento são aplicados no lado esquerdo.
  • O texto RTL e os filhos são dispostos da direita para a esquerda. A margem e o preenchimento aplicados ao início de um elemento são aplicados no lado direito.
tsx
import React, {useState} from 'react';
+import {View, TouchableOpacity, Text, StyleSheet} from 'react-native';
+import type {PropsWithChildren} from 'react';
+
+const DirectionLayout = () => {
+  const [direction, setDirection] = useState('ltr');
+
+  return (
+    <PreviewLayout
+      label="direction"
+      selectedValue={direction}
+      values={['ltr', 'rtl']}
+      setSelectedValue={setDirection}>
+      <View style={[styles.box, {backgroundColor: 'powderblue'}]} />
+      <View style={[styles.box, {backgroundColor: 'skyblue'}]} />
+      <View style={[styles.box, {backgroundColor: 'steelblue'}]} />
+    </PreviewLayout>
+  );
+};
+
+type PreviewLayoutProps = PropsWithChildren<{
+  label: string;
+  values: string[];
+  selectedValue: string;
+  setSelectedValue: (value: string) => void;
+}>;
+
+const PreviewLayout = ({
+  label,
+  children,
+  values,
+  selectedValue,
+  setSelectedValue,
+}: PreviewLayoutProps) => (
+  <View style={{padding: 10, flex: 1}}>
+    <Text style={styles.label}>{label}</Text>
+    <View style={styles.row}>
+      {values.map(value => (
+        <TouchableOpacity
+          key={value}
+          onPress={() => setSelectedValue(value)}
+          style={[styles.button, selectedValue === value && styles.selected]}>
+          <Text
+            style={[
+              styles.buttonLabel,
+              selectedValue === value && styles.selectedLabel,
+            ]}>
+            {value}
+          </Text>
+        </TouchableOpacity>
+      ))}
+    </View>
+    <View style={[styles.container, {[label]: selectedValue}]}>{children}</View>
+  </View>
+);
+
+const styles = StyleSheet.create({
+  container: {
+    flex: 1,
+    marginTop: 8,
+    backgroundColor: 'aliceblue',
+  },
+  box: {
+    width: 50,
+    height: 50,
+  },
+  row: {
+    flexDirection: 'row',
+    flexWrap: 'wrap',
+  },
+  button: {
+    paddingHorizontal: 8,
+    paddingVertical: 6,
+    borderRadius: 4,
+    backgroundColor: 'oldlace',
+    alignSelf: 'flex-start',
+    marginHorizontal: '1%',
+    marginBottom: 6,
+    minWidth: '48%',
+    textAlign: 'center',
+  },
+  selected: {
+    backgroundColor: 'coral',
+    borderWidth: 0,
+  },
+  buttonLabel: {
+    fontSize: 12,
+    fontWeight: '500',
+    color: 'coral',
+  },
+  selectedLabel: {
+    color: 'white',
+  },
+  label: {
+    textAlign: 'center',
+    marginBottom: 10,
+    fontSize: 24,
+  },
+});
+
+export default DirectionLayout;

image

Justificar o conteúdo

justifyContent descreve como alinhar filhos dentro do eixo principal de seu contêiner. Por exemplo, você pode usar essa propriedade para centralizar um filho horizontalmente em um contêiner com flexDirection definido como linha ou verticalmente em um contêiner com flexDirection definido como coluna.

  • flex-start(valor padrão) Alinha os filhos de um contêiner ao início do eixo principal do contêiner.
  • flex-end Alinha os filhos de um contêiner ao final do eixo principal do contêiner.
  • center Alinha os filhos de um contêiner no centro do eixo principal do contêiner.
  • space-between Espaçar uniformemente os filhos no eixo principal do contêiner, distribuindo o espaço restante entre os filhos.
  • space-around Afaste uniformemente os filhos no eixo principal do contêiner, distribuindo o espaço restante ao redor dos filhos. Comparado ao espaço entre, usar o espaço ao redor resultará na distribuição do espaço para o início do primeiro filho e o final do último filho.

space-evenly Distribua uniformemente os filhos dentro do contêiner de alinhamento ao longo do eixo principal. O espaçamento entre cada par de itens adjacentes, a borda inicial principal e o primeiro item, e a borda final principal e o último item, são todos exatamente iguais.

Você pode aprender mais aqui.

tsx
import React, {useState} from 'react';
+import {View, TouchableOpacity, Text, StyleSheet} from 'react-native';
+import type {PropsWithChildren} from 'react';
+
+const JustifyContentBasics = () => {
+  const [justifyContent, setJustifyContent] = useState('flex-start');
+
+  return (
+    <PreviewLayout
+      label="justifyContent"
+      selectedValue={justifyContent}
+      values={[
+        'flex-start',
+        'flex-end',
+        'center',
+        'space-between',
+        'space-around',
+        'space-evenly',
+      ]}
+      setSelectedValue={setJustifyContent}>
+      <View style={[styles.box, {backgroundColor: 'powderblue'}]} />
+      <View style={[styles.box, {backgroundColor: 'skyblue'}]} />
+      <View style={[styles.box, {backgroundColor: 'steelblue'}]} />
+    </PreviewLayout>
+  );
+};
+
+type PreviewLayoutProps = PropsWithChildren<{
+  label: string;
+  values: string[];
+  selectedValue: string;
+  setSelectedValue: (value: string) => void;
+}>;
+
+const PreviewLayout = ({
+  label,
+  children,
+  values,
+  selectedValue,
+  setSelectedValue,
+}: PreviewLayoutProps) => (
+  <View style={{padding: 10, flex: 1}}>
+    <Text style={styles.label}>{label}</Text>
+    <View style={styles.row}>
+      {values.map(value => (
+        <TouchableOpacity
+          key={value}
+          onPress={() => setSelectedValue(value)}
+          style={[styles.button, selectedValue === value && styles.selected]}>
+          <Text
+            style={[
+              styles.buttonLabel,
+              selectedValue === value && styles.selectedLabel,
+            ]}>
+            {value}
+          </Text>
+        </TouchableOpacity>
+      ))}
+    </View>
+    <View style={[styles.container, {[label]: selectedValue}]}>{children}</View>
+  </View>
+);
+
+const styles = StyleSheet.create({
+  container: {
+    flex: 1,
+    marginTop: 8,
+    backgroundColor: 'aliceblue',
+  },
+  box: {
+    width: 50,
+    height: 50,
+  },
+  row: {
+    flexDirection: 'row',
+    flexWrap: 'wrap',
+  },
+  button: {
+    paddingHorizontal: 8,
+    paddingVertical: 6,
+    borderRadius: 4,
+    backgroundColor: 'oldlace',
+    alignSelf: 'flex-start',
+    marginHorizontal: '1%',
+    marginBottom: 6,
+    minWidth: '48%',
+    textAlign: 'center',
+  },
+  selected: {
+    backgroundColor: 'coral',
+    borderWidth: 0,
+  },
+  buttonLabel: {
+    fontSize: 12,
+    fontWeight: '500',
+    color: 'coral',
+  },
+  selectedLabel: {
+    color: 'white',
+  },
+  label: {
+    textAlign: 'center',
+    marginBottom: 10,
+    fontSize: 24,
+  },
+});
+
+export default JustifyContentBasics;

image

Alinhar itens

alignItems descreve como alinhar filhos ao longo do eixo cruzado de seu contêiner. É muito semelhante a justifyContent, mas em vez de aplicar ao eixo principal, alignItems aplica-se ao eixo cruzado.

  • stretch (valor padrão) Alonga os filhos de um contêiner para corresponder à altura do eixo transversal do contêiner.
  • flex-start Alinha os filhos de um contêiner ao início do eixo cruzado do contêiner.
  • flex-end Alinha os filhos de um contêiner ao final do eixo transversal do contêiner.
  • center Alinhe os filhos de um contêiner no centro do eixo transversal do contêiner.
  • baseline Alinha os filhos de um contêiner ao longo de uma linha de base comum. Cada criança pode ser definida como referência para seus pais.

INFORMAÇÕES

Para que o stretch tenha efeito, as crianças não devem ter uma dimensão fixa ao longo do eixo secundário. No exemplo a seguir, a configuração de alignItems: stretch não faz nada até que width: 50 seja removido dos filhos.

Você pode aprender mais aqui.

tsx
import React, {useState} from 'react';
+import {View, TouchableOpacity, Text, StyleSheet} from 'react-native';
+import type {PropsWithChildren} from 'react';
+
+const AlignItemsLayout = () => {
+  const [alignItems, setAlignItems] = useState('stretch');
+
+  return (
+    <PreviewLayout
+      label="alignItems"
+      selectedValue={alignItems}
+      values={['stretch', 'flex-start', 'flex-end', 'center', 'baseline']}
+      setSelectedValue={setAlignItems}>
+      <View style={[styles.box, {backgroundColor: 'powderblue'}]} />
+      <View style={[styles.box, {backgroundColor: 'skyblue'}]} />
+      <View
+        style={[
+          styles.box,
+          {
+            backgroundColor: 'steelblue',
+            width: 'auto',
+            minWidth: 50,
+          },
+        ]}
+      />
+    </PreviewLayout>
+  );
+};
+
+type PreviewLayoutProps = PropsWithChildren<{
+  label: string;
+  values: string[];
+  selectedValue: string;
+  setSelectedValue: (value: string) => void;
+}>;
+
+const PreviewLayout = ({
+  label,
+  children,
+  values,
+  selectedValue,
+  setSelectedValue,
+}: PreviewLayoutProps) => (
+  <View style={{padding: 10, flex: 1}}>
+    <Text style={styles.label}>{label}</Text>
+    <View style={styles.row}>
+      {values.map(value => (
+        <TouchableOpacity
+          key={value}
+          onPress={() => setSelectedValue(value)}
+          style={[styles.button, selectedValue === value && styles.selected]}>
+          <Text
+            style={[
+              styles.buttonLabel,
+              selectedValue === value && styles.selectedLabel,
+            ]}>
+            {value}
+          </Text>
+        </TouchableOpacity>
+      ))}
+    </View>
+    <View style={[styles.container, {[label]: selectedValue}]}>{children}</View>
+  </View>
+);
+
+const styles = StyleSheet.create({
+  container: {
+    flex: 1,
+    marginTop: 8,
+    backgroundColor: 'aliceblue',
+    minHeight: 200,
+  },
+  box: {
+    width: 50,
+    height: 50,
+  },
+  row: {
+    flexDirection: 'row',
+    flexWrap: 'wrap',
+  },
+  button: {
+    paddingHorizontal: 8,
+    paddingVertical: 6,
+    borderRadius: 4,
+    backgroundColor: 'oldlace',
+    alignSelf: 'flex-start',
+    marginHorizontal: '1%',
+    marginBottom: 6,
+    minWidth: '48%',
+    textAlign: 'center',
+  },
+  selected: {
+    backgroundColor: 'coral',
+    borderWidth: 0,
+  },
+  buttonLabel: {
+    fontSize: 12,
+    fontWeight: '500',
+    color: 'coral',
+  },
+  selectedLabel: {
+    color: 'white',
+  },
+  label: {
+    textAlign: 'center',
+    marginBottom: 10,
+    fontSize: 24,
+  },
+});
+
+export default AlignItemsLayout;

image

Alinhar-se

alignSelf tem as mesmas opções e efeitos que alignItems, mas em vez de afetar os filhos dentro de um contêiner, você pode aplicar essa propriedade a um único filho para alterar seu alinhamento dentro de seu pai. alignSelf substitui qualquer opção definida pelo pai com alignItems.

tsx
import React, {useState} from 'react';
+import {View, TouchableOpacity, Text, StyleSheet} from 'react-native';
+import type {PropsWithChildren} from 'react';
+import type {FlexAlignType} from 'react-native';
+
+const AlignSelfLayout = () => {
+  const [alignSelf, setAlignSelf] = useState<FlexAlignType>('stretch');
+
+  return (
+    <PreviewLayout
+      label="alignSelf"
+      selectedValue={alignSelf}
+      values={['stretch', 'flex-start', 'flex-end', 'center', 'baseline']}
+      setSelectedValue={setAlignSelf}>
+      <View
+        style={[
+          styles.box,
+          {
+            alignSelf,
+            width: 'auto',
+            minWidth: 50,
+            backgroundColor: 'powderblue',
+          },
+        ]}
+      />
+      <View style={[styles.box, {backgroundColor: 'skyblue'}]} />
+      <View style={[styles.box, {backgroundColor: 'steelblue'}]} />
+    </PreviewLayout>
+  );
+};
+
+type PreviewLayoutProps = PropsWithChildren<{
+  label: string;
+  values: FlexAlignType[];
+  selectedValue: string;
+  setSelectedValue: (value: FlexAlignType) => void;
+}>;
+
+const PreviewLayout = ({
+  label,
+  children,
+  values,
+  selectedValue,
+  setSelectedValue,
+}: PreviewLayoutProps) => (
+  <View style={{padding: 10, flex: 1}}>
+    <Text style={styles.label}>{label}</Text>
+    <View style={styles.row}>
+      {values.map(value => (
+        <TouchableOpacity
+          key={value}
+          onPress={() => setSelectedValue(value)}
+          style={[styles.button, selectedValue === value && styles.selected]}>
+          <Text
+            style={[
+              styles.buttonLabel,
+              selectedValue === value && styles.selectedLabel,
+            ]}>
+            {value}
+          </Text>
+        </TouchableOpacity>
+      ))}
+    </View>
+    <View style={styles.container}>{children}</View>
+  </View>
+);
+
+const styles = StyleSheet.create({
+  container: {
+    flex: 1,
+    marginTop: 8,
+    backgroundColor: 'aliceblue',
+    minHeight: 200,
+  },
+  box: {
+    width: 50,
+    height: 50,
+  },
+  row: {
+    flexDirection: 'row',
+    flexWrap: 'wrap',
+  },
+  button: {
+    paddingHorizontal: 8,
+    paddingVertical: 6,
+    borderRadius: 4,
+    backgroundColor: 'oldlace',
+    alignSelf: 'flex-start',
+    marginHorizontal: '1%',
+    marginBottom: 6,
+    minWidth: '48%',
+    textAlign: 'center',
+  },
+  selected: {
+    backgroundColor: 'coral',
+    borderWidth: 0,
+  },
+  buttonLabel: {
+    fontSize: 12,
+    fontWeight: '500',
+    color: 'coral',
+  },
+  selectedLabel: {
+    color: 'white',
+  },
+  label: {
+    textAlign: 'center',
+    marginBottom: 10,
+    fontSize: 24,
+  },
+});
+
+export default AlignSelfLayout;

image

Alinhar conteúdo

alignContent define a distribuição de linhas ao longo do eixo cruzado. Isso só tem efeito quando os itens são agrupados em várias linhas usando flexWrap.

  • flex-start (valor padrão) Alinha as linhas quebradas ao início do eixo cruzado do contêiner.
  • flex-end Alinhe as linhas quebradas ao final do eixo cruzado do contêiner.
  • stretch (valor padrão ao usar o Yoga na Web) Estica as linhas quebradas para corresponder à altura do eixo transversal do contêiner.
  • center Alinhe as linhas quebradas no centro do eixo transversal do contêiner.
  • space-between Espaçar uniformemente as linhas agrupadas ao longo do eixo cruzado do contêiner, distribuindo o espaço restante entre as linhas.
  • space-around Espaça uniformemente as linhas quebradas ao longo do eixo cruzado do contêiner, distribuindo o espaço restante ao redor das linhas. Comparado ao space-between, usar space-around resultará na distribuição do espaço no início da primeira linha e no final da última linha.

Você pode aprender mais aqui.

tsx
import React, {useState} from 'react';
+import {View, TouchableOpacity, Text, StyleSheet} from 'react-native';
+import type {PropsWithChildren} from 'react';
+
+const AlignContentLayout = () => {
+  const [alignContent, setAlignContent] = useState('flex-start');
+
+  return (
+    <PreviewLayout
+      label="alignContent"
+      selectedValue={alignContent}
+      values={[
+        'flex-start',
+        'flex-end',
+        'stretch',
+        'center',
+        'space-between',
+        'space-around',
+      ]}
+      setSelectedValue={setAlignContent}>
+      <View style={[styles.box, {backgroundColor: 'orangered'}]} />
+      <View style={[styles.box, {backgroundColor: 'orange'}]} />
+      <View style={[styles.box, {backgroundColor: 'mediumseagreen'}]} />
+      <View style={[styles.box, {backgroundColor: 'deepskyblue'}]} />
+      <View style={[styles.box, {backgroundColor: 'mediumturquoise'}]} />
+      <View style={[styles.box, {backgroundColor: 'mediumslateblue'}]} />
+      <View style={[styles.box, {backgroundColor: 'purple'}]} />
+    </PreviewLayout>
+  );
+};
+
+type PreviewLayoutProps = PropsWithChildren<{
+  label: string;
+  values: string[];
+  selectedValue: string;
+  setSelectedValue: (value: string) => void;
+}>;
+
+const PreviewLayout = ({
+  label,
+  children,
+  values,
+  selectedValue,
+  setSelectedValue,
+}: PreviewLayoutProps) => (
+  <View style={{padding: 10, flex: 1}}>
+    <Text style={styles.label}>{label}</Text>
+    <View style={styles.row}>
+      {values.map(value => (
+        <TouchableOpacity
+          key={value}
+          onPress={() => setSelectedValue(value)}
+          style={[styles.button, selectedValue === value && styles.selected]}>
+          <Text
+            style={[
+              styles.buttonLabel,
+              selectedValue === value && styles.selectedLabel,
+            ]}>
+            {value}
+          </Text>
+        </TouchableOpacity>
+      ))}
+    </View>
+    <View style={[styles.container, {[label]: selectedValue}]}>{children}</View>
+  </View>
+);
+
+const styles = StyleSheet.create({
+  container: {
+    flex: 1,
+    flexWrap: 'wrap',
+    marginTop: 8,
+    backgroundColor: 'aliceblue',
+    maxHeight: 400,
+  },
+  box: {
+    width: 50,
+    height: 80,
+  },
+  row: {
+    flexDirection: 'row',
+    flexWrap: 'wrap',
+  },
+  button: {
+    paddingHorizontal: 8,
+    paddingVertical: 6,
+    borderRadius: 4,
+    backgroundColor: 'oldlace',
+    alignSelf: 'flex-start',
+    marginHorizontal: '1%',
+    marginBottom: 6,
+    minWidth: '48%',
+    textAlign: 'center',
+  },
+  selected: {
+    backgroundColor: 'coral',
+    borderWidth: 0,
+  },
+  buttonLabel: {
+    fontSize: 12,
+    fontWeight: '500',
+    color: 'coral',
+  },
+  selectedLabel: {
+    color: 'white',
+  },
+  label: {
+    textAlign: 'center',
+    marginBottom: 10,
+    fontSize: 24,
+  },
+});
+
+export default AlignContentLayout;

image

Flex Wrap

A propriedade flexWrap é definida em contêineres e controla o que acontece quando os filhos excedem o tamanho do contêiner ao longo do eixo principal. Por padrão, os filhos são forçados a formar uma única linha (o que pode reduzir os elementos). Se o agrupamento for permitido, os itens serão agrupados em diversas linhas ao longo do eixo principal, se necessário.

Ao agrupar linhas, alignContent pode ser usado para especificar como as linhas são colocadas no contêiner. Saiba mais aqui.

tsx
import React, {useState} from 'react';
+import {View, TouchableOpacity, Text, StyleSheet} from 'react-native';
+import type {PropsWithChildren} from 'react';
+
+const FlexWrapLayout = () => {
+  const [flexWrap, setFlexWrap] = useState('wrap');
+
+  return (
+    <PreviewLayout
+      label="flexWrap"
+      selectedValue={flexWrap}
+      values={['wrap', 'nowrap']}
+      setSelectedValue={setFlexWrap}>
+      <View style={[styles.box, {backgroundColor: 'orangered'}]} />
+      <View style={[styles.box, {backgroundColor: 'orange'}]} />
+      <View style={[styles.box, {backgroundColor: 'mediumseagreen'}]} />
+      <View style={[styles.box, {backgroundColor: 'deepskyblue'}]} />
+      <View style={[styles.box, {backgroundColor: 'mediumturquoise'}]} />
+      <View style={[styles.box, {backgroundColor: 'mediumslateblue'}]} />
+      <View style={[styles.box, {backgroundColor: 'purple'}]} />
+    </PreviewLayout>
+  );
+};
+
+type PreviewLayoutProps = PropsWithChildren<{
+  label: string;
+  values: string[];
+  selectedValue: string;
+  setSelectedValue: (value: string) => void;
+}>;
+
+const PreviewLayout = ({
+  label,
+  children,
+  values,
+  selectedValue,
+  setSelectedValue,
+}: PreviewLayoutProps) => (
+  <View style={{padding: 10, flex: 1}}>
+    <Text style={styles.label}>{label}</Text>
+    <View style={styles.row}>
+      {values.map(value => (
+        <TouchableOpacity
+          key={value}
+          onPress={() => setSelectedValue(value)}
+          style={[styles.button, selectedValue === value && styles.selected]}>
+          <Text
+            style={[
+              styles.buttonLabel,
+              selectedValue === value && styles.selectedLabel,
+            ]}>
+            {value}
+          </Text>
+        </TouchableOpacity>
+      ))}
+    </View>
+    <View style={[styles.container, {[label]: selectedValue}]}>{children}</View>
+  </View>
+);
+
+const styles = StyleSheet.create({
+  container: {
+    flex: 1,
+    marginTop: 8,
+    backgroundColor: 'aliceblue',
+    maxHeight: 400,
+  },
+  box: {
+    width: 50,
+    height: 80,
+  },
+  row: {
+    flexDirection: 'row',
+    flexWrap: 'wrap',
+  },
+  button: {
+    paddingHorizontal: 8,
+    paddingVertical: 6,
+    borderRadius: 4,
+    backgroundColor: 'oldlace',
+    marginHorizontal: '1%',
+    marginBottom: 6,
+    minWidth: '48%',
+    textAlign: 'center',
+  },
+  selected: {
+    backgroundColor: 'coral',
+    borderWidth: 0,
+  },
+  buttonLabel: {
+    fontSize: 12,
+    fontWeight: '500',
+    color: 'coral',
+  },
+  selectedLabel: {
+    color: 'white',
+  },
+  label: {
+    textAlign: 'center',
+    marginBottom: 10,
+    fontSize: 24,
+  },
+});
+
+export default FlexWrapLayout;

image

Base Flexível, Crescer e Encolher

  • flexBasis é uma forma independente de eixo de fornecer o tamanho padrão de um item ao longo do eixo principal. Definir o flexBasis de um filho é semelhante a definir o width desse filho se seu pai for um contêiner com flexDirection: row ou definir o height de um filho se seu pai for um contêiner com flexDirection: column. O flexBasis de um item é o tamanho padrão desse item, o tamanho do item antes de qualquer cálculo de flexGrow e flexShrink ser executado.
  • flexGrow descreve quanto espaço dentro de um contêiner deve ser distribuído entre seus filhos ao longo do eixo principal. Depois de dispor seus filhos, um contêiner distribuirá qualquer espaço restante de acordo com os valores flex grow especificados por seus filhos.

flexGrow aceita qualquer valor de ponto flutuante >= 0, sendo 0 o valor padrão. Um contêiner distribuirá qualquer espaço restante entre seus filhos, ponderado pelos valores flexGrow dos filhos.

  • flexShrink descreve como reduzir os filhos ao longo do eixo principal no caso em que o tamanho total dos filhos excede o tamanho do contêiner no eixo principal. flexShrink é muito semelhante ao flexGrow e pode ser pensado da mesma maneira se qualquer tamanho excedente for considerado espaço restante negativo. Essas duas propriedades também funcionam bem juntas, permitindo que as crianças cresçam e diminuam conforme necessário.

flexShrink aceita qualquer valor de ponto flutuante >= 0, sendo 0 o valor padrão (na web, o padrão é 1). Um contêiner reduzirá seus filhos ponderados pelos valores flexShrink dos filhos.

Você pode aprender mais aqui.

tsx
import React, {useState} from 'react';
+import {View, Text, TextInput, StyleSheet} from 'react-native';
+import type {ViewStyle} from 'react-native';
+
+const App = () => {
+  const [powderblue, setPowderblue] = useState<ViewStyle>({
+    flexGrow: 0,
+    flexShrink: 1,
+    flexBasis: 'auto',
+  });
+  const [skyblue, setSkyblue] = useState<ViewStyle>({
+    flexGrow: 1,
+    flexShrink: 0,
+    flexBasis: 100,
+  });
+  const [steelblue, setSteelblue] = useState<ViewStyle>({
+    flexGrow: 0,
+    flexShrink: 1,
+    flexBasis: 200,
+  });
+  return (
+    <View style={styles.container}>
+      <View
+        style={[
+          styles.container,
+          {
+            flexDirection: 'row',
+            alignContent: 'space-between',
+          },
+        ]}>
+        <BoxInfo color="powderblue" {...powderblue} setStyle={setPowderblue} />
+        <BoxInfo color="skyblue" {...skyblue} setStyle={setSkyblue} />
+        <BoxInfo color="steelblue" {...steelblue} setStyle={setSteelblue} />
+      </View>
+      <View style={styles.previewContainer}>
+        <View
+          style={[
+            styles.box,
+            {
+              flexBasis: powderblue.flexBasis,
+              flexGrow: powderblue.flexGrow,
+              flexShrink: powderblue.flexShrink,
+              backgroundColor: 'powderblue',
+            },
+          ]}
+        />
+        <View
+          style={[
+            styles.box,
+            {
+              flexBasis: skyblue.flexBasis,
+              flexGrow: skyblue.flexGrow,
+              flexShrink: skyblue.flexShrink,
+              backgroundColor: 'skyblue',
+            },
+          ]}
+        />
+        <View
+          style={[
+            styles.box,
+            {
+              flexBasis: steelblue.flexBasis,
+              flexGrow: steelblue.flexGrow,
+              flexShrink: steelblue.flexShrink,
+              backgroundColor: 'steelblue',
+            },
+          ]}
+        />
+      </View>
+    </View>
+  );
+};
+
+type BoxInfoProps = ViewStyle & {
+  color: string;
+  setStyle: React.Dispatch<React.SetStateAction<ViewStyle>>;
+};
+
+const BoxInfo = ({
+  color,
+  flexBasis,
+  flexShrink,
+  setStyle,
+  flexGrow,
+}: BoxInfoProps) => (
+  <View style={[styles.row, {flexDirection: 'column'}]}>
+    <View
+      style={[
+        styles.boxLabel,
+        {
+          backgroundColor: color,
+        },
+      ]}>
+      <Text
+        style={{
+          color: '#fff',
+          fontWeight: '500',
+          textAlign: 'center',
+        }}>
+        Box
+      </Text>
+    </View>
+    <Text style={styles.label}>flexBasis</Text>
+    <TextInput
+      value={String(flexBasis)}
+      style={styles.input}
+      onChangeText={fB =>
+        setStyle(value => ({
+          ...value,
+          flexBasis: isNaN(parseInt(fB, 10)) ? 'auto' : parseInt(fB, 10),
+        }))
+      }
+    />
+    <Text style={styles.label}>flexShrink</Text>
+    <TextInput
+      value={String(flexShrink)}
+      style={styles.input}
+      onChangeText={fS =>
+        setStyle(value => ({
+          ...value,
+          flexShrink: isNaN(parseInt(fS, 10)) ? undefined : parseInt(fS, 10),
+        }))
+      }
+    />
+    <Text style={styles.label}>flexGrow</Text>
+    <TextInput
+      value={String(flexGrow)}
+      style={styles.input}
+      onChangeText={fG =>
+        setStyle(value => ({
+          ...value,
+          flexGrow: isNaN(parseInt(fG, 10)) ? undefined : parseInt(fG, 10),
+        }))
+      }
+    />
+  </View>
+);
+
+const styles = StyleSheet.create({
+  container: {
+    flex: 1,
+    paddingHorizontal: 10,
+  },
+  box: {
+    flex: 1,
+    height: 50,
+    width: 50,
+  },
+  boxLabel: {
+    minWidth: 80,
+    padding: 8,
+    borderRadius: 4,
+    marginTop: 8,
+  },
+  label: {
+    marginTop: 6,
+    fontSize: 16,
+    fontWeight: '100',
+  },
+  previewContainer: {
+    flex: 1,
+    flexDirection: 'row',
+    backgroundColor: 'aliceblue',
+  },
+  row: {
+    flex: 1,
+    flexDirection: 'row',
+    flexWrap: 'wrap',
+    alignItems: 'center',
+    marginBottom: 10,
+  },
+  input: {
+    borderBottomWidth: 1,
+    paddingVertical: 3,
+    width: 50,
+    textAlign: 'center',
+  },
+});
+
+export default App;

image

Lacuna de linha, lacuna de coluna e lacuna

  • rowGap define o tamanho da lacuna (gutter) entre as linhas de um elemento.
  • columnGap define o tamanho da lacuna (gutter) entre as colunas de um elemento.
  • gap define o tamanho do intervalo (gutter) entre linhas e colunas. É uma abreviação de rowGap e columnGap.

Você pode usar flexWrap e alignContent junto com gap para adicionar espaçamento consistente entre os itens.

tsx
import React, {useState} from 'react';
+import {View, Text, StyleSheet, TextInput} from 'react-native';
+import type {PropsWithChildren} from 'react';
+
+const RowGapAndColumnGap = () => {
+  const [rowGap, setRowGap] = useState(10);
+  const [columnGap, setColumnGap] = useState(10);
+
+  return (
+    <PreviewLayout
+      columnGap={columnGap}
+      handleColumnGapChange={setColumnGap}
+      rowGap={rowGap}
+      handleRowGapChange={setRowGap}>
+      <View style={[styles.box, styles.box1]} />
+      <View style={[styles.box, styles.box2]} />
+      <View style={[styles.box, styles.box3]} />
+      <View style={[styles.box, styles.box4]} />
+      <View style={[styles.box, styles.box5]} />
+    </PreviewLayout>
+  );
+};
+
+type PreviewLayoutProps = PropsWithChildren<{
+  columnGap: number;
+  handleColumnGapChange: (gap: number) => void;
+  rowGap: number;
+  handleRowGapChange: (gap: number) => void;
+}>;
+
+const PreviewLayout = ({
+  children,
+  handleColumnGapChange,
+  handleRowGapChange,
+  rowGap,
+  columnGap,
+}: PreviewLayoutProps) => (
+  <View style={styles.previewContainer}>
+    <View style={styles.inputContainer}>
+      <View style={styles.itemsCenter}>
+        <Text>Row Gap</Text>
+        <TextInput
+          style={styles.input}
+          value={String(rowGap)}
+          onChangeText={v => handleRowGapChange(Number(v))}
+        />
+      </View>
+      <View style={styles.itemsCenter}>
+        <Text>Column Gap</Text>
+        <TextInput
+          style={styles.input}
+          value={String(columnGap)}
+          onChangeText={v => handleColumnGapChange(Number(v))}
+        />
+      </View>
+    </View>
+    <View style={[styles.container, {rowGap, columnGap}]}>{children}</View>
+  </View>
+);
+
+const styles = StyleSheet.create({
+  itemsCenter: {alignItems: 'center'},
+  inputContainer: {
+    gap: 4,
+    flexDirection: 'row',
+    justifyContent: 'space-around',
+  },
+  previewContainer: {padding: 10, flex: 1},
+  input: {
+    borderBottomWidth: 1,
+    paddingVertical: 3,
+    width: 50,
+    textAlign: 'center',
+  },
+  container: {
+    flex: 1,
+    marginTop: 8,
+    backgroundColor: 'aliceblue',
+    maxHeight: 400,
+    flexWrap: 'wrap',
+    alignContent: 'flex-start',
+  },
+  box: {
+    width: 50,
+    height: 80,
+  },
+  box1: {
+    backgroundColor: 'orangered',
+  },
+  box2: {
+    backgroundColor: 'orange',
+  },
+  box3: {
+    backgroundColor: 'mediumseagreen',
+  },
+  box4: {
+    backgroundColor: 'deepskyblue',
+  },
+  box5: {
+    backgroundColor: 'mediumturquoise',
+  },
+});
+
+export default RowGapAndColumnGap;

image

Largura e altura

A propriedade width especifica a largura da área de conteúdo de um elemento. Da mesma forma, a propriedade height especifica a altura da área de conteúdo de um elemento.

Tanto a largura quanto a altura podem assumir os seguintes valores:

  • auto (valor padrão) React Native calcula a largura/altura do elemento com base em seu conteúdo, seja ele outros filhos, texto ou uma imagem.
  • pixels Define a largura/altura em pixels absolutos. Dependendo de outros estilos definidos no componente, esta pode ou não ser a dimensão final do nó.
  • percentage Define a largura ou altura em porcentagem da largura ou altura do pai, respectivamente.
tsx
import React, {useState} from 'react';
+import {
+  View,
+  SafeAreaView,
+  TouchableOpacity,
+  Text,
+  StyleSheet,
+} from 'react-native';
+import type {PropsWithChildren} from 'react';
+
+type Dimension = 'auto' | `${number}%` | number;
+
+const WidthHeightBasics = () => {
+  const [widthType, setWidthType] = useState<Dimension>('auto');
+  const [heightType, setHeightType] = useState<Dimension>('auto');
+
+  return (
+    <PreviewLayout
+      widthType={widthType}
+      heightType={heightType}
+      widthValues={['auto', 300, '80%']}
+      heightValues={['auto', 200, '60%']}
+      setWidthType={setWidthType}
+      setHeightType={setHeightType}>
+      <View
+        style={{
+          alignSelf: 'flex-start',
+          backgroundColor: 'aliceblue',
+          height: heightType,
+          width: widthType,
+          padding: 15,
+        }}>
+        <View style={[styles.box, {backgroundColor: 'powderblue'}]} />
+        <View style={[styles.box, {backgroundColor: 'skyblue'}]} />
+        <View style={[styles.box, {backgroundColor: 'steelblue'}]} />
+      </View>
+    </PreviewLayout>
+  );
+};
+
+type PreviewLayoutProps = PropsWithChildren<{
+  widthType: Dimension;
+  heightType: Dimension;
+  widthValues: Dimension[];
+  heightValues: Dimension[];
+  setWidthType: (value: Dimension) => void;
+  setHeightType: (value: Dimension) => void;
+}>;
+
+const PreviewLayout = ({
+  children,
+  widthType,
+  heightType,
+  widthValues,
+  heightValues,
+  setWidthType,
+  setHeightType,
+}: PreviewLayoutProps) => (
+  <SafeAreaView style={{flex: 1, padding: 10}}>
+    <View style={styles.row}>
+      <Text style={styles.label}>width </Text>
+      {widthValues.map(value => (
+        <TouchableOpacity
+          key={value}
+          onPress={() => setWidthType(value)}
+          style={[styles.button, widthType === value && styles.selected]}>
+          <Text
+            style={[
+              styles.buttonLabel,
+              widthType === value && styles.selectedLabel,
+            ]}>
+            {value}
+          </Text>
+        </TouchableOpacity>
+      ))}
+    </View>
+    <View style={styles.row}>
+      <Text style={styles.label}>height </Text>
+      {heightValues.map(value => (
+        <TouchableOpacity
+          key={value}
+          onPress={() => setHeightType(value)}
+          style={[styles.button, heightType === value && styles.selected]}>
+          <Text
+            style={[
+              styles.buttonLabel,
+              heightType === value && styles.selectedLabel,
+            ]}>
+            {value}
+          </Text>
+        </TouchableOpacity>
+      ))}
+    </View>
+    {children}
+  </SafeAreaView>
+);
+
+const styles = StyleSheet.create({
+  box: {
+    width: 50,
+    height: 50,
+  },
+  row: {
+    flexDirection: 'row',
+    flexWrap: 'wrap',
+  },
+  button: {
+    padding: 8,
+    borderRadius: 4,
+    backgroundColor: 'oldlace',
+    alignSelf: 'flex-start',
+    marginRight: 10,
+    marginBottom: 10,
+  },
+  selected: {
+    backgroundColor: 'coral',
+    shadowOpacity: 0,
+    borderWidth: 0,
+  },
+  buttonLabel: {
+    fontSize: 12,
+    fontWeight: '500',
+    color: 'coral',
+  },
+  selectedLabel: {
+    color: 'white',
+  },
+  label: {
+    textAlign: 'center',
+    marginBottom: 10,
+    fontSize: 24,
+  },
+});
+
+export default WidthHeightBasics;

image

Layout Absoluto e Relativo

O tipo de position de um elemento define como ele é posicionado em seu pai.

  • relative (valor padrão) Por padrão, um elemento é posicionado relativamente. Isso significa que um elemento é posicionado de acordo com o fluxo normal do layout e, em seguida, deslocado em relação a essa posição com base nos valores top, right, bottom e left. O deslocamento não afeta a posição de nenhum elemento irmão ou pai.
  • absolute Quando posicionado de forma absoluta, um elemento não participa do fluxo normal do layout. Em vez disso, é apresentado independente de seus irmãos. A posição é determinada com base nos valores superior, direito, inferior e esquerdo.
tsx
import React, {useState} from 'react';
+import {View, TouchableOpacity, Text, StyleSheet} from 'react-native';
+import type {PropsWithChildren} from 'react';
+
+const PositionLayout = () => {
+  const [position, setPosition] = useState<'relative' | 'absolute'>('relative');
+
+  return (
+    <PreviewLayout
+      label="position"
+      selectedValue={position}
+      values={['relative', 'absolute']}
+      setSelectedValue={setPosition}>
+      <View
+        style={[
+          styles.box,
+          {
+            top: 25,
+            left: 25,
+            position,
+            backgroundColor: 'powderblue',
+          },
+        ]}
+      />
+      <View
+        style={[
+          styles.box,
+          {
+            top: 50,
+            left: 50,
+            position,
+            backgroundColor: 'skyblue',
+          },
+        ]}
+      />
+      <View
+        style={[
+          styles.box,
+          {
+            top: 75,
+            left: 75,
+            position,
+            backgroundColor: 'steelblue',
+          },
+        ]}
+      />
+    </PreviewLayout>
+  );
+};
+
+type PreviewLayoutProps = PropsWithChildren<{
+  label: string;
+  values: Array<'relative' | 'absolute'>;
+  selectedValue: string;
+  setSelectedValue: (value: 'relative' | 'absolute') => void;
+}>;
+
+const PreviewLayout = ({
+  label,
+  children,
+  values,
+  selectedValue,
+  setSelectedValue,
+}: PreviewLayoutProps) => (
+  <View style={{padding: 10, flex: 1}}>
+    <Text style={styles.label}>{label}</Text>
+    <View style={styles.row}>
+      {values.map(value => (
+        <TouchableOpacity
+          key={value}
+          onPress={() => setSelectedValue(value)}
+          style={[styles.button, selectedValue === value && styles.selected]}>
+          <Text
+            style={[
+              styles.buttonLabel,
+              selectedValue === value && styles.selectedLabel,
+            ]}>
+            {value}
+          </Text>
+        </TouchableOpacity>
+      ))}
+    </View>
+    <View style={styles.container}>{children}</View>
+  </View>
+);
+
+const styles = StyleSheet.create({
+  container: {
+    flex: 1,
+    marginTop: 8,
+    backgroundColor: 'aliceblue',
+    minHeight: 200,
+  },
+  box: {
+    width: 50,
+    height: 50,
+  },
+  row: {
+    flexDirection: 'row',
+    flexWrap: 'wrap',
+  },
+  button: {
+    paddingHorizontal: 8,
+    paddingVertical: 6,
+    borderRadius: 4,
+    backgroundColor: 'oldlace',
+    alignSelf: 'flex-start',
+    marginHorizontal: '1%',
+    marginBottom: 6,
+    minWidth: '48%',
+    textAlign: 'center',
+  },
+  selected: {
+    backgroundColor: 'coral',
+    borderWidth: 0,
+  },
+  buttonLabel: {
+    fontSize: 12,
+    fontWeight: '500',
+    color: 'coral',
+  },
+  selectedLabel: {
+    color: 'white',
+  },
+  label: {
+    textAlign: 'center',
+    marginBottom: 10,
+    fontSize: 24,
+  },
+});
+
+export default PositionLayout;

image

Indo mais fundo

Confira o playground interativo de ioga que você pode usar para entender melhor o flexbox.

Abordamos o básico, mas existem muitos outros estilos que você pode precisar para layouts. A lista completa de adereços que controlam o layout está documentada aqui.

Além disso, você pode ver alguns exemplos dos Engenheiros da Wix.

+ + + + \ No newline at end of file diff --git a/vitepress/docs/.vitepress/dist/docs/gesture-responder-system.html b/vitepress/docs/.vitepress/dist/docs/gesture-responder-system.html new file mode 100644 index 0000000..e086f11 --- /dev/null +++ b/vitepress/docs/.vitepress/dist/docs/gesture-responder-system.html @@ -0,0 +1,27 @@ + + + + + + Sistema de resposta por gestos | React Native 0.72 + + + + + + + + + + + + + + + + +
Skip to content

Sistema de resposta por gestos

O sistema de resposta por gestos gerencia o ciclo de vida dos gestos no seu aplicativo. Um toque pode passar por diversas fases enquanto o app determina qual é a intenção do usuário. Por exemplo, o aplicativo precisa determinar se o toque está rolando, deslizando em um widget ou tocando. Isso pode até mudar durante um toque. Também pode haver vários toques simultâneos.

O sistema de resposta ao toque é necessário para permitir que os componentes negociem essas interações por toque sem qualquer conhecimento adicional sobre seus componentes pai ou filho.

Melhores Práticas

Para que seu aplicativo seja ótimo, cada ação deve ter os seguintes atributos:

  • Feedback/destaque – mostre ao usuário o que está acontecendo com seu toque e o que acontecerá quando ele liberar o gesto
  • Capacidade de cancelamento - ao realizar uma ação, o usuário deve ser capaz de abortá-la no meio do toque, arrastando o dedo para longe

Esses recursos deixam os usuários mais confortáveis ao usar um aplicativo, pois permitem que as pessoas experimentem e interajam sem medo de cometer erros.

TouchableHighlight and Touchable*

O sistema de resposta pode ser complicado de usar. Portanto, fornecemos uma implementação abstrata Touchable para coisas que deveriam ser "tocáveis". Isso usa o sistema de resposta e permite configurar interações de toque de forma declarativa. Use TouchableHighlight em qualquer lugar onde você usaria um botão ou link na web.

Ciclo de vida do Respondente

Uma visualização pode se tornar a resposta ao toque, implementando os métodos de negociação corretos. Existem dois métodos para perguntar à visualização se ela deseja se tornar respondente:

  • View.props.onStartShouldSetResponder: evt => true, - Esta visualização deseja se tornar respondente no início de um toque?
  • View.props.onMoveShouldSetResponder: evt => true, - Chamado para cada movimento de toque na Visualização quando não é o respondedor: esta visualização deseja "reivindicar" capacidade de resposta ao toque?

Se a View retornar true e tentar se tornar o respondente, uma das seguintes situações acontecerá:

  • View.props.onResponderGrant: evt => {} - A visualização agora está respondendo a eventos de toque. Este é o momento de destacar e mostrar ao usuário o que está acontecendo
  • View.props.onResponderReject: evt => {} - Outra coisa está respondendo agora e não irá liberá-la

Se a visualização estiver respondendo, os seguintes manipuladores poderão ser chamados:

  • View.props.onResponderMove: evt => {} - O usuário está movendo o dedo
  • View.props.onResponderRelease: evt => {} - Disparado no final do toque, ou seja, "touchUp"
  • View.props.onResponderTerminationRequest: evt => true - Outra coisa deseja se tornar respondedor. Essa visão deve liberar o respondedor? Retornar verdadeiro permite a liberação
  • View.props.onResponderTerminate: evt => {} - O respondente foi retirado da Visualização. Pode ser obtido por outras visualizações após uma chamada para onResponderTerminationRequest ou pode ser obtido pelo sistema operacional sem perguntar (acontece com o centro de controle/centro de notificação no iOS)

evt é um evento de toque sintético com o seguinte formato:

  • nativeEvent
    • changeTouches - Matriz de todos os eventos de toque que foram alterados desde o último evento
    • identifier - O ID do toque
    • locationX - A posição X do toque, em relação ao elemento
    • locationY - A posição Y do toque, em relação ao elemento
    • pageX - A posição X do toque, em relação ao elemento raiz
    • pageY - A posição Y do toque, em relação ao elemento raiz
    • target - O ID do nó do elemento que recebe o evento de toque
    • timestamp - Um identificador de tempo para o toque, útil para cálculo de velocidade
    • touches - Matriz de todos os toques atuais na tela

Capturar manipuladores ShouldSet

onStartShouldSetResponder e onMoveShouldSetResponder são chamados com um padrão de bolha, onde o nó mais profundo é chamado primeiro. Isso significa que o componente mais profundo se tornará respondedor quando múltiplas Views retornarem true para manipuladores *ShouldSetResponder. Isso é desejável na maioria dos casos, porque garante que todos os controles e botões possam ser usados.

No entanto, às vezes um pai vai querer ter certeza de que ele responderá. Isso pode ser resolvido usando a fase de captura. Antes que o sistema de resposta surja do componente mais profundo, ele fará uma fase de captura, disparando em *ShouldSetResponderCapture. Portanto, se uma visualização pai quiser evitar que o filho se torne respondedor em uma inicialização por toque, ela deverá ter um manipulador onStartShouldSetResponderCapture que retorne verdadeiro.

  • View.props.onStartShouldSetResponderCapture: evt => true,
  • View.props.onMoveShouldSetResponderCapture: evt => true,

PanResponder

Para interpretação de gestos de nível superior, confira PanResponder.

+ + + + \ No newline at end of file diff --git a/vitepress/docs/.vitepress/dist/docs/getting-started.html b/vitepress/docs/.vitepress/dist/docs/getting-started.html new file mode 100644 index 0000000..4bd12b4 --- /dev/null +++ b/vitepress/docs/.vitepress/dist/docs/getting-started.html @@ -0,0 +1,44 @@ + + + + + + Introdução | React Native 0.72 + + + + + + + + + + + + + + + + +
Skip to content

Introdução

Bem-vindo ao início de sua jornada React Native! Se você estiver procurando instruções de configuração do ambiente, elas foram movidas para sua própria seção. Continue lendo para obter uma introdução à documentação, componentes nativos, React e muito mais!

Muitos tipos diferentes de pessoas usam React Native: desde desenvolvedores iOS avançados até iniciantes em React, até pessoas que estão começando a programar pela primeira vez em suas carreiras. Esses documentos foram escritos para todos os alunos, independentemente do nível de experiência ou formação.

Como usar esses documentos

Você pode começar aqui e ler esses documentos linearmente como um livro; ou você pode ler as seções específicas de que precisa. Já conhece o React? Você pode pular para essa seção - ou lê-la para uma atualização leve.

Pré-requisitos

Para trabalhar com React Native, você precisará entender os fundamentos do JavaScript. Se você é novo em JavaScript ou precisa de uma atualização, você pode mergulhar ou se atualizar na Mozilla Developer Network.

Exemplos interativos

Esta introdução permite que você comece imediatamente em seu navegador com exemplos interativos como este:

js
// Hello World
+import React from 'react';
+import {Text, View} from 'react-native';
+
+const YourApp = () => {
+  return (
+    <View
+      style={{
+        flex: 1,
+        justifyContent: 'center',
+        alignItems: 'center',
+      }}>
+      <Text>Try editing me! 🎉</Text>
+    </View>
+  );
+};
+
+export default YourApp;

Opcionalmente

Se desejar configurar um ambiente de desenvolvimento local, você pode seguir nosso guia para configurar seu ambiente em sua máquina local e colar os exemplos de código em seu arquivo App.js. (Se você é um desenvolvedor web, talvez já tenha um ambiente local configurado para testes de navegadores móveis!)

Notas do desenvolvedor

Pessoas de diversas origens de desenvolvimento estão aprendendo React Native. Você pode ter experiência com uma variedade de tecnologias, desde web até Android, iOS e muito mais. Tentamos escrever para desenvolvedores de todas as origens.

Formatação

Os caminhos dos menus são escritos em negrito e usam sinais de intercalação para navegar nos submenus. Exemplo: Android Studio > Preference

Agora que você sabe como funciona este guia, é hora de conhecer a base do React Native: Native Components.

+ + + + \ No newline at end of file diff --git a/vitepress/docs/.vitepress/dist/docs/handling-text-input.html b/vitepress/docs/.vitepress/dist/docs/handling-text-input.html new file mode 100644 index 0000000..458f944 --- /dev/null +++ b/vitepress/docs/.vitepress/dist/docs/handling-text-input.html @@ -0,0 +1,50 @@ + + + + + + Tratamento de entrada de texto | React Native 0.72 + + + + + + + + + + + + + + + + +
Skip to content

Tratamento de entrada de texto

TextInput é um componente principal que permite ao usuário inserir texto. Ele tem uma propriedade onChangeText que leva uma função a ser chamada toda vez que o texto é alterado, e uma propriedade onSubmitEditing que leva uma função a ser chamada quando o texto é enviado.

Por exemplo, digamos que enquanto o usuário digita, você traduz as palavras dele para um idioma diferente. Neste novo idioma, cada palavra é escrita da mesma maneira: 🍕. Portanto, a frase "Olá, Bob" seria traduzida como "🍕 🍕 🍕".

jsx
import React, {useState} from 'react';
+import {Text, TextInput, View} from 'react-native';
+
+const PizzaTranslator = () => {
+  const [text, setText] = useState('');
+  return (
+    <View style={{padding: 10}}>
+      <TextInput
+        style={{height: 40}}
+        placeholder="Type here to translate!"
+        onChangeText={newText => setText(newText)}
+        defaultValue={text}
+      />
+      <Text style={{padding: 10, fontSize: 42}}>
+        {text
+          .split(' ')
+          .map(word => word && '🍕')
+          .join(' ')}
+      </Text>
+    </View>
+  );
+};
+
+export default PizzaTranslator;

Neste exemplo, armazenamos texto no estado, pois ele muda com o tempo.

Há muito mais coisas que você pode querer fazer com uma entrada de texto. Por exemplo, você pode validar o texto interno enquanto o usuário digita. Para exemplos mais detalhados, consulte a documentação do React sobre componentes controlados ou a documentação de referência para TextInput.

A entrada de texto é uma das maneiras pelas quais o usuário interage com o aplicativo. A seguir, vamos examinar outro tipo de entrada e aprender como lidar com toques.

+ + + + \ No newline at end of file diff --git a/vitepress/docs/.vitepress/dist/docs/handling-touches.html b/vitepress/docs/.vitepress/dist/docs/handling-touches.html new file mode 100644 index 0000000..503a851 --- /dev/null +++ b/vitepress/docs/.vitepress/dist/docs/handling-touches.html @@ -0,0 +1,158 @@ + + + + + + Lidando com toques | React Native 0.72 + + + + + + + + + + + + + + + + +
Skip to content

Lidando com toques

Os usuários interagem com aplicativos móveis principalmente por meio do toque. Eles podem usar uma combinação de gestos, como tocar em um botão, rolar uma lista ou ampliar um mapa. O React Native fornece componentes para lidar com todos os tipos de gestos comuns, bem como um sistema abrangente de resposta a gestos para permitir um reconhecimento de gestos mais avançado, mas o componente no qual você provavelmente estará interessado é o botão básico.

Exibindo um botão básico

Button fornece um componente básico de botão que é bem renderizado em todas as plataformas. O exemplo mínimo para exibir um botão é assim:

tsx
<Button
+  onPress={() => {
+    console.log('You tapped the button!');
+  }}
+  title="Press Me"
+/>

Isso renderizará um rótulo azul no iOS e um retângulo arredondado azul com texto claro no Android. Pressionar o botão chamará a função "onPress", que neste caso exibe um pop-up de alerta. Se desejar, você pode especificar um adereço "color" para alterar a cor do seu botão.

Vá em frente e brinque com o componente Button usando o exemplo abaixo. Você pode selecionar em qual plataforma seu aplicativo será visualizado clicando no botão de alternância no canto inferior direito e depois clicando em "Tap to Play" para visualizar o aplicativo.

jsx
import React, {Component} from 'react';
+import {Alert, Button, StyleSheet, View} from 'react-native';
+
+export default class ButtonBasics extends Component {
+  _onPressButton() {
+    Alert.alert('You tapped the button!');
+  }
+
+  render() {
+    return (
+      <View style={styles.container}>
+        <View style={styles.buttonContainer}>
+          <Button onPress={this._onPressButton} title="Press Me" />
+        </View>
+        <View style={styles.buttonContainer}>
+          <Button
+            onPress={this._onPressButton}
+            title="Press Me"
+            color="#841584"
+          />
+        </View>
+        <View style={styles.alternativeLayoutButtonContainer}>
+          <Button onPress={this._onPressButton} title="This looks great!" />
+          <Button onPress={this._onPressButton} title="OK!" color="#841584" />
+        </View>
+      </View>
+    );
+  }
+}
+
+const styles = StyleSheet.create({
+  container: {
+    flex: 1,
+    justifyContent: 'center',
+  },
+  buttonContainer: {
+    margin: 20,
+  },
+  alternativeLayoutButtonContainer: {
+    margin: 20,
+    flexDirection: 'row',
+    justifyContent: 'space-between',
+  },
+});

image

Tocáveis

Se o botão básico não parecer adequado ao seu aplicativo, você poderá criar seu próprio botão usando qualquer um dos componentes "Tocáveis" fornecidos pelo React Native. Os componentes "Tocáveis" oferecem a capacidade de capturar gestos de toque e podem exibir feedback quando um gesto é reconhecido. Esses componentes não fornecem nenhum estilo padrão, portanto, você precisará trabalhar um pouco para que eles tenham uma boa aparência em seu aplicativo.

O componente "Tocável" que você usará dependerá do tipo de feedback que você deseja fornecer:

  • Geralmente, você pode usar TouchableHighlight em qualquer lugar onde usaria um botão ou link na web. O fundo da visualização ficará escurecido quando o usuário pressionar o botão.
  • Você pode considerar usar TouchableNativeFeedback no Android para exibir ondulações de reação na superfície que respondem ao toque do usuário.
  • TouchableOpacity pode ser usado para fornecer feedback, reduzindo a opacidade do botão, permitindo que o fundo seja visto enquanto o usuário pressiona.
  • Se você precisar manipular um gesto de toque, mas não quiser que nenhum feedback seja exibido, use TouchableWithoutFeedback.

Em alguns casos, você pode querer detectar quando um usuário pressiona e mantém uma visualização por um determinado período de tempo. Essas pressões longas podem ser tratadas passando uma função para os adereços onLongPress de qualquer um dos componentes "Tocáveis".

Vamos ver tudo isso em ação:

jsx
import React, {Component} from 'react';
+import {
+  Alert,
+  Platform,
+  StyleSheet,
+  Text,
+  TouchableHighlight,
+  TouchableOpacity,
+  TouchableNativeFeedback,
+  TouchableWithoutFeedback,
+  View,
+} from 'react-native';
+
+export default class Touchables extends Component {
+  _onPressButton() {
+    Alert.alert('You tapped the button!');
+  }
+
+  _onLongPressButton() {
+    Alert.alert('You long-pressed the button!');
+  }
+
+  render() {
+    return (
+      <View style={styles.container}>
+        <TouchableHighlight onPress={this._onPressButton} underlayColor="white">
+          <View style={styles.button}>
+            <Text style={styles.buttonText}>TouchableHighlight</Text>
+          </View>
+        </TouchableHighlight>
+        <TouchableOpacity onPress={this._onPressButton}>
+          <View style={styles.button}>
+            <Text style={styles.buttonText}>TouchableOpacity</Text>
+          </View>
+        </TouchableOpacity>
+        <TouchableNativeFeedback
+          onPress={this._onPressButton}
+          background={
+            Platform.OS === 'android'
+              ? TouchableNativeFeedback.SelectableBackground()
+              : undefined
+          }>
+          <View style={styles.button}>
+            <Text style={styles.buttonText}>
+              TouchableNativeFeedback{' '}
+              {Platform.OS !== 'android' ? '(Android only)' : ''}
+            </Text>
+          </View>
+        </TouchableNativeFeedback>
+        <TouchableWithoutFeedback onPress={this._onPressButton}>
+          <View style={styles.button}>
+            <Text style={styles.buttonText}>TouchableWithoutFeedback</Text>
+          </View>
+        </TouchableWithoutFeedback>
+        <TouchableHighlight
+          onPress={this._onPressButton}
+          onLongPress={this._onLongPressButton}
+          underlayColor="white">
+          <View style={styles.button}>
+            <Text style={styles.buttonText}>Touchable with Long Press</Text>
+          </View>
+        </TouchableHighlight>
+      </View>
+    );
+  }
+}
+
+const styles = StyleSheet.create({
+  container: {
+    paddingTop: 60,
+    alignItems: 'center',
+  },
+  button: {
+    marginBottom: 30,
+    width: 260,
+    alignItems: 'center',
+    backgroundColor: '#2196F3',
+  },
+  buttonText: {
+    textAlign: 'center',
+    padding: 20,
+    color: 'white',
+  },
+});

image

Rolar e deslizar

Os gestos comumente usados em dispositivos com telas tocáveis incluem deslizar e movimentar. Eles permitem que o usuário role por uma lista de itens ou percorra páginas de conteúdo. Para estes, verifique o componente ScrollView Core.

Problemas conhecidos

  • react-native#29308: A área de toque nunca ultrapassa os limites da visualização pai e no Android a margem negativa não é suportada.
+ + + + \ No newline at end of file diff --git a/vitepress/docs/.vitepress/dist/docs/headless-js-android.html b/vitepress/docs/.vitepress/dist/docs/headless-js-android.html new file mode 100644 index 0000000..0f36094 --- /dev/null +++ b/vitepress/docs/.vitepress/dist/docs/headless-js-android.html @@ -0,0 +1,278 @@ + + + + + + Headless JS | React Native 0.72 + + + + + + + + + + + + + + + + +
Skip to content

Headless JS

Headless JS é uma forma de executar tarefas em JavaScript enquanto seu aplicativo está em segundo plano. Ele pode ser usado, por exemplo, para sincronizar dados recentes, lidar com notificações push ou reproduzir música.

A API JS

Uma tarefa é uma função assíncrona que você registra no AppRegistry, semelhante ao registro de aplicativos React:

tsx
import {AppRegistry} from 'react-native';
+AppRegistry.registerHeadlessTask('SomeTaskName', () =>
+  require('SomeTaskName'),
+);

Então, em SomeTaskName.js:

tsx
module.exports = async taskData => {
+  // Fazer coisas
+};

Você pode fazer qualquer coisa em sua tarefa, como solicitações de rede, temporizadores e assim por diante, desde que não toque na interface do usuário. Assim que sua tarefa for concluída (ou seja, a promessa for resolvida), o React Native entrará no modo "pausado" (a menos que haja outras tarefas em execução ou um aplicativo em primeiro plano).

A API da plataforma

Sim, isso ainda requer algum código nativo, mas é bastante limitado. Você precisa estender HeadlessJsTaskService e substituir getTaskConfig, por exemplo:

java
package com.your_application_name;
+
+import android.content.Intent;
+import android.os.Bundle;
+import com.facebook.react.HeadlessJsTaskService;
+import com.facebook.react.bridge.Arguments;
+import com.facebook.react.jstasks.HeadlessJsTaskConfig;
+import javax.annotation.Nullable;
+
+public class MyTaskService extends HeadlessJsTaskService {
+
+  @Override
+  protected @Nullable HeadlessJsTaskConfig getTaskConfig(Intent intent) {
+    Bundle extras = intent.getExtras();
+    if (extras != null) {
+      return new HeadlessJsTaskConfig(
+          "SomeTaskName",
+          Arguments.fromBundle(extras),
+          5000, // timeout in milliseconds for the task
+          false // optional: defines whether or not the task is allowed in foreground. Default is false
+        );
+    }
+    return null;
+  }
+}
kotlin
package com.your_application_name;
+
+import android.content.Intent
+import com.facebook.react.HeadlessJsTaskService
+import com.facebook.react.bridge.Arguments
+import com.facebook.react.jstasks.HeadlessJsTaskConfig
+
+class MyTaskService : HeadlessJsTaskService() {
+    override fun getTaskConfig(intent: Intent): HeadlessJsTaskConfig? {
+        return intent.extras?.let {
+            HeadlessJsTaskConfig(
+                "SomeTaskName",
+                Arguments.fromBundle(it),
+                5000, // timeout for the task
+                false // optional: defines whether or not the task is allowed in foreground.
+                // Default is false
+            )
+        }
+    }
+}

Em seguida, adicione o serviço ao seu arquivo AndroidManifest.xml dentro da tag application:

<service android:name="com.example.MyTaskService" />

Agora, sempre que você iniciar seu serviço, por exemplo. como uma tarefa periódica ou em resposta a algum evento/transmissão do sistema, o JS irá acelerar, executar sua tarefa e, em seguida, diminuir a rotação.

Exemplo:

java
Intent service = new Intent(getApplicationContext(), MyTaskService.class);
+Bundle bundle = new Bundle();
+
+bundle.putString("foo", "bar");
+service.putExtras(bundle);
+
+getApplicationContext().startService(service);
kotlin
val service = Intent(applicationContext, MyTaskService::class.java)
+val bundle = Bundle()
+
+bundle.putString("foo", "bar")
+
+service.putExtras(bundle)
+
+applicationContext.startService(service)

Novas tentativas

Por padrão, a tarefa JS headless não executará nenhuma nova tentativa. Para fazer isso, você precisa criar um HeadlessJsRetryPolicy e lançar um Error específico.

LinearCountingRetryPolicy é uma implementação de HeadlessJsRetryPolicy que permite especificar um número máximo de novas tentativas com um atraso fixo entre cada tentativa. Se isso não atender às suas necessidades, você pode implementar seu próprio HeadlessJsRetryPolicy. Essas políticas podem ser passadas como um argumento extra para o construtor HeadlessJsTaskConfig, por exemplo.

java
HeadlessJsRetryPolicy retryPolicy = new LinearCountingRetryPolicy(
+  3, // Número máximo de novas tentativas
+  1000 // Atraso entre cada nova tentativa
+);
+
+return new HeadlessJsTaskConfig(
+  'SomeTaskName',
+  Arguments.fromBundle(extras),
+  5000,
+  false,
+  retryPolicy
+);
kotlin
val retryPolicy: HeadlessJsTaskRetryPolicy =
+    LinearCountingRetryPolicy(
+        3, // Número máximo de novas tentativas
+        1000 // Atraso entre cada nova tentativa
+    )
+
+return HeadlessJsTaskConfig("SomeTaskName", Arguments.fromBundle(extras), 5000, false, retryPolicy)

Uma nova tentativa só será feita quando um Error específico for lançado. Dentro de uma tarefa JS headless, você pode importar o erro e lançá-lo quando uma nova tentativa for necessária.

Exemplo:

tsx
import {HeadlessJsTaskError} from 'HeadlessJsTask';
+
+module.exports = async taskData => {
+  const condition = ...;
+  if (!condition) {
+    throw new HeadlessJsTaskError();
+  }
+};

Se desejar que todos os erros causem uma nova tentativa, você precisará capturá-los e lançar o erro acima.

Ressalvas

  • Por padrão, seu aplicativo travará se você tentar executar uma tarefa enquanto o aplicativo estiver em primeiro plano. Isso evita que os desenvolvedores dêem um tiro no próprio pé ao trabalhar muito em uma tarefa e tornar a interface do usuário lenta. Você pode passar um quarto argumento booleano para controlar este comportamento.
  • Se você iniciar seu serviço a partir de um BroadcastReceiver, certifique-se de chamar HeadlessJsTaskService.acquireWakeLockNow() antes de retornar de onReceive().

Exemplo de uso

O serviço pode ser iniciado a partir da API Java. Primeiro você precisa decidir quando o serviço deve ser iniciado e implementar sua solução de acordo. Aqui está um exemplo que reage à mudança na conexão de rede.

As linhas a seguir mostram parte do arquivo de manifesto do Android para registrar o receptor de transmissão.

xml
<receiver android:name=".NetworkChangeReceiver" >
+  <intent-filter>
+    <action android:name="android.net.conn.CONNECTIVITY_CHANGE" />
+  </intent-filter>
+</receiver>

O receptor de transmissão então lida com a intenção que foi transmitida na função onReceive. Este é um ótimo lugar para verificar se seu aplicativo está em primeiro plano ou não. Se o aplicativo não estiver em primeiro plano, podemos preparar nossa intenção para ser iniciado, sem informações ou informações adicionais agrupadas usando putExtra (lembre-se de que o pacote pode lidar apenas com valores parcelados). No final o serviço é iniciado e o wakelock é adquirido.

java
import android.app.ActivityManager;
+import android.content.BroadcastReceiver;
+import android.content.Context;
+import android.content.Intent;
+import android.net.ConnectivityManager;
+import android.net.Network;
+import android.net.NetworkCapabilities;
+import android.net.NetworkInfo;
+import android.os.Build;
+
+import com.facebook.react.HeadlessJsTaskService;
+
+public class NetworkChangeReceiver extends BroadcastReceiver {
+
+    @Override
+    public void onReceive(final Context context, final Intent intent) {
+        /**
+          Esta parte será chamada sempre que a conexão de rede for alterada
+          por exemplo. Conectado -> Não conectado
+         **/
+        if (!isAppOnForeground((context))) {
+            /**
+             Iniciaremos nosso serviço e enviaremos informações extras sobre
+             conexões de rede
+             **/
+            boolean hasInternet = isNetworkAvailable(context);
+            Intent serviceIntent = new Intent(context, MyTaskService.class);
+            serviceIntent.putExtra("hasInternet", hasInternet);
+            context.startService(serviceIntent);
+            HeadlessJsTaskService.acquireWakeLockNow(context);
+        }
+    }
+
+    private boolean isAppOnForeground(Context context) {
+        /**
+          Precisamos verificar se o aplicativo está em primeiro plano, caso contrário ele irá travar.
+          https://stackoverflow.com/questions/8489993/check-android-application-is-in-foreground-or-not
+         **/
+        ActivityManager activityManager = (ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE);
+        List<ActivityManager.RunningAppProcessInfo> appProcesses =
+                activityManager.getRunningAppProcesses();
+        if (appProcesses == null) {
+            return false;
+        }
+        final String packageName = context.getPackageName();
+        for (ActivityManager.RunningAppProcessInfo appProcess : appProcesses) {
+            if (appProcess.importance ==
+                    ActivityManager.RunningAppProcessInfo.IMPORTANCE_FOREGROUND &&
+                    appProcess.processName.equals(packageName)) {
+                return true;
+            }
+        }
+        return false;
+    }
+
+    public static boolean isNetworkAvailable(Context context) {
+        ConnectivityManager cm = (ConnectivityManager)
+                context.getSystemService(Context.CONNECTIVITY_SERVICE);
+
+        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
+            Network networkCapabilities = cm.getActiveNetwork();
+
+            if(networkCapabilities == null) {
+                return false;
+            }
+
+            NetworkCapabilities actNw = cm.getNetworkCapabilities(networkCapabilities);
+
+            if(actNw == null) {
+                return false;
+            }
+
+            if(actNw.hasTransport(NetworkCapabilities.TRANSPORT_WIFI) || actNw.hasTransport(NetworkCapabilities.TRANSPORT_CELLULAR) || actNw.hasTransport(NetworkCapabilities.TRANSPORT_ETHERNET)) {
+                return true;
+            }
+
+            return false;
+        }
+
+        // obsoleto na API nível 29
+        NetworkInfo netInfo = cm.getActiveNetworkInfo();
+        return (netInfo != null && netInfo.isConnected());
+    }
+}
kotlin
import android.app.ActivityManager
+import android.app.ActivityManager.RunningAppProcessInfo
+import android.content.BroadcastReceiver
+import android.content.Context
+import android.content.Intent
+import android.net.ConnectivityManager
+import android.net.NetworkCapabilities
+import android.os.Build
+import com.facebook.react.HeadlessJsTaskService
+
+class NetworkChangeReceiver : BroadcastReceiver() {
+    override fun onReceive(context: Context, intent: Intent?) {
+        /**
+         * Esta parte será chamada sempre que a conexão de rede for alterada, por exemplo. Conectado -> Não Conectado
+         */
+        if (!isAppOnForeground(context)) {
+            /** Iniciaremos nosso serviço e enviaremos informações extras sobre conexões de rede */
+            val hasInternet = isNetworkAvailable(context)
+            val serviceIntent = Intent(context, MyTaskService::class.java)
+            serviceIntent.putExtra("hasInternet", hasInternet)
+            context.startService(serviceIntent)
+            HeadlessJsTaskService.acquireWakeLockNow(context)
+        }
+    }
+
+    private fun isAppOnForeground(context: Context): Boolean {
+        /**
+         * Precisamos verificar se o aplicativo está em primeiro plano, caso contrário ele irá travar.
+         * https://stackoverflow.com/questions/8489993/check-android-application-is-in-foreground-or-not
+         */
+        val activityManager = context.getSystemService(Context.ACTIVITY_SERVICE) as ActivityManager
+        val appProcesses = activityManager.runningAppProcesses ?: return false
+        val packageName: String = context.getPackageName()
+        for (appProcess in appProcesses) {
+            if (appProcess.importance == RunningAppProcessInfo.IMPORTANCE_FOREGROUND &&
+                    appProcess.processName == packageName
+            ) {
+                return true
+            }
+        }
+        return false
+    }
+
+    companion object {
+        fun isNetworkAvailable(context: Context): Boolean {
+            val cm = context.getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager
+            var result = false
+
+            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
+                val networkCapabilities = cm.activeNetwork ?: return false
+
+                val actNw = cm.getNetworkCapabilities(networkCapabilities) ?: return false
+
+                result =
+                    when {
+                        actNw.hasTransport(NetworkCapabilities.TRANSPORT_WIFI) -> true
+                        actNw.hasTransport(NetworkCapabilities.TRANSPORT_CELLULAR) -> true
+                        actNw.hasTransport(NetworkCapabilities.TRANSPORT_ETHERNET) -> true
+                        else -> false
+                    }
+
+                return result
+            } else {
+                cm.run {
+                    // obsoleto na API nível 29
+                    cm.activeNetworkInfo?.run {
+                        result =
+                            when (type) {
+                                ConnectivityManager.TYPE_WIFI -> true
+                                ConnectivityManager.TYPE_MOBILE -> true
+                                ConnectivityManager.TYPE_ETHERNET -> true
+                                else -> false
+                            }
+                    }
+                }
+            }
+            return result
+        }
+    }
+}
+ + + + \ No newline at end of file diff --git a/vitepress/docs/.vitepress/dist/docs/height-and-width.html b/vitepress/docs/.vitepress/dist/docs/height-and-width.html new file mode 100644 index 0000000..dc42fd2 --- /dev/null +++ b/vitepress/docs/.vitepress/dist/docs/height-and-width.html @@ -0,0 +1,106 @@ + + + + + + Altura e Largura | React Native 0.72 + + + + + + + + + + + + + + + + +
Skip to content

Altura e Largura

A altura e a largura de um componente determinam seu tamanho na tela.

Dimensões fixas

A maneira geral de definir as dimensões de um componente é adicionando uma width (largura) e uma height (altura) fixas ao estilo. Todas as dimensões no React Native não têm unidade e representam pixels independentes de densidade.

jsx
import React from 'react';
+import {View} from 'react-native';
+
+const FixedDimensionsBasics = () => {
+  return (
+    <View>
+      <View
+        style={{
+          width: 50,
+          height: 50,
+          backgroundColor: 'powderblue',
+        }}
+      />
+      <View
+        style={{
+          width: 100,
+          height: 100,
+          backgroundColor: 'skyblue',
+        }}
+      />
+      <View
+        style={{
+          width: 150,
+          height: 150,
+          backgroundColor: 'steelblue',
+        }}
+      />
+    </View>
+  );
+};
+
+export default FixedDimensionsBasics;

image

Definir dimensões desta forma é comum para componentes cujo tamanho deve sempre ser fixado em um número de pontos e não calculado com base no tamanho da tela.

CUIDADO

Não existe um mapeamento universal de pontos para unidades físicas de medida. Isso significa que um componente com dimensões fixas pode não ter o mesmo tamanho físico em diferentes dispositivos e tamanhos de tela. No entanto, essa diferença é imperceptível na maioria dos casos de uso.

Dimensões flexíveis

Use flex no estilo de um componente para que o componente se expanda e diminua dinamicamente com base no espaço disponível. Normalmente você usará flex: 1, que diz a um componente para preencher todo o espaço disponível, compartilhado igualmente entre outros componentes com o mesmo pai. Quanto maior for a flexibilidade fornecida, maior será a proporção de espaço que um componente ocupará em comparação com seus irmãos.

INFORMAÇÕES

Um componente só pode se expandir para preencher o espaço disponível se seu pai tiver dimensões maiores que 0. Se um pai não tiver width e height fixas ou flex, o pai terá dimensões de 0 e os filhos flexíveis não serão visíveis.

jsx
import React from 'react';
+import {View} from 'react-native';
+
+const FlexDimensionsBasics = () => {
+  return (
+    //Tente remover o `flex: 1` na visualização pai.
+    // O pai não terá dimensões, portanto os filhos não poderão expandir.
+    // E se você adicionar `height: 300` em vez de `flex: 1`?
+    <View style={{flex: 1}}>
+      <View style={{flex: 1, backgroundColor: 'powderblue'}} />
+      <View style={{flex: 2, backgroundColor: 'skyblue'}} />
+      <View style={{flex: 3, backgroundColor: 'steelblue'}} />
+    </View>
+  );
+};
+
+export default FlexDimensionsBasics;

image

Depois de controlar o tamanho de um componente, a próxima etapa é aprender como organizá-lo na tela.

Dimensões percentuais

Se quiser preencher uma determinada parte da tela, mas não quiser usar o layout flexível, você pode usar valores percentuais no estilo do componente. Semelhante às dimensões flexíveis, as dimensões percentuais exigem um pai com um tamanho definido.

jsx
import React from 'react';
+import {View} from 'react-native';
+
+const PercentageDimensionsBasics = () => {
+  // Tente remover `height: '100%'` na visualização pai.
+  // O pai não terá dimensões, portanto os filhos não poderão expandir.
+  return (
+    <View style={{height: '100%'}}>
+      <View
+        style={{
+          height: '15%',
+          backgroundColor: 'powderblue',
+        }}
+      />
+      <View
+        style={{
+          width: '66%',
+          height: '35%',
+          backgroundColor: 'skyblue',
+        }}
+      />
+      <View
+        style={{
+          width: '33%',
+          height: '50%',
+          backgroundColor: 'steelblue',
+        }}
+      />
+    </View>
+  );
+};
+
+export default PercentageDimensionsBasics;

image

+ + + + \ No newline at end of file diff --git a/vitepress/docs/.vitepress/dist/docs/images.html b/vitepress/docs/.vitepress/dist/docs/images.html new file mode 100644 index 0000000..53cecf4 --- /dev/null +++ b/vitepress/docs/.vitepress/dist/docs/images.html @@ -0,0 +1,86 @@ + + + + + + Imagens | React Native 0.72 + + + + + + + + + + + + + + + + +
Skip to content

Imagens

Recursos de imagem estática

React Native fornece uma maneira unificada de gerenciar imagens e outros ativos de mídia em seus aplicativos Android e iOS. Para adicionar uma imagem estática ao seu aplicativo, coloque-a em algum lugar da árvore do código-fonte e referencie-a assim:

jsx
<Image source={require('./my-icon.png')} />

O nome da imagem é resolvido da mesma forma que os módulos JS são resolvidos. No exemplo acima, o bundler procurará my-icon.png na mesma pasta do componente que o requer.

Você pode usar os sufixos @2x e @3x para fornecer imagens para diferentes densidades de tela. Se você tiver a seguinte estrutura de arquivos:

.
+├── button.js
+└── img
+    ├── check.png
+    ├── check@2x.png
+    └── check@3x.png

...e o código button.js contém:

jsx
<Image source={require('./img/check.png')} />

...o empacotador agrupará e exibirá a imagem correspondente à densidade da tela do dispositivo. Por exemplo, check@2x.png será usado em um iPhone 7, enquanto check@3x.png será usado em um iPhone 7 Plus ou Nexus 5. Se não houver imagem que corresponda à densidade da tela, a melhor opção mais próxima será ser selecionado.

No Windows, talvez seja necessário reiniciar o empacotador se você adicionar novas imagens ao seu projeto.

Aqui estão alguns benefícios que você obtém:

  1. Mesmo sistema em Android e iOS.
  2. As imagens ficam na mesma pasta do seu código JavaScript. Os componentes são independentes.
  3. Nenhum namespace global, ou seja, você não precisa se preocupar com colisões de nomes.
  4. Somente as imagens realmente usadas serão empacotadas em seu aplicativo.
  5. Adicionar e alterar imagens não requer recompilação do aplicativo, você pode atualizar o simulador normalmente.
  6. O empacotador conhece as dimensões da imagem, não há necessidade de duplicá-la no código.
  7. As imagens podem ser distribuídas por meio de pacotes npm.

Para que isso funcione, o nome da imagem em require deve ser conhecido estaticamente.

// BOM
+<Image source={require('./my-icon.png')} />;
+
+// RUIM
+const icon = this.props.active
+  ? 'my-icon-active'
+  : 'my-icon-inactive';
+<Image source={require('./' + icon + '.png')} />;
+
+// BOM
+const icon = this.props.active
+  ? require('./my-icon-active.png')
+  : require('./my-icon-inactive.png');
+<Image source={icon} />;

Observe que as fontes de imagem exigidas desta forma incluem informações de tamanho (largura, altura) da imagem. Se você precisar dimensionar a imagem dinamicamente (ou seja, via flex), pode ser necessário definir manualmente {width: undefined, height: undefined} no atributo de estilo.

Recursos estáticos sem imagem

A sintaxe require descrita acima também pode ser usada para incluir estaticamente arquivos de áudio, vídeo ou documentos em seu projeto. Os tipos de arquivo mais comuns são suportados, incluindo .mp3, .wav, .mp4, .mov, .html e .pdf. Consulte os padrões do bundler para obter a lista completa.

Você pode adicionar suporte para outros tipos adicionando uma opção de resolvedor assetsExts em sua configuração Metro.

Uma ressalva é que os vídeos devem usar posicionamento absoluto em vez de flexGrow, uma vez que as informações de tamanho não são transmitidas atualmente para ativos que não sejam de imagem. Essa limitação não ocorre para vídeos vinculados diretamente ao Xcode ou à pasta Assets para Android.

Imagens dos recursos do aplicativo híbrido

Se você estiver construindo um aplicativo híbrido (algumas UIs no React Native, algumas UIs no código da plataforma), você ainda poderá usar imagens que já estão incluídas no aplicativo.

Para imagens incluídas nos catálogos de ativos do Xcode ou na pasta drawable do Android, use o nome da imagem sem a extensão:

jsx
<Image
+  source={{uri: 'app_icon'}}
+  style={{width: 40, height: 40}}
+/>

Para imagens na pasta de ativos do Android, use o esquema assets:/:

jsx
<Image
+  source={{uri: 'asset:/app_icon.png'}}
+  style={{width: 40, height: 40}}
+/>

Essas abordagens não fornecem verificações de segurança. Cabe a você garantir que essas imagens estejam disponíveis no aplicativo. Além disso, você deve especificar as dimensões da imagem manualmente.

Imagens de rede

Muitas das imagens que você exibirá em seu aplicativo não estarão disponíveis em tempo de compilação ou você desejará carregar algumas dinamicamente para manter o tamanho binário baixo. Ao contrário dos recursos estáticos, você precisará especificar manualmente as dimensões da sua imagem. É altamente recomendável que você use https também para atender aos requisitos de segurança de transporte de aplicativos no iOS.

jsx
// BOM
+<Image source={{uri: 'https://reactjs.org/logo-og.png'}}
+       style={{width: 400, height: 400}} />
+
+// RUIM
+<Image source={{uri: 'https://reactjs.org/logo-og.png'}} />

Solicitações de rede para imagens

Se você quiser definir coisas como HTTP-Verb, Headers ou Body junto com a solicitação de imagem, você pode fazer isso definindo estas propriedades no objeto de origem:

jsx
<Image
+  source={{
+    uri: 'https://reactjs.org/logo-og.png',
+    method: 'POST',
+    headers: {
+      Pragma: 'no-cache',
+    },
+    body: 'Your Body goes here',
+  }}
+  style={{width: 400, height: 400}}
+/>

URI com dados

Às vezes, você pode obter dados de imagem codificados de uma chamada da API REST. Você pode usar o esquema uri 'data:' para usar essas imagens. Da mesma forma que para os recursos de rede, você precisará especificar manualmente as dimensões da sua imagem.

INFORMAÇÕES Isso é recomendado apenas para imagens muito pequenas e dinâmicas, como ícones em uma lista de um banco de dados.

jsx
// inclua pelo menos largura e altura!
+<Image
+  style={{
+    width: 51,
+    height: 51,
+    resizeMode: 'contain',
+  }}
+  source={{
+    uri: 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADMAAAAzCAYAAAA6oTAqAAAAEXRFWHRTb2Z0d2FyZQBwbmdjcnVzaEB1SfMAAABQSURBVGje7dSxCQBACARB+2/ab8BEeQNhFi6WSYzYLYudDQYGBgYGBgYGBgYGBgYGBgZmcvDqYGBgmhivGQYGBgYGBgYGBgYGBgYGBgbmQw+P/eMrC5UTVAAAAABJRU5ErkJggg==',
+  }}
+/>

Controle de cache (somente iOS)

Em alguns casos, você pode querer exibir uma imagem apenas se ela já estiver no cache local, ou seja, um espaço reservado de baixa resolução até que uma resolução mais alta esteja disponível. Em outros casos, você não se importa se a imagem está desatualizada e está disposto a exibi-la para economizar largura de banda. A propriedade de origem do cache fornece controle sobre como a camada de rede interage com o cache.

  • default: use a estratégia padrão das plataformas nativas.
  • reload: os dados do URL serão carregados da fonte de origem. Nenhum dado de cache existente deve ser usado para atender a uma solicitação de carregamento de URL.
  • force-cache: Os dados existentes em cache serão usados para atender à solicitação, independentemente de sua idade ou data de expiração. Se não houver dados existentes no cache correspondente à solicitação, os dados serão carregados da fonte de origem.
  • only-if-cached: os dados de cache existentes serão usados para atender a uma solicitação, independentemente de sua idade ou data de expiração. Se não houver dados existentes no cache correspondentes a uma solicitação de carregamento de URL, nenhuma tentativa será feita para carregar os dados da fonte de origem e o carregamento será considerado como tendo falhado.
jsx
<Image
+  source={{
+    uri: 'https://reactjs.org/logo-og.png',
+    cache: 'only-if-cached',
+  }}
+  style={{width: 400, height: 400}}
+/>

Imagens do sistema de arquivos local

Consulte CameraRoll para obter um exemplo de uso de recursos locais que estão fora de Images.xcassets.

Melhor imagem do rolo da câmera

O iOS salva vários tamanhos para a mesma imagem no rolo da câmera. É muito importante escolher aquele que seja o mais próximo possível por motivos de desempenho. Você não gostaria de usar a imagem de 3264x2448 com qualidade total como fonte ao exibir uma miniatura de 200x200. Se houver uma correspondência exata, o React Native irá escolhê-la, caso contrário, usará a primeira que for pelo menos 50% maior para evitar desfoque ao redimensionar de um tamanho próximo. Tudo isso é feito por padrão, então você não precisa se preocupar em escrever o código tedioso (e sujeito a erros) para fazer isso sozinho.

Por que não dimensionar tudo automaticamente?

No navegador, se você não fornecer um tamanho para uma imagem, o navegador renderizará um elemento 0x0, fará o download da imagem e, em seguida, renderizará a imagem com base no tamanho correto. O grande problema com esse comportamento é que sua IU vai pular conforme as imagens são carregadas, o que torna a experiência do usuário muito ruim. Isso é chamado de mudança cumulativa de layout.

No React Native esse comportamento não é implementado intencionalmente. É mais trabalhoso para o desenvolvedor saber antecipadamente as dimensões (ou proporção) da imagem remota, mas acreditamos que isso leva a uma melhor experiência do usuário. Imagens estáticas carregadas do pacote de aplicativos por meio da sintaxe require('./my-icon.png') podem ser dimensionadas automaticamente porque suas dimensões estão disponíveis imediatamente no momento da montagem.

Por exemplo, o resultado de require('./my-icon.png') pode ser:

jsx
{"__packager_asset":true,"uri":"my-icon.png","width":591,"height":573}

Fonte como um objeto

No React Native, uma decisão interessante é que o atributo src é denominado source e não aceita uma string, mas um objeto com um atributo uri.

jsx
<Image source={{uri: 'something.jpg'}} />

Do lado da infraestrutura, a razão é que nos permite anexar metadados a este objeto. Por exemplo, se você estiver usando require('./my-icon.png'), adicionamos informações sobre sua localização e tamanho reais (não confie neste fato, pois pode mudar no futuro!). Isso também é uma prova futura, por exemplo, podemos querer oferecer suporte a sprites em algum momento, em vez de gerar {uri: ...}, podemos gerar {uri: ..., crop: {left: 10, top: 50, width: 20, height: 40}} e suporta sprites de forma transparente em todos os sites de chamada existentes.

Do lado do usuário, isso permite anotar o objeto com atributos úteis, como a dimensão da imagem, para calcular o tamanho em que ela será exibida. Sinta-se à vontade para usá-lo como sua estrutura de dados para armazenar mais informações sobre sua imagem .

Imagem de fundo via aninhamento

Uma solicitação de recurso comum de desenvolvedores familiarizados com a web é a imagem de fundo. Para lidar com esse caso de uso, você pode usar o componente <ImageBackground>, que possui os mesmos adereços de <Image>, e adicionar quaisquer filhos que você gostaria de colocar em camadas sobre ele.

Talvez você não queira usar <ImageBackground> em alguns casos, pois a implementação é básica. Consulte a documentação do <ImageBackground> para obter mais informações e crie seu próprio componente personalizado quando necessário.

jsx
return (
+  <ImageBackground source={...} style={{width: '100%', height: '100%'}}>
+    <Text>Inside</Text>
+  </ImageBackground>
+);

Observe que você deve especificar alguns atributos de estilo de largura e altura.

Estilo arredondado do iOS

Observe que as seguintes propriedades de estilo de raio de borda específicas de canto podem ser ignoradas pelo componente de imagem do iOS:

  • borderTopLeftRadius
  • borderTopRightRadius
  • borderBottomLeftRadius
  • borderBottomRightRadius

Decodificação fora do thread

A decodificação de imagens pode levar mais do que um quadro. Esta é uma das principais fontes de queda de quadros na web porque a decodificação é feita na thread principal. No React Native, a decodificação da imagem é feita em uma thread diferente. Na prática, você já precisa cuidar do caso quando a imagem ainda não foi baixada, portanto, exibir o espaço reservado para mais alguns quadros enquanto ela é decodificada não requer nenhuma alteração de código.

Configurando limites de cache de imagens do iOS

No iOS, expomos uma API para substituir os limites de cache de imagem padrão do React Native. Isso deve ser chamado de dentro do seu código AppDelegate nativo (por exemplo, dentro de didFinishLaunchingWithOptions).

RCTSetImageCacheLimits(4*1024*1024, 200*1024*1024);

Parâmetros

NOMETIPOOBRIGATÓRIODESCRIÇÃO
imageSizeLimitnumberSimLimite de tamanho do cache de imagem.
totalCostLimitnumberSimLimite total de custo do cache.

No exemplo de código acima, o limite de tamanho da imagem é definido como 4 MB e o limite de custo total é definido como 200 MB.

+ + + + \ No newline at end of file diff --git a/vitepress/docs/.vitepress/dist/docs/integration-with-android-fragment.html b/vitepress/docs/.vitepress/dist/docs/integration-with-android-fragment.html new file mode 100644 index 0000000..4e6e26d --- /dev/null +++ b/vitepress/docs/.vitepress/dist/docs/integration-with-android-fragment.html @@ -0,0 +1,143 @@ + + + + + + Integração com um fragmento Android | React Native 0.72 + + + + + + + + + + + + + + + + +
Skip to content

Integração com um fragmento Android

O guia para integração com aplicativos existentes detalha como integrar um aplicativo React Native de tela inteira em um aplicativo Android existente como uma Activity. Usar componentes React Native em Fragments em um aplicativo existente requer alguma configuração adicional. A vantagem disso é que permite que um aplicativo nativo integre componentes React Native junto com fragmentos nativos em uma Activity.

1. Adicione React Native ao seu aplicativo

Siga o guia de integração com aplicativos existentes até a seção Integração de código. Continue seguindo a Etapa 1. Crie um arquivo index.android.js e a Etapa 2. Adicione seu código React Native desta seção.

2. Integrando seu aplicativo com um fragmento React Native

Você pode renderizar seu componente React Native em um Fragment em vez de uma Activity React Native em tela inteira. O componente pode ser denominado “screen” ou “fragment” e funcionará da mesma maneira que um fragmento do Android, provavelmente contendo componentes filhos. Esses componentes podem ser colocados em uma pasta /fragments e os componentes filhos usados para compor o fragmento podem ser colocados em uma pasta /components.

Você precisará implementar a interface ReactApplication em sua classe principal do aplicativo Java/Kotlin. Se você criou um novo projeto no Android Studio com uma Activity padrão, precisará criar uma nova classe (por exemplo, MyReactApplication.java ou MyReactApplication.kt). Se for uma classe existente, você poderá encontrar esta classe principal em seu arquivo AndroidManifest.xml. Sob a tag <application /> você deverá ver uma propriedade android:name, por exemplo. android:name=".MyReactApplication". Este valor é a classe que você deseja implementar e para a qual fornecer os métodos necessários.

Certifique-se de que sua classe principal Application implemente ReactApplication:

java
public class MyReactApplication extends Application implements ReactApplication {...}
kt
class MyReactApplication: Application(), ReactApplication {...}

Substitua os métodos necessários getUseDeveloperSupport, getPackages e getReactNativeHost:

java
public class MyReactApplication extends Application implements ReactApplication {
+    @Override
+    public void onCreate() {
+        super.onCreate();
+        SoLoader.init(this, false);
+    }
+
+    private final ReactNativeHost mReactNativeHost = new DefaultReactNativeHost(this) {
+        @Override
+        public boolean getUseDeveloperSupport() {
+            return BuildConfig.DEBUG;
+        }
+
+        protected List<ReactPackage> getPackages() {
+            List<ReactPackage> packages = new PackageList(this).getPackages();
+            // Pacotes que ainda não podem ser vinculados automaticamente podem ser adicionados manualmente aqui
+            return packages;
+        }
+    };
+
+    @Override
+    public ReactNativeHost getReactNativeHost() {
+        return mReactNativeHost;
+    }
+}
kotlin
class MyReactApplication : Application(), ReactApplication {
+    override fun onCreate() {
+        super.onCreate()
+        SoLoader.init(this, false)
+    }
+    private val reactNativeHost =
+        object : DefaultReactNativeHost(this) {
+            override fun getUseDeveloperSupport() = BuildConfig.DEBUG
+            override fun getPackages(): List<ReactPackage> {
+                val packages = PackageList(this).getPackages().toMutableList()
+                // Pacotes que ainda não podem ser vinculados automaticamente podem ser adicionados manualmente aqui
+                return packages
+            }
+        }
+    override fun getReactNativeHost(): ReactNativeHost = reactNativeHost
+}

Se você estiver usando o Android Studio, use Alt + Enter para adicionar todas as importações ausentes na sua classe. Alternativamente, estas são as importações necessárias para incluir manualmente:

java
import android.app.Application;
+
+import com.facebook.react.PackageList;
+import com.facebook.react.ReactApplication;
+import com.facebook.react.ReactNativeHost;
+import com.facebook.react.ReactPackage;
+import com.facebook.react.defaults.DefaultReactNativeHost;
+import com.facebook.soloader.SoLoader;
+
+import java.util.List;
kotlin
import android.app.Application
+
+import com.facebook.react.PackageList
+import com.facebook.react.ReactApplication
+import com.facebook.react.ReactNativeHost
+import com.facebook.react.ReactPackage
+import com.facebook.react.defaults.DefaultReactNativeHost
+import com.facebook.soloader.SoLoader

Execute uma operação "Sync Project files with Gradle".

3. Adicione um FrameLayout para o fragmento React Native

Agora você adicionará seu fragmento React Native a uma Activity. Para um novo projeto, esta Activity será MainActivity, mas pode ser qualquer activity e mais fragmentos podem ser adicionados a Activity à medida que você integra mais componentes React Native em seu aplicativo.

Primeiro adicione o React Native Fragment ao layout da sua Activity. Por exemplo main_activity.xml na pasta res/layouts`.

Adicione um <FrameLayout> com 'id`, largura e altura. Este é o layout no qual você encontrará e renderizará seu fragmento React Native.

xml
<FrameLayout
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    android:id="@+id/reactNativeFragment"
+    android:layout_width="match_parent"
+    android:layout_height="match_parent" />

4. Adicionar um fragmento React Native ao FrameLayout

Para adicionar seu React Native Fragment ao seu layout, você precisa ter uma Activity. Conforme mencionado em um novo projeto, esta será a MainActivity. Nesta Activity adicione um botão e um ouvinte de evento. Ao clicar no botão, você renderizará seu fragmento React Native.

Modifique o layout da sua Activity para adicionar o botão:

xml
<Button
+    android:layout_margin="10dp"
+    android:id="@+id/button"
+    android:layout_width="match_parent"
+    android:layout_height="wrap_content"
+    android:text="Show react fragment" />

Agora, em sua classe Activity (por exemplo, MainActivity.java ou MainActivity.kt), você precisa adicionar um OnClickListener para o botão, instanciar seu ReactFragment e adicioná-lo ao layout do quadro.

Adicione o campo do botão ao topo da sua Activity:

java
private Button mButton;
kotlin
private lateinit var button: Button

Atualize o método onCreate da sua Activity da seguinte forma:

java
@Override
+protected void onCreate(Bundle savedInstanceState) {
+    super.onCreate(savedInstanceState);
+    setContentView(R.layout.main_activity);
+
+    mButton = findViewById(R.id.button);
+    mButton.setOnClickListener(new View.OnClickListener() {
+        public void onClick(View v) {
+            Fragment reactNativeFragment = new ReactFragment.Builder()
+                    .setComponentName("HelloWorld")
+                    .setLaunchOptions(getLaunchOptions("test message"))
+                    .build();
+
+            getSupportFragmentManager()
+                    .beginTransaction()
+                    .add(R.id.reactNativeFragment, reactNativeFragment)
+                    .commit();
+
+        }
+    });
+}
kotlin
override fun onCreate(savedInstanceState: Bundle) {
+    super.onCreate(savedInstanceState)
+    setContentView(R.layout.main_activity)
+    button = findViewById<Button>(R.id.button)
+    button.setOnClickListener {
+        val reactNativeFragment = ReactFragment.Builder()
+                .setComponentName("HelloWorld")
+                .setLaunchOptions(getLaunchOptions("test message"))
+                .build()
+        getSupportFragmentManager()
+                .beginTransaction()
+                .add(R.id.reactNativeFragment, reactNativeFragment)
+                .commit()
+    }
+}

No código acima, Fragment reactNativeFragment = new ReactFragment.Builder() cria o ReactFragment e getSupportFragmentManager().beginTransaction().add() adiciona o Fragment ao Frame Layout.`

Se você estiver usando um kit inicial para React Native, substitua a string "HelloWorld" pela que está em seu arquivo index.js ou index.android.js (é o primeiro argumento para o método AppRegistry.registerComponent()).

Adicione o método getLaunchOptions que permitirá que você passe acessórios para o seu componente. Isso é opcional e você pode remover setLaunchOptions se não precisar passar nenhum props.

java
private Bundle getLaunchOptions(String message) {
+    Bundle initialProperties = new Bundle();
+    initialProperties.putString("message", message);
+    return initialProperties;
+}
kotlin
private fun getLaunchOptions(message: String) = Bundle().apply {
+    putString("message", message)
+}

Adicione todas as importações ausentes na sua classe Activity. Tenha cuidado ao usar o BuildConfig do seu pacote e não o do pacote Facebook! Alternativamente, estas são as importações necessárias para incluir manualmente:

java
import android.app.Application;
+
+import com.facebook.react.ReactApplication;
+import com.facebook.react.ReactNativeHost;
+import com.facebook.react.ReactPackage;
+import com.facebook.react.shell.MainReactPackage;
+import com.facebook.soloader.SoLoader;
kotlin
import android.app.Application
+
+import com.facebook.react.ReactApplication
+import com.facebook.react.ReactNativeHost
+import com.facebook.react.ReactPackage
+import com.facebook.react.shell.MainReactPackage
+import com.facebook.soloader.SoLoader

Execute uma operação "Sync Project files with Gradle".

5. Teste sua integração

Certifique-se de executar o yarn para instalar suas dependências react-native e executar o yarn native para iniciar o empacotador metro. Execute seu aplicativo Android no Android Studio e ele deverá carregar o código JavaScript do servidor de desenvolvimento e exibi-lo em seu fragmento React Native na Activity.

6. Configuração adicional – Módulos nativos

Pode ser necessário chamar o código Java/Kotlin existente do seu componente react. Os módulos nativos permitem que você chame código nativo e execute métodos em seu aplicativo nativo. Siga a configuração aqui native-modules-android

+ + + + \ No newline at end of file diff --git a/vitepress/docs/.vitepress/dist/docs/integration-with-existing-apps.html b/vitepress/docs/.vitepress/dist/docs/integration-with-existing-apps.html new file mode 100644 index 0000000..88c7d82 --- /dev/null +++ b/vitepress/docs/.vitepress/dist/docs/integration-with-existing-apps.html @@ -0,0 +1,27 @@ + + + + + + Integração com aplicativos existentes | React Native 0.72 + + + + + + + + + + + + + + + + +
Skip to content

Integração com aplicativos existentes

React Native é ótimo quando você inicia um novo aplicativo móvel do zero. No entanto, também funciona bem para adicionar uma visualização única ou fluxo de usuário a aplicativos nativos existentes. Com algumas etapas, você pode adicionar novos recursos, telas, visualizações, etc. baseados no React Native.

As etapas específicas são diferentes dependendo da plataforma que você está almejando.

+ + + + \ No newline at end of file diff --git a/vitepress/docs/.vitepress/dist/docs/integration-with-existing-apps/android-java.html b/vitepress/docs/.vitepress/dist/docs/integration-with-existing-apps/android-java.html new file mode 100644 index 0000000..bbffb48 --- /dev/null +++ b/vitepress/docs/.vitepress/dist/docs/integration-with-existing-apps/android-java.html @@ -0,0 +1,186 @@ + + + + + + Android (Java) | React Native 0.72 + + + + + + + + + + + + + + + + +
Skip to content

Android (Java)

Conceitos chave

Os segredos para integrar componentes React Native em seu aplicativo Android são:

  1. Configure as dependências e a estrutura de diretórios do React Native.
  2. Desenvolva seus componentes React Native em JavaScript.
  3. Adicione um ReactRootView ao seu aplicativo Android. Esta visualização servirá como contêiner para seu componente React Native.
  4. Inicie o servidor React Native e execute seu aplicativo nativo.
  5. Verifique se o aspecto do React Native no seu aplicativo funciona conforme o esperado.

Pré-requisitos

Siga o início rápido do React Native CLI no guia de configuração do ambiente para configurar seu ambiente de desenvolvimento para construir aplicativos React Native para Android.

1. Configure a estrutura de diretórios

Para garantir uma experiência tranquila, crie uma nova pasta para seu projeto React Native integrado e copie seu projeto Android existente para uma subpasta /android.

2. Instale dependências JavaScript

Vá para o diretório raiz do seu projeto e crie um novo arquivo package.json com o seguinte conteúdo:

json
{
+  "name": "MyReactNativeApp",
+  "version": "0.0.1",
+  "private": true,
+  "scripts": {
+    "start": "react-native start"
+  }
+}

Em seguida, instale os pacotes react e react-native. Abra um terminal ou prompt de comando, navegue até o diretório com seu arquivo package.json e execute:

bash
npm install react-native
bash
yarn add react-native

Isso imprimirá uma mensagem semelhante à seguinte (role para cima na saída do yarn para vê-la):

bash
warning "react-native@0.70.5" has unmet peer dependency "react@18.1.0"

Tudo bem, significa que também precisamos instalar o React:

bash
npm install react@version_printed_above
bash
yarn add react@version_printed_above

Yarn/npm criou uma nova pasta chamada /node_modules. Esta pasta armazena todas as dependências JavaScript necessárias para construir seu projeto.

Adicione node_modules/ ao seu arquivo .gitignore.

Adicionando React Native ao seu aplicativo

Configurando o Gradle

React Native usa o plugin React Native Gradle para configurar suas dependências e configuração do projeto.

Primeiro, vamos editar seu arquivo settings.gradle adicionando esta linha:

includeBuild('../node_modules/@react-native/gradle-plugin')

Então você precisa abrir seu build.gradle de nível superior e incluir esta linha:

buildscript {
+    repositories {
+        google()
+        mavenCentral()
+    }
+    dependencies {
+        classpath("com.android.tools.build:gradle:7.3.1")
+        classpath("com.facebook.react:react-native-gradle-plugin")
+    }
+}

Isso garante que o plugin React Native Gradle esteja disponível em seu projeto. Por fim, adicione essas linhas ao arquivo build.gradle do seu aplicativo (é um arquivo build.gradle diferente dentro da pasta do seu aplicativo):

apply plugin: "com.android.application"
+apply plugin: "com.facebook.react"
+
+repositories {
+    mavenCentral()
+}
+
+dependencies {
+    // Outras dependências aqui
+    implementation "com.facebook.react:react-android"
+    implementation "com.facebook.react:hermes-android"
+}

Essas dependências estão disponíveis em mavenCentral(), portanto, certifique-se de tê-las definidas no bloco repositories{}.

INFORMAÇÕES

Intencionalmente não especificamos a versão para essas dependências de implementation, pois o React Native Gradle Plugin cuidará disso. Se você não usar o plugin React Native Gradle, terá que especificar a versão manualmente.

Habilitar autolinking de módulos nativos

Para usar o poder do autolinking, temos que aplicá-lo em alguns lugares. Primeiro adicione a seguinte entrada em settings.gradle:

apply from: file("../node_modules/@react-native-community/cli-platform-android/native_modules.gradle"); applyNativeModulesSettingsGradle(settings)

Em seguida, adicione a seguinte entrada na parte inferior do app/build.gradle:

apply from: file("../../node_modules/@react-native-community/cli-platform-android/native_modules.gradle"); applyNativeModulesAppBuildGradle(project)

Configurando permissões

Em seguida, certifique-se de ter permissão de Internet em seu AndroidManifest.xml:

xml
<uses-permission android:name="android.permission.INTERNET" />

Se você precisar acessar DevSettingsActivity, adicione ao seu AndroidManifest.xml:

xml
<activity android:name="com.facebook.react.devsupport.DevSettingsActivity" />

Isso só é usado no modo de desenvolvimento ao recarregar o JavaScript do servidor de desenvolvimento, portanto, você pode removê-lo nas compilações de lançamento, se necessário.

Tráfego de texto simples (nível de API 28+)

Texto não criptografado

A partir do Android 9 (API de nível 28), o tráfego de texto não criptografado é desativado por padrão; isso evita que seu aplicativo se conecte ao empacotador Metro. As alterações abaixo permitem tráfego de texto não criptografado em compilações de depuração.

  1. Aplique a opção usesCleartextTraffic ao seu Debug AndroidManifest.xml
xml
<!-- ... -->
+<application
+  android:usesCleartextTraffic="true" tools:targetApi="28" >
+  <!-- ... -->
+</application>
+<!-- ... -->

Isso não é necessário para compilações de versão.

Para saber mais sobre a configuração de segurança de rede e a política de tráfego de texto não criptografado, consulte este link.

Integração de código

Agora vamos modificar o aplicativo Android nativo para integrar o React Native.

O componente React Native

O primeiro código que escreveremos é o código React Native real para a nova tela "High Score" que será integrada em nosso aplicativo.

1. Crie um arquivo index.js

Primeiro, crie um arquivo index.js vazio na raiz do seu projeto React Native.

index.js é o ponto de partida para aplicativos React Native e é sempre necessário. Pode ser um arquivo pequeno que requer outro arquivo que faça parte do seu componente ou aplicativo React Native, ou pode conter todo o código necessário para ele. No nosso caso, colocaremos tudo em index.js.

2. Adicione seu código React Native

No seu index.js, crie seu componente. Em nosso exemplo aqui, adicionaremos um componente <Text> dentro de um <View> estilizado:

jsx
import React from 'react';
+import {AppRegistry, StyleSheet, Text, View} from 'react-native';
+
+const HelloWorld = () => {
+  return (
+    <View style={styles.container}>
+      <Text style={styles.hello}>Hello, World</Text>
+    </View>
+  );
+};
+const styles = StyleSheet.create({
+  container: {
+    flex: 1,
+    justifyContent: 'center',
+  },
+  hello: {
+    fontSize: 20,
+    textAlign: 'center',
+    margin: 10,
+  },
+});
+
+AppRegistry.registerComponent(
+  'MyReactNativeApp',
+  () => HelloWorld,
+);

3. Configure permissões para sobreposição de erros de desenvolvimento

Se o seu aplicativo for direcionado à API Android de nível 23 ou superior, verifique se você tem a permissão android.permission.SYSTEM_ALERT_WINDOW ativada para a compilação de desenvolvimento. Você pode verificar isso com Settings.canDrawOverlays(this);. Isso é necessário em compilações de desenvolvimento porque os erros de desenvolvimento do React Native devem ser exibidos acima de todas as outras janelas. Devido ao novo sistema de permissões introduzido na API nível 23 (Android M), o usuário precisa aprová-lo. Isso pode ser conseguido adicionando o seguinte código ao método onCreate() da sua atividade.

java
private final int OVERLAY_PERMISSION_REQ_CODE = 1;  // Escolha qualquer valor
+
+...
+
+if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
+    if (!Settings.canDrawOverlays(this)) {
+        Intent intent = new Intent(Settings.ACTION_MANAGE_OVERLAY_PERMISSION,
+                                   Uri.parse("package:" + getPackageName()));
+        startActivityForResult(intent, OVERLAY_PERMISSION_REQ_CODE);
+    }
+}

Finalmente, o método onActivityResult() (conforme mostrado no código abaixo) deve ser substituído para lidar com os casos de permissão aceita ou negada para uma UX consistente. Além disso, para integrar módulos nativos que usam startActivityForResult, precisamos passar o resultado para o método onActivityResult de nossa instância ReactInstanceManager.

java
@Override
+protected void onActivityResult(int requestCode, int resultCode, Intent data) {
+    if (requestCode == OVERLAY_PERMISSION_REQ_CODE) {
+        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
+            if (!Settings.canDrawOverlays(this)) {
+                // Permissão SYSTEM_ALERT_WINDOW não concedida
+            }
+        }
+    }
+    mReactInstanceManager.onActivityResult( this, requestCode, resultCode, data );
+}

A mágica: ReactRootView

Vamos adicionar algum código nativo para iniciar o tempo de execução do React Native e solicitar que ele renderize nosso componente JS. Para fazer isso, vamos criar uma Activity que cria um ReactRootView, inicia um aplicativo React dentro dele e o define como a visualização de conteúdo principal.

Android

Se você estiver direcionando a versão Android <5, use a classe AppCompatActivity do pacote com.android.support:appcompat em vez de Activity.

java
public class MyReactActivity extends Activity implements DefaultHardwareBackBtnHandler {
+    private ReactRootView mReactRootView;
+    private ReactInstanceManager mReactInstanceManager;
+
+    @Override
+    protected void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+        SoLoader.init(this, false);
+
+        mReactRootView = new ReactRootView(this);
+        List<ReactPackage> packages = new PackageList(getApplication()).getPackages();
+        // Pacotes que ainda não podem ser vinculados automaticamente podem ser adicionados manualmente aqui, por exemplo:
+        // pacotes.add(new MyReactNativePackage());
+        // Lembre-se de incluí-los em `settings.gradle` e `app/build.gradle` também.
+
+        mReactInstanceManager = ReactInstanceManager.builder()
+                .setApplication(getApplication())
+                .setCurrentActivity(this)
+                .setBundleAssetName("index.android.bundle")
+                .setJSMainModulePath("index")
+                .addPackages(packages)
+                .setUseDeveloperSupport(BuildConfig.DEBUG)
+                .setInitialLifecycleState(LifecycleState.RESUMED)
+                .build();
+
+        // A string aqui (por exemplo, "MyReactNativeApp") deve corresponder
+        // a string em AppRegistry.registerComponent() em index.js
+        mReactRootView.startReactApplication(mReactInstanceManager, "MyReactNativeApp", null);
+
+        setContentView(mReactRootView);
+    }
+
+    @Override
+    public void invokeDefaultOnBackPressed() {
+        super.onBackPressed();
+    }
+}

Informação

Se você estiver usando um kit inicial para React Native, substitua a string "HelloWorld" pela do seu arquivo index.js (é o primeiro argumento para o método AppRegistry.registerComponent()).

Execute a operação “Sync Project files with Gradle”.

Se você estiver usando o Android Studio, use Alt + Enter para adicionar todas as importações ausentes em sua classe MyReactActivity. Tenha cuidado ao usar o BuildConfig do seu pacote e não o do pacote facebook.

Precisamos definir o tema de MyReactActivity como Theme.AppCompat.Light.NoActionBar porque alguns componentes da UI do React Native dependem deste tema.

xml
<activity
+  android:name=".MyReactActivity"
+  android:label="@string/app_name"
+  android:theme="@style/Theme.AppCompat.Light.NoActionBar">
+</activity>

Dica

Um ReactInstanceManager pode ser compartilhado por múltiplas atividades e/ou fragmentos. Você desejará criar seu próprio ReactFragment ou ReactActivity e ter um suporte singleton que contenha um ReactInstanceManager. Quando você precisar do ReactInstanceManager (por exemplo, para conectar o ReactInstanceManager ao ciclo de vida dessas atividades ou fragmentos), use aquele fornecido pelo singleton.

Em seguida, precisamos passar alguns retornos de chamada do ciclo de vida da atividade para ReactInstanceManager e ReactRootView:

java
@Override
+protected void onPause() {
+    super.onPause();
+
+    if (mReactInstanceManager != null) {
+        mReactInstanceManager.onHostPause(this);
+    }
+}
+
+@Override
+protected void onResume() {
+    super.onResume();
+
+    if (mReactInstanceManager != null) {
+        mReactInstanceManager.onHostResume(this, this);
+    }
+}
+
+@Override
+protected void onDestroy() {
+    super.onDestroy();
+
+    if (mReactInstanceManager != null) {
+        mReactInstanceManager.onHostDestroy(this);
+    }
+    if (mReactRootView != null) {
+        mReactRootView.unmountReactApplication();
+    }
+}

Também precisamos passar de volta os eventos do botão para o React Native:

java
@Override
+ public void onBackPressed() {
+    if (mReactInstanceManager != null) {
+        mReactInstanceManager.onBackPressed();
+    } else {
+        super.onBackPressed();
+    }
+}

Isso permite que o JavaScript controle o que acontece quando o usuário pressiona o botão Voltar do hardware (por exemplo, para implementar a navegação). Quando o JavaScript não controla o pressionamento do botão Voltar, seu método invocaDefaultOnBackPressed será chamado. Por padrão, isso encerra sua atividade.

Finalmente, precisamos conectar o menu de desenvolvimento. Por padrão, isso é ativado agitando o dispositivo, mas isso não é muito útil em emuladores. Então, mostramos isso quando você pressiona o botão do menu de hardware (use Ctrl + M se estiver usando o emulador do Android Studio):

java
@Override
+public boolean onKeyUp(int keyCode, KeyEvent event) {
+    if (keyCode == KeyEvent.KEYCODE_MENU && mReactInstanceManager != null) {
+        mReactInstanceManager.showDevOptionsDialog();
+        return true;
+    }
+    return super.onKeyUp(keyCode, event);
+}

Agora sua atividade está pronta para executar algum código JavaScript.

Teste sua integração

Agora você executou todas as etapas básicas para integrar o React Native ao seu aplicativo atual. Agora iniciaremos o empacotador Metro para construir o pacote index.bundle e o servidor rodando em localhost para servi-lo.

1. Execute o empacotador

Para executar seu aplicativo, primeiro você precisa iniciar o servidor de desenvolvimento. Para fazer isso, execute o seguinte comando no diretório raiz do seu projeto React Native:

bash
npm start
bash
yarn start

2. Execute o aplicativo

Agora crie e execute seu aplicativo Android normalmente.

Assim que você atingir sua atividade com React dentro do aplicativo, ele deverá carregar o código JavaScript do servidor de desenvolvimento e exibir:

image

Criando uma versão de lançamento no Android Studio

Você também pode usar o Android Studio para criar suas versões de lançamento! É tão rápido quanto criar versões de lançamento do seu aplicativo Android nativo já existente.

Se você usar o plugin React Native Gradle conforme descrito acima, tudo deverá funcionar ao executar o aplicativo do Android Studio.

Se você não estiver usando o plugin React Native Gradle, há uma etapa adicional que você terá que executar antes de cada versão. Você precisa executar o seguinte para criar um pacote React Native, que será incluído em seu aplicativo Android nativo:

bash
$ npx react-native bundle --platform android --dev false --entry-file index.js --bundle-output android/com/your-company-name/app-package-name/src/main/assets/index.android.bundle --assets-dest android/com/your-company-name/app-package-name/src/main/res/

Dica

Não se esqueça de substituir os caminhos pelos corretos e criar a pasta de ativos caso ela não exista.

Agora, crie uma versão de lançamento do seu aplicativo nativo no Android Studio, como de costume, e você estará pronto para prosseguir!

E agora?

Neste ponto, você pode continuar desenvolvendo seu aplicativo normalmente. Consulte nossos documentos de depuração e implantação para saber mais sobre como trabalhar com React Native.

+ + + + \ No newline at end of file diff --git a/vitepress/docs/.vitepress/dist/docs/integration-with-existing-apps/android-kotlin.html b/vitepress/docs/.vitepress/dist/docs/integration-with-existing-apps/android-kotlin.html new file mode 100644 index 0000000..c4076a6 --- /dev/null +++ b/vitepress/docs/.vitepress/dist/docs/integration-with-existing-apps/android-kotlin.html @@ -0,0 +1,163 @@ + + + + + + Android (Kotlin) | React Native 0.72 + + + + + + + + + + + + + + + + +
Skip to content

Android (Kotlin)

Conceitos chave

Os segredos para integrar componentes React Native em seu aplicativo Android são:

  1. Configure as dependências e a estrutura de diretórios do React Native.
  2. Desenvolva seus componentes React Native em JavaScript.
  3. Adicione um ReactRootView ao seu aplicativo Android. Esta visualização servirá como contêiner para seu componente React Native.
  4. Inicie o servidor React Native e execute seu aplicativo nativo.
  5. Verifique se o aspecto do seu aplicativo React Native funciona conforme o esperado.

Pré-requisitos

Siga o início rápido do React Native CLI no guia de configuração do ambiente para configurar seu ambiente de desenvolvimento para construir aplicativos React Native para Android.

  1. Configure a estrutura de diretórios Para garantir uma experiência tranquila, crie uma nova pasta para seu projeto React Native integrado e copie seu projeto Android existente para uma subpasta /android.

  2. Instale as dependências do JavaScript Vá para o diretório raiz do seu projeto e crie um novo arquivo package.json com o seguinte conteúdo:

json
{
+  "name": "MyReactNativeApp",
+  "version": "0.0.1",
+  "private": true,
+  "scripts": {
+    "start": "yarn react-native start"
+  }
+}

Em seguida, instale os pacotes react e react-native. Abra um terminal ou prompt de comando, navegue até o diretório com seu arquivo package.json e execute:

bash
npm install react-native
bash
yarn add react-native

Isso imprimirá uma mensagem semelhante à seguinte (role para cima na saída do fio para vê-la):

Atenção

O pacote "react-native@0.70.5" tem dependência de peer não atendida de "react@18.1.0"

Tudo bem, significa que também precisamos instalar o React:

bash
npm install react@version_printed_above
bash
yarn add react@version_printed_above

Yarn/npm criou uma nova pasta /node_modules. Esta pasta armazena todas as dependências JavaScript necessárias para construir seu projeto.

Adicione node_modules/ ao seu arquivo .gitignore.

Adicionando React Native ao seu aplicativo

Configurando o Gradle

React Native usa o plugin React Native Gradle para configurar suas dependências e configuração do projeto.

Primeiro, vamos editar seu arquivo settings.gradle adicionando esta linha:

includeBuild('../node_modules/@react-native/gradle-plugin')

Então você precisa abrir seu build.gradle de nível superior e incluir esta linha:

buildscript {
+    repositories {
+        google()
+        mavenCentral()
+    }
+    dependencies {
+        classpath("com.android.tools.build:gradle:7.3.1")
+        classpath("com.facebook.react:react-native-gradle-plugin")
+    }
+}

Isso garante que o plugin React Native Gradle esteja disponível em seu projeto. Por fim, adicione essas linhas ao arquivo build.gradle do seu aplicativo (é um arquivo build.gradle diferente dentro da pasta do seu aplicativo):

apply plugin: "com.android.application"
+apply plugin: "com.facebook.react"
+
+repositories {
+    mavenCentral()
+}
+
+dependencies {
+    // Outras dependências aqui
+    implementation "com.facebook.react:react-android"
+    implementation "com.facebook.react:hermes-android"
+}

Essas dependências estão disponíveis em mavenCentral(), portanto, certifique-se de tê-las definidas no repositories {}.

INFORMAÇÕES

Intencionalmente não especificamos a versão para essas dependências de implementation, pois o React Native Gradle Plugin cuidará disso. Se você não usar o plugin React Native Gradle, terá que especificar a versão manualmente.

Habilitar autolinking de módulos nativos

Para usar o poder do autolinking, temos que aplicá-lo em alguns lugares. Primeiro adicione a seguinte entrada em settings.gradle:

apply from: file("../node_modules/@react-native-community/cli-platform-android/native_modules.gradle"); applyNativeModulesSettingsGradle(settings)

Em seguida, adicione a seguinte entrada na parte inferior do app/build.gradle:

apply from: file("../../node_modules/@react-native-community/cli-platform-android/native_modules.gradle"); applyNativeModulesAppBuildGradle(project)

Configurando permissões

Em seguida, certifique-se de ter permissão de Internet em seu AndroidManifest.xml:

xml
<uses-permission android:name="android.permission.INTERNET" />

Se você precisar acessar DevSettingsActivity, adicione ao seu AndroidManifest.xml:

xml
<activity android:name="com.facebook.react.devsupport.DevSettingsActivity" />

Isso só é usado no modo de desenvolvimento ao recarregar o JavaScript do servidor de desenvolvimento, portanto, você pode removê-lo nas compilações de lançamento, se necessário.

Tráfego de texto simples (nível de API 28+)

Dica

A partir do Android 9 (API de nível 28), o tráfego de texto não criptografado é desativado por padrão; isso evita que seu aplicativo se conecte ao empacotador Metro. As alterações abaixo permitem tráfego de texto não criptografado em compilações de depuração.

  1. Aplique a opção usesCleartextTraffic ao seu Debug AndroidManifest.xml
xml
<!-- ... -->
+<application
+  android:usesCleartextTraffic="true" tools:targetApi="28" >
+  <!-- ... -->
+</application>
+<!-- ... -->

Isso não é necessário para compilações de versão.

Para saber mais sobre a configuração de segurança de rede e a política de tráfego de texto não criptografado, consulte este link.

Integração de código

Agora vamos modificar o aplicativo Android nativo para integrar o React Native.

O componente React Native

O primeiro código que escreveremos é o código React Native real para a nova tela "High Score" que será integrada em nosso aplicativo.

1. Crie um arquivo index.js

Primeiro, crie um arquivo index.js vazio na raiz do seu projeto React Native.

index.js é o ponto de partida para aplicativos React Native e é sempre necessário. Pode ser um arquivo pequeno que require outro arquivo que faça parte do seu componente ou aplicativo React Native, ou pode conter todo o código necessário para ele. No nosso caso, colocaremos tudo em index.js.

2. Adicione seu código React Native

No seu index.js, crie seu componente. Em nosso exemplo aqui, adicionaremos um componente <Text> dentro de um <View> estilizado:

jsx
import React from 'react';
+import {AppRegistry, StyleSheet, Text, View} from 'react-native';
+
+const HelloWorld = () => {
+  return (
+    <View style={styles.container}>
+      <Text style={styles.hello}>Hello, World</Text>
+    </View>
+  );
+};
+const styles = StyleSheet.create({
+  container: {
+    flex: 1,
+    justifyContent: 'center',
+  },
+  hello: {
+    fontSize: 20,
+    textAlign: 'center',
+    margin: 10,
+  },
+});
+
+AppRegistry.registerComponent(
+  'MyReactNativeApp',
+  () => HelloWorld,
+);

3. Configure permissões para sobreposição de erros de desenvolvimento

Se o seu aplicativo for direcionado à API Android de nível 23 ou superior, verifique se você tem a permissão android.permission.SYSTEM_ALERT_WINDOW ativada para a compilação de desenvolvimento. Você pode verificar isso com Settings.canDrawOverlays(this). Isso é necessário em compilações de desenvolvimento porque os erros de desenvolvimento do React Native devem ser exibidos acima de todas as outras janelas. Devido ao novo sistema de permissões introduzido na API nível 23 (Android M), o usuário precisa aprová-lo. Isso pode ser conseguido adicionando o seguinte código ao método onCreate() da sua Activity.

companion object {
+    const val OVERLAY_PERMISSION_REQ_CODE = 1  // Escolha qualquer valor
+}
+
+...
+
+if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
+    if(!Settings.canDrawOverlays(this)) {
+        val intent = Intent(Settings.ACTION_MANAGE_OVERLAY_PERMISSION,
+                                    Uri.parse("package: $packageName"))
+        startActivityForResult(intent, OVERLAY_PERMISSION_REQ_CODE);
+    }
+}

Finalmente, o método onActivityResult() (conforme mostrado no código abaixo) deve ser substituído para lidar com os casos de permissão aceita ou negada para um UX consistente. Além disso, para integrar módulos nativos que usam startActivityForResult, precisamos passar o resultado para o método onActivityResult de nossa instância ReactInstanceManager.

kotlin
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
+    if (requestCode == OVERLAY_PERMISSION_REQ_CODE) {
+        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
+            if (!Settings.canDrawOverlays(this)) {
+                // SYSTEM_ALERT_WINDOW permission not granted
+            }
+        }
+    }
+    reactInstanceManager?.onActivityResult(this, requestCode, resultCode, data)
+}

A mágica: ReactRootView

Vamos adicionar algum código nativo para iniciar o runtime do React Native e solicitar que ele renderize nosso componente JS. Para fazer isso, vamos criar uma Activity que cria um ReactRootView, inicia um aplicativo React dentro dele e o define como a visualização de conteúdo principal.

Se você estiver direcionando a versão Android <5, use a classe AppCompatActivity do pacote com.android.support:appcompat em vez de Activity.

kotlin
class MyReactActivity : Activity(), DefaultHardwareBackBtnHandler {
+    private lateinit var reactRootView: ReactRootView
+    private lateinit var reactInstanceManager: ReactInstanceManager
+    override fun onCreate(savedInstanceState: Bundle?) {
+        super.onCreate(savedInstanceState)
+        SoLoader.init(this, false)
+        reactRootView = ReactRootView(this)
+        val packages: List<ReactPackage> = PackageList(application).packages
+
+        // Pacotes que ainda não podem ser vinculados automaticamente podem ser adicionados manualmente aqui, por exemplo:
+        // packages.add(MyReactNativePackage())
+        // Lembre-se de incluí-los em `settings.gradle` e `app/build.gradle` também.
+        reactInstanceManager = ReactInstanceManager.builder()
+            .setApplication(application)
+            .setCurrentActivity(this)
+            .setBundleAssetName("index.android.bundle")
+            .setJSMainModulePath("index")
+            .addPackages(packages)
+            .setUseDeveloperSupport(BuildConfig.DEBUG)
+            .setInitialLifecycleState(LifecycleState.RESUMED)
+            .build()
+
+        // A string aqui (por exemplo, "MyReactNativeApp") deve corresponder
+        // a string em AppRegistry.registerComponent() em index.js
+        reactRootView?.startReactApplication(reactInstanceManager, "MyReactNativeApp", null)
+        setContentView(reactRootView)
+    }
+
+    override fun invokeDefaultOnBackPressed() {
+        super.onBackPressed()
+    }
+}

Se você estiver usando um kit inicial para React Native, substitua a string "HelloWorld" pela do seu arquivo index.js (é o primeiro argumento para o método AppRegistry.registerComponent()).

Execute uma operação “Sync Project files with Gradle”.

Se você estiver usando o Android Studio, use Alt + Enter para adicionar todas as importações ausentes em sua classe MyReactActivity. Tenha cuidado ao usar o BuildConfig do seu pacote e não o do pacote facebook.

Precisamos definir o tema de MyReactActivity como Theme.AppCompat.Light.NoActionBar porque alguns componentes da UI do React Native dependem deste tema.

<activity
+  android:name=".MyReactActivity"
+  android:label="@string/app_name"
+  android:theme="@style/Theme.AppCompat.Light.NoActionBar">
+</activity>

Nota

Um ReactInstanceManager pode ser compartilhado por múltiplas atividades e/ou fragmentos. Você desejará criar seu próprio ReactFragment ou ReactActivity e ter um suporte singleton que contenha um ReactInstanceManager. Quando você precisar do ReactInstanceManager (por exemplo, para conectar o ReactInstanceManager ao ciclo de vida dessas atividades ou fragmentos), use aquele fornecido pelo singleton.

Em seguida, precisamos passar alguns retornos de chamada do ciclo de vida da atividade para ReactInstanceManager e ReactRootView:

kotlin
override fun onPause() {
+    super.onPause()
+    reactInstanceManager.onHostPause(this)
+}
+
+override fun onResume() {
+    super.onResume()
+    reactInstanceManager.onHostResume(this, this)
+}
+
+override fun onDestroy() {
+    super.onDestroy()
+    reactInstanceManager.onHostDestroy(this)
+    reactRootView.unmountReactApplication()
+}

Também precisamos passar de volta os eventos do botão para o React Native:

kotlin
override fun onBackPressed() {
+    reactInstanceManager.onBackPressed()
+    super.onBackPressed()
+}

Isso permite que o JavaScript controle o que acontece quando o usuário pressiona o botão Voltar do hardware (por exemplo, para implementar a navegação). Quando o JavaScript não controla o pressionamento do botão Voltar, seu método invocaDefaultOnBackPressed será chamado. Por padrão, isso encerra sua Activity.

Finalmente, precisamos conectar o menu de desenvolvimento. Por padrão, isso é ativado agitando (intensamente) o dispositivo, mas isso não é muito útil em emuladores. Então, mostramos isso quando você pressiona o botão do menu de hardware (use Ctrl + M se estiver usando o emulador do Android Studio):

kt
override fun onKeyUp(keyCode: Int, event: KeyEvent?): Boolean {
+    if (keyCode == KeyEvent.KEYCODE_MENU && reactInstanceManager != null) {
+        reactInstanceManager.showDevOptionsDialog()
+        return true
+    }
+    return super.onKeyUp(keyCode, event)
+}

Agora sua atividade está pronta para executar algum código JavaScript.

Teste sua integração

Agora você executou todas as etapas básicas para integrar o React Native ao seu aplicativo atual. Agora iniciaremos o empacotador Metro para construir o pacote index.bundle e o servidor rodando em localhost para servi-lo.

1. Execute o empacotador

Para executar seu aplicativo, primeiro você precisa iniciar o servidor de desenvolvimento. Para fazer isso, execute o seguinte comando no diretório raiz do seu projeto React Native:

bash
npm start
bash
yarn start

2. Execute o aplicativo

Agora crie e execute seu aplicativo Android normalmente.

Assim que você atingir sua atividade com React dentro do aplicativo, ele deverá carregar o código JavaScript do servidor de desenvolvimento e exibir:

image

Criando uma versão de lançamento no Android Studio

Você também pode usar o Android Studio para criar suas versões de lançamento! É tão rápido quanto criar versões de lançamento do seu aplicativo Android nativo já existente.

Se você usar o plugin React Native Gradle conforme descrito acima, tudo deverá funcionar ao executar o aplicativo do Android Studio.

Se você não estiver usando o plugin React Native Gradle, há uma etapa adicional que você terá que executar antes de cada versão. Você precisa executar o seguinte para criar um pacote React Native, que será incluído em seu aplicativo Android nativo:

bash
$ npx react-native bundle --platform android --dev false --entry-file index.js --bundle-output android/com/your-company-name/app-package-name/src/main/assets/index.android.bundle --assets-dest android/com/your-company-name/app-package-name/src/main/res/

Nota

Não se esqueça de substituir os caminhos pelos corretos e criar a pasta de ativos caso ela não exista.

Agora, crie uma versão de lançamento do seu aplicativo nativo no Android Studio, como de costume, e você estará pronto para prosseguir!

E agora?

Neste ponto, você pode continuar desenvolvendo seu aplicativo normalmente. Consulte nossos documentos de depuração e implantação para saber mais sobre como trabalhar com React Native.

+ + + + \ No newline at end of file diff --git a/vitepress/docs/.vitepress/dist/docs/integration-with-existing-apps/ios-objective-c.html b/vitepress/docs/.vitepress/dist/docs/integration-with-existing-apps/ios-objective-c.html new file mode 100644 index 0000000..8662ebc --- /dev/null +++ b/vitepress/docs/.vitepress/dist/docs/integration-with-existing-apps/ios-objective-c.html @@ -0,0 +1,151 @@ + + + + + + iOS (Objective-C) | React Native 0.72 + + + + + + + + + + + + + + + + +
Skip to content

iOS (Objective-C)

Conceitos chave

Os segredos para integrar componentes React Native em seu aplicativo iOS são:

  1. Configure as dependências e a estrutura de diretórios do React Native.
  2. Entenda quais componentes do React Native você usará em seu aplicativo.
  3. Adicione esses componentes como dependências usando CocoaPods. 4.Desenvolva seus componentes React Native em JavaScript.
  4. Adicione um RTRRootView ao seu aplicativo iOS. Esta visualização servirá como contêiner para seu componente React Native.
  5. Inicie o servidor React Native e execute seu aplicativo nativo.
  6. Verifique se o aspecto React Native do seu aplicativo funciona conforme o esperado.

Pré-requisitos

Siga o início rápido do React Native CLI no guia de configuração do ambiente para configurar seu ambiente de desenvolvimento para construir aplicativos React Native para iOS.

1. Configure a estrutura de diretórios

Para garantir uma experiência tranquila, crie uma nova pasta para seu projeto React Native integrado e copie seu projeto iOS existente para uma subpasta /ios.

2. Instale dependências JavaScript

Vá para o diretório raiz do seu projeto e crie um novo arquivo package.json com o seguinte conteúdo:

json
{
+  "name": "MyReactNativeApp",
+  "version": "0.0.1",
+  "private": true,
+  "scripts": {
+    "start": "yarn react-native start"
+  }
+}

Em seguida, certifique-se de ter instalado o gerenciador de pacotes Yarn.

Instale os pacotes react e react-native. Abra um terminal ou prompt de comando, navegue até o diretório com seu arquivo package.json e execute:

bash
npm install react-native
bash
yarn add react-native

Isso imprimirá uma mensagem semelhante à seguinte (role para cima na saída do fio para vê-la):

warning "react-native@0.52.2" has unmet peer dependency "react@16.2.0".

Tudo bem, significa que também precisamos instalar o React:

bash
npm install react@version_printed_above
bash
yarn add react@version_printed_above

O processo de instalação criou uma nova pasta /node_modules. Esta pasta armazena todas as dependências JavaScript necessárias para construir seu projeto.

Adicione node_modules/ ao seu arquivo .gitignore.

3. Instale CocoaPods

CocoaPods é uma ferramenta de gerenciamento de pacotes para desenvolvimento iOS e macOS. Nós o usamos para adicionar o código da estrutura React Native localmente ao seu projeto atual.

Recomendamos instalar CocoaPods usando Homebrew.

brew install cocoapods

Nota

É tecnicamente possível não usar CocoaPods, mas isso exigiria adições manuais de biblioteca e vinculador que complicariam excessivamente esse processo.

Adicionando React Native ao seu aplicativo

Suponha que o aplicativo para integração seja um jogo de 2048. Esta é a aparência do menu principal do aplicativo nativo sem o React Native.

image

Ferramentas de linha de comando para Xcode

Instale as ferramentas de linha de comando. Escolha Settings... (ou Preferences...) no menu do Xcode. Vá para o painel Locais e instale as ferramentas selecionando a versão mais recente no menu suspenso Ferramentas de linha de comando.

image

Configurando dependências do CocoaPods

Antes de integrar o React Native ao seu aplicativo, você desejará decidir quais partes da estrutura React Native você gostaria de integrar. Usaremos CocoaPods para especificar de quais dessas "subespecificações" seu aplicativo dependerá.

A lista de subespecificações suportadas está disponível em /node_modules/react-native/React.podspec. Eles geralmente são nomeados por funcionalidade. Por exemplo, geralmente você sempre desejará a subespecificação Core. Isso lhe dará o AppRegistry, StyleSheet, View e outras bibliotecas principais do React Native. Se você deseja adicionar a biblioteca React Native Text (por exemplo, para elementos <Text> ), você precisará da subespecificação RCTText. Se você quiser a biblioteca de imagens (por exemplo, para elementos <Image> ), precisará da subespecificação RCTImage.

Você pode especificar de quais subespecificações seu aplicativo dependerá em um arquivo Podfile. A maneira mais fácil de criar um Podfile é executando o comando init do CocoaPods na subpasta /ios do seu projeto:

bash
pod init

O Podfile conterá uma configuração padrão que você ajustará para fins de integração.

Nota

A versão do 'Podfilemuda dependendo da sua versão doreact-native. Consulte [https://react-native-community.github.io/upgrade-helper/](https://react-native-community.github.io/upgrade-helper/) para a versão específica do Podfile` que você deve usar.

No final das contas, seu Podfile deve ser semelhante a isto:

# The target name is most likely the name of your project.
+target 'NumberTileGame' do
+
+  # Your 'node_modules' directory is probably in the root of your project,
+  # but if not, adjust the `:path` accordingly
+  pod 'FBLazyVector', :path => "../node_modules/react-native/Libraries/FBLazyVector"
+  pod 'FBReactNativeSpec', :path => "../node_modules/react-native/Libraries/FBReactNativeSpec"
+  pod 'RCTRequired', :path => "../node_modules/react-native/Libraries/RCTRequired"
+  pod 'RCTTypeSafety', :path => "../node_modules/react-native/Libraries/TypeSafety"
+  pod 'React', :path => '../node_modules/react-native/'
+  pod 'React-Core', :path => '../node_modules/react-native/'
+  pod 'React-CoreModules', :path => '../node_modules/react-native/React/CoreModules'
+  pod 'React-Core/DevSupport', :path => '../node_modules/react-native/'
+  pod 'React-RCTActionSheet', :path => '../node_modules/react-native/Libraries/ActionSheetIOS'
+  pod 'React-RCTAnimation', :path => '../node_modules/react-native/Libraries/NativeAnimation'
+  pod 'React-RCTBlob', :path => '../node_modules/react-native/Libraries/Blob'
+  pod 'React-RCTImage', :path => '../node_modules/react-native/Libraries/Image'
+  pod 'React-RCTLinking', :path => '../node_modules/react-native/Libraries/LinkingIOS'
+  pod 'React-RCTNetwork', :path => '../node_modules/react-native/Libraries/Network'
+  pod 'React-RCTSettings', :path => '../node_modules/react-native/Libraries/Settings'
+  pod 'React-RCTText', :path => '../node_modules/react-native/Libraries/Text'
+  pod 'React-RCTVibration', :path => '../node_modules/react-native/Libraries/Vibration'
+  pod 'React-Core/RCTWebSocket', :path => '../node_modules/react-native/'
+
+  pod 'React-cxxreact', :path => '../node_modules/react-native/ReactCommon/cxxreact'
+  pod 'React-jsi', :path => '../node_modules/react-native/ReactCommon/jsi'
+  pod 'React-jsiexecutor', :path => '../node_modules/react-native/ReactCommon/jsiexecutor'
+  pod 'React-jsinspector', :path => '../node_modules/react-native/ReactCommon/jsinspector'
+  pod 'ReactCommon/callinvoker', :path => "../node_modules/react-native/ReactCommon"
+  pod 'ReactCommon/turbomodule/core', :path => "../node_modules/react-native/ReactCommon"
+  pod 'Yoga', :path => '../node_modules/react-native/ReactCommon/yoga'
+
+  pod 'DoubleConversion', :podspec => '../node_modules/react-native/third-party-podspecs/DoubleConversion.podspec'
+  pod 'glog', :podspec => '../node_modules/react-native/third-party-podspecs/glog.podspec'
+  pod 'Folly', :podspec => '../node_modules/react-native/third-party-podspecs/Folly.podspec'
+
+end

Depois de criar seu Podfile, você estará pronto para instalar o pod React Native.

bash
pod install

Você deverá ver resultados como:

Analyzing dependencies
+Fetching podspec for `React` from `../node_modules/react-native`
+Downloading dependencies
+Installing React (0.62.0)
+Generating Pods project
+Integrating client project
+Sending stats
+Pod installation complete! There are 3 dependencies from the Podfile and 1 total pod installed.

Dica

Se isso falhar com erros mencionando o xcrun, certifique-se de que no Xcode em Settings... (or Preferences...) > Locations as Ferramentas de Linha de Comando estejam atribuídas.

Integração de código

Agora iremos modificar o aplicativo iOS nativo para integrar o React Native. Para nosso aplicativo de amostra 2048, adicionaremos uma tela "High Score" no React Native.

O componente React Native

O primeiro código que escreveremos é o código React Native real para a nova tela "High Score" que será integrada em nosso aplicativo.

1. Crie um arquivo index.js

Primeiro, crie um arquivo index.js vazio na raiz do seu projeto React Native.

index.js é o ponto de partida para aplicativos React Native e é sempre necessário. Pode ser um arquivo pequeno que requer outro arquivo que faça parte do seu componente ou aplicativo React Native, ou pode conter todo o código necessário para ele. No nosso caso, colocaremos tudo em index.js.

2. Adicione seu código React Native

No seu index.js, crie seu componente. Em nosso exemplo aqui, adicionaremos um componente <Text> dentro de um estilo <View>

jsx
import React from 'react';
+import {AppRegistry, StyleSheet, Text, View} from 'react-native';
+
+const RNHighScores = ({scores}) => {
+  const contents = scores.map(score => (
+    <Text key={score.name}>
+      {score.name}:{score.value}
+      {'\n'}
+    </Text>
+  ));
+  return (
+    <View style={styles.container}>
+      <Text style={styles.highScoresTitle}>
+        2048 High Scores!
+      </Text>
+      <Text style={styles.scores}>{contents}</Text>
+    </View>
+  );
+};
+
+const styles = StyleSheet.create({
+  container: {
+    flex: 1,
+    justifyContent: 'center',
+    alignItems: 'center',
+    backgroundColor: '#FFFFFF',
+  },
+  highScoresTitle: {
+    fontSize: 20,
+    textAlign: 'center',
+    margin: 10,
+  },
+  scores: {
+    textAlign: 'center',
+    color: '#333333',
+    marginBottom: 5,
+  },
+});
+
+// Nome do módulo
+AppRegistry.registerComponent('RNHighScores', () => RNHighScores);

Nota

RNHighScores é o nome do seu módulo que será usado quando você adicionar uma visualização ao React Native de dentro do seu aplicativo iOS.

A mágica: RCTRootView

Agora que seu componente React Native foi criado por meio de index.js, você precisa adicionar esse componente a um ViewController novo ou existente. O caminho mais fácil é criar opcionalmente um caminho de evento para seu componente e, em seguida, adicionar esse componente a um ViewController existente.

Amarraremos nosso componente React Native a uma nova visualização nativa no ViewController que na verdade o conterá uma chamada a RCTRootView .

1. Crie um caminho de evento

Você pode adicionar um novo link no menu principal do jogo para ir para a página “High Score” do React Native.

image

2. Manipulador de eventos

Agora adicionaremos um manipulador de eventos no link do menu. Um método será adicionado ao ViewController principal da sua aplicação. É aqui que o RTRRootView entra em ação.

Ao construir um aplicativo React Native, você usa o empacotador Metro para criar um index.bundle que será servido pelo servidor React Native. Dentro de index.bundle estará nosso módulo RNHighScore. Portanto, precisamos apontar nosso RTRRootView para o local do recurso index.bundle (via NSURL) e vinculá-lo ao módulo.

Iremos, para fins de depuração, registrar que o manipulador de eventos foi invocado. Em seguida, criaremos uma string com a localização do nosso código React Native que existe dentro do index.bundle. Por fim, criaremos o RTRRootView principal. Observe como fornecemos RNHighScores como moduleName que criamos acima ao escrever o código para nosso componente React Native.

Primeiro import o cabeçalho RTRRootView.

objective-c
#import <React/RCTRootView.h>

Nota

As initialProperties (propriedades iniciais) estão aqui para fins ilustrativos, por isso temos alguns dados para nossa tela de pontuação mais alta. Em nosso componente React Native, usaremos this.props para obter acesso a esses dados.

objective-c
- (IBAction)highScoreButtonPressed:(id)sender {
+    NSLog(@"High Score Button Pressed");
+    NSURL *jsCodeLocation = [NSURL URLWithString:@"http://localhost:8081/index.bundle?platform=ios"];
+
+    RCTRootView *rootView =
+      [[RCTRootView alloc] initWithBundleURL: jsCodeLocation
+                                  moduleName: @"RNHighScores"
+                           initialProperties:
+                             @{
+                               @"scores" : @[
+                                 @{
+                                   @"name" : @"Alex",
+                                   @"value": @"42"
+                                  },
+                                 @{
+                                   @"name" : @"Joel",
+                                   @"value": @"10"
+                                 }
+                               ]
+                             }
+                               launchOptions: nil];
+    UIViewController *vc = [[UIViewController alloc] init];
+    vc.view = rootView;
+    [self presentViewController:vc animated:YES completion:nil];
+}

Nota

Observe que o RTRRootView initWithURL inicia uma nova VM JSC. Para economizar recursos e simplificar a comunicação entre visualizações RN em diferentes partes do seu aplicativo nativo, você pode ter várias visualizações desenvolvidas pelo React Native associadas a um único tempo de execução JS. Para fazer isso, em vez de usar [RCTRootView alloc] initWithURL, use RCTBridge initWithBundleURL para criar uma ponte e, em seguida, use RCTRootView initWithBridge.

Dica

Ao mover seu aplicativo para produção, o NSURL pode apontar para um arquivo pré-empacotado no disco por meio de algo como [[NSBundle mainBundle] URLForResource:@"main" withExtension:@"jsbundle"];. Você pode usar o script react-native-xcode.sh em node_modules/react-native/scripts/ para gerar esse arquivo pré-empacotado.

3. Conecte

Conecte o novo link no menu principal ao método manipulador de eventos recém-adicionado.

image

Dica

Uma das maneiras mais fáceis de fazer isso é abrir a visualização no storyboard e clicar com o botão direito no novo link. Selecione algo como o evento Touch Up Inside, arraste-o para o storyboard e selecione o método criado na lista fornecida.

Teste sua integração

Agora você executou todas as etapas básicas para integrar o React Native ao seu aplicativo atual. Agora iniciaremos o empacotador Metro para construir o pacote index.bundle e o servidor rodando em localhost para servi-lo.

1. Adicionar exceção de segurança de transporte de aplicativos

A Apple bloqueou o carregamento implícito de recursos HTTP em texto não criptografado. Portanto, precisamos adicionar o seguinte arquivo Info.plist (ou equivalente) do nosso projeto.

<key>NSAppTransportSecurity</key>
+<dict>
+    <key>NSExceptionDomains</key>
+    <dict>
+        <key>localhost</key>
+        <dict>
+            <key>NSTemporaryExceptionAllowsInsecureHTTPLoads</key>
+            <true/>
+        </dict>
+    </dict>
+</dict>

Dica

O App Transport Security é bom para seus usuários. Certifique-se de reativá-lo antes de lançar seu aplicativo para produção.

2. Execute o empacotador

Para executar seu aplicativo, primeiro você precisa iniciar o servidor de desenvolvimento. Para fazer isso, execute o seguinte comando no diretório raiz do seu projeto React Native:

bash
npm start
bash
yarn start

3. Execute o aplicativo

Se você estiver usando o Xcode ou seu editor favorito, crie e execute seu aplicativo iOS nativo normalmente. Alternativamente, você pode executar o aplicativo na linha de comando usando:

bash
npm run ios
bash
yarn ios

Em nosso aplicativo de exemplo, você deverá ver o link para "High Scores" e, ao clicar nele, verá a renderização do seu componente React Native.

Aqui está a tela inicial do aplicativo nativo:

image

Aqui está a tela de pontuação mais alta do React Native:

image

Nota

Se você estiver tendo problemas de resolução de módulo ao executar seu aplicativo, consulte este problema do GitHub para obter informações e possível resolução. Este comentário parecia ser a última resolução possível.

E agora?

Neste ponto, você pode continuar desenvolvendo seu aplicativo normalmente. Consulte nossos documentos de depuração e implantação para saber mais sobre como trabalhar com React Native.

+ + + + \ No newline at end of file diff --git a/vitepress/docs/.vitepress/dist/docs/integration-with-existing-apps/ios-swift.html b/vitepress/docs/.vitepress/dist/docs/integration-with-existing-apps/ios-swift.html new file mode 100644 index 0000000..1ea7191 --- /dev/null +++ b/vitepress/docs/.vitepress/dist/docs/integration-with-existing-apps/ios-swift.html @@ -0,0 +1,124 @@ + + + + + + iOS (Swift) | React Native 0.72 + + + + + + + + + + + + + + + + +
Skip to content

iOS (Swift)

Conceitos chave

Os segredos para integrar componentes React Native em seu aplicativo iOS são:

  1. Configure as dependências e a estrutura de diretórios do React Native.
  2. Entenda quais componentes do React Native você usará em seu aplicativo.
  3. Adicione esses componentes como dependências usando CocoaPods.
  4. Desenvolva seus componentes React Native em JavaScript.
  5. Adicione um RTRRootView ao seu aplicativo iOS. Esta visualização servirá como contêiner para seu componente React Native.
  6. Inicie o servidor React Native e execute seu aplicativo nativo.
  7. Verifique se o aspecto React Native do seu aplicativo funciona conforme o esperado.

Pré-requisitos

Siga o início rápido do React Native CLI no guia de configuração do ambiente para configurar seu ambiente de desenvolvimento para construir aplicativos React Native para iOS.

1. Configure a estrutura de diretórios

Para garantir uma experiência tranquila, crie uma nova pasta para seu projeto React Native integrado e copie seu projeto iOS existente para uma subpasta /ios.

2. Instale dependências JavaScript

Vá para o diretório raiz do seu projeto e crie um novo arquivo package.json com o seguinte conteúdo:

json
{
+  "name": "MyReactNativeApp",
+  "version": "0.0.1",
+  "private": true,
+  "scripts": {
+    "start": "yarn react-native start"
+  }
+}

Em seguida, instale os pacotes react e react-native. Abra um terminal ou prompt de comando, navegue até o diretório com seu arquivo package.json e execute:

bash
npm install react-native
bash
yarn add react-native

Isso imprimirá uma mensagem semelhante à seguinte (role para cima na saída do yarn para vê-la):

warning "react-native@0.52.2" has unmet peer dependency "react@16.2.0".

Tudo bem, significa que também precisamos instalar o React:

bash
npm install react@version_printed_above
bash
yarn add react@version_printed_above

Yarn criou uma nova pasta /node_modules. Esta pasta armazena todas as dependências JavaScript necessárias para construir seu projeto.

Adicione node_modules/ ao seu arquivo .gitignore.

3. Instale CocoaPods

CocoaPods é uma ferramenta de gerenciamento de pacotes para desenvolvimento iOS e macOS. Nós o usamos para adicionar o código da estrutura React Native localmente ao seu projeto atual.

Recomendamos instalar CocoaPods usando Homebrew.

bash
brew install cocoapods

Dica

É tecnicamente possível não usar CocoaPods, mas isso exigiria adições manuais de biblioteca e vinculador que complicariam excessivamente esse processo.

Adicionando React Native ao seu aplicativo

Suponha que o aplicativo para integração seja um jogo de 2048. Esta é a aparência do menu principal do aplicativo nativo sem o React Native.

image

Ferramentas de linha de comando para Xcode

Instale as ferramentas de linha de comando. Escolha Settings... (or Preferences...) no menu Xcode. Vá para o painel Locais e instale as ferramentas selecionando a versão mais recente no menu suspenso Ferramentas de linha de comando.

image

Configurando dependências do CocoaPods

Antes de integrar o React Native ao seu aplicativo, você desejará decidir quais partes da estrutura React Native você gostaria de integrar. Usaremos CocoaPods para especificar de quais dessas "subespecificações" seu aplicativo dependerá.

A lista de subespecificações suportadas está disponível em /node_modules/react-native/React.podspec. Eles geralmente são nomeados por funcionalidade. Por exemplo, geralmente você sempre desejará a subespecificação Core. Isso lhe dará o AppRegistry, StyleSheet, View e outras bibliotecas principais do React Native. Se você deseja adicionar a biblioteca React Native Text (por exemplo, para elementos <Text>), você precisará da subespecificação RCTText. Se você quiser a biblioteca de imagens (por exemplo, para elementos <Image>), precisará da subespecificação RCTImage.

Você pode especificar de quais subespecificações seu aplicativo dependerá em um arquivo Podfile. A maneira mais fácil de criar um Podfile é executando o comando init CocoaPods na subpasta /ios do seu projeto:

bash
pod init

O Podfile conterá uma configuração padrão que você ajustará para fins de integração.

Nota

A versão do Podfile muda dependendo da sua versão do react-native. Consulte https://react-native-community.github.io/upgrade-helper/ para a versão específica do Podfile que você deve usar.

No final das contas, seu Podfile deve ser semelhante a este: Template Podfile

Depois de criar seu Podfile, você estará pronto para instalar o pod React Native.

bash
pod install

Você deverá ver resultados como:

Analyzing dependencies
+Fetching podspec for `React` from `../node_modules/react-native`
+Downloading dependencies
+Installing React (0.62.0)
+Generating Pods project
+Integrating client project
+Sending stats
+Pod installation complete! There are 3 dependencies from the Podfile and 1 total pod installed.

Nota

Se isso falhar com erros mencionando o xcrun, certifique-se de que no Xcode em Settings... (or Preferences...) > Locations as Ferramentas de Linha de Comando estejam atribuídas.

Dica

Se você receber um aviso como "The swift-2048 [Debug] target overrides the FRAMEWORK_SEARCH_PATHS build setting defined in Pods/Target Support Files/Pods-swift-2048/Pods-swift-2048.debug.xcconfig. This can lead to problems with the CocoaPods installation", certifique-se de que os caminhos de pesquisa da estrutura nas configurações de compilação para depuração e versão contenham apenas $(inherited).

Integração de código

Agora iremos modificar o aplicativo iOS nativo para integrar o React Native. Para nosso aplicativo de amostra 2048, adicionaremos uma tela "High Score" no React Native.

O componente React Native

O primeiro código que escreveremos é o código React Native real para a nova tela "High Score" que será integrada em nosso aplicativo.

1. Crie um arquivo index.js

Primeiro, crie um arquivo index.js vazio na raiz do seu projeto React Native.

index.js é o ponto de partida para aplicativos React Native e é sempre necessário. Pode ser um arquivo pequeno que requer outro arquivo que faça parte do seu componente ou aplicativo React Native, ou pode conter todo o código necessário para ele. No nosso caso, colocaremos tudo em index.js.

2. Adicione seu código React Native

No seu index.js, crie seu componente. Em nosso exemplo aqui, adicionaremos um componente <Text> dentro de um estilo <View>

jsx
import React from 'react';
+import {AppRegistry, StyleSheet, Text, View} from 'react-native';
+
+const RNHighScores = ({scores}) => {
+  const contents = scores.map(score => (
+    <Text key={score.name}>
+      {score.name}:{score.value}
+      {'\n'}
+    </Text>
+  ));
+  return (
+    <View style={styles.container}>
+      <Text style={styles.highScoresTitle}>
+        2048 High Scores!
+      </Text>
+      <Text style={styles.scores}>{contents}</Text>
+    </View>
+  );
+};
+
+const styles = StyleSheet.create({
+  container: {
+    flex: 1,
+    justifyContent: 'center',
+    alignItems: 'center',
+    backgroundColor: '#FFFFFF',
+  },
+  highScoresTitle: {
+    fontSize: 20,
+    textAlign: 'center',
+    margin: 10,
+  },
+  scores: {
+    textAlign: 'center',
+    color: '#333333',
+    marginBottom: 5,
+  },
+});
+
+// Nome do módulo
+AppRegistry.registerComponent('RNHighScores', () => RNHighScores);

Nota

RNHighScores é o nome do seu módulo que será usado quando você adicionar uma visualização ao React Native de dentro do seu aplicativo iOS.

A mágica: RCTRootView

Agora que seu componente React Native foi criado por meio de index.js, você precisa adicionar esse componente a um ViewController novo ou existente. O caminho mais fácil é criar opcionalmente um caminho de evento para seu componente e, em seguida, adicionar esse componente a um ViewController existente.

Amarraremos nosso componente React Native a uma nova visualização nativa no ViewController que na verdade o conterá, chamada RCTRootView.

1. Crie um caminho de evento

Você pode adicionar um novo link no menu principal do jogo para ir para a página "High Score" do React Native.

image

2. Manipulador de eventos

Agora adicionaremos um manipulador de eventos no link do menu. Um método será adicionado ao ViewController principal da sua aplicação. É aqui que o RTRRootView entra em ação.

Ao construir um aplicativo React Native, você usa o empacotador Metro para criar um index.bundle que será servido pelo servidor React Native. Dentro de index.bundle estará nosso módulo RNHighScore. Portanto, precisamos apontar nosso RTRRootView para o local do recurso index.bundle (via NSURL) e vinculá-lo ao módulo.

Iremos, para fins de depuração, registrar que o manipulador de eventos foi invocado. Em seguida, criaremos uma string com a localização do nosso código React Native que existe dentro do index.bundle. Por fim, criaremos o RTRRootView principal. Observe como fornecemos RNHighScores como moduleName que criamos acima ao escrever o código para nosso componente React Native.

Primeiro import a biblioteca React.

js
import React

Informação

As initialProperties (propriedades iniciais) estão aqui para fins ilustrativos, por isso temos alguns dados para nossa tela de pontuação mais alta. Em nosso componente React Native, usaremos this.props para obter acesso a esses dados.

swift
@IBAction func highScoreButtonTapped(sender : UIButton) {
+  NSLog("Hello")
+  let jsCodeLocation = URL(string: "http://localhost:8081/index.bundle?platform=ios")
+  let mockData:NSDictionary = ["scores":
+      [
+          ["name":"Alex", "value":"42"],
+          ["name":"Joel", "value":"10"]
+      ]
+  ]
+
+  let rootView = RCTRootView(
+      bundleURL: jsCodeLocation,
+      moduleName: "RNHighScores",
+      initialProperties: mockData as [NSObject : AnyObject],
+      launchOptions: nil
+  )
+  let vc = UIViewController()
+  vc.view = rootView
+  self.present(vc, animated: true, completion: nil)
+}

Nota

Observe que o RTRRootView bundleURL inicia uma nova VM JSC. Para economizar recursos e simplificar a comunicação entre visualizações RN em diferentes partes do seu aplicativo nativo, você pode ter várias visualizações desenvolvidas pelo React Native associadas a um único tempo de execução JS. Para fazer isso, em vez de usar RCTRootView bundleURL, use RCTBridge initWithBundleURL para criar uma ponte e, em seguida, use RCTRootView initWithBridge.

Ao mover seu aplicativo para produção, o NSURL pode apontar para um arquivo pré-empacotado no disco por meio de algo como let mainBundle = NSBundle(URLForResource: "main" withExtension:"jsbundle"). Você pode usar o script react-native-xcode.sh em node_modules/react-native/scripts/ para gerar esse arquivo pré-empacotado.

3. Conecte

Conecte o novo link no menu principal ao método manipulador de eventos recém-adicionado.

image

Dica

Uma das maneiras mais fáceis de fazer isso é abrir a visualização no storyboard e clicar com o botão direito no novo link. Selecione algo como o evento Touch Up Inside, arraste-o para o storyboard e selecione o método criado na lista fornecida.

4. Referência da janela

Adicione uma referência de janela ao seu arquivo AppDelegate.swift. Por fim, seu AppDelegate deve ser algo semelhante a isto:

swift
import UIKit
+
+@main
+class AppDelegate: UIResponder, UIApplicationDelegate {
+
+    // Adicionar referência de janela
+    var window: UIWindow?
+
+    func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
+        // Ponto de substituição para personalização após o lançamento do aplicativo.
+        return true
+    }
+
+    ....
+}

Teste sua integração

Agora você executou todas as etapas básicas para integrar o React Native ao seu aplicativo atual. Agora iniciaremos o empacotador Metro para construir o pacote index.bundle e o servidor rodando em localhost para servi-lo.

1. Adicionar exceção de segurança de transporte de aplicativos

A Apple bloqueou o carregamento implícito de recursos HTTP em texto não criptografado. Portanto, precisamos adicionar o seguinte arquivo Info.plist (ou equivalente) do nosso projeto.

<key>NSAppTransportSecurity</key>
+<dict>
+    <key>NSExceptionDomains</key>
+    <dict>
+        <key>localhost</key>
+        <dict>
+            <key>NSTemporaryExceptionAllowsInsecureHTTPLoads</key>
+            <true/>
+        </dict>
+    </dict>
+</dict>

Dica

O App Transport Security é bom para seus usuários. Certifique-se de reativá-lo antes de lançar seu aplicativo para produção.

2. Execute o empacotador

Para executar seu aplicativo, primeiro você precisa iniciar o servidor de desenvolvimento. Para fazer isso, execute o seguinte comando no diretório raiz do seu projeto React Native:

bash
npm start
bash
yarn start

3. Execute o aplicativo

Se você estiver usando o Xcode ou seu editor favorito, crie e execute seu aplicativo iOS nativo normalmente. Alternativamente, você pode executar o aplicativo a partir da linha de comando usando o seguinte comando do diretório raiz do seu projeto React Native:

bash
npm run ios
bash
yarn ios

Em nosso aplicativo de exemplo, você deverá ver o link para "High Scores" e, ao clicar nele, verá a renderização do seu componente React Native.

Aqui está a tela inicial do aplicativo nativo:

image

Aqui está a tela de pontuação mais alta do React Native:

image

Se você estiver tendo problemas de resolução de módulo ao executar seu aplicativo, consulte este problema do GitHub para obter informações e possível resolução. Este comentário parecia ser a última resolução possível.

E agora?

Neste ponto, você pode continuar desenvolvendo seu aplicativo normalmente. Consulte nossos documentos de depuração e implantação para saber mais sobre como trabalhar com React Native.

+ + + + \ No newline at end of file diff --git a/vitepress/docs/.vitepress/dist/docs/intro-react-native-components.html b/vitepress/docs/.vitepress/dist/docs/intro-react-native-components.html new file mode 100644 index 0000000..9a1a6d9 --- /dev/null +++ b/vitepress/docs/.vitepress/dist/docs/intro-react-native-components.html @@ -0,0 +1,55 @@ + + + + + + Componentes principais e componentes nativos | React Native 0.72 + + + + + + + + + + + + + + + + +
Skip to content

Componentes principais e componentes nativos

React Native é uma estrutura de código aberto para construir aplicativos Android e iOS usando React e os recursos nativos da plataforma de aplicativos. Com o React Native, você usa JavaScript para acessar as APIs da sua plataforma, bem como para descrever a aparência e o comportamento da sua UI usando componentes do React: pacotes de código reutilizável e aninhado. Você pode aprender mais sobre React na próxima seção. Mas primeiro, vamos abordar como os componentes funcionam no React Native.

Visualizações e desenvolvimento móvel

No desenvolvimento Android e iOS, uma visualização é o bloco de construção básico da UI: um pequeno elemento retangular na tela que pode ser usado para exibir texto, imagens ou responder à entrada do usuário. Mesmo os menores elementos visuais de um aplicativo, como uma linha de texto ou um botão, são tipos de visualizações. Alguns tipos de visualizações podem conter outras visualizações. São visualizações até o fim!

Apenas uma amostra das muitas visualizações usadas em aplicativos Android e iOS.

Componentes nativos

No desenvolvimento Android, você escreve visualizações em Kotlin ou Java; no desenvolvimento iOS, você usa Swift ou Objective-C. Com React Native, você pode invocar essas visualizações com JavaScript usando componentes React. Em tempo de execução, o React Native cria as visualizações Android e iOS correspondentes para esses componentes. Como os componentes React Native são apoiados pelas mesmas visualizações do Android e iOS, os aplicativos React Native têm aparência, comportamento e desempenho como qualquer outro aplicativo. Chamamos esses componentes apoiados pela plataforma de Componentes Nativos.

React Native vem com um conjunto de componentes nativos essenciais e prontos para uso que você pode usar para começar a construir seu aplicativo hoje mesmo. Estes são os componentes principais do React Native.

React Native também permite que você crie seus próprios componentes nativos para Android e iOS para atender às necessidades exclusivas do seu aplicativo. Também temos um ecossistema próspero desses componentes contribuídos pela comunidade. Confira o Native Directory para descobrir o que a comunidade está criando.

Core Componentes

React Native possui muitos componentes principais para tudo, desde controles até indicadores de atividade. Você pode encontrá-los todos documentados na seção API. Você trabalhará principalmente com os seguintes componentes principais:

REACT NATIVE UI COMPONENTANDROID VIEWIOS VIEWWEB ANÁLOGODESCRIÇÃO
<View><ViewGroup><UIView>Um <div> sem rolagemUm contêiner que suporta layout com flexbox, estilo, algum manuseio de toque e controles de acessibilidade
<Text><TextView><UITextView><p>Exibe, estiliza e aninha sequências de texto e até mesmo manipula eventos de toque
<Image><ImageView><UIImageView><img>Exibe diferentes tipos de imagens
<ScrollView><ScrollView><UIScrollView><div>Um contêiner de rolagem genérico que pode conter vários componentes e visualizações
<TextInput><EditText><UITextField><input type="text">Permite que o usuário insira texto

Na próxima seção, você começará a combinar esses componentes principais para aprender como o React funciona:

js
import React from 'react';
+import {View, Text, Image, ScrollView, TextInput} from 'react-native';
+
+const App = () => {
+  return (
+    <ScrollView>
+      <Text>Some text</Text>
+      <View>
+        <Text>Some more text</Text>
+        <Image
+          source={{
+            uri: 'https://reactnative.dev/docs/assets/p_cat2.png',
+          }}
+          style={{width: 200, height: 200}}
+        />
+      </View>
+      <TextInput
+        style={{
+          height: 40,
+          borderColor: 'gray',
+          borderWidth: 1,
+        }}
+        defaultValue="You can type in me"
+      />
+    </ScrollView>
+  );
+};
+
+export default App;

Como o React Native usa a mesma estrutura de API dos componentes do React, você precisará entender as APIs dos componentes do React para começar. A próxima seção faz uma rápida introdução ou atualização sobre o tópico. No entanto, se você já estiver familiarizado com o React, sinta-se à vontade para avançar.

+ + + + \ No newline at end of file diff --git a/vitepress/docs/.vitepress/dist/docs/intro-react.html b/vitepress/docs/.vitepress/dist/docs/intro-react.html new file mode 100644 index 0000000..9f6622e --- /dev/null +++ b/vitepress/docs/.vitepress/dist/docs/intro-react.html @@ -0,0 +1,264 @@ + + + + + + Fundamentos do React | React Native 0.72 + + + + + + + + + + + + + + + + +
Skip to content

Fundamentos do React

React Native é executado em React, uma popular biblioteca de código aberto para construção de interfaces de usuário com JavaScript. Para aproveitar ao máximo o React Native, é útil entender o próprio React. Esta seção pode ajudá-lo a começar ou servir como um curso de atualização.

Vamos cobrir os principais conceitos por trás do React:

  • componentes
  • JSX
  • adereços
  • estado

Se você quiser se aprofundar, recomendamos que você verifique a documentação oficial do React.

Seu primeiro componente

O restante desta introdução ao React usa gatos em seus exemplos: criaturas amigáveis ​​e acessíveis que precisam de nomes e de um café para trabalhar. Aqui está seu primeiro componente Cat:

jsx
import React from 'react';
+import {Text} from 'react-native';
+
+const Cat = () => {
+  return <Text>Hello, I am your cat!</Text>;
+};
+
+export default Cat;

Veja como fazer isso: Para definir seu componente Cat, primeiro use o import do JavaScript para importar o componente principal Text do React e React Native:

tsx
import React from 'react';
+import {Text} from 'react-native';

Seu componente começa como uma função:

tsx
const Cat = () => {};

Você pode pensar nos componentes como projetos. Tudo o que um componente de função retorna é renderizado como um elemento React. Os elementos React permitem descrever o que você deseja ver na tela.

Aqui o componente Cat irá renderizar um elemento <Text>:

tsx
const Cat = () => {
+  return <Text>Hello, I am your cat!</Text>;
+};

Você pode exportar seu componente de função com export default do JavaScript para uso em todo o seu aplicativo da seguinte forma:

tsx
const Cat = () => {
+  return <Text>Hello, I am your cat!</Text>;
+};
+
+export default Cat;

Esta é uma das muitas maneiras de exportar seu componente. Este tipo de exportação funciona bem com o Snack Player. No entanto, dependendo da estrutura de arquivos do seu aplicativo, pode ser necessário usar uma convenção diferente. Este post de dicas sobre importações e exportações de JavaScript pode ajudar.

Agora dê uma olhada mais de perto na declaração return. <Text>Olá, sou seu gato!</Text> está usando um tipo de sintaxe JavaScript que torna a escrita de elementos conveniente: JSX.

JSX

React e React Native usam JSX, uma sintaxe que permite escrever elementos dentro do JavaScript como: <Text>Olá, sou seu gato!</Text>. A documentação do React tem um guia completo para JSX que você pode consultar para saber ainda mais. Como JSX é JavaScript, você pode usar variáveis ​​dentro dele. Aqui você está declarando um nome para o gato, name, e incorporando-o com chaves dentro de <Text>.

jsx
import React from 'react';
+import {Text} from 'react-native';
+
+const Cat = () => {
+  const name = 'Maru';
+  return <Text>Hello, I am {name}!</Text>;
+};
+
+export default Cat;

Qualquer expressão JavaScript funcionará entre chaves, incluindo chamadas de função como {getFullName("Rum", "Tum", "Tugger")}:

jsx
import React from 'react';
+import {Text} from 'react-native';
+
+const getFullName = (firstName, secondName, thirdName) => {
+  return firstName + ' ' + secondName + ' ' + thirdName;
+};
+
+const Cat = () => {
+  return <Text>Hello, I am {getFullName('Rum', 'Tum', 'Tugger')}!</Text>;
+};
+
+export default Cat;
tsx
import React from 'react';
+import {Text} from 'react-native';
+
+const getFullName = (
+  firstName: string,
+  secondName: string,
+  thirdName: string,
+) => {
+  return firstName + ' ' + secondName + ' ' + thirdName;
+};
+
+const Cat = () => {
+  return <Text>Hello, I am {getFullName('Rum', 'Tum', 'Tugger')}!</Text>;
+};
+
+export default Cat;

Você pode pensar nas chaves como a criação de um portal para a funcionalidade JS em seu JSX!

Como JSX está incluído na biblioteca React, ele não funcionará se você não tiver import React from 'react' no topo do seu arquivo!

Componentes personalizados

Você já conheceu Componentes principais do React Native. O React permite aninhar esses componentes uns dentro dos outros para criar novos componentes. Esses componentes aninhados e reutilizáveis ​​estão no centro do paradigma React.

Por exemplo, você pode aninhar Text e TextInput dentro de um View abaixo, e o React Native irá renderizá-los juntos:

jsx
import React from 'react';
+import {Text, TextInput, View} from 'react-native';
+
+const Cat = () => {
+  return (
+    <View>
+      <Text>Hello, I am...</Text>
+      <TextInput
+        style={{
+          height: 40,
+          borderColor: 'gray',
+          borderWidth: 1,
+        }}
+        defaultValue="Name me!"
+      />
+    </View>
+  );
+};
+
+export default Cat;

Notas do desenvolvedor

Web Se você está familiarizado com desenvolvimento web, <View> e <Text> podem lembrá-lo de HTML! Você pode pensar nelas como as tags <div> e <p> de desenvolvimento de aplicativos.

Android No Android, você normalmente coloca suas visualizações dentro de LinearLayout, FrameLayout, RelativeLayout, etc. para definir como os filhos da visualização serão organizados na tela. No React Native, View usa Flexbox para o layout de seus filhos. Você pode aprender mais em nosso guia de layout com Flexbox.

Você pode renderizar este componente várias vezes e em vários lugares sem repetir seu código usando <Cat>:

jsx
import React from 'react';
+import {Text, View} from 'react-native';
+
+const Cat = () => {
+  return (
+    <View>
+      <Text>I am also a cat!</Text>
+    </View>
+  );
+};
+
+const Cafe = () => {
+  return (
+    <View>
+      <Text>Welcome!</Text>
+      <Cat />
+      <Cat />
+      <Cat />
+    </View>
+  );
+};
+
+export default Cafe;

Qualquer componente que renderize outros componentes é um componente pai. Aqui, Cafe é o componente pai e cada Cat é um componente filho.

Você pode colocar quantos gatos quiser em seu café. Cada <Cat> renderiza um elemento único – que você pode personalizar com adereços.

Adereços

Props é a abreviação de "propriedades". Os adereços permitem personalizar os componentes do React. Por exemplo, aqui você passa para cada <Cat> um nome diferente para Cat renderizar:

jsx
import React from 'react';
+import {Text, View} from 'react-native';
+
+const Cat = props => {
+  return (
+    <View>
+      <Text>Hello, I am {props.name}!</Text>
+    </View>
+  );
+};
+
+const Cafe = () => {
+  return (
+    <View>
+      <Cat name="Maru" />
+      <Cat name="Jellylorum" />
+      <Cat name="Spot" />
+    </View>
+  );
+};
+
+export default Cafe;
tsx
import React from 'react';
+import {Text, View} from 'react-native';
+
+type CatProps = {
+  name: string;
+};
+
+const Cat = (props: CatProps) => {
+  return (
+    <View>
+      <Text>Hello, I am {props.name}!</Text>
+    </View>
+  );
+};
+
+const Cafe = () => {
+  return (
+    <View>
+      <Cat name="Maru" />
+      <Cat name="Jellylorum" />
+      <Cat name="Spot" />
+    </View>
+  );
+};
+
+export default Cafe;

A maioria dos componentes principais do React Native também pode ser personalizada com acessórios. Por exemplo, ao usar Image, você passa um prop chamado source para definir qual imagem ele mostra:

jsx
import React from 'react';
+import {Text, View, Image} from 'react-native';
+
+const CatApp = () => {
+  return (
+    <View>
+      <Image
+        source={{
+          uri: 'https://reactnative.dev/docs/assets/p_cat1.png',
+        }}
+        style={{width: 200, height: 200}}
+      />
+      <Text>Hello, I am your cat!</Text>
+    </View>
+  );
+};
+
+export default CatApp;

Image tem muitos adereços diferentes, incluindo style, que aceita um objeto JS de pares de propriedade-valor relacionados a design e layout.

Nota

Observe as chaves duplas {{ }} ao redor da largura e altura do style. Em JSX, os valores JavaScript são referenciados com {}. Isso é útil se você estiver passando algo diferente de uma string como adereços, como um array ou número: <Cat food={["fish", "kibble"]} age={2} />. No entanto, objetos JS são também denotados com chaves: {width: 200, height: 200}. Portanto, para passar um objeto JS em JSX, você deve envolver o objeto em outro par de chaves: {{ width: 200, height: 200 }}

Você pode construir muitas coisas com adereços e os componentes principais Text, Image e View! Mas para construir algo interativo, você precisará de estado.

Estado

Embora você possa pensar em props como argumentos usados ​​para configurar como os componentes são renderizados, state é como o armazenamento de dados pessoais de um componente. O estado é útil para lidar com dados que mudam ao longo do tempo ou provenientes da interação do usuário. O estado dá memória aos seus componentes!

Como regra geral, use props para configurar um componente quando ele for renderizado. Use o estado para acompanhar todos os dados do componente que você espera alterar ao longo do tempo.

O exemplo a seguir ocorre em um café para gatos, onde dois gatos famintos estão esperando para serem alimentados. A sua fome, que esperamos que mude com o tempo (ao contrário dos seus nomes), é armazenada como estado. Para alimentar os gatos, pressione seus botões – o que atualizará seu estado.

Você pode adicionar estado a um componente chamando o gancho useState do React. Um Hook é um tipo de função que permite “conectar-se” aos recursos do React. Por exemplo, useState é um gancho que permite adicionar estado aos componentes da função. Você pode aprender mais sobre outros tipos de Hooks na documentação do React.

jsx
import React, {useState} from 'react';
+import {Button, Text, View} from 'react-native';
+
+const Cat = props => {
+  const [isHungry, setIsHungry] = useState(true);
+
+  return (
+    <View>
+      <Text>
+        I am {props.name}, and I am {isHungry ? 'hungry' : 'full'}!
+      </Text>
+      <Button
+        onPress={() => {
+          setIsHungry(false);
+        }}
+        disabled={!isHungry}
+        title={isHungry ? 'Give me some food, please!' : 'Thank you!'}
+      />
+    </View>
+  );
+};
+
+const Cafe = () => {
+  return (
+    <>
+      <Cat name="Munkustrap" />
+      <Cat name="Spot" />
+    </>
+  );
+};
+
+export default Cafe;
tsx
import React, {useState} from 'react';
+import {Button, Text, View} from 'react-native';
+
+type CatProps = {
+  name: string;
+};
+
+const Cat = (props: CatProps) => {
+  const [isHungry, setIsHungry] = useState(true);
+
+  return (
+    <View>
+      <Text>
+        I am {props.name}, and I am {isHungry ? 'hungry' : 'full'}!
+      </Text>
+      <Button
+        onPress={() => {
+          setIsHungry(false);
+        }}
+        disabled={!isHungry}
+        title={isHungry ? 'Give me some food, please!' : 'Thank you!'}
+      />
+    </View>
+  );
+};
+
+const Cafe = () => {
+  return (
+    <>
+      <Cat name="Munkustrap" />
+      <Cat name="Spot" />
+    </>
+  );
+};
+
+export default Cafe;

Primeiro, você desejará importar useState do React assim:

tsx
import React, {useState} from 'react';

Então você declara o estado do componente chamando useState dentro de sua função. Neste exemplo, useState cria uma variável de estado isHungry:

tsx
const Cat = (props: CatProps) => {
+  const [isHungry, setIsHungry] = useState(true);
+  // ...
+};

Você pode usar useState para rastrear qualquer tipo de dados: strings, números, booleanos, arrays, objetos. Por exemplo, você pode monitorar o número de vezes que um gato foi acariciado com const [timesPetted, setTimesPetted] = useState(0)!

Chamar useState faz duas coisas:

  • cria uma “variável de estado” com um valor inicial – neste caso a variável de estado é isHungry e seu valor inicial é true
  • cria uma função para definir o valor dessa variável de estado setIsHungry

Não importa quais nomes você usa. Mas pode ser útil pensar no padrão como [<getter>, <setter>] = useState(<initialValue>).

Em seguida, você adiciona o componente principal Button e atribui a ele uma propriedade onPress:

tsx
<Button
+  onPress={() => {
+    setIsHungry(false);
+  }}
+  //..
+/>

Agora, quando alguém pressiona o botão, onPress será acionado, chamando setIsHungry(false). Isso define a variável de estado isHungry como false. Quando isHungry é falso, a propriedade disabled do Button é definida como true e seu title também muda:

tsx
<Button
+  //..
+  disabled={!isHungry}
+  title={isHungry ? 'Give me some food, please!' : 'Thank you!'}
+/>

Você deve ter notado que embora isHungry seja um const, ele é aparentemente reatribuível! O que está acontecendo é que quando uma função de configuração de estado como setIsHungry é chamada, seu componente será renderizado novamente. Neste caso, a função Cat será executada novamente - e desta vez, useState nos dará o próximo valor de isHungry.

Finalmente, coloque seus gatos dentro de um componente Cafe:

tsx
const Cafe = () => {
+  return (
+    <>
+      <Cat name="Munkustrap" />
+      <Cat name="Spot" />
+    </>
+  );
+};

Veja <> e </> acima? Esses bits de JSX são fragmentos. Os elementos JSX adjacentes devem ser agrupados em uma tag envolvente. Os fragmentos permitem fazer isso sem aninhar um elemento de encapsulamento extra e desnecessário, como View.

Agora que você cobriu os componentes principais do React e do React Native, vamos nos aprofundar em alguns desses componentes principais examinando handling <TextInput>.

+ + + + \ No newline at end of file diff --git a/vitepress/docs/.vitepress/dist/docs/introduction.html b/vitepress/docs/.vitepress/dist/docs/introduction.html new file mode 100644 index 0000000..e797d5a --- /dev/null +++ b/vitepress/docs/.vitepress/dist/docs/introduction.html @@ -0,0 +1,27 @@ + + + + + + React Native 0.72 + + + + + + + + + + + + + + + + +
Skip to content
+ + + + \ No newline at end of file diff --git a/vitepress/docs/.vitepress/dist/docs/javascript-environment.html b/vitepress/docs/.vitepress/dist/docs/javascript-environment.html new file mode 100644 index 0000000..5448749 --- /dev/null +++ b/vitepress/docs/.vitepress/dist/docs/javascript-environment.html @@ -0,0 +1,27 @@ + + + + + + Ambiente JavaScript | React Native 0.72 + + + + + + + + + + + + + + + + +
Skip to content

Ambiente JavaScript

Tempo de execução JavaScript

Ao usar React Native, você executará seu código JavaScript em até três ambientes:

  • Na maioria dos casos, o React Native usará o Hermes, um mecanismo JavaScript de código aberto otimizado para o React Native.
  • Se o Hermes estiver desativado, o React Native usará JavaScriptCore, o mecanismo JavaScript que alimenta o Safari. Observe que no iOS, JavaScriptCore não usa JIT devido à ausência de memória executável gravável em aplicativos iOS.
  • Ao usar a depuração do Chrome, todo o código JavaScript é executado no próprio Chrome, comunicando-se com o código nativo por meio de WebSockets. O Chrome usa V8 como mecanismo JavaScript.

Embora esses ambientes sejam muito semelhantes, você pode acabar encontrando algumas inconsistências. É melhor evitar depender de especificações de qualquer tempo de execução.

Transformadores de sintaxe JavaScript

Os transformadores de sintaxe tornam a escrita de código mais agradável, permitindo que você use a nova sintaxe JavaScript sem ter que esperar pelo suporte de todos os interpretadores.

O React Native vem com o compilador Babel JavaScript. Verifique a documentação do Babel sobre suas transformações suportadas para obter mais detalhes.

Uma lista completa das transformações habilitadas para React Native pode ser encontrada em @react-native/babel-preset.

TRANSFORMAÇÃOCÓDIGO
ECMAScript 5
Palavras reservadaspromise.catch(function() {...});
Arrow functions<C onPress={() => this.setState({pressed: true})} />
Block scopinglet greeting = 'hi';
Call spreadMath.max(...array);
Classesclass C extends React.Component { render() { return <View />; } }
Computed Propertiesconst key = 'abc'; const obj = {[key]: 10};
Constantsconst answer = 42;
Destructuringconst {isActive, style} = this.props;
for…offor (var num of [1, 2, 3]) {...};
Function Namelet number = x => x;
Literalsconst b = 0b11; const o = 0o7; const u = 'Hello\u{000A}\u{0009}!';
Modulesimport React, {Component} from 'react';
Object Concise Methodconst obj = {method() { return 10; }};
Object Short Notationconst name = 'vjeux'; const obj = {name};
Parametersfunction test(x = 'hello', {a, b}, ...args) {}
Rest Paramsfunction(type, ...args) {};
Shorthand Propertiesconst o = {a, b, c};
Sticky Regexconst a = /o+/y;
Template Literalsconst who = 'world'; const str = Hello ${who};
Unicode Regexconst string = 'foo💩bar'; const match = string.match(/foo(.)bar/u);
ECMAScript 2016 (ES7)
Exponentiation Operatorlet x = 10 ** 2;
ECMAScript 2017 (ES8)
Async Functionsasync function doStuffAsync() {const foo = await doOtherStuffAsync();};
Function Trailing Commafunction f(a, b, c,) {};
ECMAScript 2018 (ES9)
Object Spreadconst extended = {...obj, a: 10};
ECMAScript 2019 (ES10)
Optional Catch Bindingtry {throw 0; } catch { doSomethingWhichDoesNotCareAboutTheValueThrown();}
ECMAScript 2020 (ES11)
Dynamic Importsconst package = await import('package'); package.function()
Nullish Coalescing Operatorconst foo = object.foo ?? 'default';
Optional Chainingconst name = obj.user?.name;
ECMAScript 2022 (ES13)
Class Fieldsclass Bork {static a = 'foo'; static b; x = 'bar'; y;}
Proposta da etapa 1
Export Default Fromexport v from 'mod';
Diversos
Babel Templatetemplate(const %%importName%% = require(%%source%%););
Flowfunction foo(x: ?number): string {};
ESM to CJSexport default 42;
JSX<View style={{color: 'red'}} />
Object AssignObject.assign(a, b);
React Display Nameconst bar = createReactClass({});
TypeScriptfunction foo(x: {hello: true, target: 'react native!'}): string {};

Polifills

Muitas funções padrão também estão disponíveis em todos os tempos de execução JavaScript suportados.

ECMAScript 2015 (ES6)

ECMAScript 2016 (ES7)

ECMAScript 2017 (ES8)

Específico

  • __DEV__
+ + + + \ No newline at end of file diff --git a/vitepress/docs/.vitepress/dist/docs/libraries.html b/vitepress/docs/.vitepress/dist/docs/libraries.html new file mode 100644 index 0000000..c203d37 --- /dev/null +++ b/vitepress/docs/.vitepress/dist/docs/libraries.html @@ -0,0 +1,27 @@ + + + + + + Usando bibliotecas | React Native 0.72 + + + + + + + + + + + + + + + + +
Skip to content

Usando bibliotecas

React Native fornece um conjunto de componentes principais e APIs integrados, prontos para uso em seu aplicativo. Você não está limitado aos componentes e APIs incluídos no React Native. React Native tem uma comunidade de milhares de desenvolvedores. Se os componentes principais e as APIs não tiverem o que você procura, você poderá encontrar e instalar uma biblioteca da comunidade para adicionar a funcionalidade ao seu aplicativo.

Selecionando um gerenciador de pacotes

As bibliotecas React Native são normalmente instaladas a partir do npm usando um gerenciador de pacotes Node.js, como npm CLI ou Yarn Classic.

Se você tiver o Node.js instalado em seu computador, então você já tem a CLI npm instalada. Alguns desenvolvedores preferem usar o Yarn Classic para tempos de instalação um pouco mais rápidos e recursos avançados adicionais, como Workspaces. Ambas as ferramentas funcionam muito bem com React Native. Assumiremos o npm no restante deste guia para simplificar a explicação.

DICA

Os termos “biblioteca” e “pacote” são usados indistintamente na comunidade JavaScript.

Instalando uma biblioteca

Para instalar uma biblioteca em seu projeto, navegue até o diretório do projeto em seu terminal e execute o comando de instalação. Vamos tentar isso com react-native-webview:

bash
npm install react-native-webview
bash
yarn add react-native-webview

A biblioteca que instalamos inclui código nativo e precisamos vincular ao nosso aplicativo antes de usá-lo.

Vinculando código nativo no iOS

React Native usa CocoaPods para gerenciar dependências de projetos iOS e a maioria das bibliotecas React Native seguem esta mesma convenção. Se uma biblioteca que você está usando não tiver, consulte o README para obter instruções adicionais. Na maioria dos casos, as instruções a seguir serão aplicadas.

Execute pod install em nosso diretório ios para vinculá-lo ao nosso projeto iOS nativo. Um atalho para fazer isso sem mudar para o diretório ios é executar npx pod-install.

bash
npx pod-install

Quando isso estiver concluído, reconstrua o binário do aplicativo para começar a usar sua nova biblioteca:

bash
npm run ios
bash
yarn ios

Vinculando código nativo no Android

React Native usa Gradle para gerenciar dependências de projetos Android. Depois de instalar uma biblioteca com dependências nativas, você precisará reconstruir o binário do aplicativo para usar sua nova biblioteca:

bash
npm run android
bash
yarn android

Encontrando Bibliotecas

React Native Directory é um banco de dados pesquisável de bibliotecas construídas especificamente para React Native. Este é o primeiro lugar para procurar uma biblioteca para seu aplicativo React Native.

Muitas das bibliotecas que você encontrará no diretório são da React Native Community ou Expo.

As bibliotecas construídas pela comunidade React Native são dirigidas por voluntários e indivíduos em empresas que dependem do React Native. Eles geralmente oferecem suporte a iOS, tvOS, Android, Windows, mas isso varia entre os projetos. Muitas das bibliotecas nesta organização já foram componentes principais e APIs do React Native.

As bibliotecas criadas pela Expo são todas escritas em TypeScript e suportam iOS, Android e react-native-web sempre que possível.

Depois do React Native Directory, o registro npm é o próximo melhor lugar se você não conseguir encontrar uma biblioteca específica para React Native. O registro npm é a fonte definitiva para bibliotecas JavaScript, mas as bibliotecas listadas podem não ser todas compatíveis com React Native. React Native é um dos muitos ambientes de programação JavaScript, incluindo Node.js, navegadores da web, Electron e muito mais, e o npm inclui bibliotecas que funcionam para todos esses ambientes.

Determinando a compatibilidade da biblioteca

Funciona com React Native?

Normalmente, bibliotecas construídas especificamente para outras plataformas não funcionarão com React Native. Os exemplos incluem react-select, que é desenvolvido para a web e tem como alvo específico o react-dom, e rimraf, que é desenvolvido para Node.js e interage com o sistema de arquivos do seu computador. Outras bibliotecas como a lodash usam apenas recursos da linguagem JavaScript e funcionam em qualquer ambiente. Você entenderá isso com o tempo, mas até então a maneira mais fácil de descobrir é tentar você mesmo. Você pode remover pacotes usando npm uninstall se descobrir que ele não funciona no React Native.

Funciona nas plataformas suportadas pelo meu aplicativo?

React Native Directory permite filtrar por compatibilidade de plataforma, como iOS, Android, Web e Windows. Se a biblioteca que você gostaria de usar não estiver listada lá, consulte o README da biblioteca para saber mais.

Funciona com a versão do meu aplicativo React Native?

A versão mais recente de uma biblioteca normalmente é compatível com a versão mais recente do React Native. Se você estiver usando uma versão mais antiga, consulte o README para saber qual versão da biblioteca deve instalar. Você pode instalar uma versão específica da biblioteca executando npm install <library-name>@<version-number>, por exemplo: npm install @react-native-community/netinfo@^2.0.0.

+ + + + \ No newline at end of file diff --git a/vitepress/docs/.vitepress/dist/docs/linking-libraries-ios.html b/vitepress/docs/.vitepress/dist/docs/linking-libraries-ios.html new file mode 100644 index 0000000..66382f3 --- /dev/null +++ b/vitepress/docs/.vitepress/dist/docs/linking-libraries-ios.html @@ -0,0 +1,27 @@ + + + + + + Vinculando Bibliotecas | React Native 0.72 + + + + + + + + + + + + + + + + +
Skip to content

Vinculando Bibliotecas

Nem todo aplicativo usa todos os recursos nativos, e incluir o código para suportar todos esses recursos afetaria o tamanho binário... Mas ainda queremos oferecer suporte à adição desses recursos sempre que você precisar deles.

Com isso em mente, expusemos muitos desses recursos como bibliotecas estáticas independentes.

Para a maioria das bibliotecas será tão rápido quanto arrastar dois arquivos, às vezes será necessário um terceiro passo, mas não mais que isso.

Observação

Todas as bibliotecas que enviamos com o React Native ficam na pasta Libraries na raiz do repositório. Alguns deles são JavaScript puro e você só precisa usar o require. Outras bibliotecas também dependem de algum código nativo; nesse caso, você terá que adicionar esses arquivos ao seu aplicativo, caso contrário, o aplicativo gerará um erro assim que você tentar usar a biblioteca.

Aqui estão algumas etapas para vincular suas bibliotecas que contêm código nativo

Vinculação automática

Instale uma biblioteca com dependências nativas:

bash
npm install <library-with-native-dependencies> --save

Informações

O sinalizador --save ou --save-dev é muito importante para esta etapa. React Native vinculará suas bibliotecas com base em dependencies e devDependencies em seu arquivo package.json.

É isso! Na próxima vez que você criar seu aplicativo, o código nativo será vinculado graças ao mecanismo autolinking.

Vinculação manual

Passo 1

Se a biblioteca possuir código nativo, deve haver um arquivo .xcodeproj dentro de sua pasta. Arraste este arquivo para o seu projeto no Xcode (geralmente no grupo Libraries no Xcode);

Passo 2

Clique no arquivo principal do seu projeto (aquele que representa o .xcodeproj) selecione Build Phases e arraste a biblioteca estática da pasta Products dentro da biblioteca que você está importando para Link Binary With Libraries

Etapa 3

Nem toda biblioteca precisará desta etapa, o que você precisa considerar é:

Preciso conhecer o conteúdo da biblioteca em tempo de compilação?

Isso significa que você está usando esta biblioteca no lado nativo ou apenas em JavaScript? Se você estiver usando apenas em JavaScript, está pronto para prosseguir!

Se você precisar chamá-lo do nativo, precisaremos saber os cabeçalhos da biblioteca. Para conseguir isso você deve ir ao arquivo do seu projeto, selecionar Build Settings e procurar por Header Search Paths. Lá você deve incluir o caminho para sua biblioteca. (Esta documentação costumava recomendar o uso de recursive, mas isso não é mais recomendado, pois pode causar falhas sutis de compilação, especialmente com CocoaPods.)

image

+ + + + \ No newline at end of file diff --git a/vitepress/docs/.vitepress/dist/docs/metro.html b/vitepress/docs/.vitepress/dist/docs/metro.html new file mode 100644 index 0000000..766114d --- /dev/null +++ b/vitepress/docs/.vitepress/dist/docs/metro.html @@ -0,0 +1,64 @@ + + + + + + Metro | React Native 0.72 + + + + + + + + + + + + + + + + +
Skip to content

Metro

React Native usa Metro para construir seu código JavaScript e ativos.

Configurando Metro

As opções de configuração do Metro podem ser personalizadas no arquivo metro.config.js do seu projeto. Isso pode exportar:

  • Um objeto (recomendado) que será mesclado com os padrões de configuração interna do Metro.
  • Uma função que será chamada com os padrões de configuração interna do Metro e deverá retornar um objeto de configuração final.

DICA

Consulte Configurando o Metro no site do Metro para obter documentação sobre todas as opções de configuração disponíveis.

No React Native, sua configuração Metro deve estender @react-native/metro-config ou @expo/metro-config. Esses pacotes contêm padrões essenciais necessários para construir e executar aplicativos React Native.

Abaixo está o arquivo metro.config.js padrão em um projeto de modelo React Native:

js
const {getDefaultConfig, mergeConfig} = require('@react-native/metro-config');
+
+/**
+ * Metro configuration
+ * https://facebook.github.io/metro/docs/configuration
+ *
+ * @type {import('metro-config').MetroConfig}
+ */
+const config = {};
+
+module.exports = mergeConfig(getDefaultConfig(__dirname), config);

As opções Metro que você deseja personalizar podem ser feitas dentro do objeto de configuração.

Avançado: usando uma função de configuração

Exportar uma função de configuração é uma opção para você mesmo gerenciar a configuração final – o Metro não aplicará nenhum padrão interno. Este padrão pode ser útil quando for necessário ler o objeto de configuração padrão base do Metro ou definir opções dinamicamente.

INFORMAÇÕES

A partir do @react-native/metro-config 0.72.1, não é mais necessário usar uma função de configuração para acessar a configuração padrão completa. Veja a seção de dicas abaixo.

js
const {getDefaultConfig, mergeConfig} = require('@react-native/metro-config');
+
+module.exports = function (baseConfig) {
+  const defaultConfig = mergeConfig(baseConfig, getDefaultConfig(__dirname));
+  const {resolver: {assetExts, sourceExts}} = defaultConfig;
+
+  return mergeConfig(
+    defaultConfig,
+    {
+      resolver: {
+        assetExts: assetExts.filter(ext => ext !== 'svg'),
+        sourceExts: [...sourceExts, 'svg'],
+      },
+    },
+  );
+};

DICA

Usar uma função de configuração é para casos de uso avançados. Um método mais simples do que o acima, por ex. para personalizar sourceExts, seria ler esses padrões em @react-native/metro-config.

Alternativa

js
const defaultConfig = getDefaultConfig(__dirname);
+ 
+const config = {
+  resolver: {
+    sourceExts: [...defaultConfig.resolver.sourceExts, 'svg'],
+  },
+};
+
+module.exports = mergeConfig(defaultConfig, config);

No entanto!, recomendamos copiar e editar ao substituir esses valores de configuração – colocando a fonte da verdade em seu arquivo de configuração.

✅ Recomendado

js
const config = {
+  resolver: {
+    sourceExts: ['js', 'ts', 'tsx', 'svg'],
+  },
+};
+ + + + \ No newline at end of file diff --git a/vitepress/docs/.vitepress/dist/docs/more-resources.html b/vitepress/docs/.vitepress/dist/docs/more-resources.html new file mode 100644 index 0000000..3f4a6b7 --- /dev/null +++ b/vitepress/docs/.vitepress/dist/docs/more-resources.html @@ -0,0 +1,27 @@ + + + + + + Mais recursos | React Native 0.72 + + + + + + + + + + + + + + + + +
Skip to content

Mais recursos

Sempre há mais para aprender: fluxos de trabalho de desenvolvedores, envio para lojas de aplicativos, internacionalização, segurança e muito mais.

Para onde ir a partir daqui:

Mergulho profundo

IDEs

Recomendamos usar o editor de código VS Code e suas úteis ferramentas React Native.

Plataformas para experimentar

Expo é uma estrutura de ferramentas e serviços para React Native que se concentra em ajudar você a construir, enviar e iterar em seu aplicativo, para usar fluxos de trabalho de implantação de visualização que são populares no desenvolvimento web e para automatizar seus fluxos de trabalho de desenvolvimento. A Expo também torna possível construir aplicativos React Native sem nunca tocar no Xcode ou no Android Studio, e não atrapalha se você quiser usar essas ferramentas.

Ignite é um kit inicial CLI com vários padrões React Native. O mais recente, Ignite Maverick, usa MobX-State-Tree para gerenciamento de estado, React Navigation e outras bibliotecas comuns. Possui geradores para telas, modelos e muito mais, e suporta Expo imediatamente. O Ignite também vem com uma biblioteca de componentes ajustada para designs personalizados, suporte a temas e testes. Se você está procurando uma pilha de tecnologia pré-configurada, o Ignite pode ser perfeito para você.

Aplicativos de exemplo

Experimente os aplicativos do Showcase para ver do que o React Native é capaz! Procurando algo mais prático? Confira este conjunto de aplicativos de exemplo no GitHub. Você pode ver o código-fonte deles – tente executar um em um simulador ou dispositivo.

Encontre, crie e compartilhe seus próprios componentes nativos e TurboModules

React Native tem uma comunidade de milhares de desenvolvedores como você, criando conteúdo, ferramentas, tutoriais – e componentes nativos!

Não consegue encontrar o que procura nos componentes principais? Visite React Native Directory para descobrir o que a comunidade está criando.

Interessado em criar seu próprio componente ou módulo nativo? Criar módulos para seu próprio caso de uso e compartilhá-los com outras pessoas no NPM e GitHub ajuda a expandir o ecossistema e a comunidade React Native! Leia os guias para criar seus próprios módulos nativos (Android, iOS) e componentes nativos (Android, iOS).

+ + + + \ No newline at end of file diff --git a/vitepress/docs/.vitepress/dist/docs/native-components-android.html b/vitepress/docs/.vitepress/dist/docs/native-components-android.html new file mode 100644 index 0000000..856d2be --- /dev/null +++ b/vitepress/docs/.vitepress/dist/docs/native-components-android.html @@ -0,0 +1,609 @@ + + + + + + Componentes de IU nativos do Android | React Native 0.72 + + + + + + + + + + + + + + + + +
Skip to content

Componentes de IU nativos do Android

INFORMAÇÕES

Módulo Nativo e Componentes Nativos são nossas tecnologias estáveis usadas pela arquitetura legada. Eles serão descontinuados no futuro, quando a Nova Arquitetura estiver estável. A nova arquitetura usa Turbo Native Module e Fabric Native Components para obter resultados semelhantes.

Existem muitos widgets de UI nativos prontos para serem usados nos aplicativos mais recentes - alguns deles fazem parte da plataforma, outros estão disponíveis como bibliotecas de terceiros e ainda mais podem estar em uso em seu próprio portfólio. React Native tem vários dos componentes de plataforma mais críticos já empacotados, como ScrollView e TextInput, mas não todos eles, e certamente não aqueles que você mesmo possa ter escrito para um aplicativo anterior. Felizmente, podemos agrupar esses componentes existentes para uma integração perfeita com seu aplicativo React Native.

Assim como o guia do módulo nativo, este também é um guia mais avançado que pressupõe que você esteja familiarizado com a programação do Android SDK. Este guia mostrará como construir um componente de UI nativo, orientando você na implementação de um subconjunto do componente ImageView existente disponível na biblioteca principal do React Native.

Exemplo de ImageView

Neste exemplo, examinaremos os requisitos de implementação para permitir o uso de ImageViews em JavaScript.

As visualizações nativas são criadas e manipuladas estendendo o ViewManager ou, mais comumente, o SimpleViewManager. Um SimpleViewManager é conveniente nesse caso porque aplica propriedades comuns, como cor de fundo, opacidade e layout Flexbox.

Essas subclasses são essencialmente singletons – apenas uma instância de cada é criada pela ponte. Eles enviam visualizações nativas para o NativeViewHierarchyManager, que delega de volta a eles a definição e atualização das propriedades das visualizações conforme necessário. Os ViewManagers também são normalmente os delegados das visualizações, enviando eventos de volta ao JavaScript por meio da ponte.

Para enviar uma view:

  1. Crie a subclasse ViewManager.
  2. Implemente o método createViewInstance
  3. Expor configuradores de propriedades de visualização usando a anotação @ReactProp (ou @ReactPropGroup)
  4. Cadastre o gerenciador em createViewManagers do pacote de aplicações.
  5. Implementar o módulo JavaScript

1. Crie a subclasse ViewManager

Neste exemplo, criamos a classe gerenciadora de visualizações ReactImageManager que estende SimpleViewManager do tipo ReactImageView. ReactImageView é o tipo de objeto controlado pelo gerenciador, esta será a visualização nativa customizada. O nome retornado por getName é usado para fazer referência ao tipo de visualização nativa do JavaScript.

java
public class ReactImageManager extends SimpleViewManager<ReactImageView> {
+
+  public static final String REACT_CLASS = "RCTImageView";
+  ReactApplicationContext mCallerContext;
+
+  public ReactImageManager(ReactApplicationContext reactContext) {
+    mCallerContext = reactContext;
+  }
+
+  @Override
+  public String getName() {
+    return REACT_CLASS;
+  }
+}
kotlin
class ReactImageManager(
+    private val callerContext: ReactApplicationContext
+) : SimpleViewManager<ReactImageView>() {
+
+  override fun getName() = REACT_CLASS
+
+  companion object {
+    const val REACT_CLASS = "RCTImageView"
+  }
+}

2. Implementar o método createViewInstance

As visualizações são criadas no método createViewInstance, a visualização deve ser inicializada em seu estado padrão, quaisquer propriedades serão definidas por meio de uma chamada de acompanhamento para updateView.

java
@Override
+  public ReactImageView createViewInstance(ThemedReactContext context) {
+    return new ReactImageView(context, Fresco.newDraweeControllerBuilder(), null, mCallerContext);
+  }
kotlin
  override fun createViewInstance(context: ThemedReactContext) =
+      ReactImageView(context, Fresco.newDraweeControllerBuilder(), null, callerContext)

3. Exponha os configuradores de propriedades de visualização usando a anotação @ReactProp (ou @ReactPropGroup)

As propriedades que devem ser refletidas em JavaScript precisam ser expostas como método setter anotado com @ReactProp (ou @ReactPropGroup). O método setter deve considerar a visão atualizada (do tipo de visão atual) como primeiro argumento e o valor da propriedade como segundo argumento. O setter deve ser público e não retornar um valor (ou seja, o tipo de retorno deve ser void em Java ou Unit em Kotlin). O tipo de propriedade enviado para JS é determinado automaticamente com base no tipo de argumento de valor do setter. Os seguintes tipos de valores são atualmente suportados (em Java): boolean, int, float, double, String, Boolean, Integer, ReadableArray, ReadableMap. Os tipos correspondentes em Kotlin são Boolean, Int, Float, Double, String, ReadableArray, ReadableMap`.

A anotação @ReactProp possui um nome de argumento obrigatório do tipo String. O nome atribuído à anotação @ReactProp vinculada ao método setter é usado para referenciar a propriedade no lado JS.

Exceto pelo nome, a anotação @ReactProp pode receber os seguintes argumentos opcionais: defaultBoolean, defaultInt, defaultFloat. Esses argumentos devem ser do tipo correspondente (respectivamente boolean, int, float em Java e Boolean, Int, Float em Kotlin) e o valor fornecido será passado para o método setter caso a propriedade que o setter está referenciando tenha sido removida do componente. Observe que os valores "padrão" são fornecidos apenas para tipos primitivos; caso o setter seja de algum tipo complexo, null será fornecido como valor padrão caso a propriedade correspondente seja removida.

Os requisitos de declaração do setter para métodos anotados com @ReactPropGroup são diferentes dos de @ReactProp. Consulte os documentos da classe de anotação @ReactPropGroup para obter mais informações sobre isso. IMPORTANTE! no ReactJS, atualizar o valor da propriedade resultará na chamada do método setter. Observe que uma das maneiras de atualizar o componente é removendo as propriedades que foram definidas anteriormente. Nesse caso, o método setter também será chamado para notificar o gerenciador de visualização de que a propriedade foi alterada. Nesse caso, o valor "default" será fornecido (para tipos primitivos, o valor "default" pode ser especificado usando argumentos defaultBoolean, defaultFloat, etc. da anotação @ReactProp, para tipos complexos, o setter será chamado com o valor definido como nulo).

java
  @ReactProp(name = "src")
+  public void setSrc(ReactImageView view, @Nullable ReadableArray sources) {
+    view.setSource(sources);
+  }
+
+  @ReactProp(name = "borderRadius", defaultFloat = 0f)
+  public void setBorderRadius(ReactImageView view, float borderRadius) {
+    view.setBorderRadius(borderRadius);
+  }
+
+  @ReactProp(name = ViewProps.RESIZE_MODE)
+  public void setResizeMode(ReactImageView view, @Nullable String resizeMode) {
+    view.setScaleType(ImageResizeMode.toScaleType(resizeMode));
+  }
kotlin
  @ReactProp(name = "src")
+  fun setSrc(view: ReactImageView, sources: ReadableArray?) {
+    view.setSource(sources)
+  }
+
+  @ReactProp(name = "borderRadius", defaultFloat = 0f)
+  override fun setBorderRadius(view: ReactImageView, borderRadius: Float) {
+    view.setBorderRadius(borderRadius)
+  }
+
+  @ReactProp(name = ViewProps.RESIZE_MODE)
+  fun setResizeMode(view: ReactImageView, resizeMode: String?) {
+    view.setScaleType(ImageResizeMode.toScaleType(resizeMode))
+  }

4. Cadastre o ViewManager

A etapa final é registrar o ViewManager na aplicação, isso acontece de forma semelhante aos Módulos Nativos, por meio da função membro do pacote de aplicações createViewManagers.

java
  @Override
+  public List<ViewManager> createViewManagers(
+                            ReactApplicationContext reactContext) {
+    return Arrays.<ViewManager>asList(
+      new ReactImageManager(reactContext)
+    );
+  }
kotlin
  override fun createViewManagers(
+      reactContext: ReactApplicationContext
+  ) = listOf(ReactImageManager(reactContext))

:::

5. Implemente o módulo JavaScript

A etapa final é criar o módulo JavaScript que define a camada de interface entre Java/Kotlin e JavaScript para os usuários de sua nova visualização. É recomendado que você documente a interface do componente neste módulo (por exemplo, usando TypeScript, Flow ou comentários antigos).

tsx
// ImageView.tsx
+
+import {requireNativeComponent} from 'react-native';
+
+/**
+ * Composes `View`.
+ *
+ * - src: string
+ * - borderRadius: number
+ * - resizeMode: 'cover' | 'contain' | 'stretch'
+ */
+module.exports = requireNativeComponent('RCTImageView');

A função requireNativeComponent leva o nome da visualização nativa. Observe que se o seu componente precisar fazer algo mais sofisticado (por exemplo, manipulação de eventos personalizados), você deverá agrupar o componente nativo em outro componente React. Isso é ilustrado no exemplo MyCustomView abaixo.

Eventos

Agora sabemos como expor componentes de visualização nativa que podemos controlar livremente a partir de JS, mas como lidamos com eventos do usuário, como pinçar zoom ou panorâmica? Quando ocorre um evento nativo, o código nativo deve emitir um evento para a representação JavaScript da View, e as duas visualizações são vinculadas ao valor retornado do método getId().

java
class MyCustomView extends View {
+   ...
+   public void onReceiveNativeEvent() {
+      WritableMap event = Arguments.createMap();
+      event.putString("message", "MyMessage");
+      ReactContext reactContext = (ReactContext)getContext();
+      reactContext
+          .getJSModule(RCTEventEmitter.class)
+          .receiveEvent(getId(), "topChange", event);
+    }
+}
kotlin
class MyCustomView(context: Context) : View(context) {
+  ...
+  fun onReceiveNativeEvent() {
+    val event = Arguments.createMap().apply {
+      putString("message", "MyMessage")
+    }
+    val reactContext = context as ReactContext
+    reactContext
+        .getJSModule(RCTEventEmitter::class.java)
+        .receiveEvent(id, "topChange", event)
+  }
+}

Para mapear o nome do evento topChange para a propriedade de retorno de chamada onChange em JavaScript, registre-o substituindo o método getExportedCustomBubblingEventTypeConstants em seu ViewManager:

java
public class ReactImageManager extends SimpleViewManager<MyCustomView> {
+    ...
+    public Map getExportedCustomBubblingEventTypeConstants() {
+        return MapBuilder.builder().put(
+            "topChange",
+            MapBuilder.of(
+                "phasedRegistrationNames",
+                MapBuilder.of("bubbled", "onChange")
+            )
+        ).build();
+    }
+}
kotlin
class ReactImageManager : SimpleViewManager<MyCustomView>() {
+  ...
+  override fun getExportedCustomBubblingEventTypeConstants(): Map<String, Any> {
+    return mapOf(
+      "topChange" to mapOf(
+        "phasedRegistrationNames" to mapOf(
+          "bubbled" to "onChange"
+        )
+      )
+    )
+  }
+}

Esse retorno de chamada é invocado com o evento bruto, que normalmente processamos no componente wrapper para criar uma API mais simples:

tsx
// MyCustomView.tsx
+
+class MyCustomView extends React.Component {
+  constructor(props) {
+    super(props);
+    this._onChange = this._onChange.bind(this);
+  }
+  _onChange(event) {
+    if (!this.props.onChangeMessage) {
+      return;
+    }
+    this.props.onChangeMessage(event.nativeEvent.message);
+  }
+  render() {
+    return <RCTMyCustomView {...this.props} onChange={this._onChange} />;
+  }
+}
+MyCustomView.propTypes = {
+  /**
+   * Retorno de chamada que é chamado continuamente quando o usuário arrasta o mapa.
+   */
+  onChangeMessage: PropTypes.func,
+  ...
+};
+
+const RCTMyCustomView = requireNativeComponent(`RCTMyCustomView`);

Exemplo de integração com um fragmento Android

Para integrar elementos de UI nativa existentes ao seu aplicativo React Native, pode ser necessário usar Android Fragments para fornecer um controle mais granular sobre seu componente nativo do que retornar uma View do seu ViewManager. Você precisará disso se quiser adicionar lógica personalizada vinculada à sua visualização com a ajuda de métodos de ciclo de vida, como onViewCreated, onPause, onResume. As etapas a seguir mostrarão como fazer isso:

1. Crie um exemplo de visualização personalizada

Primeiro, vamos criar uma classe CustomView que estende FrameLayout (o conteúdo desta visualização pode ser qualquer visualização que você gostaria de renderizar)

java
// substitua pelo seu pacote
+package com.mypackage;
+
+import android.content.Context;
+import android.graphics.Color;
+import android.widget.FrameLayout;
+import android.widget.ImageView;
+import android.widget.TextView;
+
+import androidx.annotation.NonNull;
+
+public class CustomView extends FrameLayout {
+  public CustomView(@NonNull Context context) {
+    super(context);
+    // definir preenchimento e cor de fundo
+    this.setPadding(16,16,16,16);
+    this.setBackgroundColor(Color.parseColor("#5FD3F3"));
+
+    // adicionar visualização de texto padrão
+    TextView text = new TextView(context);
+    text.setText("Welcome to Android Fragments with React Native.");
+    this.addView(text);
+  }
+}
kotlin
// substitua pelo seu pacote
+package com.mypackage
+
+import android.content.Context
+import android.graphics.Color
+import android.widget.FrameLayout
+import android.widget.TextView
+
+class CustomView(context: Context) : FrameLayout(context) {
+  init {
+    // definir preenchimento e cor de fundo
+    setPadding(16,16,16,16)
+    setBackgroundColor(Color.parseColor("#5FD3F3"))
+
+    // adicionar visualização de texto padrão
+    addView(TextView(context).apply {
+      text = "Welcome to Android Fragments with React Native."
+    })
+  }
+}

2. Crie um fragmento

java
// replace with your package
+package com.mypackage;
+
+import android.os.Bundle;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+import androidx.fragment.app.Fragment;
+
+// replace with your view's import
+import com.mypackage.CustomView;
+
+public class MyFragment extends Fragment {
+    CustomView customView;
+
+    @Override
+    public View onCreateView(LayoutInflater inflater, ViewGroup parent, Bundle savedInstanceState) {
+        super.onCreateView(inflater, parent, savedInstanceState);
+        customView = new CustomView(this.getContext());
+        return customView; // this CustomView could be any view that you want to render
+    }
+
+    @Override
+    public void onViewCreated(View view, Bundle savedInstanceState) {
+        super.onViewCreated(view, savedInstanceState);
+        // do any logic that should happen in an `onCreate` method, e.g:
+        // customView.onCreate(savedInstanceState);
+    }
+
+    @Override
+    public void onPause() {
+        super.onPause();
+        // do any logic that should happen in an `onPause` method
+        // e.g.: customView.onPause();
+    }
+
+    @Override
+    public void onResume() {
+        super.onResume();
+       // do any logic that should happen in an `onResume` method
+       // e.g.: customView.onResume();
+    }
+
+    @Override
+    public void onDestroy() {
+        super.onDestroy();
+        // do any logic that should happen in an `onDestroy` method
+        // e.g.: customView.onDestroy();
+    }
+}
kt
// substitua pelo seu pacote
+package com.mypackage
+
+import android.os.Bundle
+import android.view.LayoutInflater
+import android.view.View
+import android.view.ViewGroup
+import androidx.fragment.app.Fragment
+
+// substitua pela importação da sua visualização
+import com.mypackage.CustomView
+
+class MyFragment : Fragment() {
+  private lateinit var customView: CustomView
+
+  override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View {
+    super.onCreateView(inflater, container, savedInstanceState)
+    customView = CustomView(requireNotNull(context))
+    return customView // este CustomView pode ser qualquer visualização que você deseja renderizar
+  }
+
+  override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
+    super.onViewCreated(view, savedInstanceState)
+    // faça qualquer lógica que deva acontecer em um método `onCreate`, por exemplo:
+    // customView.onCreate(savedInstanceState);
+  }
+
+  override fun onPause() {
+    super.onPause()
+    // faça qualquer lógica que deveria acontecer em um método `onPause`
+    // por exemplo: customView.onPause();
+  }
+
+  override fun onResume() {
+    super.onResume()
+    // faz qualquer lógica que deveria acontecer em um método `onResume`
+    // por exemplo: customView.onResume();
+  }
+
+  override fun onDestroy() {
+    super.onDestroy()
+    // faça qualquer lógica que deveria acontecer em um método `onDestroy`
+    // por exemplo: customView.onDestroy();
+  }
+}

3. Crie a subclasse ViewManager

java
// replace with your package
+package com.mypackage;
+
+import android.view.Choreographer;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.FrameLayout;
+
+import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
+import androidx.fragment.app.FragmentActivity;
+
+import com.facebook.react.bridge.ReactApplicationContext;
+import com.facebook.react.bridge.ReadableArray;
+import com.facebook.react.common.MapBuilder;
+import com.facebook.react.uimanager.annotations.ReactProp;
+import com.facebook.react.uimanager.annotations.ReactPropGroup;
+import com.facebook.react.uimanager.ViewGroupManager;
+import com.facebook.react.uimanager.ThemedReactContext;
+
+import java.util.Map;
+
+public class MyViewManager extends ViewGroupManager<FrameLayout> {
+
+  public static final String REACT_CLASS = "MyViewManager";
+  public final int COMMAND_CREATE = 1;
+  private int propWidth;
+  private int propHeight;
+
+  ReactApplicationContext reactContext;
+
+  public MyViewManager(ReactApplicationContext reactContext) {
+    this.reactContext = reactContext;
+  }
+
+  @Override
+  public String getName() {
+    return REACT_CLASS;
+  }
+
+  /**
+   * Return a FrameLayout which will later hold the Fragment
+   */
+  @Override
+  public FrameLayout createViewInstance(ThemedReactContext reactContext) {
+    return new FrameLayout(reactContext);
+  }
+
+  /**
+   * Map the "create" command to an integer
+   */
+  @Nullable
+  @Override
+  public Map<String, Integer> getCommandsMap() {
+    return MapBuilder.of("create", COMMAND_CREATE);
+  }
+
+  /**
+   * Handle "create" command (called from JS) and call createFragment method
+   */
+  @Override
+  public void receiveCommand(
+    @NonNull FrameLayout root,
+    String commandId,
+    @Nullable ReadableArray args
+  ) {
+    super.receiveCommand(root, commandId, args);
+    int reactNativeViewId = args.getInt(0);
+    int commandIdInt = Integer.parseInt(commandId);
+
+    switch (commandIdInt) {
+      case COMMAND_CREATE:
+        createFragment(root, reactNativeViewId);
+        break;
+      default: {}
+    }
+  }
+
+  @ReactPropGroup(names = {"width", "height"}, customType = "Style")
+  public void setStyle(FrameLayout view, int index, Integer value) {
+    if (index == 0) {
+      propWidth = value;
+    }
+
+    if (index == 1) {
+      propHeight = value;
+    }
+  }
+
+  /**
+   * Replace your React Native view with a custom fragment
+   */
+  public void createFragment(FrameLayout root, int reactNativeViewId) {
+    ViewGroup parentView = (ViewGroup) root.findViewById(reactNativeViewId);
+    setupLayout(parentView);
+
+    final MyFragment myFragment = new MyFragment();
+    FragmentActivity activity = (FragmentActivity) reactContext.getCurrentActivity();
+    activity.getSupportFragmentManager()
+            .beginTransaction()
+            .replace(reactNativeViewId, myFragment, String.valueOf(reactNativeViewId))
+            .commit();
+  }
+
+  public void setupLayout(View view) {
+    Choreographer.getInstance().postFrameCallback(new Choreographer.FrameCallback() {
+      @Override
+      public void doFrame(long frameTimeNanos) {
+        manuallyLayoutChildren(view);
+        view.getViewTreeObserver().dispatchOnGlobalLayout();
+        Choreographer.getInstance().postFrameCallback(this);
+      }
+    });
+  }
+
+  /**
+   * Layout all children properly
+   */
+  public void manuallyLayoutChildren(View view) {
+      // propWidth and propHeight coming from react-native props
+      int width = propWidth;
+      int height = propHeight;
+
+      view.measure(
+              View.MeasureSpec.makeMeasureSpec(width, View.MeasureSpec.EXACTLY),
+              View.MeasureSpec.makeMeasureSpec(height, View.MeasureSpec.EXACTLY));
+
+      view.layout(0, 0, width, height);
+  }
+}
kt
// substitua pelo seu pacote
+package com.mypackage
+
+import android.view.Choreographer
+import android.view.View
+import android.view.ViewGroup
+import android.widget.FrameLayout
+import androidx.fragment.app.FragmentActivity
+import com.facebook.react.bridge.ReactApplicationContext
+import com.facebook.react.bridge.ReadableArray
+import com.facebook.react.uimanager.ThemedReactContext
+import com.facebook.react.uimanager.ViewGroupManager
+import com.facebook.react.uimanager.annotations.ReactPropGroup
+
+class MyViewManager(
+    private val reactContext: ReactApplicationContext
+) : ViewGroupManager<FrameLayout>() {
+  private var propWidth: Int? = null
+  private var propHeight: Int? = null
+
+  override fun getName() = REACT_CLASS
+
+  /**
+   * Retorne um FrameLayout que posteriormente conterá o Fragment
+   */
+  override fun createViewInstance(reactContext: ThemedReactContext) =
+      FrameLayout(reactContext)
+
+  /**
+   * Mapeie o comando "create" para um número inteiro
+   */
+  override fun getCommandsMap() = mapOf("create" to COMMAND_CREATE)
+
+  /**
+   * Lidar com o comando "create" (chamado de JS) e chamar o método createFragment
+   */
+  override fun receiveCommand(
+      root: FrameLayout,
+      commandId: String,
+      args: ReadableArray?
+  ) {
+    super.receiveCommand(root, commandId, args)
+    val reactNativeViewId = requireNotNull(args).getInt(0)
+
+    when (commandId.toInt()) {
+      COMMAND_CREATE -> createFragment(root, reactNativeViewId)
+    }
+  }
+
+  @ReactPropGroup(names = ["width", "height"], customType = "Style")
+  fun setStyle(view: FrameLayout, index: Int, value: Int) {
+    if (index == 0) propWidth = value
+    if (index == 1) propHeight = value
+  }
+
+  /**
+   * Substitua sua visualização React Native por um fragmento personalizado
+   */
+  fun createFragment(root: FrameLayout, reactNativeViewId: Int) {
+    val parentView = root.findViewById<ViewGroup>(reactNativeViewId)
+    setupLayout(parentView)
+
+    val myFragment = MyFragment()
+    val activity = reactContext.currentActivity as FragmentActivity
+    activity.supportFragmentManager
+        .beginTransaction()
+        .replace(reactNativeViewId, myFragment, reactNativeViewId.toString())
+        .commit()
+  }
+
+  fun setupLayout(view: View) {
+    Choreographer.getInstance().postFrameCallback(object: Choreographer.FrameCallback {
+      override fun doFrame(frameTimeNanos: Long) {
+        manuallyLayoutChildren(view)
+        view.viewTreeObserver.dispatchOnGlobalLayout()
+        Choreographer.getInstance().postFrameCallback(this)
+      }
+    })
+  }
+
+  /**
+   * Disponha todas as crianças corretamente
+   */
+  private fun manuallyLayoutChildren(view: View) {
+    // propWidth e propHeight provenientes de adereços nativos de do react
+    val width = requireNotNull(propWidth)
+    val height = requireNotNull(propHeight)
+
+    view.measure(
+        View.MeasureSpec.makeMeasureSpec(width, View.MeasureSpec.EXACTLY),
+        View.MeasureSpec.makeMeasureSpec(height, View.MeasureSpec.EXACTLY))
+
+    view.layout(0, 0, width, height)
+  }
+
+  companion object {
+    private const val REACT_CLASS = "MyViewManager"
+    private const val COMMAND_CREATE = 1
+  }
+}

4. Cadastre o ViewManager

java
// replace with your package
+package com.mypackage;
+
+import com.facebook.react.ReactPackage;
+import com.facebook.react.bridge.ReactApplicationContext;
+import com.facebook.react.uimanager.ViewManager;
+
+import java.util.Arrays;
+import java.util.List;
+
+public class MyPackage implements ReactPackage {
+
+   @Override
+   public List<ViewManager> createViewManagers(ReactApplicationContext reactContext) {
+       return Arrays.<ViewManager>asList(
+            new MyViewManager(reactContext)
+       );
+   }
+
+}
kt
// substitua pelo seu pacote
+package com.mypackage
+
+import com.facebook.react.ReactPackage
+import com.facebook.react.bridge.ReactApplicationContext
+import com.facebook.react.uimanager.ViewManager
+
+class MyPackage : ReactPackage {
+  ...
+  override fun createViewManagers(
+      reactContext: ReactApplicationContext
+  ) = listOf(MyViewManager(reactContext))
+}

5. Registre o Package

java
@Override
+protected List<ReactPackage> getPackages() {
+  List<ReactPackage> packages = new PackageList(this).getPackages();
+  ...
+  packages.add(new MyPackage());
+  return packages;
+}
kt
override fun getPackages() = PackageList(this).packages.apply {
+  add(MyPackage())
+}

6. Implemente o módulo JavaScript

I. Comece com o gerenciador de visualização personalizado:

tsx
// MyViewManager.tsx
+
+import {requireNativeComponent} from 'react-native';
+
+export const MyViewManager =
+  requireNativeComponent('MyViewManager');

II. Em seguida, implemente a View personalizada chamando o método create:

tsx
import React, {useEffect, useRef} from 'react';
+import {
+  PixelRatio,
+  UIManager,
+  findNodeHandle,
+} from 'react-native';
+
+import {MyViewManager} from './my-view-manager';
+
+const createFragment = viewId =>
+  UIManager.dispatchViewManagerCommand(
+    viewId,
+    // estamos chamando o comando 'criar'
+    UIManager.MyViewManager.Commands.create.toString(),
+    [viewId],
+  );
+
+export const MyView = () => {
+  const ref = useRef(null);
+
+  useEffect(() => {
+    const viewId = findNodeHandle(ref.current);
+    createFragment(viewId);
+  }, []);
+
+  return (
+    <MyViewManager
+      style={{
+        // converte dpi em px, fornece a altura desejada
+        height: PixelRatio.getPixelSizeForLayoutSize(200),
+        // converte dpi em px, fornece a largura desejada
+        width: PixelRatio.getPixelSizeForLayoutSize(200),
+      }}
+      ref={ref}
+    />
+  );
+};

Se você deseja expor configuradores de propriedades usando a anotação @ReactProp (ou @ReactPropGroup), consulte o exemplo ImageView acima.

+ + + + \ No newline at end of file diff --git a/vitepress/docs/.vitepress/dist/docs/native-components-ios.html b/vitepress/docs/.vitepress/dist/docs/native-components-ios.html new file mode 100644 index 0000000..053893a --- /dev/null +++ b/vitepress/docs/.vitepress/dist/docs/native-components-ios.html @@ -0,0 +1,362 @@ + + + + + + Componentes de UI nativos do iOS | React Native 0.72 + + + + + + + + + + + + + + + + +
Skip to content

Componentes de UI nativos do iOS

INFORMAÇÕES

Módulo Nativo e Componentes Nativos são nossas tecnologias estáveis usadas pela arquitetura legada. Eles serão descontinuados no futuro, quando a Nova Arquitetura estiver estável. A nova arquitetura usa Turbo Native Module e Fabric Native Components para obter resultados semelhantes.

Existem muitos widgets de UI nativos prontos para serem usados nos aplicativos mais recentes - alguns deles fazem parte da plataforma, outros estão disponíveis como bibliotecas de terceiros e ainda mais podem estar em uso em seu próprio portfólio. React Native tem vários dos componentes de plataforma mais críticos já empacotados, como ScrollView e TextInput, mas não todos eles, e certamente não aqueles que você mesmo possa ter escrito para um aplicativo anterior. Felizmente, podemos agrupar esses componentes existentes para uma integração perfeita com seu aplicativo React Native.

Assim como o guia do módulo nativo, este também é um guia mais avançado que pressupõe que você esteja familiarizado com a programação iOS. Este guia mostrará como construir um componente de UI nativo, orientando você na implementação de um subconjunto do componente MapView existente disponível na biblioteca principal do React Native.

Exemplo de MapView para iOS

Digamos que queremos adicionar um mapa interativo ao nosso aplicativo - podemos também usar MKMapView, só precisamos torná-lo utilizável a partir de JavaScript.

As visualizações nativas são criadas e manipuladas por subclasses de RCTViewManager. Essas subclasses são semelhantes em função aos controladores de visualização, mas são essencialmente singletons - apenas uma instância de cada é criada pela ponte. Eles expõem visualizações nativas ao RCTUIManager, que delega a eles a definição e atualização das propriedades das visualizações conforme necessário. Os RCTViewManagers também são normalmente os delegados das visualizações, enviando eventos de volta ao JavaScript por meio da ponte.

Para expor uma visualização, você pode:

  • Subclasse RCTViewManager para criar um gerenciador para seu componente.
  • Adicione a macro do marcador RCT_EXPORT_MODULE().
  • Implemente o método -(UIView *)view.
c
// RNTMapManager.m
+
+#import <MapKit/MapKit.h>
+
+#import <React/RCTViewManager.h>
+
+@interface RNTMapManager : RCTViewManager
+@end
+
+@implementation RNTMapManager
+
+RCT_EXPORT_MODULE(RNTMap)
+
+- (UIView *)view
+{
+  return [[MKMapView alloc] init];
+}
+
+@end

OBSERVAÇÃO

Não tente definir as propriedades frame ou backgroundColor na instância UIView que você expõe por meio do método -view. O React Native substituirá os valores definidos pela sua classe personalizada para corresponder aos adereços de layout do seu componente JavaScript. Se você precisar dessa granularidade de controle, talvez seja melhor agrupar a instância do UIView que você deseja estilizar em outro UIView e retornar o UIView do wrapper. Consulte a edição 2948 para obter mais contexto.

DICA

No exemplo acima, prefixamos nosso nome de classe com RNT. Os prefixos são usados para evitar colisões de nomes com outras estruturas. As estruturas Apple usam prefixos de duas letras e o React Native usa RCT como prefixo. Para evitar colisões de nomes, recomendamos usar um prefixo de três letras diferente de RCT em suas próprias classes.

Então você precisa de um pouco de JavaScript para tornar este um componente React utilizável:

tsx
// MapView.tsx
+
+import {requireNativeComponent} from 'react-native';
+
+// requireNativeComponent resolve automaticamente 'RNTMap' para 'RNTMapManager'
+module.exports = requireNativeComponent('RNTMap');
tsx
// MyApp.tsx
+
+import MapView from './MapView.tsx';
+
+...
+
+render() {
+  return <MapView style={{flex: 1}} />;
+}

Certifique-se de usar RNTMap aqui. Queremos exigir o gerenciador aqui, que irá expor a visão do nosso gerenciador para uso em JavaScript.

OBSERVAÇÃO

Ao renderizar, não se esqueça de esticar a visualização, caso contrário você estará olhando para uma tela em branco.

tsx
  render() {
+    return <MapView style={{flex: 1}} />;
+  }

Este é agora um componente de visualização de mapa nativo totalmente funcional em JavaScript, completo com zoom de pinça e outros suportes a gestos nativos. Ainda não podemos controlá-lo a partir do JavaScript 😦

Propriedades

A primeira coisa que podemos fazer para tornar este componente mais utilizável é conectar algumas propriedades nativas. Digamos que queremos desabilitar o zoom e especificar a região visível. Desativar o zoom é um booleano, então adicionamos esta linha:

c
// RNTMapManager.m
+
+RCT_EXPORT_VIEW_PROPERTY(zoomEnabled, BOOL)

Observe que especificamos explicitamente o tipo como BOOL - React Native usa RCTConvert nos bastidores para converter todos os tipos de tipos de dados diferentes ao falar pela ponte, e valores incorretos mostrarão erros "RedBox" convenientes para que você saiba que há um problema o mais rápido possível . Quando as coisas são simples assim, toda a implementação é feita por esta macro.

Agora, para realmente desabilitar o zoom, definimos a propriedade em JS:

tsx
// MyApp.tsx
+
+<MapView zoomEnabled={false} style={{flex: 1}} />

Para documentar as propriedades (e quais valores elas aceitam) do nosso componente MapView, adicionaremos um componente wrapper e documentaremos a interface com React PropTypes:

tsx
// MapView.tsx
+
+import PropTypes from 'prop-types';
+import React from 'react';
+import {requireNativeComponent} from 'react-native';
+
+class MapView extends React.Component {
+  render() {
+    return <RNTMap {...this.props} />;
+  }
+}
+
+MapView.propTypes = {
+  /**
+   * Um valor booleano que determina se o usuário pode usar pinçar
+   * gestos para aumentar e diminuir o zoom do mapa.
+   */
+  zoomEnabled: PropTypes.bool,
+};
+
+const RNTMap = requireNativeComponent('RNTMap');
+
+module.exports = MapView;

Agora temos um componente wrapper bem documentado para trabalhar.

A seguir, vamos adicionar a propriedade de region mais complexa. Começamos adicionando o código nativo:

c
// RNTMapManager.m
+
+RCT_CUSTOM_VIEW_PROPERTY(region, MKCoordinateRegion, MKMapView)
+{
+  [view setRegion:json ? [RCTConvert MKCoordinateRegion:json] : defaultView.region animated:YES];
+}

Ok, isso é mais complicado do que o caso BOOL que tivemos antes. Agora temos um tipo MKCoordenRegion que precisa de uma função de conversão e temos um código personalizado para que a visualização seja animada quando definirmos a região de JS. Dentro do corpo da função que fornecemos, json refere-se ao valor bruto que foi passado de JS. Há também uma variável de visualização que nos dá acesso à instância de visualização do gerenciador e um defaultView que usamos para redefinir a propriedade de volta ao valor padrão se JS nos enviar um sentinela nulo.

Você pode escrever qualquer função de conversão que desejar para sua visualização - aqui está a implementação de MKCoordenRegion por meio de uma categoria no RCTConvert. Ele usa uma categoria já existente de ReactNative RCTConvert+CoreLocation:

c
// RNTMapManager.m
+
+#import "RCTConvert+Mapkit.h"
c
RCTConvert+Mapkit.h
+#import <MapKit/MapKit.h>
+#import <React/RCTConvert.h>
+#import <CoreLocation/CoreLocation.h>
+#import <React/RCTConvert+CoreLocation.h>
+
+@interface RCTConvert (Mapkit)
+
++ (MKCoordinateSpan)MKCoordinateSpan:(id)json;
++ (MKCoordinateRegion)MKCoordinateRegion:(id)json;
+
+@end
+
+@implementation RCTConvert(MapKit)
+
++ (MKCoordinateSpan)MKCoordinateSpan:(id)json
+{
+  json = [self NSDictionary:json];
+  return (MKCoordinateSpan){
+    [self CLLocationDegrees:json[@"latitudeDelta"]],
+    [self CLLocationDegrees:json[@"longitudeDelta"]]
+  };
+}
+
++ (MKCoordinateRegion)MKCoordinateRegion:(id)json
+{
+  return (MKCoordinateRegion){
+    [self CLLocationCoordinate2D:json],
+    [self MKCoordinateSpan:json]
+  };
+}
+
+@end

Essas funções de conversão são projetadas para processar com segurança qualquer JSON que o JS possa lançar neles, exibindo erros "RedBox" e retornando valores de inicialização padrão quando chaves ausentes ou outros erros do desenvolvedor são encontrados.

Para finalizar o suporte para a propriedade region, precisamos documentá-la em propTypes:

tsx
// MapView.tsx
+
+MapView.propTypes = {
+  /**
+   * Um valor booleano que determina se o usuário pode usar o gesto de pinça
+   * para aumentar e diminuir o zoom do mapa.
+   */
+  zoomEnabled: PropTypes.bool,
+
+  /**
+   * A região a ser exibida pelo mapa.
+   *
+   * A região é definida pelas coordenadas do centro e pela extensão do
+   * coordenadas a serem exibidas.
+   */
+  region: PropTypes.shape({
+    /**
+     * Coordenadas para o centro do mapa.
+     */
+    latitude: PropTypes.number.isRequired,
+    longitude: PropTypes.number.isRequired,
+
+    /**
+     * Distância entre a latitude/longitude mínima e máxima
+     * a ser exibida.
+     */
+    latitudeDelta: PropTypes.number.isRequired,
+    longitudeDelta: PropTypes.number.isRequired,
+  }),
+};
tsx
// MyApp.tsx
+
+render() {
+  const region = {
+    latitude: 37.48,
+    longitude: -122.16,
+    latitudeDelta: 0.1,
+    longitudeDelta: 0.1,
+  };
+  return (
+    <MapView
+      region={region}
+      zoomEnabled={false}
+      style={{flex: 1}}
+    />
+  );
+}

Aqui você pode ver que o formato da região está explícito na documentação JS.

Eventos

Portanto, agora temos um componente de mapa nativo que podemos controlar livremente a partir de JS, mas como lidamos com eventos do usuário, como pinçar zoom ou panorâmica para alterar a região visível?

Até agora, retornamos apenas uma instância MKMapView do método -(UIView *)view do nosso gerente. Não podemos adicionar novas propriedades ao MKMapView, então temos que criar uma nova subclasse do MKMapView que usaremos para nossa View. Podemos então adicionar um retorno de chamada onRegionChange nesta subclasse:

c
// RNTMapView.h
+
+#import <MapKit/MapKit.h>
+
+#import <React/RCTComponent.h>
+
+@interface RNTMapView: MKMapView
+
+@property (nonatomic, copy) RCTBubblingEventBlock onRegionChange;
+
+@end
c
// RNTMapView.m
+
+#import "RNTMapView.h"
+
+@implementation RNTMapView
+
+@end

Observe que todos os RCTBubblingEventBlock devem ser prefixados com on. Em seguida, declare uma propriedade de manipulador de eventos em RNTMapManager, torne-a um delegado para todas as visualizações que expõe e encaminhe eventos para JS chamando o bloco do manipulador de eventos a partir da visualização nativa.

c
// RNTMapManager.m
+
+#import <MapKit/MapKit.h>
+#import <React/RCTViewManager.h>
+
+#import "RNTMapView.h"
+#import "RCTConvert+Mapkit.h"
+
+@interface RNTMapManager : RCTViewManager <MKMapViewDelegate>
+@end
+
+@implementation RNTMapManager
+
+RCT_EXPORT_MODULE()
+
+RCT_EXPORT_VIEW_PROPERTY(zoomEnabled, BOOL)
+RCT_EXPORT_VIEW_PROPERTY(onRegionChange, RCTBubblingEventBlock)
+
+RCT_CUSTOM_VIEW_PROPERTY(region, MKCoordinateRegion, MKMapView)
+{
+  [view setRegion:json ? [RCTConvert MKCoordinateRegion:json] : defaultView.region animated:YES];
+}
+
+- (UIView *)view
+{
+  RNTMapView *map = [RNTMapView new];
+  map.delegate = self;
+  return map;
+}
+
+#pragma mark MKMapViewDelegate
+
+- (void)mapView:(RNTMapView *)mapView regionDidChangeAnimated:(BOOL)animated
+{
+  if (!mapView.onRegionChange) {
+    return;
+  }
+
+  MKCoordinateRegion region = mapView.region;
+  mapView.onRegionChange(@{
+    @"region": @{
+      @"latitude": @(region.center.latitude),
+      @"longitude": @(region.center.longitude),
+      @"latitudeDelta": @(region.span.latitudeDelta),
+      @"longitudeDelta": @(region.span.longitudeDelta),
+    }
+  });
+}
+@end

No método delegado -mapView:regionDidChangeAnimated: o bloco manipulador de eventos é chamado na visualização correspondente com os dados da região. Chamar o bloco do manipulador de eventos onRegionChange resulta na chamada do mesmo suporte de retorno de chamada em JavaScript. Esse retorno de chamada é invocado com o evento bruto, que normalmente processamos no componente wrapper para simplificar a API:

tsx
MapView.tsx
+class MapView extends React.Component {
+  _onRegionChange = event => {
+    if (!this.props.onRegionChange) {
+      return;
+    }
+
+    // processar evento bruto...
+    this.props.onRegionChange(event.nativeEvent);
+  };
+  render() {
+    return (
+      <RNTMap
+        {...this.props}
+        onRegionChange={this._onRegionChange}
+      />
+    );
+  }
+}
+MapView.propTypes = {
+  /**
+   * Retorno de chamada que é chamado continuamente quando o usuário arrasta o mapa.
+   */
+  onRegionChange: PropTypes.func,
+  ...
+};
tsx
// MyApp.tsx
+
+class MyApp extends React.Component {
+  onRegionChange(event) {
+    // Faça coisas com event.region.latitude, etc.
+  }
+
+  render() {
+    const region = {
+      latitude: 37.48,
+      longitude: -122.16,
+      latitudeDelta: 0.1,
+      longitudeDelta: 0.1,
+    };
+    return (
+      <MapView
+        region={region}
+        zoomEnabled={false}
+        onRegionChange={this.onRegionChange}
+      />
+    );
+  }
+}

Lidando com múltiplas visualizações nativas

Uma visualização React Native pode ter mais de uma visualização filha na árvore de visualização, por exemplo.

tsx
<View>
+  <MyNativeView />
+  <MyNativeView />
+  <Button />
+</View>

Neste exemplo, a classe MyNativeView é um wrapper para 'NativeComponente expõe métodos que serão chamados na plataforma iOS.MyNativeViewé definido emMyNativeView.ios.jse contém métodos proxy deNativeComponent`.

Quando o usuário interage com o componente, como clicar no botão, a backgroundColor de MyNativeView muda. Nesse caso, o UIManager não saberia qual MyNativeView deveria ser tratado e qual deveria mudar backgroundColor. Abaixo você encontrará uma solução para este problema:

tsx
<View>
+  <MyNativeView ref={this.myNativeReference} />
+  <MyNativeView ref={this.myNativeReference2} />
+  <Button
+    onPress={() => {
+      this.myNativeReference.callNativeMethod();
+    }}
+  />
+</View>

Agora, o componente acima tem uma referência a um MyNativeView específico que nos permite usar uma instância específica de MyNativeView. Agora o botão pode controlar qual MyNativeView deve alterar sua cor de fundo. Neste exemplo, vamos supor que callNativeMethod altere backgroundColor.

tsx
MyNativeView.ios.tsx
+class MyNativeView extends React.Component {
+  callNativeMethod = () => {
+    UIManager.dispatchViewManagerCommand(
+      ReactNative.findNodeHandle(this),
+      UIManager.getViewManagerConfig('RNCMyNativeView').Commands
+        .callNativeMethod,
+      [],
+    );
+  };
+
+  render() {
+    return <NativeComponent ref={NATIVE_COMPONENT_REF} />;
+  }
+}

callNativeMethod é nosso método iOS personalizado que, por exemplo, altera o backgroundColor que é exposto por meio de MyNativeView. Este método usa UIManager.dispatchViewManagerCommand que precisa de 3 parâmetros:

  • (nonnull NSNumber \*)reactTag  -  id da visualização de reação.
  • commandID:(NSInteger)commandID  -  Id do método nativo que deve ser chamado
  • commandArgs:(NSArray<id> \*)commandArgs  -  Args do método nativo que podemos passar de JS para nativo.
c
// RNCMyNativeViewManager.m
+
+#import <React/RCTViewManager.h>
+#import <React/RCTUIManager.h>
+#import <React/RCTLog.h>
+
+RCT_EXPORT_METHOD(callNativeMethod:(nonnull NSNumber*) reactTag) {
+    [self.bridge.uiManager addUIBlock:^(RCTUIManager *uiManager, NSDictionary<NSNumber *,UIView *> *viewRegistry) {
+        NativeView *view = viewRegistry[reactTag];
+        if (!view || ![view isKindOfClass:[NativeView class]]) {
+            RCTLogError(@"Cannot find NativeView with tag #%@", reactTag);
+            return;
+        }
+        [view callNativeMethod];
+    }];
+
+}

Aqui, o callNativeMethod' é definido no arquivo RNCMyNativeViewManager.me contém apenas um parâmetro que é(nonnull NSNumber*) reactTag. Esta função exportada encontrará uma visualização específica usando addUIBlockque contém o parâmetroviewRegistrye retorna o componente baseado emreactTag` permitindo chamar o método no componente correto.

Estilos

Como todas as nossas visualizações de reação nativas são subclasses de UIView, a maioria dos atributos de estilo funcionarão como você esperaria imediatamente. Alguns componentes irão querer um estilo padrão, por exemplo UIDatePicker que é um tamanho fixo. Esse estilo padrão é importante para que o algoritmo de layout funcione conforme o esperado, mas também queremos poder substituir o estilo padrão ao usar o componente. DatePickerIOS faz isso agrupando o componente nativo em uma visualização extra, que possui estilo flexível, e usando um estilo fixo (que é gerado com constantes passadas do nativo) no componente nativo interno:

tsx
// DatePickerIOS.ios.tsx
+
+import {UIManager} from 'react-native';
+const RCTDatePickerIOSConsts = UIManager.RCTDatePicker.Constants;
+...
+  render: function() {
+    return (
+      <View style={this.props.style}>
+        <RCTDatePickerIOS
+          ref={DATEPICKER}
+          style={styles.rkDatePickerIOS}
+          ...
+        />
+      </View>
+    );
+  }
+});
+
+const styles = StyleSheet.create({
+  rkDatePickerIOS: {
+    height: RCTDatePickerIOSConsts.ComponentHeight,
+    width: RCTDatePickerIOSConsts.ComponentWidth,
+  },
+});

As constantes RCTDatePickerIOSConsts são exportadas do nativo capturando o quadro real do componente nativo da seguinte forma:

c
// RCTDatePickerManager.m
+
+- (NSDictionary *)constantsToExport
+{
+  UIDatePicker *dp = [[UIDatePicker alloc] init];
+  [dp layoutIfNeeded];
+
+  return @{
+    @"ComponentHeight": @(CGRectGetHeight(dp.frame)),
+    @"ComponentWidth": @(CGRectGetWidth(dp.frame)),
+    @"DatePickerModes": @{
+      @"time": @(UIDatePickerModeTime),
+      @"date": @(UIDatePickerModeDate),
+      @"datetime": @(UIDatePickerModeDateAndTime),
+    }
+  };
+}

Este guia abordou muitos dos aspectos da ponte sobre componentes nativos personalizados, mas há ainda mais que você pode precisar considerar, como ganchos personalizados para inserir e organizar subvisualizações. Se quiser se aprofundar ainda mais, confira o código-fonte de alguns dos componentes implementados.

+ + + + \ No newline at end of file diff --git a/vitepress/docs/.vitepress/dist/docs/native-debugging.html b/vitepress/docs/.vitepress/dist/docs/native-debugging.html new file mode 100644 index 0000000..3bb725c --- /dev/null +++ b/vitepress/docs/.vitepress/dist/docs/native-debugging.html @@ -0,0 +1,27 @@ + + + + + + Debug Nativo | React Native 0.72 + + + + + + + + + + + + + + + + +
Skip to content

Debug Nativo

Projetos com somente código nativo

A seção a seguir se aplica apenas a projetos com código nativo exposto. Se você estiver usando o fluxo de trabalho gerenciado da Expo, consulte o guia sobre pré-construção para usar esta API.

Acessando logs nativos

Você pode exibir os logs do console de um aplicativo iOS ou Android usando os seguintes comandos em um terminal enquanto o aplicativo está em execução:

bash
npx react-native log-android
bash
npx react-native log-ios

Você também pode acessá-los por meio de Debug > Open System Log… no iOS Simulator ou executando adb logcat "*:S" ReactNative:V ReactNativeJS:V em um terminal enquanto um aplicativo Android está sendo executado em um dispositivo ou emulador.

INFORMAÇÕES

Se você estiver usando o Expo CLI, os logs do console já aparecerão na mesma saída do terminal que o empacotador.

Depurando código nativo

Ao trabalhar com código nativo, como ao escrever módulos nativos, você pode iniciar o aplicativo no Android Studio ou Xcode e aproveitar as vantagens dos recursos de depuração nativos (configuração de pontos de interrupção etc.), como faria no caso de criar um aplicativo nativo padrão. .

Outra opção é executar seu aplicativo usando a CLI React Native e anexar o depurador nativo do IDE nativo (Android Studio ou Xcode) ao processo.

Android Studio

No Android Studio você pode fazer isso acessando a opção "Run" na barra de menu, clicando em "Attach to Process..." e selecionando o aplicativo React Native em execução.

Xcode

No Xcode clique em "Debug" na barra de menu superior, selecione a opção "Attach to process" e selecione o aplicativo na lista de "Likely Targets".

+ + + + \ No newline at end of file diff --git a/vitepress/docs/.vitepress/dist/docs/native-modules-android.html b/vitepress/docs/.vitepress/dist/docs/native-modules-android.html new file mode 100644 index 0000000..35db22f --- /dev/null +++ b/vitepress/docs/.vitepress/dist/docs/native-modules-android.html @@ -0,0 +1,532 @@ + + + + + + Módulos nativos do Android | React Native 0.72 + + + + + + + + + + + + + + + + +
Skip to content

Módulos nativos do Android

INFORMAÇÕES

Módulo Nativo e Componentes Nativos são nossas tecnologias estáveis usadas pela arquitetura legada. Eles serão descontinuados no futuro, quando a Nova Arquitetura estiver estável. A nova arquitetura usa Turbo Native Module e Fabric Native Components para obter resultados semelhantes.

Bem-vindo aos Módulos Nativos para Android. Comece lendo a introdução aos módulos nativos para obter uma introdução ao que são os módulos nativos.

Crie um módulo nativo de calendário

No guia a seguir você criará um módulo nativo, CalendarModule, que permitirá acessar APIs de calendário do Android a partir de JavaScript. Ao final, você poderá chamar CalendarModule.createCalendarEvent('Dinner Party', 'My House'); do JavaScript, invocando um método Java/Kotlin que cria um evento de calendário.

Configurar

Para começar, abra o projeto Android em seu aplicativo React Native no Android Studio. Você pode encontrar seu projeto Android aqui em um aplicativo React Native:

Imagem de onde você pode encontrar seu projeto Android

Recomendamos usar o Android Studio para escrever seu código nativo. Android Studio é um IDE desenvolvido para desenvolvimento Android e usá-lo ajudará você a resolver pequenos problemas, como erros de sintaxe de código, rapidamente.

Também recomendamos ativar o Gradle Daemon para acelerar as compilações conforme você itera no código Java/Kotlin.

Crie um arquivo de módulo nativo personalizado

A primeira etapa é criar o arquivo Java/Kotlin (CalendarModule.java ou CalendarModule.kt) dentro da pasta android/app/src/main/java/com/your-app-name/ (a pasta é a mesma para Kotlin e Java). Este arquivo Java/Kotlin conterá sua classe Java/Kotlin do módulo nativo.

Imagem de como adicionar o CalendarModuleClass

Em seguida, adicione o seguinte conteúdo:

java
package com.your-apps-package-name; // substitua o com.your-apps-package-name pelo nome do pacote do seu aplicativo
+import com.facebook.react.bridge.NativeModule;
+import com.facebook.react.bridge.ReactApplicationContext;
+import com.facebook.react.bridge.ReactContext;
+import com.facebook.react.bridge.ReactContextBaseJavaModule;
+import com.facebook.react.bridge.ReactMethod;
+import java.util.Map;
+import java.util.HashMap;
+
+public class CalendarModule extends ReactContextBaseJavaModule {
+   CalendarModule(ReactApplicationContext context) {
+       super(context);
+   }
+}
kotlin
package com.your-apps-package-name; // substitua o com.your-apps-package-name pelo nome do pacote do seu aplicativo
+import com.facebook.react.bridge.NativeModule
+import com.facebook.react.bridge.ReactApplicationContext
+import com.facebook.react.bridge.ReactContext
+import com.facebook.react.bridge.ReactContextBaseJavaModule
+import com.facebook.react.bridge.ReactMethod
+
+class CalendarModule(reactContext: ReactApplicationContext) : ReactContextBaseJavaModule(reactContext) {...}

Como você pode ver, sua classe CalendarModule estende a classe ReactContextBaseJavaModule. Para Android, os módulos nativos Java/Kotlin são escritos como classes que estendem ReactContextBaseJavaModule e implementam a funcionalidade exigida pelo JavaScript.

INFORMAÇÕES

É importante notar que tecnicamente as classes Java/Kotlin só precisam estender a classe BaseJavaModule ou implementar a interface NativeModule para serem consideradas um Módulo Nativo pelo React Native.

No entanto, recomendamos que você use ReactContextBaseJavaModule, conforme mostrado acima. ReactContextBaseJavaModule dá acesso ao ReactApplicationContext (RAC), que é útil para módulos nativos que precisam se conectar a métodos de ciclo de vida de atividade. Usar ReactContextBaseJavaModule também tornará mais fácil tornar seu módulo nativo seguro para tipos no futuro. Para segurança de tipo de módulo nativo, que será lançada em versões futuras, o React Native analisa as especificações JavaScript de cada módulo nativo e gera uma classe base abstrata que estende ReactContextBaseJavaModule.

Nome do módulo

Todos os módulos nativos Java/Kotlin no Android precisam implementar o método getName(). Este método retorna uma string, que representa o nome do módulo nativo. O módulo nativo pode então ser acessado em JavaScript usando seu nome. Por exemplo, no trecho de código abaixo, getName() retorna "CalendarModule".

java
// adicionar ao CalendarModule.java
+@Override
+public String getName() {
+   return "CalendarModule";
+}
kotlin
// adicionar ao CalendarModule.kt
+override fun getName() = "CalendarModule"

O módulo nativo pode então ser acessado em JS assim:

js
const {CalendarModule} = ReactNative.NativeModules;

Exportar um método nativo para JavaScript

Em seguida, você precisará adicionar um método ao seu módulo nativo que criará eventos de calendário e poderá ser invocado em JavaScript. Todos os métodos de módulo nativos destinados a serem invocados a partir de JavaScript devem ser anotados com @ReactMethod.

Configure um método createCalendarEvent() para CalendarModule que pode ser invocado em JS por meio de CalendarModule.createCalendarEvent(). Por enquanto, o método receberá um nome e um local como strings. As opções de tipo de argumento serão abordadas em breve.

java
@ReactMethod
+public void createCalendarEvent(String name, String location) {
+}
kotlin
@ReactMethod fun createCalendarEvent(name: String, location: String) {}

Adicione um log de depuração ao método para confirmar que ele foi invocado quando você o chama do seu aplicativo. Abaixo está um exemplo de como você pode importar e usar a classe Log do pacote de utilitários do Android:

java
import android.util.Log;
+
+@ReactMethod
+public void createCalendarEvent(String name, String location) {
+   Log.d("CalendarModule", "Create event called with name: " + name
+   + " and location: " + location);
+}
kotlin
import android.util.Log
+
+@ReactMethod
+fun createCalendarEvent(name: String, location: String) {
+    Log.d("CalendarModule", "Create event called with name: $name and location: $location")
+}

Depois de concluir a implementação do módulo nativo e conectá-lo em JavaScript, você pode seguir estas etapas para visualizar os logs do seu aplicativo.

Métodos Síncronos

Você pode passar isBlockingSynchronousMethod = true para um método nativo para marcá-lo como um método síncrono.

java
@ReactMethod(isBlockingSynchronousMethod = true)
kotlin
@ReactMethod(isBlockingSynchronousMethod = true)

No momento, não recomendamos isso, pois chamar métodos de forma síncrona pode ter fortes penalidades de desempenho e introduzir bugs relacionados a threading em seus módulos nativos. Além disso, observe que se você optar por ativar isBlockingSynchronousMethod, seu aplicativo não poderá mais usar o depurador do Google Chrome. Isso ocorre porque os métodos síncronos exigem que a VM JS compartilhe memória com o aplicativo. Para o depurador do Google Chrome, o React Native é executado dentro da VM JS no Google Chrome e se comunica de forma assíncrona com os dispositivos móveis por meio de WebSockets.

Registre o módulo (específico para Android)

Depois que um módulo nativo é escrito, ele precisa ser registrado no React Native. Para fazer isso, você precisa adicionar seu módulo nativo a um ReactPackage e registrar o ReactPackage com React Native. Durante a inicialização, o React Native fará um loop em todos os pacotes e, para cada ReactPackage, registrará cada módulo nativo dentro dele.

React Native invoca o método createNativeModules() em um ReactPackage para obter a lista de módulos nativos para registrar. Para Android, se um módulo não for instanciado e retornado em createNativeModules, ele não estará disponível em JavaScript.

Para adicionar seu módulo nativo ao ReactPackage, primeiro crie uma nova classe Java/Kotlin chamada (MyAppPackage.java ou MyAppPackage.kt) que implementa ReactPackage dentro da pasta android/app/src/main/java/com/your-app-name/:

Em seguida, adicione o seguinte conteúdo:

java
package com.your-app-name; // substitua o com.your-app-name pelo nome do seu aplicativo
+
+import com.facebook.react.ReactPackage;
+import com.facebook.react.bridge.NativeModule;
+import com.facebook.react.bridge.ReactApplicationContext;
+import com.facebook.react.uimanager.ViewManager;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+
+public class MyAppPackage implements ReactPackage {
+
+   @Override
+   public List<ViewManager> createViewManagers(ReactApplicationContext reactContext) {
+       return Collections.emptyList();
+   }
+
+   @Override
+   public List<NativeModule> createNativeModules(
+           ReactApplicationContext reactContext) {
+       List<NativeModule> modules = new ArrayList<>();
+
+       modules.add(new CalendarModule(reactContext));
+
+       return modules;
+   }
+
+}
kotlin
package com.your-app-name // substitua o com.your-app-name pelo nome do seu aplicativo
+
+import android.view.View
+import com.facebook.react.ReactPackage
+import com.facebook.react.bridge.NativeModule
+import com.facebook.react.bridge.ReactApplicationContext
+import com.facebook.react.uimanager.ReactShadowNode
+import com.facebook.react.uimanager.ViewManager
+
+class MyAppPackage : ReactPackage {
+
+    override fun createViewManagers(
+        reactContext: ReactApplicationContext
+    ): MutableList<ViewManager<View, ReactShadowNode<*>>> = mutableListOf()
+
+    override fun createNativeModules(
+        reactContext: ReactApplicationContext
+    ): MutableList<NativeModule> = listOf(CalendarModule(reactContext)).toMutableList()
+}

Este arquivo importa o módulo nativo que você criou, CalendarModule. Em seguida, ele instancia CalendarModule dentro da função createNativeModules() e o retorna como uma lista de NativeModules para registrar. Se você adicionar mais módulos nativos posteriormente, também poderá instanciá-los e adicioná-los à lista retornada aqui.

INFORMAÇÕES

É importante notar que esta forma de registrar módulos nativos inicializa avidamente todos os módulos nativos quando o aplicativo é iniciado, o que aumenta o tempo de inicialização de um aplicativo. Você pode usar o TurboReactPackage como alternativa. Em vez de createNativeModules, que retorna uma lista de objetos de módulo nativos instanciados, TurboReactPackage implementa um método getModule(String name, ReactApplicationContext rac) que cria o objeto de módulo nativo, quando necessário. TurboReactPackage é um pouco mais complicado de implementar no momento. Além de implementar um método getModule(), você deve implementar um método getReactModuleInfoProvider(), que retorna uma lista de todos os módulos nativos que o pacote pode instanciar junto com uma função que os instancia, exemplo aqui. Novamente, usar o TurboReactPackage permitirá que seu aplicativo tenha um tempo de inicialização mais rápido, mas atualmente é um pouco complicado de escrever. Portanto, proceda com cuidado se você optar por usar TurboReactPackages.

Para registrar o pacote CalendarModule, você deve adicionar MyAppPackage à lista de pacotes retornados no método getPackages() do ReactNativeHost. Abra seu arquivo MainApplication.java ou MainApplication.kt, que pode ser encontrado no seguinte caminho: android/app/src/main/java/com/your-app-name/.

Localize o método getPackages() do ReactNativeHost e adicione seu pacote à lista de pacotes que getPackages() retorna:

java
@Override
+  protected List<ReactPackage> getPackages() {
+    @SuppressWarnings("UnnecessaryLocalVariable")
+    List<ReactPackage> packages = new PackageList(this).getPackages();
+    // abaixo MyAppPackage é adicionado à lista de pacotes retornados
+    packages.add(new MyAppPackage());
+    return packages;
+  }
kotlin
override fun getPackages(): List<ReactPackage> =
+    PackageList(this).packages.apply {
+        // Pacotes que ainda não podem ser vinculados automaticamente podem ser adicionados manualmente aqui, por exemplo:
+        // packages.add(new MyReactNativePackage());
+        add(MyAppPackage())
+    }

Agora você registrou com sucesso seu módulo nativo para Android!

Teste o que você construiu

Neste ponto, você configurou a estrutura básica para seu módulo nativo no Android. Teste isso acessando o módulo nativo e invocando seu método exportado em JavaScript.

Encontre um local em seu aplicativo onde você gostaria de adicionar uma chamada ao método createCalendarEvent() do módulo nativo. Abaixo está um exemplo de componente, NewModuleButton, que você pode adicionar ao seu aplicativo. Você pode invocar o módulo nativo dentro da função onPress() do NewModuleButton.

jsx
import React from 'react';
+import {NativeModules, Button} from 'react-native';
+
+const NewModuleButton = () => {
+  const onPress = () => {
+    console.log('We will invoke the native module here!');
+  };
+
+  return (
+    <Button
+      title="Click to invoke your native module!"
+      color="#841584"
+      onPress={onPress}
+    />
+  );
+};
+
+export default NewModuleButton;

Para acessar seu módulo nativo a partir de JavaScript, você precisa primeiro importar NativeModules do React Native:

jsx
import {NativeModules} from 'react-native';

Você pode então acessar o módulo nativo CalendarModule fora de NativeModules.

jsx
const {CalendarModule} = NativeModules;

Agora que você tem o módulo nativo CalendarModule disponível, você pode invocar seu método nativo createCalendarEvent(). Abaixo é adicionado ao método onPress() em NewModuleButton:

jsx
const onPress = () => {
+  CalendarModule.createCalendarEvent('testName', 'testLocation');
+};

A etapa final é reconstruir o aplicativo React Native para que você possa ter o código nativo mais recente (com seu novo módulo nativo!) Disponível. Na linha de comando, onde o aplicativo react nativo está localizado, execute o seguinte:

bash
npm run android
bash
yarn android

Construindo enquanto você itera

À medida que você trabalha nesses guias e itera em seu módulo nativo, você precisará fazer uma reconstrução nativa de seu aplicativo para acessar as alterações mais recentes do JavaScript. Isso ocorre porque o código que você está escrevendo fica na parte nativa do seu aplicativo. Embora o empacotador metro do React Native possa observar mudanças no JavaScript e reconstruir instantaneamente para você, ele não fará isso para o código nativo. Portanto, se você quiser testar suas alterações nativas mais recentes, precisará reconstruí-las usando o comando acima.

Recapitulação✨

Agora você deve ser capaz de invocar seu método createCalendarEvent() em seu módulo nativo no aplicativo. No nosso exemplo isso ocorre pressionando o NewModuleButton. Você pode confirmar isso visualizando o log configurado no método createCalendarEvent(). Você pode seguir estas etapas para visualizar os logs do ADB em seu aplicativo. Você deverá então ser capaz de pesquisar sua mensagem Log.d (em nosso exemplo “Criar evento chamado com nome: testName e local: testLocation”) e ver sua mensagem registrada sempre que invocar seu método de módulo nativo.

Imagem dos logs do ADB no Android Studio

Neste ponto, você criou um módulo nativo Android e invocou seu método nativo a partir de JavaScript em seu aplicativo React Native. Você pode continuar lendo para aprender mais sobre coisas como tipos de argumentos disponíveis para um método de módulo nativo e como configurar retornos de chamada e promessas.

Além de um módulo nativo de calendário

Melhor exportação de módulo nativo

Importar seu módulo nativo retirando-o de NativeModules como acima é um pouco complicado.

Para evitar que os consumidores do seu módulo nativo precisem fazer isso sempre que quiserem acessar seu módulo nativo, você pode criar um wrapper JavaScript para o módulo. Crie um novo arquivo JavaScript chamado CalendarModule.js com o seguinte conteúdo:

js
/**
+* Isso expõe o módulo nativo CalendarModule como um módulo JS. Isto tem um
+* função 'createCalendarEvent' que leva os seguintes parâmetros:
+
+* 1. String name: Uma string que representa o nome do evento
+* 2. String location: Uma string que representa a localização do evento
+*/
+import {NativeModules} from 'react-native';
+const {CalendarModule} = NativeModules;
+export default CalendarModule;

Este arquivo JavaScript também se torna um bom local para você adicionar qualquer funcionalidade secundária do JavaScript. Por exemplo, se você usar um sistema de tipos como TypeScript, poderá adicionar anotações de tipo para seu módulo nativo aqui. Embora o React Native ainda não ofereça suporte à segurança de tipo, todo o seu código JS será de tipo seguro. Isso também tornará mais fácil mudar para módulos nativos com segurança de tipo no futuro. Abaixo está um exemplo de adição de segurança de tipo ao CalendarModule:

tsx
/**
+ * Isso expõe o módulo nativo CalendarModule como um módulo JS. Isto tem um
+ * função 'createCalendarEvent' que leva os seguintes parâmetros:
+ *
+ * 1. String name: Uma string que representa o nome do evento
+ * 2. String location: Uma string que representa a localização do evento
+ */
+import {NativeModules} from 'react-native';
+const {CalendarModule} = NativeModules;
+
+interface CalendarInterface {
+  createCalendarEvent(name: string, location: string): void;
+}
+
+export default CalendarModule as CalendarInterface;

Nos seus outros arquivos JavaScript você pode acessar o módulo nativo e invocar seu método assim:

tsx
import CalendarModule from './CalendarModule';
+CalendarModule.createCalendarEvent('foo', 'bar');

INFORMAÇÕES

Isso pressupõe que o local que você está importando CalendarModule esteja na mesma hierarquia que CalendarModule.js. Atualize a importação relativa conforme necessário.

Tipos de argumento

Quando um método de módulo nativo é invocado em JavaScript, o React Native converte os argumentos dos objetos JS em seus objetos análogos Java/Kotlin. Então, por exemplo, se o seu método Java Native Module aceita um double, em JS você precisa chamar o método com um número. React Native cuidará da conversão para você. Abaixo está uma lista dos tipos de argumentos suportados pelos métodos de módulo nativos e os equivalentes JavaScript para os quais eles mapeiam.

JAVAKOTLINJAVASCRIPT
BooleanBoolean?boolean
booleanboolean
DoubleDouble?number
doublenumber
StringStringstring
CallbackCallbackFunction
PromisePromisePromise
ReadableMapReadableMapObject
ReadableArrayReadableArrayArray

INFORMAÇÕES

Os seguintes tipos são atualmente suportados, mas não serão suportados em TurboModules. Evite usá-los:

  • Integer Java/Kotlin -> ?number
  • Float Java/Kotlin -> ?number
  • int Java -> number
  • float Java -> number

Para tipos de argumentos não listados acima, você mesmo precisará lidar com a conversão. Por exemplo, no Android, a conversão de data não é compatível imediatamente. Você mesmo pode lidar com a conversão para o tipo Date dentro do método nativo da seguinte forma:

java
String dateFormat = "yyyy-MM-dd";
+SimpleDateFormat sdf = new SimpleDateFormat(dateFormat);
+Calendar eStartDate = Calendar.getInstance();
+try {
+    eStartDate.setTime(sdf.parse(startDate));
+}
kotlin
val dateFormat = "yyyy-MM-dd"
+val sdf = SimpleDateFormat(dateFormat, Locale.US)
+val eStartDate = Calendar.getInstance()
+try {
+    sdf.parse(startDate)?.let {
+        eStartDate.time = it
+    }
+}

Exportando Constantes

Um módulo nativo pode exportar constantes implementando o método nativo getConstants(), que está disponível em JS. Abaixo você implementará getConstants() e retornará um Map que contém uma constante DEFAULT_EVENT_NAME que você pode acessar em JavaScript:

java
@Override
+public Map<String, Object> getConstants() {
+   final Map<String, Object> constants = new HashMap<>();
+   constants.put("DEFAULT_EVENT_NAME", "New Event");
+   return constants;
+}
kotlin
override fun getConstants(): MutableMap<String, Any> =
+    hashMapOf("DEFAULT_EVENT_NAME" to "New Event")

A constante pode então ser acessada invocando getConstants no módulo nativo em JS:

java
const {DEFAULT_EVENT_NAME} = CalendarModule.getConstants();
+console.log(DEFAULT_EVENT_NAME);
kotlin
const {DEFAULT_EVENT_NAME} = CalendarModule.getConstants();
+console.log(DEFAULT_EVENT_NAME);

Tecnicamente, é possível acessar constantes exportadas em getConstants() diretamente do objeto do módulo nativo. Isso não será mais compatível com TurboModules, por isso encorajamos a comunidade a mudar para a abordagem acima para evitar a migração necessária no futuro.

INFORMAÇÕES

Atualmente, as constantes são exportadas apenas no momento da inicialização, portanto, se você alterar os valores getConstants em tempo de execução, isso não afetará o ambiente JavaScript. Isso mudará com Turbomodules. Com Turbomodules, getConstants() se tornará um método de módulo nativo regular e cada invocação atingirá o lado nativo.

Callbacks

Os módulos nativos também suportam um tipo único de argumento: um retorno de chamada. Retornos de chamada são usados para passar dados de Java/Kotlin para JavaScript para métodos assíncronos. Eles também podem ser usados para executar JavaScript de forma assíncrona do lado nativo.

Para criar um método de módulo nativo com retorno de chamada, primeiro importe a interface Callback e, em seguida, adicione um novo parâmetro ao método de módulo nativo do tipo Callback. Existem algumas nuances nos argumentos de retorno de chamada que em breve serão eliminadas com TurboModules. Primeiro, você só pode ter dois retornos de chamada nos argumentos de sua função – um successCallback e um failedCallback. Além disso, o último argumento para uma chamada de método de módulo nativo, se for uma função, é tratado como sucessCallback, e o penúltimo argumento para uma chamada de método de módulo nativo, se for uma função, é tratado como retorno de chamada de falha.

java
import com.facebook.react.bridge.Callback;
+
+@ReactMethod
+public void createCalendarEvent(String name, String location, Callback callBack) {
+}
kotlin
import com.facebook.react.bridge.Callback
+
+@ReactMethod fun createCalendarEvent(name: String, location: String, callback: Callback) {}

Você pode invocar o retorno de chamada em seu método Java/Kotlin, fornecendo quaisquer dados que deseja passar para JavaScript. Observe que você só pode passar dados serializáveis de código nativo para JavaScript. Se você precisar retornar um objeto nativo, você pode usar WriteableMaps, se precisar usar uma coleção, use WritableArrays. Também é importante destacar que o retorno de chamada não é invocado imediatamente após a conclusão da função nativa. Abaixo do ID de um evento criado em uma chamada anterior é passado para o retorno de chamada.

java
@ReactMethod
+public void createCalendarEvent(String name, String location, Callback callBack) {
+     Integer eventId = ...
+     callBack.invoke(eventId);
+}
kotlin
@ReactMethod
+fun createCalendarEvent(name: String, location: String, callback: Callback) {
+    val eventId = ...
+    callback.invoke(eventId)
+}

Este método pode então ser acessado em JavaScript usando:

tsx
const onPress = () => {
+  CalendarModule.createCalendarEvent(
+    'Party',
+    'My House',
+    eventId => {
+      console.log(`Created a new event with id ${eventId}`);
+    },
+  );
+};

Outro detalhe importante a ser observado é que um método de módulo nativo só pode invocar um retorno de chamada uma vez. Isso significa que você pode chamar um retorno de chamada com sucesso ou um retorno de chamada com falha, mas não ambos, e cada retorno de chamada só pode ser invocado no máximo uma vez. Um módulo nativo pode, entretanto, armazenar o retorno de chamada e invocá-lo posteriormente.

Existem duas abordagens para tratamento de erros com retornos de chamada. A primeira é seguir a convenção do Node e tratar o primeiro argumento passado para o retorno de chamada como um objeto de erro.

java
@ReactMethod
+ public void createCalendarEvent(String name, String location, Callback callBack) {
+     Integer eventId = ...
+     callBack.invoke(null, eventId);
+ }
kotlin
@ReactMethod
+fun createCalendarEvent(name: String, location: String, callback: Callback) {
+    val eventId = ...
+    callback.invoke(null, eventId)
+}

Em JavaScript, você pode verificar o primeiro argumento para ver se um erro foi transmitido:

tsx
const onPress = () => {
+  CalendarModule.createCalendarEvent(
+    'testName',
+    'testLocation',
+    (error, eventId) => {
+      if (error) {
+        console.error(`Error found! ${error}`);
+      }
+      console.log(`event id ${eventId} returned`);
+    },
+  );
+};

Outra opção é usar um retorno de chamada onSuccess e onFailure:

java
@ReactMethod
+public void createCalendarEvent(String name, String location, Callback myFailureCallback, Callback mySuccessCallback) {
+}
kotlin
@ReactMethod
+  fun createCalendarEvent(
+      name: String,
+      location: String,
+      myFailureCallback: Callback,
+      mySuccessCallback: Callback
+  ) {}

Então, em JavaScript, você pode adicionar um retorno de chamada separado para respostas de erro e sucesso:

tsx
const onPress = () => {
+  CalendarModule.createCalendarEvent(
+    'testName',
+    'testLocation',
+    error => {
+      console.error(`Error found! ${error}`);
+    },
+    eventId => {
+      console.log(`event id ${eventId} returned`);
+    },
+  );
+};

Promises

Módulos nativos também podem cumprir uma promessa, o que pode simplificar seu JavaScript, especialmente ao usar a sintaxe async/await do ES2016. Quando o último parâmetro de um método Java/Kotlin de módulo nativo é uma Promise, seu método JS correspondente retornará um objeto JS Promise.

Refatorar o código acima para usar uma promessa em vez de retornos de chamada é assim:

java
import com.facebook.react.bridge.Promise;
+
+@ReactMethod
+public void createCalendarEvent(String name, String location, Promise promise) {
+    try {
+        Integer eventId = ...
+        promise.resolve(eventId);
+    } catch(Exception e) {
+        promise.reject("Create Event Error", e);
+    }
+}
kotlin
import com.facebook.react.bridge.Promise
+
+@ReactMethod
+fun createCalendarEvent(name: String, location: String, promise: Promise) {
+    try {
+        val eventId = ...
+        promise.resolve(eventId)
+    } catch (e: Throwable) {
+        promise.reject("Create Event Error", e)
+    }
+}

INFORMAÇÕES

Semelhante aos retornos de chamada, um método de módulo nativo pode rejeitar ou resolver uma promessa (mas não ambos) e pode fazer isso no máximo uma vez. Isso significa que você pode chamar um retorno de chamada com sucesso ou um retorno de chamada com falha, mas não ambos, e cada retorno de chamada só pode ser invocado no máximo uma vez. Um módulo nativo pode, entretanto, armazenar o retorno de chamada e invocá-lo posteriormente.

A contraparte JavaScript deste método retorna uma promessa. Isso significa que você pode usar a palavra-chave await dentro de uma função assíncrona para chamá-la e aguardar seu resultado:

tsx
const onSubmit = async () => {
+  try {
+    const eventId = await CalendarModule.createCalendarEvent(
+      'Party',
+      'My House',
+    );
+    console.log(`Created a new event with id ${eventId}`);
+  } catch (e) {
+    console.error(e);
+  }
+};

O método rejeitar utiliza diferentes combinações dos seguintes argumentos:

java
String code, String message, WritableMap userInfo, Throwable throwable
kotlin
code: String, message: String, userInfo: WritableMap, throwable: Throwable

Para mais detalhes, você pode encontrar a interface Promise.java aqui. Se userInfo não for fornecido, ReactNative irá defini-lo como nulo. Para o restante dos parâmetros, o React Native usará um valor padrão. O argumento message fornece a mensagem de erro mostrada no topo de uma pilha de chamadas de erro. Abaixo está um exemplo da mensagem de erro mostrada em JavaScript da seguinte chamada rejeitada em Java/Kotlin.

Chamada rejeitada de Java/Kotlin:

java
promise.reject("Create Event error", "Error parsing date", e);
kotlin
promise.reject("Create Event error", "Error parsing date", e)

Mensagem de erro no aplicativo React Native quando a promessa é rejeitada:

Imagem da mensagem de erro

Enviando eventos para JavaScript

Módulos nativos podem sinalizar eventos para JavaScript sem serem invocados diretamente. Por exemplo, você pode sinalizar para o JavaScript um lembrete de que um evento de calendário do aplicativo de calendário nativo do Android ocorrerá em breve. A maneira mais fácil de fazer isso é usar o RCTDeviceEventEmitter que pode ser obtido no ReactContext como no trecho de código abaixo.

java
...
+import com.facebook.react.modules.core.DeviceEventManagerModule;
+import com.facebook.react.bridge.WritableMap;
+import com.facebook.react.bridge.Arguments;
+...
+private void sendEvent(ReactContext reactContext,
+                      String eventName,
+                      @Nullable WritableMap params) {
+ reactContext
+     .getJSModule(DeviceEventManagerModule.RCTDeviceEventEmitter.class)
+     .emit(eventName, params);
+}
+
+private int listenerCount = 0;
+
+@ReactMethod
+public void addListener(String eventName) {
+  if (listenerCount == 0) {
+    // Configure quaisquer ouvintes upstream ou tarefas em segundo plano conforme necessário
+  }
+
+  listenerCount += 1;
+}
+
+@ReactMethod
+public void removeListeners(Integer count) {
+  listenerCount -= count;
+  if (listenerCount == 0) {
+    // Remova ouvintes upstream, interrompa tarefas desnecessárias em segundo plano
+  }
+}
+...
+WritableMap params = Arguments.createMap();
+params.putString("eventProperty", "someValue");
+...
+sendEvent(reactContext, "EventReminder", params);
kotlin
...
+import com.facebook.react.bridge.WritableMap
+import com.facebook.react.bridge.Arguments
+import com.facebook.react.modules.core.DeviceEventManagerModule
+...
+
+private fun sendEvent(reactContext: ReactContext, eventName: String, params: WritableMap?) {
+    reactContext
+      .getJSModule(DeviceEventManagerModule.RCTDeviceEventEmitter::class.java)
+      .emit(eventName, params)
+}
+
+private var listenerCount = 0
+
+@ReactMethod
+fun addListener(eventName: String) {
+  if (listenerCount == 0) {
+    // Configure quaisquer ouvintes upstream ou tarefas em segundo plano conforme necessário
+  }
+
+  listenerCount += 1
+}
+
+@ReactMethod
+fun removeListeners(count: Int) {
+  listenerCount -= count
+  if (listenerCount == 0) {
+    // Remova ouvintes upstream, interrompa tarefas desnecessárias em segundo plano
+  }
+}
+...
+val params = Arguments.createMap().apply {
+    putString("eventProperty", "someValue")
+}
+...
+sendEvent(reactContext, "EventReminder", params)

Os módulos JavaScript podem então se registrar para receber eventos por addListener na classe NativeEventEmitter.

tsx
import {NativeEventEmitter, NativeModules} from 'react-native';
+...
+useEffect(() => {
+    const eventEmitter = new NativeEventEmitter(NativeModules.ToastExample);
+    let eventListener = eventEmitter.addListener('EventReminder', event => {
+      console.log(event.eventProperty) // "algumValor"
+    });
+
+    // Remove o ouvinte depois de desmontado
+    return () => {
+      eventListener.remove();
+    };
+  }, []);

Obtendo o resultado da atividade de startActivityForResult

Você precisará ouvir onActivityResult se quiser obter resultados de uma atividade iniciada com startActivityForResult. Para fazer isso, você deve estender BaseActivityEventListener ou implementar ActivityEventListener. O primeiro é preferido porque é mais resiliente às alterações da API. Então, você precisa registrar o ouvinte no construtor do módulo assim:

java
reactContext.addActivityEventListener(mActivityResultListener);

Agora você pode ouvir onActivityResult implementando o seguinte método:

java
@Override
+public void onActivityResult(
+ final Activity activity,
+ final int requestCode,
+ final int resultCode,
+ final Intent intent) {
+ // Sua lógica aqui
+}
kotlin
override fun onActivityResult(
+    activity: Activity?,
+    requestCode: Int,
+    resultCode: Int,
+    intent: Intent?
+) {
+    // Sua lógica aqui
+}

Vamos implementar um seletor de imagens básico para demonstrar isso. O seletor de imagens irá expor o método pickImage no JavaScript, que retornará o caminho da imagem quando chamado.

java
public class ImagePickerModule extends ReactContextBaseJavaModule {
+
+  private static final int IMAGE_PICKER_REQUEST = 1;
+  private static final String E_ACTIVITY_DOES_NOT_EXIST = "E_ACTIVITY_DOES_NOT_EXIST";
+  private static final String E_PICKER_CANCELLED = "E_PICKER_CANCELLED";
+  private static final String E_FAILED_TO_SHOW_PICKER = "E_FAILED_TO_SHOW_PICKER";
+  private static final String E_NO_IMAGE_DATA_FOUND = "E_NO_IMAGE_DATA_FOUND";
+
+  private Promise mPickerPromise;
+
+  private final ActivityEventListener mActivityEventListener = new BaseActivityEventListener() {
+
+    @Override
+    public void onActivityResult(Activity activity, int requestCode, int resultCode, Intent intent) {
+      if (requestCode == IMAGE_PICKER_REQUEST) {
+        if (mPickerPromise != null) {
+          if (resultCode == Activity.RESULT_CANCELED) {
+            mPickerPromise.reject(E_PICKER_CANCELLED, "Image picker was cancelled");
+          } else if (resultCode == Activity.RESULT_OK) {
+            Uri uri = intent.getData();
+
+            if (uri == null) {
+              mPickerPromise.reject(E_NO_IMAGE_DATA_FOUND, "No image data found");
+            } else {
+              mPickerPromise.resolve(uri.toString());
+            }
+          }
+
+          mPickerPromise = null;
+        }
+      }
+    }
+  };
+
+  ImagePickerModule(ReactApplicationContext reactContext) {
+    super(reactContext);
+
+    // Adicione o ouvinte para `onActivityResult`
+    reactContext.addActivityEventListener(mActivityEventListener);
+  }
+
+  @Override
+  public String getName() {
+    return "ImagePickerModule";
+  }
+
+  @ReactMethod
+  public void pickImage(final Promise promise) {
+    Activity currentActivity = getCurrentActivity();
+
+    if (currentActivity == null) {
+      promise.reject(E_ACTIVITY_DOES_NOT_EXIST, "Activity doesn't exist");
+      return;
+    }
+
+    // Armazene a promessa de resolver/rejeitar quando o seletor retornar dados
+    mPickerPromise = promise;
+
+    try {
+      final Intent galleryIntent = new Intent(Intent.ACTION_PICK);
+
+      galleryIntent.setType("image/*");
+
+      final Intent chooserIntent = Intent.createChooser(galleryIntent, "Pick an image");
+
+      currentActivity.startActivityForResult(chooserIntent, IMAGE_PICKER_REQUEST);
+    } catch (Exception e) {
+      mPickerPromise.reject(E_FAILED_TO_SHOW_PICKER, e);
+      mPickerPromise = null;
+    }
+  }
+}
kotlin
class ImagePickerModule(reactContext: ReactApplicationContext) :
+    ReactContextBaseJavaModule(reactContext) {
+
+    private var pickerPromise: Promise? = null
+
+    private val activityEventListener =
+        object : BaseActivityEventListener() {
+            override fun onActivityResult(
+                activity: Activity?,
+                requestCode: Int,
+                resultCode: Int,
+                intent: Intent?
+            ) {
+                if (requestCode == IMAGE_PICKER_REQUEST) {
+                    pickerPromise?.let { promise ->
+                        when (resultCode) {
+                            Activity.RESULT_CANCELED ->
+                                promise.reject(E_PICKER_CANCELLED, "Image picker was cancelled")
+                            Activity.RESULT_OK -> {
+                                val uri = intent?.data
+
+                                uri?.let { promise.resolve(uri.toString())}
+                                    ?: promise.reject(E_NO_IMAGE_DATA_FOUND, "No image data found")
+                            }
+                        }
+
+                        pickerPromise = null
+                    }
+                }
+            }
+        }
+
+    init {
+        reactContext.addActivityEventListener(activityEventListener)
+    }
+
+    override fun getName() = "ImagePickerModule"
+
+    @ReactMethod
+    fun pickImage(promise: Promise) {
+        val activity = currentActivity
+
+        if (activity == null) {
+            promise.reject(E_ACTIVITY_DOES_NOT_EXIST, "Activity doesn't exist")
+            return
+        }
+
+        pickerPromise = promise
+
+        try {
+            val galleryIntent = Intent(Intent.ACTION_PICK).apply { type = "image\/*" }
+
+            val chooserIntent = Intent.createChooser(galleryIntent, "Pick an image")
+
+            activity.startActivityForResult(chooserIntent, IMAGE_PICKER_REQUEST)
+        } catch (t: Throwable) {
+            pickerPromise?.reject(E_FAILED_TO_SHOW_PICKER, t)
+            pickerPromise = null
+        }
+    }
+
+    companion object {
+        const val IMAGE_PICKER_REQUEST = 1
+        const val E_ACTIVITY_DOES_NOT_EXIST = "E_ACTIVITY_DOES_NOT_EXIST"
+        const val E_PICKER_CANCELLED = "E_PICKER_CANCELLED"
+        const val E_FAILED_TO_SHOW_PICKER = "E_FAILED_TO_SHOW_PICKER"
+        const val E_NO_IMAGE_DATA_FOUND = "E_NO_IMAGE_DATA_FOUND"
+    }
+}

Ouvindo eventos do ciclo de vida

Ouvir os eventos LifeCycle da atividade, como onResume, onPause etc., é muito semelhante a como ActivityEventListener foi implementado. O módulo deve implementar LifecycleEventListener. Então, você precisa registrar um ouvinte no construtor do módulo como:

java
reactContext.addLifecycleEventListener(this);
kotlin
reactContext.addLifecycleEventListener(this)

Agora você pode ouvir os eventos LifeCycle da atividade implementando os seguintes métodos:

java
@Override
+public void onHostResume() {
+   // Activity `onResume`
+}
+@Override
+public void onHostPause() {
+   // Activity `onPause`
+}
+@Override
+public void onHostDestroy() {
+   // Activity `onDestroy`
+}
kotlin
override fun onHostResume() {
+    // Activity `onResume`
+}
+
+override fun onHostPause() {
+    // Activity `onPause`
+}
+
+override fun onHostDestroy() {
+    // Activity `onDestroy`
+}

Threading

Até o momento, no Android, todos os métodos assíncronos do módulo nativo são executados em um thread. Os módulos nativos não devem ter nenhuma suposição sobre em qual thread estão sendo chamados, pois a atribuição atual está sujeita a alterações no futuro. Se uma chamada de bloqueio for necessária, o trabalho pesado deverá ser despachado para um thread de trabalho gerenciado internamente e quaisquer retornos de chamada distribuídos a partir daí.

+ + + + \ No newline at end of file diff --git a/vitepress/docs/.vitepress/dist/docs/native-modules-intro.html b/vitepress/docs/.vitepress/dist/docs/native-modules-intro.html new file mode 100644 index 0000000..a069c91 --- /dev/null +++ b/vitepress/docs/.vitepress/dist/docs/native-modules-intro.html @@ -0,0 +1,27 @@ + + + + + + Introdução aos módulos nativos | React Native 0.72 + + + + + + + + + + + + + + + + +
Skip to content

Introdução aos módulos nativos

INFORMAÇÕES

Módulo Nativo e Componentes Nativos são nossas tecnologias estáveis usadas pela arquitetura legada. Eles serão descontinuados no futuro, quando a Nova Arquitetura estiver estável. A nova arquitetura usa Turbo Native Module e Fabric Native Components para obter resultados semelhantes.

Às vezes, um aplicativo React Native precisa acessar uma API de plataforma nativa que não está disponível por padrão em JavaScript, por exemplo, as APIs nativas para acessar Apple ou Google Pay. Talvez você queira reutilizar algumas bibliotecas existentes de Objective-C, Swift, Java ou C++ sem ter que reimplementá-las em JavaScript ou escrever algum código multithread de alto desempenho para coisas como processamento de imagens.

O sistema NativeModule expõe instâncias de classes Java/Objective-C/C++ (nativas) para JavaScript (JS) como objetos JS, permitindo assim que você execute código nativo arbitrário de dentro de JS. Embora não esperemos que esse recurso faça parte do processo normal de desenvolvimento, é essencial que ele exista. Se o React Native não exportar uma API nativa que seu aplicativo JS precisa, você mesmo poderá exportá-la!

Configuração do módulo nativo

Existem duas maneiras de escrever um módulo nativo para seu aplicativo React Native:

  1. Diretamente nos projetos iOS/Android do seu aplicativo React Native
  2. Como um pacote NPM que pode ser instalado como uma dependência por seus/outros aplicativos React Native

Este guia primeiro orientará você na implementação de um módulo nativo diretamente em um aplicativo React Native. No entanto, o módulo nativo que você constrói no guia a seguir pode ser distribuído como um pacote NPM. Confira o guia Configurando um Módulo Nativo como um Pacote NPM se você estiver interessado em fazê-lo.

Começando

Nas seções a seguir, orientaremos você em guias sobre como construir um módulo nativo diretamente em um aplicativo React Native. Como pré-requisito, você precisará de um aplicativo React Native para trabalhar. Você pode seguir as etapas aqui para configurar um aplicativo React Native se ainda não tiver um.

Imagine que você deseja acessar as APIs de calendário nativas do iOS/Android a partir do JavaScript em um aplicativo React Native para criar eventos de calendário. React Native não expõe uma API JavaScript para se comunicar com as bibliotecas de calendário nativas. No entanto, por meio de módulos nativos, você pode escrever código nativo que se comunique com APIs de calendário nativas. Então você pode invocar esse código nativo por meio de JavaScript em seu aplicativo React Native.

Nas seções a seguir, você criará um módulo nativo do Calendário para Android e iOS.

+ + + + \ No newline at end of file diff --git a/vitepress/docs/.vitepress/dist/docs/native-modules-ios.html b/vitepress/docs/.vitepress/dist/docs/native-modules-ios.html new file mode 100644 index 0000000..2813cbc --- /dev/null +++ b/vitepress/docs/.vitepress/dist/docs/native-modules-ios.html @@ -0,0 +1,243 @@ + + + + + + Módulos nativos iOS | React Native 0.72 + + + + + + + + + + + + + + + + +
Skip to content

Módulos nativos iOS

INFORMAÇÕES

Módulo Nativo e Componentes Nativos são nossas tecnologias estáveis usadas pela arquitetura legada. Eles serão descontinuados no futuro, quando a Nova Arquitetura estiver estável. A nova arquitetura usa Turbo Native Module e Fabric Native Components para obter resultados semelhantes.

Bem-vindo aos Módulos Nativos para iOS. Comece lendo a introdução aos módulos nativos para obter uma introdução ao que são os módulos nativos.

Crie um módulo nativo de calendário

No guia a seguir você criará um módulo nativo, CalendarModule, que permitirá acessar APIs de calendário da Apple a partir de JavaScript. No final você poderá chamar CalendarModule.createCalendarEvent('Dinner Party', 'My House'); do JavaScript, invocando um método nativo que cria um evento de calendário.

Configurar

Para começar, abra o projeto iOS em seu aplicativo React Native no Xcode. Você pode encontrar seu projeto iOS aqui em um aplicativo React Native:

Imagem de onde você pode encontrar seu projeto iOS

Recomendamos usar o Xcode para escrever seu código nativo. O Xcode foi desenvolvido para desenvolvimento em iOS e usá-lo ajudará você a resolver rapidamente erros menores, como sintaxe de código.

Crie arquivos de módulo nativos personalizados

A primeira etapa é criar nosso principal cabeçalho de módulo nativo personalizado e arquivos de implementação. Crie um novo arquivo chamado RCTCalendarModule.h

Imagem da criação de um arquivo de módulo nativo personalizado na mesma pasta do AppDelegate

e adicione o seguinte a ele:

cpp
//  RCTCalendarModule.h
+#import <React/RCTBridgeModule.h>
+@interface RCTCalendarModule : NSObject <RCTBridgeModule>
+@end

Você pode usar qualquer nome que corresponda ao módulo nativo que você está construindo. Nomeie a classe RCTCalendarModule, pois você está criando um módulo nativo de calendário. Como ObjC não tem suporte em nível de linguagem para namespaces como Java ou C++, a convenção é acrescentar uma substring ao nome da classe. Pode ser uma abreviatura do nome do seu aplicativo ou do seu infranome. RCT, neste exemplo, refere-se ao React.

Como você pode ver abaixo, a classe CalendarModule implementa o protocolo RCTBridgeModule. Um módulo nativo é uma classe Objective-C que implementa o protocolo RCTBridgeModule.

A seguir, vamos começar a implementar o módulo nativo. Crie o arquivo de implementação correspondente, RCTCalendarModule.m, na mesma pasta e inclua o seguinte conteúdo:

cpp
// RCTCalendarModule.m
+#import "RCTCalendarModule.h"
+
+@implementation RCTCalendarModule
+
+// Para exportar um módulo denominado RCTCalendarModule
+RCT_EXPORT_MODULE();
+
+@end

Nome do módulo

Por enquanto, seu módulo nativo RCTCalendarModule.m inclui apenas um macro RCT_EXPORT_MODULE, que exporta e registra a classe do módulo nativo com React Native. O macro RCT_EXPORT_MODULE também usa um argumento opcional que especifica o nome pelo qual o módulo estará acessível em seu código JavaScript.

Este argumento não é uma string literal. No exemplo abaixo RCT_EXPORT_MODULE(CalendarModuleFoo) é passado, não RCT_EXPORT_MODULE("CalendarModuleFoo").

cpp
// Para exportar um módulo chamado CalendarModuleFoo
+RCT_EXPORT_MODULE(CalendarModuleFoo);

O módulo nativo pode então ser acessado em JS assim:

js
const {CalendarModuleFoo} = ReactNative.NativeModules;

Se você não especificar um nome, o nome do módulo JavaScript corresponderá ao nome da classe Objective-C, com quaisquer prefixos "RCT" ou "RK" removidos.

Vamos seguir o exemplo abaixo e chamar RCT_EXPORT_MODULE sem nenhum argumento. Como resultado, o módulo será exposto ao React Native usando o nome CalendarModule, já que esse é o nome da classe Objective-C, com RCT removido.

cpp
// Sem passar um nome, isso exportará o nome do módulo nativo como o nome da classe Objective-C com “RCT” removido
+RCT_EXPORT_MODULE();

O módulo nativo pode então ser acessado em JS assim:

js
const {CalendarModule} = ReactNative.NativeModules;

Exportar um método nativo para JavaScript

O React Native não exporá nenhum método em um módulo nativo ao JavaScript, a menos que seja explicitamente solicitado. Isso pode ser feito usando o macro RCT_EXPORT_METHOD. Os métodos escritos na macro RCT_EXPORT_METHOD são assíncronos e o tipo de retorno é, portanto, sempre nulo. Para passar um resultado de um método RCT_EXPORT_METHOD para JavaScript você pode usar retornos de chamada ou emitir eventos (abordados abaixo). Vamos configurar um método nativo para nosso módulo nativo CalendarModule usando a macro RCT_EXPORT_METHOD. Chame-o de createCalendarEvent() e, por enquanto, aceite argumentos de nome e localização como strings. As opções de tipo de argumento serão abordadas em breve.

cpp
RCT_EXPORT_METHOD(createCalendarEvent:(NSString *)name location:(NSString *)location)
+{
+}

INFORMAÇÕES

Observe que o macro RCT_EXPORT_METHOD não será necessário com TurboModules, a menos que seu método dependa da conversão de argumentos RCT (veja os tipos de argumentos abaixo). Em última análise, o React Native removerá o RCT_EXPORT_MACRO, por isso desencorajamos as pessoas a usar o RCTConvert. Em vez disso, você pode fazer a conversão do argumento dentro do corpo do método.

Antes de desenvolver a funcionalidade do método createCalendarEvent(), adicione um log de console no método para que você possa confirmar se ele foi invocado a partir de JavaScript em seu aplicativo React Native. Use as APIs RCTLog do React. Vamos importar esse cabeçalho no topo do seu arquivo e adicionar a chamada de log.

c
#import <React/RCTLog.h>
+RCT_EXPORT_METHOD(createCalendarEvent:(NSString *)name location:(NSString *)location)
+{
+ RCTLogInfo(@"Pretending to create an event %@ at %@", name, location);
+}

Métodos Síncronos

Você pode usar RCT_EXPORT_BLOCKING_SYNCHRONOUS_METHOD para criar um método nativo síncrono.

c
RCT_EXPORT_BLOCKING_SYNCHRONOUS_METHOD(getName)
+{
+return [[UIDevice currentDevice] name];
+}

O tipo de retorno deste método deve ser do tipo objeto (id) e ser serializável para JSON. Isso significa que o gancho só pode retornar valores nulos ou JSON (por exemplo, NSNumber, NSString, NSArray, NSDictionary).

No momento, não recomendamos o uso de métodos síncronos, pois chamar métodos de forma síncrona pode causar fortes penalidades de desempenho e introduzir bugs relacionados a threading em seus módulos nativos. Além disso, observe que se você optar por usar RCT_EXPORT_BLOCKING_SYNCHRONOUS_METHOD, seu aplicativo não poderá mais usar o depurador do Google Chrome. Isso ocorre porque os métodos síncronos exigem que a VM JS compartilhe memória com o aplicativo. Para o depurador do Google Chrome, o React Native é executado dentro da VM JS no Google Chrome e se comunica de forma assíncrona com os dispositivos móveis por meio de WebSockets.

Teste o que você construiu

Neste ponto, você configurou a estrutura básica para seu módulo nativo no iOS. Teste isso acessando o módulo nativo e invocando seu método exportado em JavaScript.

Encontre um local em seu aplicativo onde você gostaria de adicionar uma chamada ao método createCalendarEvent() do módulo nativo. Abaixo está um exemplo de componente, NewModuleButton, que você pode adicionar ao seu aplicativo. Você pode invocar o módulo nativo dentro da função onPress() do NewModuleButton.

tsx
import React from 'react';
+import {NativeModules, Button} from 'react-native';
+
+const NewModuleButton = () => {
+  const onPress = () => {
+    console.log('We will invoke the native module here!');
+  };
+
+  return (
+    <Button
+      title="Click to invoke your native module!"
+      color="#841584"
+      onPress={onPress}
+    />
+  );
+};
+
+export default NewModuleButton;

Para acessar seu módulo nativo a partir de JavaScript, você precisa primeiro importar NativeModules do React Native:

tsx
import {NativeModules} from 'react-native';

Você pode então acessar o módulo nativo CalendarModule fora de NativeModules.

tsx
const {CalendarModule} = NativeModules;

Agora que você tem o módulo nativo CalendarModule disponível, você pode invocar seu método nativo createCalendarEvent(). Abaixo é adicionado ao método onPress() em NewModuleButton:

tsx
const onPress = () => {
+  CalendarModule.createCalendarEvent('testName', 'testLocation');
+};

A etapa final é reconstruir o aplicativo React Native para que você possa ter o código nativo mais recente (com seu novo módulo nativo!) Disponível. Na linha de comando, onde o aplicativo react nativo está localizado, execute o seguinte:

bash
npm run ios
bash
yarn ios

Construindo enquanto você itera

À medida que você trabalha nesses guias e itera em seu módulo nativo, você precisará fazer uma reconstrução nativa de seu aplicativo para acessar as alterações mais recentes do JavaScript. Isso ocorre porque o código que você está escrevendo fica na parte nativa do seu aplicativo. Embora o empacotador metro do React Native possa observar mudanças no JavaScript e reconstruir o pacote JS rapidamente para você, ele não fará isso para o código nativo. Portanto, se você quiser testar suas alterações nativas mais recentes, precisará reconstruí-las usando o comando acima.

Recapitulação✨

Agora você deve conseguir invocar seu método createCalendarEvent() em seu módulo nativo em JavaScript. Como você está usando RCTLog na função, você pode confirmar se seu método nativo está sendo invocado ativando o modo de depuração em seu aplicativo e observando o console JS no Chrome ou o depurador de aplicativo móvel Flipper. Você deverá ver seu RCTLogInfo(@"Fingindo criar um evento %@ em %@", nome, local); mensagem cada vez que você invoca o método do módulo nativo.

Imagem dos registros do iOS no Flipper

Neste ponto, você criou um módulo nativo do iOS e invocou um método nele a partir de JavaScript em seu aplicativo React Native. Você pode continuar lendo para aprender mais sobre coisas como quais tipos de argumento seu método de módulo nativo usa e como configurar retornos de chamada e promessas em seu módulo nativo.

Além de um módulo nativo de calendário

Melhor exportação de módulo nativo

Importar seu módulo nativo retirando-o de NativeModules como acima é um pouco complicado.

Para evitar que os consumidores do seu módulo nativo precisem fazer isso sempre que quiserem acessar seu módulo nativo, você pode criar um wrapper JavaScript para o módulo. Crie um novo arquivo JavaScript chamado NativeCalendarModule.js com o seguinte conteúdo:

js
/**
+* Isso expõe o módulo nativo CalendarModule como um módulo JS. Isto tem um
+* função 'createCalendarEvent' que leva os seguintes parâmetros:
+
+* 1. String name: Uma string que representa o nome do evento
+* 2. String location: Uma string que representa a localização do evento
+*/
+import {NativeModules} from 'react-native';
+const {CalendarModule} = NativeModules;
+export default CalendarModule;

Este arquivo JavaScript também se torna um bom local para você adicionar qualquer funcionalidade secundária do JavaScript. Por exemplo, se você usar um sistema de tipos como TypeScript, poderá adicionar anotações de tipo para seu módulo nativo aqui. Embora o React Native ainda não ofereça suporte à segurança de tipo Native to JS, com essas anotações de tipo, todo o seu código JS será de tipo seguro. Essas anotações também facilitarão a mudança para módulos nativos com segurança de tipo no futuro. Abaixo está um exemplo de adição de segurança de tipo ao Módulo Calendário:

js
/**
+ * Isso expõe o módulo nativo CalendarModule como um módulo JS. Isto tem um
+ * função 'createCalendarEvent' que leva os seguintes parâmetros:
+ *
+ * 1. String name: Uma string que representa o nome do evento
+ * 2. String location: Uma string que representa a localização do evento
+ */
+import {NativeModules} from 'react-native';
+const {CalendarModule} = NativeModules;
+interface CalendarInterface {
+  createCalendarEvent(name: string, location: string): void;
+}
+export default CalendarModule as CalendarInterface;

Nos seus outros arquivos JavaScript você pode acessar o módulo nativo e invocar seu método assim:

jsx
import NativeCalendarModule from './NativeCalendarModule';
+NativeCalendarModule.createCalendarEvent('foo', 'bar');

DICA

Observe que isso pressupõe que o local que você está importando CalendarModule está na mesma hierarquia que CalendarModule.js. Atualize a importação relativa conforme necessário.

Tipos de argumento

Quando um método de módulo nativo é invocado em JavaScript, o React Native converte os argumentos dos objetos JS em seus análogos de objetos Objective-C/Swift. Por exemplo, se o seu método Objective-C Native Module aceita um NSNumber, em JS você precisa chamar o método com um número. React Native cuidará da conversão para você. Abaixo está uma lista dos tipos de argumentos suportados pelos métodos de módulo nativos e os equivalentes JavaScript para os quais eles mapeiam.

OBJECTIVE-CJAVASCRIPT
N SStringstring, ?string
BOOLboolean
doublenumber
NSNumber?number
NSArrayArray, ?Array
NSDictionaryObject, ?Object
RCTResponseSenderBlockFunction (success)
RCTResponseSenderBlock, RCTResponseErrorBlockFunction (failure)
RCTPromiseResolveBlock, RCTPromiseRejectBlockPromise

INFORMAÇÕES

Os seguintes tipos são atualmente suportados, mas não serão suportados em TurboModules. Por favor, evite usá-los.

  • Function (failure) -> RCTResponseErrorBlock
  • Number -> NSInteger
  • Number -> CGFloat
  • Number -> float

Para iOS, você também pode escrever métodos de módulo nativos com qualquer tipo de argumento compatível com a classe RCTConvert (consulte RCTConvert para obter detalhes sobre o que é compatível). Todas as funções auxiliares RCTConvert aceitam um valor JSON como entrada e o mapeiam para um tipo ou classe Objective-C nativo.

Exportando Constantes

Um módulo nativo pode exportar constantes substituindo o método nativo constantsToExport(). Abaixo de constantsToExport() é substituído e retorna um Dicionário que contém uma propriedade de nome de evento padrão que você pode acessar em JavaScript da seguinte forma:

c
- (NSDictionary *)constantsToExport
+{
+ return @{ @"DEFAULT_EVENT_NAME": @"New Event" };
+}

A constante pode então ser acessada invocando getConstants() no módulo nativo em JS da seguinte forma:

js
const {DEFAULT_EVENT_NAME} = CalendarModule.getConstants();
+console.log(DEFAULT_EVENT_NAME);

Tecnicamente, é possível acessar constantes exportadas em constantsToExport() diretamente do objeto NativeModule. Isso não será mais compatível com TurboModules, por isso encorajamos a comunidade a mudar para a abordagem acima para evitar a migração necessária no futuro.

INFORMAÇÕES

Observe que as constantes são exportadas apenas no momento da inicialização, portanto, se você alterar os valores de constantsToExport() no tempo de execução, isso não afetará o ambiente JavaScript.

Para iOS, se você substituir constantsToExport() então você também deve implementar +requireMainQueueSetup para que o React Native saiba se seu módulo precisa ser inicializado no thread principal, antes da execução de qualquer código JavaScript. Caso contrário, você verá um aviso de que no futuro seu módulo poderá ser inicializado em um thread em segundo plano, a menos que você desative explicitamente com +requireMainQueueSetup:. Se o seu módulo não requer acesso ao UIKit, você deve responder a +requerMainQueueSetup com NÃO.

Callback

Os módulos nativos também suportam um tipo único de argumento - um retorno de chamada. Retornos de chamada são usados para passar dados de Objective-C para JavaScript para métodos assíncronos. Eles também podem ser usados para executar JS de forma assíncrona do lado nativo.

Para iOS, os retornos de chamada são implementados usando o tipo RCTResponseSenderBlock. Abaixo do parâmetro de retorno de chamada myCallBack é adicionado ao createCalendarEventMethod():

c
RCT_EXPORT_METHOD(createCalendarEvent:(NSString *)title
+                location:(NSString *)location
+                myCallback:(RCTResponseSenderBlock)callback)

Você pode então invocar o retorno de chamada em sua função nativa, fornecendo qualquer resultado que deseja passar para JavaScript em um array. Observe que RCTResponseSenderBlock aceita apenas um argumento - uma matriz de parâmetros a serem passados para o retorno de chamada JavaScript. Abaixo você retornará o ID de um evento criado em uma chamada anterior.

INFORMAÇÕES

É importante destacar que o retorno de chamada não é invocado imediatamente após a conclusão da função nativa – lembre-se que a comunicação é assíncrona.

c
RCT_EXPORT_METHOD(createCalendarEvent:(NSString *)title location:(NSString *)location callback: (RCTResponseSenderBlock)callback)
+{
+ NSInteger eventId = ...
+ callback(@[@(eventId)]);
+
+ RCTLogInfo(@"Pretending to create an event %@ at %@", title, location);
+}

Este método pode então ser acessado em JavaScript usando o seguinte:

tsx
const onSubmit = () => {
+  CalendarModule.createCalendarEvent(
+    'Party',
+    '04-12-2020',
+    eventId => {
+      console.log(`Created a new event with id ${eventId}`);
+    },
+  );
+};

Um módulo nativo deve invocar seu retorno de chamada apenas uma vez. No entanto, ele pode armazenar o retorno de chamada e invocá-lo mais tarde. Esse padrão é frequentemente usado para agrupar APIs iOS que exigem delegados — consulte RCTAlertManager para obter um exemplo. Se o retorno de chamada nunca for invocado, alguma memória será vazada.

Existem duas abordagens para tratamento de erros com retornos de chamada. A primeira é seguir a convenção do Node e tratar o primeiro argumento passado para o array de retorno de chamada como um objeto de erro.

c
RCT_EXPORT_METHOD(createCalendarEventCallback:(NSString *)title location:(NSString *)location callback: (RCTResponseSenderBlock)callback)
+{
+  NSNumber *eventId = [NSNumber numberWithInt:123];
+  callback(@[[NSNull null], eventId]);
+}

Em JavaScript, você pode verificar o primeiro argumento para ver se um erro foi transmitido:

tsx
const onPress = () => {
+  CalendarModule.createCalendarEventCallback(
+    'testName',
+    'testLocation',
+    (error, eventId) => {
+      if (error) {
+        console.error(`Error found! ${error}`);
+      }
+      console.log(`event id ${eventId} returned`);
+    },
+  );
+};

Outra opção é usar dois retornos de chamada separados: onFailure e onSuccess.

c
RCT_EXPORT_METHOD(createCalendarEventCallback:(NSString *)title
+                  location:(NSString *)location
+                  errorCallback: (RCTResponseSenderBlock)errorCallback
+                  successCallback: (RCTResponseSenderBlock)successCallback)
+{
+  @try {
+    NSNumber *eventId = [NSNumber numberWithInt:123];
+    successCallback(@[eventId]);
+  }
+
+  @catch ( NSException *e ) {
+    errorCallback(@[e]);
+  }
+}

Então, em JavaScript, você pode adicionar um retorno de chamada separado para respostas de erro e sucesso:

tsx
const onPress = () => {
+  CalendarModule.createCalendarEventCallback(
+    'testName',
+    'testLocation',
+    error => {
+      console.error(`Error found! ${error}`);
+    },
+    eventId => {
+      console.log(`event id ${eventId} returned`);
+    },
+  );
+};

Se você deseja passar objetos semelhantes a erros para JavaScript, use RCTMakeError de RCTUtils.h. No momento, isso apenas passa um dicionário em formato de erro para JavaScript, mas o React Native visa gerar automaticamente objetos de erro JavaScript reais no futuro. Você também pode fornecer um argumento RCTResponseErrorBlock, que é usado para retornos de chamada de erro e aceita um NSError \* object. Observe que este tipo de argumento não será compatível com TurboModules.

Promises

Módulos nativos também podem cumprir uma promessa, o que pode simplificar seu JavaScript, especialmente ao usar a sintaxe async/await do ES2016. Quando o último parâmetro de um método de módulo nativo é RCTPromiseResolveBlock e RCTPromiseRejectBlock, seu método JS correspondente retornará um objeto JS Promise.

Refatorar o código acima para usar uma promessa em vez de retornos de chamada é assim:

c
RCT_EXPORT_METHOD(createCalendarEvent:(NSString *)title
+                 location:(NSString *)location
+                 resolver:(RCTPromiseResolveBlock)resolve
+                 rejecter:(RCTPromiseRejectBlock)reject)
+{
+ NSInteger eventId = createCalendarEvent();
+ if (eventId) {
+    resolve(@(eventId));
+  } else {
+    reject(@"event_failure", @"no event id returned", nil);
+  }
+}

A contraparte JavaScript deste método retorna uma promessa. Isso significa que você pode usar a palavra-chave await dentro de uma função assíncrona para chamá-la e aguardar seu resultado:

tsx
const onSubmit = async () => {
+  try {
+    const eventId = await CalendarModule.createCalendarEvent(
+      'Party',
+      'my house',
+    );
+    console.log(`Created a new event with id ${eventId}`);
+  } catch (e) {
+    console.error(e);
+  }
+};

Enviando eventos para JavaScript

Módulos nativos podem sinalizar eventos para o JavaScript sem serem invocados diretamente. Por exemplo, você pode sinalizar para o JavaScript um lembrete de que um evento de calendário do aplicativo de calendário nativo do iOS ocorrerá em breve. A maneira preferida de fazer isso é subclassificar RCTEventEmitter, implementar SupportedEvents e chamar sendEventWithName:

Atualize sua classe de cabeçalho para importar RCTEventEmitter e subclasse RCTEventEmitter:

c
//  CalendarModule.h
+
+#import <React/RCTBridgeModule.h>
+#import <React/RCTEventEmitter.h>
+
+@interface CalendarModule : RCTEventEmitter <RCTBridgeModule>
+@end

O código JavaScript pode assinar esses eventos criando uma nova instância NativeEventEmitter em torno do seu módulo.

Você receberá um aviso se gastar recursos desnecessariamente emitindo um evento enquanto não houver ouvintes. Para evitar isso e otimizar a carga de trabalho do seu módulo (por exemplo, cancelando a assinatura de notificações upstream ou pausando tarefas em segundo plano), você pode substituir startObserving e stopObserving em sua subclasse RCTEventEmitter.

c
@implementation CalendarManager
+{
+  bool hasListeners;
+}
+
+// Será chamado quando o primeiro ouvinte deste módulo for adicionado.
+-(void)startObserving {
+    hasListeners = YES;
+    // Configure quaisquer ouvintes upstream ou tarefas em segundo plano conforme necessário
+}
+
+// Será chamado quando o último ouvinte deste módulo for removido ou no dealloc.
+-(void)stopObserving {
+    hasListeners = NO;
+    // Remove upstream listeners, stop unnecessary background tasks
+}
+
+- (void)calendarEventReminderReceived:(NSNotification *)notification
+{
+  NSString *eventName = notification.userInfo[@"name"];
+  if (hasListeners) {//Só envia eventos se alguém estiver ouvindo
+    [self sendEventWithName:@"EventReminder" body:@{@"name": eventName}];
+  }
+}

Threading

A menos que o módulo nativo forneça sua própria fila de métodos, ele não deve fazer nenhuma suposição sobre em qual thread está sendo chamado. Atualmente, se um módulo nativo não fornecer uma fila de métodos, o React Native criará uma fila GCD separada para ele e invocará seus métodos lá. Observe que este é um detalhe de implementação e pode mudar. Se você quiser fornecer explicitamente uma fila de métodos para um módulo nativo, substitua o método (dispatch_queue_t) methodQueue no módulo nativo. Por exemplo, se for necessário usar uma API iOS somente de thread principal, ele deverá especificar isso por meio de:

c
- (dispatch_queue_t)methodQueue
+{
+  return dispatch_get_main_queue();
+}

Da mesma forma, se uma operação demorar muito para ser concluída, o módulo nativo poderá especificar sua própria fila para executar as operações. Novamente, atualmente o React Native fornecerá uma fila de métodos separada para seu módulo nativo, mas este é um detalhe de implementação no qual você não deve confiar. Se você não fornecer sua própria fila de métodos, no futuro, as operações de longa execução do seu módulo nativo poderão acabar bloqueando a execução de chamadas assíncronas em outros módulos nativos não relacionados. O módulo RCTAsyncLocalStorage aqui, por exemplo, cria sua própria fila para que a fila React não seja bloqueada aguardando um acesso potencialmente lento ao disco.

c
- (dispatch_queue_t)methodQueue
+{
+ return dispatch_queue_create("com.facebook.React.AsyncLocalStorageQueue", DISPATCH_QUEUE_SERIAL);
+}

O methodQueue especificado será compartilhado por todos os métodos do seu módulo. Se apenas um dos seus métodos for de longa duração (ou precisar ser executado em uma fila diferente dos outros por algum motivo), você poderá usar dispatch_async dentro do método para executar o código desse método específico em outra fila, sem afetar os outros:

c
RCT_EXPORT_METHOD(doSomethingExpensive:(NSString *)param callback:(RCTResponseSenderBlock)callback)
+{
+ dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
+   // Call long-running code on background thread
+   ...
+   // You can invoke callback from any thread/queue
+   callback(@[...]);
+ });
+}

Compartilhando filas de despacho entre módulos

O método methodQueue será chamado uma vez quando o módulo for inicializado e então retido pelo React Native, portanto não há necessidade de manter uma referência à fila, a menos que você queira usá-la em seu módulo. No entanto, se desejar compartilhar a mesma fila entre vários módulos, você precisará garantir que retém e retorna a mesma instância de fila para cada um deles.

Injeção de dependência

O React Native criará e inicializará automaticamente quaisquer módulos nativos registrados. No entanto, você pode desejar criar e inicializar suas próprias instâncias de módulo para, por exemplo, injetar dependências.

Você pode fazer isso criando uma classe que implemente o protocolo RCTBridgeDelegate, inicializando um RCTBridge com o delegado como argumento e inicializando um RCTRootView com a ponte inicializada.

c
id<RCTBridgeDelegate> moduleInitialiser = [[classThatImplementsRCTBridgeDelegate alloc] init];
+
+RCTBridge *bridge = [[RCTBridge alloc] initWithDelegate:moduleInitialiser launchOptions:nil];
+
+RCTRootView *rootView = [[RCTRootView alloc]
+                        initWithBridge:bridge
+                            moduleName:kModuleName
+                     initialProperties:nil];

Exportando Swift

Swift não tem suporte para macros, então expor módulos nativos e seus métodos ao JavaScript dentro do React Native requer um pouco mais de configuração. No entanto, funciona relativamente da mesma forma. Digamos que você tenha o mesmo CalendarModule, mas como uma classe Swift:

swift
// CalendarManager.swift
+
+@objc(CalendarManager)
+class CalendarManager: NSObject {
+
+ @objc(addEvent:location:date:)
+ func addEvent(_ name: String, location: String, date: NSNumber) -> Void {
+   // A data está pronta para uso!
+ }
+
+ @objc
+ func constantsToExport() -> [String: Any]! {
+   return ["someKey": "someValue"]
+ }
+
+}

INFORMAÇÕES

É importante usar os modificadores @objc para garantir que a classe e as funções sejam exportadas corretamente para o tempo de execução do Objective-C.

Em seguida, crie um arquivo de implementação privado que registrará as informações necessárias com React Native:

c
// CalendarManagerBridge.m
+#import <React/RCTBridgeModule.h>
+
+@interface RCT_EXTERN_MODULE(CalendarManager, NSObject)
+
+RCT_EXTERN_METHOD(addEvent:(NSString *)name location:(NSString *)location date:(nonnull NSNumber *)date)
+
+@end

Para aqueles que são novos em Swift e Objective-C, sempre que misturar as duas linguagens em um projeto iOS, você também precisará de um arquivo de ponte adicional, conhecido como cabeçalho de ponte, para expor os arquivos de Objective-C ao Swift. O Xcode se oferecerá para criar este arquivo de cabeçalho para você se você adicionar seu arquivo Swift ao seu aplicativo por meio da opção de menu File > New File. Você precisará importar RCTBridgeModule.h neste arquivo de cabeçalho.

c
// CalendarManager-Bridging-Header.h
+#import <React/RCTBridgeModule.h>

Você também pode usar RCT_EXTERN_REMAP_MODULE e _RCT_EXTERN_REMAP_METHOD para alterar o nome JavaScript do módulo ou métodos que você está exportando. Para obter mais informações, consulte RCTBridgeModule.

INFORMAÇÕES

Importante ao criar módulos de terceiros: Bibliotecas estáticas com Swift são suportadas apenas no Xcode 9 e posterior. Para que o projeto Xcode seja compilado quando você usa Swift na biblioteca estática do iOS incluída no módulo, o projeto principal do seu aplicativo deve conter o código Swift e um cabeçalho de ponte em si. Se o projeto do seu aplicativo não contiver nenhum código Swift, uma solução alternativa poderá ser um único arquivo .swift vazio e um cabeçalho de ponte vazio.

Nomes de métodos reservados

invalidate()

Os módulos nativos podem estar em conformidade com o protocolo RCTInvalidating no iOS implementando o método invalidate(). Este método pode ser invocado quando a ponte nativa é invalidada (ou seja: no recarregamento do devmode). Use este mecanismo conforme necessário para fazer a limpeza necessária para seu módulo nativo.

+ + + + \ No newline at end of file diff --git a/vitepress/docs/.vitepress/dist/docs/native-modules-setup.html b/vitepress/docs/.vitepress/dist/docs/native-modules-setup.html new file mode 100644 index 0000000..456ec6f --- /dev/null +++ b/vitepress/docs/.vitepress/dist/docs/native-modules-setup.html @@ -0,0 +1,27 @@ + + + + + + Configuração do pacote NPM de módulos nativos | React Native 0.72 + + + + + + + + + + + + + + + + +
Skip to content

Configuração do pacote NPM de módulos nativos

INFORMAÇÕES

Módulo Nativo e Componentes Nativos são nossas tecnologias estáveis usadas pela arquitetura legada. Eles serão descontinuados no futuro, quando a Nova Arquitetura estiver estável. A nova arquitetura usa Turbo Native Module e Fabric Native Components para obter resultados semelhantes.

Módulos nativos são geralmente distribuídos como pacotes npm, exceto que além do JavaScript usual eles incluirão algum código nativo por plataforma. Para entender mais sobre os pacotes npm, este guia pode ser útil.

Para configurar a estrutura básica do projeto para um módulo nativo, usaremos a ferramenta da comunidade chamada create-react-native-library. Você pode ir mais longe e se aprofundar em como essa biblioteca funciona, mas para nossas necessidades executaremos apenas o script básico:

bash
npx create-react-native-library@latest react-native-awesome-module

Onde react-native-awesome-module é o nome que você gostaria para o novo módulo. Depois de fazer isso, você navegará até a pasta react-native-awesome-module e inicializará o projeto de exemplo executando:

bash
yarn

Quando o bootstrap estiver concluído, você poderá iniciar o aplicativo de exemplo executando um dos seguintes comandos:

bash
yarn example android
bash
yarn example ios

Quando todas as etapas acima forem concluídas, você poderá continuar com os guias de módulos nativos do Android ou módulos nativos do iOS para adicionar algum código.

INFORMAÇÕES

Para uma configuração menos opinativa, dê uma olhada na ferramenta de terceiros create-react-native-module.

+ + + + \ No newline at end of file diff --git a/vitepress/docs/.vitepress/dist/docs/navigation.html b/vitepress/docs/.vitepress/dist/docs/navigation.html new file mode 100644 index 0000000..031389f --- /dev/null +++ b/vitepress/docs/.vitepress/dist/docs/navigation.html @@ -0,0 +1,27 @@ + + + + + + Navegando entre telas | React Native 0.72 + + + + + + + + + + + + + + + + +
Skip to content

Navegando entre telas

Os aplicativos móveis raramente são compostos de uma única tela. O gerenciamento da apresentação e da transição entre várias telas normalmente é feito pelo que é conhecido como navegador.

Este guia aponta para os vários componentes de navegação disponíveis no React Native. Se você está começando com a navegação, provavelmente desejará usar o React Navigation. React Navigation fornece uma solução de navegação simples, com a capacidade de apresentar navegação de pilha comum e padrões de navegação com guias no Android e iOS.

Se você estiver integrando o React Native em um aplicativo que já gerencia a navegação nativamente ou procurando uma alternativa ao React Navigation, a biblioteca a seguir fornece navegação nativa em ambas as plataformas: react-native-navigation.

A solução comunitária para navegação é uma biblioteca independente que permite aos desenvolvedores configurar as telas de um aplicativo com algumas linhas de código.

Para uma introdução completa ao React Navigation, siga o Guia de primeiros passos do React Navigation.

React Native Navigation

Conforme afirmado acima, react-native-navigation é outra solução para navegação em aplicativos react nativos. É uma biblioteca que oferece soluções para navegações básicas e avançadas.

Para uma introdução completa ao React Native Navigation, siga o Guia de primeiros passos do React Native Navigation.

+ + + + \ No newline at end of file diff --git a/vitepress/docs/.vitepress/dist/docs/network.html b/vitepress/docs/.vitepress/dist/docs/network.html new file mode 100644 index 0000000..23e9991 --- /dev/null +++ b/vitepress/docs/.vitepress/dist/docs/network.html @@ -0,0 +1,152 @@ + + + + + + Rede | React Native 0.72 + + + + + + + + + + + + + + + + +
Skip to content

Rede

Muitos aplicativos móveis precisam carregar recursos de uma URL remota. Você pode querer fazer uma solicitação POST para uma API REST ou pode precisar buscar um pedaço de conteúdo estático de outro servidor.

Usando o Fetch

React Native fornece a API Fetch para suas necessidades de rede. Fetch parecerá familiar se você já usou XMLHttpRequest ou outras APIs de rede antes. Você pode consultar o guia do MDN sobre como usar o Fetch para obter informações adicionais.

Fazendo requisições

Para buscar conteúdo de um URL arbitrário, você pode passar o URL a ser buscado:

js
fetch('https://mywebsite.com/mydata.json');

Fetch também usa um segundo argumento opcional que permite personalizar a solicitação HTTP. Você pode especificar cabeçalhos adicionais ou fazer uma solicitação POST:

js
fetch('https://mywebsite.com/endpoint/', {
+  method: 'POST',
+  headers: {
+    Accept: 'application/json',
+    'Content-Type': 'application/json',
+  },
+  body: JSON.stringify({
+    firstParam: 'yourValue',
+    secondParam: 'yourOtherValue',
+  }),
+});

Dê uma olhada na documentação do Fetch Request para obter uma lista completa de propriedades.

Lidando com a resposta

Os exemplos acima mostram como você pode fazer uma solicitação. Em muitos casos, você desejará fazer algo com a resposta.

A rede é uma operação inerentemente assíncrona. O método Fetch retornará uma Promise que simplifica a escrita de código que funciona de maneira assíncrona:

js
const getMoviesFromApi = () => {
+  return fetch('https://reactnative.dev/movies.json')
+    .then(response => response.json())
+    .then(json => {
+      return json.movies;
+    })
+    .catch(error => {
+      console.error(error);
+    });
+};

Você também pode usar a sintaxe async/await em um aplicativo React Native:

js
const getMoviesFromApiAsync = async () => {
+  try {
+    const response = await fetch(
+      'https://reactnative.dev/movies.json',
+    );
+    const json = await response.json();
+    return json.movies;
+  } catch (error) {
+    console.error(error);
+  }
+};

Não se esqueça de capturar quaisquer erros que possam ser lançados pela busca, caso contrário eles serão descartados silenciosamente.

js
import React, {useEffect, useState} from 'react';
+import {ActivityIndicator, FlatList, Text, View} from 'react-native';
+
+type Movie = {
+  id: string;
+  title: string;
+  releaseYear: string;
+};
+
+const App = () => {
+  const [isLoading, setLoading] = useState(true);
+  const [data, setData] = useState<Movie[]>([]);
+
+  const getMovies = async () => {
+    try {
+      const response = await fetch('https://reactnative.dev/movies.json');
+      const json = await response.json();
+      setData(json.movies);
+    } catch (error) {
+      console.error(error);
+    } finally {
+      setLoading(false);
+    }
+  };
+
+  useEffect(() => {
+    getMovies();
+  }, []);
+
+  return (
+    <View style={{flex: 1, padding: 24}}>
+      {isLoading ? (
+        <ActivityIndicator />
+      ) : (
+        <FlatList
+          data={data}
+          keyExtractor={({id}) => id}
+          renderItem={({item}) => (
+            <Text>
+              {item.title}, {item.releaseYear}
+            </Text>
+          )}
+        />
+      )}
+    </View>
+  );
+};
+
+export default App;

Resposta:

Star Wars, 1977
+Back to the Future, 1985
+The Matrix, 1999
+Inception, 2010
+Interstellar, 2014

Por padrão, o iOS 9.0 ou posterior aplica o App Transport Secruity (ATS). O ATS requer qualquer conexão HTTP para usar HTTPS. Se você precisar buscar em um URL de texto simples (que comece com http), primeiro você precisará adicionar uma exceção ATS. Se você souber antecipadamente a quais domínios precisará acessar, será mais seguro adicionar exceções apenas para esses domínios; se os domínios não forem conhecidos até o tempo de execução, você poderá desativar o ATS completamente. Observe, entretanto, que a partir de janeiro de 2017, a revisão da App Store da Apple exigirá uma justificativa razoável para desativar o ATS. Consulte a documentação da Apple para obter mais informações.

No Android, a partir do nível 28 da API, o tráfego de texto simples também é bloqueado por padrão. Esse comportamento pode ser substituído definindo android:usesCleartextTraffic no arquivo de manifesto do aplicativo.

Usando outras bibliotecas de rede

A API XMLHttpRequest está integrada ao React Native. Isso significa que você pode usar bibliotecas de terceiros, como frisbee ou axios, que dependem dele, ou pode usar a API XMLHttpRequest diretamente, se preferir.

js
const request = new XMLHttpRequest();
+request.onreadystatechange = e => {
+  if (request.readyState !== 4) {
+    return;
+  }
+
+  if (request.status === 200) {
+    console.log('success', request.responseText);
+  } else {
+    console.warn('error');
+  }
+};
+
+request.open('GET', 'https://mywebsite.com/endpoint/');
+request.send();

O modelo de segurança para XMLHttpRequest é diferente do modelo da web, pois não há conceito de CORS em aplicativos nativos.

Suporte WebSocket

React Native também oferece suporte a WebSockets, um protocolo que fornece canais de comunicação full-duplex em uma única conexão TCP.

js
const ws = new WebSocket('ws://host.com/path');
+
+ws.onopen = () => {
+  // conexão aberta
+  ws.send('something'); // envia uma mensagem
+};
+
+ws.onmessage = e => {
+  // uma mensagem foi recebida
+  console.log(e.data);
+};
+
+ws.onerror = e => {
+  // um erro aconteceu
+  console.log(e.message);
+};
+
+ws.onclose = e => {
+  // conexão fechada
+  console.log(e.code, e.reason);
+};

As opções a seguir não estão funcionando atualmente com busca

  • redirect:manual
  • credentials:omit
  • Ter cabeçalhos com o mesmo nome no Android resultará na presença apenas do mais recente. Uma solução temporária pode ser encontrada aqui: https://github.com/facebook/react-native/issues/18837#issuecomment-398779994.
  • A autenticação baseada em cookies é atualmente instável. Você pode ver algumas das questões levantadas aqui: https://github.com/facebook/react-native/issues/23185
  • No mínimo no iOS, quando redirecionado através de um 302, se um cabeçalho Set-Cookie estiver presente, o cookie não será definido corretamente. Como o redirecionamento não pode ser tratado manualmente, isso pode causar um cenário em que ocorrem solicitações infinitas se o redirecionamento for o resultado de uma sessão expirada.

Configurando NSURLSession no iOS

Para alguns aplicativos, pode ser apropriado fornecer um NSURLSessionConfiguration personalizado para o NSURLSession subjacente que é usado para solicitações de rede em um aplicativo React Native em execução no iOS. Por exemplo, pode ser necessário definir uma string de agente de usuário personalizada para todas as solicitações de rede provenientes do aplicativo ou fornecer NSURLSession com um NSURLSessionConfiguration efêmero. A função RCTSetCustomNSURLSessionConfigurationProvider permite tal customização. Lembre-se de adicionar a seguinte importação ao arquivo no qual RCTSetCustomNSURLSessionConfigurationProvider será chamado:

swift
#import <React/RCTHTTPRequestHandler.h>

RCTSetCustomNSURLSessionConfigurationProvider deve ser chamado no início do ciclo de vida do aplicativo para que esteja prontamente disponível quando necessário pelo React, por exemplo:

-(void)application:(__unused UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
+
+  // set RCTSetCustomNSURLSessionConfigurationProvider
+  RCTSetCustomNSURLSessionConfigurationProvider(^NSURLSessionConfiguration *{
+     NSURLSessionConfiguration *configuration = [NSURLSessionConfiguration defaultSessionConfiguration];
+     // configure the session
+     return configuration;
+  });
+
+  // set up React
+  _bridge = [[RCTBridge alloc] initWithDelegate:self launchOptions:launchOptions];
+ + + + \ No newline at end of file diff --git a/vitepress/docs/.vitepress/dist/docs/optimizing-flatlist-configuration.html b/vitepress/docs/.vitepress/dist/docs/optimizing-flatlist-configuration.html new file mode 100644 index 0000000..046d759 --- /dev/null +++ b/vitepress/docs/.vitepress/dist/docs/optimizing-flatlist-configuration.html @@ -0,0 +1,40 @@ + + + + + + Otimizando a configuração da Flatlist | React Native 0.72 + + + + + + + + + + + + + + + + +
Skip to content

Otimizando a configuração da Flatlist

Termos

  • VirtualizedList: O componente por trás do FlatList (implementação do conceito de Lista Virtual do React Native).
  • Consumo de memória: quanta informação sobre sua lista está armazenada na memória, o que pode causar falha no aplicativo.
  • Capacidade de resposta: capacidade do aplicativo de responder às interações. A baixa capacidade de resposta, por exemplo, ocorre quando você toca em um componente e ele espera um pouco para responder, em vez de responder imediatamente conforme o esperado.
  • Áreas em branco: quando VirtualizedList não consegue renderizar seus itens com rapidez suficiente, você pode inserir uma parte de sua lista com componentes não renderizados que aparecem como espaço em branco.
  • Viewport: a área visível do conteúdo que é renderizada em pixels.
  • Window: A área na qual os itens devem ser montados, que geralmente é muito maior que a janela de visualização.

Props

Aqui está uma lista de acessórios que podem ajudar a melhorar o desempenho do FlatList:

removeClippedSubviews

TIPOPADRÃO
BooleanFalse

Se for true, as visualizações que estão fora da viewport serão desanexadas da hierarquia de visualizações nativas.

Prós: Isso reduz o tempo gasto no thread principal e, portanto, reduz o risco de perda de quadros, excluindo visualizações fora da janela de visualização da renderização nativa e das travessias de desenho.

Contras: Esteja ciente de que esta implementação pode ter bugs, como conteúdo ausente (observado principalmente no iOS), especialmente se você estiver fazendo coisas complexas com transformações e/ou posicionamento absoluto. Observe também que isso não economiza memória significativa porque as visualizações não são desalocadas, apenas desanexadas.

maxToRenderPerBatch

TIPOPADRÃO
Number10

É um suporte VirtualizedList que pode ser passado por FlatList. Isso controla a quantidade de itens renderizados por lote, que é o próximo pedaço de itens renderizados em cada pergaminho.

Prós: Definir um número maior significa menos áreas em branco visuais durante a rolagem (aumenta a taxa de preenchimento).

Contras: mais itens por lote significam períodos mais longos de execução de JavaScript, potencialmente bloqueando o processamento de outros eventos, como clicks, prejudicando a capacidade de resposta.

updateCellsBatchingPeriod

TIPOPADRÃO
Number50

Enquanto maxToRenderPerBatch informa a quantidade de itens renderizados por lote, a configuração updateCellsBatchingPeriod informa ao VirtualizedList o atraso em milissegundos entre as renderizações em lote (com que frequência seu componente renderizará os itens em janela).

Prós: combinar esta propriedade com maxToRenderPerBatch dá a você o poder de, por exemplo, renderizar mais itens em um lote menos frequente ou menos itens em um lote mais frequente.

Contras: Lotes menos frequentes podem causar áreas em branco. Lotes mais frequentes podem causar problemas de capacidade de resposta.

initialNumToRender

TIPOPADRÃO
Number10

A quantidade inicial de itens a serem renderizados.

Prós: Defina o número preciso de itens que cobririam a tela de cada dispositivo. Isso pode ser um grande aumento de desempenho para a renderização inicial.

Contras: Definir um initialNumToRender baixo pode causar áreas em branco, especialmente se for muito pequeno para cobrir a janela de visualização na renderização inicial.

windowSize

TIPOPADRÃO
Number21

O número passado aqui é uma unidade de medida onde 1 é equivalente à altura da sua janela de visualização. O valor padrão é 21 (10 viewports acima, 10 abaixo e uma intermediária).

Prós: windowSize maior resultará em menos chance de ver espaços em branco durante a rolagem. Por outro lado, windowSize menor resultará em menos itens montados simultaneamente, economizando memória.

Contras: Para um tamanho de janela maior, você terá mais consumo de memória. Para um tamanho de janela menor, você terá uma chance maior de ver áreas em branco.

Lista de itens

Abaixo estão algumas dicas sobre os componentes dos itens da lista. Eles são o núcleo da sua lista, por isso precisam ser rápidos.

Use componentes básicos

Quanto mais complexos forem seus componentes, mais lento eles serão renderizados. Tente evitar muita lógica e aninhamento nos itens da sua lista. Se você reutiliza muito esse componente de item de lista em seu aplicativo, crie um componente apenas para suas listas grandes e faça-as com o mínimo de lógica e aninhamento possível.

Use componentes leves

Quanto mais pesados forem seus componentes, mais lento eles serão renderizados. Evite imagens pesadas (use uma versão recortada ou miniatura para os itens da lista, o menor possível). Converse com sua equipe de design, use o mínimo possível de efeitos, interações e informações em sua lista. Mostre-os nos detalhes do seu item.

Usar shouldComponentUpdate

Implemente a verificação de atualização em seus componentes. O PureComponent do React implementa um shouldComponentUpdate com comparação superficial. Isso é caro aqui porque precisa verificar todos os seus props. Se você deseja um bom desempenho em nível de bits, crie as regras mais rígidas para os componentes dos itens da lista, verificando apenas os props que podem mudar. Se sua lista for básica o suficiente, você pode até usar

js
shouldComponentUpdate() {
+  return false
+}

Use imagens otimizadas em cache

Você pode usar os pacotes da comunidade (como react-native-fast-image de @DylanVann) para obter imagens com melhor desempenho. Cada imagem na sua lista é uma nova instância de Image(). Quanto mais rápido ele atingir o gancho carregado, mais rápido seu thread JavaScript ficará livre novamente.

Use getItemLayout

Se todos os componentes do item da sua lista tiverem a mesma altura (ou largura, para uma lista horizontal), fornecer a propriedade getItemLayout elimina a necessidade de sua FlatList gerenciar cálculos de layout assíncronos. Esta é uma técnica de otimização muito desejável.

Se seus componentes têm tamanho dinâmico e você realmente precisa de desempenho, pergunte à sua equipe de design se eles podem pensar em um redesenho para ter um melhor desempenho.

Use keyExtractor ou key

Você pode definir o keyExtractor para o seu componente FlatList. Este suporte é usado para armazenamento em cache e como chave React para rastrear a reordenação de itens.

Você também pode usar um prop key em seu componente de item.

Evite função anônima em renderItem

Para componentes funcionais, mova a função renderItem para fora do JSX retornado. Além disso, certifique-se de que ele esteja encapsulado em um gancho useCallback para evitar que seja recriado a cada renderização.

Para componentes de classe, mova a função renderItem para fora da função de renderização, para que ela não se recrie cada vez que a função de renderização for chamada.

jsx
const renderItem = useCallback(({item}) => (
+   <View key={item.key}>
+      <Text>{item.title}</Text>
+   </View>
+ ), []);
+
+return (
+  // ...
+
+  <FlatList data={items} renderItem={renderItem} />;
+  // ...
+);
+ + + + \ No newline at end of file diff --git a/vitepress/docs/.vitepress/dist/docs/out-of-tree-platforms.html b/vitepress/docs/.vitepress/dist/docs/out-of-tree-platforms.html new file mode 100644 index 0000000..4f7ee48 --- /dev/null +++ b/vitepress/docs/.vitepress/dist/docs/out-of-tree-platforms.html @@ -0,0 +1,34 @@ + + + + + + Plataformas fora da árvore | React Native 0.72 + + + + + + + + + + + + + + + + +
Skip to content

Plataformas fora da árvore

React Native não é apenas para dispositivos Android e iOS - nossos parceiros e a comunidade mantêm projetos que levam o React Native para outras plataformas, como:

De parceiros

Da comunidade

Criando sua própria plataforma React Native

No momento, o processo de criação de uma plataforma React Native do zero não está muito bem documentado - um dos objetivos da próxima re-arquitetura (Fabric) é facilitar a manutenção de uma plataforma.

Bundling

A partir do React Native 0.57, agora você pode registrar sua plataforma React Native com o empacotador JavaScript do React Native, Metro. Isso significa que você pode passar o --platform example para o pacote npx react-native e ele procurará arquivos JavaScript com o sufixo .example.js.

Para cadastrar sua plataforma no RNPM, o nome do seu módulo deve corresponder a um destes padrões:

  • react-native-example - Ele irá pesquisar todos os módulos de nível superior que começam com react-native-
  • @org/react-native-example - Procurará módulos que começam com react-native- em qualquer escopo
  • @react-native-example/module - Ele pesquisará em todos os módulos sob escopos com nomes começando com @react-native-

Você também deve ter uma entrada em seu package.json assim:

json
{
+  "rnpm": {
+    "haste": {
+      "providesModuleNodeModules": ["react-native-example"],
+      "platforms": ["example"]
+    }
+  }
+}

"providesModuleNodeModules" é uma matriz de módulos que serão adicionados ao caminho de pesquisa do módulo Haste, e "platforms" é uma matriz de sufixos de plataforma que serão adicionados como plataformas válidas.

+ + + + \ No newline at end of file diff --git a/vitepress/docs/.vitepress/dist/docs/performance.html b/vitepress/docs/.vitepress/dist/docs/performance.html new file mode 100644 index 0000000..13dc597 --- /dev/null +++ b/vitepress/docs/.vitepress/dist/docs/performance.html @@ -0,0 +1,37 @@ + + + + + + Visão geral do desempenho | React Native 0.72 + + + + + + + + + + + + + + + + +
Skip to content

Visão geral do desempenho

Um motivo convincente para usar React Native em vez de ferramentas baseadas em WebView é atingir 60 quadros por segundo e uma aparência nativa para seus aplicativos. Sempre que possível, gostaríamos que o React Native fizesse a coisa certa e ajudasse você a se concentrar no seu aplicativo em vez da otimização do desempenho, mas há áreas onde ainda não chegamos lá e outras onde o React Native (semelhante a escrever nativo código diretamente) não pode determinar a melhor maneira de otimizar para você e, portanto, será necessária uma intervenção manual. Tentamos o nosso melhor para oferecer um desempenho de interface de usuário suave por padrão, mas às vezes isso não é possível.

Este guia tem como objetivo ensinar alguns princípios básicos para ajudá-lo a solucionar problemas de desempenho, bem como discutir fontes comuns de problemas e suas soluções sugeridas nesta seção.

O que você precisa saber sobre frames

A geração dos seus avós chamava os filmes de “imagens em movimento” por uma razão: o movimento realista no vídeo é uma ilusão criada pela rápida mudança de imagens estáticas a uma velocidade consistente. Referimo-nos a cada uma dessas imagens como quadros. O número de quadros exibidos a cada segundo tem um impacto direto na aparência suave e realista de um vídeo (ou interface do usuário). Os dispositivos iOS exibem 60 quadros por segundo, o que dá a você e ao sistema de UI cerca de 16,67 ms para realizar todo o trabalho necessário para gerar a imagem estática (quadro) que o usuário verá na tela nesse intervalo. Se você não conseguir fazer o trabalho necessário para gerar esse quadro dentro dos 16,67 ms alocados, você "descartará um quadro" e a IU parecerá sem resposta.

Agora, para confundir um pouco o assunto, abra o menu Dev em seu aplicativo e alterne Show Perf Monitor. Você notará que existem duas taxas de quadros diferentes.

Taxa de quadros JS (thread JavaScript)

Para a maioria dos aplicativos React Native, sua lógica de negócios será executada no thread JavaScript. É aqui que reside o seu aplicativo React, as chamadas de API são feitas, os eventos de toque são processados, etc... As atualizações para visualizações com suporte nativo são agrupadas e enviadas para o lado nativo no final de cada iteração do loop de eventos, antes do prazo do quadro (se tudo correr bem). Se o thread JavaScript não responder a um quadro, ele será considerado um quadro descartado. Por exemplo, se você chamar this.setState no componente raiz de um aplicativo complexo e isso resultar na nova renderização de subárvores de componentes computacionalmente caras, é concebível que isso possa levar 200 ms e resultar na eliminação de 12 quadros. Quaisquer animações controladas por JavaScript pareceriam congelar durante esse período. Se algo demorar mais de 100 ms, o usuário sentirá.

Isso geralmente acontece durante as transições do Navigator: quando você envia uma nova rota, o thread JavaScript precisa renderizar todos os componentes necessários para a cena para enviar os comandos apropriados ao lado nativo para criar as visualizações de apoio. É comum que o trabalho feito aqui ocupe alguns quadros e cause instabilidade porque a transição é controlada pelo thread JavaScript. Às vezes, os componentes farão trabalho adicional no componentDidMount, o que pode resultar em uma segunda falha na transição.

Outro exemplo é responder a toques: se você estiver trabalhando em vários quadros no thread JavaScript, poderá notar um atraso na resposta a TouchableOpacity, por exemplo. Isso ocorre porque a thread JavaScript está ocupada e não pode processar os eventos de toque brutos enviados da thread principal. Como resultado, TouchableOpacity não pode reagir aos eventos de toque e comandar a visualização nativa para ajustar sua opacidade.

Taxa de quadros da UI (thread principal)

Muitas pessoas notaram que o desempenho do NavigatorIOS é melhor do que o Navigator. A razão para isso é que as animações das transições são feitas inteiramente no thread principal e, portanto, não são interrompidas por quedas de quadros no thread JavaScript.

Da mesma forma, você pode rolar para cima e para baixo em um ScrollView quando o thread JavaScript está bloqueado porque o ScrollView reside no thread principal. Os eventos de rolagem são despachados para o thread JS, mas seu recebimento não é necessário para que a rolagem ocorra.

Fontes comuns de problemas de desempenho

Executando em modo de desenvolvimento (dev=true)

O desempenho do thread JavaScript sofre muito quando executado no modo de desenvolvimento. Isso é inevitável: muito mais trabalho precisa ser feito em tempo de execução para fornecer bons avisos e mensagens de erro, como validação de propTypes e várias outras asserções. Sempre certifique-se de testar o desempenho nas compilações de lançamento.

Usando instruções console.log

Ao executar um aplicativo compilado, essas instruções podem causar um grande gargalo na thread JavaScript. Isso inclui chamadas de bibliotecas de depuração, como redux-logger, portanto, certifique-se de removê-las antes de compilar. Você também pode usar este plugin babel que remove todas as chamadas console.*. Você precisa instalá-lo primeiro com npm i babel-plugin-transform-remove-console --save-dev e, em seguida, editar o arquivo .babelrc no diretório do projeto assim:

json
{
+  "env": {
+    "production": {
+      "plugins": ["transform-remove-console"]
+    }
+  }
+}

Isso removerá automaticamente todas as chamadas console.* nas versões de lançamento (produção) do seu projeto.

É recomendado usar o plugin mesmo que nenhuma chamada console.* seja feita em seu projeto. Uma biblioteca terceirizada também poderia ligar para eles.

A renderização inicial do ListView é muito lenta ou o desempenho da rolagem é ruim para listas grandes

Use o novo componente FlatList ou SectionList. Além de simplificar a API, os novos componentes da lista também apresentam melhorias significativas de desempenho, sendo a principal delas o uso quase constante de memória para qualquer número de linhas.

Se sua FlatList estiver com renderização lenta, certifique-se de ter implementado getItemLayout para otimizar a velocidade de renderização, ignorando a medição dos itens renderizados.

JS FPS despenca ao renderizar novamente uma visualização que quase não muda

Se você estiver usando um ListView, deverá fornecer uma função rowHasChanged que pode reduzir muito trabalho, determinando rapidamente se uma linha precisa ou não ser renderizada novamente. Se você estiver usando estruturas de dados imutáveis, isso só precisará ser uma verificação de igualdade de referência.

Da mesma forma, você pode implementar shouldComponentUpdate e indicar as condições exatas sob as quais gostaria que o componente fosse renderizado novamente. Se você escrever componentes puros (onde o valor de retorno da função de renderização depende inteiramente de adereços e estado), poderá aproveitar o PureComponent para fazer isso para você. Mais uma vez, estruturas de dados imutáveis são úteis para manter isso rápido - se você tiver que fazer uma comparação profunda de uma grande lista de objetos, pode ser que a re-renderização de todo o seu componente seja mais rápida e certamente exigiria menos código.

Descartando o FPS do thread JS por causa de muito trabalho no thread JavaScript ao mesmo tempo

As “transições lentas do Navigator” são a manifestação mais comum disso, mas há outras ocasiões em que isso pode acontecer. Usar o InteractionManager pode ser uma boa abordagem, mas se o custo da experiência do usuário for muito alto para atrasar o trabalho durante uma animação, você pode considerar o LayoutAnimation.

A API Animated atualmente calcula cada quadro-chave sob demanda no thread JavaScript, a menos que você defina useNativeDriver: true, enquanto LayoutAnimation aproveita o Core Animation e não é afetado por thread JS e quedas de quadro de thread principal.

Um caso em que usei isso foi para animar em um modal (deslizando de cima para baixo e desaparecendo em uma sobreposição translúcida) enquanto inicializo e talvez receba respostas para várias solicitações de rede, renderizando o conteúdo do modal e atualizando a visualização onde o modal foi aberto. Consulte o guia Animações para obter mais informações sobre como usar o LayoutAnimation.

Ressalvas:

  • LayoutAnimation funciona apenas para animações do tipo "dispare e esqueça" (animações "estáticas") - se for interrompível, você precisará usar o Animated.

Mover uma visualização na tela (rolar, traduzir, girar) elimina o FPS do thread da UI

Isso é especialmente verdadeiro quando você tem texto com fundo transparente posicionado no topo de uma imagem ou qualquer outra situação em que a composição alfa seja necessária para redesenhar a visualização em cada quadro. Você descobrirá que ativar o shouldRasterizeIOS ou o renderToHardwareTextureAndroid pode ajudar significativamente nisso.

Tenha cuidado para não abusar disso ou o uso de memória pode disparar. Analise seu desempenho e uso de memória ao usar esses acessórios. Se você não planeja mais mover uma visualização, desative essa propriedade.

Animar o tamanho de uma imagem reduz o FPS do thread da interface do usuário

No iOS, cada vez que você ajusta a largura ou a altura de um componente de imagem, ele é recortado e dimensionado a partir da imagem original. Isto pode ser muito caro, especialmente para imagens grandes. Em vez disso, use a propriedade de estilo transform: [{scale}] para animar o tamanho. Um exemplo de quando você pode fazer isso é tocar em uma imagem e aumentá-la para tela inteira.

Minha visualização TouchableX não responde muito bem

Às vezes, se fizermos uma ação no mesmo quadro em que estamos ajustando a opacidade ou realce de um componente que está respondendo a um toque, não veremos esse efeito até que a função onPress retorne. Se onPress fizer um setState que resulte em muito trabalho e alguns quadros perdidos, isso poderá ocorrer. Uma solução para isso é agrupar qualquer ação dentro do seu manipulador onPress em requestAnimationFrame:

js
handleOnPress() {
+  requestAnimationFrame(() => {
+    this.doExpensiveAction();
+  });
+}

Transições lentas do navegador

Conforme mencionado acima, as animações do Navigator são controladas pelo thread JavaScript. Imagine a transição de cena "empurrar da direita": a cada quadro, a nova cena é movida da direita para a esquerda, começando fora da tela (digamos em um deslocamento x de 320) e finalmente se estabelecendo quando a cena fica em um deslocamento x de 0. Cada quadro durante esta transição, o thread JavaScript precisa enviar um novo deslocamento x para o thread principal. Se o thread JavaScript estiver bloqueado, ele não poderá fazer isso e, portanto, nenhuma atualização ocorrerá naquele quadro e a animação falhará.

Uma solução para isso é permitir que animações baseadas em JavaScript sejam descarregadas para o thread principal. Se fizéssemos a mesma coisa que no exemplo acima com esta abordagem, poderíamos calcular uma lista de todos os deslocamentos x para a nova cena quando iniciamos a transição e enviá-los para o thread principal para executar de forma otimizada . Agora que o thread JavaScript está livre dessa responsabilidade, não será um grande problema se ele perder alguns quadros durante a renderização da cena - você provavelmente nem notará porque ficará muito distraído com a bela transição.

Resolver isso é um dos principais objetivos da nova biblioteca React Navigation. As visualizações no React Navigation usam componentes nativos e a biblioteca Animated para fornecer animações de 60 FPS que são executadas no thread nativo.

+ + + + \ No newline at end of file diff --git a/vitepress/docs/.vitepress/dist/docs/platform-specific-code.html b/vitepress/docs/.vitepress/dist/docs/platform-specific-code.html new file mode 100644 index 0000000..3bfa672 --- /dev/null +++ b/vitepress/docs/.vitepress/dist/docs/platform-specific-code.html @@ -0,0 +1,70 @@ + + + + + + Código específico da plataforma | React Native 0.72 + + + + + + + + + + + + + + + + +
Skip to content

Código específico da plataforma

Ao criar um aplicativo multiplataforma, você desejará reutilizar o máximo de código possível. Podem surgir cenários em que faça sentido que o código seja diferente, por exemplo, você pode querer implementar componentes visuais separados para Android e iOS.

React Native oferece duas maneiras de organizar seu código e separá-lo por plataforma:

  1. Usando o módulo Platform.
  2. Usando extensões de arquivo específicas da plataforma.

Certos componentes podem ter propriedades que funcionam apenas em uma plataforma. Todos esses props são anotados com @platform e possuem um pequeno emblema próximo a eles no site.

Módulo de plataforma

React Native fornece um módulo que detecta a plataforma na qual o aplicativo está sendo executado. Você pode usar a lógica de detecção para implementar código específico da plataforma. Use esta opção quando apenas pequenas partes de um componente forem específicas da plataforma.

jsx
import {Platform, StyleSheet} from 'react-native';
+
+const styles = StyleSheet.create({
+  height: Platform.OS === 'ios' ? 200 : 100,
+});

Platform.OS será ios quando executado em iOS e Android quando executado em Android.

Há também um método Platform.select disponível, que fornece um objeto onde as chaves podem ser 'ios' | 'android' | 'native' | 'default', retorna o valor mais adequado para a plataforma em que você está executando atualmente. Ou seja, se você estiver rodando em um celular, as teclas iOS e Android terão preferência. Se não forem especificadas, a chave nativa será usada e depois a chave padrão.

jsx
import {Platform, StyleSheet} from 'react-native';
+
+const styles = StyleSheet.create({
+  container: {
+    flex: 1,
+    ...Platform.select({
+      ios: {
+        backgroundColor: 'red',
+      },
+      android: {
+        backgroundColor: 'green',
+      },
+      default: {
+        // outras plataformas, web por exemplo
+        backgroundColor: 'blue',
+      },
+    }),
+  },
+});

Isso resultará em um contêiner com flex: 1 em todas as plataformas, uma cor de fundo vermelha no iOS, uma cor de fundo verde no Android e uma cor de fundo azul em outras plataformas.

Como aceita qualquer valor, você também pode usá-lo para retornar componentes específicos da plataforma, como abaixo:

jsx
const Component = Platform.select({
+  ios: () => require('ComponentIOS'),
+  android: () => require('ComponentAndroid'),
+})();
+
+<Component />;
jsx
const Component = Platform.select({
+  native: () => require('ComponentForNative'),
+  default: () => require('ComponentForWeb'),
+})();
+
+<Component />;

Detectando a versão do Android

No Android, o módulo Platform também pode ser usado para detectar a versão da plataforma Android na qual o aplicativo está sendo executado:

jsx
import {Platform} from 'react-native';
+
+if (Platform.Version === 25) {
+  console.log('Running on Nougat!');
+}

Observação

A Version é definida como a versão da API do Android e não como a versão do sistema operacional Android. Para encontrar um mapeamento, consulte o Histórico de versões do Android.

Detectando a versão do iOS

No iOS, a Version é resultado de -[UIDevice systemVersion], que é uma string com a versão atual do sistema operacional. Um exemplo de versão do sistema é "10.3". Por exemplo, para detectar o número da versão principal no iOS:

jsx
import {Platform} from 'react-native';
+
+const majorVersionIOS = parseInt(Platform.Version, 10);
+if (majorVersionIOS <= 9) {
+  console.log('Work around a change in behavior');
+}

Extensões específicas da plataforma

Quando o código específico da plataforma for mais complexo, considere dividir o código em arquivos separados. O React Native detectará quando um arquivo tiver uma extensão .ios. ou .android. e carregará o arquivo de plataforma relevante quando necessário de outros componentes.

Por exemplo, digamos que você tenha os seguintes arquivos em seu projeto:

BigButton.ios.js
+BigButton.android.js

Você pode então importar o componente da seguinte maneira:

jsx
import BigButton from './BigButton';

O React Native selecionará automaticamente o arquivo correto com base na plataforma em execução.

Extensões específicas nativas (ou seja, compartilhamento de código com NodeJS e Web)

Você também pode usar a extensão .native.js quando um módulo precisa ser compartilhado entre NodeJS/Web e React Native, mas não tem diferenças Android/iOS. Isso é especialmente útil para projetos que possuem código comum compartilhado entre React Native e ReactJS.

Por exemplo, digamos que você tenha os seguintes arquivos em seu projeto:

Container.js # obtido por webpack, Rollup ou qualquer outro empacotador da Web
+Container.native.js # obtido pelo empacotador React Native para Android e iOS (Metro)

Você ainda pode importá-lo sem a extensão .native, da seguinte maneira:

jsx
import Container from './Container';

Dica profissional

Configure seu web bundler para ignorar extensões .native.js para evitar código não utilizado em seu pacote de produção, reduzindo assim o tamanho final do pacote.

+ + + + \ No newline at end of file diff --git a/vitepress/docs/.vitepress/dist/docs/profile-hermes.html b/vitepress/docs/.vitepress/dist/docs/profile-hermes.html new file mode 100644 index 0000000..c534302 --- /dev/null +++ b/vitepress/docs/.vitepress/dist/docs/profile-hermes.html @@ -0,0 +1,54 @@ + + + + + + Perfil com Hermes | React Native 0.72 + + + + + + + + + + + + + + + + +
Skip to content

Perfil com Hermes

Você pode visualizar o desempenho do JavaScript em um aplicativo React Native usando Hermes. Hermes é um mecanismo JavaScript pequeno e leve otimizado para executar React Native (você pode ler mais sobre como usá-lo com React Native aqui). Hermes ajuda a melhorar o desempenho do aplicativo e também expõe maneiras de analisar o desempenho do JavaScript que ele executa.

Nesta seção, você aprenderá como criar o perfil de seu aplicativo React Native em execução no Hermes e como visualizar o perfil usando a guia Desempenho no Chrome DevTools

CUIDADO Certifique-se de ativar o Hermes em seu aplicativo antes de começar!

Siga as instruções abaixo para começar a criar o perfil:

  • Grave um perfil de amostragem Hermes
  • Execute o comando da CLI
  • Abra o perfil baixado no Chrome DevTools

Grave um perfil de amostragem Hermes

Para gravar um perfil de amostragem no menu Dev:

  1. Navegue até o terminal do servidor Metro em execução.
  2. Pressione d para abrir o menu Dev.
  3. Selecione Enable Sampling Profiler.
  4. Execute seu JavaScript em seu aplicativo (pressione botões, etc.)
  5. Abra o menu Dev pressionando d novamente.
  6. Selecione Disable Sampling Profiler para interromper a gravação e salvar o sampler profiler.

Um toast mostrará o local onde o criador de perfil de amostragem foi salvo, geralmente em /data/user/0/com.appName/cache/*.cpuprofile

image

Execute o comando da CLI

Você pode usar a CLI do React Native para converter o perfil de rastreamento Hermes em perfil de rastreamento do Chrome e, em seguida, enviá-lo para sua máquina local usando:

npx react-native profile-hermes [diretorioDestino]

Habilitando mapa de origem

INFORMAÇÕES Você pode ler sobre mapas de origem na página de mapas de origem.

Erros comuns

adb: no devices/emulators found ou adb: device offline

  • Por que isso acontece: A CLI não pode acessar o dispositivo ou emulador (por meio do adb) que você está usando para executar o aplicativo.
  • Como corrigir: Certifique-se de que seu dispositivo/emulador Android esteja conectado e funcionando. O comando só funciona quando pode acessar o adb.

There is no file in the cache/ directory

  • Por que isso acontece: A CLI não consegue encontrar nenhum arquivo .cpuprofile no diretório cache/ do seu aplicativo. Você pode ter esquecido de gravar um perfil do dispositivo.
  • Como corrigir: Siga as instruções para ativar/desativar o criador de perfil do dispositivo.

Erro: your_profile_name.cpuprofile é um arquivo vazio

  • Por que isso acontece: O perfil está vazio, pode ser porque o Hermes não está funcionando corretamente.
  • Como corrigir: Certifique-se de que seu aplicativo esteja rodando na versão mais recente do Hermes.

Abra o perfil baixado no Chrome DevTools

Para abrir o perfil no Chrome DevTools:

  1. Abra o Chrome DevTools.
  2. Selecione a guia Performance.
  3. Clique com o botão direito e escolha Carregar perfil...

image

Como funciona o transformador de perfil Hermes?

O Hermes Sample Profile tem o formato de objeto JSON, enquanto o formato suportado pelo DevTools do Google é JSON Array Format. (Mais informações sobre os formatos podem ser encontradas no documento Trace Event Format)

js
export interface HermesCPUProfile {
+  traceEvents: SharedEventProperties[];
+  samples: HermesSample[];
+  stackFrames: {[key in string]: HermesStackFrame};
+}

O perfil Hermes tem a maior parte de suas informações codificadas nas amostras (samples) e nas propriedades stackFrames. Cada amostra é um instantâneo da pilha de chamadas de função naquele carimbo de data/hora específico, pois cada amostra possui uma propriedade sf que corresponde a uma chamada de função.

js
export interface HermesSample {
+  cpu: string;
+  name: string;
+  ts: string;
+  pid: number;
+  tid: string;
+  weight: string;
+  /**
+   * Irá se referir a um elemento no objeto stackFrames do Perfil Hermes
+   */
+  sf: number;
+  stackFrameData?: HermesStackFrame;
+}

As informações sobre uma chamada de função podem ser encontradas em stackFrames que contém pares chave-objeto, onde a chave é o número sf e o objeto correspondente nos fornece todas as informações relevantes sobre a função, incluindo o número sf de sua função pai. Esse relacionamento pai-filho pode ser rastreado para cima para encontrar as informações de todas as funções em execução em um carimbo de data/hora específico.

js
export interface HermesStackFrame {
+  line: string;
+  column: string;
+  funcLine: string;
+  funcColumn: string;
+  name: string;
+  category: string;
+  /**
+   * Uma função pai pode ou não existir
+   */
+  parent?: number;
+}

Neste ponto, você deve definir mais alguns termos, a saber:

  1. Nós: os objetos correspondentes aos números sf em stackFrames
  2. Nós ativos: os nós que estão atualmente em execução em um carimbo de data/hora específico. Um nó é classificado como em execução se seu número sf estiver na pilha de chamadas de função. Esta pilha de chamadas pode ser obtida a partir do número sf da amostra e rastreada para cima até que os sfs pai estejam disponíveis

As amostras e os stackFrames em conjunto podem então ser usados para gerar todos os eventos de início e término nos carimbos de data/hora correspondentes, em que:

  1. Nós/Eventos iniciais: nós ausentes na pilha de chamadas de função da amostra anterior, mas presentes na amostra atual.
  2. Nós finais/eventos: nós presentes na pilha de chamadas de função da amostra anterior, mas ausentes na amostra atual.

image

Agora você pode construir um flamechart de chamadas de função, pois possui todas as informações da função, incluindo seus carimbos de data e hora de início e término.

O hermes-profile-transformer pode converter qualquer perfil gerado usando Hermes em um formato que pode ser exibido diretamente no Chrome DevTools. Mais informações sobre isso podem ser encontradas em @react-native-community/hermes-profile-transformer.

+ + + + \ No newline at end of file diff --git a/vitepress/docs/.vitepress/dist/docs/profiling.html b/vitepress/docs/.vitepress/dist/docs/profiling.html new file mode 100644 index 0000000..5f6f609 --- /dev/null +++ b/vitepress/docs/.vitepress/dist/docs/profiling.html @@ -0,0 +1,27 @@ + + + + + + Perfil | React Native 0.72 + + + + + + + + + + + + + + + + +
Skip to content

Perfil

Use o criador de perfil integrado para obter informações detalhadas sobre o trabalho realizado no thread JavaScript e no thread principal lado a lado. Acesse-o selecionando "Perf Monitor" no menu Debug.

Para iOS, Instruments é uma ferramenta inestimável, e no Android você deve aprender a usar o systrace.

Mas primeiro, certifique-se de que o Modo de Desenvolvimento esteja DESLIGADO! Você deverá ver __DEV__ === false, o aviso em nível de desenvolvimento está DESATIVADO e as otimizações de desempenho estão ATIVADAS nos logs do seu aplicativo.

Outra maneira de criar o perfil do JavaScript é usar o criador de perfil do Chrome durante a depuração. Isso não fornecerá resultados precisos, pois o código está sendo executado no Chrome, mas fornecerá uma ideia geral de onde podem estar os gargalos. Execute o criador de perfil na guia Desempenho do Chrome. Um gráfico em degradê aparecerá em User Timing. Para ver mais detalhes em formato tabular, clique na guia Bottom Up abaixo e selecione DedicatedWorker Thread no menu superior esquerdo.

Criação de perfil de desempenho da interface do Android com systrace

O Android suporta mais de 10 mil telefones diferentes e é generalizado para suportar renderização de software: a arquitetura da estrutura e a necessidade de generalizar para muitos alvos de hardware, infelizmente significam que você recebe menos de graça, em relação ao iOS. Mas às vezes há coisas que você pode melhorar - e muitas vezes não é culpa do código nativo!

O primeiro passo para depurar essa instabilidade é responder à questão fundamental de onde seu tempo está sendo gasto durante cada quadro de 16 ms. Para isso, usaremos uma ferramenta padrão de criação de perfil do Android chamada systrace.

systrace é uma ferramenta de criação de perfil padrão baseada em marcadores do Android (e é instalada quando você instala o pacote de ferramentas da plataforma Android). Os blocos de código perfilados são cercados por marcadores de início/fim que são visualizados em um formato de gráfico colorido. Tanto o Android SDK quanto a estrutura React Native fornecem marcadores padrão que você pode visualizar.

1. Coletando um rastro

Primeiro, conecte um dispositivo que exiba as telas que você deseja investigar ao seu computador via USB e leve-o ao ponto logo antes da navegação/animação que você deseja criar o perfil. Execute o systrace da seguinte maneira:

$ <path_to_android_sdk>/platform-tools/systrace/systrace.py --time=10 -o trace.html sched gfx view -a <your_package_name>

Uma análise rápida deste comando:

  • time é o período de tempo que o rastreamento será coletado em segundos
  • sched, gfx e view são as tags Android SDK (coleções de marcadores) com as quais nos preocupamos: sched fornece informações sobre o que está sendo executado em cada núcleo do seu telefone, gfx fornece informações gráficas, como limites de quadros, e view fornece informações sobre medir, fazer o layout e desenhar passes
  • -a <your_package_name> habilita marcadores específicos do aplicativo, especificamente aqueles integrados à estrutura React Native. your_package_name pode ser encontrado no AndroidManifest.xml do seu aplicativo e se parece com com.example.app

Assim que o rastreamento começar a ser coletado, execute a animação ou interação de seu interesse. No final do rastreamento, o systrace fornecerá um link para o rastreamento que você pode abrir em seu navegador.

2. Lendo o rastreamento

Depois de abrir o rastreamento em seu navegador (de preferência Chrome), você deverá ver algo assim:

image

DICA Use as teclas WASD para guiar e ampliar.

Se o arquivo .html de rastreamento não estiver abrindo corretamente, verifique o seguinte no console do navegador:

image

Como Object.observe foi descontinuado em navegadores recentes, pode ser necessário abrir o arquivo na ferramenta de rastreamento do Google Chrome. Você pode fazer isso:

  • Aba de abertura no chrome chrome://tracing
  • Selecionando load
  • Selecionando o arquivo html gerado a partir do comando anterior.

ATIVAR HIGHLIGHT VSYNC Marque esta caixa de seleção no canto superior direito da tela para destacar os limites do quadro de 16ms: image

Você deverá ver listras de zebra como na imagem acima. Caso contrário, tente criar um perfil em um dispositivo diferente: sabe-se que a Samsung tem problemas para exibir vsyncs, enquanto a série Nexus é geralmente bastante confiável.

3. Encontre o seu processo

Role até ver (parte do) nome do seu pacote. Nesse caso, eu estava criando o perfil de com.facebook.adsmanager, que aparece como book.adsmanager por causa de limites bobos de nomes de threads no kernel.

No lado esquerdo, você verá um conjunto de tópicos que correspondem às linhas da linha do tempo à direita. Existem alguns threads com os quais nos preocupamos para nossos propósitos: o thread de UI (que tem o nome do seu pacote ou o nome Thread de UI), mqt_js e mqt_native_modules. Se você estiver executando o Android 5+, também nos preocupamos com o Render Thread.

  • UI Thread. É aqui que acontece a medida/layout/desenho padrão do Android. O nome do tópico à direita será o nome do seu pacote (no meu caso book.adsmanager) ou UI Thread. Os eventos que você vê neste tópico devem ser parecidos com isto e têm a ver com Choreographer, traversals e DispatchUI: image

  • JS Thread. É aqui que o JavaScript é executado. O nome do thread será mqt_js ou <...> dependendo de quão cooperativo o kernel do seu dispositivo está sendo. Para identificá-lo caso não tenha nome, procure coisas como JSCall, Bridge.executeJSCall, etc: image

  • Native Modules Thread. É aqui que as chamadas do módulo nativo (por exemplo, o UIManager) são executadas. O nome do encadeamento será mqt_native_modules ou <...>. Para identificá-lo neste último caso, procure coisas como NativeCall, callJavaModuleMethod e onBatchComplete: image

  • Bônus: Thread Render. Se estiver usando Android L (5.0) e superior, você também terá uma thread de renderização em seu aplicativo. Esta thread gera os comandos OpenGL reais usados para desenhar sua UI. O nome do thread será RenderThread ou <...>. Para identificá-lo neste último caso, procure coisas como DrawFrame e queueBuffer:

image

Identificando um culpado

Uma animação suave deve ser semelhante a esta:

image

Cada mudança de cor é um quadro – lembre-se que para exibir um quadro, todo o nosso trabalho de UI precisa ser feito até o final desse período de 16 ms. Observe que nenhuma thread está funcionando próximo ao limite do quadro. Uma renderização de aplicativo como essa é renderizada a 60 FPS.

Se você notou um corte, no entanto, poderá ver algo assim:

image

Observe que o thread JS está em execução quase o tempo todo e além dos limites do quadro! Este aplicativo não está renderizando a 60 FPS. Neste caso, o problema está em JS.

Você também pode ver algo assim:

image

Nesse caso, a interface do usuário e as threads de renderização são os que têm trabalho cruzando os limites do quadro. A UI que estamos tentando renderizar em cada quadro está exigindo muito trabalho. Nesse caso, o problema está na renderização das visualizações nativas.

Neste ponto, você terá algumas informações muito úteis para orientar suas próximas etapas.

Resolvendo problemas de JavaScript

Se você identificou um problema de JS, procure pistas no JS específico que está executando. No cenário acima, vemos RCTEventEmitter sendo chamado várias vezes por quadro. Aqui está um zoom do thread JS do rastreamento acima:

image

Isso não parece certo. Por que está sendo chamado com tanta frequência? São realmente eventos diferentes? As respostas a essas perguntas provavelmente dependerão do código do seu produto. E muitas vezes, você vai querer dar uma olhada em shouldComponentUpdate.

Resolvendo problemas de UI nativa

Se você identificou um problema de UI nativa, geralmente há dois cenários:

  • a IU que você está tentando desenhar cada quadro envolve muito trabalho na GPU ou
  • Você está construindo uma nova UI durante a animação/interação (por exemplo, carregando um novo conteúdo durante uma rolagem).

Muito trabalho de GPU

No primeiro cenário, você verá um trace que tem o thread de UI e/ou Thread de Renderização parecido com este:

image

Observe a longa quantidade de tempo gasto no DrawFrame que ultrapassa os limites do quadro. Este é o tempo gasto esperando que a GPU drene seu buffer de comando do quadro anterior.

Para mitigar isso, você deve:

  • investigue usando renderToHardwareTextureAndroid para conteúdo estático e complexo que está sendo animado/transformado (por exemplo, animações de slide/alfa do Navigator)
  • certifique-se de não usar o NeedOffscreenAlphaCompositing, que está desabilitado por padrão, pois aumenta muito a carga por quadro na GPU na maioria dos casos.

Criando novas visualizações no thread da UI

No segundo cenário, você verá algo mais parecido com isto:

image

Observe que primeiro o thread JS pensa um pouco, depois você vê algum trabalho realizado no thread de módulos nativos, seguido por uma travessia cara no thread de UI.

Não há uma maneira rápida de atenuar isso, a menos que você consiga adiar a criação de uma nova IU até depois da interação ou simplifique a IU que está criando. A equipe do React Native está trabalhando em uma solução de nível de infraestrutura para isso que permitirá que novas UI sejam criadas e configuradas fora do thread principal, permitindo que a interação continue sem problemas.

+ + + + \ No newline at end of file diff --git a/vitepress/docs/.vitepress/dist/docs/publishing-to-app-store.html b/vitepress/docs/.vitepress/dist/docs/publishing-to-app-store.html new file mode 100644 index 0000000..b7a6280 --- /dev/null +++ b/vitepress/docs/.vitepress/dist/docs/publishing-to-app-store.html @@ -0,0 +1,32 @@ + + + + + + Publicação na Apple App Store | React Native 0.72 + + + + + + + + + + + + + + + + +
Skip to content

Publicação na Apple App Store

O processo de publicação é igual ao de qualquer outro aplicativo iOS nativo, com algumas considerações adicionais a serem levadas em consideração.

Informações

Se você estiver usando o Expo, leia o guia do Expo para Implantação nas App Stores para criar e enviar seu aplicativo para a Apple App Store. Este guia funciona com qualquer aplicativo React Native para automatizar o processo de implantação.

1. Configurar esquema de liberação

Construir um aplicativo para distribuição na App Store requer o uso do esquema Release no Xcode. Os aplicativos desenvolvidos para Release desativarão automaticamente o menu Dev no aplicativo, o que impedirá que seus usuários acessem inadvertidamente o menu em produção. Ele também agrupará o JavaScript localmente, para que você possa colocar o aplicativo em um dispositivo e testá-lo enquanto não estiver conectado ao computador.

Para configurar seu aplicativo para ser construído usando o esquema Release, vá para Product → Scheme → Edit Scheme. Selecione a guia Run na barra lateral e defina o menu suspenso Build Configuration como Release.

Dicas profissionais

À medida que o tamanho do seu App Bundle aumenta, você pode começar a ver uma tela em branco piscando entre a tela inicial e a exibição da visualização do aplicativo raiz. Se for esse o caso, você pode adicionar o seguinte código a AppDelegate.m para manter sua tela inicial exibida durante a transição.

objective-c
  // Coloque este código depois de "[self.window makeKeyAndVisible]" e antes de "return YES;"
+  UIStoryboard *sb = [UIStoryboard storyboardWithName:@"LaunchScreen" bundle:nil];
+  UIViewController *vc = [sb instantiateInitialViewController];
+  rootView.loadingView = vc.view;

O pacote estático é criado sempre que você direciona um dispositivo físico, mesmo na depuração. Se você quiser economizar tempo, desative a geração de pacotes no Debug adicionando o seguinte ao seu script de shell na fase de construção do Xcode Bundle React Native code and images:

bash
 if [ "${CONFIGURATION}" == "Debug" ]; then
+  export SKIP_BUNDLING=true
+ fi

2. Construir aplicativo para lançamento

Agora você pode criar seu aplicativo para lançamento tocando em Cmd ⌘ + B ou selecionando ProdutoConstruir na barra de menu. Depois de criado para lançamento, você poderá distribuir o aplicativo para testadores beta e enviá-lo para a App Store.

Informações

Você também pode usar o React Native CLI para realizar esta operação usando a opção --mode com o valor Release (por exemplo, da raiz do seu projeto: npm run ios -- --mode="Release" ou yarn ios --mode Release).

Quando terminar os testes e estiver pronto para publicar na App Store, siga este guia.

  • Inicie seu terminal, navegue até a pasta iOS do seu aplicativo e digite open ..
  • Clique duas vezes em YOUR_APP_NAME.xcworkspace. Deve iniciar o XCode.
  • Clique em ProdutoArquivo. Certifique-se de configurar o dispositivo para "Qualquer dispositivo iOS (arm64)".

Observação

Verifique seu identificador de pacote e certifique-se de que seja exatamente igual ao que você criou nos identificadores no Apple Developer Dashboard.

  • Após a conclusão do arquivo, na janela de arquivo, clique em Distribute App.
  • Clique em App Store Connect agora (se quiser publicar na App Store).
  • Clique em Upload → Certifique-se de que todas as caixas de seleção estejam marcadas, clique em Next.
  • Escolha entre Automatically manage signing e Manually manage signing com base em suas necessidades.
  • Clique em Upload.
  • Agora você pode encontrá-lo na App Store Connect em TestFlight.

Agora preencha as informações necessárias e na seção Build, selecione a build do aplicativo e clique em SaveSubmit For Review.

4. Capturas de tela

A Apple Store exige que você tenha capturas de tela dos dispositivos mais recentes. A referência para tais dispositivos pode ser encontrada aqui. Observe que as capturas de tela para alguns tamanhos de exibição não serão necessárias se forem fornecidas para outros tamanhos.

+ + + + \ No newline at end of file diff --git a/vitepress/docs/.vitepress/dist/docs/ram-bundles-inline-requires.html b/vitepress/docs/.vitepress/dist/docs/ram-bundles-inline-requires.html new file mode 100644 index 0000000..c22b8e6 --- /dev/null +++ b/vitepress/docs/.vitepress/dist/docs/ram-bundles-inline-requires.html @@ -0,0 +1,128 @@ + + + + + + Pacotes de RAM e require inline | React Native 0.72 + + + + + + + + + + + + + + + + +
Skip to content

Pacotes de RAM e require inline

Se você tiver um aplicativo grande, considere o formato do pacote Random Access Modules (RAM) e o uso de requisitos in-line. Isso é útil para aplicativos que possuem um grande número de telas que talvez nunca sejam abertas durante o uso normal do aplicativo. Geralmente é útil para aplicativos que possuem grandes quantidades de código que não são necessários por um tempo após a inicialização. Por exemplo, o aplicativo inclui telas de perfil complicadas ou recursos menos usados, mas a maioria das sessões envolve apenas a visita à tela principal do aplicativo para atualizações. Podemos otimizar o carregamento do pacote usando o formato RAM e exigindo esses recursos e telas inline (quando são realmente usados).

Carregando JavaScript

Antes que o react-native possa executar o código JS, esse código deve ser carregado na memória e analisado. Com um pacote padrão, se você carregar um pacote de 50 MB, todos os 50 MB deverão ser carregados e analisados antes que qualquer um deles possa ser executado. A otimização por trás dos pacotes de RAM é que você pode carregar apenas a parte dos 50 MB que realmente precisa na inicialização e carregar progressivamente mais do pacote conforme essas seções forem necessárias.

Require Inline

Inline exige atrasar a solicitação de um módulo ou arquivo até que esse arquivo seja realmente necessário. Um exemplo básico seria assim:

jsx
// VeryExpensive.tsx
+
+import React, {Component} from 'react';
+import {Text} from 'react-native';
+// ... importe alguns módulos muito grande
+
+// Você pode querer registrar no nível do arquivo para verificar quando isso está acontecendo
+console.log('VeryExpensive component loaded');
+
+export default class VeryExpensive extends Component {
+  // muito e muito código
+  render() {
+    return <Text>Very Expensive Component</Text>;
+  }
+}
jsx
// Optimized.tsx
+
+import React, {Component} from 'react';
+import {TouchableOpacity, View, Text} from 'react-native';
+
+let VeryExpensive = null;
+
+export default class Optimized extends Component {
+  state = {needsExpensive: false};
+
+  didPress = () => {
+    if (VeryExpensive == null) {
+      VeryExpensive = require('./VeryExpensive').default;
+    }
+
+    this.setState(() => ({
+      needsExpensive: true,
+    }));
+  };
+
+  render() {
+    return (
+      <View style={{marginTop: 20}}>
+        <TouchableOpacity onPress={this.didPress}>
+          <Text>Load</Text>
+        </TouchableOpacity>
+        {this.state.needsExpensive ? <VeryExpensive /> : null}
+      </View>
+    );
+  }
+}

Mesmo sem o formato RAM, as solicitações in-line podem levar a melhorias no tempo de inicialização, porque o código dentro do VeryExpensive.js só será executado quando for necessário pela primeira vez.

Habilite o formato RAM

No iOS, usar o formato RAM criará um único arquivo indexado que reagirá nativamente e carregará um módulo por vez. No Android, por padrão, será criado um conjunto de arquivos para cada módulo. Você pode forçar o Android a criar um único arquivo, como o iOS, mas usar vários arquivos pode ter melhor desempenho e requer menos memória.

Habilite o formato RAM no Xcode editando a fase de construção "Bundle React Native code and images". Antes de ../node_modules/react-native/scripts/react-native-xcode.sh adicione export BUNDLE_COMMAND="ram-bundle":

sh
export BUNDLE_COMMAND="ram-bundle"
+export NODE_BINARY=node
+../node_modules/react-native/scripts/react-native-xcode.sh

No Android, habilite o formato RAM editando seu arquivo android/app/build.gradle. Antes da linha apply from: "../../node_modules/react-native/react.gradle" adicione ou altere o bloco project.ext.react:

project.ext.react = [
+  bundleCommand: "ram-bundle",
+]

Use as seguintes linhas no Android se quiser usar um único arquivo indexado:

projeto.ext.react = [
+   bundleCommand: "ram-bundle",
+   extraPackagerArgs: ["--indexed-ram-bundle"]
+]

INFORMAÇÕES Se você estiver usando o Hermes JS Engine, não deverá ter o recurso de pacotes de RAM ativado. No Hermes, ao carregar o bytecode, o mmap garante que o arquivo inteiro não seja carregado. Usar Hermes com pacotes de RAM pode causar problemas, porque esses mecanismos não são compatíveis entre si.

Configurar pré-carregamento e requisitos embutidos

Agora que temos um pacote de RAM, há sobrecarga para chamar require. require agora precisa enviar uma mensagem pela ponte quando encontrar um módulo que ainda não foi carregado. Isso terá maior impacto na inicialização, porque é onde o maior número de chamadas require provavelmente ocorrerá enquanto o aplicativo carrega o módulo inicial. Felizmente podemos configurar uma parte dos módulos para serem pré-carregados. Para fazer isso, você precisará implementar alguma forma de importação in-line.

Investigando os Módulos Carregados

No seu arquivo raiz (index.(ios|android).js) você pode adicionar o seguinte após as importações iniciais:

js
const modules = require.getModules();
+const moduleIds = Object.keys(modules);
+const loadedModuleNames = moduleIds
+  .filter(moduleId => modules[moduleId].isInitialized)
+  .map(moduleId => modules[moduleId].verboseName);
+const waitingModuleNames = moduleIds
+  .filter(moduleId => !modules[moduleId].isInitialized)
+  .map(moduleId => modules[moduleId].verboseName);
+
+// certifique-se de que os módulos que você espera estarem aguardando, estão realmente esperando
+console.log(
+  'loaded:',
+  loadedModuleNames.length,
+  'waiting:',
+  waitingModuleNames.length,
+);
+
+// pegue este blob de texto e coloque-o em um arquivo chamado packager/modulePaths.js
+console.log(
+  `module.exports = ${JSON.stringify(
+    loadedModuleNames.sort(),
+    null,
+    2,
+  )};`,
+);

Ao executar seu aplicativo, você pode olhar no console e ver quantos módulos foram carregados e quantos estão aguardando. Você pode querer ler os moduleNames e ver se há alguma surpresa. Observe que os requisitos inline são invocados na primeira vez que as importações são referenciadas. Talvez seja necessário investigar e refatorar para garantir que apenas os módulos desejados sejam carregados na inicialização. Observe que você pode alterar o objeto Systrace em require para ajudar a depurar requisitos problemáticos.

js
require.Systrace.beginEvent = message => {
+  if (message.includes(problematicModule)) {
+    throw new Error();
+  }
+};

Cada aplicativo é diferente, mas pode fazer sentido carregar apenas os módulos necessários para a primeira tela. Quando estiver satisfeito, coloque a saída de loadModuleNames em um arquivo chamado packager/modulePaths.js.

Atualizando metro.config.js

Agora precisamos atualizar metro.config.js na raiz do projeto para usar nosso arquivo modulePaths.js recém-gerado:

js
const {getDefaultConfig, mergeConfig} = require('@react-native/metro-config');
+const fs = require('fs');
+const path = require('path');
+const modulePaths = require('./packager/modulePaths');
+
+const config = {
+  transformer: {
+    getTransformOptions: () => {
+      const moduleMap = {};
+      modulePaths.forEach(modulePath => {
+        if (fs.existsSync(modulePath)) {
+          moduleMap[path.resolve(modulePath)] = true;
+        }
+      });
+      return {
+        preloadedModules: moduleMap,
+        transform: {inlineRequires: {blockList: moduleMap}},
+      };
+    },
+  },
+};
+
+module.exports = mergeConfig(getDefaultConfig(__dirname), config);

Consulte também Configurando o Metro.

A entrada preloadedModules na configuração indica quais módulos devem ser marcados como pré-carregados ao construir um pacote de RAM. Quando o pacote é carregado, esses módulos são carregados imediatamente, antes mesmo de qualquer requerimento ser executado. A entrada blockList indica que esses módulos não devem ser necessários em linha. Como eles são pré-carregados, não há benefício de desempenho no uso de um require in-line. Na verdade, o JavaScript gerado gasta mais tempo resolvendo a necessidade inline toda vez que as importações são referenciadas.

Teste e meça melhorias

Agora você deve estar pronto para criar seu aplicativo usando o formato RAM e os requisitos embutidos. Certifique-se de medir os tempos de inicialização antes e depois.

+ + + + \ No newline at end of file diff --git a/vitepress/docs/.vitepress/dist/docs/react-devtools.html b/vitepress/docs/.vitepress/dist/docs/react-devtools.html new file mode 100644 index 0000000..e0d4c70 --- /dev/null +++ b/vitepress/docs/.vitepress/dist/docs/react-devtools.html @@ -0,0 +1,27 @@ + + + + + + Ferramentas de desenvolvedor React | React Native 0.72 + + + + + + + + + + + + + + + + +
Skip to content

Ferramentas de desenvolvedor React

Você pode usar a versão autônoma do React Developer Tools para depurar a hierarquia de componentes do React. Para usá-lo, instale o pacote react-devtools globalmente:

bash
npm install -g react-devtools
bash
yarn global add react-devtools

Agora execute react-devtools no terminal para iniciar o aplicativo DevTools independente. Ele deve se conectar ao seu simulador em alguns segundos.

bash
react-devtools

image

Informações

Se preferir evitar instalações globais, você pode adicionar react-devtools como uma dependência do projeto. Adicione o pacote react-devtools ao seu projeto usando npm install --save-dev react-devtools e, em seguida, adicione "react-devtools": "react-devtools" à seção de scripts em seu package.json e execute npm run react-devtools da pasta do seu projeto para abrir o DevTools.

Integração com React Native Inspector

Abra o menu Dev e escolha "Toggle Inspector". Isso abrirá uma sobreposição que permite tocar em qualquer elemento da interface do usuário e ver informações sobre ele:

image

No entanto, quando o react-devtools estiver em execução, o Inspector entrará em um modo recolhido e, em vez disso, usará o DevTools como UI principal. Neste modo, clicar em algo no simulador exibirá os componentes relevantes no DevTools:

Você pode escolher "Toggle Inspector" no mesmo menu para sair deste modo.

Depurando o estado do aplicativo

Reactotron é um aplicativo de desktop de código aberto que permite inspecionar o estado do aplicativo Redux ou MobX-State-Tree, bem como visualizar logs personalizados, executar comandos personalizados, como redefinir estado, armazenar e restaurar instantâneos de estado e outros recursos úteis de depuração para React Aplicativos nativos.

Você pode ver as instruções de instalação no README. Se você estiver usando o Expo, aqui está um artigo detalhando como instalar no Expo.

Solução de problemas

Dica

Depois de executar o React DevTools, siga as instruções. Se seu aplicativo estava em execução antes de abrir o React DevTools, pode ser necessário abrir o menu do desenvolvedor para conectá-los.

image

INFORMAÇÕES

Se a conexão com o emulador for problemática (especialmente Android 12), tente executar adb reverse tcp:8097 tcp:8097 em um novo terminal.

+ + + + \ No newline at end of file diff --git a/vitepress/docs/.vitepress/dist/docs/react-native-gradle-plugin.html b/vitepress/docs/.vitepress/dist/docs/react-native-gradle-plugin.html new file mode 100644 index 0000000..c1c42ff --- /dev/null +++ b/vitepress/docs/.vitepress/dist/docs/react-native-gradle-plugin.html @@ -0,0 +1,39 @@ + + + + + + Plug-in React Native Gradle | React Native 0.72 + + + + + + + + + + + + + + + + +
Skip to content

Plug-in React Native Gradle

Este guia descreve como configurar o Plugin React Native Gradle (geralmente chamado de RNGP) ao criar seu aplicativo React Native para Android.

Usando o plugin

O plugin React Native Gradle é distribuído como um pacote NPM separado que é instalado automaticamente com react-native.

O plugin já está configurado para novos projetos criados usando npx react-native init. Você não precisa realizar nenhuma etapa extra para instalá-lo se tiver criado seu aplicativo com este comando.

Se você estiver integrando o React Native em um projeto existente, consulte a página correspondente: ela contém instruções específicas sobre como instalar o plugin.

Configurando o plugin

Por padrão, o plugin funcionará pronto para uso com padrões razoáveis. Você deve consultar este guia e personalizar o comportamento somente se precisar.

Para configurar o plugin você pode modificar o bloco react, dentro do seu android/app/build.gradle:

groovy
apply plugin: "com.facebook.react"
+
+/**
+ * Este é o bloco de configuração para personalizar seu aplicativo React Native Android.
+ * Por padrão você não precisa aplicar nenhuma configuração, apenas descomente as linhas necessárias.
+ */
+react {
+  // A configuração personalizada vai aqui.
+}

Cada chave de configuração é descrita abaixo:

root

Esta é a pasta raiz do seu projeto React Native, ou seja, onde reside o arquivo package.json. O padrão é ... Você pode personalizá-lo da seguinte maneira:

groovy
root = file("../")

reactNativeDir

Esta é a pasta onde reside o pacote react-native. O padrão é ../node_modules/react-native. Se você estiver em um monorepo ou usando um gerenciador de pacotes diferente, você pode usar o ajuste reactNativeDir para sua configuração.

Você pode personalizá-lo da seguinte maneira:

groovy
reactNativeDir = file("../node_modules/react-native")

codegenDir

Esta é a pasta onde reside o pacote react-native-codegen. O padrão é ../node_modules/react-native-codegen. Se você estiver em um monorepo ou usando um gerenciador de pacotes diferente, você pode ajustar codegenDir à sua configuração.

Você pode personalizá-lo da seguinte maneira:

groovy
codegenDir = file("../node_modules/@react-native/codegen")

cliFile

Este é o arquivo de ponto de entrada para o React Native CLI. O padrão é ../node_modules/react-native/cli.js. O arquivo do ponto de entrada é necessário porque o plug-in precisa invocar a CLI para agrupar e criar seu aplicativo.

Se você estiver em um monorepo ou usando um gerenciador de pacotes diferente, você pode ajustar o cliFile à sua configuração. Você pode personalizá-lo da seguinte maneira:

groovy
cliFile = file("../node_modules/react-native/cli.js")

debuggableVariants

Esta é a lista de variantes que podem ser depuradas (consulte a seção usando variantes disponível aqui para obter mais contexto sobre variantes).

Por padrão o plugin considera como debuggableVariants apenas debug, enquanto release não é. Se você tiver outra variantes (como staging, lite, etc.), você precisará ajustar isso de acordo.

As variantes listadas como debuggableVariants não virão com um pacote, então você precisará do Metro para executá-las.

Você pode personalizá-lo da seguinte maneira:

groovy
debuggableVariants = ["liteDebug", "prodDebug"]

nodeExecutableAndArgs

Esta é a lista de comandos e argumentos do nó que devem ser invocados para todos os scripts. Por padrão é [node] mas pode ser personalizado para adicionar sinalizadores extras como segue:

groovy
nodeExecutableAndArgs = ["node"]

bundleCommand

Este é o nome do comando bundle a ser invocado ao criar o pacote para seu aplicativo. Isso é útil se você estiver usando pacotes de RAM. Por padrão é bundle mas pode ser personalizado para adicionar sinalizadores extras como segue:

groovy
bundleCommand = "ram-bundle"

bundleConfig

Este é o caminho para um arquivo de configuração que será passado para bundle --config <file> se fornecido. O padrão é vazio (nenhum arquivo de configuração será proibido). Mais informações sobre o agrupamento de arquivos de configuração podem ser encontradas na documentação da CLI. Pode ser personalizado da seguinte forma:

groovy
bundleConfig = file(../rn-cli.config.js)

bundleAssetName

Este é o nome do arquivo do pacote que deve ser gerado. O padrão é index.android.bundle. Pode ser personalizado da seguinte forma:

groovy
bundleAssetName = "MyApplication.android.bundle"

entryFile

O arquivo de entrada usado para geração de pacote configurável. O padrão é procurar por index.android.js ou index.js. Pode ser personalizado da seguinte forma:

groovy
entryFile = file("../js/MyApplication.android.js")

extraPackagerArgs

Uma lista de sinalizadores extras que serão passados ​​para o comando bundle. A lista de sinalizadores disponíveis está na documentação da CLI. O padrão está vazio. Pode ser personalizado da seguinte forma:

groovy
extraPackagerArgs = []

hermesCommand

O caminho para o comando hermesc (o compilador Hermes). O React Native vem com uma versão do compilador Hermes, então geralmente você não precisará personalizá-lo. O plugin usará o compilador correto para o seu sistema por padrão.

hermesFlags

A lista de sinalizadores a serem passados ​​para hermesc. Por padrão é ["-O", "-output-source-map"]. Você pode personalizá-lo da seguinte maneira

groovy
hermesFlags = ["-O", "-output-source-map"]

Usando sabores e variantes de construção

Ao criar aplicativos Android, talvez você queira usar variações personalizadas para ter versões diferentes do seu aplicativo a partir do mesmo projeto.

Consulte o guia oficial do Android para configurar tipos de compilação personalizados (como staging) ou versões personalizadas (como full, lite , etc.).

Por padrão, novos aplicativos são criados com dois tipos de compilação (debug e release) e sem variações personalizadas.

A combinação de todos os tipos de compilação e todas as variações gera um conjunto de variantes de compilação. Por exemplo, para os tipos de compilação debug/staging/release e ​​full/lite você terá 6 variantes de compilação: fullDebug, fullStaging, fullRelease e ​​assim por diante.

Se você estiver usando variantes personalizadas além de debug e release, você precisa instruir o plugin React Native Gradle especificando quais de suas variantes são depuráveis usando a configuração debuggableVariants da seguinte forma :

diff
apply plugin: "com.facebook.react"
+
+react {
++ debuggableVariants = ["fullStaging", "fullDebug"]
+}

Isso é necessário porque o plugin irá ignorar o empacotamento JS para todos os debuggableVariants: você precisará do Metro para executá-los. Por exemplo, se você listar fullStaging em debuggableVariants, não será possível publicá-lo em uma loja, pois faltará o pacote.

O que o plugin está fazendo nos bastidores?

O plugin React Native Gradle é responsável por configurar a construção do seu aplicativo para enviar aplicativos React Native para produção. O plugin também é usado em bibliotecas de terceiros, para executar o Codegen usado para a Nova Arquitetura.

Aqui está um resumo das responsabilidades do plugin:

  • Adiciona uma tarefa createBundle<Variant>JsAndAssets para cada variante não depurável, que é responsável por invocar os comandos bundle, hermesc e compose-source-map.
  • Configura a versão adequada da dependência com.facebook.react:react-android e com.facebook.react:hermes-android, lendo a versão React Native do package.json de react-native .
  • Configura os repositórios Maven adequados (Maven Central, Google Maven Repo, repositório Maven local JSC, etc.) necessários para consumir todas as dependências Maven necessárias.
  • Configura o NDK para permitir a criação de aplicativos que usam a Nova Arquitetura.
  • Configura o buildConfigFields para que você possa saber em tempo de execução se o Hermes ou a Nova Arquitetura estão habilitados.
  • Configura a porta Metro DevServer como um recurso Android para que o aplicativo saiba em qual porta se conectar.
  • Invoca o React Native Codegen se uma biblioteca ou aplicativo estiver usando o Codegen para a nova arquitetura.
+ + + + \ No newline at end of file diff --git a/vitepress/docs/.vitepress/dist/docs/running-on-device.html b/vitepress/docs/.vitepress/dist/docs/running-on-device.html new file mode 100644 index 0000000..cb56719 --- /dev/null +++ b/vitepress/docs/.vitepress/dist/docs/running-on-device.html @@ -0,0 +1,27 @@ + + + + + + Executando no dispositivo | React Native 0.72 + + + + + + + + + + + + + + + + +
Skip to content

Executando no dispositivo

É sempre uma boa ideia testar seu aplicativo em um dispositivo real antes de liberá-lo para seus usuários. Este documento irá guiá-lo pelas etapas necessárias para executar seu aplicativo React Native em um dispositivo e prepará-lo para produção.

Informações

Se você usou create-expo-app para configurar seu projeto, você pode executar seu aplicativo em um dispositivo no Expo Go digitalizando o código QR que é exibido quando você executa npm start. Consulte o guia Expo para executar seu projeto em seu dispositivo para obter mais informações.

+ + + + \ No newline at end of file diff --git a/vitepress/docs/.vitepress/dist/docs/running-on-device/android-linux.html b/vitepress/docs/.vitepress/dist/docs/running-on-device/android-linux.html new file mode 100644 index 0000000..c4128c7 --- /dev/null +++ b/vitepress/docs/.vitepress/dist/docs/running-on-device/android-linux.html @@ -0,0 +1,43 @@ + + + + + + Linux (Android) | React Native 0.72 + + + + + + + + + + + + + + + + +
Skip to content

Linux (Android)

1. Habilite a depuração via USB

A maioria dos dispositivos Android só pode instalar e executar aplicativos baixados do Google Play, por padrão. Você precisará habilitar a depuração USB em seu dispositivo para instalar seu aplicativo durante o desenvolvimento.

Para ativar a depuração USB no seu dispositivo, primeiro você precisa ativar o menu "Opções do desenvolvedor" acessando Settings → About phone → Software information e tocando na linha Build number na parte inferior sete vezes. Você pode então voltar para Settings → Developer options para ativar a "USB debugging".

2. Conecte seu dispositivo via USB

Vamos agora configurar um dispositivo Android para executar nossos projetos React Native. Vá em frente e conecte seu dispositivo via USB à sua máquina de desenvolvimento.

Em seguida, verifique o código do fabricante usando lsusb (no Mac, você deve primeiro instalar o lsusb). lsusb deve gerar algo assim:

bash
$ lsusb
+Bus 002 Device 002: ID 8087:0024 Intel Corp. Integrated Rate Matching Hub
+Bus 002 Device 001: ID 1d6b:0002 Linux Foundation 2.0 root hub
+Bus 001 Device 003: ID 22b8:2e76 Motorola PCS
+Bus 001 Device 002: ID 8087:0024 Intel Corp. Integrated Rate Matching Hub
+Bus 001 Device 001: ID 1d6b:0002 Linux Foundation 2.0 root hub
+Bus 004 Device 001: ID 1d6b:0003 Linux Foundation 3.0 root hub
+Bus 003 Device 001: ID 1d6b:0002 Linux Foundation 2.0 root hub

Estas linhas representam os dispositivos USB atualmente conectados à sua máquina.

Você quer a linha que representa o seu telefone. Em caso de dúvida, tente desconectar o telefone e executar o comando novamente:

bash
$ lsusb
+Bus 002 Device 002: ID 8087:0024 Intel Corp. Integrated Rate Matching Hub
+Bus 002 Device 001: ID 1d6b:0002 Linux Foundation 2.0 root hub
+Bus 001 Device 002: ID 8087:0024 Intel Corp. Integrated Rate Matching Hub
+Bus 001 Device 001: ID 1d6b:0002 Linux Foundation 2.0 root hub
+Bus 004 Device 001: ID 1d6b:0003 Linux Foundation 3.0 root hub
+Bus 003 Device 001: ID 1d6b:0002 Linux Foundation 2.0 root hub

Você verá que após retirar o telefone, a linha que contém o modelo do telefone (“Motorola PCS” neste caso) desapareceu da lista. Esta é a linha com a qual nos preocupamos.

bash
Bus 001 Device 003: ID 22b8:2e76 Motorola PCS

Na linha acima, você deve obter os primeiros quatro dígitos do ID do dispositivo:

bash
22b8:2e76

Neste caso, é 22b8. Esse é o identificador da Motorola.

Você precisará inserir isso nas regras do udev para começar a trabalhar:

bash
echo 'SUBSYSTEM=="usb", ATTR{idVendor}=="22b8", MODE="0666", GROUP="plugdev"' | sudo tee /etc/udev/rules.d/51-android-usb.rules

Certifique-se de substituir 22b8 pelo identificador obtido no comando acima.

Agora verifique se o seu dispositivo está conectado corretamente ao ADB, o Android Debug Bridge, executando adb devices.

bash
$ adb devices
+List of devices attached
+emulator-5554 offline   # Google emulator
+14ed2fcc device         # Dispositivo físico

Ver o device na coluna da direita significa que o dispositivo está conectado. Você deve ter apenas um dispositivo conectado por vez.

3. Execute seu aplicativo

Na raiz do seu projeto, digite o seguinte no prompt de comando para instalar e iniciar seu aplicativo no dispositivo:

bash
npm run android
bash
yarn android

DICA

Você também pode usar o React Native CLI para gerar e executar uma release (por exemplo, da raiz do seu projeto: yarn android --mode release).

Conectando-se ao servidor de desenvolvimento

Você também pode iterar rapidamente em um dispositivo conectando-se ao servidor de desenvolvimento em execução na sua máquina de desenvolvimento. Existem várias maneiras de fazer isso, dependendo se você tem acesso a um cabo USB ou a uma rede Wi-Fi.

Método 1: usando adb reverse (recomendado)

Você pode usar este método se o seu dispositivo estiver executando o Android 5.0 (Lollipop) ou mais recente, tiver a depuração USB ativada e estiver conectado via USB à sua máquina de desenvolvimento.

Execute o seguinte em um prompt de comando:

bash
adb -s <device name> reverse tcp:8081 tcp:8081

Para encontrar o nome do dispositivo, execute o seguinte comando adb:

bash
adb devices

Agora você pode ativar o recarregamento ao vivo no Dev Menu. Seu aplicativo será recarregado sempre que seu código JavaScript for alterado.

Método 2: conectar via Wi-Fi

Você também pode se conectar ao servidor de desenvolvimento por Wi-Fi. Primeiro, você precisará instalar o aplicativo em seu dispositivo usando um cabo USB, mas depois de fazer isso, você poderá depurar sem fio seguindo estas instruções. Você precisará do endereço IP atual da sua máquina de desenvolvimento antes de continuar.

Abra um terminal e digite /sbin/ifconfig para encontrar o endereço IP da sua máquina.

  1. Certifique-se de que seu laptop e telefone estejam na mesma rede Wi-Fi.
  2. Abra seu aplicativo React Native em seu dispositivo.
  3. Você verá uma tela vermelha com um erro. Tudo bem. As etapas a seguir corrigirão isso.
  4. Abra o menu de desenvolvimento do aplicativo.
  5. Vá para Dev Settings → Debug server host & port for device.
  6. Digite o endereço IP da sua máquina e a porta do servidor de desenvolvimento local (por exemplo, 10.0.1.1:8081).
  7. Volte ao Dev Menu e selecione Reload JS.

Agora você pode ativar o recarregamento ao vivo no Dev Menu. Seu aplicativo será recarregado sempre que seu código JavaScript for alterado.

Construindo seu aplicativo para produção

Você construiu um ótimo aplicativo usando React Native e agora está ansioso para lançá-lo na Play Store. O processo é igual ao de qualquer outro aplicativo Android nativo, com algumas considerações adicionais a serem levadas em consideração. Siga o guia para gerar um APK assinado para saber mais.

+ + + + \ No newline at end of file diff --git a/vitepress/docs/.vitepress/dist/docs/running-on-device/android-mac-os.html b/vitepress/docs/.vitepress/dist/docs/running-on-device/android-mac-os.html new file mode 100644 index 0000000..6f12684 --- /dev/null +++ b/vitepress/docs/.vitepress/dist/docs/running-on-device/android-mac-os.html @@ -0,0 +1,30 @@ + + + + + + Mac OS (Android) | React Native 0.72 + + + + + + + + + + + + + + + + +
Skip to content

Mac OS (Android)

1. Habilite a depuração via USB

A maioria dos dispositivos Android só pode instalar e executar aplicativos baixados do Google Play, por padrão. Você precisará habilitar a depuração USB em seu dispositivo para instalar seu aplicativo durante o desenvolvimento.

Para ativar a depuração USB no seu dispositivo, primeiro você precisa ativar o menu "Developer options" acessando Settings → About phone → Software information e tocando na linha Build number na parte inferior sete vezes. Você pode então voltar para Settings → Developer options para ativar a "USB debugging".

2. Conecte seu dispositivo via USB

Vamos agora configurar um dispositivo Android para executar nossos projetos React Native. Vá em frente e conecte seu dispositivo via USB à sua máquina de desenvolvimento.

Agora verifique se o seu dispositivo está conectado corretamente ao ADB, o Android Debug Bridge, executando adb devices.

bash
$ adb devices
+List of devices attached
+emulator-5554 offline   # Google emulator
+14ed2fcc device         # Physical device

Ver o device na coluna da direita significa que o dispositivo está conectado. Você deve ter apenas um dispositivo conectado por vez.

OBSERVAÇÃO

Se você vê unauthorized na lista, precisará executar adb reverse tcp:8081 tcp:8081 e pressionar permitir depuração USB no dispositivo.

3. Execute seu aplicativo

Da raiz do seu projeto; digite o seguinte no prompt de comando para instalar e iniciar seu aplicativo no dispositivo:

bash
npm run android
bash
yarn android

DICA

Você também pode usar o React Native CLI para gerar e executar uma versão build (por exemplo, da raiz do seu projeto: yarn android --mode release).

Conectando-se ao servidor de desenvolvimento

Você também pode iterar rapidamente em um dispositivo conectando-se ao servidor de desenvolvimento em execução na sua máquina de desenvolvimento. Existem várias maneiras de fazer isso, dependendo se você tem acesso a um cabo USB ou a uma rede Wi-Fi.

Método 1: usando adb reverse (recomendado)

Você pode usar este método se o seu dispositivo estiver executando o Android 5.0 (Lollipop) ou mais recente, tiver a depuração USB ativada e estiver conectado via USB à sua máquina de desenvolvimento.

Execute o seguinte em um prompt de comando:

bash
adb -s <device name> reverse tcp:8081 tcp:8081

Para encontrar o nome do dispositivo, execute o seguinte comando adb:

bash
adb devices

Agora você pode ativar o recarregamento ao vivo no menu Dev. Seu aplicativo será recarregado sempre que seu código JavaScript for alterado.

Método 2: conectar via Wi-Fi

Você também pode se conectar ao servidor de desenvolvimento por Wi-Fi. Primeiro, você precisará instalar o aplicativo em seu dispositivo usando um cabo USB, mas depois de fazer isso, você poderá depurar sem fio seguindo estas instruções. Você precisará do endereço IP atual da sua máquina de desenvolvimento antes de continuar.

Você pode encontrar o endereço IP em System Settings (ou System Preferences) → Network.

  1. Certifique-se de que seu laptop e telefone estejam na mesma rede Wi-Fi.
  2. Abra seu aplicativo React Native em seu dispositivo.
  3. Você verá uma tela vermelha com um erro, tudo bem. As etapas a seguir corrigirão isso.
  4. Abra o menu de desenvolvimento do aplicativo.
  5. Vá para Dev Settings → Debug server host & port for device. 6.Digite o endereço IP da sua máquina e a porta do servidor de desenvolvimento local (por exemplo, 10.0.1.1:8081).
  6. Volte ao Dev Menu e selecione Reload JS.

Agora você pode ativar o recarregamento ao vivo no menu Dev. Seu aplicativo será recarregado sempre que seu código JavaScript for alterado.

Construindo seu aplicativo para produção

Você construiu um ótimo aplicativo usando React Native e agora está ansioso para lançá-lo na Play Store. O processo é igual ao de qualquer outro aplicativo Android nativo, com algumas considerações adicionais a serem levadas em consideração. Siga o guia para gerar um APK assinado para saber mais.

+ + + + \ No newline at end of file diff --git a/vitepress/docs/.vitepress/dist/docs/running-on-device/android-windows.html b/vitepress/docs/.vitepress/dist/docs/running-on-device/android-windows.html new file mode 100644 index 0000000..d6f9a2a --- /dev/null +++ b/vitepress/docs/.vitepress/dist/docs/running-on-device/android-windows.html @@ -0,0 +1,30 @@ + + + + + + Windows (Android) | React Native 0.72 + + + + + + + + + + + + + + + + +
Skip to content

Windows (Android)

1. Habilite a depuração via USB

A maioria dos dispositivos Android só pode instalar e executar aplicativos baixados do Google Play, por padrão. Você precisará habilitar a depuração USB em seu dispositivo para instalar seu aplicativo durante o desenvolvimento.

Para ativar a depuração USB no seu dispositivo, primeiro você precisa ativar o menu "Opções do desenvolvedor" acessando Settings → About phone → Software information e tocando na linha Build number na parte inferior sete vezes. Você pode então voltar para Settings → Developer options para ativar a "depuração USB".

2. Conecte seu dispositivo via USB

Vamos agora configurar um dispositivo Android para executar nossos projetos React Native. Vá em frente e conecte seu dispositivo via USB à sua máquina de desenvolvimento.

Agora verifique se o seu dispositivo está conectado corretamente ao ADB, o Android Debug Bridge, executando adb devices.

bash
$ adb devices
+List of devices attached
+emulator-5554 offline   # Google emulator
+14ed2fcc device         # Physical device

Ver o dispositivo na coluna da direita significa que o dispositivo está conectado. Você deve ter apenas um dispositivo conectado por vez.

3. Execute seu aplicativo

Na raiz do seu projeto, execute o seguinte no prompt de comando para instalar e iniciar seu aplicativo no dispositivo:

bash
npm run android
bash
yarn android

DICA

Você também pode usar o React Native CLI para gerar e executar uma release build (por exemplo, da raiz do seu projeto: yarn android --mode release).

Conectando-se ao servidor de desenvolvimento

Você também pode iterar rapidamente em um dispositivo conectando-se ao servidor de desenvolvimento em execução na sua máquina de desenvolvimento. Existem várias maneiras de fazer isso, dependendo se você tem acesso a um cabo USB ou a uma rede Wi-Fi.

Método 1: usando adb reverse (recomendado)

Você pode usar este método se o seu dispositivo estiver executando o Android 5.0 (Lollipop) ou mais recente, tiver a depuração USB ativada e estiver conectado via USB à sua máquina de desenvolvimento.

Execute o seguinte em um prompt de comando:

bash
adb -s <device name> reverse tcp:8081 tcp:8081

Para encontrar o nome do dispositivo, execute o seguinte comando adb:

bash
adb devices

Agora você pode ativar o recarregamento ao vivo no Dev Menu. Seu aplicativo será recarregado sempre que seu código JavaScript for alterado.

Método 2: conectar via Wi-Fi

Você também pode se conectar ao servidor de desenvolvimento por Wi-Fi. Primeiro, você precisará instalar o aplicativo em seu dispositivo usando um cabo USB, mas depois de fazer isso, você poderá depurar sem fio seguindo estas instruções. Você precisará do endereço IP atual da sua máquina de desenvolvimento antes de continuar.

Abra o prompt de comando e digite ipconfig para encontrar o endereço IP da sua máquina (mais informações).

  1. Certifique-se de que seu laptop e telefone estejam na mesma rede Wi-Fi.
  2. Abra seu aplicativo React Native em seu dispositivo.
  3. Você verá uma tela vermelha com um erro. Tudo bem. As etapas a seguir corrigirão isso.
  4. Abra o menu de Dev Menu.
  5. Vá para Dev Settings → Debug server host & port for device.
  6. Digite o endereço IP da sua máquina e a porta do servidor de desenvolvimento local (por exemplo, 10.0.1.1:8081).
  7. Volte ao Dev Menu e selecione Reload JS.

Agora você pode ativar o recarregamento ao vivo no Dev Menu. Seu aplicativo será recarregado sempre que seu código JavaScript for alterado.

Construindo seu aplicativo para produção

Você construiu um ótimo aplicativo usando React Native e agora está ansioso para lançá-lo na Play Store. O processo é igual ao de qualquer outro aplicativo Android nativo, com algumas considerações adicionais a serem levadas em consideração. Siga o guia para gerar um APK assinado para saber mais.

+ + + + \ No newline at end of file diff --git a/vitepress/docs/.vitepress/dist/docs/running-on-device/ios-macos.html b/vitepress/docs/.vitepress/dist/docs/running-on-device/ios-macos.html new file mode 100644 index 0000000..2eda889 --- /dev/null +++ b/vitepress/docs/.vitepress/dist/docs/running-on-device/ios-macos.html @@ -0,0 +1,27 @@ + + + + + + Mac OS (iOS) | React Native 0.72 + + + + + + + + + + + + + + + + +
Skip to content

Mac OS (iOS)

1. Conecte seu dispositivo via USB

Conecte seu dispositivo iOS ao Mac usando um cabo USB para Lightning. Navegue até a pasta ios em seu projeto e abra o arquivo .xcodeproj ou, se estiver usando CocoaPods, abra .xcworkspace, dentro dele usando o Xcode.

Se esta for a primeira vez que você executa um aplicativo em seu dispositivo iOS, talvez seja necessário registrar seu dispositivo para desenvolvimento. Abra o menu Product na barra de menu do Xcode e vá para Destination. Procure e selecione seu dispositivo na lista. O Xcode registrará seu dispositivo para desenvolvimento.

2. Configure a assinatura de código

Registre-se para obter uma conta de desenvolvedor Apple, caso ainda não tenha uma.

Selecione seu projeto no Xcode Project Navigator e, em seguida, selecione seu destino principal (deve ter o mesmo nome do seu projeto). Procure a aba “General”. Vá para "Signing" e certifique-se de que sua conta ou equipe de desenvolvedor Apple esteja selecionada no menu suspenso Equipe. Faça o mesmo para o alvo de testes (termina com Tests e está abaixo do seu alvo principal).

Repita esta etapa para o destino Testes em seu projeto.

image

3. Crie e execute seu aplicativo

Se tudo estiver configurado corretamente, seu dispositivo será listado como destino de compilação na barra de ferramentas do Xcode e também aparecerá no painel Dispositivos (Shift ⇧ + Cmd ⌘ + 2). Agora você pode pressionar o botão Build and run (Cmd ⌘ + R) ou selecionar Run no menu Product. Seu aplicativo será iniciado em seu dispositivo em breve.

image

DICA

Se você tiver algum problema, consulte os documentos da Apple Como iniciar seu aplicativo em um dispositivo.

Conectando-se ao servidor de desenvolvimento

Você também pode iterar rapidamente em um dispositivo usando o servidor de desenvolvimento. Você só precisa estar na mesma rede Wi-Fi do seu computador. Agite seu dispositivo para abrir o Dev Menu e ative o Live Reload. Seu aplicativo será recarregado sempre que seu código JavaScript for alterado.

image

Solução de problemas

DICA

Se você tiver algum problema, certifique-se de que seu Mac e seu dispositivo estejam na mesma rede e possam se comunicar. Muitas redes sem fio abertas com portais cativos são configuradas para impedir que dispositivos alcancem outros dispositivos na rede. Você pode usar o recurso Personal Hotspot do seu dispositivo neste caso. Você também pode compartilhar sua conexão de Internet (Wi-Fi/Ethernet) do seu Mac para o seu dispositivo via USB e conectar-se ao empacotador através deste túnel para velocidades de transferência muito altas.

Ao tentar se conectar ao servidor de desenvolvimento, você poderá receber uma tela vermelha com um erro dizendo:

DICA

A conexão com http://localhost:8081/debugger-proxy?role=client expirou. Você está executando o proxy do nó? Se você estiver executando no dispositivo, verifique se possui o endereço IP correto em RCTWebSocketExecutor.m.

Para resolver este problema verifique os seguintes pontos.

1. Rede Wi-Fi.

Certifique-se de que seu laptop e telefone estejam na mesma rede Wi-Fi.

2. Endereço IP

Certifique-se de que o script de construção detectou o endereço IP da sua máquina corretamente (por exemplo, 10.0.1.123).

image

Abra a aba Report Navigator, selecione o último Build e pesquise IP= seguido de um endereço IP. O endereço IP incorporado no aplicativo deve corresponder ao endereço IP da sua máquina.

Construindo seu aplicativo para produção

Você construiu um ótimo aplicativo usando React Native e agora está ansioso para lançá-lo na App Store. O processo é igual ao de qualquer outro aplicativo iOS nativo, com algumas considerações adicionais a serem levadas em consideração. Siga o guia de publicação na Apple App Store para saber mais.

+ + + + \ No newline at end of file diff --git a/vitepress/docs/.vitepress/dist/docs/running-on-simulator-ios.html b/vitepress/docs/.vitepress/dist/docs/running-on-simulator-ios.html new file mode 100644 index 0000000..7713188 --- /dev/null +++ b/vitepress/docs/.vitepress/dist/docs/running-on-simulator-ios.html @@ -0,0 +1,27 @@ + + + + + + Executando no Simulador | React Native 0.72 + + + + + + + + + + + + + + + + +
Skip to content

Executando no Simulador

Iniciando o simulador

Depois de inicializar seu projeto React Native, você pode executar o seguinte comando dentro do diretório do projeto recém-criado.

bash
npm run ios
bash
yarn ios

Se tudo estiver configurado corretamente, você deverá ver seu novo aplicativo em execução no Simulador iOS em breve.

Especificando um dispositivo

Você pode especificar o dispositivo que o simulador deve executar com o sinalizador --simulator, seguido pelo nome do dispositivo como uma string. O padrão é "iPhone 14". Se desejar executar seu aplicativo em um iPhone SE (3ª geração), execute o seguinte comando:

bash
npm run ios -- --simulator="iPhone SE (3rd generation)"
bash
yarn ios --simulator "iPhone SE (3rd generation)"

Os nomes dos dispositivos correspondem à lista de dispositivos disponíveis no Xcode. Você pode verificar seus dispositivos disponíveis executando xcrun simctl list devices no console.

Especificando uma versão do dispositivo

Se você tiver várias versões do iOS instaladas, também precisará especificar a versão apropriada. Por exemplo. Para executar seu aplicativo em um iPhone 14 Pro (16.0), execute o seguinte comando:

bash
npm run ios -- --simulator="iPhone 14 Pro (16.0)"
bash
yarn ios --simulator "iPhone 14 Pro (16.0)"

Especificando um UDID

Você pode especificar o UDID do dispositivo retornado do comando xcrun simctl list devices. Por exemplo. Para executar seu aplicativo com UDID AAAAAAAA-AAAA-AAAA-AAAA-AAAAAAAAAAAA execute o seguinte comando:

bash
npm run ios -- --udid="AAAAAAAA-AAAA-AAAA-AAAA-AAAAAAAAAAAA"
bash
yarn ios --udid "AAAAAAAA-AAAA-AAAA-AAAA-AAAAAAAAAAAA"
+ + + + \ No newline at end of file diff --git a/vitepress/docs/.vitepress/dist/docs/security.html b/vitepress/docs/.vitepress/dist/docs/security.html new file mode 100644 index 0000000..c87039d --- /dev/null +++ b/vitepress/docs/.vitepress/dist/docs/security.html @@ -0,0 +1,27 @@ + + + + + + Segurança | React Native 0.72 + + + + + + + + + + + + + + + + +
Skip to content

Segurança

A segurança é frequentemente negligenciada ao criar aplicativos. É verdade que é impossível construir software que seja completamente impenetrável – ainda temos que inventar uma fechadura completamente impenetrável (afinal, os cofres dos bancos ainda são arrombados). No entanto, a probabilidade de ser vítima de um ataque malicioso ou de ser exposto a uma vulnerabilidade de segurança é inversamente proporcional ao esforço que você está disposto a fazer para proteger seu aplicativo contra tal eventualidade. Embora um cadeado comum possa ser arrombado, ainda é muito mais difícil de passar do que um gancho de armário!

Neste guia, você aprenderá sobre as práticas recomendadas para armazenamento de informações confidenciais, autenticação, segurança de rede e ferramentas que ajudarão você a proteger seu aplicativo. Esta não é uma lista de verificação prévia – é um catálogo de opções, cada uma das quais ajudará a proteger ainda mais seu aplicativo e seus usuários.

Probabilidade de violação x esforço investido em segurança

Armazenando informações confidenciais

Nunca armazene chaves de API confidenciais no código do seu aplicativo. Qualquer coisa incluída no seu código pode ser acessada em texto simples por qualquer pessoa que inspecione o pacote de aplicativos. Ferramentas como react-native-dotenv e react-native-config são ótimas para adicionar variáveis específicas do ambiente, como endpoints de API, mas não devem ser confundidas com variáveis de ambiente do lado do servidor, que muitas vezes podem conter segredos e chaves de API.

Se você precisar de uma chave de API ou um segredo para acessar algum recurso do seu aplicativo, a maneira mais segura de lidar com isso seria construir uma camada de orquestração entre o seu aplicativo e o recurso. Esta poderia ser uma função sem servidor (por exemplo, usando AWS Lambda ou Google Cloud Functions) que pode encaminhar a solicitação com a chave ou segredo de API necessário. Os segredos no código do lado do servidor não podem ser acessados pelos consumidores da API da mesma forma que os segredos no código do seu aplicativo.

Para dados persistentes do usuário, escolha o tipo certo de armazenamento com base em sua sensibilidade. À medida que seu aplicativo é usado, muitas vezes você encontrará a necessidade de salvar dados no dispositivo, seja para oferecer suporte ao uso off-line do seu aplicativo, reduzir solicitações de rede ou salvar o token de acesso do usuário entre sessões para que eles não precisem voltar. -autenticar cada vez que usarem o aplicativo.

Persistente versus não persistente – os dados persistentes são gravados no disco do dispositivo, o que permite que os dados sejam lidos pelo seu aplicativo durante a inicialização do aplicativo, sem a necessidade de fazer outra solicitação de rede para buscá-los ou solicitar ao usuário que os insira novamente. Mas isso também pode tornar esses dados mais vulneráveis ao acesso de invasores. Os dados não persistentes nunca são gravados no disco — portanto, não há dados para acessar!

Armazenamento assíncrono

Async Storage é um módulo mantido pela comunidade para React Native que fornece um armazenamento de chave-valor assíncrono e não criptografado. O armazenamento assíncrono não é compartilhado entre aplicativos: cada aplicativo possui seu próprio ambiente sandbox e não tem acesso aos dados de outros aplicativos.

USE ARMAZENAMENTO ASSYNC QUANDO...NÃO USE ARMAZENAMENTO ASSINCRONO PARA...
Persistência de dados não confidenciais em execuções de aplicativosArmazenamento de tokens
Estado Redux persistenteSegredos
Estado GraphQL persistente
Armazenando variáveis globais em todo o aplicativo

Notas do desenvolvedor

Async Storage é o equivalente React Native do armazenamento local da web

Armazenamento seguro

O React Native não vem com nenhuma forma de armazenar dados confidenciais. No entanto, existem soluções pré-existentes para plataformas Android e iOS.

iOS - Serviços de chaveiro

O Keychain Services permite armazenar com segurança pequenos pedaços de informações confidenciais para o usuário. Este é o local ideal para armazenar certificados, tokens, senhas e qualquer outra informação confidencial que não pertença ao armazenamento assíncrono.

Android - Preferências compartilhadas seguras

Shared Preferences são o equivalente Android para um armazenamento de dados de valor-chave persistente. Os dados em Preferências compartilhadas não são criptografados por padrão, mas Encrypted Shared Preferences agrupam a classe Shared Preferences para Android e criptografam automaticamente chaves e valores.

Android - armazenamento de chaves

O sistema Android Keystore permite armazenar chaves criptográficas em um contêiner para dificultar a extração do dispositivo.

Para usar os serviços iOS Keychain ou Android Secure Shared Preferences, você mesmo pode escrever uma ponte ou usar uma biblioteca que os agrupa para você e fornece uma API unificada por sua conta e risco. Algumas bibliotecas a serem consideradas:

INFORMAÇÕES

Esteja atento ao armazenamento ou exposição involuntária de informações confidenciais. Isso pode acontecer acidentalmente, por exemplo, salvando dados de formulário confidenciais em estado redux e persistindo toda a árvore de estado no armazenamento assíncrono. Ou enviar tokens de usuários e informações pessoais para um serviço de monitoramento de aplicativos como Sentry ou Crashlytics.

Os aplicativos móveis têm uma vulnerabilidade única que não existe na web: links diretos. Deep linking é uma forma de enviar dados diretamente para um aplicativo nativo de uma fonte externa. Um link direto se parece com app:// onde app é o esquema do seu aplicativo e qualquer coisa após // pode ser usada internamente para lidar com a solicitação.

Por exemplo, se você estivesse criando um aplicativo de comércio eletrônico, poderia usar app://products/1 para criar um link direto para seu aplicativo e abrir a página de detalhes do produto com ID 1. Você pode pensar nesses tipos de URLs em na web, mas com uma distinção crucial:

Links diretos não são seguros e você nunca deve enviar informações confidenciais neles.

A razão pela qual os links diretos não são seguros é porque não existe um método centralizado de registro de esquemas de URL. Como desenvolvedor de aplicativos, você pode usar praticamente qualquer esquema de URL de sua escolha, configurando-o no Xcode para iOS ou adicionando uma intenção no Android.

Não há nada que impeça um aplicativo malicioso de sequestrar seu link direto, registrando-se também no mesmo esquema e obtendo acesso aos dados que seu link contém. Enviar algo como app://products/1 não é prejudicial, mas enviar tokens é uma preocupação de segurança.

Quando o sistema operacional tiver dois ou mais aplicativos para escolher ao abrir um link, o Android mostrará ao usuário uma caixa de diálogo de desambiguação e solicitará que ele escolha qual aplicativo usar para abrir o link. No entanto, no iOS, o sistema operacional fará a escolha por você, então o usuário ficará felizmente inconsciente. A Apple tomou medidas para resolver esse problema em versões posteriores do iOS (iOS 11), onde instituiu o princípio de ordem de chegada, embora essa vulnerabilidade ainda possa ser explorada de diferentes maneiras, sobre as quais você pode ler mais aqui. O uso de links universais permitirá vincular o conteúdo do seu aplicativo com segurança no iOS.

OAuth2 e redirecionamentos

O protocolo de autenticação OAuth2 é incrivelmente popular hoje em dia, considerado o protocolo mais completo e seguro que existe. O protocolo OpenID Connect também se baseia nisso. No OAuth2, o usuário é solicitado a se autenticar por meio de terceiros. Após a conclusão bem-sucedida, esse terceiro redireciona de volta para o aplicativo solicitante com um código de verificação que pode ser trocado por um JWT – um JSON Web Token. JWT é um padrão aberto para transmissão segura de informações entre partes na web.

Na web, essa etapa de redirecionamento é segura, porque os URLs na web são garantidos como exclusivos. Isso não é verdade para aplicativos porque, como mencionado anteriormente, não existe um método centralizado de registro de esquemas de URL! Para resolver esta questão de segurança, uma verificação adicional deve ser adicionada na forma de PKCE.

PKCE, pronunciado “Pixy”, significa Proof of Key Code Exchange e é uma extensão da especificação OAuth 2. Isso envolve adicionar uma camada adicional de segurança que verifica se as solicitações de autenticação e troca de tokens vêm do mesmo cliente. PKCE usa o algoritmo de hash criptográfico SHA 256. SHA 256 cria uma “assinatura” exclusiva para um texto ou arquivo de qualquer tamanho, mas é:

  • Sempre o mesmo comprimento, independentemente do arquivo de entrada
  • Garantido para produzir sempre o mesmo resultado para a mesma entrada
  • Uma maneira (ou seja, você não pode fazer engenharia reversa para revelar a entrada original)

Agora você tem dois valores:

  • code_verifier - uma grande string aleatória gerada pelo cliente
  • code_challenge - o SHA 256 do code_verifier

Durante a solicitação inicial /authorize, o cliente também envia o code_challenge para o code_verifier que mantém na memória. Após a solicitação de autorização retornar corretamente, o cliente também envia o code_verifier que foi usado para gerar o code_challenge. O IDP calculará então o code_challenge, verificará se ele corresponde ao que foi definido na primeira solicitação /authorize e enviará o token de acesso apenas se os valores corresponderem.

Isso garante que apenas o aplicativo que acionou o fluxo de autorização inicial poderá trocar com êxito o código de verificação por um JWT. Portanto, mesmo que um aplicativo malicioso obtenha acesso ao código de verificação, ele será inútil por si só. Para ver isso em ação, confira este exemplo.

Uma biblioteca a ser considerada para OAuth nativo é react-native-app-auth. React-native-app-auth é um SDK para comunicação com provedores OAuth2. Ele agrupa as bibliotecas nativas AppAuth-iOS e AppAuth-Android e pode oferecer suporte a PKCE.

INFORMAÇÃO

React-native-app-auth pode oferecer suporte a PKCE somente se seu provedor de identidade oferecer suporte.

image

Segurança de rede

Suas APIs devem sempre usar criptografia SSL. A criptografia SSL protege contra a leitura dos dados solicitados em texto simples entre o momento em que saem do servidor e antes de chegarem ao cliente. Você saberá que o endpoint é seguro porque começa com https:// em vez de http://.

SSL Pinning

O uso de endpoints https ainda pode deixar seus dados vulneráveis à interceptação. Com https, o cliente só confiará no servidor se puder fornecer um certificado válido assinado por uma autoridade de certificação confiável pré-instalada no cliente. Um invasor pode tirar vantagem disso instalando um certificado CA raiz malicioso no dispositivo do usuário, para que o cliente confie em todos os certificados assinados pelo invasor. Portanto, confiar apenas em certificados ainda pode deixá-lo vulnerável a um ataque man-in-the-middle.

A SSL Pinning é uma técnica que pode ser usada no lado do cliente para evitar esse ataque. Ele funciona incorporando (ou fixando) uma lista de certificados confiáveis ao cliente durante o desenvolvimento, de modo que apenas as solicitações assinadas com um dos certificados confiáveis serão aceitas e quaisquer certificados autoassinados não serão aceitos.

INFORMAÇÃO

Ao usar o SSL Pinnig, você deve estar atento à expiração do certificado. Os certificados expiram a cada 1-2 anos e, quando isso acontecer, precisarão ser atualizados no aplicativo e também no servidor. Assim que o certificado no servidor for atualizado, todos os aplicativos com o certificado antigo incorporado deixarão de funcionar.

Resumo

Não existe uma maneira infalível de lidar com a segurança, mas com esforço consciente e diligência, é possível reduzir significativamente a probabilidade de uma violação de segurança em seu aplicativo. Invista em segurança proporcional à sensibilidade dos dados armazenados em sua aplicação, ao número de usuários e aos danos que um hacker pode causar ao obter acesso à sua conta. E lembre-se: é significativamente mais difícil acessar informações que nunca foram solicitadas.

+ + + + \ No newline at end of file diff --git a/vitepress/docs/.vitepress/dist/docs/signed-apk-android.html b/vitepress/docs/.vitepress/dist/docs/signed-apk-android.html new file mode 100644 index 0000000..f4540cf --- /dev/null +++ b/vitepress/docs/.vitepress/dist/docs/signed-apk-android.html @@ -0,0 +1,65 @@ + + + + + + Publicação na Google Play Store | React Native 0.72 + + + + + + + + + + + + + + + + +
Skip to content

Publicação na Google Play Store

O Android exige que todos os aplicativos sejam assinados digitalmente com um certificado antes de serem instalados. Para distribuir seu aplicativo Android pela Google Play Store, ele precisa ser assinado com uma chave de versão que deverá ser usada em todas as atualizações futuras. Desde 2017, o Google Play pode gerenciar versões de assinatura automaticamente graças à funcionalidade App Signing by Google Play . No entanto, antes de o binário do seu aplicativo ser carregado no Google Play, ele precisa ser assinado com uma chave de upload. A página Assinando seus aplicativos na documentação para desenvolvedores Android descreve o tópico em detalhes. Este guia aborda resumidamente o processo, bem como lista as etapas necessárias para empacotar o pacote JavaScript.

INFORMAÇÃO

Se você estiver usando a Expo, leia o guia da Expo para Implantação nas App Stores para criar e enviar seu aplicativo para a Google Play Store. Este guia funciona com qualquer aplicativo React Native para automatizar o processo de implantação.

Gerando uma chave de upload

Você pode gerar uma chave de assinatura privada usando keytool.

Windows

No Windows keytool deve ser executado em C:\Program Files\Java\jdkx.x.x_x\bin, como administrador.

bash
keytool -genkeypair -v -storetype PKCS12 -keystore my-upload-key.keystore -alias my-key-alias -keyalg RSA -keysize 2048 -validity 10000

Este comando solicita senhas para o keystore e a chave para os campos "Distinguished Name" da sua chave. Em seguida, ele gera o keystore como um arquivo chamado my-upload-key.keystore.

O keystore contém uma única chave, válida por 10.000 dias. O alias é um nome que você usará posteriormente ao assinar seu aplicativo, portanto, lembre-se de anotar o alias.

Mac OS

No macOS, se você não tiver certeza de onde está a pasta bin do JDK, execute o seguinte comando para localizá-la:

bash
/usr/libexec/java_home

Ele gerará o diretório do JDK, que será parecido com isto:

bash
/Library/Java/JavaVirtualMachines/jdkX.X.X_XXX.jdk/Contents/Home

Navegue até esse diretório usando o comando cd /your/jdk/path e use o comando keytool com permissão sudo conforme mostrado abaixo.

bash
sudo keytool -genkey -v -keystore my-upload-key.keystore -alias my-key-alias -keyalg RSA -keysize 2048 -validity 10000

ATENÇÃO

Lembre-se de manter o arquivo keystore privado. Caso você tenha perdido a chave de upload ou ela tenha sido comprometida, siga estas instruções.

Configurando variáveis ​​Gradle

  1. Coloque o arquivo my-upload-key.keystore no diretório android/app na pasta do seu projeto.
  2. Edite o arquivo ~/.gradle/gradle.properties ou android/gradle.properties e adicione o seguinte (substitua ***** pela senha correta do keystore, alias e senha da chave),
MYAPP_UPLOAD_STORE_FILE=my-upload-key.keystore
+MYAPP_UPLOAD_KEY_ALIAS=my-key-alias
+MYAPP_UPLOAD_STORE_PASSWORD=*****
+MYAPP_UPLOAD_KEY_PASSWORD=*****

Essas serão variáveis ​​globais do Gradle, que poderemos usar posteriormente em nossa configuração do Gradle para assinar nosso aplicativo.

Nota sobre o uso do git

Salvar as variáveis ​​Gradle acima em ~/.gradle/gradle.properties em vez de android/gradle.properties impede que elas sejam registradas no git. Talvez seja necessário criar o arquivo ~/.gradle/gradle.properties no diretório inicial do usuário antes de adicionar as variáveis.

Nota sobre segurança

Se você não deseja armazenar suas senhas em texto simples e estiver executando o macOS, você também pode [armazenar suas credenciais no aplicativo Keychain Access](https://pilloxa.gitlab.io/posts/safer-passwords-in- grau/). Então você pode pular as duas últimas linhas em ~/.gradle/gradle.properties.

Adicionando configuração de assinatura à configuração Gradle do seu aplicativo

A última etapa de configuração que precisa ser feita é configurar as compilações de versão para serem assinadas usando a chave de upload. Edite o arquivo android/app/build.gradle na pasta do seu projeto e adicione a configuração de assinatura,

...
+android {
+    ...
+    defaultConfig { ... }
+    signingConfigs {
+        release {
+            if (project.hasProperty('MYAPP_UPLOAD_STORE_FILE')) {
+                storeFile file(MYAPP_UPLOAD_STORE_FILE)
+                storePassword MYAPP_UPLOAD_STORE_PASSWORD
+                keyAlias MYAPP_UPLOAD_KEY_ALIAS
+                keyPassword MYAPP_UPLOAD_KEY_PASSWORD
+            }
+        }
+    }
+    buildTypes {
+        release {
+            ...
+            signingConfig signingConfigs.release
+        }
+    }
+}
+...

Gerando uma release AAB

Execute o seguinte comando em um terminal:

bash
npx react-native build-android --mode=release

Este comando usa o bundleRelease do Gradle que agrupa todo o JavaScript necessário para executar seu aplicativo no AAB (Android App Bundle). Se você precisar alterar a forma como o pacote JavaScript e/ou os recursos drawable são agrupados (por exemplo, se você alterou os nomes de arquivos/pastas padrão ou a estrutura geral do projeto), dê uma olhada em android/app/build.gradle para ver como você pode atualizá-lo para refletir essas alterações.

INFORMAÇÃO

Certifique-se de que gradle.properties não inclua org.gradle.configureondemand=true, pois isso fará com que a compilação de lançamento ignore o agrupamento de JS e ativos no binário do aplicativo.

O AAB gerado pode ser encontrado em android/app/build/outputs/bundle/release/app-release.aab e está pronto para ser carregado no Google Play.

Para que o Google Play aceite o formato AAB, a assinatura de aplicativos do Google Play precisa ser configurada para seu aplicativo no Google Play Console. Se você estiver atualizando um aplicativo existente que não usa a assinatura de aplicativos do Google Play, consulte a seção de migração para aprender como realizar essa alteração na configuração.

Testando a versão de lançamento do seu aplicativo

Antes de enviar a versão de lançamento para a Play Store, teste-a completamente. Primeiro desinstale qualquer versão anterior do aplicativo que você já instalou. Instale-o no dispositivo usando o seguinte comando na raiz do projeto:

bash
npm run android -- --mode="release"
bash
yarn android --mode release

Observe que --mode release só está disponível se você configurou a assinatura conforme descrito acima.

Você pode encerrar qualquer instância do bundler em execução, já que toda a estrutura e o código JavaScript estão agrupados nos ativos do APK.

Publicação em outras lojas

Por padrão, o APK gerado possui o código nativo para as arquiteturas de CPU x86, x86_64, ARMv7a e ARM64-v8a. Isso facilita o compartilhamento de APKs executados em quase todos os dispositivos Android. No entanto, isso tem a desvantagem de que haverá algum código nativo não utilizado em qualquer dispositivo, levando a APKs desnecessariamente maiores.

Você pode criar um APK para cada CPU adicionando a seguinte linha em seu arquivo android/app/build.gradle:

android {
+
+    splits {
+        abi {
+            reset()
+            enable true
+            universalApk false
+            include "armeabi-v7a", "arm64-v8a", "x86", "x86_64"
+        }
+    }
+
+}

Faça upload desses arquivos para mercados que oferecem suporte à segmentação por dispositivo, como Amazon AppStore ou F-Droid, e os usuários obterão automaticamente o APK apropriado. Se você quiser fazer upload para outros mercados, como APKFiles, que não suportam vários APKs para um único aplicativo, altere a linha universalApk false para true para crie o APK universal padrão com binários para ambas as CPUs.

Observe que você também terá que configurar códigos de versão distintos, conforme sugerido nesta página do site oficial da Documentação do Android.

Habilitando o Proguard para reduzir o tamanho do APK (opcional)

Proguard é uma ferramenta que pode reduzir ligeiramente o tamanho do APK. Isso é feito removendo partes do bytecode React Native Java (e suas dependências) que seu aplicativo não está usando.

Importante

Certifique-se de testar completamente seu aplicativo se você ativou o Proguard. O Proguard geralmente requer configuração específica para cada biblioteca nativa que você está usando. Consulte app/proguard-rules.pro.

Para ativar o Proguard, edite android/app/build.gradle:

/**
+ * Execute o Proguard para reduzir o bytecode Java em compilações de lançamento.
+ */
+def enableProguardInReleaseBuilds = true

Migrando aplicativos antigos do Android React Native para usar o App Signing do Google Play

Se você estiver migrando da versão anterior do React Native, é provável que seu aplicativo não use o recurso App Signing by Google Play. Recomendamos que você habilite isso para aproveitar recursos como a divisão automática de aplicativos. Para migrar da forma antiga de assinatura, você precisa começar gerando nova chave de upload e, em seguida, substituindo a configuração de assinatura de lançamento em android/app/build.gradle para usar o chave de upload em vez da de lançamento (consulte a seção sobre adicionando configuração de assinatura ao gradle). Feito isso, siga as instruções do site de ajuda do Google Play para enviar sua chave de versão original ao Google Play.

Permissões padrão

Por padrão, a permissão INTERNET é adicionada ao seu aplicativo Android, pois praticamente todos os aplicativos a utilizam. A permissão SYSTEM_ALERT_WINDOW é adicionada ao seu APK Android no modo de depuração, mas será removida na produção.

+ + + + \ No newline at end of file diff --git a/vitepress/docs/.vitepress/dist/docs/sourcemaps.html b/vitepress/docs/.vitepress/dist/docs/sourcemaps.html new file mode 100644 index 0000000..3f1d7a4 --- /dev/null +++ b/vitepress/docs/.vitepress/dist/docs/sourcemaps.html @@ -0,0 +1,41 @@ + + + + + + Mapas de origem | React Native 0.72 + + + + + + + + + + + + + + + + +
Skip to content

Mapas de origem

Os mapas de origem permitem mapear um arquivo transformado de volta ao arquivo de origem original. O objetivo principal dos mapas de origem é ajudar na depuração e na investigação de problemas de compilações de lançamento.

Sem os mapas de origem, ao encontrar um erro na compilação da versão, você verá um stacktrace como:

bash
TypeError: Cannot read property 'data' of undefined
+  at anonymous(app:///index.android.bundle:1:4277021)
+  at call(native)
+  at p(app:///index.android.bundle:1:227785)

Com os mapas de origem gerados, um stacktrace incluirá o caminho, o nome do arquivo e o número da linha do arquivo de origem original:

bash
TypeError: Cannot read property 'data' of undefined
+  at anonymous(src/modules/notifications/Permission.js:15:requestNotificationPermission)
+  at call(native)
+  at p(node_modules/regenerator-runtime/runtime.js:64:Generator)

Isso permite que você faça a triagem de problemas de lançamento usando um stacktrace decifrável.

Siga as instruções abaixo para começar a usar os mapas de origem.

Habilitar mapas de origem no Android

Hermes

INFORMAÇÕES

Os mapas de origem são criados no modo Release por padrão, a menos que hermesFlagsRelease não esteja definido. Nesse caso, os mapas de origem terão que ser habilitados.

Para fazer isso, certifique-se de que o seguinte esteja definido no arquivo Android/app/build.gradle do seu aplicativo.

js
project.ext.react = [
+    enableHermes: true,
+    hermesFlagsRelease: ["-O", "-output-source-map"], // mais qualquer sinalizador necessário para definir isso fora do padrão
+]

Se feito corretamente, você deverá ver o local de saída do mapa de origem durante a saída da compilação Metro.

Writing bundle output to:, android/app/build/generated/assets/react/release/index.android.bundle
+Writing sourcemap output to:, android/app/build/intermediates/sourcemaps/react/release/index.android.bundle.packager.map

As compilações de desenvolvimento não produzem um pacote configurável e, portanto, já possuem símbolos, mas se a compilação de desenvolvimento estiver empacotada, você pode usar hermesFlagsDebug como acima para habilitar mapas de origem.

Habilitar mapas de origem no iOS

Os mapas de origem estão desabilitados por padrão. Para habilitá-los é necessário definir uma variável de ambiente SOURCEMAP_FILE.

Para fazer isso, dentro do Xcode vá para a fase de construção - "Bundle React Native code and images".

Na parte superior do arquivo, próximo às outras exportações, adicione uma entrada para SOURCEMAP_FILE ao local e nome preferidos. Como abaixo:

export SOURCEMAP_FILE="$(pwd)/../main.jsbundle.map";
+
+export NODE_BINARY=node
+../node_modules/react-native/scripts/react-native-xcode.sh

Se feito corretamente, você deverá ver o local de saída do mapa de origem durante a saída da compilação Metro.

Writing bundle output to:, Build/Intermediates.noindex/ArchiveIntermediates/application/BuildProductsPath/Release-iphoneos/main.jsbundle
+Writing sourcemap output to:, Build/Intermediates.noindex/ArchiveIntermediates/application/BuildProductsPath/Release-iphoneos/main.jsbundle.map

Simbolização Manual

INFORMAÇÕES

Você pode ler sobre a simbolização manual de um rastreamento de pilha na página de simbolização.

+ + + + \ No newline at end of file diff --git a/vitepress/docs/.vitepress/dist/docs/speeding-ci-builds.html b/vitepress/docs/.vitepress/dist/docs/speeding-ci-builds.html new file mode 100644 index 0000000..4380d6c --- /dev/null +++ b/vitepress/docs/.vitepress/dist/docs/speeding-ci-builds.html @@ -0,0 +1,37 @@ + + + + + + Acelerando as compilações de CI | React Native 0.72 + + + + + + + + + + + + + + + + +
Skip to content

Acelerando as compilações de CI

Você ou sua empresa podem ter configurado um ambiente de Integração Contínua (CI) para testar seu aplicativo React Native.

Um serviço de CI rápido é importante por 2 motivos:

  • Quanto mais tempo as máquinas de CI ficam em execução, mais elas custam.
  • Quanto mais tempo os trabalhos de CI levarem para serem executados, maior será o ciclo de desenvolvimento.

Portanto, é importante tentar minimizar o tempo que o ambiente de CI gasta construindo o React Native.

Desative o Flipper para iOS

Flipper é uma ferramenta de depuração fornecida por padrão com React Native, para ajudar os desenvolvedores a depurar e criar o perfil de seus aplicativos React Native. No entanto, o Flipper não é necessário no CI: é muito improvável que você ou um de seus colegas precise depurar o aplicativo criado no ambiente de CI.

Para aplicativos iOS, o Flipper é construído toda vez que a estrutura React Native é construída e pode levar algum tempo para ser construída, e esse é o tempo que você pode economizar.

A partir do React Native 0.71, introduzimos um novo sinalizador no Podfile do modelo: o sinalizador NO_FLIPPER.

Por padrão, o sinalizador NO_FLIPPER não está definido, portanto o Flipper será incluído por padrão em seu aplicativo.

Você pode especificar NO_FLIPPER=1 ao instalar seus pods iOS, para instruir o React Native a não instalar o Flipper. Normalmente, o comando ficaria assim:

# da pasta raiz do projeto react native
+NO_FLIPPER=1 bundle exec pod install --project-directory=ios

Adicione este comando em seu ambiente de CI para ignorar a instalação das dependências do Flipper e, assim, economizar tempo e dinheiro.

Lidar com dependências transitivas

Seu aplicativo pode estar usando algumas bibliotecas que dependem dos pods do Flipper. Se for esse o seu caso, desabilitar o flipper com o sinalizador NO_FLIPPER pode não ser suficiente: seu aplicativo pode falhar na construção neste caso.

A maneira correta de lidar com esse caso é adicionar uma configuração personalizada para react native, instruindo o aplicativo a instalar corretamente a dependência transitiva. Para conseguir isso:

  • Se ainda não o fez, crie um novo arquivo chamado react-native.config.js.
  • Exclua explicitamente a dependência transitiva das dependências quando o sinalizador estiver ativado.

Por exemplo, a biblioteca react-native-flipper é uma biblioteca adicional que depende do Flipper. Se o seu aplicativo usa isso, você precisa excluí-lo das dependências. Seu react-native.config.js ficaria assim:

js
// react-native.config.js
+
+module.exports = {
+  // outros campos
+  dependencies: {
+    ...(process.env.NO_FLIPPER
+      ? {'react-native-flipper': {platforms: {ios: null}}}
+      : {}),
+  },
+};
+ + + + \ No newline at end of file diff --git a/vitepress/docs/.vitepress/dist/docs/style.html b/vitepress/docs/.vitepress/dist/docs/style.html new file mode 100644 index 0000000..80590b0 --- /dev/null +++ b/vitepress/docs/.vitepress/dist/docs/style.html @@ -0,0 +1,55 @@ + + + + + + Estilo | React Native 0.72 + + + + + + + + + + + + + + + + +
Skip to content

Estilo

Com React Native, você estiliza seu aplicativo usando JavaScript. Todos os componentes principais aceitam um estilo chamado prop. Os nomes e valores dos estilos geralmente correspondem ao modo como o CSS funciona na web, exceto que os nomes são escritos em camel case, por exemplo. backgroundColor em vez de background-color.

A propriedade style pode ser um objeto JavaScript simples e antigo. Isso é o que normalmente usamos como código de exemplo. Você também pode passar uma matriz de estilos - o último estilo da matriz tem precedência, portanto você pode usar isso para herdar estilos.

À medida que um componente cresce em complexidade, geralmente é mais fácil usar StyleSheet.create para definir vários estilos em um só lugar. Aqui está um exemplo:

jsx
import React from 'react';
+import {StyleSheet, Text, View} from 'react-native';
+
+const LotsOfStyles = () => {
+  return (
+    <View style={styles.container}>
+      <Text style={styles.red}>just red</Text>
+      <Text style={styles.bigBlue}>just bigBlue</Text>
+      <Text style={[styles.bigBlue, styles.red]}>bigBlue, then red</Text>
+      <Text style={[styles.red, styles.bigBlue]}>red, then bigBlue</Text>
+    </View>
+  );
+};
+
+const styles = StyleSheet.create({
+  container: {
+    marginTop: 50,
+  },
+  bigBlue: {
+    color: 'blue',
+    fontWeight: 'bold',
+    fontSize: 30,
+  },
+  red: {
+    color: 'red',
+  },
+});
+
+export default LotsOfStyles;

image

Um padrão comum é fazer com que seu componente aceite um suporte de style que, por sua vez, é usado para estilizar subcomponentes. Você pode usar isso para fazer com que os estilos "casquem" da mesma forma que fazem no CSS.

Existem muito mais maneiras de personalizar o estilo do texto. Confira a referência do componente Texto para uma lista completa.

Agora você pode deixar seu texto lindo. O próximo passo para se tornar um especialista em estilo é aprender como controlar o tamanho dos componentes.

Problemas conhecidos

  • react-native#29308: Em alguns casos, o React Native não corresponde ao modo como o CSS funciona na web, por exemplo, a área de toque nunca ultrapassa os limites da visualização pai e no Android a margem negativa não é suportada.
+ + + + \ No newline at end of file diff --git a/vitepress/docs/.vitepress/dist/docs/symbolication.html b/vitepress/docs/.vitepress/dist/docs/symbolication.html new file mode 100644 index 0000000..95f3229 --- /dev/null +++ b/vitepress/docs/.vitepress/dist/docs/symbolication.html @@ -0,0 +1,32 @@ + + + + + + Simbolizando um rastreamento de pilha | React Native 0.72 + + + + + + + + + + + + + + + + +
Skip to content

Simbolizando um rastreamento de pilha

Se um aplicativo React Native lançar uma exceção não tratada em uma compilação de lançamento, a saída poderá ficar ofuscada e difícil de ler:

bash
07-15 10:58:25.820 18979 18998 E AndroidRuntime: FATAL EXCEPTION: mqt_native_modules
+07-15 10:58:25.820 18979 18998 E AndroidRuntime: Process: com.awesomeproject, PID: 18979 07-15 10:58:25.820 18979 18998 E AndroidRuntime: com.facebook.react.common.JavascriptException: Failed, js engine: hermes, stack:
+07-15 10:58:25.820 18979 18998 E AndroidRuntime: p@1:132161
+07-15 10:58:25.820 18979 18998 E AndroidRuntime: p@1:132084
+07-15 10:58:25.820 18979 18998 E AndroidRuntime: f@1:131854
+07-15 10:58:25.820 18979 18998 E AndroidRuntime: anonymous@1:131119

As seções como p@1:132161 são nomes de funções reduzidos e deslocamentos de bytecode. Para depurar o problema, você deve traduzi-lo em nome de arquivo, linha e função: AwesomeProject/App.js:54:initializeMap. Isso é conhecido como simbolização. Você pode simbolizar nomes de funções minificados e bytecode como acima, passando metro-symbolicate um mapa de origem gerado e o rastreamento de pilha.

INFORMAÇÃO

O pacote metro-symbolicate é instalado por padrão no projeto de modelo React Native ao configurar seu ambiente de desenvolvimento.

De um arquivo contendo o stacktrace:

bash
npx metro-symbolicate android/app/build/generated/sourcemaps/react/release/index.android.bundle.map < stacktrace.txt

Diretamente do adb logcat:

bash
adb logcat -d | npx metro-symbolicate android/app/build/generated/sourcemaps/react/release/index.android.bundle.map

Isso transformará cada nome de função minificado e deslocamento como p@1:132161 no nome real do arquivo e da função AwesomeProject/App.js:54:initializeMap.

Notas sobre mapas de origem

  • Vários mapas de origem podem ser gerados pelo processo de construção. Certifique-se de usar aquele no local mostrado nos exemplos.
  • Certifique-se de que o mapa de origem usado corresponda ao commit exato do aplicativo com falha. Pequenas alterações no código-fonte podem causar grandes diferenças nos deslocamentos.
  • Se o metro-symbolicate sair imediatamente com sucesso, certifique-se de que a entrada venha de um pipe ou redirecionamento e não de um terminal.
+ + + + \ No newline at end of file diff --git a/vitepress/docs/.vitepress/dist/docs/testing-overview.html b/vitepress/docs/.vitepress/dist/docs/testing-overview.html new file mode 100644 index 0000000..fdcd8ea --- /dev/null +++ b/vitepress/docs/.vitepress/dist/docs/testing-overview.html @@ -0,0 +1,75 @@ + + + + + + Teste | React Native 0.72 + + + + + + + + + + + + + + + + +
Skip to content

Teste

À medida que sua base de código se expande, pequenos erros e casos extremos que você não espera podem se transformar em falhas maiores. Bugs levam a uma experiência ruim do usuário e, em última análise, a perdas de negócios. Uma maneira de evitar uma programação frágil é testar seu código antes de liberá-lo.

Neste guia, abordaremos diferentes maneiras automatizadas de garantir que seu aplicativo funcione conforme o esperado, desde análises estáticas até testes completos.

image

Por que testar

Somos humanos e os humanos cometem erros. O teste é importante porque ajuda a descobrir esses erros e verifica se seu código está funcionando. Talvez ainda mais importante, o teste garante que seu código continue funcionando no futuro à medida que você adiciona novos recursos, refatora os existentes ou atualiza dependências importantes do seu projeto.

Há mais valor em testar do que você imagina. Uma das melhores maneiras de corrigir um bug em seu código é escrever um teste com falha que o exponha. Então, quando você corrige o bug e executa novamente o teste, se ele passar, significa que o bug foi corrigido, nunca reintroduzido na base de código.

Os testes também podem servir como documentação para novas pessoas ingressando na sua equipe. Para pessoas que nunca viram uma base de código antes, a leitura de testes pode ajudá-las a entender como funciona o código existente.

Por último, mas não menos importante, testes mais automatizados significam menos tempo gasto com controle de qualidade manual, liberando um tempo valioso.

Análise Estática

O primeiro passo para melhorar a qualidade do seu código é começar a usar ferramentas de análise estática. A análise estática verifica se há erros em seu código enquanto você o escreve, mas sem executar nenhum código.

  • Os linters analisam o código para detectar erros comuns, como código não utilizado, e para ajudar a evitar armadilhas, para sinalizar proibições do guia de estilo, como usar tabulações em vez de espaços (ou vice-versa, dependendo da sua configuração).
  • A verificação de tipo garante que a construção que você está passando para uma função corresponde ao que a função foi projetada para aceitar, evitando passar uma string para uma função de contagem que espera um número, por exemplo.

React Native vem com duas dessas ferramentas configuradas imediatamente: ESLint para linting e TypeScript para verificação de tipo.

Escrevendo código testável

Para começar com os testes, primeiro você precisa escrever um código que seja testável. Considere um processo de fabricação de aeronave – antes de qualquer modelo decolar para mostrar que todos os seus sistemas complexos funcionam bem juntos, peças individuais são testadas para garantir que são seguras e funcionam corretamente. Por exemplo, as asas são testadas dobrando-as sob carga extrema; as peças do motor são testadas quanto à sua durabilidade; o pára-brisa é testado contra impacto simulado de pássaros.

O software é semelhante. Em vez de escrever seu programa inteiro em um arquivo enorme com muitas linhas de código, você escreve seu código em vários módulos pequenos que podem ser testados mais detalhadamente do que se você testasse o todo montado. Dessa forma, escrever código testável está interligado com escrever código limpo e modular.

Para tornar seu aplicativo mais testável, comece separando a parte de visualização do seu aplicativo – seus componentes React – da lógica de negócios e do estado do aplicativo (independentemente de você usar Redux, MobX ou outras soluções). Dessa forma, você pode manter seus testes de lógica de negócios – que não devem depender de seus componentes React – independentes dos próprios componentes, cujo trabalho é principalmente renderizar a UI do seu aplicativo!

Teoricamente, você poderia ir tão longe a ponto de remover toda a lógica e a busca de dados de seus componentes. Desta forma, seus componentes seriam exclusivamente dedicados à renderização. Seu estado seria totalmente independente de seus componentes. A lógica do seu aplicativo funcionaria sem nenhum componente React!

Informação

Incentivamos você a explorar ainda mais o tópico de código testável em outros recursos de aprendizagem.

Escrevendo testes

Depois de escrever o código testável, é hora de escrever alguns testes reais! O modelo padrão do React Native vem com a estrutura de teste Jest. Ele inclui uma predefinição adaptada a esse ambiente para que você possa ser produtivo sem ajustar a configuração e as simulações imediatamente. Falaremos mais sobre simulações em breve. Você pode usar o Jest para escrever todos os tipos de testes apresentados neste guia.

Se você faz desenvolvimento orientado a testes, na verdade você escreve os testes primeiro! Dessa forma, é dada a testabilidade do seu código.

Estruturando Testes

Seus testes devem ser curtos e, idealmente, testar apenas uma coisa. Vamos começar com um exemplo de teste de unidade escrito com Jest:

js
it('given a date in the past, colorForDueDate() returns red', () => {
+  expect(colorForDueDate('2000-10-20')).toBe('red');
+});

O teste é descrito pela string passada para a função it. Tome muito cuidado ao escrever a descrição para que fique claro o que está sendo testado. Faça o seu melhor para cobrir o seguinte:

  • Dado - alguma pré-condição
  • Quando - alguma ação executada pela função que você está testando
  • Então - o resultado esperado

Isso também é conhecido como AAA (organizar, agir, afirmar (tradução de: Arrange, Act, Assert).

Jest oferece uma função de descrição/describe para ajudar a estruturar seus testes. Use describe para agrupar todos os testes que pertencem a uma funcionalidade. As descrições podem ser aninhadas, se você precisar. Outras funções que você normalmente usará são beforeEach ou beforeAll, que você pode usar para configurar os objetos que está testando. Leia mais na referência da API Jest.

Se o seu teste tiver muitas etapas ou muitas expectativas, você provavelmente desejará dividi-lo em várias etapas menores. Além disso, certifique-se de que seus testes sejam completamente independentes um do outro. Cada teste em seu conjunto deve ser executável por si só, sem primeiro executar algum outro teste. Por outro lado, se você executar todos os seus testes juntos, o primeiro teste não deverá influenciar o resultado do segundo.

Por último, como desenvolvedores, gostamos quando nosso código funciona bem e não trava. Com os testes, isso geralmente acontece ao contrário. Pense em um teste reprovado como uma coisa boa! Quando um teste falha, muitas vezes significa que algo não está certo. Isso lhe dá a oportunidade de corrigir o problema antes que ele afete os usuários.

Testes Unitários

Os testes unitários cobrem as menores partes do código, como funções ou classes individuais.

Quando o objeto que está sendo testado tiver alguma dependência, muitas vezes você precisará "mockar" ela, conforme descrito no próximo parágrafo.

A grande vantagem dos testes unitários é que eles são rápidos de escrever e executar. Portanto, à medida que você trabalha, você obtém feedback rápido sobre se seus testes estão sendo aprovados. Jest ainda tem a opção de executar continuamente testes relacionados ao código que você está editando: modo Watch.

image

Mock

Às vezes, quando seus objetos testados têm dependências externas, você vai querer “mockar eles”. “Mocking” é quando você substitui alguma dependência do seu código pela sua própria implementação.

Informação

Geralmente, usar objetos reais em seus testes é melhor do que usar mocks, mas há situações em que isso não é possível. Por exemplo: quando seu teste de unidade JS depende de um módulo nativo escrito em Java ou Objective-C.

Imagine que você está escrevendo um aplicativo que mostra o clima atual em sua cidade e está usando algum serviço externo ou outra dependência que fornece informações meteorológicas. Se o serviço informar que está chovendo, você deseja mostrar uma imagem com uma nuvem chuvosa. Você não quer chamar esse serviço em seus testes porque:

  • Poderia tornar os testes lentos e instáveis (devido às solicitações de rede envolvidas)
  • O serviço pode retornar dados diferentes toda vez que você executa o teste
  • Serviços de terceiros podem ficar offline quando você realmente precisa executar testes!

Portanto, você pode fornecer uma implementação simulada do serviço, substituindo efetivamente milhares de linhas de código e alguns termômetros conectados à Internet!

Informação

Jest vem com suporte para simulação desde o nível de função até a simulação em nível de módulo.

Testes de Integração

Ao escrever sistemas de software maiores, suas partes individuais precisam interagir umas com as outras. Em testes unitários, se sua unidade depender de outra, às vezes você acabará mockando a dependência, substituindo-a por uma falsa.

Nos testes de integração, unidades individuais reais são combinadas (da mesma forma que no seu aplicativo) e testadas em conjunto para garantir que sua cooperação funcione conforme o esperado. Isso não quer dizer que a simulação não aconteça aqui: você ainda precisará de simulações (por exemplo, para simular a comunicação com um serviço meteorológico), mas precisará muito menos delas do que em testes unitários.

Informações

Observe que a terminologia sobre o que significa teste de integração nem sempre é consistente. Além disso, a linha entre o que é um teste de unidade e o que é um teste de integração pode nem sempre ser clara. Para este guia, seu teste se enquadra em "teste de integração" se:

  • Combina vários módulos do seu aplicativo conforme descrito acima
  • Usa um sistema externo
  • Faz uma chamada de rede para outro aplicativo (como a API do serviço meteorológico)
  • Qualquer tipo de E/S de arquivo ou banco de dados

image

Testes de Componentes

Os componentes React são responsáveis por renderizar seu aplicativo e os usuários interagirão diretamente com sua saída. Mesmo que a lógica de negócios do seu aplicativo tenha alta cobertura de testes e esteja correta, sem testes de componentes você ainda poderá entregar uma UI quebrada aos seus usuários. Os testes de componentes podem se enquadrar nos testes de unidade e de integração, mas como são uma parte essencial do React Native, iremos abordá-los separadamente.

Para testar os componentes do React, há duas coisas que você pode querer testar:

  • Interação: para garantir que o componente se comporte corretamente quando interagido por um usuário (por exemplo, quando o usuário pressiona um botão)
  • Renderização: para garantir que a saída de renderização do componente usada pelo React esteja correta (por exemplo, a aparência e o posicionamento do botão na UI)

Por exemplo, se você tiver um botão que possui um ouvinte onPress, você deseja testar se o botão aparece corretamente e se o toque no botão é manipulado corretamente pelo componente.

Existem várias bibliotecas que podem ajudá-lo a testá-los:

  • O Test Renderer do React, desenvolvido junto com seu núcleo, fornece um renderizador React que pode ser usado para renderizar componentes React em objetos JavaScript puros, sem depender do DOM ou de um ambiente móvel nativo.
  • A biblioteca de testes React Native é baseada no renderizador de teste do React e adiciona fireEvent e APIs de consulta descritas no próximo parágrafo.

Informações

Os testes de componentes são apenas testes de JavaScript executados no ambiente Node.js. Eles não levam em consideração nenhum código iOS, Android ou outro código de plataforma que suporte os componentes React Native. Conclui-se que eles não podem lhe dar 100% de confiança de que tudo funciona para o usuário. Se houver um bug no código do iOS ou Android, eles não o encontrarão.

image

Testando interações do usuário

Além de renderizar algumas UI, seus componentes lidam com eventos como onChangeText para TextInput ou onPress para Button. Eles também podem conter outras funções e retornos de chamada de eventos. Considere o seguinte exemplo:

jsx
function GroceryShoppingList() {
+  const [groceryItem, setGroceryItem] = useState('');
+  const [items, setItems] = useState<string[]>([]);
+
+  const addNewItemToShoppingList = useCallback(() => {
+    setItems([groceryItem, ...items]);
+    setGroceryItem('');
+  }, [groceryItem, items]);
+
+  return (
+    <>
+      <TextInput
+        value={groceryItem}
+        placeholder="Enter grocery item"
+        onChangeText={text => setGroceryItem(text)}
+      />
+      <Button
+        title="Add the item to list"
+        onPress={addNewItemToShoppingList}
+      />
+      {items.map(item => (
+        <Text key={item}>{item}</Text>
+      ))}
+    </>
+  );
+}

Ao testar as interações do usuário, teste o componente da perspectiva do usuário – o que há na página? O que muda quando interagido?

Como regra geral, prefira usar coisas que os usuários possam ver ou ouvir:

Por outro lado, você deve evitar:

  • fazendo afirmações sobre adereços de componentes ou estado
  • consultas testID

Evite testar detalhes de implementação como adereços ou estado - embora esses testes funcionem, eles não são orientados para como os usuários irão interagir com o componente e tendem a quebrar por refatoração (por exemplo, quando você deseja renomear algumas coisas ou reescrever um componente de classe usando ganchos ).

Informações

Os componentes da classe React são especialmente propensos a testar detalhes de sua implementação, como estado interno, adereços ou manipuladores de eventos. Para evitar testar detalhes de implementação, prefira usar componentes de função com Hooks, o que torna mais difícil confiar nos componentes internos.

Bibliotecas de teste de componentes, como React Native Testing Library, facilitam a escrita de testes centrados no usuário por meio da escolha cuidadosa das APIs fornecidas. O exemplo a seguir usa os métodos fireEvent, changeText e press que simulam um usuário interagindo com o componente e uma função de consulta getAllByText que encontra nós Text correspondentes na saída renderizada.

jsx
test('given empty GroceryShoppingList, user can add an item to it', () => {
+  const {getByPlaceholderText, getByText, getAllByText} = render(
+    <GroceryShoppingList />,
+  );
+
+  fireEvent.changeText(
+    getByPlaceholderText('Enter grocery item'),
+    'banana',
+  );
+  fireEvent.press(getByText('Add the item to list'));
+
+  const bananaElements = getAllByText('banana');
+  expect(bananaElements).toHaveLength(1); // expect 'banana' to be on the list
+});

Este exemplo não está testando como alguns estados mudam quando você chama uma função. Ele testa o que acontece quando um usuário altera o texto no TextInput e pressiona o Button!

Testando saída renderizada

O teste instantâneo é um tipo avançado de teste habilitado pelo Jest. É uma ferramenta muito poderosa e de baixo nível, por isso é aconselhável atenção redobrada ao utilizá-la.

Um "instantâneo de componente" é uma string semelhante a JSX criada por um serializador React personalizado integrado ao Jest. Este serializador permite que Jest traduza árvores de componentes React em strings legíveis por humanos. Dito de outra forma: um snapshot de componente é uma representação textual da saída de renderização do seu componente gerada durante uma execução de teste. Pode ser assim:

jsx
<Text
+  style={
+    Object {
+      "fontSize": 20,
+      "textAlign": "center",
+    }
+  }>
+  Welcome to React Native!
+</Text>

Com o teste de instantâneo, normalmente você primeiro implementa seu componente e depois executa o teste de instantâneo. O teste de instantâneo cria um instantâneo e o salva em um arquivo em seu repositório como um instantâneo de referência. O arquivo é então confirmado e verificado durante a revisão do código. Quaisquer alterações futuras na saída de renderização do componente alterarão seu instantâneo, o que fará com que o teste falhe. Em seguida, você precisa atualizar o instantâneo de referência armazenado para que o teste seja aprovado. Essa mudança novamente precisa ser comprometida e revisada.

Os instantâneos têm vários pontos fracos:

  • Para você, como desenvolvedor ou revisor, pode ser difícil dizer se uma alteração no snapshot é intencional ou se é evidência de um bug. Instantâneos especialmente grandes podem rapidamente tornar-se difíceis de compreender e o seu valor acrescentado torna-se baixo.
  • Quando o instantâneo é criado, nesse ponto ele é considerado correto, mesmo no caso em que a saída renderizada esteja realmente errada.
  • Quando um instantâneo falha, é tentador atualizá-lo usando a opção --updateSnapshot sem tomar o devido cuidado para investigar se a mudança é esperada. Uma certa dose de disciplina do desenvolvedor é, portanto, necessária.

Os instantâneos em si não garantem que a lógica de renderização do seu componente esteja correta, eles são apenas bons para proteger contra mudanças inesperadas e para verificar se os componentes na árvore React em teste recebem os acessórios esperados (estilos e etc.).

Recomendamos que você use apenas snapshots pequenos (consulte a regra de não usar snapshots grandes). Se você quiser testar uma mudança entre dois estados de componentes React, use snapshot-diff. Em caso de dúvida, prefira expectativas explícitas conforme descrito no parágrafo anterior.

image

Testes ponta a ponta

Nos testes ponta a ponta (E2E), você verifica se seu aplicativo está funcionando conforme o esperado em um dispositivo (ou simulador/emulador) da perspectiva do usuário.

Isso é feito criando seu aplicativo na configuração de lançamento e executando os testes nele. Nos testes E2E, você não pensa mais em componentes React, APIs React Native, Redux ou qualquer lógica de negócio. Esse não é o propósito dos testes E2E e eles nem sequer estão acessíveis para você durante os testes E2E.

Em vez disso, as bibliotecas de teste E2E permitem que você encontre e controle elementos na tela do seu aplicativo: por exemplo, você pode tocar em botões ou inserir texto em TextInputs da mesma forma que um usuário real faria. Depois, você pode fazer afirmações sobre se um determinado elemento existe ou não na tela do aplicativo, se está visível ou não, que texto ele contém e assim por diante.

Os testes E2E oferecem a maior confiança possível de que parte do seu aplicativo está funcionando. As compensações incluem:

  • Escrevê-los consome mais tempo em comparação com outros tipos de testes
  • Eles são mais lentos para correr
  • Eles são mais propensos a instabilidade (um teste "instável" é um teste que passa aleatoriamente e falha sem qualquer alteração no código)

Tente cobrir as partes vitais do seu aplicativo com testes E2E: fluxo de autenticação, funcionalidades principais, pagamentos, etc. Use testes JS mais rápidos para as partes não vitais do seu aplicativo. Quanto mais testes você adicionar, maior será sua confiança, mas também mais tempo você gastará para mantê-los e executá-los. Considere as vantagens e desvantagens e decida o que é melhor para você.

Existem várias ferramentas de teste E2E disponíveis: na comunidade React Native, Detox é uma estrutura popular porque é adaptada para aplicativos React Native. Outra biblioteca popular no espaço de aplicativos iOS e Android é Appium ou Maestro.

image

Resumo

Esperamos que você tenha gostado de ler e aprendido algo com este guia. Há muitas maneiras de testar seus aplicativos. Pode ser difícil decidir o que usar no início. No entanto, acreditamos que tudo fará sentido quando você começar a adicionar testes ao seu incrível aplicativo React Native. Então, o que você está esperando? Aumente sua cobertura!

+ + + + \ No newline at end of file diff --git a/vitepress/docs/.vitepress/dist/docs/the-new-architecture/landing-page.html b/vitepress/docs/.vitepress/dist/docs/the-new-architecture/landing-page.html new file mode 100644 index 0000000..cc7d32b --- /dev/null +++ b/vitepress/docs/.vitepress/dist/docs/the-new-architecture/landing-page.html @@ -0,0 +1,100 @@ + + + + + + Sobre a Nova Arquitetura | React Native 0.72 + + + + + + + + + + + + + + + + +
Skip to content

Sobre a Nova Arquitetura

Informações

Se você está procurando os guias da Nova Arquitetura, eles foram transferidos para o grupo de trabalho.

Desde 2018, a equipe do React Native vem redesenhando os principais componentes internos do React Native para permitir que os desenvolvedores criem experiências de maior qualidade. Em 2024, esta versão do React Native foi comprovada em escala e potencializa aplicativos de produção da Meta.

O termo Nova Arquitetura refere-se tanto à nova arquitetura de framework quanto ao trabalho para trazê-la para o código aberto.

A nova arquitetura está disponível para aceitação experimental a partir do React Native 0.68 com melhorias contínuas em cada liberação. A equipe agora está trabalhando para tornar esta a experiência padrão para o ecossistema de código aberto React Native.

Por que uma nova arquitetura?

Depois de muitos anos construindo com React Native, a equipe identificou um conjunto de limitações que impediam os desenvolvedores de criar certas experiências com alto nível de polimento. Essas limitações foram fundamentais para o design existente do framework, então a Nova Arquitetura começou como um investimento no futuro do React Native.

A Nova Arquitetura desbloqueia capacidades e melhorias que eram impossíveis na arquitetura legada.

Layout e efeitos síncronos

Construir experiências de UI adaptáveis ​​geralmente requer medir o tamanho e a posição de suas visualizações e ajustar o layout.

Hoje, você usaria o evento onLayout para obter as informações de layout de uma visualização e fazer quaisquer ajustes. No entanto, as atualizações de estado dentro do retorno de chamada onLayout podem ser aplicadas após pintar a renderização anterior. Isso significa que os usuários podem ver estados intermediários ou saltos visuais entre a renderização do layout inicial e a resposta às medições do layout.

Com a Nova Arquitetura, podemos evitar totalmente esse problema com acesso síncrono às informações de layout e atualizações devidamente programadas, de modo que nenhum estado intermediário fique visível para os usuários.

Exemplo: renderizando uma dica de ferramenta

Medir e colocar uma dica de ferramenta acima de uma visualização nos permite mostrar o que a renderização síncrona desbloqueia. A dica de ferramenta precisa saber a posição de sua visualização de destino para determinar onde ela deve ser renderizada.

Na arquitetura atual, usamos onLayout para obter as medidas da visualização e então atualizar o posicionamento da dica de ferramenta com base em onde a visualização está.

jsx
function ViewWithTooltip() {
+  // ...
+  // Pegamos as informações do layout e passamos para o ToolTip se posicionar
+  const onLayout = React.useCallback(event => {
+    targetRef.current?.measureInWindow((x, y, width, height) => {
+      // Não é garantido que esta atualização de estado seja executada no mesmo commit
+      // Isso resulta em um "salto" visual conforme a dica de ferramenta se reposiciona
+      setTargetRect({x, y, width, height});
+    });
+  }, []);
+
+  return (
+    <>
+      <View ref={targetRef} onLayout={onLayout}>
+        <Text>Some content that renders a tooltip above</Text>
+      </View>
+      <Tooltip targetRect={targetRect} />
+    </>
+  );
+}

Com a Nova Arquitetura, podemos usar useLayoutEffect para medir e aplicar atualizações de layout de forma síncrona em um único commit, evitando o "salto" visual.

jsx
function ViewWithTooltip() {
+  // ...
+
+  useLayoutEffect(() => {
+    // A medição e atualização de estado para `targetRect` acontece em um único commit
+    // permitindo que o ToolTip se posicione sem pinturas intermediárias
+    targetRef.current?.measureInWindow((x, y, width, height) => {
+      setTargetRect({x, y, width, height});
+    });
+  }, [setTargetRect]);
+
+  return (
+    <>
+      <View ref={targetRef}>
+        <Text>Some content that renders a tooltip above</Text>
+      </View>
+      <Tooltip targetRect={targetRect} />
+    </>
+  );
+}
Uma visualização que se move para os cantos da viewport e para o centro com uma dica de ferramenta renderizada acima ou abaixo dela. A dica de ferramenta é renderizada após um pequeno atraso após a visualização se mover
Medição e renderização assíncrona da dica de ferramenta.
Uma visualização que está se movendo para os cantos da janela de visualização e centralizada com uma dica de ferramenta renderizada acima ou abaixo dela. A visualização e a dica se movem em uníssono.
Medição síncrona e renderização da dica de ferramenta.

Suporte para renderização e recursos simultâneos

A nova arquitetura suporta renderização simultânea e recursos fornecidos no React 18 e além. Agora você pode usar recursos como Suspense para busca de dados, Transições e outras novas APIs React em seu código React Native, adaptando ainda mais as bases de código e os conceitos entre o desenvolvimento web e React nativo.

O renderizador simultâneo também traz melhorias prontas para uso, como lote automático, que reduz novas renderizações no React.

Com a nova arquitetura, você obterá lotes automáticos com o renderizador React 18.

Neste exemplo, um controle deslizante especifica quantos blocos serão renderizados. Arrastar o controle deslizante de 0 a 1000 iniciará uma rápida sucessão de atualizações de estado e novas renderizações.

Ao comparar os renderizadores para o mesmo código, você pode notar visualmente que o renderizador fornece uma UI mais suave, com menos atualizações intermediárias da UI. As atualizações de estado de manipuladores de eventos nativos, como este componente Slider nativo, agora são agrupadas em lote.

Uma visualização que se move para os cantos da viewport e para o centro com uma dica de ferramenta renderizada acima ou abaixo dela. A dica de ferramenta é renderizada após um pequeno atraso após a visualização se mover
Renderizando atualizações de estado frequentes com renderizador legado.
Uma visualização que está se movendo para os cantos da janela de visualização e centralizada com uma dica de ferramenta renderizada acima ou abaixo dela. A visualização e a dica se movem em uníssono.
Renderizando atualizações de estado frequentes com o renderizador React 18.

Novos recursos simultâneos, como Transições, permitem expressar a prioridade das atualizações da IU. Marcar uma atualização como de prioridade mais baixa informa ao React que ele pode "interromper" a renderização da atualização para lidar com atualizações de prioridade mais alta para garantir uma experiência de usuário responsiva onde for importante.

Exemplo: Usando startTransition

Podemos aproveitar o exemplo anterior para mostrar como as transições podem interromper a renderização em andamento para lidar com uma atualização de estado mais recente.

Envolvemos a atualização do estado do número do bloco com startTransition para indicar que a renderização dos blocos pode ser interrompida. startTransition também fornece um sinalizador isPending para nos informar quando a transição for concluída.

jsx
function TileSlider({value, onValueChange}) {
+  const [isPending, startTransition] = useTransition();
+
+  return (
+    <>
+      <View>
+        <Text>
+          Render {value} Tiles
+        </Text>
+        <ActivityIndicator animating={isPending} />
+      </View>
+      <Slider
+        value={1}
+        minimumValue={1}
+        maximumValue={1000}
+        step={1}
+        onValueChange={newValue => {
+          startTransition(() => {
+            onValueChange(newValue);
+          });
+        }}
+      />
+    </>
+  );
+}
+
+function ManyTiles() {
+  const [value, setValue] = useState(1);
+  const tiles = generateTileViews(value);
+  return (
+      <TileSlider onValueChange={setValue} value={value} />
+      <View>
+        {tiles}
+      </View>
+  )
+}

Você notará que com as atualizações frequentes em uma transição, o React renderiza menos estados intermediários porque ele deixa de renderizar o estado assim que ele se torna obsoleto. Em comparação, sem transições, mais estados intermediários são renderizados. Ambos os exemplos ainda usam lote automático. Ainda assim, as transições dão ainda mais poder aos desenvolvedores para agrupar renderizações em andamento.

Renderização de blocos com transições para interromper renderizações em andamento de estado obsoleto.
Renderizar blocos sem marcá-los como transição.

JavaScript rápido/interface nativa

A Nova Arquitetura remove a ponte assíncrona entre JavaScript e nativo e a substitui pela Interface JavaScript (JSI). JSI é uma interface que permite ao JavaScript manter uma referência a um objeto C++ e vice-versa. Com uma referência de memória, você pode invocar métodos diretamente sem custos de serialização.

JSI permite que VisionCamera, uma biblioteca de câmeras popular para React Native, processe quadros em tempo real. Os buffers de quadros típicos têm 10 MB, o que equivale a aproximadamente 1 GB de dados por segundo, dependendo da taxa de quadros. Em comparação com os custos de serialização da ponte, o JSI lida com essa quantidade de dados de interface com facilidade. JSI pode expor outros tipos complexos baseados em instâncias, como bancos de dados, imagens, amostras de áudio, etc.

A adoção de JSI na Nova Arquitetura remove essa classe de trabalho de serialização de toda interoperabilidade JavaScript nativa. Isso inclui inicializar e renderizar novamente os componentes principais nativos, como View e Text. Você pode ler mais sobre nossa investigação em desempenho de renderização na Nova Arquitetura e nos benchmarks aprimorados que medimos.

Saber mais

Para conseguir isso, a Nova Arquitetura teve que refatorar várias partes da infraestrutura React Native. Para saber mais sobre o refatorador e outros benefícios que ele traz, confira a documentação no grupo de trabalho Nova Arquitetura.

O que posso esperar ao ativar a Nova Arquitetura?

Embora a Nova Arquitetura habilite esses recursos e melhorias, habilitar a Nova Arquitetura para seu aplicativo ou biblioteca pode não melhorar imediatamente o desempenho ou a experiência do usuário.

Por exemplo, seu código pode precisar de refatoração para aproveitar novos recursos, como efeitos de layout síncronos ou recursos simultâneos. Embora o JSI minimize a sobrecarga entre o JavaScript e a memória nativa, a serialização de dados pode não ter sido um gargalo para o desempenho do seu aplicativo.

Habilitar a Nova Arquitetura em seu aplicativo ou biblioteca é optar pelo futuro do React Native.

A equipe está pesquisando e desenvolvendo ativamente novos recursos que a Nova Arquitetura desbloqueia. Por exemplo, o alinhamento da web é uma área ativa de exploração na Meta que será enviada para o ecossistema de código aberto React Native.

Você pode acompanhar e contribuir em nosso repositório dedicado discussões e propostas.

Devo usar a Nova Arquitetura hoje?

Hoje, a Nova Arquitetura é considerada experimental e continuamos a refinar a compatibilidade com versões anteriores para uma melhor experiência de adoção.

A equipe planeja habilitar a Nova Arquitetura por padrão em uma próxima versão do React Native até o final de 2024.

Nossa orientação é a seguinte

  • Para a maioria dos aplicativos de produção, não recomendamos ativar a Nova Arquitetura hoje. Esperar pelo lançamento oficial oferecerá a melhor experiência.
  • Se você mantém uma biblioteca React Native, recomendamos habilitá-la e verificar se seus casos de uso estão cobertos. Você pode encontrar as instruções aqui.

Habilite a nova arquitetura

Se você estiver interessado em usar a experiência da Nova Arquitetura como dogfood, você pode encontrar instruções em nosso grupo de trabalho dedicado. O grupo de trabalho da Nova Arquitetura é um espaço dedicado para suporte e coordenação para a adoção da Nova Arquitetura e onde a equipe publica atualizações regulares.

+ + + + \ No newline at end of file diff --git a/vitepress/docs/.vitepress/dist/docs/timers.html b/vitepress/docs/.vitepress/dist/docs/timers.html new file mode 100644 index 0000000..699a25b --- /dev/null +++ b/vitepress/docs/.vitepress/dist/docs/timers.html @@ -0,0 +1,33 @@ + + + + + + Temporizadores | React Native 0.72 + + + + + + + + + + + + + + + + +
Skip to content

Temporizadores

Os temporizadores são uma parte importante de um aplicativo e o React Native implementa os temporizadores do navegador.

Temporizadores

  • setTimeout, clearTimeout
  • setInterval, clearInterval
  • setImmediate, clearImmediate
  • requestAnimationFrame, cancelAnimationFrame

requestAnimationFrame(fn) não é o mesmo que setTimeout(fn, 0) - o primeiro será acionado depois que todos os quadros forem liberados, enquanto o último será acionado o mais rápido possível (mais de 1000x por segundo em um iPhone 5S).

setImmediate é executado no final do bloco de execução JavaScript atual, logo antes de enviar a resposta em lote de volta ao nativo. Observe que se você chamar setImmediate dentro de um retorno de chamada setImmediate, ele será executado imediatamente, não retornará ao nativo no meio.

A implementação do Promise usa setImmediate como implementação de assincronicidade.

OBSERVAÇÃO Ao depurar no Android, se os tempos entre o depurador e o dispositivo variaram; coisas como animação, comportamento de eventos, etc., podem não funcionar corretamente ou os resultados podem não ser precisos. Corrija isso executando adb shell "date date +%m%d%H%M%Y.%S%3N" em sua máquina depuradora. O acesso root é necessário para uso em dispositivos reais.

Gerenciador de interação

Uma razão pela qual aplicativos nativos bem construídos parecem tão suaves é que evitam operações caras durante interações e animações. No React Native, atualmente temos uma limitação de que há apenas um único thread de execução JS, mas você pode usar o InteractionManager para garantir que o trabalho de longa execução seja programado para começar após a conclusão de quaisquer interações/animações.

Os aplicativos podem agendar tarefas para execução após interações como o seguinte:

js
InteractionManager.runAfterInteractions(() => {
+  // ...tarefa síncrona de longa duração...
+});

Compare isso com outras alternativas de agendamento:

  • requestAnimationFrame(): para código que anima uma visualização ao longo do tempo.
  • setImmediate/setTimeout/setInterval(): execute o código mais tarde, observe que isso pode atrasar as animações.
  • runAfterInteractions(): executa o código posteriormente, sem atrasar as animações ativas.

O sistema de tratamento de toque considera um ou mais toques ativos como uma 'interação' e atrasará os retornos de chamada runAfterInteractions() até que todos os toques tenham terminado ou sejam cancelados.

O InteractionManager também permite que aplicativos registrem animações criando um 'identificador' de interação no início da animação e limpando-o após a conclusão:

js
const handle = InteractionManager.createInteractionHandle();
+// executar animação... (as tarefas `runAfterInteractions` estão na fila)
+// mais tarde, na conclusão da animação:
+InteractionManager.clearInteractionHandle(handle);
+// tarefas enfileiradas serão executadas se todos os identificadores forem apagados
+ + + + \ No newline at end of file diff --git a/vitepress/docs/.vitepress/dist/docs/troubleshooting.html b/vitepress/docs/.vitepress/dist/docs/troubleshooting.html new file mode 100644 index 0000000..ea2e05a --- /dev/null +++ b/vitepress/docs/.vitepress/dist/docs/troubleshooting.html @@ -0,0 +1,35 @@ + + + + + + Solução de problemas | React Native 0.72 + + + + + + + + + + + + + + + + +
Skip to content

Solução de problemas

Estes são alguns problemas comuns que você pode encontrar ao configurar o React Native. Se você encontrar algo que não esteja listado aqui, tente pesquisar o problema no GitHub.

Porta já em uso (Port already in use)

O empacotador Metro é executado na porta 8081. Se outro processo já estiver usando essa porta, você poderá encerrar esse processo ou alterar a porta que o empacotador usa.

Encerrando um processo na porta 8081

Execute o seguinte comando para encontrar o ID do processo que está escutando na porta 8081:

bash
sudo lsof -i :8081

Em seguida, execute o seguinte para encerrar o processo:

bash
kill -9 <PID>

No Windows você pode encontrar o processo usando a porta 8081 usando o Monitor de Recursos e interrompê-lo usando o Gerenciador de Tarefas.

Usando uma porta diferente de 8081

Você pode configurar o bundler para usar uma porta diferente de 8081 usando o parâmetro port, na raiz da execução do seu projeto:

bash
npm start -- --port=8088
bash
yarn start --port 8088

Você também precisará atualizar seus aplicativos para carregar o pacote JavaScript da nova porta. Se estiver executando no dispositivo do Xcode, você pode fazer isso atualizando as ocorrências de 8081 para a porta escolhida no arquivo ios/__App_Name__.xcodeproj/project.pbxproj.

Erro de bloqueio NPM

Se você encontrar um erro como npm WARN locking Error: EACCES ao usar o React Native CLI, tente executar o seguinte:

bash
sudo chown -R $USER ~/.npm
+sudo chown -R $USER /usr/local/lib/node_modules

Bibliotecas ausentes para React

Se você adicionou React Native manualmente ao seu projeto, certifique-se de ter incluído todas as dependências relevantes que está usando, como RCTText.xcodeproj, RCTImage.xcodeproj. Em seguida, os binários criados por essas dependências devem ser vinculados ao binário do seu aplicativo. Use a seção Linked Frameworks and Binaries nas configurações do projeto Xcode. Etapas mais detalhadas estão aqui: Vinculando Bibliotecas.

Se você estiver usando CocoaPods, verifique se adicionou React junto com as subespecificações ao Podfile. Por exemplo, se você estivesse usando as APIs <Text />, <Image /> e fetch(), você precisaria adicioná-las em seu Podfile:

pod 'React', :path => '../node_modules/react-native', :subspecs => [
+  'RCTText',
+  'RCTImage',
+  'RCTNetwork',
+  'RCTWebSocket',
+]

Em seguida, certifique-se de ter executado pod install e de que um diretório Pods/ tenha sido criado em seu projeto com o React instalado. CocoaPods irá instruí-lo a usar o arquivo .xcworkspace gerado daqui em diante para poder usar essas dependências instaladas.

React Native não compila ao ser usado como CocoaPod

Existe um plugin CocoaPods chamado cocoapods-fix-react-native que lida com qualquer possível pós-correção do código-fonte devido a diferenças ao usar um gerenciador de dependências.

Lista de argumentos muito longa: falha na expansão do cabeçalho recursivo

Nas configurações de construção do projeto, User Search Header Paths e Header Search Paths são duas configurações que especificam onde o Xcode deve procurar os arquivos de cabeçalho #import especificados no código. Para pods, CocoaPods usa uma matriz padrão de pastas específicas para procurar. Verifique se essa configuração específica não foi substituída e se nenhuma das pastas configuradas é muito grande. Se uma das pastas for grande, o Xcode tentará pesquisar recursivamente o diretório inteiro e gerará o erro acima em algum momento.

Para reverter as configurações de compilação dos User Search Header PathseHeader Search Paths` para seus padrões definidos pelo CocoaPods - selecione a entrada no painel Build Settings e clique em excluir. Isso removerá a substituição personalizada e retornará aos padrões do CocoaPod.

Não há transportes disponíveis

React Native implementa um polyfill para WebSockets. Esses polyfills são inicializados como parte do módulo react-native que você inclui em seu aplicativo por meio do import React from 'react'. Se você carregar outro módulo que requer WebSockets, como Firebase, certifique-se de carregá-lo/solicitá-lo após o React Native:

jsx
import React from 'react';
+import Firebase from 'firebase';

Exceção sem resposta do comando Shell

Se você encontrar uma exceção ShellCommandUnresponsiveException como:

Execution failed for task ':app:installDebug'.
+  com.android.builder.testing.api.DeviceException: com.android.ddmlib.ShellCommandUnresponsiveException

Tente fazer o downgrade da sua versão do Gradle para 1.2.3 em android/build.gradle.

inicialização travada do react-native

Se você tiver problemas em que a execução do npx react-native init trava em seu sistema, tente executá-lo novamente no modo detalhado e consulte #2797 para causas comuns:

bash
npx react-native init --verbose

Quando você está depurando um processo ou precisa saber um pouco mais sobre o erro que está sendo gerado, você pode querer usar a opção detalhada para gerar mais logs e informações para resolver seu problema.

Execute o seguinte comando no diretório raiz do seu projeto.

npm
bash
npm run android -- --verbose
yarn
bash
yarn android --verbose

Não é possível iniciar o gerenciador de pacotes react-native (no Linux)

Caso 1: Erro "código":"ENOSPC","errno":"ENOSPC"

Problema causado pelo número de diretórios que o inotify (usado pelo watchman no Linux) pode monitorar. Para resolver isso, execute este comando na janela do seu terminal:

bash
echo fs.inotify.max_user_watches=582222 | sudo tee -a /etc/sysctl.conf && sudo sysctl -p

Error: spawnSync ./gradlew EACCES

Se você tiver um problema em que a execução do npm run android ou yarn android no macOS gera o erro acima, tente executar o comando sudo chmod +x android/gradlew para tornar os arquivos gradlew em executáveis.

+ + + + \ No newline at end of file diff --git a/vitepress/docs/.vitepress/dist/docs/typescript.html b/vitepress/docs/.vitepress/dist/docs/typescript.html new file mode 100644 index 0000000..6ecb683 --- /dev/null +++ b/vitepress/docs/.vitepress/dist/docs/typescript.html @@ -0,0 +1,120 @@ + + + + + + Usando TypeScript | React Native 0.72 + + + + + + + + + + + + + + + + +
Skip to content

Usando TypeScript

TypeScript é uma linguagem que estende JavaScript adicionando definições de tipo. Novos projetos React Native são direcionados ao TypeScript por padrão, mas também oferecem suporte a JavaScript e Flow.

Introdução ao TypeScript

Novos projetos criados pela CLI React Native ou modelos populares como Ignite usarão TypeScript por padrão.

O TypeScript também pode ser usado com o Expo, que mantém modelos TypeScript, ou solicitará que você instale e configure automaticamente o TypeScript quando um arquivo .ts ou .tsx for adicionado ao seu projeto.

bash
npx create-expo-app --template

Adicionando TypeScript a um projeto existente

  1. Adicione plug-ins TypeScript, tipos e ESLint ao seu projeto.
bash
npm install -D @tsconfig/react-native @types/jest @types/react @types/react-test-renderer typescript
bash
yarn add --dev @tsconfig/react-native @types/jest @types/react @types/react-test-renderer typescript

OBSERVAÇÃO

Este comando adiciona a versão mais recente de cada dependência. As versões podem precisar ser alteradas para corresponder aos pacotes existentes usados pelo seu projeto. Você pode usar uma ferramenta como React Native Upgrade Helper para ver as versões fornecidas pelo React Native.

  1. Adicione um arquivo de configuração TypeScript. Crie um tsconfig.json na raiz do seu projeto:
json
{
+  "extends": "@tsconfig/react-native/tsconfig.json"
+}
  1. Renomeie um arquivo JavaScript para *.tsx

ATENÇÃO

Você deve deixar o arquivo de ponto de entrada ./index.js como está, caso contrário, poderá ter problemas ao agrupar uma construção de produção.

  1. Execute o yarn tsc para verificar o tipo de seus novos arquivos TypeScript.

Usando JavaScript em vez de TypeScript

O React Native padroniza novos aplicativos para TypeScript, mas JavaScript ainda pode ser usado. Arquivos com extensão .jsx são tratados como JavaScript em vez de TypeScript e não serão verificados. Módulos JavaScript ainda podem ser importados por módulos TypeScript, junto com o inverso.

Como funcionam o TypeScript e o React Native

Pronto para uso, os códigos TypeScript são transformados pelo Babel durante o empacotamento. Recomendamos que você use o compilador TypeScript apenas para verificação de tipo. Este é o comportamento padrão do tsc para aplicativos recém-criados. Se você tiver código TypeScript existente sendo portado para React Native, há uma ou duas advertências ao usar Babel em vez de TypeScript.

Qual é a aparência do React Native + TypeScript

Você pode fornecer uma interface para Props e State de um componente React via React.Component<Props, State> que fornecerá verificação de tipo e preenchimento automático do editor ao trabalhar com esse componente em JSX.

tsx
// components/Hello.tsx
+
+import React from 'react';
+import {Button, StyleSheet, Text, View} from 'react-native';
+
+export type Props = {
+  name: string;
+  baseEnthusiasmLevel?: number;
+};
+
+const Hello: React.FC<Props> = ({
+  name,
+  baseEnthusiasmLevel = 0,
+}) => {
+  const [enthusiasmLevel, setEnthusiasmLevel] = React.useState(
+    baseEnthusiasmLevel,
+  );
+
+  const onIncrement = () =>
+    setEnthusiasmLevel(enthusiasmLevel + 1);
+  const onDecrement = () =>
+    setEnthusiasmLevel(
+      enthusiasmLevel > 0 ? enthusiasmLevel - 1 : 0,
+    );
+
+  const getExclamationMarks = (numChars: number) =>
+    numChars > 0 ? Array(numChars + 1).join('!') : '';
+
+  return (
+    <View style={styles.container}>
+      <Text style={styles.greeting}>
+        Hello {name}
+        {getExclamationMarks(enthusiasmLevel)}
+      </Text>
+      <View>
+        <Button
+          title="Increase enthusiasm"
+          accessibilityLabel="increment"
+          onPress={onIncrement}
+          color="blue"
+        />
+        <Button
+          title="Decrease enthusiasm"
+          accessibilityLabel="decrement"
+          onPress={onDecrement}
+          color="red"
+        />
+      </View>
+    </View>
+  );
+};
+
+const styles = StyleSheet.create({
+  container: {
+    flex: 1,
+    alignItems: 'center',
+    justifyContent: 'center',
+  },
+  greeting: {
+    fontSize: 20,
+    fontWeight: 'bold',
+    margin: 16,
+  },
+});
+
+export default Hello;

Você pode explorar mais a sintaxe no playground TypeScript.

Onde encontrar conselhos úteis

Usando aliases de caminho personalizados com TypeScript

Para usar aliases de caminho personalizados com TypeScript, você precisa definir os aliases de caminho para funcionarem tanto no Babel quanto no TypeScript. Veja como:

  1. Edite seu tsconfig.json para ter seus mapeamentos de caminho personalizados. Defina qualquer coisa na raiz de src para estar disponível sem nenhuma referência de caminho anterior e permita que qualquer arquivo de teste seja acessado usando tests/File.tsx:
{
+  "extends": "@tsconfig/react-native/tsconfig.json"
+  "extends": "@tsconfig/react-native/tsconfig.json",
+  "compilerOptions": {
+    "baseUrl": ".",
+    "paths": {
+      "*": ["src/*"],
+      "tests": ["tests/*"],
+      "@components/*": ["src/components/*"],
+    },
+  }
+}

Adicione babel-plugin-module-resolver como um pacote de desenvolvimento ao seu projeto:

bash
npm install --save-dev babel-plugin-module-resolver
bash
yarn add --dev babel-plugin-module-resolver

Por fim, configure seu babel.config.js (observe que a sintaxe do seu babel.config.js é diferente do seu tsconfig.json):

json
{
+  presets: ['module:metro-react-native-babel-preset'],
+  plugins: [ 
+    [ 
+        'module-resolver', 
+        { 
+          root: ['./src'], 
+          extensions: ['.ios.js', '.android.js', '.js', '.ts', '.tsx', '.json'], 
+          alias: { 
+          tests: ['./tests/'], 
+          "@components": "./src/components", 
+        } 
+      } 
+    ] 
+  ] 
+}
+ + + + \ No newline at end of file diff --git a/vitepress/docs/.vitepress/dist/docs/upgrading.html b/vitepress/docs/.vitepress/dist/docs/upgrading.html new file mode 100644 index 0000000..917d96f --- /dev/null +++ b/vitepress/docs/.vitepress/dist/docs/upgrading.html @@ -0,0 +1,50 @@ + + + + + + Atualizando para novas versões | React Native 0.72 + + + + + + + + + + + + + + + + +
Skip to content

Atualizando para novas versões

A atualização para novas versões do React Native lhe dará acesso a mais APIs, visualizações, ferramentas de desenvolvedor e outras vantagens. A atualização requer um pouco de esforço, mas tentamos torná-la simples para você.

Projetos de expo

Atualizar seu projeto Expo para uma nova versão do React Native requer a atualização das versões dos pacotes react-native, react e expo em seu arquivo package.json. Expo fornece um comando de atualização para lidar com a atualização dessas e de quaisquer outras dependências conhecidas para você. Consulte o passo a passo de atualização do Expo SDK para obter informações atualizadas sobre como atualizar seu projeto.

Projetos React Native

Como os projetos típicos do React Native são essencialmente compostos de um projeto Android, um projeto iOS e um projeto JavaScript, a atualização pode ser bastante complicada. Atualmente, existem duas maneiras de atualizar seu projeto React Native: usando React Native CLI ou manualmente com Upgrade Helper.

CLI React Native

O React Native CLI vem com o comando upgrade que fornece uma operação de uma etapa para atualizar os arquivos de origem com um mínimo de conflitos. Ele usa internamente o projeto rn-diff-purge para descobrir quais arquivos precisam ser criados, removidos ou modificados.

1. Execute o comando upgrade

DICA

O comando upgrade funciona em cima do Git usando git apply com mesclagem de 3 vias, portanto é necessário usar o Git para que isso funcione, se você não usa o Git, mas ainda deseja usar esta solução, você pode verificar como fazer isso na seção Solução de problemas nesta página.

Execute o seguinte comando para iniciar o processo de atualização para a versão mais recente:

bash
npx react-native upgrade

Você pode especificar uma versão do React Native passando um argumento, por exemplo. para atualizar para 0.61.0-rc.0 execute:

bash
npx react-native upgrade 0.61.0-rc.0

O projeto é atualizado usando git apply com mesclagem de 3 vias, pode acontecer que você precise resolver alguns conflitos após terminar.

2. Resolva os conflitos

Os arquivos em conflito incluem delimitadores que deixam bem claro de onde vêm as alterações. Por exemplo:

13B07F951A680F5B00A75B9A /* Release */ = {
+  isa = XCBuildConfiguration;
+  buildSettings = {
+    ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
+<<<<<<< ours
+    CODE_SIGN_IDENTITY = "iPhone Developer";
+    FRAMEWORK_SEARCH_PATHS = (
+      "$(inherited)",
+      "$(PROJECT_DIR)/HockeySDK.embeddedframework",
+      "$(PROJECT_DIR)/HockeySDK-iOS/HockeySDK.embeddedframework",
+    );
+=======
+    CURRENT_PROJECT_VERSION = 1;
+>>>>>>> theirs
+    HEADER_SEARCH_PATHS = (
+      "$(inherited)",
+      /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/include,
+      "$(SRCROOT)/../node_modules/react-native/React/**",
+      "$(SRCROOT)/../node_modules/react-native-code-push/ios/CodePush/**",
+    );

Você pode pensar em "ours" como "sua equipe" e "theirs" como "a equipe de desenvolvimento do React Native".

Ajudante de atualização

O Upgrade Helper é uma ferramenta da web para ajudá-lo na atualização de seus aplicativos, fornecendo o conjunto completo de alterações que ocorrem entre duas versões. Ele também mostra comentários sobre arquivos específicos para ajudar a entender por que essa alteração é necessária.

1. Selecione as versões

Primeiro você precisa selecionar para qual versão deseja atualizar; por padrão, as versões principais mais recentes são selecionadas. Após selecionar você pode clicar no botão "Mostre-me como atualizar".

DICA

as principais atualizações mostrarão uma seção de "useful content" (conteúdo útil) na parte superior com links para ajudá-lo durante a atualização.

2. Atualizar dependências

O primeiro arquivo que aparece é o package.json, é bom atualizar as dependências que estão aparecendo nele. Por exemplo, se react-native e react aparecerem como alterações, você poderá instalá-lo em seu projeto executando yarn add:

bash
# {{VERSION}} e {{REACT_VERSION}} são as versões de lançamento mostradas na comparação
+yarn add react-native@{{VERSION}}
+yarn add react@{{REACT_VERSION}}

3. Atualize seus arquivos de projeto

A nova versão pode conter atualizações para outros arquivos que são gerados quando você executa o npx react-native init. Esses arquivos são listados após package.json na página do Upgrade Helper. Se não houver outras alterações, você só precisará reconstruir o projeto para continuar o desenvolvimento.

Caso haja alterações, você pode atualizá-las manualmente, copiando e colando as alterações na página ou pode fazer isso com o comando de atualização React Native CLI executando:

bash
npx react-native upgrade

Isso verificará seus arquivos em relação ao modelo mais recente e executará o seguinte:

  • Se houver um novo arquivo no modelo, ele será criado.
  • Se um arquivo no modelo for idêntico ao seu arquivo, ele será ignorado.
  • Se um arquivo em seu projeto for diferente do modelo, você será avisado; você tem opções para manter seu arquivo ou substituí-lo pela versão do modelo.

INFORMAÇÕES

Algumas atualizações não serão feitas automaticamente com o React Native CLI e requerem trabalho manual, por exemplo. 0.28 a 0.29 ou 0.56 a 0.57. Certifique-se de verificar as notas de versão ao atualizar para poder identificar quaisquer alterações manuais que seu projeto específico possa exigir.

Solução de problemas

Quero atualizar com React Native CLI, mas não uso Git

Embora seu projeto não precise ser gerenciado pelo sistema de versionamento Git - você pode usar Mercurial, SVN ou nada - você ainda precisará instalar o Git em seu sistema para usar o npx react-native upgrade. O Git também precisará estar disponível no PATH. Se o seu projeto não usa Git, inicialize-o e faça o commit:

bash
git init # Inicialize um repositório Git
+git add . # Prepare todos os arquivos atuais
+git commit -m "Upgrade react-native" # Salva os arquivos atuais em um commit

Depois de terminar a atualização, você pode remover o diretório .git.

Fiz todas as alterações, mas meu aplicativo ainda usa uma versão antiga

Esses tipos de erros geralmente estão relacionados ao cache, é recomendado instalar o react-native-clean-project para limpar todo o cache do seu projeto e então você pode executá-lo novamente.

+ + + + \ No newline at end of file diff --git a/vitepress/docs/.vitepress/dist/docs/using-a-listview.html b/vitepress/docs/.vitepress/dist/docs/using-a-listview.html new file mode 100644 index 0000000..bbcdc98 --- /dev/null +++ b/vitepress/docs/.vitepress/dist/docs/using-a-listview.html @@ -0,0 +1,117 @@ + + + + + + Usando List View | React Native 0.72 + + + + + + + + + + + + + + + + +
Skip to content

Usando List View

React Native fornece um conjunto de componentes para apresentar listas de dados. Geralmente, você desejará usar FlatList ou SectionList.

O componente FlatList exibe uma lista de rolagem de dados alterados, mas estruturados de forma semelhante. FlatList funciona bem para longas listas de dados, onde o número de itens pode mudar com o tempo. Ao contrário do ScrollView mais genérico, o FlatList renderiza apenas os elementos que estão sendo exibidos na tela no momento, e não todos os elementos de uma vez.

O componente FlatList requer dois props: data e renderItem. data é a fonte de informações da lista. renderItem pega um item da fonte e retorna um componente formatado para renderizar.

Este exemplo cria uma FlatList básica de dados codificados. Cada item nas propriedades de dados é renderizado como um componente Text. O componente FlatListBasics renderiza FlatList e todos os componentes Text.

jsx
import React from 'react';
+import {FlatList, StyleSheet, Text, View} from 'react-native';
+
+const styles = StyleSheet.create({
+  container: {
+    flex: 1,
+    paddingTop: 22,
+  },
+  item: {
+    padding: 10,
+    fontSize: 18,
+    height: 44,
+  },
+});
+
+const FlatListBasics = () => {
+  return (
+    <View style={styles.container}>
+      <FlatList
+        data={[
+          {key: 'Devin'},
+          {key: 'Dan'},
+          {key: 'Dominic'},
+          {key: 'Jackson'},
+          {key: 'James'},
+          {key: 'Joel'},
+          {key: 'John'},
+          {key: 'Jillian'},
+          {key: 'Jimmy'},
+          {key: 'Julie'},
+        ]}
+        renderItem={({item}) => <Text style={styles.item}>{item.key}</Text>}
+      />
+    </View>
+  );
+};
+
+export default FlatListBasics;

image

Se você deseja renderizar um conjunto de dados divididos em seções lógicas, talvez com cabeçalhos de seção, semelhante ao UITableViews no iOS, então um SectionList é o caminho a percorrer.

jsx
import React from 'react';
+import {SectionList, StyleSheet, Text, View} from 'react-native';
+
+const styles = StyleSheet.create({
+  container: {
+    flex: 1,
+    paddingTop: 22,
+  },
+  sectionHeader: {
+    paddingTop: 2,
+    paddingLeft: 10,
+    paddingRight: 10,
+    paddingBottom: 2,
+    fontSize: 14,
+    fontWeight: 'bold',
+    backgroundColor: 'rgba(247,247,247,1.0)',
+  },
+  item: {
+    padding: 10,
+    fontSize: 18,
+    height: 44,
+  },
+});
+
+const SectionListBasics = () => {
+  return (
+    <View style={styles.container}>
+      <SectionList
+        sections={[
+          {title: 'D', data: ['Devin', 'Dan', 'Dominic']},
+          {
+            title: 'J',
+            data: [
+              'Jackson',
+              'James',
+              'Jillian',
+              'Jimmy',
+              'Joel',
+              'John',
+              'Julie',
+            ],
+          },
+        ]}
+        renderItem={({item}) => <Text style={styles.item}>{item}</Text>}
+        renderSectionHeader={({section}) => (
+          <Text style={styles.sectionHeader}>{section.title}</Text>
+        )}
+        keyExtractor={item => `basicListEntry-${item}`}
+      />
+    </View>
+  );
+};
+
+export default SectionListBasics;

image

Um dos usos mais comuns de uma exibição de lista é exibir dados que você busca em um servidor. Para fazer isso, você precisará aprender sobre redes no React Native.

+ + + + \ No newline at end of file diff --git a/vitepress/docs/.vitepress/dist/docs/using-a-scrollview.html b/vitepress/docs/.vitepress/dist/docs/using-a-scrollview.html new file mode 100644 index 0000000..5f3327f --- /dev/null +++ b/vitepress/docs/.vitepress/dist/docs/using-a-scrollview.html @@ -0,0 +1,72 @@ + + + + + + Usando um ScrollView | React Native 0.72 + + + + + + + + + + + + + + + + +
Skip to content

Usando um ScrollView

O ScrollView é um contêiner de rolagem genérico que pode conter vários componentes e visualizações. Os itens roláveis podem ser heterogêneos e você pode rolar vertical e horizontalmente (definindo a propriedade horizontal).

Este exemplo cria um ScrollView vertical com imagens e texto misturados.

jsx
import React from 'react';
+import {Image, ScrollView, Text} from 'react-native';
+
+const logo = {
+  uri: 'https://reactnative.dev/img/tiny_logo.png',
+  width: 64,
+  height: 64,
+};
+
+const App = () => (
+  <ScrollView>
+    <Text style={{fontSize: 96}}>Scroll me plz</Text>
+    <Image source={logo} />
+    <Image source={logo} />
+    <Image source={logo} />
+    <Image source={logo} />
+    <Image source={logo} />
+    <Text style={{fontSize: 96}}>If you like</Text>
+    <Image source={logo} />
+    <Image source={logo} />
+    <Image source={logo} />
+    <Image source={logo} />
+    <Image source={logo} />
+    <Text style={{fontSize: 96}}>Scrolling down</Text>
+    <Image source={logo} />
+    <Image source={logo} />
+    <Image source={logo} />
+    <Image source={logo} />
+    <Image source={logo} />
+    <Text style={{fontSize: 96}}>What's the best</Text>
+    <Image source={logo} />
+    <Image source={logo} />
+    <Image source={logo} />
+    <Image source={logo} />
+    <Image source={logo} />
+    <Text style={{fontSize: 96}}>Framework around?</Text>
+    <Image source={logo} />
+    <Image source={logo} />
+    <Image source={logo} />
+    <Image source={logo} />
+    <Image source={logo} />
+    <Text style={{fontSize: 80}}>React Native</Text>
+  </ScrollView>
+);
+
+export default App;

ScrollViews pode ser configurado para permitir a paginação através de visualizações usando gestos de deslizar com os props pagingEnabled. Deslizar horizontalmente entre visualizações também pode ser implementado no Android usando o componente ViewPager.

No iOS, um ScrollView com um único item pode ser usado para permitir ao usuário ampliar o conteúdo. Configure os props maximumZoomScale e minimumZoomScale e seu usuário poderá usar gestos de pinçar e expandir para aumentar e diminuir o zoom.

O ScrollView funciona melhor para apresentar um pequeno número de coisas de tamanho limitado. Todos os elementos e visualizações de um ScrollView são renderizados, mesmo que não sejam mostrados na tela no momento. Se você tiver uma longa lista de itens que não cabem na tela, você deve usar uma FlatList. Então, vamos aprender sobre as visualizações de lista a seguir.

+ + + + \ No newline at end of file diff --git a/vitepress/docs/.vitepress/dist/docs/using-hermes.html b/vitepress/docs/.vitepress/dist/docs/using-hermes.html new file mode 100644 index 0000000..7865194 --- /dev/null +++ b/vitepress/docs/.vitepress/dist/docs/using-hermes.html @@ -0,0 +1,46 @@ + + + + + + Usando o Hermes | React Native 0.72 + + + + + + + + + + + + + + + + +
Skip to content

Usando o Hermes

Hermes é um mecanismo JavaScript de código aberto otimizado para React Native. Para muitos aplicativos, o uso do Hermes resultará em melhor tempo de inicialização, menor uso de memória e tamanho menor do aplicativo quando comparado ao JavaScriptCore. Hermes é usado por padrão pelo React Native e nenhuma configuração adicional é necessária para habilitá-lo.

Pacote Hermes

React Native vem com uma versão integrada do Hermes. Estaremos construindo uma versão do Hermes para você sempre que lançarmos uma nova versão do React Native. Isso garantirá que você esteja consumindo uma versão do Hermes totalmente compatível com a versão do React Native que você está usando.

Historicamente, tivemos problemas ao combinar versões do Hermes com versões do React Native. Isso elimina totalmente esse problema e oferece aos usuários um mecanismo JS compatível com a versão específica do React Native.

Esta mudança é totalmente transparente para os usuários do React Native. Você ainda pode desativar o Hermes usando o comando descrito nesta página. Você pode ler mais sobre a implementação técnica nesta página.

Confirmando que Hermes está em uso

Se você criou recentemente um novo aplicativo do zero, deverá ver se o Hermes está ativado na visualização de boas-vindas:

image

Uma variável global HermesInternal estará disponível em JavaScript que pode ser usada para verificar se o Hermes está em uso:

js
const isHermes = () => !!global.HermesInternal;

CUIDADO

Se você estiver usando uma forma não padrão de carregar o pacote JS, é possível que a variável HermesInternal esteja disponível, mas você não esteja usando o bytecode pré-compilado altamente otimizado. Confirme se você está usando o arquivo .hbc e também compare o antes/depois conforme detalhado abaixo.

Para ver os benefícios do Hermes, tente fazer uma versão build/implantação do seu aplicativo para comparar. Por exemplo; da raiz do seu projeto:

Android

bash
npm run android -- --mode="release"
bash
yarn android --mode release

iOS

bash
npm run ios -- --mode="Release"
bash
yarn ios --mode Release

Isso compilará o JavaScript em bytecode durante o tempo de construção, o que melhorará a velocidade de inicialização do seu aplicativo no dispositivo.

Depurando JS no Hermes usando DevTools do Google Chrome

Hermes oferece suporte ao depurador do Chrome implementando o protocolo do inspetor do Chrome. Isso significa que as ferramentas do Chrome podem ser usadas para depurar diretamente o JavaScript em execução no Hermes, em um emulador ou em um dispositivo físico real.

INFORMAÇÕES

Observe que isso é muito diferente da "Depuração remota de JS" do menu de desenvolvimento no aplicativo documentado na seção Depuração, que na verdade executa o código JS no V8 do Chrome em sua máquina de desenvolvimento (laptop ou desktop).

O Chrome se conecta ao Hermes em execução no dispositivo via Metro, então você precisa saber onde o Metro está ouvindo. Normalmente, isso estará em localhost:8081, mas é configurável. Ao executar o yarn start, o endereço é gravado em stdout na inicialização.

Depois de saber onde o servidor Metro está escutando, você pode conectar-se ao Chrome seguindo as seguintes etapas:

  1. Navegue para chrome://inspect em uma instância do navegador Chrome.
  2. Use o botão Configure... para adicionar o endereço do servidor Metro (normalmente localhost:8081 conforme descrito acima).
  1. Agora você deve ver um alvo "Hermes React Native" com um link "inspecionar" que pode ser usado para abrir o depurador. Se você não vir o link “inspect”, certifique-se de que o servidor Metro esteja em execução.
  1. Agora você pode usar as ferramentas de depuração do Chrome. Por exemplo, para fazer um ponto de interrupção na próxima vez que algum JavaScript for executado, clique no botão de pausa e acione uma ação em seu aplicativo que faria com que o JavaScript fosse executado.

Habilitando Hermes em versões mais antigas do React Native

Hermes é o mecanismo padrão no React Native 0.70. Esta seção explica como habilitar o Hermes em versões mais antigas do React Native. Primeiro, certifique-se de usar pelo menos a versão 0.60.4 do React Native para habilitar o Hermes no Android ou 0.64 do React Native para habilitar o Hermes no iOS.

Se você já possui um aplicativo baseado em uma versão anterior do React Native, você terá que atualizá-lo primeiro. Consulte Atualizando para novas versões do React Native para saber como fazer isso. Depois de atualizar o aplicativo, certifique-se de que tudo funciona antes de tentar mudar para o Hermes.

NOTA PARA COMPATIBILIDADE REACT NATIVE

Cada lançamento da Hermes é direcionado a uma versão RN específica. A regra é sempre seguir rigorosamente os lançamentos do Hermes. A incompatibilidade de versão pode resultar na falha instantânea de seus aplicativos na pior das hipóteses.

NOTA PARA USUÁRIOS DO WINDOWS

Hermes requer Microsoft Visual C++ 2015 Redistributable.

Android

Edite seu arquivo android/gradle.properties e certifique-se de que hermesEnabled seja verdadeiro:

# Use esta propriedade para ativar ou desativar o mecanismo Hermes JS.
+# Se definido como falso, você usará JSC.
+hermesEnabled=true

OBSERVAÇÃO

Esta propriedade foi adicionada no React Native 0.71. Se você não conseguir encontrá-lo em seu arquivo gradle.properties, consulte a documentação da versão correspondente do React Native que você está usando.

Além disso, se estiver usando o ProGuard, você precisará adicionar estas regras em proguard-rules.pro:

-keep class com.facebook.hermes.unicode.** { *; }
+-keep class com.facebook.jni.** { *; }

A seguir, se você já criou seu aplicativo pelo menos uma vez, limpe a compilação:

bash
cd android && ./gradlew clean

É isso! Agora você deve conseguir desenvolver e implantar seu aplicativo normalmente:

bash
npm run android
bash
yarn android

iOS

Desde o React Native 0.64, o Hermes também roda em iOS. Para habilitar o Hermes para iOS, edite seu arquivo ios/Podfile e faça a alteração ilustrada abaixo:

   use_react_native!(
+     :path => config[:reactNativePath],
+     # to enable hermes on iOS, change `false` to `true` and then install pods
+     # By default, Hermes is disabled on Old Architecture, and enabled on New Architecture.
+     # You can enable/disable it manually by replacing `flags[:hermes_enabled]` with `true` or `false`.
+-    :hermes_enabled => flags[:hermes_enabled],
++    :hermes_enabled => true
+   )

Por padrão, você usará Hermes se estiver na Nova Arquitetura. Ao especificar um valor como true ou false, você pode ativar/desativar o Hermes como desejar.

Depois de configurá-lo, você pode instalar os pods Hermes com:

bash
cd ios && pod install

É isso! Agora você deve conseguir desenvolver e implantar seu aplicativo normalmente:

bash
npm run ios
bash
yarn ios

Voltando para JavaScriptCore

React Native também oferece suporte ao uso de JavaScriptCore como mecanismo JavaScript. Siga estas instruções para cancelar o Hermes.

Android

Edite seu arquivo android/gradle.properties e mude hermesEnabled de volta para false:

# Use esta propriedade para ativar ou desativar o mecanismo Hermes JS.
+# Se definido como false, você usará JSC.
+hermesEnabled=false

iOS

Edite seu arquivo ios/Podfile e faça a alteração ilustrada abaixo:

   use_react_native!(
+     :path => config[:reactNativePath],
+     # Hermes agora está habilitado por padrão. Desative definindo este sinalizador como false.
+     # As próximas versões do React Native podem contar com get_default_flags(), mas
+     # deixamos isso explícito aqui para auxiliar no processo de atualização do React Native.
+     :hermes_enabled => flags[:hermes_enabled],
+     :hermes_enabled => false,
+   )
+ + + + \ No newline at end of file diff --git a/vitepress/docs/.vitepress/dist/hashmap.json b/vitepress/docs/.vitepress/dist/hashmap.json new file mode 100644 index 0000000..1921347 --- /dev/null +++ b/vitepress/docs/.vitepress/dist/hashmap.json @@ -0,0 +1 @@ +{"docs_build-speed.md":"DV6MDRQw","docs_communication-android.md":"qDQRzEbQ","docs_environment-setup.md":"B4_6Jwis","docs_navigation.md":"C1M6AWCZ","docs_communication-ios.md":"4nM-4AlR","docs_linking-libraries-ios.md":"CDTwulNM","docs_ram-bundles-inline-requires.md":"9rIYNLSr","docs_debugging.md":"DXY2CnKb","docs_native-debugging.md":"BUnmSub-","docs_handling-touches.md":"CyOwDJM4","docs_accessibility.md":"BwWJ5VBO","docs_native-modules-setup.md":"DYhKxXRl","docs_building-for-tv.md":"CwVLBrRD","docs_publishing-to-app-store.md":"7oRPhMVE","docs_profile-hermes.md":"CpRwgQSa","docs_out-of-tree-platforms.md":"Dgy9KTGW","docs_intro-react.md":"DeRGrixp","docs_fast-refresh.md":"CBUe46rB","docs_environment-setup_mac-os_ios.md":"DF3dIjK5","docs_animations.md":"ByV0vIgI","docs_gesture-responder-system.md":"C0ulhXXT","docs_running-on-device.md":"CXhWyhx3","docs_more-resources.md":"D6RVttbW","docs_colors.md":"DKDwf1Wk","docs_libraries.md":"DmT4KVPl","docs_getting-started.md":"QTale-rH","docs_handling-text-input.md":"4h5B6goh","docs_introduction.md":"WUMOn0xY","docs_app-extensions.md":"CvbwvPY8","docs_metro.md":"odTVVPP7","docs_network.md":"B8Zp_fLB","docs_react-devtools.md":"CK7_TSWs","docs_environment-setup_mac-os_android.md":"DzvP4V5m","docs_performance.md":"DQcK4vI4","docs_native-modules-intro.md":"BZ9q-CdX","docs_speeding-ci-builds.md":"ZHm8lsYC","docs_native-components-android.md":"D-fmrhIe","docs_profiling.md":"t1WkloPk","docs_integration-with-existing-apps_ios-swift.md":"CJQfODMc","docs_images.md":"CwJwsq7S","docs_react-native-gradle-plugin.md":"CPNRWRKn","docs_height-and-width.md":"BMEpPzGn","docs_integration-with-existing-apps_android-kotlin.md":"CmoaTw48","docs_optimizing-flatlist-configuration.md":"CfT25_mU","docs_integration-with-existing-apps.md":"sEybxE0W","docs_environment-setup_windows_android.md":"B0rJC79z","docs_style.md":"q_o4n3Pn","docs_environment-setup_linux_android.md":"Bjd4UZfh","docs_running-on-device_android-linux.md":"DRwWLWsA","docs_platform-specific-code.md":"5F505iA3","docs_timers.md":"OY67ndDu","docs_intro-react-native-components.md":"BwonAn8f","docs_running-on-simulator-ios.md":"HAs3yTdi","docs_integration-with-existing-apps_android-java.md":"D1ywsP1m","docs_running-on-device_android-mac-os.md":"CaJ567kc","docs_sourcemaps.md":"05e838l-","docs_troubleshooting.md":"CsjZzp3G","docs_javascript-environment.md":"Bj5yh4uJ","docs_integration-with-existing-apps_ios-objective-c.md":"DN1AFpQp","docs_native-modules-ios.md":"B8RNq7sy","docs_integration-with-android-fragment.md":"LAbR2gAq","docs_symbolication.md":"C65zpAiS","docs_the-new-architecture_landing-page.md":"CiPTxvE2","docs_running-on-device_android-windows.md":"CdtSsrGE","docs_headless-js-android.md":"eP8fnmCn","docs_running-on-device_ios-macos.md":"R_Mogg6l","docs_direct-manipulation.md":"DDnwwmfN","docs_upgrading.md":"gMgWgGeT","docs_security.md":"DrXA_4lZ","docs_using-a-scrollview.md":"DX0O7WVS","docs_signed-apk-android.md":"B206yoTk","docs_typescript.md":"DgYzLLD4","docs_using-a-listview.md":"ChEZh-qr","docs_testing-overview.md":"By6FslrL","docs_native-components-ios.md":"y8UW3Fo9","docs_using-hermes.md":"BML4G3i2","index.md":"O8eZyTNG","docs_native-modules-android.md":"BI96nnL8","docs_flexbox.md":"BrZwMBtp"} diff --git a/vitepress/docs/.vitepress/dist/index.html b/vitepress/docs/.vitepress/dist/index.html new file mode 100644 index 0000000..b9ef07e --- /dev/null +++ b/vitepress/docs/.vitepress/dist/index.html @@ -0,0 +1,27 @@ + + + + + + Documentação em português do React Native 0.72 | React Native 0.72 + + + + + + + + + + + + + + + + +
Skip to content

Documentação em português do React Native 0.72

Básico

Configuração do ambiente

Workflow

UI & Interação

Debugging

Testando

Performance

JavaScript Runtime

Módulos Nativos

Componentes Nativos

Guias Android e iOS

Experimental

+ + + + \ No newline at end of file diff --git a/vitepress/docs/.vitepress/sidebar.js b/vitepress/docs/.vitepress/sidebar.js new file mode 100644 index 0000000..1fce6bf --- /dev/null +++ b/vitepress/docs/.vitepress/sidebar.js @@ -0,0 +1,170 @@ +export default [ + { + text: 'Básico', + collapsed: false, + items: [ + { text: 'Introdução', link: '/docs/getting-started' }, + { text: 'Core Componentes e Componentes Nativos', link: '/docs/intro-react-native-components' }, + { text: 'Fundamentos do React', link: '/docs/intro-react.md' }, + { text: 'Tratamento de entrada de texto', link: '/docs/handling-text-input' }, + { text: 'Usando um ScrollView', link: '/docs/using-a-scrollview' }, + { text: 'Usando List Views', link: '/docs/using-a-listview' }, + { text: 'Solução de problemas', link: '/docs/troubleshooting' }, + { text: 'Código específico da plataforma', link: 'docs/platform-specific-code' }, + { text: 'Mais recursos', link: '/docs/more-resources' } + ] + }, + { + text: 'Configuração do ambiente', + collapsed: false, + items: [ + { text: 'Configurando o ambiente de desenvolvimento', link: '/docs/environment-setup.md' }, + { text: 'Integração com aplicativos existentes', link: '/docs/integration-with-existing-apps.md' }, + { text: 'Integração com um fragmento Android', link: '/docs/integration-with-android-fragment.md' }, + { text: 'Construindo para TV', link: '/docs/building-for-tv.md' }, + { text: 'Plataformas fora da árvore', link: '/docs/out-of-tree-platforms.md' } + ] + }, + { + text: 'Workflow', + collapsed: false, + items: [ + { text: 'Executando no dispositivo', link: '/docs/running-on-device' }, + { text: 'Atualização rápida', link: '/docs/fast-refresh' }, + { text: 'Metro', link: '/docs/metro' }, + { text: 'Simbolizando um rastreamento de pilha', link: '/docs/symbolication' }, + { text: 'Mapas de origem', link: '/docs/sourcemaps' }, + { text: 'Usando bibliotecas', link: '/docs/libraries' }, + { text: 'Usando TypeScript', link: '/docs/typescript' }, + { text: 'Atualizando para novas versões', link: '/docs/upgrading' }, + ] + }, + { + text: 'UI & Interação', + collapsed: false, + items: [ + { text: 'Estilo', link: '/docs/style' }, + { text: 'Altura e largura', link: '/docs/height-and-width' }, + { text: 'Layout com Flexbox', link: '/docs/flexbox' }, + { text: 'Imagens', link: '/docs/images' }, + { text: 'Referência de Cores', link: '/docs/colors' }, + { + text: 'Interação', + collapsed: true, + items: [ + { text: 'Lidando com toques', link: '/docs/handling-touches' }, + { text: 'Navegando entre telas', link: '/docs/navigation' }, + { text: 'Animações', link: '/docs/animations' }, + { text: 'Sistema de resposta por gestos', link: '/docs/gesture-responder-system' }, + ] + }, + { + text: 'Conectividade', + collapsed: true, + items: [ + { text: 'Rede', link: '/docs/network' }, + { text: 'Segurança', link: '/docs/security' }, + ] + }, + { + text: 'Inclusão', + collapsed: true, + items: [ + { text: 'Acessibilidade', link: '/docs/accessibility' }, + ] + } + ] + }, + { + text: 'Debugging', + collapsed: false, + items: [ + { text: 'Noções básicas de depuração', link: '/docs/debugging' }, + { text: 'Ferramentas de desenvolvedor React', link: '/docs/react-devtools' }, + { text: 'Debug Nativo', link: '/docs/native-debugging' }, + ] + }, + { + text: 'Testando', + collapsed: false, + items: [ + { text: 'Testando', link: '/docs/testing-overview' }, + ] + }, + { + text: 'Performance', + collapsed: false, + items: [ + { text: 'Visão geral do desempenho', link: '/docs/performance' }, + { text: 'Acelerando sua fase de construção', link: '/docs/build-speed' }, + { text: 'Acelerando as compilações de CI', link: '/docs/speeding-ci-builds' }, + { text: 'Otimizando a configuração da Flatlist', link: '/docs/optimizing-flatlist-configuration' }, + { text: 'Pacotes de RAM e require inline', link: '/docs/ram-bundles-inline-requires' }, + { text: 'Perfil', link: '/docs/profiling' }, + { text: 'Perfis com Hermes', link: '/docs/profile-hermes' }, + ] + }, + { + text: 'JavaScript Runtime', + collapsed: false, + items: [ + { text: 'Ambiente JavaScript', link: '/docs/javascript-environment' }, + { text: 'Timers', link: '/docs/timers' }, + { text: 'Usando o Hermes', link: '/docs/using-hermes' }, + ] + }, + { + text: 'Módulos Nativos', + collapsed: false, + items: [ + { text: 'Introdução aos módulos nativos', link: '/docs/native-modules-intro' }, + { text: 'Módulos nativos do Android', link: '/docs/native-modules-android' }, + { text: 'Módulos nativos iOS', link: '/docs/native-modules-ios' }, + { text: 'Configuração do pacote NPM de módulos nativos', link: '/docs/native-modules-setup' }, + ] + }, + { + text: 'Componentes Nativos', + collapsed: false, + items: [ + { text: 'Componentes de IU nativos do Android', link: '/docs/native-components-android' }, + { text: 'Componentes de UI nativos do iOS', link: '/docs/native-components-ios' }, + { text: 'Manipulação Direta', link: '/docs/direct-manipulation' }, + ] + }, + { + text: 'Guias Android e iOS', + collapsed: false, + items: [ + { + text: 'Android', + collapsed: true, + items: [ + { text: 'Headless JS', link: '/docs/headless-js-android' }, + { text: 'Publicação na Google Play Store', link: '/docs/signed-apk-android' }, + { text: 'Comunicação entre nativo e React Native', link: '/docs/communication-android' }, + { text: 'Plug-in React Native Gradle', link: '/docs/react-native-gradle-plugin' }, + ] + }, + { + text: 'iOS', + collapsed: true, + items: [ + { text: 'Vinculando Bibliotecas', link: '/docs/linking-libraries-ios' }, + { text: 'Executando no Simulador', link: '/docs/running-on-simulator-ios' }, + { text: 'Comunicação entre nativo e React Native', link: '/docs/communication-ios' }, + { text: 'Extensões de aplicativos', link: '/docs/app-extensions' }, + { text: 'Publicação na Apple App Store', link: '/docs/publishing-to-app-store' }, + ] + } + + ] + }, + { + text: 'Experimental', + collapsed: false, + items: [ + { text: 'Sobre a Nova Arquitetura', link: '/docs/the-new-architecture/landing-page' }, + ] + } +] diff --git a/vitepress/docs/.vitepress/theme/custom.css b/vitepress/docs/.vitepress/theme/custom.css new file mode 100644 index 0000000..d231771 --- /dev/null +++ b/vitepress/docs/.vitepress/theme/custom.css @@ -0,0 +1,51 @@ +:root { + --vp-font-family-base: 'Montserrat'; + /* --vp-c-brand-1: #333; */ + /* --vp-c-brand-2: #747bff; */ + /** --vp-font-family-mono: code font */ +} + +.one-image { + padding: 1em 0; + width: 100%; + text-align: center; +} + +.one-image img { + width: 100%; + margin: 0 auto; + max-width: 500px; +} + +.one-image figcaption { + font-style: italic; + padding: 1em 0; + font-size: .9em; +} + +.rounded-shadow { + border-radius: 8px; + box-shadow: rgba(50, 50, 93, 0.25) 0px 50px 100px -20px, rgba(0, 0, 0, 0.3) 0px 30px 60px -30px; +} + +.two-images { + display: flex; + align-items: flex; + justify-content: space-between; +} + +.two-images figure { + width: 50%; +} + +.two-images figcaption { + font-size: .8em; + padding: 1em; + text-align: center; +} + +.two-images img { + width: 90%; + margin: 0 auto; + max-width: 250px; +} \ No newline at end of file diff --git a/vitepress/docs/.vitepress/theme/index.js b/vitepress/docs/.vitepress/theme/index.js new file mode 100644 index 0000000..a02c67e --- /dev/null +++ b/vitepress/docs/.vitepress/theme/index.js @@ -0,0 +1,4 @@ +import DefaultTheme from 'vitepress/theme-without-fonts' +import './custom.css' + +export default DefaultTheme diff --git a/vitepress/docs/docs/accessibility.md b/vitepress/docs/docs/accessibility.md new file mode 100644 index 0000000..d563758 --- /dev/null +++ b/vitepress/docs/docs/accessibility.md @@ -0,0 +1,445 @@ +# Acessibilidade + +Tanto o Android quanto o iOS fornecem APIs para integração de aplicativos com tecnologias assistivas, como os leitores de tela incluídos VoiceOver (iOS) e TalkBack (Android). React Native possui APIs complementares que permitem que seu aplicativo acomode todos os usuários. + +> **INFORMAÇÕES** +> Android e iOS diferem ligeiramente em suas abordagens e, portanto, as implementações do React Native podem variar de acordo com a plataforma. + +## Propriedades de acessibilidade + +### accessible +Quando verdadeiro, indica que a visualização é um elemento de acessibilidade. Quando uma visualização é um elemento de acessibilidade, ela agrupa seus filhos em um único componente selecionável. Por padrão, todos os elementos tocáveis estão acessíveis. + +No Android, a propriedade `access={true}` para uma visualização react-native será traduzida em `focusable={true}` nativo. + +```tsx + + texto um + texto dois + +``` + +No exemplo acima, o foco de acessibilidade está disponível apenas na visualização pai com a propriedade acessível, e não individualmente para 'texto um' e 'texto dois'. + +### accessibilityLabel +Quando uma visualização é marcada como acessível, é uma boa prática definir um `accessibilityLabel` na visualização, para que as pessoas que usam o VoiceOver ou o TalkBack saibam qual elemento selecionaram. Um leitor de tela verbalizará esta string quando o elemento associado for selecionado. + +Para usar, defina a propriedade `accessibilityLabel` como uma string personalizada em sua `View`, `Text` ou `Touchable`: + +```tsx + + + Press me! + + +``` + +No exemplo acima, o `accessLabel` no elemento `TouchableOpacity` seria padronizado como `"Press me!"`. O rótulo é construído concatenando todos os filhos do nó `Text` separados por espaços. + +### accessibilityLabelledBy [Android] + +Uma referência a outro elemento [nativeID](/docs/view.md) usado para criar formulários complexos. O valor de `acessibilidadeLabelledBy` deve corresponder ao nativeID do elemento relacionado: + +```jsx + + Label for Input Field + + +``` + +No exemplo acima, o leitor de tela anuncia `Input, Edit Box for Label for Input Field` ao focar no TextInput. + +### accessibilityHint + +Uma dica de acessibilidade pode ser usada para fornecer contexto adicional ao usuário sobre o resultado da ação quando isso não estiver claro apenas no rótulo de acessibilidade. + +Forneça à propriedade `acessibilidadeHint` uma string personalizada em sua View, Text ou Touchable: + +```jsx + + + Back + + +``` + +#### iOS +No exemplo acima, o VoiceOver lerá a dica após o rótulo, se o usuário tiver as dicas habilitadas nas configurações do VoiceOver do dispositivo. Leia mais sobre as diretrizes para `acessibilidadeHint` nos [documentos do desenvolvedor iOS](https://developer.apple.com/documentation/objectivec/nsobject/1615093-accessibilityhint) + +#### Android +No exemplo acima, o TalkBack lerá a dica após o rótulo. No momento, as dicas não podem ser desativadas no Android. + +### accessibilityLanguage [iOS] + +Ao usar a propriedade `accessibilityLanguage`, o leitor de tela entenderá qual idioma usar ao ler o `label`, o `value` e o `hint`. O valor da string fornecido deve seguir a [especificação BCP 47](https://www.rfc-editor.org/info/bcp47). + +```tsx + + 🍕 + +``` + +### acessibilidadeIgnoresInvertColors [iOS] +A inversão das cores da tela é um recurso de acessibilidade disponível no iOS e iPadOS para pessoas com daltonismo, baixa visão ou deficiência visual. Se houver uma visualização que você não deseja inverter quando esta configuração estiver ativada, possivelmente uma foto, defina esta propriedade como verdadeira. + +### accessibilityLiveRegion [Android] +Quando os componentes mudam dinamicamente, queremos que o TalkBack alerte o usuário final. Isso é possível graças à propriedade `accessibilityLiveRegion`. Pode ser definido como `none`, `polite` e `assertive`: + +* `none` Os serviços de acessibilidade não devem anunciar alterações nesta visão. +* `polite` serviços de acessibilidade educados devem anunciar mudanças nesta visão. +* `assertive` Os serviços de acessibilidade devem interromper o discurso em curso para anunciar imediatamente alterações nesta visão. + +```tsx + + + Click me + + + + Clicked {count} times + +``` + +No exemplo acima, o método `addOne` altera a contagem (`count`} da variável de estado. Quando `TouchableWithoutFeedback` é acionado, o TalkBack lê o texto na visualização Texto devido à sua propriedade `accessibilityLiveRegion="polite"`. + +### accessibilityRole +`accessibilityRole` comunica a finalidade de um componente ao usuário de tecnologia assistiva. + +`accessibilityRole` pode ser um dos seguintes: + +* **adjustable** Usado quando um elemento pode ser "ajustado" (por exemplo, um controle deslizante). +* **alert** Usado quando um elemento contém texto importante a ser apresentado ao usuário. +* **button** Usado quando o elemento deve ser tratado como um botão. +* **checkbox** Usado quando um elemento representa uma caixa de seleção que pode ser marcada, desmarcada ou ter um estado misto de marcado. +* **combobox** Usado quando um elemento representa uma caixa de combinação, que permite ao usuário selecionar entre diversas opções. +* **header** Usado quando um elemento atua como cabeçalho para uma seção de conteúdo (por exemplo, o título de uma barra de navegação). +* **image** Usado quando o elemento deve ser tratado como uma imagem. Pode ser combinado com um botão ou link. +* **imagebutton** Utilizado quando o elemento deve ser tratado como um botão e também é uma imagem. +* **keyboardkey** Usado quando o elemento atua como uma tecla do teclado. +* **link** Usado quando o elemento deve ser tratado como um link. +* **menu** Usado quando o componente é um menu de opções. +* **menubar** Usada quando um componente é um contêiner de vários menus. +* **menuitem** Usado para representar um item dentro de um menu. +* **none** Usado quando o elemento não tem função. +* **progressbar** Usado para representar um componente que indica o progresso de uma tarefa. +* **radio** Usado para representar um botão de opção. +* **radiogroup** Usado para representar um grupo de botões de opção. +* **scrollbar** Usada para representar uma barra de rolagem. +* **search** Usado quando um elemento de campo de texto também deve ser tratado como um campo de pesquisa. +* **spinbutton** Usado para representar um botão que abre uma lista de opções. +* **summary** Usado quando um elemento pode ser usado para fornecer um resumo rápido das condições atuais no aplicativo quando ele é iniciado pela primeira vez. +* **switch** Usado para representar um switch que pode ser ligado e desligado. +* **tab** Usado para representar uma guia. +* **tablist** Usado para representar uma lista de guias. +* **text** Usado quando o elemento deve ser tratado como texto estático que não pode ser alterado. +* **timer** Usado para representar um timer. +* **togglebutton** Usado para representar um botão de alternância. Deve ser usado com acessibilidadeState marcado para indicar se o botão está ativado ou desativado. +* **toolbar** Usada para representar uma barra de ferramentas (um contêiner de botões de ação ou componentes). +* **grid** Usado com ScrollView, VirtualizedList, FlatList ou SectionList para representar uma grade. Adiciona anúncios de entrada/saída da grade ao GridView do Android. + +### accessibilityState +Descreve o estado atual de um componente para o usuário de tecnologia assistiva. + +acessibilidadeState é um objeto. Ele contém os seguintes campos: + +| NOME | DESCRIÇÃO | TIPO | OBRIGATÓRIO | +|-------------|--------------------|---------------------------|----------------| +| disabled | Indica se o elemento está desabilitado ou não. | `boolean` | Não | +| selected | Indica se um elemento selecionável está selecionado ou não. | `boolean` | Não | +| checked | Indica o estado de um elemento verificável. Este campo pode receber uma string booleana ou "mista" para representar caixas de seleção mistas. | `boolean` ou 'mixed' | Não | +| busy | Indica se um elemento está ocupado ou não. | `boolean` | Não | +| expanded | Indica se um elemento expansível está atualmente expandido ou recolhido. | `boolean` | Não | + +Para usar, defina `accessibilityState` como um objeto com uma definição específica. + +### accessibilityValue +Representa o valor atual de um componente. Pode ser uma descrição textual do valor de um componente ou, para componentes baseados em intervalo, como controles deslizantes e barras de progresso, contém informações de intervalo (mínimo, atual e máximo). + +`accessibilityValue` é um objeto. Ele contém os seguintes campos: + +| NOME | DESCRIÇÃO | TIPO | NECESSÁRIO | +|--------|------------------------------------------------|-------------------|-------------| +| min | O valor mínimo do intervalo deste componente. | `integer` | Obrigatório se `now` estiver definido. | +| max | O valor máximo do intervalo deste componente. | `integer` | Obrigatório se `now` estiver definido. | +| now | O valor atual do intervalo deste componente. | `integer` | Não | +| text | Uma descrição textual do valor deste componente. Substituirá `min`, `now` e `max` se definido. | `integer` | Não | + +### accessibilityViewIsModal [iOS] +Um valor booleano que indica se o VoiceOver deve ignorar os elementos nas visualizações que são irmãos do receptor. + +Por exemplo, em uma janela que contém visualizações irmãs `A` e `B`, definir `accessibilityViewIsModal` como `true` na visualização `B` faz com que o VoiceOver ignore os elementos na visualização `A`. Por outro lado, se a visualização `B` contiver uma visualização filha `C` e você definir `accessibilityViewIsModal` como `true` na visualização `C`, o VoiceOver não ignora os elementos da visualização `A`. + +### accessibilityElementsHidden [iOS] +Um valor booleano que indica se os elementos de acessibilidade contidos neste elemento de acessibilidade estão ocultos. + +Por exemplo, em uma janela que contém visualizações irmãs `A` e `B`, definir `accessibilityElementsHidden` como verdadeiro na visualização `B` faz com que o VoiceOver ignore os elementos na visualização B. Isso é semelhante à propriedade Android `importantForAccessibility="no-hide-descendants"`. + +### aria-valuemax +Representa o valor máximo para componentes baseados em intervalo, como controles deslizantes e barras de progresso. + +### aria-valuemin +Representa o valor mínimo para componentes baseados em intervalo, como controles deslizantes e barras de progresso. + +### aria-valuenow +Representa o valor atual para componentes baseados em intervalo, como controles deslizantes e barras de progresso. + +### aria-valuetext +Representa a descrição textual do componente. + +### aria-busy +Indica que um elemento está sendo modificado e que as tecnologias assistivas podem querer esperar até que as alterações sejam concluídas antes de informar o usuário sobre a atualização. + +| TIPO | PADRÃO | +|----------|---------| +| boolean | `false` | + + +### aria-checked +Indica o estado de um elemento verificável. Este campo pode receber uma string booleana ou "mista" para representar caixas de seleção mistas. + +| TIPO | PADRÃO | +|------------------|----------| +| boolean, 'mixed' | `false` | + +### aria-disabled +Indica que o elemento é perceptível, mas desabilitado, portanto não é editável ou operável de outra forma. + +| TIPO | PADRÃO | +|----------|---------| +| boolean | `false` | + +### aria-expanded +Indica se um elemento expansível está atualmente expandido ou recolhido. + +| TIPO | PADRÃO | +|----------|---------| +| boolean | `false` | + +### aria-hidden +Indica se os elementos de acessibilidade contidos neste elemento de acessibilidade estão ocultos. + +Por exemplo, numa janela que contém vistas irmãs `A` e `B`, definir aria-hidden como verdadeiro na vista `B` faz com que o VoiceOver ignore os elementos na vista `B`. + +| TIPO | PADRÃO | +|----------|---------| +| boolean | `false` | + +### aria-label +Define um valor de string que rotula um elemento interativo. + +| TIPO | +|----------| +| string | + +### aria-labelledby [Android] +Identifica o elemento que rotula o elemento ao qual é aplicado. O valor de aria-labelledby deve corresponder ao [nativeID](/docs/view#nativeid) do elemento relacionado: + +```jsx + + Label for Input Field + + +``` +| TIPO | +|----------| +| string | + +### aria-live [Android] +Indica que um elemento será atualizado e descreve os tipos de atualizações que os agentes de usuário, as tecnologias assistivas e o usuário podem esperar da região ativa. + +* **off** Os serviços de acessibilidade não devem anunciar alterações nesta visualização. +* **polite** Os serviços de acessibilidade devem anunciar alterações nesta visão. +* **assertive** Os serviços de acessibilidade devem interromper o discurso em curso para anunciar imediatamente alterações nesta visão. + +| TIPO | PADRÃO | +|----------------------------------------|---------| +| `enum('assertive', 'off', 'polite')` | `'off'` | + +### aria-modal [iOS] +Valor booleano que indica se o VoiceOver deve ignorar os elementos nas visualizações que são irmãos do receptor. + +| TIPO | PADRÃO | +|----------|---------| +| boolean | `false` | + +### aria-selected +Indica se um elemento selecionável está selecionado ou não. + +| TIPO | +|----------| +| boolean | + +### importantForAccessibility [Android] +No caso de dois componentes de UI sobrepostos com o mesmo pai, o foco de acessibilidade padrão pode ter um comportamento imprevisível. A propriedade `importantForAccessibility` resolverá isso controlando se uma visualização dispara eventos de acessibilidade e se é reportada aos serviços de acessibilidade. Pode ser definido como `auto`, `yes`, `no` e `no-hide-descendants` (o último valor forçará os serviços de acessibilidade a ignorar o componente e todos os seus filhos). + +```jsx + + + First layout + + + Second layout + + +``` + +No exemplo acima, o layout `yellow` e seus descendentes são completamente invisíveis para o TalkBack e todos os outros serviços de acessibilidade. Assim, podemos usar visualizações sobrepostas com o mesmo pai sem confundir o TalkBack. + +### onAccessibilityEscape [iOS] +Atribua esta propriedade a uma função personalizada que será chamada quando alguém realizar o gesto de "escape", que é um gesto em forma de Z com dois dedos. Uma função de escape deve voltar hierarquicamente na interface do usuário. Isso pode significar subir ou voltar em uma hierarquia de navegação ou descartar uma interface de usuário modal. Se o elemento selecionado não tiver uma função `onAccessibilityEscape`, o sistema tentará percorrer a hierarquia de visualizações até encontrar uma visualização que tenha ou piscar para indicar que não foi possível encontrar uma. + +### onAccessibilityTap +Use esta propriedade para atribuir uma função personalizada a ser chamada quando alguém ativar um elemento acessível tocando duas vezes nele enquanto estiver selecionado. + +### onMagicTap [iOS] +Atribua esta propriedade a uma função personalizada que será chamada quando alguém realizar o gesto de "toque mágico", que é um toque duplo com dois dedos. Uma função de toque mágico deve executar a ação mais relevante que um usuário pode realizar em um componente. No aplicativo Telefone do iPhone, um toque mágico atende uma chamada ou encerra a atual. Se o elemento selecionado não tiver uma função onMagicTap, o sistema percorrerá a hierarquia de visualizações até encontrar uma visualização que tenha. + +### role +`role` comunica a finalidade de um componente e tem precedência sobre a propriedade [accessRole](#accessibilityrole). + +a função pode ser uma das seguintes: + +* **alert** Usado quando um elemento contém texto importante a ser apresentado ao usuário. +* **button** Usado quando o elemento deve ser tratado como um botão. +* **checkbox** Usado quando um elemento representa uma caixa de seleção que pode ser marcada, desmarcada ou ter um estado misto de marcado. +* **combobox** Usado quando um elemento representa uma caixa de combinação, que permite ao usuário selecionar entre diversas opções. +* **grid** Usado com `ScrollView`, `VirtualizedList`, `FlatList` ou `SectionList` para representar uma grade. Adiciona os anúncios de entrada/saída da grade ao `GridView` do Android. +* **heading** Usado quando um elemento atua como cabeçalho para uma seção de conteúdo (por exemplo, o título de uma barra de navegação). +* **img** Usado quando o elemento deve ser tratado como uma imagem. Pode ser combinado com um botão ou link, por exemplo. +* **link** Usado quando o elemento deve ser tratado como um link. +* **list** Usado para identificar uma lista de itens. +* **menu** Usado quando o componente é um menu de opções. +* **menubar** Usada quando um componente é um contêiner de vários menus. +* **menuitem** Usado para representar um item dentro de um menu. +* **none** Usado quando o elemento não tem função. +* **presentation** Usado quando o elemento não tem função. +* **progressbar** Usado para representar um componente que indica o progresso de uma tarefa. +* **radio** Usado para representar um botão de opção. +* **radiogroup** Usado para representar um grupo de botões de opção. +* **scrollbar** Usada para representar uma barra de rolagem. +* **searchbox** Usado quando o elemento do campo de texto também deve ser tratado como um campo de pesquisa. +* **slider** Usado quando um elemento pode ser "ajustado" (por exemplo, um controle deslizante). +* **spinbutton** Usado para representar um botão que abre uma lista de opções. +* **summary** Usado quando um elemento pode ser usado para fornecer um resumo rápido das condições atuais no aplicativo quando ele é iniciado pela primeira vez. +* **switch** Usado para representar um switch que pode ser ligado e desligado. +* **tab** Usado para representar uma guia. +* **tablist** Usado para representar uma lista de guias. +* **timer** Usado para representar um timer. +* **toolbar** Usada para representar uma barra de ferramentas (um contêiner de botões de ação ou componentes). + +## Ações de acessibilidade + +As ações de acessibilidade permitem que a tecnologia assistiva invoque programaticamente a(s) ação(ões) de um componente. Para apoiar ações de acessibilidade, um componente deve fazer duas coisas: + +* Defina a lista de ações suportadas por meio da propriedade `accessibilityActions`. +* Implemente uma função `onAccessibilityAction` para lidar com solicitações de ação. + +A propriedade `accessibilityActions` deve conter uma lista de objetos de ação. Cada objeto de ação deve conter os seguintes campos: + + +| NOME | TIPO | OBRIGATÓRIO | +|----------|---------|--------------| +| name | `string`| Sim | +| label | `string`| Não | + +As ações representam ações padrão, como clicar em um botão ou ajustar um controle deslizante, ou ações personalizadas específicas de um determinado componente, como excluir uma mensagem de email. O campo `name` é obrigatório para ações padrão e personalizadas, mas o `label` é opcional para ações padrão. + +Ao adicionar suporte para ações padrão, o `name` deve ser um dos seguintes: + +* `'magicTap'` - apenas iOS - Enquanto o foco do VoiceOver está no componente ou dentro dele, o usuário toca duas vezes com dois dedos. +* `'escape'` - apenas iOS - Enquanto o foco do VoiceOver está no componente ou dentro dele, o usuário executou um gesto de esfregar com dois dedos (esquerda, direita, esquerda). +* `'activate'` - Ativa o componente. Este deve realizar a mesma ação com ou sem tecnologia assistiva. Ativado quando um usuário de leitor de tela toca duas vezes no componente. +* `'increment'` - Incrementa um componente ajustável. No iOS, o VoiceOver gera essa ação quando o componente tem a função de ‘ajustável’ e o usuário coloca o foco nele e desliza para cima. No Android, o TalkBack gera essa ação quando o usuário coloca o foco de acessibilidade no componente e pressiona o botão de aumentar volume. +* `'decrement'` - Diminui um componente ajustável. No iOS, o VoiceOver gera essa ação quando o componente tem a função de ‘ajustável’ e o usuário coloca o foco nele e desliza para baixo. No Android, o TalkBack gera essa ação quando o usuário coloca o foco de acessibilidade no componente e pressiona o botão de diminuir volume. +* `'longpress'` - somente Android - Esta ação é gerada quando o usuário coloca o foco de acessibilidade no componente, depois dá um toque duplo e mantém um dedo na tela. Este deve realizar a mesma ação com ou sem tecnologia assistiva. + +O campo `label` é opcional para ações padrão e muitas vezes não é utilizado por tecnologias assistivas. Para ações customizadas, é uma string localizada contendo uma descrição da ação a ser apresentada ao usuário. + +Para lidar com solicitações de ação, um componente deve implementar uma função `onAccessibilityAction`. O único argumento para esta função é um evento contendo o nome da ação a ser executada. O exemplo abaixo do RNTester mostra como criar um componente que define e trata diversas ações customizadas. + +```jsx + { + switch (event.nativeEvent.actionName) { + case 'cut': + Alert.alert('Alert', 'cut action success'); + break; + case 'copy': + Alert.alert('Alert', 'copy action success'); + break; + case 'paste': + Alert.alert('Alert', 'paste action success'); + break; + } + }} +/> +``` + +## Verificando se um leitor de tela está ativado +A API `AccessibilityInfo` permite determinar se um leitor de tela está ativo ou não. Consulte a documentação do [`AccessibilityInfo`](https://reactnative.dev/docs/0.72/accessibilityinfo) para obter detalhes. + +## Envio de eventos de acessibilidade Android [Android] +Às vezes é útil acionar um evento de acessibilidade em um componente de UI (ou seja, quando uma visualização personalizada aparece em uma tela ou define o foco de acessibilidade para uma visualização). O módulo UIManager nativo expõe um método 'sendAccessibilityEvent' para esta finalidade. São necessários dois argumentos: uma tag de visualização e um tipo de evento. Os tipos de eventos suportados são `typeWindowStateChanged`, `typeViewFocused` e `typeViewClicked`. + +```jsx +import {Platform, UIManager, findNodeHandle} from 'react-native'; + +if (Platform.OS === 'android') { + UIManager.sendAccessibilityEvent( + findNodeHandle(this), + UIManager.AccessibilityEventTypes.typeViewFocused, + ); +} +``` + +## Testando o suporte do TalkBack [Android] +Para ativar o TalkBack, acesse o aplicativo Configurações em seu dispositivo ou emulador Android. Toque em Acessibilidade e depois em TalkBack. Alterne a opção "Usar serviço" para ativá-lo ou desativá-lo. + +Os emuladores Android não têm o TalkBack instalado por padrão. Você pode instalar o TalkBack no seu emulador através da Google Play Store. Certifique-se de escolher um emulador com a Google Play Store instalada. Eles estão disponíveis no Android Studio. + +Você pode usar o atalho da tecla de volume para alternar o TalkBack. Para ativar o atalho da tecla de volume, vá para o aplicativo Configurações e, em seguida, Acessibilidade. Na parte superior, ative o atalho da tecla de volume. + +Para usar o atalho da tecla de volume, pressione ambas as teclas de volume por 3 segundos para iniciar uma ferramenta de acessibilidade. + +Além disso, se preferir, você pode alternar o TalkBack por meio da linha de comando com: + +``` +# desabilitado +adb shell settings put secure enabled_accessibility_services com.android.talkback/com.google.android.marvin.talkback.TalkBackService + +# habilitado +adb shell settings put secure enabled_accessibility_services com.google.android.marvin.talkback/com.google.android.marvin.talkback.TalkBackService +``` + +## Testando o suporte do VoiceOver [iOS] +Para ativar o VoiceOver em seu dispositivo iOS ou iPadOS, acesse o aplicativo Ajustes, toque em Geral e em Acessibilidade. Lá você encontrará muitas ferramentas disponíveis para as pessoas permitirem que seus dispositivos sejam mais utilizáveis, incluindo VoiceOver. Para ativar o VoiceOver, toque em VoiceOver em “Visão” e alterne o botão que aparece na parte superior. + +Na parte inferior das configurações de acessibilidade, há um “Atalho de acessibilidade”. Você pode usar isso para alternar o VoiceOver clicando três vezes no botão Início. + +O VoiceOver não está disponível por meio do simulador, mas você pode usar o Accessibility Inspector do Xcode para usar o macOS VoiceOver por meio de um aplicativo. Observe que é sempre melhor testar com um dispositivo, pois o VoiceOver do macOS pode resultar em experiências variadas. + +## Recursos adicionais +* [Tornando aplicativos React Native acessíveis](https://engineering.fb.com/ios/making-react-native-apps-accessible/) diff --git a/vitepress/docs/docs/animations.md b/vitepress/docs/docs/animations.md new file mode 100644 index 0000000..468c090 --- /dev/null +++ b/vitepress/docs/docs/animations.md @@ -0,0 +1,613 @@ +# Animações + +As animações são muito importantes para criar uma ótima experiência do usuário. Objetos estacionários devem superar a inércia à medida que começam a se mover. Objetos em movimento têm impulso e raramente param imediatamente. As animações permitem transmitir movimentos fisicamente verossímeis em sua interface. + +React Native fornece dois sistemas de animação complementares: **`Animated`** para controle granular e interativo de valores específicos e **`LayoutAnimation`** para transações de layout global animadas. + +## `Animated` API + +A API `Animated` foi projetada para expressar de forma concisa uma ampla variedade de padrões interessantes de animação e interação com muito desempenho. `Animated` concentra-se em relacionamentos declarativos entre entradas e saídas, com transformações configuráveis entre elas e métodos de `start`/`stop` para controlar a execução da animação baseada em tempo. + +`Animated` exporta seis tipos de componentes animáveis: `View`, `Text`, `Image`, `ScrollView`, `FlatList` e `SectionList`, mas você também pode criar o seu próprio usando `Animated.createAnimatedComponent()`. + +Por exemplo, uma visualização de contêiner que aparece gradualmente quando é montada pode ter esta aparência: + +```tsx +import React, {useRef, useEffect} from 'react'; +import {Animated, Text, View} from 'react-native'; +import type {PropsWithChildren} from 'react'; +import type {ViewStyle} from 'react-native'; + +type FadeInViewProps = PropsWithChildren<{style: ViewStyle}>; + +const FadeInView: React.FC = props => { + const fadeAnim = useRef(new Animated.Value(0)).current; // Valor inicial para opacidade: 0 + + useEffect(() => { + Animated.timing(fadeAnim, { + toValue: 1, + duration: 10000, + useNativeDriver: true, + }).start(); + }, [fadeAnim]); + + return ( + + {props.children} + + ); +}; + +// Você pode então usar seu `FadeInView` no lugar de um `View` em seus componentes: +export default () => { + return ( + + + + Fading in + + + + ); +}; +``` + +![image](/docs/assets/294185554-0a53d571-a6d4-4d9c-8473-e1a497cb4771.png) + +Vamos analisar o que está acontecendo aqui. No construtor `FadeInView`, um novo `Animated.Value` chamado `fadeAnim` é inicializado como parte do estado. A propriedade de opacidade na `View` é mapeada para esse valor animado. Nos bastidores, o valor numérico é extraído e usado para definir a opacidade. + +Quando o componente é montado, a opacidade é definida como 0. Em seguida, uma animação de atenuação é iniciada no valor animado `fadeAnim`, que atualizará todos os seus mapeamentos dependentes (neste caso, apenas a opacidade) em cada quadro à medida que o valor for animado para o valor final de 1. + +Isso é feito de maneira otimizada e mais rápida do que chamar `setState` e renderizar novamente. Como toda a configuração é declarativa, poderemos implementar otimizações adicionais que serializam a configuração e executam a animação em um thread de alta prioridade. + +## Configurando animações + +As animações são altamente configuráveis. Funções de atenuação personalizadas e predefinidas, atrasos, durações, fatores de decaimento, constantes de mola e muito mais podem ser ajustados dependendo do tipo de animação. + +`Animated` fornece vários tipos de animação, sendo o mais comumente usado `Animated.timing()`. Ele suporta a animação de um valor ao longo do tempo usando uma das várias funções de atenuação predefinidas, ou você pode usar a sua própria. As funções de atenuação são normalmente usadas em animação para transmitir aceleração e desaceleração graduais de objetos. + +Por padrão, o tempo usará uma curva `easyInOut` que transmite aceleração gradual até a velocidade máxima e termina desacelerando gradualmente até parar. Você pode especificar uma função de atenuação diferente passando um parâmetro de `easing. A `duration` personalizada ou mesmo um `delay` antes do início da animação também é suportada. + +Por exemplo, se quisermos criar uma animação de 2 segundos de um objeto que recua ligeiramente antes de se mover para sua posição final: + +```js +Animated.timing(this.state.xPosition, { + toValue: 100, + easing: Easing.back(), + duration: 2000, + useNativeDriver: true, +}).start(); +``` + +Dê uma olhada na seção [**Configurando animações** da referência da API](/docs/animated.md) animada para saber mais sobre todos os parâmetros de configuração suportados pelas animações integradas. + +## Compondo animações +As animações podem ser combinadas e reproduzidas em sequência ou em paralelo. As animações sequenciais podem ser reproduzidas imediatamente após o término da animação anterior ou podem começar após um atraso especificado. A API `Animated` fornece vários métodos, como `sequence()` e `delay()`, cada um dos quais usa uma matriz de animações para ser executado e chama automaticamente `start()`/`stop()` conforme necessário. + +Por exemplo, a animação a seguir para e depois retorna enquanto gira em paralelo: + +```jsx +Animated.sequence([ + // decair, então o spring começa e gira + Animated.decay(position, { + // desce até parar + velocity: {x: gestureState.vx, y: gestureState.vy}, // velocidade da liberação do gesto + deceleration: 0.997, + useNativeDriver: true, + }), + Animated.parallel([ + // após a decadência, em paralelo: + Animated.spring(position, { + toValue: {x: 0, y: 0}, // voltar para começar + useNativeDriver: true, + }), + Animated.timing(twirl, { + // e girar + toValue: 360, + useNativeDriver: true, + }), + ]), +]).start(); // iniciar o grupo de sequência +``` + +Se uma animação for parada ou interrompida, todas as outras animações do grupo também serão interrompidas. `Animated.parallel` tem uma opção `stopTogether` que pode ser definida como `false` para desabilitar isso. + +Você pode encontrar uma lista completa de métodos de composição na seção [Compondo animações da referência da API `Animated`](/docs/animated.md). + +## Combinando valores animados +Você pode combinar [dois valores animados](/docs/animated.md) por meio de adição, multiplicação, divisão ou módulo para criar um novo valor animado. + +Existem alguns casos em que um valor animado precisa inverter outro valor animado para cálculo. Um exemplo é inverter uma escala (2x -> 0,5x): + +```jsx +const a = new Animated.Value(1); +const b = Animated.divide(1, a); + +Animated.spring(a, { + toValue: 2, + useNativeDriver: true, +}).start(); +``` + +## Interpolação +Cada propriedade pode ser executada primeiro por meio de uma interpolação. Uma interpolação mapeia intervalos de entrada para intervalos de saída, normalmente usando uma interpolação linear, mas também oferece suporte a funções de atenuação. Por padrão, ele extrapolará a curva além dos intervalos fornecidos, mas você também poderá limitar o valor de saída. + +Um mapeamento básico para converter um intervalo de 0-1 em um intervalo de 0-100 seria: + +```js +value.interpolate({ + inputRange: [0, 1], + outputRange: [0, 100], +}); +``` + +Por exemplo, você pode querer pensar em seu `Animated.Value` como indo de 0 a 1, mas anime a posição de `150px` para `0px` e a opacidade de 0 a 1. Isso pode ser feito modificando o `style` do exemplo acima, assim: + +```jsx + style={{ + opacity: this.state.fadeAnim, // Vincula diretamente + transform: [{ + translateY: this.state.fadeAnim.interpolate({ + inputRange: [0, 1], + outputRange: [150, 0] // 0 : 150, 0.5 : 75, 1 : 0 + }), + }], + }} +``` + +`interpolate()` também suporta vários segmentos de intervalo, o que é útil para definir zonas mortas e outros truques úteis. Por exemplo, para obter um relacionamento de negação em -300 que vai para 0 em -100, depois volta para 1 em 0 e depois volta para zero em 100 seguido por uma zona morta que permanece em 0 para tudo além disso, você poderia fazer: + +```js +value.interpolate({ + inputRange: [-300, -100, 0, 100, 101], + outputRange: [300, 0, 1, 0, 0], +}); +``` + +O que seria mapeado assim: + +``` +Input | Output +------|------- + -400| 450 + -300| 300 + -200| 150 + -100| 0 + -50| 0.5 + 0| 1 + 50| 0.5 + 100| 0 + 101| 0 + 200| 0 +``` + +`interpolate()` também suporta mapeamento para strings, permitindo animar cores e também valores com unidades. Por exemplo, se você quiser animar uma rotação você poderia fazer: + +```js +value.interpolate({ + inputRange: [0, 360], + outputRange: ['0deg', '360deg'], +}); +``` + +`interpolate()` também suporta funções de atenuação arbitrárias, muitas das quais já estão implementadas no módulo [Easing](/docs/easing.md). `interpolate()` também possui comportamento configurável para extrapolar o `outputRange`. Você pode definir a extrapolação definindo as opções `extrapolate`, `extrapolateLeft` ou `extrapolateRight`. O valor padrão é `extend`, mas você pode usar `clamp` para evitar que o valor de saída exceda `outputRange`. + +## Rastreando valores dinâmicos +Os valores animados também podem rastrear outros valores definindo `toValue` de uma animação como outro valor animado em vez de um número simples. Por exemplo, uma animação "Chat Heads" como a usada pelo Messenger no Android poderia ser implementada com um `spring()` fixado em outro valor animado, ou com `timing()` e uma `duration` de 0 para rastreamento rígido. Também podem ser compostos com interpolações: + +```jsx +Animated.spring(follower, {toValue: leader}).start(); +Animated.timing(opacity, { + toValue: pan.x.interpolate({ + inputRange: [0, 300], + outputRange: [1, 0], + useNativeDriver: true, + }), +}).start(); +``` + +Os valores animados do `leader` e do `follower` seriam implementados usando `Animated.ValueXY()`. `ValueXY` é uma maneira prática de lidar com interações 2D, como panorâmica ou arrastamento. É um wrapper básico que contém duas instâncias de `Animated.Value` e algumas funções auxiliares que as chamam, tornando `ValueXY` um substituto imediato para `Value` em muitos casos. Isso nos permite rastrear os valores de x e y no exemplo acima. + +## Gestos de rastreamento +Gestos, como movimento panorâmico ou rolagem, e outros eventos podem ser mapeados diretamente para valores animados usando [`Animated.event`](/docs/animated.md). Isto é feito com uma sintaxe de mapa estruturada para que os valores possam ser extraídos de objetos de eventos complexos. O primeiro nível é uma matriz para permitir o mapeamento entre vários argumentos, e essa matriz contém objetos aninhados. + +Por exemplo, ao trabalhar com gestos de rolagem horizontal, você faria o seguinte para mapear `event.nativeEvent.contentOffset.x` para `scrollX` (um `Animated.Value`): + +```jsx + onScroll={Animated.event( + // scrollX = e.nativeEvent.contentOffset.x + [{nativeEvent: { + contentOffset: { + x: scrollX + } + } + }] + )} +``` + +O exemplo a seguir implementa um carrossel de rolagem horizontal onde os indicadores de posição de rolagem são animados usando o `Animated.event` usado no `ScrollView` + +## ScrollView com exemplo de evento animado + +```jsx +import React, {useRef} from 'react'; +import { + SafeAreaView, + ScrollView, + Text, + StyleSheet, + View, + ImageBackground, + Animated, + useWindowDimensions, +} from 'react-native'; + +const images = new Array(6).fill( + 'https://images.unsplash.com/photo-1556740749-887f6717d7e4', +); + +const App = () => { + const scrollX = useRef(new Animated.Value(0)).current; + + const {width: windowWidth} = useWindowDimensions(); + + return ( + + + + {images.map((image, imageIndex) => { + return ( + + + + + {'Image - ' + imageIndex} + + + + + ); + })} + + + {images.map((image, imageIndex) => { + const width = scrollX.interpolate({ + inputRange: [ + windowWidth * (imageIndex - 1), + windowWidth * imageIndex, + windowWidth * (imageIndex + 1), + ], + outputRange: [8, 16, 8], + extrapolate: 'clamp', + }); + return ( + + ); + })} + + + + ); +}; + +const styles = StyleSheet.create({ + container: { + flex: 1, + alignItems: 'center', + justifyContent: 'center', + }, + scrollContainer: { + height: 300, + alignItems: 'center', + justifyContent: 'center', + }, + card: { + flex: 1, + marginVertical: 4, + marginHorizontal: 16, + borderRadius: 5, + overflow: 'hidden', + alignItems: 'center', + justifyContent: 'center', + }, + textContainer: { + backgroundColor: 'rgba(0,0,0, 0.7)', + paddingHorizontal: 24, + paddingVertical: 8, + borderRadius: 5, + }, + infoText: { + color: 'white', + fontSize: 16, + fontWeight: 'bold', + }, + normalDot: { + height: 8, + width: 8, + borderRadius: 4, + backgroundColor: 'silver', + marginHorizontal: 4, + }, + indicatorContainer: { + flexDirection: 'row', + alignItems: 'center', + justifyContent: 'center', + }, +}); + +export default App; +``` + +![image](/docs/assets/294203476-c38ee8dd-d990-491b-ac01-5940b5237aeb.png) + +Ao usar o `PanResponder`, você pode usar o código a seguir para extrair as posições x e y de `gestureState.dx` e `gestureState.dy`. Usamos um `null` na primeira posição do array, pois estamos interessados apenas no segundo argumento passado para o manipulador `PanResponder`, que é o `gestureState`. + +```jsx +onPanResponderMove={Animated.event( + [null, // ignora o evento nativo + // extraia dx e dy do gestureState + // como 'pan.x = gestureState.dx, pan.y = gestureState.dy' + {dx: pan.x, dy: pan.y} +])} +``` + +## PanResponder com exemplo de evento animado + +```jsx +import React, {useRef} from 'react'; +import {Animated, View, StyleSheet, PanResponder, Text} from 'react-native'; + +const App = () => { + const pan = useRef(new Animated.ValueXY()).current; + const panResponder = useRef( + PanResponder.create({ + onMoveShouldSetPanResponder: () => true, + onPanResponderMove: Animated.event([null, {dx: pan.x, dy: pan.y}]), + onPanResponderRelease: () => { + Animated.spring(pan, { + toValue: {x: 0, y: 0}, + useNativeDriver: true, + }).start(); + }, + }), + ).current; + + return ( + + Drag & Release this box! + + + + + ); +}; + +const styles = StyleSheet.create({ + container: { + flex: 1, + alignItems: 'center', + justifyContent: 'center', + }, + titleText: { + fontSize: 14, + lineHeight: 24, + fontWeight: 'bold', + }, + box: { + height: 150, + width: 150, + backgroundColor: 'blue', + borderRadius: 5, + }, +}); + +export default App; +``` + +![image](/docs/assets/294206249-2c01dacd-b0e9-4160-8f63-01d73c758f9b.png) + +## Respondendo ao valor atual da animação + +Você pode perceber que não há uma maneira clara de ler o valor atual durante a animação. Isso ocorre porque o valor só pode ser conhecido no tempo de execução nativo devido a otimizações. Se você precisar executar JavaScript em resposta ao valor atual, existem duas abordagens: + +* `spring.stopAnimation(callback)` interromperá a animação e invocará o retorno de chamada com o valor final. Isto é útil ao fazer transições de gestos. +* `spring.addListener(callback)` invocará o retorno de chamada de forma assíncrona enquanto a animação estiver em execução, fornecendo um valor recente. Isso é útil para acionar mudanças de estado, por exemplo, encaixar um bobble em uma nova opção conforme o usuário o arrasta para mais perto, porque essas mudanças de estado maiores são menos sensíveis a alguns quadros de atraso em comparação com gestos contínuos como o movimento panorâmico, que precisa ser executado a 60 fps. + +`Animated` foi projetado para ser totalmente serializável para que as animações possam ser executadas com alto desempenho, independentemente do loop de eventos normal do JavaScript. Isso influencia a API, então tenha isso em mente quando parecer um pouco mais complicado fazer algo em comparação com um sistema totalmente síncrono. Confira `Animated.Value.addListener` como uma forma de contornar algumas dessas limitações, mas use-o com moderação, pois pode ter implicações de desempenho no futuro. + +## Usando o driver nativo + +A API `Animated` foi projetada para ser serializável. Ao usar o [driver nativo](https://reactnative.dev/blog/2017/02/14/using-native-driver-for-animated), enviamos tudo sobre a animação para o nativo antes de iniciá-la, permitindo que o código nativo execute a animação no thread da UI sem ter que passar pela ponte em cada quadro. Depois que a animação for iniciada, o thread JS poderá ser bloqueado sem afetar a animação. + +O uso do driver nativo para animações normais pode ser feito definindo `useNativeDriver: true` na configuração da animação ao iniciá-la. Animações sem uma propriedade `useNativeDriver` serão padronizadas como false por motivos legados, mas emitirão um aviso (e erro de verificação de digitação no TypeScript). + +```js +Animated.timing(this.state.animatedValue, { + toValue: 1, + duration: 500, + useNativeDriver: true, // <-- Seta isso como true +}).start(); +``` + +Os valores animados são compatíveis apenas com um driver, portanto, se você usar o driver nativo ao iniciar uma animação em um valor, certifique-se de que cada animação nesse valor também use o driver nativo. + +O driver nativo também funciona com `Animated.event`. Isso é especialmente útil para animações que seguem a posição de rolagem, pois sem o driver nativo, a animação sempre executará um quadro atrás do gesto devido à natureza assíncrona do React Native. + +```jsx + + {content} + +``` + +Você pode ver o driver nativo em ação executando o [aplicativo RNTester](https://github.com/facebook/react-native/blob/main/packages/rn-tester/) e carregando o exemplo animado nativo. Você também pode dar uma olhada no [código-fonte](https://github.com/facebook/react-native/blob/master/packages/rn-tester/js/examples/NativeAnimation/NativeAnimationsExample.js) para saber como esses exemplos foram produzidos. + +## Ressalvas + +Nem tudo o que você pode fazer com o `Animated` é atualmente compatível com o driver nativo. A principal limitação é que você só pode animar propriedades que não sejam de layout: coisas como `transformation` e `opacity` funcionarão, mas Flexbox e propriedades de posição não. Ao usar `Animated.event`, ele funcionará apenas com eventos diretos e não com eventos "borbulhantes". Isso significa que ele não funciona com `PanResponder`, mas funciona com coisas como `ScrollView#onScroll`. + +Quando uma animação está em execução, ela pode impedir que os componentes `VirtualizedList` renderizem mais linhas. Se você precisar executar uma animação longa ou em loop enquanto o usuário percorre uma lista, você pode usar `isInteraction: false` na configuração da sua animação para evitar esse problema. + +## Tenha em mente + +Ao usar estilos de transformação, como `rotateY`, `rotateX` e outros, certifique-se de que a perspectiva do estilo de transformação esteja em vigor. No momento, algumas animações podem não ser renderizadas no Android sem ele. Exemplo abaixo. + +```jsx + +``` + +## Exemplos adicionais + +O aplicativo RNTester possui vários exemplos de `Animated` em uso: + +* [AnimatedGratuitousApp](https://github.com/facebook/react-native/tree/main/packages/rn-tester/js/examples/AnimatedGratuitousApp) +* [NativeAnimationsExample](https://github.com/facebook/react-native/blob/main/packages/rn-tester/js/examples/NativeAnimation/NativeAnimationsExample.js) + +## API `LayoutAnimation` +`LayoutAnimation` permite configurar globalmente, criar e atualizar animações que serão usadas para todas as visualizações no próximo ciclo de renderização/layout. Isto é útil para fazer atualizações de layout do Flexbox sem se preocupar em medir ou calcular propriedades específicas para animá-las diretamente, e é especialmente útil quando alterações de layout podem afetar ancestrais, por exemplo, uma expansão "veja mais" que também aumenta o tamanho do pai e empurra para baixo a linha abaixo, o que de outra forma exigiria coordenação explícita entre os componentes para animá-los todos em sincronia. + +Observe que, embora o `LayoutAnimation` seja muito poderoso e possa ser bastante útil, ele fornece muito menos controle do que o `Animated` e outras bibliotecas de animação, portanto, talvez seja necessário usar outra abordagem se não conseguir que o `LayoutAnimation` faça o que deseja. + +Observe que para que isso funcione no Android, você precisa definir os seguintes sinalizadores via `UIManager`: + +```java +UIManager.setLayoutAnimationEnabledExperimental(true); +``` + +```jsx +import React from 'react'; +import { + NativeModules, + LayoutAnimation, + Text, + TouchableOpacity, + StyleSheet, + View, +} from 'react-native'; + +const {UIManager} = NativeModules; + +UIManager.setLayoutAnimationEnabledExperimental && + UIManager.setLayoutAnimationEnabledExperimental(true); + +export default class App extends React.Component { + state = { + w: 100, + h: 100, + }; + + _onPress = () => { + // Animate the update + LayoutAnimation.spring(); + this.setState({w: this.state.w + 15, h: this.state.h + 15}); + }; + + render() { + return ( + + + + + Press me! + + + + ); + } +} + +const styles = StyleSheet.create({ + container: { + flex: 1, + alignItems: 'center', + justifyContent: 'center', + }, + box: { + width: 200, + height: 200, + backgroundColor: 'red', + }, + button: { + backgroundColor: 'black', + paddingHorizontal: 20, + paddingVertical: 15, + marginTop: 15, + }, + buttonText: { + color: '#fff', + fontWeight: 'bold', + }, +}); +``` + +![image](/docs/assets/294212416-ca6367a9-3d9d-46f2-bb61-8683320171dc.png) + +Este exemplo usa um valor predefinido, você pode personalizar as animações conforme necessário, consulte [LayoutAnimation.js](https://github.com/facebook/react-native/blob/main/packages/react-native/Libraries/LayoutAnimation/LayoutAnimation.js) para obter mais informações. + +## Notas Adicionais + +### `requestAnimationFrame` + +`requestAnimationFrame` é um polyfill do navegador com o qual você deve estar familiarizado. Ele aceita uma função como seu único argumento e chama essa função antes da próxima repintura. É um elemento essencial para animações que sustenta todas as APIs de animação baseadas em JavaScript. Em geral, você não precisa chamar isso sozinho - as APIs de animação gerenciarão as atualizações de quadros para você. + +### `setNativeProps` + +Conforme mencionado na seção [Manipulação Direta](/docs/direct-manipulation.md), `setNativeProps` nos permite modificar propriedades de componentes com suporte nativo (componentes que são realmente apoiados por visualizações nativas, ao contrário dos componentes compostos) diretamente, sem ter que `setState` renderizar novamente a hierarquia de componentes. + +Poderíamos usar isso no exemplo Rebound para atualizar a escala - isso pode ser útil se o componente que estamos atualizando estiver profundamente aninhado e não tiver sido otimizado com `shouldComponentUpdate`. + +Se você encontrar suas animações com queda de quadros (desempenho abaixo de 60 quadros por segundo), use `setNativeProps` ou `shouldComponentUpdate` para otimizá-las. Ou você pode executar as animações no thread da UI em vez do thread JavaScript [com a opção `useNativeDriver`](https://reactnative.dev/blog/2017/02/14/using-native-driver-for-animated). Você também pode adiar qualquer trabalho computacional intensivo até que as animações sejam concluídas, usando o [`InteractionManager`](/docs/interactionmanager.md). Você pode monitorar a taxa de quadros usando a ferramenta "FPS Monitor" do menu de desenvolvimento do aplicativo. diff --git a/vitepress/docs/docs/app-extensions.md b/vitepress/docs/docs/app-extensions.md new file mode 100644 index 0000000..10d7c43 --- /dev/null +++ b/vitepress/docs/docs/app-extensions.md @@ -0,0 +1,23 @@ +# Extensões de aplicativos + +As extensões de aplicativo permitem fornecer funcionalidade e conteúdo personalizados fora do aplicativo principal. Existem diferentes tipos de extensões de aplicativos no iOS, e todas elas são abordadas no [Guia de programação de extensões de aplicativos](https://developer.apple.com/library/content/documentation/General/Conceptual/ExtensibilityPG/index.html#//apple_ref/doc/uid/TP40014214-CH20-SW1). Neste guia, abordaremos brevemente como você pode aproveitar as vantagens das extensões de aplicativos no iOS. + +## Uso de memória em extensões + +Como essas extensões são carregadas fora da sandbox normal do aplicativo, é altamente provável que várias dessas extensões de aplicativo sejam carregadas simultaneamente. Como seria de esperar, essas extensões têm pequenos limites de uso de memória. Tenha isso em mente ao desenvolver suas extensões de aplicativo. É sempre altamente recomendável testar seu aplicativo em um dispositivo real, ainda mais ao desenvolver extensões de aplicativo: com muita frequência, os desenvolvedores descobrem que sua extensão funciona bem no simulador iOS, apenas para receber relatórios de usuários de que sua extensão não está carregando em dispositivos reais. + +É altamente recomendável que você assista à palestra de Conrad Kramer sobre [Uso de memória em extensões](https://www.youtube.com/watch?v=GqXMqn6MXrM) para saber mais sobre esse tópico. + +### Widget Today + +O limite de memória de um widget Hoje é de 16 MB. Acontece que as implementações do widget Today usando React Native podem não funcionar de maneira confiável porque o uso de memória tende a ser muito alto. Você pode saber se o widget Today está excedendo o limite de memória se exibir a mensagem 'Não é possível carregar': + +![image](https://github.com/tavaresgerson/reactnativedocbr/assets/22455192/f3da10aa-01c1-413a-b65f-d3fe8b3a127c) + +Sempre teste suas extensões de aplicativo em um dispositivo real, mas esteja ciente de que isso pode não ser suficiente, especialmente ao lidar com o widget Today. As compilações configuradas para depuração têm maior probabilidade de exceder os limites de memória, enquanto as compilações configuradas para versão não falham imediatamente. É altamente recomendável que você use [Instrumentos do Xcode](https://developer.apple.com/library/content/documentation/DeveloperTools/Conceptual/InstrumentsUserGuide/index.html) para analisar seu uso de memória no mundo real, pois é muito provável que sua compilação configurada para lançamento está muito próxima do limite de 16 MB. Em situações como essas, você pode ultrapassar rapidamente o limite de 16 MB executando operações comuns, como buscar dados de uma API. + +Para experimentar os limites das implementações do widget React Native Today, tente estender o projeto de exemplo em [react-native-today-widget](https://github.com/matejkriz/react-native-today-widget/). + +### Outras extensões de aplicativos + +Outros tipos de extensões de aplicativo têm limites de memória maiores que o widget Today. Por exemplo, as extensões de teclado personalizado são limitadas a 48 MB e as extensões de compartilhamento são limitadas a 120 MB. Implementar essas extensões de aplicativo com React Native é mais viável. Um exemplo de prova de conceito é [react-native-ios-share-extension](https://github.com/andrewsardone/react-native-ios-share-extension). diff --git a/vitepress/docs/docs/assets/288755758-175ae9d7-3e6d-42ba-9b12-a1e89bf0df53.png b/vitepress/docs/docs/assets/288755758-175ae9d7-3e6d-42ba-9b12-a1e89bf0df53.png new file mode 100644 index 0000000..ac91d56 Binary files /dev/null and b/vitepress/docs/docs/assets/288755758-175ae9d7-3e6d-42ba-9b12-a1e89bf0df53.png differ diff --git a/vitepress/docs/docs/assets/288759376-65fb76bd-40b8-4301-b292-a776ea55f17e.png b/vitepress/docs/docs/assets/288759376-65fb76bd-40b8-4301-b292-a776ea55f17e.png new file mode 100644 index 0000000..ec395ac Binary files /dev/null and b/vitepress/docs/docs/assets/288759376-65fb76bd-40b8-4301-b292-a776ea55f17e.png differ diff --git a/vitepress/docs/docs/assets/289078069-79daecf4-41df-45e4-bdfd-34120ecb2d9b.png b/vitepress/docs/docs/assets/289078069-79daecf4-41df-45e4-bdfd-34120ecb2d9b.png new file mode 100644 index 0000000..7ad4527 Binary files /dev/null and b/vitepress/docs/docs/assets/289078069-79daecf4-41df-45e4-bdfd-34120ecb2d9b.png differ diff --git a/vitepress/docs/docs/assets/289086561-8042a459-ead2-4b1a-ba59-41b673d9b7d8.png b/vitepress/docs/docs/assets/289086561-8042a459-ead2-4b1a-ba59-41b673d9b7d8.png new file mode 100644 index 0000000..6f64661 Binary files /dev/null and b/vitepress/docs/docs/assets/289086561-8042a459-ead2-4b1a-ba59-41b673d9b7d8.png differ diff --git a/vitepress/docs/docs/assets/289088717-bc864112-bd55-43b6-8369-9d78e896376e.png b/vitepress/docs/docs/assets/289088717-bc864112-bd55-43b6-8369-9d78e896376e.png new file mode 100644 index 0000000..45a6d80 Binary files /dev/null and b/vitepress/docs/docs/assets/289088717-bc864112-bd55-43b6-8369-9d78e896376e.png differ diff --git a/vitepress/docs/docs/assets/289275766-33a7f3de-c80c-47db-b195-35cf25023b27.png b/vitepress/docs/docs/assets/289275766-33a7f3de-c80c-47db-b195-35cf25023b27.png new file mode 100644 index 0000000..a3b8429 Binary files /dev/null and b/vitepress/docs/docs/assets/289275766-33a7f3de-c80c-47db-b195-35cf25023b27.png differ diff --git a/vitepress/docs/docs/assets/289276022-2b29397f-f3d1-41cb-a25c-84aff19487bf.png b/vitepress/docs/docs/assets/289276022-2b29397f-f3d1-41cb-a25c-84aff19487bf.png new file mode 100644 index 0000000..7ba7c8e Binary files /dev/null and b/vitepress/docs/docs/assets/289276022-2b29397f-f3d1-41cb-a25c-84aff19487bf.png differ diff --git a/vitepress/docs/docs/assets/289277030-71da2fbe-ea92-48ae-b243-edf07876a7db.png b/vitepress/docs/docs/assets/289277030-71da2fbe-ea92-48ae-b243-edf07876a7db.png new file mode 100644 index 0000000..6f69954 Binary files /dev/null and b/vitepress/docs/docs/assets/289277030-71da2fbe-ea92-48ae-b243-edf07876a7db.png differ diff --git a/vitepress/docs/docs/assets/289311225-21b28d91-4031-4e02-bbcd-0232c1c24a16.png b/vitepress/docs/docs/assets/289311225-21b28d91-4031-4e02-bbcd-0232c1c24a16.png new file mode 100644 index 0000000..6be3da7 Binary files /dev/null and b/vitepress/docs/docs/assets/289311225-21b28d91-4031-4e02-bbcd-0232c1c24a16.png differ diff --git a/vitepress/docs/docs/assets/289545377-702d32f5-610b-4bca-949f-c96a9fe79dca.png b/vitepress/docs/docs/assets/289545377-702d32f5-610b-4bca-949f-c96a9fe79dca.png new file mode 100644 index 0000000..6be3da7 Binary files /dev/null and b/vitepress/docs/docs/assets/289545377-702d32f5-610b-4bca-949f-c96a9fe79dca.png differ diff --git a/vitepress/docs/docs/assets/290205035-be5d7e97-b86c-4a0f-94d3-673886cc49a3.png b/vitepress/docs/docs/assets/290205035-be5d7e97-b86c-4a0f-94d3-673886cc49a3.png new file mode 100644 index 0000000..543a8b1 Binary files /dev/null and b/vitepress/docs/docs/assets/290205035-be5d7e97-b86c-4a0f-94d3-673886cc49a3.png differ diff --git a/vitepress/docs/docs/assets/290205319-78f78d6b-73ef-4e46-8ab7-ce74064bd2dc.png b/vitepress/docs/docs/assets/290205319-78f78d6b-73ef-4e46-8ab7-ce74064bd2dc.png new file mode 100644 index 0000000..7ad4527 Binary files /dev/null and b/vitepress/docs/docs/assets/290205319-78f78d6b-73ef-4e46-8ab7-ce74064bd2dc.png differ diff --git a/vitepress/docs/docs/assets/290218954-e41f72f9-dabc-4735-a4df-ab3260c30f3f.png b/vitepress/docs/docs/assets/290218954-e41f72f9-dabc-4735-a4df-ab3260c30f3f.png new file mode 100644 index 0000000..780974e Binary files /dev/null and b/vitepress/docs/docs/assets/290218954-e41f72f9-dabc-4735-a4df-ab3260c30f3f.png differ diff --git a/vitepress/docs/docs/assets/290220401-8f9b33a4-3f00-4caf-9be3-2d06a10584a5.png b/vitepress/docs/docs/assets/290220401-8f9b33a4-3f00-4caf-9be3-2d06a10584a5.png new file mode 100644 index 0000000..608fd2a Binary files /dev/null and b/vitepress/docs/docs/assets/290220401-8f9b33a4-3f00-4caf-9be3-2d06a10584a5.png differ diff --git a/vitepress/docs/docs/assets/290225173-8c00a858-3507-4de4-84e0-536c094532f8.png b/vitepress/docs/docs/assets/290225173-8c00a858-3507-4de4-84e0-536c094532f8.png new file mode 100644 index 0000000..0985c96 Binary files /dev/null and b/vitepress/docs/docs/assets/290225173-8c00a858-3507-4de4-84e0-536c094532f8.png differ diff --git a/vitepress/docs/docs/assets/290225251-23ad63ff-3ee2-4767-a7c0-438cc2c20ece.png b/vitepress/docs/docs/assets/290225251-23ad63ff-3ee2-4767-a7c0-438cc2c20ece.png new file mode 100644 index 0000000..b27be64 Binary files /dev/null and b/vitepress/docs/docs/assets/290225251-23ad63ff-3ee2-4767-a7c0-438cc2c20ece.png differ diff --git a/vitepress/docs/docs/assets/290534925-53598a14-4991-4f4f-bd8a-3d7ae572d75f.png b/vitepress/docs/docs/assets/290534925-53598a14-4991-4f4f-bd8a-3d7ae572d75f.png new file mode 100644 index 0000000..543a8b1 Binary files /dev/null and b/vitepress/docs/docs/assets/290534925-53598a14-4991-4f4f-bd8a-3d7ae572d75f.png differ diff --git a/vitepress/docs/docs/assets/290535034-455122e1-6d13-43b1-be26-6c88877f4e54.png b/vitepress/docs/docs/assets/290535034-455122e1-6d13-43b1-be26-6c88877f4e54.png new file mode 100644 index 0000000..7ad4527 Binary files /dev/null and b/vitepress/docs/docs/assets/290535034-455122e1-6d13-43b1-be26-6c88877f4e54.png differ diff --git a/vitepress/docs/docs/assets/290538855-9e4d1f61-8fdf-4853-8633-f0b21f3d35c5.png b/vitepress/docs/docs/assets/290538855-9e4d1f61-8fdf-4853-8633-f0b21f3d35c5.png new file mode 100644 index 0000000..780974e Binary files /dev/null and b/vitepress/docs/docs/assets/290538855-9e4d1f61-8fdf-4853-8633-f0b21f3d35c5.png differ diff --git a/vitepress/docs/docs/assets/290544113-9fdcdc6c-ffa1-473b-a408-2a469ffdf9e0.png b/vitepress/docs/docs/assets/290544113-9fdcdc6c-ffa1-473b-a408-2a469ffdf9e0.png new file mode 100644 index 0000000..0985c96 Binary files /dev/null and b/vitepress/docs/docs/assets/290544113-9fdcdc6c-ffa1-473b-a408-2a469ffdf9e0.png differ diff --git a/vitepress/docs/docs/assets/290544190-159b63d8-4f0f-4ead-b559-8a042697af4b.png b/vitepress/docs/docs/assets/290544190-159b63d8-4f0f-4ead-b559-8a042697af4b.png new file mode 100644 index 0000000..b27be64 Binary files /dev/null and b/vitepress/docs/docs/assets/290544190-159b63d8-4f0f-4ead-b559-8a042697af4b.png differ diff --git a/vitepress/docs/docs/assets/291728755-273dca85-faa0-47ae-91df-cadf50a8d93c.png b/vitepress/docs/docs/assets/291728755-273dca85-faa0-47ae-91df-cadf50a8d93c.png new file mode 100644 index 0000000..a6f18ae Binary files /dev/null and b/vitepress/docs/docs/assets/291728755-273dca85-faa0-47ae-91df-cadf50a8d93c.png differ diff --git a/vitepress/docs/docs/assets/291729573-749ebf4e-e79c-40ba-aba4-d53d68980d2e.png b/vitepress/docs/docs/assets/291729573-749ebf4e-e79c-40ba-aba4-d53d68980d2e.png new file mode 100644 index 0000000..cec9143 Binary files /dev/null and b/vitepress/docs/docs/assets/291729573-749ebf4e-e79c-40ba-aba4-d53d68980d2e.png differ diff --git a/vitepress/docs/docs/assets/291729726-29d54dfe-1e52-4825-a725-72ef104637f6.png b/vitepress/docs/docs/assets/291729726-29d54dfe-1e52-4825-a725-72ef104637f6.png new file mode 100644 index 0000000..36326a7 Binary files /dev/null and b/vitepress/docs/docs/assets/291729726-29d54dfe-1e52-4825-a725-72ef104637f6.png differ diff --git a/vitepress/docs/docs/assets/291731440-2a8a10d3-4846-4c5a-8596-b4fcd74b8557.png b/vitepress/docs/docs/assets/291731440-2a8a10d3-4846-4c5a-8596-b4fcd74b8557.png new file mode 100644 index 0000000..1f8a86f Binary files /dev/null and b/vitepress/docs/docs/assets/291731440-2a8a10d3-4846-4c5a-8596-b4fcd74b8557.png differ diff --git a/vitepress/docs/docs/assets/292772852-0deb095f-2dad-4820-a016-80af6859988f.png b/vitepress/docs/docs/assets/292772852-0deb095f-2dad-4820-a016-80af6859988f.png new file mode 100644 index 0000000..b59cd3f Binary files /dev/null and b/vitepress/docs/docs/assets/292772852-0deb095f-2dad-4820-a016-80af6859988f.png differ diff --git a/vitepress/docs/docs/assets/292773053-a4122196-ebac-4823-a5d2-ad40bbaa0c04.png b/vitepress/docs/docs/assets/292773053-a4122196-ebac-4823-a5d2-ad40bbaa0c04.png new file mode 100644 index 0000000..36d91b8 Binary files /dev/null and b/vitepress/docs/docs/assets/292773053-a4122196-ebac-4823-a5d2-ad40bbaa0c04.png differ diff --git a/vitepress/docs/docs/assets/292773120-12b6a5d4-c776-4d9e-bc8b-8d1a820703ec.png b/vitepress/docs/docs/assets/292773120-12b6a5d4-c776-4d9e-bc8b-8d1a820703ec.png new file mode 100644 index 0000000..8953e01 Binary files /dev/null and b/vitepress/docs/docs/assets/292773120-12b6a5d4-c776-4d9e-bc8b-8d1a820703ec.png differ diff --git a/vitepress/docs/docs/assets/292773486-70cbd054-9b64-4739-b47f-393071ba0a10.png b/vitepress/docs/docs/assets/292773486-70cbd054-9b64-4739-b47f-393071ba0a10.png new file mode 100644 index 0000000..58b7724 Binary files /dev/null and b/vitepress/docs/docs/assets/292773486-70cbd054-9b64-4739-b47f-393071ba0a10.png differ diff --git a/vitepress/docs/docs/assets/292773723-4e84051a-1fec-4af3-9247-f77801e5cf2f.png b/vitepress/docs/docs/assets/292773723-4e84051a-1fec-4af3-9247-f77801e5cf2f.png new file mode 100644 index 0000000..98b5acd Binary files /dev/null and b/vitepress/docs/docs/assets/292773723-4e84051a-1fec-4af3-9247-f77801e5cf2f.png differ diff --git a/vitepress/docs/docs/assets/292774360-4866ca27-dcd8-44d5-bc7f-d5cc864c7569.png b/vitepress/docs/docs/assets/292774360-4866ca27-dcd8-44d5-bc7f-d5cc864c7569.png new file mode 100644 index 0000000..361c421 Binary files /dev/null and b/vitepress/docs/docs/assets/292774360-4866ca27-dcd8-44d5-bc7f-d5cc864c7569.png differ diff --git a/vitepress/docs/docs/assets/292776696-6843784a-f791-4bd5-ab46-4ff7474071a4.png b/vitepress/docs/docs/assets/292776696-6843784a-f791-4bd5-ab46-4ff7474071a4.png new file mode 100644 index 0000000..ea0a944 Binary files /dev/null and b/vitepress/docs/docs/assets/292776696-6843784a-f791-4bd5-ab46-4ff7474071a4.png differ diff --git a/vitepress/docs/docs/assets/292776780-7a00c116-9d7b-447f-a495-06d36b22412a.png b/vitepress/docs/docs/assets/292776780-7a00c116-9d7b-447f-a495-06d36b22412a.png new file mode 100644 index 0000000..44e753d Binary files /dev/null and b/vitepress/docs/docs/assets/292776780-7a00c116-9d7b-447f-a495-06d36b22412a.png differ diff --git a/vitepress/docs/docs/assets/292776889-1c43a42c-e7d9-4023-ba05-acdc68054c4d.png b/vitepress/docs/docs/assets/292776889-1c43a42c-e7d9-4023-ba05-acdc68054c4d.png new file mode 100644 index 0000000..4bd520d Binary files /dev/null and b/vitepress/docs/docs/assets/292776889-1c43a42c-e7d9-4023-ba05-acdc68054c4d.png differ diff --git a/vitepress/docs/docs/assets/292777024-b01e455d-d2d3-435e-9208-6b8fc11c3afb.png b/vitepress/docs/docs/assets/292777024-b01e455d-d2d3-435e-9208-6b8fc11c3afb.png new file mode 100644 index 0000000..9778bde Binary files /dev/null and b/vitepress/docs/docs/assets/292777024-b01e455d-d2d3-435e-9208-6b8fc11c3afb.png differ diff --git a/vitepress/docs/docs/assets/292777301-a9a5c486-b7e3-4f15-964d-678cc622e8d7.png b/vitepress/docs/docs/assets/292777301-a9a5c486-b7e3-4f15-964d-678cc622e8d7.png new file mode 100644 index 0000000..4b3164d Binary files /dev/null and b/vitepress/docs/docs/assets/292777301-a9a5c486-b7e3-4f15-964d-678cc622e8d7.png differ diff --git a/vitepress/docs/docs/assets/292777538-c0bbee71-c62d-4873-8d20-e04598d39a8a.png b/vitepress/docs/docs/assets/292777538-c0bbee71-c62d-4873-8d20-e04598d39a8a.png new file mode 100644 index 0000000..fe5d0b4 Binary files /dev/null and b/vitepress/docs/docs/assets/292777538-c0bbee71-c62d-4873-8d20-e04598d39a8a.png differ diff --git a/vitepress/docs/docs/assets/292777602-6f4ee12a-ddac-4dfb-9516-c093cc9282f0.png b/vitepress/docs/docs/assets/292777602-6f4ee12a-ddac-4dfb-9516-c093cc9282f0.png new file mode 100644 index 0000000..b8d1655 Binary files /dev/null and b/vitepress/docs/docs/assets/292777602-6f4ee12a-ddac-4dfb-9516-c093cc9282f0.png differ diff --git a/vitepress/docs/docs/assets/292777671-998be8d3-8e5f-4541-a938-0b3c016991ea.png b/vitepress/docs/docs/assets/292777671-998be8d3-8e5f-4541-a938-0b3c016991ea.png new file mode 100644 index 0000000..164a73a Binary files /dev/null and b/vitepress/docs/docs/assets/292777671-998be8d3-8e5f-4541-a938-0b3c016991ea.png differ diff --git a/vitepress/docs/docs/assets/294049976-589c99ab-cfb1-4274-bdea-e1c6c630adee.png b/vitepress/docs/docs/assets/294049976-589c99ab-cfb1-4274-bdea-e1c6c630adee.png new file mode 100644 index 0000000..4ee3006 Binary files /dev/null and b/vitepress/docs/docs/assets/294049976-589c99ab-cfb1-4274-bdea-e1c6c630adee.png differ diff --git a/vitepress/docs/docs/assets/294050118-afc6df54-903b-4821-8e0d-e57a396d126f.png b/vitepress/docs/docs/assets/294050118-afc6df54-903b-4821-8e0d-e57a396d126f.png new file mode 100644 index 0000000..9cfb491 Binary files /dev/null and b/vitepress/docs/docs/assets/294050118-afc6df54-903b-4821-8e0d-e57a396d126f.png differ diff --git a/vitepress/docs/docs/assets/294050559-b6bcc0f9-8745-4ead-ac9b-98a7cf92ef38.png b/vitepress/docs/docs/assets/294050559-b6bcc0f9-8745-4ead-ac9b-98a7cf92ef38.png new file mode 100644 index 0000000..c6b8459 Binary files /dev/null and b/vitepress/docs/docs/assets/294050559-b6bcc0f9-8745-4ead-ac9b-98a7cf92ef38.png differ diff --git a/vitepress/docs/docs/assets/294185554-0a53d571-a6d4-4d9c-8473-e1a497cb4771.png b/vitepress/docs/docs/assets/294185554-0a53d571-a6d4-4d9c-8473-e1a497cb4771.png new file mode 100644 index 0000000..cbb31a0 Binary files /dev/null and b/vitepress/docs/docs/assets/294185554-0a53d571-a6d4-4d9c-8473-e1a497cb4771.png differ diff --git a/vitepress/docs/docs/assets/294203476-c38ee8dd-d990-491b-ac01-5940b5237aeb.png b/vitepress/docs/docs/assets/294203476-c38ee8dd-d990-491b-ac01-5940b5237aeb.png new file mode 100644 index 0000000..85b7cb3 Binary files /dev/null and b/vitepress/docs/docs/assets/294203476-c38ee8dd-d990-491b-ac01-5940b5237aeb.png differ diff --git a/vitepress/docs/docs/assets/294206249-2c01dacd-b0e9-4160-8f63-01d73c758f9b.png b/vitepress/docs/docs/assets/294206249-2c01dacd-b0e9-4160-8f63-01d73c758f9b.png new file mode 100644 index 0000000..55b6134 Binary files /dev/null and b/vitepress/docs/docs/assets/294206249-2c01dacd-b0e9-4160-8f63-01d73c758f9b.png differ diff --git a/vitepress/docs/docs/assets/294212416-ca6367a9-3d9d-46f2-bb61-8683320171dc.png b/vitepress/docs/docs/assets/294212416-ca6367a9-3d9d-46f2-bb61-8683320171dc.png new file mode 100644 index 0000000..7e1d025 Binary files /dev/null and b/vitepress/docs/docs/assets/294212416-ca6367a9-3d9d-46f2-bb61-8683320171dc.png differ diff --git a/vitepress/docs/docs/assets/298200622-2dd8fd0b-c69c-41c3-a787-87e4f7ffe95c.png b/vitepress/docs/docs/assets/298200622-2dd8fd0b-c69c-41c3-a787-87e4f7ffe95c.png new file mode 100644 index 0000000..7ffc3b2 Binary files /dev/null and b/vitepress/docs/docs/assets/298200622-2dd8fd0b-c69c-41c3-a787-87e4f7ffe95c.png differ diff --git a/vitepress/docs/docs/assets/307929568-c4514d57-633d-48d7-acd8-85b15c785dee.png b/vitepress/docs/docs/assets/307929568-c4514d57-633d-48d7-acd8-85b15c785dee.png new file mode 100644 index 0000000..962c0b7 Binary files /dev/null and b/vitepress/docs/docs/assets/307929568-c4514d57-633d-48d7-acd8-85b15c785dee.png differ diff --git a/vitepress/docs/docs/assets/309739868-01361acc-6dcc-4519-a990-1e00dd02c666.png b/vitepress/docs/docs/assets/309739868-01361acc-6dcc-4519-a990-1e00dd02c666.png new file mode 100644 index 0000000..61d356e Binary files /dev/null and b/vitepress/docs/docs/assets/309739868-01361acc-6dcc-4519-a990-1e00dd02c666.png differ diff --git a/vitepress/docs/docs/assets/309740243-cc8fe788-5dbb-40ee-aceb-aa74e4ed643b.png b/vitepress/docs/docs/assets/309740243-cc8fe788-5dbb-40ee-aceb-aa74e4ed643b.png new file mode 100644 index 0000000..e6b2afd Binary files /dev/null and b/vitepress/docs/docs/assets/309740243-cc8fe788-5dbb-40ee-aceb-aa74e4ed643b.png differ diff --git a/vitepress/docs/docs/assets/309740399-f4fc05d5-38e3-4110-ba1f-0cce24307f9e.png b/vitepress/docs/docs/assets/309740399-f4fc05d5-38e3-4110-ba1f-0cce24307f9e.png new file mode 100644 index 0000000..baf1ef1 Binary files /dev/null and b/vitepress/docs/docs/assets/309740399-f4fc05d5-38e3-4110-ba1f-0cce24307f9e.png differ diff --git a/vitepress/docs/docs/assets/312113267-388b181e-16bd-4444-a586-8efcfe5e5da4.png b/vitepress/docs/docs/assets/312113267-388b181e-16bd-4444-a586-8efcfe5e5da4.png new file mode 100644 index 0000000..9ee1131 Binary files /dev/null and b/vitepress/docs/docs/assets/312113267-388b181e-16bd-4444-a586-8efcfe5e5da4.png differ diff --git a/vitepress/docs/docs/assets/312120479-2e3ad0ad-158e-44f9-9380-766c60734ef3.png b/vitepress/docs/docs/assets/312120479-2e3ad0ad-158e-44f9-9380-766c60734ef3.png new file mode 100644 index 0000000..81e9548 Binary files /dev/null and b/vitepress/docs/docs/assets/312120479-2e3ad0ad-158e-44f9-9380-766c60734ef3.png differ diff --git a/vitepress/docs/docs/assets/312123307-6526427d-5ece-4ed1-b980-a84cfb4b2ff1.png b/vitepress/docs/docs/assets/312123307-6526427d-5ece-4ed1-b980-a84cfb4b2ff1.png new file mode 100644 index 0000000..8d5e905 Binary files /dev/null and b/vitepress/docs/docs/assets/312123307-6526427d-5ece-4ed1-b980-a84cfb4b2ff1.png differ diff --git a/vitepress/docs/docs/assets/312123621-2ed9b518-98c0-4a67-85f2-5524997c72d9.png b/vitepress/docs/docs/assets/312123621-2ed9b518-98c0-4a67-85f2-5524997c72d9.png new file mode 100644 index 0000000..1098cf0 Binary files /dev/null and b/vitepress/docs/docs/assets/312123621-2ed9b518-98c0-4a67-85f2-5524997c72d9.png differ diff --git a/vitepress/docs/docs/assets/312123846-8e11055e-5ac9-4da6-a9da-cd4d854a3779.png b/vitepress/docs/docs/assets/312123846-8e11055e-5ac9-4da6-a9da-cd4d854a3779.png new file mode 100644 index 0000000..1f03d8c Binary files /dev/null and b/vitepress/docs/docs/assets/312123846-8e11055e-5ac9-4da6-a9da-cd4d854a3779.png differ diff --git a/vitepress/docs/docs/assets/313493455-1a5c12f5-6368-4675-af20-051a7cb2598b.png b/vitepress/docs/docs/assets/313493455-1a5c12f5-6368-4675-af20-051a7cb2598b.png new file mode 100644 index 0000000..a5d190a Binary files /dev/null and b/vitepress/docs/docs/assets/313493455-1a5c12f5-6368-4675-af20-051a7cb2598b.png differ diff --git a/vitepress/docs/docs/assets/313493538-f05df190-b27f-4511-8554-ee5dc86efcb2.png b/vitepress/docs/docs/assets/313493538-f05df190-b27f-4511-8554-ee5dc86efcb2.png new file mode 100644 index 0000000..320a1b9 Binary files /dev/null and b/vitepress/docs/docs/assets/313493538-f05df190-b27f-4511-8554-ee5dc86efcb2.png differ diff --git a/vitepress/docs/docs/assets/313495844-578b6da9-b01c-4b00-a7fb-9bd4be45b912.png b/vitepress/docs/docs/assets/313495844-578b6da9-b01c-4b00-a7fb-9bd4be45b912.png new file mode 100644 index 0000000..e47b109 Binary files /dev/null and b/vitepress/docs/docs/assets/313495844-578b6da9-b01c-4b00-a7fb-9bd4be45b912.png differ diff --git a/vitepress/docs/docs/assets/313500818-99069c93-a869-4b6e-bb50-b101c0c029ad.png b/vitepress/docs/docs/assets/313500818-99069c93-a869-4b6e-bb50-b101c0c029ad.png new file mode 100644 index 0000000..0903890 Binary files /dev/null and b/vitepress/docs/docs/assets/313500818-99069c93-a869-4b6e-bb50-b101c0c029ad.png differ diff --git a/vitepress/docs/docs/assets/313507258-a79717d3-36f2-41a5-b120-dd2bc51232eb.png b/vitepress/docs/docs/assets/313507258-a79717d3-36f2-41a5-b120-dd2bc51232eb.png new file mode 100644 index 0000000..e4089ad Binary files /dev/null and b/vitepress/docs/docs/assets/313507258-a79717d3-36f2-41a5-b120-dd2bc51232eb.png differ diff --git a/vitepress/docs/docs/assets/313507304-f06738b3-4be6-4734-8bea-1f87556a0df3.png b/vitepress/docs/docs/assets/313507304-f06738b3-4be6-4734-8bea-1f87556a0df3.png new file mode 100644 index 0000000..d0c326a Binary files /dev/null and b/vitepress/docs/docs/assets/313507304-f06738b3-4be6-4734-8bea-1f87556a0df3.png differ diff --git a/vitepress/docs/docs/assets/313508003-11f8175a-c432-4050-91e5-88b84a5d726b.png b/vitepress/docs/docs/assets/313508003-11f8175a-c432-4050-91e5-88b84a5d726b.png new file mode 100644 index 0000000..0504cd8 Binary files /dev/null and b/vitepress/docs/docs/assets/313508003-11f8175a-c432-4050-91e5-88b84a5d726b.png differ diff --git a/vitepress/docs/docs/assets/321053647-821ddb0c-400a-4139-8e72-56f6ed73743c.png b/vitepress/docs/docs/assets/321053647-821ddb0c-400a-4139-8e72-56f6ed73743c.png new file mode 100644 index 0000000..5e59173 Binary files /dev/null and b/vitepress/docs/docs/assets/321053647-821ddb0c-400a-4139-8e72-56f6ed73743c.png differ diff --git a/vitepress/docs/docs/assets/321053704-feda8ef3-32b9-484c-8413-23d09d8d08d3.png b/vitepress/docs/docs/assets/321053704-feda8ef3-32b9-484c-8413-23d09d8d08d3.png new file mode 100644 index 0000000..aa8db8c Binary files /dev/null and b/vitepress/docs/docs/assets/321053704-feda8ef3-32b9-484c-8413-23d09d8d08d3.png differ diff --git a/vitepress/docs/docs/assets/321054351-b9a3e3bb-5c9b-43a7-9819-f638fbfa64a9.png b/vitepress/docs/docs/assets/321054351-b9a3e3bb-5c9b-43a7-9819-f638fbfa64a9.png new file mode 100644 index 0000000..960c16c Binary files /dev/null and b/vitepress/docs/docs/assets/321054351-b9a3e3bb-5c9b-43a7-9819-f638fbfa64a9.png differ diff --git a/vitepress/docs/docs/assets/321064922-2e21e8bb-a216-416b-9690-09a883198c52.png b/vitepress/docs/docs/assets/321064922-2e21e8bb-a216-416b-9690-09a883198c52.png new file mode 100644 index 0000000..f17d2da Binary files /dev/null and b/vitepress/docs/docs/assets/321064922-2e21e8bb-a216-416b-9690-09a883198c52.png differ diff --git a/vitepress/docs/docs/assets/PerfUtil-38a2ddbf1777887d70563a644c72aa64.png b/vitepress/docs/docs/assets/PerfUtil-38a2ddbf1777887d70563a644c72aa64.png new file mode 100644 index 0000000..c37353d Binary files /dev/null and b/vitepress/docs/docs/assets/PerfUtil-38a2ddbf1777887d70563a644c72aa64.png differ diff --git a/vitepress/docs/docs/assets/ReactDevToolsConnection-2fcfc362befab4699fd8afceefa5903e.gif b/vitepress/docs/docs/assets/ReactDevToolsConnection-2fcfc362befab4699fd8afceefa5903e.gif new file mode 100644 index 0000000..55947bd Binary files /dev/null and b/vitepress/docs/docs/assets/ReactDevToolsConnection-2fcfc362befab4699fd8afceefa5903e.gif differ diff --git a/vitepress/docs/docs/assets/ReactDevToolsInspector-fed7286dac8ef8a793245cdd9d3d0f9c.gif b/vitepress/docs/docs/assets/ReactDevToolsInspector-fed7286dac8ef8a793245cdd9d3d0f9c.gif new file mode 100644 index 0000000..b4b9144 Binary files /dev/null and b/vitepress/docs/docs/assets/ReactDevToolsInspector-fed7286dac8ef8a793245cdd9d3d0f9c.gif differ diff --git a/vitepress/docs/docs/assets/async-on-layout.gif b/vitepress/docs/docs/assets/async-on-layout.gif new file mode 100644 index 0000000..82fa165 Binary files /dev/null and b/vitepress/docs/docs/assets/async-on-layout.gif differ diff --git a/vitepress/docs/docs/assets/d_security_chart.svg b/vitepress/docs/docs/assets/d_security_chart.svg new file mode 100644 index 0000000..4a95700 --- /dev/null +++ b/vitepress/docs/docs/assets/d_security_chart.svg @@ -0,0 +1 @@ +likelihood of a breacheffort invested in security \ No newline at end of file diff --git a/vitepress/docs/docs/assets/d_security_deep-linking.svg b/vitepress/docs/docs/assets/d_security_deep-linking.svg new file mode 100644 index 0000000..5030e84 --- /dev/null +++ b/vitepress/docs/docs/assets/d_security_deep-linking.svg @@ -0,0 +1 @@ +app://user datadeep linking \ No newline at end of file diff --git a/vitepress/docs/docs/assets/diagram_ios-android-views.svg b/vitepress/docs/docs/assets/diagram_ios-android-views.svg new file mode 100644 index 0000000..0c0b215 --- /dev/null +++ b/vitepress/docs/docs/assets/diagram_ios-android-views.svg @@ -0,0 +1 @@ +PouncivalUIViewUIImageViewUITextViewViewGroupImageViewTextViewChoupetteMrs. NorrisTunaTabbyRum Tum TuggerPouncivalSpotMaruCat Cafe MenuChoupetteMrs. NorrisTunaTabbyRum Tum TuggerPouncivalSpotMaruCat Cafe Menu \ No newline at end of file diff --git a/vitepress/docs/docs/assets/diagram_react-native-components.svg b/vitepress/docs/docs/assets/diagram_react-native-components.svg new file mode 100644 index 0000000..643dd4b --- /dev/null +++ b/vitepress/docs/docs/assets/diagram_react-native-components.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/vitepress/docs/docs/assets/diagram_testing.svg b/vitepress/docs/docs/assets/diagram_testing.svg new file mode 100644 index 0000000..5aa356d --- /dev/null +++ b/vitepress/docs/docs/assets/diagram_testing.svg @@ -0,0 +1 @@ +testfixfailpassrelease \ No newline at end of file diff --git a/vitepress/docs/docs/assets/download.png b/vitepress/docs/docs/assets/download.png new file mode 100644 index 0000000..2c87251 Binary files /dev/null and b/vitepress/docs/docs/assets/download.png differ diff --git a/vitepress/docs/docs/assets/legacy-renderer.gif b/vitepress/docs/docs/assets/legacy-renderer.gif new file mode 100644 index 0000000..75f4149 Binary files /dev/null and b/vitepress/docs/docs/assets/legacy-renderer.gif differ diff --git a/vitepress/docs/docs/assets/p_tests-component.svg b/vitepress/docs/docs/assets/p_tests-component.svg new file mode 100644 index 0000000..85554c0 --- /dev/null +++ b/vitepress/docs/docs/assets/p_tests-component.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/vitepress/docs/docs/assets/p_tests-e2e.svg b/vitepress/docs/docs/assets/p_tests-e2e.svg new file mode 100644 index 0000000..08bb956 --- /dev/null +++ b/vitepress/docs/docs/assets/p_tests-e2e.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/vitepress/docs/docs/assets/p_tests-integration.svg b/vitepress/docs/docs/assets/p_tests-integration.svg new file mode 100644 index 0000000..0586f17 --- /dev/null +++ b/vitepress/docs/docs/assets/p_tests-integration.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/vitepress/docs/docs/assets/p_tests-snapshot.svg b/vitepress/docs/docs/assets/p_tests-snapshot.svg new file mode 100644 index 0000000..bef80d7 --- /dev/null +++ b/vitepress/docs/docs/assets/p_tests-snapshot.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/vitepress/docs/docs/assets/p_tests-unit.svg b/vitepress/docs/docs/assets/p_tests-unit.svg new file mode 100644 index 0000000..8e4a560 --- /dev/null +++ b/vitepress/docs/docs/assets/p_tests-unit.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/vitepress/docs/docs/assets/react18-renderer.gif b/vitepress/docs/docs/assets/react18-renderer.gif new file mode 100644 index 0000000..c3ef44c Binary files /dev/null and b/vitepress/docs/docs/assets/react18-renderer.gif differ diff --git a/vitepress/docs/docs/assets/sync-use-layout-effect.gif b/vitepress/docs/docs/assets/sync-use-layout-effect.gif new file mode 100644 index 0000000..2075d6a Binary files /dev/null and b/vitepress/docs/docs/assets/sync-use-layout-effect.gif differ diff --git a/vitepress/docs/docs/assets/with-transitions.gif b/vitepress/docs/docs/assets/with-transitions.gif new file mode 100644 index 0000000..8d85d34 Binary files /dev/null and b/vitepress/docs/docs/assets/with-transitions.gif differ diff --git a/vitepress/docs/docs/assets/without-transitions.gif b/vitepress/docs/docs/assets/without-transitions.gif new file mode 100644 index 0000000..3e42e58 Binary files /dev/null and b/vitepress/docs/docs/assets/without-transitions.gif differ diff --git a/vitepress/docs/docs/build-speed.md b/vitepress/docs/docs/build-speed.md new file mode 100644 index 0000000..041b1e7 --- /dev/null +++ b/vitepress/docs/docs/build-speed.md @@ -0,0 +1,180 @@ +# Acelerando sua fase de construção + +Construir seu aplicativo React Native pode ser caro e levar vários minutos do tempo dos desenvolvedores. Isso pode ser problemático à medida que seu projeto cresce e geralmente em organizações maiores com vários desenvolvedores React Native. + +Para mitigar esse impacto no desempenho, esta página compartilha algumas sugestões sobre como melhorar o tempo de construção. + +::: info **INFORMAÇÕES** +Se você notar um tempo de construção mais lento com a nova arquitetura no Android, recomendamos atualizar para o React Native 0.71 +::: + +## Crie apenas uma ABI durante o desenvolvimento (somente Android) + +Ao construir seu aplicativo Android localmente, por padrão você constrói todas as [4 interfaces binárias de aplicativo](https://developer.android.com/ndk/guides/abis) (ABIs): `armeabi-v7a`, `arm64-v8a`, `x86` e `x86_64`. + +No entanto, você provavelmente não precisará compilar todos eles se estiver compilando localmente e testando seu emulador ou em um dispositivo físico. + +Isso deve reduzir o tempo de construção nativo em um fator de aproximadamente 75%. + +Se estiver usando o React Native CLI, você pode adicionar o sinalizador `--active-arch-only` ao comando run-Android. Este sinalizador garantirá que a ABI correta seja obtida no emulador em execução ou no telefone conectado. Para confirmar se essa abordagem está funcionando bem, você verá uma mensagem como `info Detected Architectures arm64-v8a` no console. + +```bash +$ yarn react-native run-android --active-arch-only + +[ ... ] +info Running jetifier to migrate libraries to AndroidX. You can disable it using "--no-jetifier" flag. +Jetifier found 1037 file(s) to forward-jetify. Using 32 workers... +info JS server already running. +info Detected architectures arm64-v8a +info Installing the app... +``` + +Este mecanismo depende da propriedade `reactNativeArchitectures` do Gradle. + +Portanto, se você estiver compilando diretamente com o Gradle na linha de comando e sem a CLI, poderá especificar a ABI que deseja compilar da seguinte maneira: + +```bash +$ ./gradlew :app:assembleDebug -PreactNativeArchitectures=x86,x86_64 +``` + +Isso pode ser útil se você deseja construir seu aplicativo Android em um CI e usar uma matriz para paralelizar a construção das diferentes arquiteturas. + +Se desejar, você também pode substituir esse valor localmente, usando o arquivo `gradle.properties` que você possui na pasta de nível superior do seu projeto: + +```bash +# Use esta propriedade para especificar qual arquitetura você deseja construir. +# Você também pode substituí-lo na CLI usando +# ./gradlew -PreactNativeArchitectures=x86_64 +reactNativeArchitectures=armeabi-v7a,arm64-v8a,x86,x86_64 +``` + +Depois de criar uma versão de lançamento do seu aplicativo, não se esqueça de remover esses sinalizadores, pois deseja criar um pacote apk/app que funcione para todas as ABIs e não apenas para aquela que você está usando em seu fluxo de trabalho de desenvolvimento diário. + +## Use um cache do compilador + +Se você estiver executando compilações nativas frequentes (C++ ou Objective-C), poderá se beneficiar do uso de um cache do compilador. + +Especificamente, você pode usar dois tipos de caches: caches de compilador local e caches de compilador distribuídos. + +### Caches locais + +::: info **INFORMAÇÕES** +As instruções a seguir funcionarão para Android e iOS. Se você estiver criando apenas aplicativos Android, você deve estar pronto. Se você também estiver criando aplicativos iOS, siga as instruções na seção Configuração específica do XCode abaixo. +::: + +Sugerimos usar o [ccache](https://ccache.dev/) para armazenar em cache a compilação de suas compilações nativas. O **Ccache** funciona agrupando os compiladores C++, armazenando os resultados da compilação e ignorando a compilação se um resultado intermediário da compilação tiver sido originalmente armazenado. + +Para instalá-lo, você pode seguir as [instruções oficiais de instalação](https://github.com/ccache/ccache/blob/master/doc/INSTALL.md). + +No macOS, podemos instalar o **ccache** com `brew install ccache`. Depois de instalado, você pode configurá-lo da seguinte maneira para armazenar em cache os resultados da compilação do NDK: + +```bash +ln -s $(which ccache) /usr/local/bin/gcc +ln -s $(which ccache) /usr/local/bin/g++ +ln -s $(which ccache) /usr/local/bin/cc +ln -s $(which ccache) /usr/local/bin/c++ +ln -s $(which ccache) /usr/local/bin/clang +ln -s $(which ccache) /usr/local/bin/clang++ +``` + +Isso criará links simbólicos para o `ccache` dentro do `/usr/local/bin/` que são chamados de `gcc`, `g++` e assim por diante. + +Isso funciona desde que `/usr/local/bin/` venha primeiro que `/usr/bin/` dentro de sua variável `$PATH`, que é o padrão. + +Você pode verificar se funciona usando o comando `which`: + +```bash +$ which gcc +/usr/local/bin/gcc +``` + +Se o resultado for `/usr/local/bin/gcc`, então você está efetivamente chamando o `ccache`, que agrupará as chamadas do `gcc`. + +::: warning **CUIDADO** +Observe que esta configuração do `ccache` afetará todas as compilações que você está executando em sua máquina, não apenas aquelas relacionadas ao React Native. Use-o por sua conta e risco. Se você não conseguir instalar/compilar outro software, esse pode ser o motivo. Se for esse o caso, você pode remover o link simbólico criado com: + +```bash +unlink /usr/local/bin/gcc +unlink /usr/local/bin/g++ +unlink /usr/local/bin/cc +unlink /usr/local/bin/c++ +unlink /usr/local/bin/clang +unlink /usr/local/bin/clang++ +``` +para reverter sua máquina ao status original e usar os compiladores padrão. +::: + +Você pode então fazer duas compilações limpas (por exemplo, no Android você pode primeiro executar o `yarn react-native run-android`, excluir a pasta `android/app/build` e executar o primeiro comando mais uma vez). Você notará que a segunda compilação foi muito mais rápida que a primeira (deve levar segundos em vez de minutos). Durante a construção, você pode verificar se o `ccache` funciona corretamente e verificar a taxa de acertos/erros do cache `ccache -s` + +```bash +$ ccache -s +Summary: + Hits: 196 / 3068 (6.39 %) + Direct: 0 / 3068 (0.00 %) + Preprocessed: 196 / 3068 (6.39 %) + Misses: 2872 + Direct: 3068 + Preprocessed: 2872 + Uncacheable: 1 +Primary storage: + Hits: 196 / 6136 (3.19 %) + Misses: 5940 + Cache size (GB): 0.60 / 20.00 (3.00 %) +``` + +Observe que o `ccache` agrega as estatísticas de todas as compilações. Você pode usar `ccache --zero-stats` para redefini-los antes de uma compilação para verificar a taxa de acertos do cache. + +Se precisar limpar seu cache, você pode fazer isso com `ccache --clear` + +### Configuração específica do XCode + +Para garantir que o `ccache` funcione corretamente com iOS e XCode, você precisa seguir algumas etapas extras: + +1. Você deve alterar a forma como o Xcode e o `xcodebuild` chamam o comando do compilador. Por padrão eles usam caminhos totalmente especificados para os binários do compilador, portanto os links simbólicos instalados em `/usr/local/bin` não serão usados. Você pode configurar o Xcode para usar nomes relativos para os compiladores usando qualquer uma destas duas opções: + * Variáveis de ambiente prefixadas na linha de comando se você usar uma linha de comando direta: `CLANG=clang CLANGPLUSPLUS=clang++ LD=clang LDPLUSPLUS=clang++ xcodebuild ` + * Uma seção `post_install` em seu `ios/Podfile` que altera o compilador em seu espaço de trabalho Xcode durante a etapa de instalação do pod: + +``` + post_install do |installer| + react_native_post_install(installer) + + # ...possibly other post_install items here + + installer.pods_project.targets.each do |target| + target.build_configurations.each do |config| + # Using the un-qualified names means you can swap in different implementations, for example ccache + config.build_settings["CC"] = "clang" + config.build_settings["LD"] = "clang" + config.build_settings["CXX"] = "clang++" + config.build_settings["LDPLUSPLUS"] = "clang++" + end + end + + __apply_Xcode_12_5_M1_post_install_workaround(installer) + end +``` + +2. Você precisa de uma configuração de `ccache` que permita um certo nível de negligência e comportamento de cache, de modo que o `ccache` registre ocorrências de cache durante as compilações do Xcode. As variáveis de configuração do `ccache` que são diferentes do padrão são as seguintes se configuradas pela variável de ambiente: + +```bash +export CCACHE_SLOPPINESS=clang_index_store,file_stat_matches,include_file_ctime,include_file_mtime,ivfsoverlay,pch_defines,modules,system_headers,time_macros +export CCACHE_FILECLONE=true +export CCACHE_DEPEND=true +export CCACHE_INODECACHE=true +``` + +O mesmo pode ser configurado em um arquivo `ccache.conf` ou qualquer outro mecanismo fornecido pelo `ccache`. Mais sobre isso pode ser encontrado no manual oficial do [`ccache`](https://ccache.dev/manual/4.3.html). + +### Usando esta abordagem em um IC +Ccache usa a pasta `/Users/$USER/Library/Caches/ccache` no macOS para armazenar o cache. Portanto, você pode salvar e restaurar a pasta correspondente também no CI para acelerar suas compilações. + +No entanto, há algumas coisas que você deve estar ciente: + +1. No CI, recomendamos fazer uma compilação totalmente limpa, para evitar problemas de cache envenenado. Se você seguir a abordagem mencionada no parágrafo anterior, poderá paralelizar a construção nativa em 4 ABIs diferentes e provavelmente não precisará do ccache no CI. + +2. O `ccache` depende de carimbos de data/hora para calcular uma ocorrência no cache. Isso não funciona bem no CI, pois os arquivos são baixados novamente a cada execução do CI. Para superar isso, você precisará usar a opção de conteúdo `compiler_check`, que depende do [hash do conteúdo do arquivo](https://ccache.dev/manual/4.3.html). + +## Caches distribuídos +Semelhante aos caches locais, você pode considerar o uso de um cache distribuído para suas compilações nativas. Isso pode ser especificamente útil em organizações maiores que fazem compilações nativas frequentes. + +Recomendamos usar [sccache](https://github.com/mozilla/sccache) para conseguir isso. [Seguimos o início rápido da compilação distribuída do sccache](https://github.com/mozilla/sccache/blob/main/docs/DistributedQuickstart.md) para obter instruções sobre como configurar e usar esta ferramenta. diff --git a/vitepress/docs/docs/building-for-tv.md b/vitepress/docs/docs/building-for-tv.md new file mode 100644 index 0000000..1fe654d --- /dev/null +++ b/vitepress/docs/docs/building-for-tv.md @@ -0,0 +1,175 @@ +# Construção para dispositivos de TV + +O suporte a dispositivos de TV foi implementado com a intenção de fazer com que os aplicativos React Native existentes funcionem na Apple TV e Android TV, com poucas ou nenhuma alteração necessária no código JavaScript dos aplicativos. + +## Android TV + +### Mudanças de compilação + +* **Camada nativa**: para executar o projeto React Native na Android TV, certifique-se de fazer as seguintes alterações em `AndroidManifest.xml`: + +```xml + + + ... + + ... + + + + ... + +``` + +* **Camada JavaScript**: suporte para Android TV foi adicionado a `Platform.android.js`. Você pode verificar se o código está sendo executado na Android TV fazendo: + +```jsx +const Platform = require('Platform'); +const running_on_android_tv = Platform.isTV; +``` + +### Mudanças de código + +* **Acesso a controles touchs**: ao executar no Android TV, a estrutura do Android aplicará automaticamente um esquema de navegação direcional com base na posição relativa dos elementos focáveis em suas visualizações. O mixin `Touchable` tem código adicionado para detectar mudanças de foco e usar métodos existentes para estilizar os componentes corretamente e iniciar as ações adequadas quando a visualização é selecionada usando o controle remoto da TV, então `TouchableWithoutFeedback`, `TouchableHighlight`, `TouchableOpacity` e `TouchableNativeFeedback` funcionarão conforme esperado. Em particular: + * `onFocus` será executado quando a visualização tocável entrar em foco + * `onBlur` será executado quando a visualização tocável ficar fora de foco + * `onPress` será executado quando a visualização tocável for realmente selecionada pressionando o botão "selecionar" no controle remoto da TV. + +* **Entrada de controle remoto/teclado de TV**: uma nova classe nativa, `ReactAndroidTVRootViewHelper`, configura manipuladores de eventos importantes para eventos remotos de TV. Quando ocorrem eventos remotos de TV, esta classe dispara um evento JS. Este evento será captado por instâncias do objeto JavaScript TVEventHandler. O código do aplicativo que precisa implementar o tratamento personalizado de eventos remotos de TV pode criar uma instância de `TVEventHandler` e escutar esses eventos, como no código a seguir: + +```js +const TVEventHandler = require('TVEventHandler'); + +class Game2048 extends React.Component { + _tvEventHandler: any; + + _enableTVEventHandler() { + this._tvEventHandler = new TVEventHandler(); + this._tvEventHandler.enable(this, function (cmp, evt) { + if (evt && evt.eventType === 'right') { + cmp.setState({board: cmp.state.board.move(2)}); + } else if (evt && evt.eventType === 'up') { + cmp.setState({board: cmp.state.board.move(1)}); + } else if (evt && evt.eventType === 'left') { + cmp.setState({board: cmp.state.board.move(0)}); + } else if (evt && evt.eventType === 'down') { + cmp.setState({board: cmp.state.board.move(3)}); + } else if (evt && evt.eventType === 'playPause') { + cmp.restartGame(); + } + }); + } + + _disableTVEventHandler() { + if (this._tvEventHandler) { + this._tvEventHandler.disable(); + delete this._tvEventHandler; + } + } + + componentDidMount() { + this._enableTVEventHandler(); + } + + componentWillUnmount() { + this._disableTVEventHandler(); + } +} +``` + +* **Suporte ao Dev Menu**: No emulador, `cmd-M` abrirá o Dev Menu, semelhante ao Android. Para acessá-lo em um dispositivo Android TV real, pressione o botão de menu ou pressione longamente o botão de avanço rápido no controle remoto. (Por favor, não agite o dispositivo Android TV, isso não funcionará :)) + +Problemas conhecidos: +* Os componentes `TextInput` não funcionam por enquanto (ou seja, eles não podem receber o foco automaticamente, [veja este comentário](https://github.com/facebook/react-native/pull/16500#issuecomment-629285638)). + * No entanto, é possível usar um ref para acionar manualmente `inputRef.current.focus()`. + * Você pode agrupar sua entrada dentro de um componente `TouchableWithoutFeedback` e acionar o foco no evento `onFocus` desse touch. Isto permite abrir o teclado através das teclas de seta. + * O teclado pode redefinir seu estado após cada pressionamento de tecla (isso só pode acontecer dentro do emulador do Android TV). +* O conteúdo dos componentes `Modal` não pode receber foco, consulte este [comentário](https://github.com/facebook/react-native/issues/24448) para obter detalhes. + +## tvOS + +::: warning Descontinuado +Em vez disso, use [react-native-tvos](https://github.com/react-native-community/react-native-tvos). Para obter detalhes, verifique a postagem do blog da [versão 0.62](https://reactnative.dev/blog/#moving-apple-tv-to-react-native-tvos). +::: + +### Alterações de compilação + +* **Camada nativa**: todos os projetos React Native Xcode agora têm alvos de construção da Apple TV, com nomes terminando na string `'-tvOS'`. +* **react-native init**: Novos projetos React Native criados com `react-native init` terão o destino Apple TV criado automaticamente em seus projetos XCode. +* **Camada JavaScript**: suporte para Apple TV foi adicionado a `Platform.ios.js`. Você pode verificar se o código está sendo executado na AppleTV fazendo + +```js +const Platform = require('Platform'); +const running_on_tv = Platform.isTV; + +// Se você quiser ser mais específico e detectar apenas dispositivos rodando tvOS +// (mas sem dispositivos Android TV) você pode usar: +const running_on_apple_tv = Platform.isTVOS; +``` + +### Mudanças de código +* **Suporte geral para tvOS**: alterações específicas da Apple TV no código nativo são todas agrupadas pela definição `TARGET_OS_TV`. Isso inclui alterações para suprimir APIs que não são suportadas no tvOS (por exemplo, visualizações da web, controles deslizantes, interruptores, barra de status, etc.) e alterações para oferecer suporte à entrada do usuário a partir do controle remoto ou teclado da TV. + +* **Base de código comum**: como tvOS e iOS compartilham a maior parte do código Objective-C e JavaScript em comum, a maior parte da documentação para iOS se aplica igualmente ao tvOS. + +* **Acesso a controles touch**: Ao executar no Apple TV, a classe de visualização nativa é `RCTTVView`, que possui métodos adicionais para fazer uso do mecanismo de foco tvOS. O mixin `Touchable` tem código adicionado para detectar mudanças de foco e usar métodos existentes para estilizar os componentes corretamente e iniciar as ações adequadas quando a visualização é selecionada usando o controle remoto da TV, então `TouchableWithoutFeedback`, `TouchableHighlight` e `TouchableOpacity` funcionarão conforme esperado. Em particular: + * `onFocus` será executado quando a visualização tocável entrar em foco + * `onBlur` será executado quando a visualização tocável ficar fora de foco + * `onPress` será executado quando a visualização tocável for realmente selecionada pressionando o botão "selecionar" no controle remoto da TV. + +* **Entrada de controle remoto/teclado de TV**: uma nova classe nativa, `RCTTVRemoteHandler`, configura reconhecedores de gestos para eventos remotos de TV. Quando ocorrem eventos remotos de TV, esta classe dispara notificações que são captadas por `RCTTVNavigationEventEmitter` (uma subclasse de `RCTEventEmitter`), que dispara um evento JS. Este evento será captado por instâncias do objeto `JavaScript TVEventHandler`. O código do aplicativo que precisa implementar o tratamento personalizado de eventos remotos de TV pode criar uma instância de `TVEventHandler` e escutar esses eventos, como no código a seguir: + +```js +const TVEventHandler = require('TVEventHandler'); + +class Game2048 extends React.Component { + _tvEventHandler: any; + + _enableTVEventHandler() { + this._tvEventHandler = new TVEventHandler(); + this._tvEventHandler.enable(this, function (cmp, evt) { + if (evt && evt.eventType === 'right') { + cmp.setState({board: cmp.state.board.move(2)}); + } else if (evt && evt.eventType === 'up') { + cmp.setState({board: cmp.state.board.move(1)}); + } else if (evt && evt.eventType === 'left') { + cmp.setState({board: cmp.state.board.move(0)}); + } else if (evt && evt.eventType === 'down') { + cmp.setState({board: cmp.state.board.move(3)}); + } else if (evt && evt.eventType === 'playPause') { + cmp.restartGame(); + } + }); + } + + _disableTVEventHandler() { + if (this._tvEventHandler) { + this._tvEventHandler.disable(); + delete this._tvEventHandler; + } + } + + componentDidMount() { + this._enableTVEventHandler(); + } + + componentWillUnmount() { + this._disableTVEventHandler(); + } +} +``` + +* **Suporte ao Dev Menu**: No simulador, cmd-D abrirá o Dev Menu, semelhante ao iOS. Para acessá-lo em um dispositivo Apple TV real, pressione longamente o botão reproduzir/pausar no controle remoto. (Por favor, não agite o dispositivo Apple TV, isso não funcionará :)) + +* **Animações remotas de TV**: o código nativo RCTTVView implementa animações de paralaxe recomendadas pela Apple para ajudar a guiar o olho enquanto o usuário navega pelas visualizações. As animações podem ser desativadas ou ajustadas com novas propriedades de visualização opcionais. + +* **Navegação de retorno com o botão de menu do controle remoto da TV**: o componente `BackHandler`, originalmente escrito para oferecer suporte ao botão de retorno do Android, agora também oferece suporte à navegação de retorno na Apple TV usando o botão de menu no controle remoto da TV. + +* **Comportamento do TabBarIOS**: o componente `TabBarIOS` envolve a API UITabBar nativa, que funciona de maneira diferente no Apple TV. Para evitar a nova renderização instável da barra de guias no tvOS (consulte esta [issue](https://github.com/facebook/react-native/issues/15081)), o item selecionado da barra de guias só pode ser definido a partir de JavaScript na renderização inicial e é controlado depois disso pelo usuário por meio de código nativo. + +### Problemas conhecidos + * **Rolagem `ListView`**: O problema pode ser contornado definindo `removeClippedSubviews` como `false` em `ListView` e componentes semelhantes. Para mais discussão sobre este assunto, consulte [este PR](https://github.com/facebook/react-native/pull/12944). + diff --git a/vitepress/docs/docs/colors.md b/vitepress/docs/docs/colors.md new file mode 100644 index 0000000..b77efd2 --- /dev/null +++ b/vitepress/docs/docs/colors.md @@ -0,0 +1,216 @@ +# Referência de Cores + +Os componentes do React Native são [estilizados usando JavaScript](/docs/style.md). As propriedades de cores geralmente correspondem ao modo como o [CSS funciona na web](https://developer.mozilla.org/en-US/docs/Web/CSS/color_value). Guias gerais sobre o uso de cores em cada plataforma podem ser encontrados abaixo: + +* [Android](https://material.io/design/color/color-usage.html) +* [iOS](https://developer.apple.com/design/human-interface-guidelines/ios/visual-design/color/) + +## APIs de cores + +React Native possui diversas APIs de cores projetadas para permitir que você aproveite ao máximo o design da sua plataforma e as preferências do usuário. + +* [PlatformColor](/docs/platformcolor.md) permite fazer referência ao sistema de cores da plataforma. +* [DynamicColorIOS](/docs/dynamiccolorios.md) é específico para iOS e permite especificar quais cores devem ser usadas no modo claro ou escuro. + +## Representações de cores + +### Vermelho Verde Azul (RGB) + +React Native suporta `rgb()` e `rgba()` em notação hexadecimal e funcional: + +* `'#f0f'` (#rgb) +* `'#ff00ff'` (#rrggbb) +* `'#f0ff'` (#rgba) +* `'#ff00ff00'` (#rrggbbaa) +* `'rgb(255, 0, 255)'` +* `'rgb(255 0 255)'` +* `'rgb(255, 0, 255, 1,0)'` +* `'rgba(255 0 255/1,0)'` + +### Tonalidade Saturação Iluminação (HSL) + +React Native suporta `hsl()` e `hsla()` em notação funcional: + +* `'hsl(360, 100%, 100%)'` +* `'hsl(360 100% 100%)'` +* `'hsla(360, 100%, 100%, 1,0)'` +* `'hsla(360 100% 100% / 1,0)'` + +### Matiz Brancura Escuridão (HWB) + +React Native suporta `hwb()` em notação funcional: + +* `'hwb(0, 0%, 100%)'` +* `'hwb(360, 100%, 100%)'` +* `'hwb(0 0% 0%)'` +* `'hwb(70 50% 0%)'` + +### Informações de cor + +React Native também suporta cores como valores `int` (no modo de cores RGB): + +* `0xff00ff00` (0xrrggbbaa) + +::: warning **CUIDADO** +Isso pode parecer semelhante à representação de cores do [Android](https://developer.android.com/reference/android/graphics/Color), mas no Android os valores são armazenados no modo de cores SRGB (0xaarrggbb). +::: + +### Cores nomeadas +No React Native você também pode usar strings de nomes de cores como valores. + + +::: info **INFORMAÇÕES** +React Native suporta apenas nomes de cores em minúsculas. Nomes de cores em letras maiúsculas não são suportados. +::: + +#### `transparent` +Este é um atalho para `rgba(0,0,0,0)`, [igual ao CSS3](https://www.w3.org/TR/css-color-3/#transparent). + +#### Palavras-chave das cores +A implementação de cores nomeadas segue a especificação [CSS3/SVG](https://www.w3.org/TR/css-color-3/#svg-color) + +* aliceblue (#f0f8ff) +* antiquewhite (#faebd7) +* aqua (#00ffff) +* aquamarine (#7fffd4) +* azure (#f0ffff) +* beige (#f5f5dc) +* bisque (#ffe4c4) +* black (#000000) +* blanchedalmond (#ffebcd) +* blue (#0000ff) +* blueviolet (#8a2be2) +* brown (#a52a2a) +* burlywood (#deb887) +* cadetblue (#5f9ea0) +* chartreuse (#7fff00) +* chocolate (#d2691e) +* coral (#ff7f50) +* cornflowerblue (#6495ed) +* cornsilk (#fff8dc) +* crimson (#dc143c) +* cyan (#00ffff) +* darkblue (#00008b) +* darkcyan (#008b8b) +* darkgoldenrod (#b8860b) +* darkgray (#a9a9a9) +* darkgreen (#006400) +* darkgrey (#a9a9a9) +* darkkhaki (#bdb76b) +* darkmagenta (#8b008b) +* darkolivegreen (#556b2f) +* darkorange (#ff8c00) +* darkorchid (#9932cc) +* darkred (#8b0000) +* darksalmon (#e9967a) +* darkseagreen (#8fbc8f) +* darkslateblue (#483d8b) +* darkslategrey (#2f4f4f) +* darkturquoise (#00ced1) +* darkviolet (#9400d3) +* deeppink (#ff1493) +* deepskyblue (#00bfff) +* dimgray (#696969) +* dimgrey (#696969) +* dodgerblue (#1e90ff) +* firebrick (#b22222) +* floralwhite (#fffaf0) +* forestgreen (#228b22) +* fuchsia (#ff00ff) +* gainsboro (#dcdcdc) +* ghostwhite (#f8f8ff) +* gold (#ffd700) +* goldenrod (#daa520) +* gray (#808080) +* green (#008000) +* greenyellow (#adff2f) +* grey (#808080) +* honeydew (#f0fff0) +* hotpink (#ff69b4) +* indianred (#cd5c5c) +* indigo (#4b0082) +* ivory (#fffff0) +* khaki (#f0e68c) +* lavender (#e6e6fa) +* lavenderblush (#fff0f5) +* lawngreen (#7cfc00) +* lemonchiffon (#fffacd) +* lightblue (#add8e6) +* lightcoral (#f08080) +* lightcyan (#e0ffff) +* lightgoldenrodyellow (#fafad2) +* lightgray (#d3d3d3) +* lightgreen (#90ee90) +* lightgrey (#d3d3d3) +* lightpink (#ffb6c1) +* lightsalmon (#ffa07a) +* lightseagreen (#20b2aa) +* lightskyblue (#87cefa) +* lightslategrey (#778899) +* lightsteelblue (#b0c4de) +* lightyellow (#ffffe0) +* lime (#00ff00) +* limegreen (#32cd32) +* linen (#faf0e6) +* magenta (#ff00ff) +* maroon (#800000) +* mediumaquamarine (#66cdaa) +* mediumblue (#0000cd) +* mediumorchid (#ba55d3) +* mediumpurple (#9370db) +* mediumseagreen (#3cb371) +* mediumslateblue (#7b68ee) +* mediumspringgreen (#00fa9a) +* mediumturquoise (#48d1cc) +* mediumvioletred (#c71585) +* midnightblue (#191970) +* mintcream (#f5fffa) +* mistyrose (#ffe4e1) +* moccasin (#ffe4b5) +* navajowhite (#ffdead) +* navy (#000080) +* oldlace (#fdf5e6) +* olive (#808000) +* olivedrab (#6b8e23) +* orange (#ffa500) +* orangered (#ff4500) +* orchid (#da70d6) +* palegoldenrod (#eee8aa) +* palegreen (#98fb98) +* paleturquoise (#afeeee) +* palevioletred (#db7093) +* papayawhip (#ffefd5) +* peachpuff (#ffdab9) +* peru (#cd853f) +* pink (#ffc0cb) +* plum (#dda0dd) +* powderblue (#b0e0e6) +* purple (#800080) +* rebeccapurple (#663399) +* red (#ff0000) +* rosybrown (#bc8f8f) +* royalblue (#4169e1) +* saddlebrown (#8b4513) +* salmon (#fa8072) +* sandybrown (#f4a460) +* seagreen (#2e8b57) +* seashell (#fff5ee) +* sienna (#a0522d) +* silver (#c0c0c0) +* skyblue (#87ceeb) +* slateblue (#6a5acd) +* slategray (#708090) +* snow (#fffafa) +* springgreen (#00ff7f) +* steelblue (#4682b4) +* tan (#d2b48c) +* teal (#008080) +* thistle (#d8bfd8) +* tomato (#ff6347) +* turquoise (#40e0d0) +* violet (#ee82ee) +* wheat (#f5deb3) +* white (#ffffff) +* whitesmoke (#f5f5f5) +* yellow (#ffff00) +* yellowgreen (#9acd32) diff --git a/vitepress/docs/docs/communication-android.md b/vitepress/docs/docs/communication-android.md new file mode 100644 index 0000000..5229781 --- /dev/null +++ b/vitepress/docs/docs/communication-android.md @@ -0,0 +1,129 @@ +# Comunicação entre nativo e React Native + +Em [Guia de integração com aplicativos existentes](/docs/integration-with-existing-apps.md) e [Guia de componentes de UI nativos](/docs/native-components-android.md) aprendemos como incorporar o React Native em um componente nativo e vice-versa. Quando misturamos componentes nativos e React Native, eventualmente encontraremos a necessidade de comunicação entre esses dois mundos. Algumas maneiras de conseguir isso já foram mencionadas em outros guias. Este artigo resume as técnicas disponíveis. + +## Introdução + +O React Native é inspirado no React, então a ideia básica do fluxo de informações é semelhante. O fluxo no React é unidirecional. Mantemos uma hierarquia de componentes, na qual cada componente depende apenas de seu pai e de seu próprio estado interno. Fazemos isso com propriedades: os dados são passados ​​de um pai para seus filhos de cima para baixo. Se um componente ancestral depende do estado de seu descendente, deve-se transmitir um retorno de chamada a ser usado pelo descendente para atualizar o ancestral. + +O mesmo conceito se aplica ao React Native. Contanto que estejamos construindo nosso aplicativo exclusivamente dentro da estrutura, podemos direcioná-lo com propriedades e retornos de chamada. Mas, quando misturamos componentes React Native e nativos, precisamos de alguns mecanismos específicos entre linguagens que nos permitam passar informações entre eles. + +## Propriedades + +As propriedades são a forma mais direta de comunicação entre componentes. Portanto, precisamos de uma maneira de passar propriedades tanto de nativo para React Native quanto de React Native para nativo. + +### Passando propriedades de Native para React Native + +Você pode passar propriedades para o aplicativo React Native fornecendo uma implementação personalizada de `ReactActivityDelegate` em sua atividade principal. Esta implementação deve substituir `getLaunchOptions` para retornar um `Bundle` com as propriedades desejadas. + +::: code-group +```java [Java] +public class MainActivity extends ReactActivity { + @Override + protected ReactActivityDelegate createReactActivityDelegate() { + return new ReactActivityDelegate(this, getMainComponentName()) { + @Override + protected Bundle getLaunchOptions() { + Bundle initialProperties = new Bundle(); + ArrayList imageList = new ArrayList(Arrays.asList( + "https://dummyimage.com/600x400/ffffff/000000.png", + "https://dummyimage.com/600x400/000000/ffffff.png" + )); + initialProperties.putStringArrayList("images", imageList); + return initialProperties; + } + }; + } +} +``` + +```kotlin [Kotlin] +class MainActivity : ReactActivity() { + override fun createReactActivityDelegate(): ReactActivityDelegate { + return object : ReactActivityDelegate(this, mainComponentName) { + override fun getLaunchOptions(): Bundle { + val imageList = arrayListOf("https://dummyimage.com/600x400/ffffff/000000.png", "https://dummyimage.com/600x400/000000/ffffff.png") + val initialProperties = Bundle().apply { putStringArrayList("images", imageList) } + return initialProperties + } + } + } +} +``` +::: + +```tsx +import React from 'react'; +import {View, Image} from 'react-native'; + +export default class ImageBrowserApp extends React.Component { + renderImage(imgURI) { + return ; + } + render() { + return {this.props.images.map(this.renderImage)}; + } +} +``` + +`ReactRootView` fornece uma propriedade de leitura e gravação `appProperties`. Depois que `appProperties` for definido, o aplicativo React Native será renderizado novamente com novas propriedades. A atualização só é realizada quando as novas propriedades atualizadas diferem das anteriores. + +::: code-group +```java [Java] +Bundle updatedProps = mReactRootView.getAppProperties(); +ArrayList imageList = new ArrayList(Arrays.asList( + "https://dummyimage.com/600x400/ff0000/000000.png", + "https://dummyimage.com/600x400/ffffff/ff0000.png" +)); +updatedProps.putStringArrayList("images", imageList); + +mReactRootView.setAppProperties(updatedProps); +``` + +```kotlin [Kotlin] +var updatedProps: Bundle = reactRootView.getAppProperties() +var imageList = arrayListOf("https://dummyimage.com/600x400/ff0000/000000.png", "https://dummyimage.com/600x400/ffffff/ff0000.png") +``` +::: + +Não há problema em atualizar propriedades a qualquer momento. No entanto, as atualizações devem ser realizadas no thread principal. Você usa o getter em qualquer thread. + +Não há como atualizar apenas algumas propriedades por vez. Sugerimos que você o crie em seu próprio wrapper. + +::: info Nota +Atualmente, a função JS `componentWillUpdateProps` do componente RN de nível superior não será chamada após uma atualização de prop. No entanto, você pode acessar os novos adereços na função `componentDidMount`. +::: + +### Passando propriedades do React Native para Native + +O problema de exposição de propriedades de componentes nativos é abordado em detalhes [neste artigo](/docs/native-components-android.md). Resumindo, as propriedades que devem ser refletidas em JavaScript precisam ser expostas como um método setter anotado com `@ReactProp` e, em seguida, usá-las no React Native como se o componente fosse um componente React Native comum. + +### Limites de propriedades + +A principal desvantagem das propriedades entre linguagens é que elas não suportam retornos de chamada, o que nos permitiria lidar com ligações de dados de baixo para cima. Imagine que você tem uma pequena visualização RN que deseja remover da visualização pai nativa como resultado de uma ação JS. Não há como fazer isso com adereços, pois as informações precisariam ir de baixo para cima. + +Embora tenhamos uma variedade de retornos de chamada entre linguagens ([descritos aqui](/docs/native-modules-android.md)), esses retornos de chamada nem sempre são o que precisamos. O principal problema é que eles não devem ser passados ​​como propriedades. Em vez disso, esse mecanismo nos permite acionar uma ação nativa de JS e manipular o resultado dessa ação em JS. + +## Outras formas de interação entre idiomas (eventos e módulos nativos) + +Conforme declarado no capítulo anterior, o uso de propriedades apresenta algumas limitações. Às vezes, as propriedades não são suficientes para conduzir a lógica do nosso aplicativo e precisamos de uma solução que dê mais flexibilidade. Este capítulo cobre outras técnicas de comunicação disponíveis no React Native. Eles podem ser usados ​​para comunicação interna (entre JS e camadas nativas no RN), bem como para comunicação externa (entre RN e a parte 'nativa pura' do seu aplicativo). + +React Native permite que você execute chamadas de função em vários idiomas. Você pode executar código nativo personalizado de JS e vice-versa. Infelizmente, dependendo do lado em que trabalhamos, alcançamos o mesmo objetivo de maneiras diferentes. Para nativo - usamos mecanismo de eventos para agendar a execução de uma função manipuladora em JS, enquanto para React Native chamamos diretamente métodos exportados por módulos nativos. + +### Chamando funções React Native a partir de nativos (eventos) + +Os eventos são descritos em detalhes [neste artigo](/docs/native-components-android.md). Observe que o uso de eventos não nos dá garantias sobre o tempo de execução, pois o evento é tratado em um thread separado. + +Os eventos são poderosos porque nos permitem alterar os componentes do React Native sem precisar de uma referência a eles. No entanto, existem algumas armadilhas nas quais você pode cair ao usá-los: + +- Como os eventos podem ser enviados de qualquer lugar, eles podem introduzir dependências do tipo espaguete em seu projeto. +- Os eventos compartilham namespace, o que significa que você pode encontrar algumas colisões de nomes. As colisões não serão detectadas estaticamente, o que as torna difíceis de depurar. +- Se você usar várias instâncias do mesmo componente React Native e quiser distingui-las da perspectiva do seu evento, provavelmente precisará introduzir identificadores e passá-los junto com os eventos (você pode usar o `reactTag` da visualização nativa como um identificador). + +### Chamando funções nativas do React Native (módulos nativos) + +Módulos nativos são classes Java/Kotlin disponíveis em JS. Normalmente, uma instância de cada módulo é criada por ponte JS. Eles podem exportar funções e constantes arbitrárias para React Native. Eles foram abordados em detalhes [neste artigo](/docs/native-modules-android.md). + +::: warning Aviso +Todos os módulos nativos compartilham o mesmo namespace. Cuidado com colisões de nomes ao criar novos. +::: diff --git a/vitepress/docs/docs/communication-ios.md b/vitepress/docs/docs/communication-ios.md new file mode 100644 index 0000000..c550ec2 --- /dev/null +++ b/vitepress/docs/docs/communication-ios.md @@ -0,0 +1,203 @@ +# Comunicação entre nativo e React Native + +Em [Guia de integração com aplicativos existentes](integração com aplicativos existentes) e [Guia de componentes de UI nativos](/docs/native-components-ios.md) aprendemos como incorporar o React Native em um componente nativo e vice-versa. Quando misturamos componentes nativos e React Native, eventualmente encontraremos a necessidade de comunicação entre esses dois mundos. Algumas maneiras de conseguir isso já foram mencionadas em outros guias. Este artigo resume as técnicas disponíveis. + +## Introdução + +O React Native é inspirado no React, então a ideia básica do fluxo de informações é semelhante. O fluxo no React é unidirecional. Mantemos uma hierarquia de componentes, na qual cada componente depende apenas de seu pai e de seu próprio estado interno. Fazemos isso com propriedades: os dados são passados ​​de um pai para seus filhos de cima para baixo. Se um componente ancestral depende do estado de seu descendente, deve-se transmitir um retorno de chamada a ser usado pelo descendente para atualizar o ancestral. + +O mesmo conceito se aplica ao React Native. Contanto que estejamos construindo nosso aplicativo exclusivamente dentro da estrutura, podemos direcioná-lo com propriedades e retornos de chamada. Mas, quando misturamos componentes React Native e nativos, precisamos de alguns mecanismos específicos entre linguagens que nos permitam passar informações entre eles. + +## Propriedades + +As propriedades são a forma mais direta de comunicação entre componentes. Portanto, precisamos de uma maneira de passar propriedades tanto de nativo para React Native quanto de React Native para nativo. + +### Passando propriedades de Native para React Native + +Para incorporar uma visualização React Native em um componente nativo, usamos `RCTRootView`. `RCTRootView` é um `UIView` que contém um aplicativo React Native. Ele também fornece uma interface entre o lado nativo e o aplicativo hospedado. + +`RCTRootView` possui um inicializador que permite passar propriedades arbitrárias para o aplicativo React Native. O parâmetro `initialProperties` deve ser uma instância de `NSDictionary`. O dicionário é convertido internamente em um objeto JSON que o componente JS de nível superior pode referenciar. + +```objective-c +NSArray *imageList = @[@"https://dummyimage.com/600x400/ffffff/000000.png", + @"https://dummyimage.com/600x400/000000/ffffff.png"]; + +NSDictionary *props = @{@"images" : imageList}; + +RCTRootView *rootView = [[RCTRootView alloc] initWithBridge:bridge + moduleName:@"ImageBrowserApp" + initialProperties:props]; +``` + +```tsx +import React from 'react'; +import {View, Image} from 'react-native'; + +export default class ImageBrowserApp extends React.Component { + renderImage(imgURI) { + return ; + } + render() { + return {this.props.images.map(this.renderImage)}; + } +} +``` + +`RCTRootView` também fornece uma propriedade de leitura e gravação `appProperties`. Depois que `appProperties` for definido, o aplicativo React Native será renderizado novamente com novas propriedades. A atualização só é realizada quando as novas propriedades atualizadas diferem das anteriores. + +```objective-c +NSArray *imageList = @[@"https://dummyimage.com/600x400/ff0000/000000.png", + @"https://dummyimage.com/600x400/ffffff/ff0000.png"]; + +rootView.appProperties = @{@"images" : imageList}; +``` + +Não há problema em atualizar propriedades a qualquer momento. No entanto, as atualizações devem ser realizadas no thread principal. Você usa o getter em qualquer thread. + +::: info Observação +Atualmente, há um problema conhecido em que, ao definir appProperties durante a inicialização da ponte, a alteração pode ser perdida. Consulte [https://github.com/facebook/react-native/issues/20115](https://github.com/facebook/react-native/issues/20115) para obter mais informações. +::: + +Não há como atualizar apenas algumas propriedades por vez. Sugerimos que você o crie em seu próprio wrapper. + +### Passando propriedades do React Native para Native + +O problema de exposição de propriedades de componentes nativos é abordado em detalhes [neste artigo](native-components-ios#properties). Resumindo, exporte propriedades com a macro `RCT_CUSTOM_VIEW_PROPERTY` em seu componente nativo personalizado e, em seguida, use-as no React Native como se o componente fosse um componente React Native comum. + +### Limites de propriedades + +A principal desvantagem das propriedades entre linguagens é que elas não suportam retornos de chamada, o que nos permitiria lidar com ligações de dados de baixo para cima. Imagine que você tem uma pequena visualização RN que deseja remover da visualização pai nativa como resultado de uma ação JS. Não há como fazer isso com adereços, pois as informações precisariam ir de baixo para cima. + +Embora tenhamos uma variedade de retornos de chamada entre idiomas ([descritos aqui](native-modules-ios#callbacks)), esses retornos de chamada nem sempre são o que precisamos. O principal problema é que eles não devem ser passados ​​como propriedades. Em vez disso, esse mecanismo nos permite acionar uma ação nativa de JS e manipular o resultado dessa ação em JS. + +## Outras formas de interação entre linguagens (eventos e módulos nativos) + +Conforme declarado no capítulo anterior, o uso de propriedades apresenta algumas limitações. Às vezes, as propriedades não são suficientes para conduzir a lógica do nosso aplicativo e precisamos de uma solução que dê mais flexibilidade. Este capítulo cobre outras técnicas de comunicação disponíveis no React Native. Eles podem ser usados ​​para comunicação interna (entre JS e camadas nativas no RN), bem como para comunicação externa (entre RN e a parte 'nativa pura' do seu aplicativo). + +React Native permite que você execute chamadas de função em vários idiomas. Você pode executar código nativo personalizado de JS e vice-versa. Infelizmente, dependendo do lado em que trabalhamos, alcançamos o mesmo objetivo de maneiras diferentes. Para nativo - usamos mecanismo de eventos para agendar a execução de uma função manipuladora em JS, enquanto para React Native chamamos diretamente métodos exportados por módulos nativos. + +### Chamando funções React Native a partir de nativos (eventos) + +Os eventos são descritos detalhadamente [neste artigo](/docs/native-components-ios.md). Observe que o uso de eventos não nos dá garantias sobre o tempo de execução, pois o evento é tratado em um thread separado. + +Os eventos são poderosos porque nos permitem alterar os componentes do React Native sem precisar de uma referência a eles. No entanto, existem algumas armadilhas nas quais você pode cair ao usá-los: + +- Como os eventos podem ser enviados de qualquer lugar, eles podem introduzir dependências do tipo espaguete em seu projeto. +- Os eventos compartilham namespace, o que significa que você pode encontrar algumas colisões de nomes. As colisões não serão detectadas estaticamente, o que as torna difíceis de depurar. +- Se você usar várias instâncias do mesmo componente React Native e quiser distingui-las da perspectiva do seu evento, provavelmente precisará introduzir identificadores e passá-los junto com os eventos (você pode usar o `reactTag` da visualização nativa como um identificador). + +O padrão comum que usamos ao incorporar nativo no React Native é tornar o RCTViewManager do componente nativo um delegado para as visualizações, enviando eventos de volta ao JavaScript por meio da ponte. Isso mantém as chamadas de eventos relacionadas em um só lugar. + +### Chamando funções nativas do React Native (módulos nativos) + +Módulos nativos são classes Objective-C disponíveis em JS. Normalmente, uma instância de cada módulo é criada por ponte JS. Eles podem exportar funções e constantes arbitrárias para React Native. Eles foram abordados em detalhes [neste artigo](/docs/native-modules-ios.md). + +O fato de os módulos nativos serem singletons limita o mecanismo no contexto de incorporação. Digamos que temos um componente React Native incorporado em uma visualização nativa e queremos atualizar a visualização pai nativa. Usando o mecanismo de módulo nativo, exportaríamos uma função que não apenas recebe os argumentos esperados, mas também um identificador da visão nativa pai. O identificador seria usado para recuperar uma referência à visualização pai a ser atualizada. Dito isto, precisaríamos manter um mapeamento dos identificadores para as visualizações nativas no módulo. + +Embora esta solução seja complexa, ela é usada em `RCTUIManager`, que é uma classe interna do React Native que gerencia todas as visualizações do React Native. + +Módulos nativos também podem ser usados ​​para expor bibliotecas nativas existentes ao JS. A [biblioteca de geolocalização](https://github.com/michalchudziak/react-native-geolocation) é um exemplo vivo da ideia. + +::: warning Cuidado +Todos os módulos nativos compartilham o mesmo namespace. Cuidado com colisões de nomes ao criar novos. +::: + +## Fluxo de cálculo de layout + +Ao integrar o nativo e o React Native, também precisamos de uma maneira de consolidar dois sistemas de layout diferentes. Esta seção aborda problemas comuns de layout e fornece uma breve descrição dos mecanismos para resolvê-los. + +### Layout de um componente nativo incorporado no React Native + +Este caso é abordado [neste artigo](/docs/native-components-ios.md). Para resumir, como todas as nossas visualizações de react nativas são subclasses de `UIView`, a maioria dos atributos de estilo e tamanho funcionarão como você esperaria imediatamente. + +### Layout de um componente React Native incorporado no nativo + +#### React Native com tamanho fixo + +O cenário geral é quando temos um aplicativo React Native com tamanho fixo, que é conhecido pelo lado nativo. Em particular, uma visualização React Native em tela inteira se enquadra neste caso. Se quisermos uma visualização raiz menor, podemos definir explicitamente o quadro do RTRRootView. + +Por exemplo, para criar um aplicativo RN com 200 pixels (lógicos) de altura e largura da visualização de hospedagem ampla, poderíamos fazer: + +::: code-group +```objective-c [SomeViewController.m] +- (void)viewDidLoad +{ + [...] + RCTRootView *rootView = [[RCTRootView alloc] initWithBridge:bridge + moduleName:appName + initialProperties:props]; + rootView.frame = CGRectMake(0, 0, self.view.width, 200); + [self.view addSubview:rootView]; +} +``` +::: + +Quando temos uma visualização raiz de tamanho fixo, precisamos respeitar seus limites no lado JS. Em outras palavras, precisamos garantir que o conteúdo do React Native possa estar contido na visualização raiz de tamanho fixo. A maneira mais fácil de garantir isso é usar o layout Flexbox. Se você usar posicionamento absoluto e os componentes do React estiverem visíveis fora dos limites da visualização raiz, você obterá sobreposição com visualizações nativas, fazendo com que alguns recursos se comportem de forma inesperada. Por exemplo, 'TouchableHighlight' não destacará seus toques fora dos limites da visualização raiz. + +Não há problema em atualizar dinamicamente o tamanho da visualização raiz, redefinindo sua propriedade de quadro. React Native cuidará do layout do conteúdo. + +#### React Native com tamanho flexível + +Em alguns casos, gostaríamos de renderizar conteúdo de tamanho inicialmente desconhecido. Digamos que o tamanho será definido dinamicamente em JS. Temos duas soluções para este problema. + +1. Você pode agrupar sua visualização React Native em um componente `ScrollView`. Isso garante que seu conteúdo estará sempre disponível e não se sobreporá às visualizações nativas. +2. React Native permite determinar, em JS, o tamanho do aplicativo RN e fornecê-lo ao proprietário da hospedagem `RCTRootView`. O proprietário é então responsável por reorganizar as subvisualizações e manter a IU consistente. Conseguimos isso com os modos de flexibilidade do `RCTRootView`. + +`RCTRootView` suporta 4 modos de flexibilidade de tamanhos diferentes: + +```objective-c title='RCTRootView.h' +typedef NS_ENUM(NSInteger, RCTRootViewSizeFlexibility) { + RCTRootViewSizeFlexibilityNone = 0, + RCTRootViewSizeFlexibilityWidth, + RCTRootViewSizeFlexibilityHeight, + RCTRootViewSizeFlexibilityWidthAndHeight, +}; +``` + +`RCTRootViewSizeFlexibilityNone` é o valor padrão, o que torna fixo o tamanho da visualização raiz (mas ainda pode ser atualizado com `setFrame:`). Os outros três modos nos permitem rastrear as atualizações de tamanho do conteúdo do React Native. Por exemplo, definir o modo como `RCTRootViewSizeFlexibilityHeight` fará com que o React Native meça a altura do conteúdo e passe essa informação de volta ao delegado de `RCTRootView`. Uma ação arbitrária pode ser executada dentro do delegado, incluindo a configuração do quadro da visualização raiz, para que o conteúdo se ajuste. O delegado é chamado somente quando o tamanho do conteúdo é alterado. + +::: warning Cuidado +Tornar uma dimensão flexível em JS e nativo leva a um comportamento indefinido. Por exemplo - não torne flexível a largura de um componente React de nível superior (com `flexbox`) enquanto estiver usando `RCTRootViewSizeFlexibilityWidth` na hospedagem `RCTRootView`. +::: + +Vejamos um exemplo. + +```objective-c title='FlexibleSizeExampleView.m' +- (instancetype)initWithFrame:(CGRect)frame +{ + [...] + + _rootView = [[RCTRootView alloc] initWithBridge:bridge + moduleName:@"FlexibilityExampleApp" + initialProperties:@{}]; + + _rootView.delegate = self; + _rootView.sizeFlexibility = RCTRootViewSizeFlexibilityHeight; + _rootView.frame = CGRectMake(0, 0, self.frame.size.width, 0); +} + +#pragma mark - RCTRootViewDelegate +- (void)rootViewDidChangeIntrinsicSize:(RCTRootView *)rootView +{ + CGRect newFrame = rootView.frame; + newFrame.size = rootView.intrinsicContentSize; + + rootView.frame = newFrame; +} +``` + +No exemplo, temos uma visualização `FlexibleSizeExampleView` que contém uma visualização raiz. Criamos a visualização raiz, inicializamos e definimos o delegado. O delegado cuidará das atualizações de tamanho. Em seguida, definimos a flexibilidade de tamanho da visualização raiz para `RCTRootViewSizeFlexibilityHeight`, o que significa que o método `rootViewDidChangeIntrinsicSize:` será chamado toda vez que o conteúdo do React Native mudar sua altura. Finalmente, definimos a largura e a posição da visualização raiz. Observe que definimos a altura também, mas isso não tem efeito, pois tornamos a altura dependente de RN. + +Você pode verificar o código-fonte completo do exemplo [aqui](https://github.com/facebook/react-native/blob/main/packages/rn-tester/RNTester/NativeExampleViews/FlexibleSizeExampleView.mm). + +Não há problema em alterar dinamicamente o modo de flexibilidade de tamanho da visualização raiz. Alterar o modo de flexibilidade de uma visualização raiz agendará um recálculo do layout e o método delegado `rootViewDidChangeIntrinsicSize:` será chamado assim que o tamanho do conteúdo for conhecido. + +::: info Observação +O cálculo do layout do React Native é executado em um thread separado, enquanto as atualizações da visualização da UI nativa são feitas no thread principal. +Isso pode causar inconsistências temporárias na interface do usuário entre o nativo e o React Native. Este é um problema conhecido e nossa equipe está trabalhando na sincronização de atualizações de IU provenientes de diferentes fontes. +::: + +::: info Observação +O React Native não executa nenhum cálculo de layout até que a visualização raiz se torne uma subvisão de algumas outras visualizações. +Se você deseja ocultar a visualização React Native até que suas dimensões sejam conhecidas, adicione a visualização raiz como uma subvisualização e torne-a inicialmente oculta (use a propriedade `hidden` de `UIView`). Em seguida, altere sua visibilidade no método delegado. +::: diff --git a/vitepress/docs/docs/debugging.md b/vitepress/docs/docs/debugging.md new file mode 100644 index 0000000..e1ae52a --- /dev/null +++ b/vitepress/docs/docs/debugging.md @@ -0,0 +1,120 @@ +# Noções básicas de depuração + +## Acessando o menu de desenvolvimento +React Native fornece um menu de desenvolvedor no aplicativo que oferece várias opções de depuração. Você pode acessar o Menu Dev agitando seu dispositivo ou por meio de atalhos de teclado: + +* Simulador iOS: Cmd ⌘ + D (ou Dispositivo > Agitar) +* Emuladores Android: Cmd ⌘ + M (macOS) ou Ctrl + M (Windows e Linux) + +Alternativamente, para dispositivos e emuladores Android, você pode executar `adb shell input keyevent 82` em seu terminal. + +![image](/docs/assets/307929568-c4514d57-633d-48d7-acd8-85b15c785dee.png) + +::: info **OBSERVAÇÃO** +O menu Dev está desabilitado em compilações de lançamento (produção). +::: + +## LogBox + +Erros e avisos em builds de desenvolvimento são exibidos no LogBox dentro do seu aplicativo. + +::: info **OBSERVAÇÃO** +LogBox está desabilitado em compilações de lançamento (produção). +::: + +## Erros e avisos do console + +Os erros e avisos do console são exibidos como notificações na tela com um emblema vermelho ou amarelo e o número de erros ou avisos no console, respectivamente. Para visualizar um erro ou avisos do console, toque na notificação para visualizar as informações em tela cheia sobre o log e para paginar todos os logs no console. + +Essas notificações podem ser ocultadas usando `LogBox.ignoreAllLogs()`. Isso é útil ao fazer demonstrações de produtos, por exemplo. Além disso, as notificações podem ser ocultadas por log por meio de `LogBox.ignoreLogs()`. Isto é útil quando há um aviso frequente que não pode ser corrigido, como aqueles em uma dependência de terceiros. + +::: info **INFORMAÇÕES** +Ignore os logs como último recurso e crie uma tarefa para corrigir quaisquer logs que sejam ignorados. +::: + +```jsx +import {LogBox} from 'react-native'; + +// Ignorar notificação de log por mensagem: +LogBox.ignoreLogs(['Warning: ...']); + +// Ignore todas as notificações de log: +LogBox.ignoreAllLogs(); +``` + +## Erros não tratados + +Erros de JavaScript não tratados, marcado como `undefined is not a function`, abrirão automaticamente um erro LogBox em tela inteira com a origem do erro. Esses erros são dispensáveis e minimizáveis para que você possa ver o estado do seu aplicativo quando esses erros ocorrem, mas sempre devem ser resolvidos. + +## Erros de sintaxe + +Quando ocorre um erro de sintaxe, o erro LogBox em tela cheia será aberto automaticamente com o rastreamento de pilha e a localização do erro de sintaxe. Este erro não pode ser descartado porque representa uma execução inválida de JavaScript que deve ser corrigida antes de continuar com seu aplicativo. Para descartar esses erros, corrija o erro de sintaxe e salve para descartar automaticamente (com Atualização Rápida habilitada) ou Cmd ⌘/Ctrl + R para recarregar (com Atualização Rápida desabilitada). + +## Ferramentas para desenvolvedores do Chrome + +Para depurar o código JavaScript no Chrome, selecione "Open Debugger" no menu Dev. Isso abrirá uma nova guia em `http://localhost:8081/debugger-ui`. + +A partir daqui, selecione `More Tools → Developer Tools` no menu do Chrome para abrir o [Chrome DevTools](https://developer.chrome.com/devtools). Alternativamente, você pode usar o atalho ⌥ Option + Cmd ⌘ + I (macOS) / Ctrl + Shift + I (Windows e Linux). + +* Se você é novo no Chrome DevTools, recomendamos aprender sobre as guias [Console](https://developer.chrome.com/docs/devtools/#console) e [Fontes](https://developer.chrome.com/docs/devtools/#sources) nos documentos. +* Você pode querer habilitar [Pause on Caught Exceptions](https://developer.chrome.com/docs/devtools/javascript/breakpoints/#exceptions) para uma melhor experiência de depuração. + +::: info **INFORMAÇÕES** +A extensão React Developer Tools Chrome não funciona com React Native, mas você pode usar sua versão independente. Leia [esta seção](/docs/react-devtools.md) para saber como. +::: + +::: tip **DICA** +No Android, se os tempos entre o depurador e o dispositivo variarem, coisas como animações e comportamento de eventos poderão não funcionar corretamente. Isso pode ser corrigido executando `adb shell "date `date +%m%d%H%M%Y.%S%3N`"`. O acesso root é necessário se estiver usando um dispositivo físico. +::: + +## Depuração em um dispositivo físico + +::: info **Informações** +Se você estiver usando Expo CLI, isso já está configurado para você. +::: + +## Android + +Em dispositivos Android 5.0+ conectados via USB, você pode usar a ferramenta de linha de comando adb para configurar o encaminhamento de porta do dispositivo para o seu computador: + +```bash +adb reverse tcp:8081 tcp:8081 +``` + +Como alternativa, selecione “Configurações” no menu Dev e atualize a configuração “Host do servidor de depuração para dispositivo” para corresponder ao endereço IP do seu computador. + +## iOS + +Em dispositivos iOS, abra o arquivo [RCTWebSocketExecutor.mm](https://github.com/facebook/react-native/blob/master/packages/react-native/React/CoreModules/RCTWebSocketExecutor.mm) e altere "localhost" para o endereço IP do seu computador e selecione "Debug JS Remotely" no menu Dev. + +::: tip **Observação** +Se você tiver algum problema, pode ser que uma de suas extensões do Chrome esteja interagindo de maneira inesperada com o depurador. Tente desabilitar todas as suas extensões e reativá-las uma por uma até encontrar a extensão problemática. +::: + +::: info **Avançado: depuração usando um depurador JavaScript personalizado** +Para usar um depurador JavaScript personalizado no lugar das Ferramentas de desenvolvedor do Chrome, defina a variável de ambiente `REACT_DEBUGGER` como um comando que iniciará seu depurador personalizado. Você pode então selecionar "Open Debugger" no menu Dev para iniciar a depuração. + +O depurador receberá uma lista de todas as raízes do projeto, separadas por um espaço. Por exemplo, se você definir `REACT_DEBUGGER="node /path/to/launchDebugger.js --port 2345 --type ReactNative"`, então o comando `node /path/to/launchDebugger.js --port 2345 --type ReactNative /path/to/reactNative/app` será usado para iniciar seu depurador. +::: + + +::: info **Observação** +Os comandos do depurador personalizado executados dessa maneira devem ser processos de curta duração e não devem produzir mais de 200 kilobytes de saída. +::: + +## Ferramentas para desenvolvedores Safari + +Você pode usar o Safari para depurar a versão iOS do seu aplicativo sem precisar ativar "Depurar JS remotamente". + +* Em um dispositivo físico, vá para: `Settings → Safari → Advanced → Make sure "Web Inspector" is turned on` (esta etapa não é necessária no Simulador) +* No seu Mac, ative o menu Desenvolver no Safari: `Settings... (or Preferences...) → Advanced → Select "Show Develop menu in menu bar"` +* Selecione o JSContext do seu aplicativo: `Develop → Simulator (or other device) → JSContext` +* O Web Inspector do Safari deve abrir, contendo um console e um depurador + +Embora os mapas de origem possam não estar habilitados por padrão, você pode seguir [este guia](http://blog.nparashuram.com/2019/10/debugging-react-native-ios-apps-with.html) ou [vídeo](https://www.youtube.com/watch?v=GrGqIIz51k4) para habilitá-los e definir pontos de interrupção nos locais certos no código-fonte. + +No entanto, sempre que o aplicativo é recarregado (usando recarregamento ao vivo ou recarregando manualmente), um novo JSContext é criado. Escolher "Mostrar automaticamente inspetores da Web para JSContexts" evita que você tenha que selecionar manualmente o JSContext mais recente. + +## Monitor de desempenho + +Você pode ativar uma sobreposição de desempenho para ajudá-lo a depurar problemas de desempenho selecionando "Perf Monitor" no menu Dev. diff --git a/vitepress/docs/docs/direct-manipulation.md b/vitepress/docs/docs/direct-manipulation.md new file mode 100644 index 0000000..029ebf2 --- /dev/null +++ b/vitepress/docs/docs/direct-manipulation.md @@ -0,0 +1,404 @@ +# Manipulação Direta + +Às vezes é necessário fazer alterações diretamente em um componente sem usar `state/props` para acionar uma nova renderização de toda a subárvore. Ao usar React no navegador, por exemplo, às vezes você precisa modificar diretamente um nó DOM, e o mesmo se aplica a visualizações em aplicativos móveis. `setNativeProps` é o equivalente React Native para definir propriedades diretamente em um nó DOM. + +::: warning ATENÇÃO +Use `setNativeProps` quando a nova renderização frequentemente criar um gargalo de desempenho! + +A manipulação direta não será uma ferramenta que você utiliza com frequência. Normalmente, você o usará apenas para criar animações contínuas para evitar a sobrecarga de renderizar a hierarquia de componentes e reconciliar muitas visualizações. + +`setNativeProps` é imperativo e armazena o estado na camada nativa (DOM, UIView, etc.) e não nos componentes do React, o que torna seu código mais difícil de compreender. + +Antes de usá-lo, tente resolver seu problema com `setState` e [`shouldComponentUpdate`](https://reactjs.org/docs/optimizing-performance.html#shouldcomponentupdate-in-action). +::: + +## setNativeProps com TouchableOpacity + +[TouchableOpacity](https://github.com/facebook/react-native/blob/main/packages/react-native/Libraries/Components/Touchable/TouchableOpacity.js) usa `setNativeProps` internamente para atualizar a opacidade de seu filho componente: + +```tsx +const viewRef = useRef(); +const setOpacityTo = useCallback(value => { + // Redigido: código relacionado à animação + viewRef.current.setNativeProps({ + opacity: value, + }); +}, []); +``` + +Isso nos permite escrever o código a seguir e saber que a criança terá sua opacidade atualizada em resposta aos toques, sem que a criança tenha conhecimento desse fato ou exija quaisquer alterações em sua implementação: + +```tsx + + + Press me! + + +``` + +Vamos imaginar que `setNativeProps` não estava disponível. Uma maneira de implementá-lo com essa restrição é armazenar o valor de opacidade no estado e, em seguida, atualizar esse valor sempre que `onPress` for acionado: + +```tsx +const [buttonOpacity, setButtonOpacity] = useState(1); +return ( + setButtonOpacity(0.5)} + onPressOut={() => setButtonOpacity(1)}> + + Press me! + + +); +``` + +Isso é computacionalmente intensivo em comparação com o exemplo original - o React precisa renderizar novamente a hierarquia de componentes cada vez que a opacidade muda, mesmo que outras propriedades da visualização e de seus filhos não tenham mudado. Normalmente, essa sobrecarga não é uma preocupação, mas ao executar animações contínuas e responder a gestos, otimizar criteriosamente seus componentes pode melhorar a fidelidade de suas animações. + +Se você observar a implementação de `setNativeProps` em [NativeMethodsMixin](https://github.com/facebook/react-native/blob/main/packages/react-native/Libraries/Renderer/implementations/ReactNativeRenderer-prod.js), você notará que é um wrapper em torno de `RCTUIManager.updateView` - esta é exatamente a mesma chamada de função que resulta da nova renderização - consulte [receiveComponent in ReactNativeBaseComponent](https://github.com/facebook/react-native /blob/fb2ec1ea47c53c2e7b873acb1cb46192ac74274e/Libraries/Renderer/oss/ReactNativeRenderer-prod.js#L5793-L5813). + +## Componentes compostos e setNativeProps + +Os componentes compostos não são apoiados por uma visualização nativa, portanto você não pode chamar `setNativeProps` neles. Considere este exemplo: + +```jsx [setNativeProps%20with%20Composite%20Components] +import React from 'react'; +import {Text, TouchableOpacity, View} from 'react-native'; + +const MyButton = props => ( + + {props.label} + +); + +const App = () => ( + + + +); + +export default App; +``` + +```tsx [setNativeProps%20with%20Composite%20Components] +import React from 'react'; +import {Text, TouchableOpacity, View} from 'react-native'; + +const MyButton = (props: {label: string}) => ( + + {props.label} + +); + +const App = () => ( + + + +); + +export default App; +``` + +Se você executar isso, verá imediatamente este erro: "`Touchable child must either be native or forward setNativeProps to a native component`" (_O filho tocável deve ser nativo ou encaminhar setNativeProps para um componente nativo_. Isso ocorre porque `MyButton` não é apoiado diretamente por uma visualização nativa cuja opacidade deve ser definida. Você pode pensar assim: se você definir um componente com `createReactClass` você não esperaria ser capaz de definir um suporte de estilo nele e fazer isso funcionar - você precisaria passar o suporte de estilo para um filho, a menos que você esteja agrupando um componente nativo. Da mesma forma, encaminharemos `setNativeProps` para um componente filho com suporte nativo. + +#### Encaminha setNativeProps para um filho + +Como o método `setNativeProps` existe em qualquer referência a um componente `View`, é suficiente encaminhar uma referência em seu componente personalizado para um dos componentes `` que ele renderiza. Isso significa que uma chamada para `setNativeProps` no componente personalizado terá o mesmo efeito como se você chamasse `setNativeProps` no próprio componente `View` encapsulado. + +```js [Forwarding%20setNativeProps] +import React from 'react'; +import {Text, TouchableOpacity, View} from 'react-native'; + +const MyButton = React.forwardRef((props, ref) => ( + + {props.label} + +)); + +const App = () => ( + + + +); + +export default App; +``` + +```tsx [Forwarding%20setNativeProps] +import React from 'react'; +import {Text, TouchableOpacity, View} from 'react-native'; + +const MyButton = React.forwardRef((props, ref) => ( + + {props.label} + +)); + +const App = () => ( + + + +); + +export default App; +``` + +Agora você pode usar `MyButton` dentro de `TouchableOpacity`! + +Você deve ter notado que passamos todos os adereços para a visualização filha usando `{...props}`. A razão para isso é que `TouchableOpacity` é na verdade um componente composto e, portanto, além de depender de `setNativeProps` em seu filho, também requer que o filho execute o tratamento de toque. Para fazer isso, ele passa [vários adereços](/docs/view.md#onmoveshouldsetresponder) que chamam de volta para o componente `TouchableOpacity`. `TouchableHighlight`, por outro lado, é apoiado por uma visão nativa e requer apenas que implementemos `setNativeProps`. + +## setNativeProps para editar o valor TextInput + +Outro caso de uso muito comum de `setNativeProps` é editar o valor do TextInput. A propriedade `controlled` do TextInput às vezes pode descartar caracteres quando o `bufferDelay` está baixo e o usuário digita muito rapidamente. Alguns desenvolvedores preferem ignorar totalmente esta propriedade e, em vez disso, usar `setNativeProps` para manipular diretamente o valor TextInput quando necessário. Por exemplo, o código a seguir demonstra a edição da entrada quando você toca em um botão: + +```jsx [Clear%20text] +import React from 'react'; +import {useCallback, useRef} from 'react'; +import { + StyleSheet, + TextInput, + Text, + TouchableOpacity, + View, +} from 'react-native'; + +const App = () => { + const inputRef = useRef(null); + const editText = useCallback(() => { + inputRef.current.setNativeProps({text: 'Edited Text'}); + }, []); + + return ( + + + + Edit text + + + ); +}; + +const styles = StyleSheet.create({ + container: { + flex: 1, + alignItems: 'center', + justifyContent: 'center', + }, + input: { + height: 50, + width: 200, + marginHorizontal: 20, + borderWidth: 1, + borderColor: '#ccc', + }, +}); + +export default App; +``` + +```tsx [Clear%20text] +import React from 'react'; +import {useCallback, useRef} from 'react'; +import { + StyleSheet, + TextInput, + Text, + TouchableOpacity, + View, +} from 'react-native'; + +const App = () => { + const inputRef = useRef(null); + const editText = useCallback(() => { + inputRef.current?.setNativeProps({text: 'Edited Text'}); + }, []); + + return ( + + + + Edit text + + + ); +}; + +const styles = StyleSheet.create({ + container: { + flex: 1, + alignItems: 'center', + justifyContent: 'center', + }, + input: { + height: 50, + width: 200, + marginHorizontal: 20, + borderWidth: 1, + borderColor: '#ccc', + }, +}); + +export default App; +``` + +Você pode usar o método [`clear`](/docs/textinput#clear) para limpar o `TextInput` que limpa o texto de entrada atual usando a mesma abordagem. + +## Evitando conflitos com a função render + +Se você atualizar uma propriedade que também é gerenciada pela função de renderização, poderá acabar com alguns bugs imprevisíveis e confusos porque sempre que o componente for renderizado novamente e essa propriedade mudar, qualquer valor que tenha sido definido anteriormente em `setNativeProps` será completamente ignorado e substituído. + +## setNativeProps e shouldComponentUpdate + +Ao [aplicar de forma inteligente `shouldComponentUpdate`](https://reactjs.org/docs/optimizing-performance.html#avoid-reconciliation), você pode evitar a sobrecarga desnecessária envolvida na reconciliação de subárvores de componentes inalteradas a ponto de ter um desempenho suficiente, basta usar `setState` em vez de `setNativeProps`. + +## Outros métodos nativos + +Os métodos descritos aqui estão disponíveis na maioria dos componentes padrão fornecidos pelo React Native. Observe, entretanto, que eles _não_ estão disponíveis em componentes compostos que não sejam diretamente apoiados por uma visualização nativa. Geralmente, isso incluirá a maioria dos componentes definidos em seu próprio aplicativo. + +### measure(callback) + +Determina a localização na tela, largura e altura na janela de visualização da view fornecida e retorna os valores por meio de um retorno de chamada assíncrono. Se for bem-sucedido, o retorno de chamada será chamado com os seguintes argumentos: + +- x +- y +- width +- height +- pageX +- pageY + +Observe que essas medidas não estarão disponíveis até que a renderização seja concluída no modo nativo. Se você precisar das medidas o mais rápido possível e não precisar de `pageX` e `pageY`, considere usar a propriedade [`onLayout`](/docs/view.md#onlayout). + +Além disso, a largura e a altura retornadas por `measure()` são a largura e a altura do componente na janela de visualização. Se você precisar do tamanho real do componente, considere usar a propriedade [`onLayout`](/docs/view.md#onlayout). + +### measureInWindow(callback) + +Determina a localização da visualização fornecida na janela e retorna os valores por meio de um retorno de chamada assíncrono. Se a visualização raiz do React estiver incorporada em outra visualização nativa, isso fornecerá as coordenadas absolutas. Se for bem-sucedido, o retorno de chamada será chamado com os seguintes argumentos: + +- x +- y +- width +- height + +### measureLayout(relativeToNativeComponentRef, onSuccess, onFail) + +Como `measure()`, mas mede a visualização relativa a um ancestral, especificado com a referência `relativeToNativeComponentRef`. Isso significa que as coordenadas retornadas são relativas à origem `x`, `y` da visão ancestral. + +::: info Observação +Este método também pode ser chamado com um manipulador `relativeToNativeNode` (em vez de referência), mas esta variante está obsoleta. +::: + +```jsx [measureLayout%20example&supportedPlatforms=android,ios] +import React, {useEffect, useRef, useState} from 'react'; +import {Text, View, StyleSheet} from 'react-native'; + +const App = () => { + const textContainerRef = useRef(null); + const textRef = useRef(null); + const [measure, setMeasure] = useState(null); + + useEffect(() => { + if (textRef.current && textContainerRef.current) { + textRef.current.measureLayout( + textContainerRef.current, + (left, top, width, height) => { + setMeasure({left, top, width, height}); + }, + ); + } + }, [measure]); + + return ( + + + Where am I? (relative to the text container) + + {JSON.stringify(measure)} + + ); +}; + +const styles = StyleSheet.create({ + container: { + flex: 1, + justifyContent: 'center', + }, + textContainer: { + backgroundColor: '#61dafb', + justifyContent: 'center', + alignItems: 'center', + padding: 12, + }, + measure: { + textAlign: 'center', + padding: 12, + }, +}); + +export default App; +``` + +```tsx [measureLayout%20example] +import React, {useEffect, useRef, useState} from 'react'; +import {Text, View, StyleSheet} from 'react-native'; + +type Measurements = { + left: number; + top: number; + width: number; + height: number; +}; + +const App = () => { + const textContainerRef = useRef(null); + const textRef = useRef(null); + const [measure, setMeasure] = useState(null); + + useEffect(() => { + if (textRef.current && textContainerRef.current) { + textRef.current?.measureLayout( + textContainerRef.current, + (left, top, width, height) => { + setMeasure({left, top, width, height}); + }, + () => { + console.error('measurement failed'); + }, + ); + } + }, [measure]); + + return ( + + + Where am I? (relative to the text container) + + {JSON.stringify(measure)} + + ); +}; + +const styles = StyleSheet.create({ + container: { + flex: 1, + justifyContent: 'center', + }, + textContainer: { + backgroundColor: '#61dafb', + justifyContent: 'center', + alignItems: 'center', + padding: 12, + }, + measure: { + textAlign: 'center', + padding: 12, + }, +}); + +export default App; +``` + +### focus() + +Solicita foco para a entrada ou visualização fornecida. O comportamento exato acionado dependerá da plataforma e do tipo de visualização. + +### blur() + +Remove o foco de uma entrada ou visualização. Este é o oposto de `focus()`. diff --git a/vitepress/docs/docs/environment-setup.md b/vitepress/docs/docs/environment-setup.md new file mode 100644 index 0000000..73b6f25 --- /dev/null +++ b/vitepress/docs/docs/environment-setup.md @@ -0,0 +1,50 @@ +# Configurando o ambiente de desenvolvimento + +Esta página te ajudará a instalar e construir seu primeiro aplicativo React Native. + +**Se você é novo no desenvolvimento móvel**, a maneira mais fácil de começar é com o Expo Go. Expo é um conjunto de ferramentas e serviços construídos em torno do React Native e, embora tenha [muitos recursos](https://docs.expo.dev/), o recurso mais relevante para nós no momento é que você pode escrever um aplicativo React Native em minutos. Você só precisará de uma versão recente do Node.js e de um telefone ou emulador. Se quiser experimentar o React Native diretamente em seu navegador antes de instalar qualquer ferramenta, você pode experimentar o [Snack](https://snack.expo.dev/). + +**Se você já está familiarizado com o desenvolvimento móvel**, você pode querer usar o React Native CLI. Requer Xcode ou Android Studio para começar. Se você já tiver uma dessas ferramentas instalada, poderá colocá-la em funcionamento em alguns minutos. Se eles não estiverem instalados, você deverá gastar cerca de uma hora instalando-os e configurando-os. + +## Expo Go Início Rápido + +Execute o seguinte comando para criar um novo projeto React Native chamado "AwesomeProject": + +::: code-group +```bash [npm] +npx create-expo-app AwesomeProject + +cd AwesomeProject +npx expo start +``` + +```bash [yarn] +yarn create expo-app AwesomeProject + +cd AwesomeProject +yarn expo start +``` +::: + +Isso iniciará um servidor de desenvolvimento para você. + +### Executando seu aplicativo React Native +Instale o aplicativo [Expo Go](https://expo.dev/client) em seu telefone iOS ou Android e conecte-se à mesma rede sem fio do seu computador. No Android, use o aplicativo Expo Go para escanear o código QR do seu terminal para abrir seu projeto. No iOS, use o leitor de código QR integrado do aplicativo iOS Camera padrão. + +## React Native CLI Início Rápido +Siga estas instruções se precisar criar código nativo em seu projeto. Por exemplo, se você estiver integrando o React Native em um aplicativo existente ou se executou o "prebuild" do Expo para gerar o código nativo do seu projeto, você precisará desta seção. + +As instruções são um pouco diferentes dependendo do seu sistema operacional de desenvolvimento e se você deseja começar a desenvolver para iOS ou Android. Se você deseja desenvolver para Android e iOS, tudo bem - você pode escolher um para começar, já que a configuração é um pouco diferente. + +### macOS + +* [Android](/docs/environment-setup/mac-os/android.md) +* [iOS](/docs/environment-setup/mac-os/ios.md) + +### Windows +* [Android](/docs/environment-setup/windows/android.md) +* iOS _(Não compatível)_ + +### Linux +* [Android](/docs/environment-setup/linux/android.md) +* iOS _(Não compatível)_ diff --git a/vitepress/docs/docs/environment-setup/linux/android.md b/vitepress/docs/docs/environment-setup/linux/android.md new file mode 100644 index 0000000..cba4a6b --- /dev/null +++ b/vitepress/docs/docs/environment-setup/linux/android.md @@ -0,0 +1,179 @@ +# Instalando dependências + +Você precisará do Node, da interface de linha de comando React Native, de um JDK e do Android Studio. + +Embora você possa usar qualquer editor de sua escolha para desenvolver seu aplicativo, você precisará instalar o Android Studio para configurar as ferramentas necessárias para construir seu aplicativo React Native para Android. + +## Node +Siga as instruções de instalação da sua distribuição Linux para instalar o Node 18 ou mais recente. + +## Kit de desenvolvimento do Java +Atualmente, o React Native recomenda a versão 17 do Java SE Development Kit (JDK). Você pode encontrar problemas ao usar versões superiores do JDK. Você pode baixar e instalar o [OpenJDK](https://openjdk.java.net/) do [AdoptOpenJDK](https://adoptopenjdk.net/) ou do seu empacotador de sistema. + +## Ambiente de desenvolvimento Android +Configurar seu ambiente de desenvolvimento pode ser um tanto entediante se você for novo no desenvolvimento Android. Se você já estiver familiarizado com o desenvolvimento Android, talvez seja necessário configurar algumas coisas. Em ambos os casos, certifique-se de seguir cuidadosamente as próximas etapas. + +### 1. Instale o Android Studio +[Baixe e instale o Android Studio](https://developer.android.com/studio/index.html). No assistente de instalação do Android Studio, certifique-se de que as caixas ao lado de todos os itens a seguir estejam marcadas: + +* `SDK Android` +* `Android SDK Platform` +* `Android Virtual Device` + +Em seguida, clique em “Next” para instalar todos esses componentes. + +::: info Nota +Se as caixas de seleção estiverem esmaecidas, você terá a chance de instalar esses componentes mais tarde. +::: + +Depois que a configuração for finalizada e a tela de boas-vindas for exibida, prossiga para a próxima etapa. + +### 2. Instale o Android SDK +O Android Studio instala o Android SDK mais recente por padrão. Construir um aplicativo React Native com código nativo, no entanto, requer o SDK do `Android 13 (Tiramisu)` em particular. SDKs Android adicionais podem ser instalados por meio do SDK Manager no Android Studio. + +Para fazer isso, abra o Android Studio, clique no botão "Configure" e selecione "SDK Manager". + +::: info Nota +O SDK Manager também pode ser encontrado na caixa de diálogo "Settings" do Android Studio, em **Languages & Frameworks → Android SDK**. +::: + +Selecione a guia "SDK Platforms" no SDK Manager e marque a caixa ao lado de "Show Package Details" no canto inferior direito. Procure e expanda a entrada `Android 13 (Tiramisu)` e certifique-se de que os seguintes itens estejam marcados: + +* `Android SDK Platform 33` +* `Intel x86 Atom_64 System Image` ou `Google APIs Intel x86 Atom System Image` + +Em seguida, selecione a guia "SDK Tools" e marque a caixa ao lado de "Show Package Details" aqui também. Procure e expanda a entrada "Android SDK Build-Tools" e certifique-se de que `33.0.0` esteja selecionado. + +Por fim, clique em “Apply” para baixar e instalar o Android SDK e ferramentas de construção relacionadas. + +3. Configure a variável de ambiente `ANDROID_HOME` +As ferramentas React Native requerem a configuração de algumas variáveis de ambiente para construir aplicativos com código nativo. + +Adicione as seguintes linhas ao seu arquivo de configuração `$HOME/.bash_profile` ou `$HOME/.bashrc` (se você estiver usando `zsh`, então `~/.zprofile` ou `~/.zshrc`): + +``` +export ANDROID_HOME=$HOME/Android/Sdk +export PATH=$PATH:$ANDROID_HOME/emulator +export PATH=$PATH:$ANDROID_HOME/platform-tools +``` + +::: info Usando outro Shell +`.bash_profile` é específico do `bash`. Se estiver usando outro shell, você precisará editar o arquivo de configuração específico do shell apropriado. +::: + +Digite `source $HOME/.bash_profile` para bash ou `source $HOME/.zprofile` para carregar a configuração em seu shell atual. Verifique se `ANDROID_HOME` foi configurado executando `echo $ANDROID_HOME` e os diretórios apropriados foram adicionados ao seu caminho executando `echo $PATH`. + +::: info Caminho do Android +Certifique-se de usar o caminho correto do Android SDK. Você pode encontrar a localização real do SDK na caixa de diálogo "Settings" do Android Studio, em **Languages & Frameworks → Android SDK**. +::: + +## Watchman +Siga o guia de [instalação do Watchman](https://facebook.github.io/watchman/docs/install#buildinstall) para compilar e instalar o Watchman a partir do código-fonte. + +::: info Sobre o Watchman +[Watchman](https://facebook.github.io/watchman/docs/install) é uma ferramenta do Facebook para observar mudanças no sistema de arquivos. É altamente recomendável que você o instale para obter melhor desempenho e maior compatibilidade em certos casos extremos (tradução: você pode conseguir sobreviver sem instalar isso, mas sua milhagem pode variar; instalar isso agora pode evitar dores de cabeça mais tarde). +::: + +## Interface de linha de comando nativa do React +React Native possui uma interface de linha de comando integrada. Em vez de instalar e gerenciar uma versão específica da CLI globalmente, recomendamos que você acesse a versão atual em tempo de execução usando `npx`, que acompanha o Node.js. Com `npx react-native `, a versão estável atual da CLI será baixada e executada no momento em que o comando for executado. + +## Criando um novo aplicativo + +::: warning Atenção +Se você instalou anteriormente um pacote global `react-native-cli`, remova-o, pois pode causar problemas inesperados: + +```bash +npm desinstalar -g react-native-cli @react-native-community/cli +``` +::: + +React Native possui uma interface de linha de comando integrada, que você pode usar para gerar um novo projeto. Você pode acessá-lo sem instalar nada globalmente usando o `npx`, que acompanha o Node.js. Vamos criar um novo projeto React Native chamado "AwesomeProject": + +```bash +npx react-native@latest init AwesomeProject +``` + +Isso não é necessário se você estiver integrando o React Native em um aplicativo existente, se você "expulsou" da Expo ou se estiver adicionando suporte Android a um projeto React Native existente (consulte [Integração com aplicativos existentes](/docs/integration-with-existing-apps.md)). Você também pode usar uma CLI de terceiros para iniciar seu aplicativo React Native, como [Ignite CLI](https://github.com/infinitered/ignite). + +## [Opcional] Usando uma versão ou modelo específico +Se quiser iniciar um novo projeto com uma versão específica do React Native, você pode usar o argumento `--version`: + +```bash +npx react-native@X.XX.X init AwesomeProject --version X.XX.X +``` + +Você também pode iniciar um projeto com um modelo React Native personalizado com o argumento `--template`. + +## Preparando o dispositivo Android +Você precisará de um dispositivo Android para executar seu aplicativo React Native para Android. Pode ser um dispositivo Android físico ou, mais comumente, você pode usar um dispositivo virtual Android que permite emular um dispositivo Android em seu computador. + +De qualquer forma, você precisará preparar o dispositivo para executar aplicativos Android para desenvolvimento. + +### Usando um dispositivo físico +Se você tiver um dispositivo Android físico, poderá usá-lo para desenvolvimento no lugar de um AVD, conectando-o ao computador usando um cabo USB e seguindo as instruções [aqui](/docs/running-on-device.md). + +### Usando um dispositivo virtual +Se você usar o Android Studio para abrir `./AwesomeProject/android`, poderá ver a lista de dispositivos virtuais Android (AVDs) disponíveis abrindo o "AVD Manager" no Android Studio. Procure um ícone parecido com este: + +![image](/docs/assets/download.png) + +Se você instalou recentemente o Android Studio, provavelmente precisará [criar um novo AVD](https://developer.android.com/studio/run/managing-avds.html). Selecione "Create Virtual Device...", escolha qualquer telefone da lista e clique em "Next" e selecione a imagem **Tiramisu** API nível 33. + +::: info Aceleração de VM +Recomendamos configurar a [aceleração de VM](https://developer.android.com/studio/run/emulator-acceleration.html#vm-linux) em seu sistema para melhorar o desempenho. Depois de seguir essas instruções, volte para o AVD Manager. +::: + +Clique em "Next" e depois em "Finish" para criar seu AVD. Neste ponto, você poderá clicar no botão de triângulo verde próximo ao seu AVD para iniciá-lo e, em seguida, prosseguir para a próxima etapa. + +## Executando seu aplicativo React Native + +### Etapa 1: iniciar o Metro +[Metro](https://facebook.github.io/metro/) é a ferramenta de construção JavaScript para React Native. Para iniciar o servidor de desenvolvimento Metro, execute o seguinte na pasta do projeto: + +```bash +npm start +# ou +yarn start +``` + + +::: info **OBSERVAÇÃO** +Se você estiver familiarizado com desenvolvimento web, o Metro é semelhante a empacotadores como Vite e webpack, mas foi projetado de ponta a ponta para React Native. Por exemplo, Metro usa [Babel](https://babel.dev/) para transformar sintaxe como JSX em JavaScript executável. +::: + +### Etapa 2: inicie seu aplicativo +Deixe o Metro Bundler rodar em seu próprio terminal. Abra um novo terminal dentro da pasta do projeto React Native. Execute o seguinte: + +::: code-group +```bash [npm] +npm run android +``` +```bash [yarn] +yarn android +``` +::: + +Se tudo estiver configurado corretamente, você deverá ver seu novo aplicativo em execução no emulador do Android em breve. + +Essa é uma maneira de executar seu aplicativo: você também pode executá-lo diretamente no Android Studio. + +::: info Ajuda +Se você não conseguir fazer isso funcionar, consulte a página [Solução de problemas](/docs/troubleshooting.md). +::: + +## Modificando seu aplicativo +Agora que você executou o aplicativo com sucesso, vamos modificá-lo. + +* Abra `App.tsx` no editor de texto de sua preferência e edite algumas linhas. +* Pressione a tecla `R` duas vezes ou selecione `Reload` no menu Dev (`Ctrl` + `M`) para ver suas alterações! + +## É isso! +Parabéns! Você executou e modificou com sucesso seu primeiro aplicativo React Native. + +![image](/docs/assets/289088717-bc864112-bd55-43b6-8369-9d78e896376e.png) + +## E agora? + +* Se você deseja adicionar este novo código React Native a um aplicativo existente, consulte o [guia de integração](/docs/integration-with-existing-apps.md). + +Se você estiver curioso para saber mais sobre o React Native, confira a [Introdução ao React Native](/docs/getting-started.md). diff --git a/vitepress/docs/docs/environment-setup/mac-os/android.md b/vitepress/docs/docs/environment-setup/mac-os/android.md new file mode 100644 index 0000000..6e0c43d --- /dev/null +++ b/vitepress/docs/docs/environment-setup/mac-os/android.md @@ -0,0 +1,194 @@ +# Android + +## Instalando dependências +Você precisará do Node, do Watchman, da interface de linha de comando React Native, de um JDK e do Android Studio. + +Embora você possa usar qualquer editor de sua escolha para desenvolver seu aplicativo, você precisará instalar o Android Studio para configurar as ferramentas necessárias para criar seu aplicativo React Native para Android. + +## Node & Watchman +Recomendamos instalar o Node e o Watchman usando o [Homebrew](https://brew.sh/). Execute os seguintes comandos em um Terminal após instalar o Homebrew: + +```bash +brew install node +brew install watchman +``` + +Se você já instalou o Node em seu sistema, certifique-se de que seja o Node 18 ou mais recente. + +[Watchman](https://facebook.github.io/watchman) é uma ferramenta do Facebook para observar mudanças no sistema de arquivos. É altamente recomendável instalá-lo para melhor desempenho. + +## kit de desenvolvimento do Java +Recomendamos instalar a distribuição OpenJDK chamada Azul **Zulu** usando [Homebrew](https://brew.sh/). Execute os seguintes comandos em um Terminal após instalar o Homebrew: + +```bash +brew tap homebrew/cask-versions +brew install --cask zulu17 + +# Obtenha o caminho para onde o cask foi instalado para clicar duas vezes no instalador +brew info --cask zulu17 +``` + +Depois de instalar o JDK, atualize sua variável de ambiente `JAVA_HOME`. Se você usou as etapas acima, o JDK provavelmente estará em `/Library/Java/JavaVirtualMachines/zulu-17.jdk/Contents/Home` + +A distribuição Zulu OpenJDK oferece JDKs para Macs Intel e M1. Isso garantirá que suas compilações sejam mais rápidas em Macs M1 em comparação com o uso de um JDK baseado em Intel. + +Se você já instalou o JDK em seu sistema, recomendamos o JDK 17. Você pode encontrar problemas ao usar versões superiores do JDK. + +### 1. Instale o Android Studio +[Baixe e instale o Android Studio](https://developer.android.com/studio/index.html). No assistente de instalação do Android Studio, certifique-se de que as caixas ao lado de todos os itens a seguir estejam marcadas: + +`SDK Android` +`Plataforma Android SDK` +`Dispositivo virtual Android` + +Em seguida, clique em "Next" para instalar todos esses componentes. + +::: info Nota +Se as caixas de seleção estiverem esmaecidas, você terá a chance de instalar esses componentes mais tarde. +::: + +Depois que a configuração for finalizada e a tela de boas-vindas for exibida, prossiga para a próxima etapa. + +### 2. Instale o Android SDK +O Android Studio instala o Android SDK mais recente por padrão. Construir um aplicativo React Native com código nativo, no entanto, requer o SDK do `Android 13 (Tiramisu)` em particular. SDKs Android adicionais podem ser instalados por meio do SDK Manager no Android Studio. + +Para fazer isso, abra o Android Studio, clique no botão "More Actions" e selecione "SDK Manager". + +![image](/docs/assets/288755758-175ae9d7-3e6d-42ba-9b12-a1e89bf0df53.png) + +::: info Nota +O SDK Manager também pode ser encontrado na caixa de diálogo "Settings" do Android Studio, em **Languages & Frameworks → Android SDK**. +::: + +Selecione a guia "Plataformas SDK" no SDK Manager e marque a caixa ao lado de "Mostrar detalhes do pacote" no canto inferior direito. Procure e expanda a entrada `Android 13 (Tiramisu)` e certifique-se de que os seguintes itens estejam marcados: + +* `Plataforma Android SDK 33` +* Imagem do sistema `Intel x86 Atom_64` ou `Google APIs Intel x86 Atom System Image` ou (para Apple M1 Silicon) `Google APIs ARM 64 v8a System Image` + +Em seguida, selecione a guia "SDK Tools" e marque a caixa ao lado de "Show Package Details" aqui também. Procure e expanda a entrada "Android SDK Build-Tools" e certifique-se de que `33.0.0` esteja selecionado. + +Por fim, clique em “Apply” para baixar e instalar o Android SDK e ferramentas de construção relacionadas. + +3. Configure a variável de ambiente `ANDROID_HOME` +As ferramentas React Native requerem a configuração de algumas variáveis de ambiente para construir aplicativos com código nativo. + +Adicione as seguintes linhas ao seu arquivo de configuração `~/.zprofile` ou `~/.zshrc` (se você estiver usando bash, então `~/.bash_profile` ou `~/.bashrc`): + +```bash +export ANDROID_HOME=$HOME/Library/Android/sdk +export PATH=$PATH:$ANDROID_HOME/emulator +export PATH=$PATH:$ANDROID_HOME/platform-tools +``` + +Execute `source ~/.zprofile` (ou `source ~/.bash_profile` para bash) para carregar a configuração em seu shell atual. Verifique se `ANDROID_HOME` foi configurado executando `echo $ANDROID_HOME` e os diretórios apropriados foram adicionados ao seu caminho executando `echo $PATH.` + +::: warning Atenção +Certifique-se de usar o caminho correto do Android SDK. Você pode encontrar a localização real do SDK na caixa de diálogo "**Settings**" do **Languages & Frameworks → Android SDK**. +::: + +## Interface de linha de comando nativa do React +React Native possui uma interface de linha de comando integrada. Em vez de instalar e gerenciar uma versão específica da CLI globalmente, recomendamos que você acesse a versão atual em tempo de execução usando `npx`, que acompanha o Node.js. Com `npx react-native `, a versão estável atual da CLI será baixada e executada no momento em que o comando for executado. + +## Criando um novo aplicativo + +::: warning Atenção +Se você instalou anteriormente um pacote global `react-native-cli`, remova-o, pois pode causar problemas inesperados: + +```bash +npm uninstall -g react-native-cli @react-native-community/cli +``` +::: + +React Native possui uma interface de linha de comando integrada, que você pode usar para gerar um novo projeto. Você pode acessá-lo sem instalar nada globalmente usando o `npx`, que acompanha o Node.js. Vamos criar um novo projeto React Native chamado "AwesomeProject": + +```bash +npx react-native@latest init AwesomeProject +``` + +Isso não é necessário se você estiver integrando o React Native em um aplicativo existente, se você "expulsou" da Expo ou se estiver adicionando suporte Android a um projeto React Native existente (consulte [Integração com aplicativos existentes](/docs/integration-with-existing-apps.md)). Você também pode usar uma CLI de terceiros para iniciar seu aplicativo React Native, como [Ignite CLI](https://github.com/infinitered/ignite). + +## [Opcional] Usando uma versão ou modelo específico +Se quiser iniciar um novo projeto com uma versão específica do React Native, você pode usar o argumento `--version`: + +```bash +npx react-native@X.XX.X init AwesomeProject --version X.XX.X +``` + +Você também pode iniciar um projeto com um modelo React Native personalizado com o argumento `--template`. + +## Preparando o dispositivo Android +Você precisará de um dispositivo Android para executar seu aplicativo React Native para Android. Pode ser um dispositivo Android físico ou, mais comumente, você pode usar um dispositivo virtual Android que permite emular um dispositivo Android em seu computador. + +De qualquer forma, você precisará preparar o dispositivo para executar aplicativos Android para desenvolvimento. + +### Usando um dispositivo físico +Se você tiver um dispositivo Android físico, poderá usá-lo para desenvolvimento no lugar de um AVD, conectando-o ao computador usando um cabo USB e seguindo as instruções [aqui](/docs/running-on-device.md). + +### Usando um dispositivo virtual +Se você usar o Android Studio para abrir `./AwesomeProject/android`, poderá ver a lista de dispositivos virtuais Android (AVDs) disponíveis abrindo o "AVD Manager" no Android Studio. Procure um ícone parecido com este: + +![image](/docs/assets/download.png) + +Se você instalou recentemente o Android Studio, provavelmente precisará [criar um novo AVD](https://developer.android.com/studio/run/managing-avds.html). Selecione "Create Virtual Device...", escolha qualquer telefone da lista e clique em "Next" e selecione a imagem **Tiramisu** API nível 33. + +Clique em “Next” e depois em “Finish” para criar seu AVD. Neste ponto, você poderá clicar no botão de triângulo verde próximo ao seu AVD para iniciá-lo e, em seguida, prosseguir para a próxima etapa. + +## Executando seu aplicativo React Native + +### Etapa 1: iniciar o Metro +[Metro](https://facebook.github.io/metro/) é a ferramenta de construção JavaScript para React Native. Para iniciar o servidor de desenvolvimento Metro, execute o seguinte na pasta do projeto: + +::: code-group + +```bash [npm] +npm start +``` + +```bash [yarn] +yarn start +``` +::: + +::: info **OBSERVAÇÃO** +Se você estiver familiarizado com desenvolvimento web, o Metro é semelhante a empacotadores como Vite e webpack, mas foi projetado de ponta a ponta para React Native. Por exemplo, Metro usa [Babel](https://babel.dev/) para transformar sintaxe como JSX em JavaScript executável. +::: + +### Step 2: Inicie sua aplicação + +::: code-group +```bash [npm] +npm run android +``` + +```bash [yarn] +yarn android +``` +::: + +Se tudo estiver configurado corretamente, você deverá ver seu novo aplicativo em execução no emulador do Android em breve. + +![image](/docs/assets/288759376-65fb76bd-40b8-4301-b292-a776ea55f17e.png) + +Essa é uma maneira de executar seu aplicativo: você também pode executá-lo diretamente no Android Studio. + +::: info Nota +Se você não conseguir fazer isso funcionar, consulte a página [Solução de problemas](/docs/troubleshooting.md). +::: + +### Modificando seu aplicativo + +Agora que você executou o aplicativo com sucesso, vamos modificá-lo. + +* Abra `App.tsx` no editor de texto de sua preferência e edite algumas linhas. +* Pressione a tecla `R` duas vezes ou selecione `Reload` no menu Dev (`Cmd ⌘` + `M`) para ver suas alterações! + +## É isso! +Parabéns! Você executou e modificou com sucesso seu primeiro aplicativo React Native. + +![image](https://github.com/tavaresgerson/reactnativedocbr/assets/22455192/c6b24c43-2e07-4845-9c2e-133189349b1c) + +#### E agora? + +* Se você deseja adicionar este novo código React Native a um aplicativo existente, consulte o [guia de integração](/docs/integration-with-existing-apps.md). + +Se você estiver curioso para saber mais sobre o React Native, confira a [Introdução ao React Native](/docs/getting-started.md). diff --git a/vitepress/docs/docs/environment-setup/mac-os/ios.md b/vitepress/docs/docs/environment-setup/mac-os/ios.md new file mode 100644 index 0000000..80db362 --- /dev/null +++ b/vitepress/docs/docs/environment-setup/mac-os/ios.md @@ -0,0 +1,161 @@ +# iOS + +## Instalando dependências +Você precisará de Node, Watchman, interface de linha de comando React Native, Xcode e CocoaPods. + +Embora você possa usar qualquer editor de sua escolha para desenvolver seu aplicativo, você precisará instalar o Xcode para configurar as ferramentas necessárias para construir seu aplicativo React Native para iOS. + +## Node e Watchman +Recomendamos instalar o Node e o Watchman usando o Homebrew. Execute os seguintes comandos em um Terminal após instalar o Homebrew: + +```bash +brew install node +brew install watchman +``` + +Se você já instalou o Node em seu sistema, certifique-se de que seja o Node 18 ou mais recente. + +[Watchman](https://facebook.github.io/watchman) é uma ferramenta do Facebook para observar mudanças no sistema de arquivos. É altamente recomendável instalá-lo para melhor desempenho. + +## Xcode +A maneira mais fácil de instalar o Xcode é através da [Mac App Store](https://itunes.apple.com/us/app/xcode/id497799835?mt=12). A instalação do Xcode também instalará o Simulador iOS e todas as ferramentas necessárias para construir seu aplicativo iOS. + +Se você já instalou o Xcode em seu sistema, certifique-se de que seja a versão 10 ou mais recente. + +### Ferramentas de linha de comando +Você também precisará instalar as ferramentas de linha de comando do Xcode. Abra o Xcode e escolha **Settings...** (ou **Preferences...**) no menu Xcode. Vá para o painel Locais e instale as ferramentas selecionando a versão mais recente no menu suspenso Ferramentas de linha de comando. + +![image](/docs/assets/289078069-79daecf4-41df-45e4-bdfd-34120ecb2d9b.png) + +### Instalando um simulador iOS no Xcode +Para instalar um simulador, abra **Xcode > Settings...** (ou **Preferences...**) e selecione a aba **Platforms** (ou **Components**). Selecione um simulador com a versão correspondente do iOS que você deseja usar. + +Se você estiver usando o Xcode versão 14.0 ou superior para instalar um simulador, abra **Xcode > Settings > Platforms**, clique no ícone "**+**" e selecione a opção **iOS…**. + +## CocoaPods +[CocoaPods](https://cocoapods.org/) é um dos sistemas de gerenciamento de dependências disponíveis para iOS. CocoaPods é uma [gem](https://en.wikipedia.org/wiki/RubyGems) Ruby. Você pode instalar CocoaPods usando a versão do Ruby fornecida com a versão mais recente do macOS. + +Para obter mais informações, visite o guia de [primeiros passos do CocoaPods](https://guides.cocoapods.org/using/getting-started.html). + +## Interface de linha de comando nativa do React +React Native possui uma interface de linha de comando integrada. Em vez de instalar e gerenciar uma versão específica da CLI globalmente, recomendamos que você acesse a versão atual em tempo de execução usando `npx`, que acompanha o Node.js. Com `npx react-native `, a versão estável atual da CLI será baixada e executada no momento em que o comando for executado. + +## Criando um novo aplicativo + + +::: warning Atenção! +Se você instalou anteriormente o pacote global `react-native-cli`, remova-o, pois pode causar problemas inesperados: +```bash +npm uninstall -g react-native-cli @react-native-community/cli +``` +::: + +Você pode usar a interface de linha de comando integrada do React Native para gerar um novo projeto. Vamos criar um novo projeto React Native chamado "AwesomeProject": + +```bash +npx react-native@latest init AwesomeProject +``` + +Isso não é necessário se você estiver integrando o React Native em um aplicativo existente, se você "expulsou" da Expo ou se estiver adicionando suporte a iOS ao projeto React Native existente (consulte [Integração com aplicativos existentes](/docs/integration-with-existing-apps.md)). Você também pode usar uma CLI de terceiros para iniciar seu aplicativo React Native, como [Ignite CLI](https://github.com/infinitered/ignite). + +::: info **INFORMAÇÕES** +Se você estiver tendo problemas com o iOS, tente reinstalar as dependências executando: + +* `cd ios` para navegar até a pasta ios. +* `bundle install` para instalar o [Bundler](https://bundler.io/) +* `bundle exec pod install` para instalar as dependências do iOS gerenciadas pelo CocoaPods. +::: + +## [Opcional] Usando uma versão ou modelo específico +Se quiser iniciar um novo projeto com uma versão específica do React Native, você pode usar o argumento `--version`: + +```bash +npx react-native@X.XX.X init AwesomeProject --version X.XX.X +``` + +Você também pode iniciar um projeto com um modelo React Native personalizado com o argumento `--template`. + +::: info **Nota** +Se o comando acima estiver falhando, você pode ter uma versão antiga do `react-native` ou `react-native-cli` instalada globalmente no seu PC. Tente desinstalar o cli e execute-o usando `npx`. +::: + +## [Opcional] Configurando seu ambiente +A partir do React Native versão 0.69, é possível configurar o ambiente Xcode usando o arquivo `.xcode.env` fornecido pelo template. + +O arquivo `.xcode.env` contém uma variável de ambiente para exportar o caminho para o executável do node na variável `NODE_BINARY`. Esta é a abordagem sugerida para dissociar a infraestrutura de construção da versão do sistema do `node`. Você deve customizar esta variável com seu próprio caminho ou seu próprio gerenciador de versão de `node`, se for diferente do padrão. + +Além disso, é possível adicionar qualquer outra variável de ambiente e originar o arquivo `.xcode.env` nas fases do script de construção. Caso você precise executar um script que requeira algum ambiente específico, esta é a abordagem sugerida: permite desacoplar as fases de construção de um ambiente específico. + +::: info **INFORMAÇÕES** +Se você já estiver usando [NVM](https://nvm.sh/) (um comando que ajuda a instalar e alternar entre versões do Node.js) e [zsh](https://ohmyz.sh/), você pode querer mover o código que inicializa o NVM de seu `~/.zshrc` para um arquivo `~/.zshenv` para ajudar o Xcode a encontre seu executável Node: + +```bash +export NVM_DIR="$HOME/.nvm" +[ -s "$NVM_DIR/nvm.sh" ] && \. "$NVM_DIR/nvm.sh" # Isso carrega o nvm +``` + +Você também pode querer garantir que toda a "fase de construção do script de shell" do seu projeto Xcode esteja usando `/bin/zsh` como seu shell. +::: + +## Executando seu aplicativo React Native + +### Etapa 1: iniciar o Metro +[Metro](https://facebook.github.io/metro/) é a ferramenta de construção JavaScript para React Native. Para iniciar o servidor de desenvolvimento Metro, execute o seguinte na pasta do projeto: + +::: code-group +```bash [npm] +npm start +``` + +```bash [yarn] +yarn start +``` +::: + + +::: info **OBSERVAÇÃO** +Se você estiver familiarizado com desenvolvimento web, o Metro é semelhante a empacotadores como Vite e webpack, mas foi projetado de ponta a ponta para React Native. Por exemplo, Metro usa [Babel](https://babel.dev/) para transformar sintaxe como JSX em JavaScript executável. +::: + +### Etapa 2: inicie seu aplicativo +Deixe o Metro Bundler rodar em seu próprio terminal. Abra um novo terminal dentro da pasta do projeto React Native. Execute o seguinte: + +::: code-group +```bash [npm] +npm run ios +``` + +```bash [yarn] +yarn ios +``` +::: + +Você deverá ver seu novo aplicativo em execução no iOS Simulator em breve. + +![image](/docs/assets/289086561-8042a459-ead2-4b1a-ba59-41b673d9b7d8.png) + +Esta é uma maneira de executar seu aplicativo. Você também pode executá-lo diretamente no Xcode. + +::: info Ajuda +Se você não conseguir fazer isso funcionar, consulte a página [Solução de problemas](/docs/troubleshooting.md). +::: + +## Executando em um dispositivo +O comando acima executará automaticamente seu aplicativo no iOS Simulator por padrão. Se você deseja executar o aplicativo em um dispositivo iOS físico real, siga as instruções [aqui](/docs/running-on-device.md). + +### Modificando seu aplicativo +Agora que você executou o aplicativo com sucesso, vamos modificá-lo. + +* Abra `App.tsx` no editor de texto de sua preferência e edite algumas linhas. +* Pressione `Cmd ⌘` + `R` no seu simulador iOS para recarregar o aplicativo e ver suas alterações! + +## É isso! +Parabéns! Você executou e modificou com sucesso seu primeiro aplicativo React Native. + +![image](/docs/assets/289088717-bc864112-bd55-43b6-8369-9d78e896376e.png) + +## E agora? + +* Se você deseja adicionar este novo código React Native a um aplicativo existente, consulte o [guia de integração](/docs/integration-with-existing-apps.md). + +Se você estiver curioso para saber mais sobre o React Native, confira a [Introdução ao React Native](https://reactnative.dev/docs/getting-started.md). diff --git a/vitepress/docs/docs/environment-setup/windows/android.md b/vitepress/docs/docs/environment-setup/windows/android.md new file mode 100644 index 0000000..fedcf44 --- /dev/null +++ b/vitepress/docs/docs/environment-setup/windows/android.md @@ -0,0 +1,217 @@ +# Instalando dependências + +Você precisará do Node, da interface de linha de comando React Native, de um JDK e do Android Studio. + +Embora você possa usar qualquer editor de sua escolha para desenvolver seu aplicativo, você precisará instalar o Android Studio para configurar as ferramentas necessárias para criar seu aplicativo React Native para Android. + +## Node, JDK +Recomendamos instalar o Node via [Chocolatey](https://chocolatey.org/install), um popular gerenciador de pacotes para Windows. + +Recomenda-se usar uma versão LTS do Node. Se você quiser alternar entre versões diferentes, você pode instalar o Node via [nvm-windows](https://github.com/coreybutler/nvm-windows), um gerenciador de versões do Node para Windows. + +React Native também requer [Java SE Development Kit (JDK)](https://openjdk.java.net/projects/jdk/17/), que também pode ser instalado usando Chocolatey. + +Abra um prompt de comando do administrador (clique com o botão direito em prompt de comando e selecione "Executar como administrador") e execute o seguinte comando: + +```bash +choco install -y nodejs-lts microsoft-openjdk17 +``` + +Se você já instalou o Node em seu sistema, certifique-se de que seja o Node 18 ou mais recente. Se você já possui um JDK em seu sistema, recomendamos o JDK17. Você pode encontrar problemas ao usar versões superiores do JDK. + +::: info Node +Você pode encontrar opções de instalação adicionais na página de [downloads do Node](https://nodejs.org/en/download/)https://nodejs.org/en/download/. +::: + +::: info Java Development Kit +Se estiver usando a versão mais recente do Java Development Kit, você precisará alterar a versão Gradle do seu projeto para que ele possa reconhecer o JDK. Você pode fazer isso acessando `{pasta raiz do projeto}\android\gradle\wrapper\gradle-wrapper.properties` e alterando o valor `DistributionUrl` para atualizar a versão Gradle. Você pode conferir [aqui](https://gradle.org/releases/) os últimos lançamentos do Gradle. +::: + +## Ambiente de desenvolvimento Android +Configurar seu ambiente de desenvolvimento pode ser um tanto entediante se você for novo no desenvolvimento Android. Se você já estiver familiarizado com o desenvolvimento Android, talvez seja necessário configurar algumas coisas. Em ambos os casos, certifique-se de seguir cuidadosamente as próximas etapas. + +### 1. Instale o Android Studio +Baixe e instale o Android Studio. No assistente de instalação do Android Studio, certifique-se de que as caixas ao lado de todos os itens a seguir estejam marcadas: + +* `SDK Android` +* `Plataforma Android SDK` +* `Dispositivo Virtual Android` +* Se você ainda não estiver usando Hyper-V: `Performance (Intel ® HAXM)` (Veja aqui para [AMD ou Hyper-V](https://android-developers.googleblog.com/2018/07/android-emulator-amd-processor-hyper-v.html)) + +Em seguida, clique em “Next” para instalar todos esses componentes. + +::: info Nota +Se as caixas de seleção estiverem esmaecidas, você terá a chance de instalar esses componentes mais tarde. +::: + +Depois que a configuração for finalizada e a tela de boas-vindas for exibida, prossiga para a próxima etapa. + +### 2. Instale o Android SDK +O Android Studio instala o Android SDK mais recente por padrão. Construir um aplicativo React Native com código nativo, no entanto, requer o SDK do `Android 13 (Tiramisu)` em particular. SDKs Android adicionais podem ser instalados por meio do SDK Manager no Android Studio. + +Para fazer isso, abra o Android Studio, clique no botão "More Actions" e selecione "SDK Manager". + +![image](/docs/assets/289275766-33a7f3de-c80c-47db-b195-35cf25023b27.png) + +::: info Nota +O SDK Manager também pode ser encontrado na caixa de diálogo "Settings" do Android Studio, em **Languages & Frameworks → Android SDK**. +::: + +Selecione a guia "SDK Platforms" no SDK Manager e marque a caixa ao lado de "Show Package Details" no canto inferior direito. Procure e expanda a entrada `Android 13 (Tiramisu)` e certifique-se de que os seguintes itens estejam marcados: + +* `Plataforma Android SDK 33` +* `Intel x86 Atom_64 System Image` ou `Google APIs Intel x86 Atom System Image` + +Em seguida, selecione a guia "SDK Tools" e marque a caixa ao lado de "Show Package Details" aqui também. Procure e expanda a entrada `Android SDK Build-Tools` e certifique-se de que `33.0.0` esteja selecionado. + +Por fim, clique em "Apply" para baixar e instalar o Android SDK e ferramentas de construção relacionadas. + +3. Configure a variável de ambiente `ANDROID_HOME` +As ferramentas React Native requerem a configuração de algumas variáveis de ambiente para construir aplicativos com código nativo. + +1. Abra o **Painel de Controle do Windows**. +2. Clique em **Contas de usuário** e clique em **Contas de usuário** novamente +3. Clique em **Alterar minhas variáveis de ambiente** +4. Clique em **Novo...** para criar uma nova variável de usuário `ANDROID_HOME` que aponta para o caminho para seu Android SDK: + +![image](/docs/assets/289276022-2b29397f-f3d1-41cb-a25c-84aff19487bf.png) + +O SDK é instalado, por padrão, no seguinte local: + +``` +%LOCALAPPDATA%\Android\Sdk +``` + +Você pode encontrar a localização real do SDK na caixa de diálogo "Settings" do Android Studio, em **Languages & Frameworks → Android SDK**. + +Abra uma nova janela do prompt de comando para garantir que a nova variável de ambiente seja carregada antes de prosseguir para a próxima etapa. + +1. Abra o PowerShell +2. Copie e cole **Get-ChildItem -Path Env:\** no PowerShell +3. Verifique se `ANDROID_HOME` foi adicionado +4. Adicione ferramentas de plataforma ao Path + + 1. Abra o **Painel de Controle do Windows**. + 2. Clique em **Contas de usuário** e clique em **Contas de usuário** novamente + 3. Clique em **Alterar minhas variáveis de ambiente** + 4. Selecione a variável **Caminho**. + 5. Clique em **Editar**. + 6. Clique em **Novo** e adicione o caminho para ferramentas de plataforma à lista. + +O local padrão para esta pasta é: + +``` +%LOCALAPPDATA%\Android\Sdk\platform-tools +``` + +## Interface de linha de comando nativa do React + +React Native possui uma interface de linha de comando integrada. Em vez de instalar e gerenciar uma versão específica da CLI globalmente, recomendamos que você acesse a versão atual em tempo de execução usando `npx`, que acompanha o Node.js. Com `npx react-native `, a versão estável atual da CLI será baixada e executada no momento em que o comando for executado. + +## Criando um novo aplicativo + +::: warning Atenção +Se você instalou anteriormente o pacote global `react-native-cli`, remova-o, pois pode causar problemas inesperados: +``` +npm desinstalar -g react-native-cli @react-native-community/cli +``` +::: + +React Native possui uma interface de linha de comando integrada, que você pode usar para gerar um novo projeto. Você pode acessá-lo sem instalar nada globalmente usando o `npx`, que acompanha o Node.js. Vamos criar um novo projeto React Native chamado "AwesomeProject": + +```bash +npx react-native@latest init AwesomeProject +``` + +Isso não é necessário se você estiver integrando o React Native em um aplicativo existente, se você "expulsou" da Expo ou se estiver adicionando suporte Android a um projeto React Native existente (consulte [Integração com aplicativos existentes](/docs/integration-with-existing-apps.md)). Você também pode usar uma CLI de terceiros para iniciar seu aplicativo React Native, como [Ignite CLI](https://github.com/infinitered/ignite). + +## [Opcional] Usando uma versão ou modelo específico + +Se quiser iniciar um novo projeto com uma versão específica do React Native, você pode usar o argumento `--version`: + +``` +npx react-native@X.XX.X init AwesomeProject --versão X.XX.X +``` + +Você também pode iniciar um projeto com um modelo React Native personalizado com o argumento `--template`. + +## Preparando o dispositivo Android +Você precisará de um dispositivo Android para executar seu aplicativo React Native para Android. Pode ser um dispositivo Android físico ou, mais comumente, você pode usar um dispositivo virtual Android que permite emular um dispositivo Android em seu computador. + +De qualquer forma, você precisará preparar o dispositivo para executar aplicativos Android para desenvolvimento. + +### Usando um dispositivo físico +Se você tiver um dispositivo Android físico, poderá usá-lo para desenvolvimento no lugar de um AVD, conectando-o ao computador usando um cabo USB e seguindo as instruções aqui. + +### Usando um dispositivo virtual +Se você usar o Android Studio para abrir `./AwesomeProject/android`, poderá ver a lista de dispositivos virtuais Android (AVDs) disponíveis abrindo o "AVD Manager" no Android Studio. Procure um ícone parecido com este: + +![image](/docs/assets/download.png) + +Se você instalou recentemente o Android Studio, provavelmente precisará criar um novo AVD. Selecione "[Create Virtual Device...](https://developer.android.com/studio/run/managing-avds.html)", escolha qualquer telefone da lista e clique em "Next" e selecione a imagem `Tiramisu` API nível 33. + +::: info Nota +Se você não possui o HAXM instalado, clique em "Install HAXM" ou siga [estas instruções](https://github.com/intel/haxm/wiki/Installation-Instructions-on-Windows) para configurá-lo e volte para o AVD Manager. +::: + +Clique em “Next” e depois em “Finish” para criar seu AVD. Neste ponto, você poderá clicar no botão de triângulo verde próximo ao seu AVD para iniciá-lo e, em seguida, prosseguir para a próxima etapa. + +## Executando seu aplicativo React Native + +### Etapa 1: iniciar o Metro +[Metro](https://facebook.github.io/metro/) é a ferramenta de construção JavaScript para React Native. Para iniciar o servidor de desenvolvimento Metro, execute o seguinte na pasta do projeto: + + +::: code-group +```bash [npm] +npm start +``` +```bash [yarn] +yarn start +``` +::: + +::: info **OBSERVAÇÃO** +Se você estiver familiarizado com desenvolvimento web, o Metro é semelhante a empacotadores como Vite e webpack, mas foi projetado de ponta a ponta para React Native. Por exemplo, Metro usa [Babel](https://babel.dev/) para transformar sintaxe como JSX em JavaScript executável. +::: + +### Etapa 2: inicie seu aplicativo +Deixe o Metro Bundler rodar em seu próprio terminal. Abra um novo terminal dentro da pasta do projeto React Native. Execute o seguinte: + +::: code-group +```bash [npm] +npm run android +``` +```bash [yarn] +yarn android +``` +::: + +Se tudo configurou tudo corretamente, você deverá ver seu novo aplicativo em execução no emulador do Android em breve. + +![image](/docs/assets/289277030-71da2fbe-ea92-48ae-b243-edf07876a7db.png) + +Essa é uma maneira de executar seu aplicativo: você também pode executá-lo diretamente no Android Studio. + +::: info Ajuda +Se você não conseguir fazer isso funcionar, consulte a página [Solução de problemas](https://reactnative.dev/docs/troubleshooting). +::: + +## Modificando seu aplicativo +Agora que você executou o aplicativo com sucesso, vamos modificá-lo. + +* Abra `App.tsx` no editor de texto de sua preferência e edite algumas linhas. +* Pressione a tecla `R` duas vezes ou selecione "Reload" no menu Dev (`Ctrl` + `M`) para ver suas alterações! + +## É isso! +Parabéns! Você executou e modificou com sucesso seu primeiro aplicativo React Native. + +![image](/docs/assets/289088717-bc864112-bd55-43b6-8369-9d78e896376e.png) + +## E agora? + +* Se você deseja adicionar este novo código React Native a um aplicativo existente, consulte o [guia de integração](/docs/integration-with-existing-apps.md). + +Se você estiver curioso para saber mais sobre o React Native, confira a [Introdução ao React Native](/docs/getting-started.md). + + diff --git a/vitepress/docs/docs/fast-refresh.md b/vitepress/docs/docs/fast-refresh.md new file mode 100644 index 0000000..02ba8f2 --- /dev/null +++ b/vitepress/docs/docs/fast-refresh.md @@ -0,0 +1,38 @@ +# Atualização rápida +Fast Refresh é um recurso do React Native que permite obter feedback quase instantâneo sobre alterações em seus componentes React. A atualização rápida está habilitada por padrão e você pode alternar "Enable Fast Refresh" no [menu React Native Dev](/docs/debugging.md). Com a Atualização rápida ativada, a maioria das edições deve ficar visível em um ou dois segundos. + +## Como funciona +* Se você editar um módulo que exporta apenas componentes React, o Fast Refresh atualizará o código apenas para esse módulo e renderizará novamente seu componente. Você pode editar qualquer coisa nesse arquivo, incluindo estilos, lógica de renderização, manipuladores de eventos ou efeitos. +* Se você editar um módulo com exportações que não sejam componentes do React, o Fast Refresh executará novamente esse módulo e os outros módulos que o importam. Portanto, se `Button.js` e `Modal.js` importarem `Theme.js`, a edição de `Theme.js` atualizará ambos os componentes. +* Finalmente, se você editar um arquivo importado por módulos fora da árvore React, o Fast Refresh voltará a fazer uma recarga completa. Você pode ter um arquivo que renderiza um componente React, mas também exporta um valor que é importado por um componente não React. Por exemplo, talvez seu componente também exporte uma constante e um módulo utilitário não React a importe. Nesse caso, considere migrar a constante para um arquivo separado e importá-la para ambos os arquivos. Isso reativará o funcionamento do Fast Refresh. Outros casos geralmente podem ser resolvidos de maneira semelhante. + +## Resiliência a erros +Se você cometer um erro de sintaxe durante uma sessão de atualização rápida, poderá corrigi-lo e salvar o arquivo novamente. A caixa vermelha desaparecerá. Módulos com erros de sintaxe são impedidos de serem executados, portanto você não precisará recarregar o aplicativo. + +Se você cometer um erro de tempo de execução durante a inicialização do módulo (por exemplo, digitando `Style.create` em vez de `StyleSheet.create`), a sessão de atualização rápida continuará depois que o erro for corrigido. A caixa vermelha desaparecerá e o módulo será atualizado. + +Se você cometer um erro que leve a um erro de tempo de execução dentro do seu componente, a sessão de atualização rápida também continuará após a correção do erro. Nesse caso, o React remontará seu aplicativo usando o código atualizado. + +Se você tiver [limites de erro](https://reactjs.org/docs/error-boundaries.html) em seu aplicativo (o que é uma boa ideia para falhas normais na produção), eles tentarão renderizar novamente na próxima edição após uma caixa vermelha. Nesse sentido, ter um limite de erro pode impedir que você seja sempre expulso da tela raiz do aplicativo. No entanto, lembre-se de que os limites de erro não devem ser muito granulares. Eles são usados pelo React em produção e devem sempre ser projetados intencionalmente. + +## Limitações +O Fast Refresh tenta preservar o estado React local no componente que você está editando, mas somente se for seguro fazê-lo. Aqui estão alguns motivos pelos quais você pode ver o estado local sendo redefinido a cada edição de um arquivo: + +* O estado local não é preservado para componentes de classe (apenas componentes de função e Hooks preservam o estado). +* O módulo que você está editando pode ter outras exportações além de um componente React. +* Às vezes, um módulo exportaria o resultado da chamada de um componente de ordem superior como `createNavigationContainer(MyScreen)`. Se o componente retornado for uma classe, o estado será redefinido. + +No longo prazo, à medida que mais da sua base de código se move para componentes de função e ganchos, você pode esperar que o estado seja preservado em mais casos. + +## Dicas +* A atualização rápida preserva o estado local do React nos componentes de função (e hooks) por padrão. +* Às vezes, você pode querer forçar a redefinição do estado e a remontagem de um componente. Por exemplo, isso pode ser útil se você estiver ajustando uma animação que só acontece na montagem. Para fazer isso, você pode adicionar `// @refresh reset` em qualquer lugar do arquivo que está editando. Esta diretiva é local para o arquivo e instrui o Fast Refresh a remontar os componentes definidos nesse arquivo em cada edição. + +## Atualização rápida e ganchos +Quando possível, a Atualização Rápida tenta preservar o estado do seu componente entre as edições. Em particular, useState e useRef preservam seus valores anteriores, desde que você não altere seus argumentos ou a ordem das chamadas do Hook. + +Ganchos com dependências — como `useEffect`, `useMemo` e `useCallback` — sempre serão atualizados durante o Fast Refresh. Sua lista de dependências será ignorada enquanto a atualização rápida estiver acontecendo. + +Por exemplo, quando você edita `useMemo(() => x * 2, [x])` para `useMemo(() => x * 10, [x])`, ele será executado novamente mesmo que `x` (a dependência) não tenha mudado. Se o React não fizesse isso, sua edição não seria refletida na tela! + +Às vezes, isso pode levar a resultados inesperados. Por exemplo, mesmo um `useEffect` com uma matriz vazia de dependências ainda seria executado novamente uma vez durante a Atualização Rápida. No entanto, escrever código resiliente a uma nova execução ocasional de `useEffect` é uma boa prática, mesmo sem o Fast Refresh. Isso torna mais fácil para você introduzir posteriormente novas dependências nele. diff --git a/vitepress/docs/docs/flexbox.md b/vitepress/docs/docs/flexbox.md new file mode 100644 index 0000000..ad8fed8 --- /dev/null +++ b/vitepress/docs/docs/flexbox.md @@ -0,0 +1,1524 @@ +# Layout com Flexbox + +Um componente pode especificar o layout de seus filhos usando o algoritmo Flexbox. Flexbox foi projetado para fornecer um layout consistente em diferentes tamanhos de tela. + +Normalmente, você usará uma combinação de `flexDirection`, `alignItems` e `justifyContent` para obter o layout correto. + +::: warning **CUIDADO** +O Flexbox funciona no React Native da mesma maneira que no CSS na web, com algumas exceções. Os padrões são diferentes, com `flexDirection` padronizando para coluna em vez de linha, `alignContent` padronizando para `flex-start` em vez de `stretch`, `flexShrink` padronizando para `0` em vez de `1`, o parâmetro `flex` suportando apenas um único número. +::: + +## Flex + +`flex` definirá como seus itens irão “preencher” o espaço disponível ao longo de seu eixo principal. O espaço será dividido de acordo com a propriedade flex de cada elemento. + +No exemplo a seguir, as visualizações vermelha, laranja e verde são todas filhas na visualização do contêiner que possui `flex: 1` definido. A visualização vermelha usa `flex: 1` , a visualização laranja usa `flex: 2` e a visualização verde usa `flex: 3`. `1+2+3 = 6`, o que significa que a visualização vermelha obterá `1/6` do espaço, a laranja `2/6` do espaço e a verde `3/6` do espaço. + +```jsx +import React from 'react'; +import {StyleSheet, View} from 'react-native'; + +const Flex = () => { + return ( + + + + + + ); +}; + +const styles = StyleSheet.create({ + container: { + flex: 1, + padding: 20, + }, +}); + +export default Flex; +``` + +![image](/docs/assets/292773486-70cbd054-9b64-4739-b47f-393071ba0a10.png) + +## Direção flexível + +[`flexDirection`](/docs/layout-props.md) controla a direção na qual os filhos de um nó são dispostos. Isso também é conhecido como eixo principal. O eixo transversal é o eixo perpendicular ao eixo principal, ou o eixo no qual as linhas de quebra são dispostas. + +* `column` (valor padrão) Alinhe os filhos de cima para baixo. Se o empacotamento estiver ativado, a próxima linha começará à direita do primeiro item na parte superior do contêiner. +* `row` Alinhe os filhos da esquerda para a direita. Se o empacotamento estiver ativado, a próxima linha começará no primeiro item à esquerda do contêiner. +* `column-reverse` Alinhe os filhos de baixo para cima. Se o empacotamento estiver ativado, a próxima linha começará à direita do primeiro item na parte inferior do contêiner. +* `row-reverse` Alinha os filhos da direita para a esquerda. Se o empacotamento estiver ativado, a próxima linha começará no primeiro item à direita do contêiner. + +Você pode aprender [mais aqui](https://yogalayout.com/docs/flex-direction). + +```jsx +import React, {useState} from 'react'; +import {StyleSheet, Text, TouchableOpacity, View} from 'react-native'; +import type {PropsWithChildren} from 'react'; + +const FlexDirectionBasics = () => { + const [flexDirection, setflexDirection] = useState('column'); + + return ( + + + + + + ); +}; + +type PreviewLayoutProps = PropsWithChildren<{ + label: string; + values: string[]; + selectedValue: string; + setSelectedValue: (value: string) => void; +}>; + +const PreviewLayout = ({ + label, + children, + values, + selectedValue, + setSelectedValue, +}: PreviewLayoutProps) => ( + + {label} + + {values.map(value => ( + setSelectedValue(value)} + style={[styles.button, selectedValue === value && styles.selected]}> + + {value} + + + ))} + + {children} + +); + +const styles = StyleSheet.create({ + container: { + flex: 1, + marginTop: 8, + backgroundColor: 'aliceblue', + }, + box: { + width: 50, + height: 50, + }, + row: { + flexDirection: 'row', + flexWrap: 'wrap', + }, + button: { + paddingHorizontal: 8, + paddingVertical: 6, + borderRadius: 4, + backgroundColor: 'oldlace', + alignSelf: 'flex-start', + marginHorizontal: '1%', + marginBottom: 6, + minWidth: '48%', + textAlign: 'center', + }, + selected: { + backgroundColor: 'coral', + borderWidth: 0, + }, + buttonLabel: { + fontSize: 12, + fontWeight: '500', + color: 'coral', + }, + selectedLabel: { + color: 'white', + }, + label: { + textAlign: 'center', + marginBottom: 10, + fontSize: 24, + }, +}); + +export default FlexDirectionBasics; +``` + +![image](https://github.com/tavaresgerson/reactnativedocbr/assets/22455192/4e84051a-1fec-4af3-9247-f77801e5cf2f) + +## Direção do layout + +A [direção](/docs/layout-props#direcao) do layout especifica a direção na qual os filhos e o texto em uma hierarquia devem ser dispostos. A direção do layout também afeta a que ponto o início e o fim da borda se referem. Por padrão, o React Native apresenta a direção do layout LTR. Neste modo, o início refere-se à esquerda e o fim refere-se à direita. + +* `LTR` (valor padrão) O texto e os filhos são dispostos da esquerda para a direita. A margem e o preenchimento aplicados ao início de um elemento são aplicados no lado esquerdo. +* O texto `RTL` e os filhos são dispostos da direita para a esquerda. A margem e o preenchimento aplicados ao início de um elemento são aplicados no lado direito. + +```tsx +import React, {useState} from 'react'; +import {View, TouchableOpacity, Text, StyleSheet} from 'react-native'; +import type {PropsWithChildren} from 'react'; + +const DirectionLayout = () => { + const [direction, setDirection] = useState('ltr'); + + return ( + + + + + + ); +}; + +type PreviewLayoutProps = PropsWithChildren<{ + label: string; + values: string[]; + selectedValue: string; + setSelectedValue: (value: string) => void; +}>; + +const PreviewLayout = ({ + label, + children, + values, + selectedValue, + setSelectedValue, +}: PreviewLayoutProps) => ( + + {label} + + {values.map(value => ( + setSelectedValue(value)} + style={[styles.button, selectedValue === value && styles.selected]}> + + {value} + + + ))} + + {children} + +); + +const styles = StyleSheet.create({ + container: { + flex: 1, + marginTop: 8, + backgroundColor: 'aliceblue', + }, + box: { + width: 50, + height: 50, + }, + row: { + flexDirection: 'row', + flexWrap: 'wrap', + }, + button: { + paddingHorizontal: 8, + paddingVertical: 6, + borderRadius: 4, + backgroundColor: 'oldlace', + alignSelf: 'flex-start', + marginHorizontal: '1%', + marginBottom: 6, + minWidth: '48%', + textAlign: 'center', + }, + selected: { + backgroundColor: 'coral', + borderWidth: 0, + }, + buttonLabel: { + fontSize: 12, + fontWeight: '500', + color: 'coral', + }, + selectedLabel: { + color: 'white', + }, + label: { + textAlign: 'center', + marginBottom: 10, + fontSize: 24, + }, +}); + +export default DirectionLayout; +``` + +![image](/docs/assets/292773723-4e84051a-1fec-4af3-9247-f77801e5cf2f.png) + +## Justificar o conteúdo + +[`justifyContent`](/docs/layout-props.md) descreve como alinhar filhos dentro do eixo principal de seu contêiner. Por exemplo, você pode usar essa propriedade para centralizar um filho horizontalmente em um contêiner com `flexDirection` definido como linha ou verticalmente em um contêiner com `flexDirection` definido como coluna. + +* `flex-start`(valor padrão) Alinha os filhos de um contêiner ao início do eixo principal do contêiner. +* `flex-end` Alinha os filhos de um contêiner ao final do eixo principal do contêiner. +* `center` Alinha os filhos de um contêiner no centro do eixo principal do contêiner. +* `space-between` Espaçar uniformemente os filhos no eixo principal do contêiner, distribuindo o espaço restante entre os filhos. +* `space-around` Afaste uniformemente os filhos no eixo principal do contêiner, distribuindo o espaço restante ao redor dos filhos. Comparado ao espaço entre, usar o espaço ao redor resultará na distribuição do espaço para o início do primeiro filho e o final do último filho. + +space-evenly Distribua uniformemente os filhos dentro do contêiner de alinhamento ao longo do eixo principal. O espaçamento entre cada par de itens adjacentes, a borda inicial principal e o primeiro item, e a borda final principal e o último item, são todos exatamente iguais. + +Você pode aprender [mais aqui](https://yogalayout.com/docs/justify-content). + +```tsx +import React, {useState} from 'react'; +import {View, TouchableOpacity, Text, StyleSheet} from 'react-native'; +import type {PropsWithChildren} from 'react'; + +const JustifyContentBasics = () => { + const [justifyContent, setJustifyContent] = useState('flex-start'); + + return ( + + + + + + ); +}; + +type PreviewLayoutProps = PropsWithChildren<{ + label: string; + values: string[]; + selectedValue: string; + setSelectedValue: (value: string) => void; +}>; + +const PreviewLayout = ({ + label, + children, + values, + selectedValue, + setSelectedValue, +}: PreviewLayoutProps) => ( + + {label} + + {values.map(value => ( + setSelectedValue(value)} + style={[styles.button, selectedValue === value && styles.selected]}> + + {value} + + + ))} + + {children} + +); + +const styles = StyleSheet.create({ + container: { + flex: 1, + marginTop: 8, + backgroundColor: 'aliceblue', + }, + box: { + width: 50, + height: 50, + }, + row: { + flexDirection: 'row', + flexWrap: 'wrap', + }, + button: { + paddingHorizontal: 8, + paddingVertical: 6, + borderRadius: 4, + backgroundColor: 'oldlace', + alignSelf: 'flex-start', + marginHorizontal: '1%', + marginBottom: 6, + minWidth: '48%', + textAlign: 'center', + }, + selected: { + backgroundColor: 'coral', + borderWidth: 0, + }, + buttonLabel: { + fontSize: 12, + fontWeight: '500', + color: 'coral', + }, + selectedLabel: { + color: 'white', + }, + label: { + textAlign: 'center', + marginBottom: 10, + fontSize: 24, + }, +}); + +export default JustifyContentBasics; +``` + +![image](/docs/assets/292774360-4866ca27-dcd8-44d5-bc7f-d5cc864c7569.png) + +## Alinhar itens + +[`alignItems`](https://reactnative.dev/docs/0.72/layout-props#alignitems) descreve como alinhar filhos ao longo do eixo cruzado de seu contêiner. É muito semelhante a `justifyContent`, mas em vez de aplicar ao eixo principal, `alignItems` aplica-se ao eixo cruzado. + +* `stretch` (valor padrão) Alonga os filhos de um contêiner para corresponder à altura do eixo transversal do contêiner. +* `flex-start` Alinha os filhos de um contêiner ao início do eixo cruzado do contêiner. +* `flex-end` Alinha os filhos de um contêiner ao final do eixo transversal do contêiner. +* `center` Alinhe os filhos de um contêiner no centro do eixo transversal do contêiner. +* `baseline` Alinha os filhos de um contêiner ao longo de uma linha de base comum. Cada criança pode ser definida como referência para seus pais. + +::: info **INFORMAÇÕES** +Para que o `stretch` tenha efeito, as crianças não devem ter uma dimensão fixa ao longo do eixo secundário. No exemplo a seguir, a configuração de `alignItems: stretch` não faz nada até que `width: 50` seja removido dos filhos. +::: + +Você pode aprender [mais aqui](https://yogalayout.com/docs/align-items). + +```tsx +import React, {useState} from 'react'; +import {View, TouchableOpacity, Text, StyleSheet} from 'react-native'; +import type {PropsWithChildren} from 'react'; + +const AlignItemsLayout = () => { + const [alignItems, setAlignItems] = useState('stretch'); + + return ( + + + + + + ); +}; + +type PreviewLayoutProps = PropsWithChildren<{ + label: string; + values: string[]; + selectedValue: string; + setSelectedValue: (value: string) => void; +}>; + +const PreviewLayout = ({ + label, + children, + values, + selectedValue, + setSelectedValue, +}: PreviewLayoutProps) => ( + + {label} + + {values.map(value => ( + setSelectedValue(value)} + style={[styles.button, selectedValue === value && styles.selected]}> + + {value} + + + ))} + + {children} + +); + +const styles = StyleSheet.create({ + container: { + flex: 1, + marginTop: 8, + backgroundColor: 'aliceblue', + minHeight: 200, + }, + box: { + width: 50, + height: 50, + }, + row: { + flexDirection: 'row', + flexWrap: 'wrap', + }, + button: { + paddingHorizontal: 8, + paddingVertical: 6, + borderRadius: 4, + backgroundColor: 'oldlace', + alignSelf: 'flex-start', + marginHorizontal: '1%', + marginBottom: 6, + minWidth: '48%', + textAlign: 'center', + }, + selected: { + backgroundColor: 'coral', + borderWidth: 0, + }, + buttonLabel: { + fontSize: 12, + fontWeight: '500', + color: 'coral', + }, + selectedLabel: { + color: 'white', + }, + label: { + textAlign: 'center', + marginBottom: 10, + fontSize: 24, + }, +}); + +export default AlignItemsLayout; +``` + +![image](/docs/assets/292776696-6843784a-f791-4bd5-ab46-4ff7474071a4.png) + +## Alinhar-se + +[`alignSelf`](/docs/layout-props#alignself) tem as mesmas opções e efeitos que `alignItems`, mas em vez de afetar os filhos dentro de um contêiner, você pode aplicar essa propriedade a um único filho para alterar seu alinhamento dentro de seu pai. `alignSelf` substitui qualquer opção definida pelo pai com `alignItems`. + +```tsx +import React, {useState} from 'react'; +import {View, TouchableOpacity, Text, StyleSheet} from 'react-native'; +import type {PropsWithChildren} from 'react'; +import type {FlexAlignType} from 'react-native'; + +const AlignSelfLayout = () => { + const [alignSelf, setAlignSelf] = useState('stretch'); + + return ( + + + + + + ); +}; + +type PreviewLayoutProps = PropsWithChildren<{ + label: string; + values: FlexAlignType[]; + selectedValue: string; + setSelectedValue: (value: FlexAlignType) => void; +}>; + +const PreviewLayout = ({ + label, + children, + values, + selectedValue, + setSelectedValue, +}: PreviewLayoutProps) => ( + + {label} + + {values.map(value => ( + setSelectedValue(value)} + style={[styles.button, selectedValue === value && styles.selected]}> + + {value} + + + ))} + + {children} + +); + +const styles = StyleSheet.create({ + container: { + flex: 1, + marginTop: 8, + backgroundColor: 'aliceblue', + minHeight: 200, + }, + box: { + width: 50, + height: 50, + }, + row: { + flexDirection: 'row', + flexWrap: 'wrap', + }, + button: { + paddingHorizontal: 8, + paddingVertical: 6, + borderRadius: 4, + backgroundColor: 'oldlace', + alignSelf: 'flex-start', + marginHorizontal: '1%', + marginBottom: 6, + minWidth: '48%', + textAlign: 'center', + }, + selected: { + backgroundColor: 'coral', + borderWidth: 0, + }, + buttonLabel: { + fontSize: 12, + fontWeight: '500', + color: 'coral', + }, + selectedLabel: { + color: 'white', + }, + label: { + textAlign: 'center', + marginBottom: 10, + fontSize: 24, + }, +}); + +export default AlignSelfLayout; +``` + +![image](/docs/assets/292776780-7a00c116-9d7b-447f-a495-06d36b22412a.png) + +## Alinhar conteúdo + +[`alignContent`](/docs/layout-props#aligncontent) define a distribuição de linhas ao longo do eixo cruzado. Isso só tem efeito quando os itens são agrupados em várias linhas usando `flexWrap`. + +* `flex-start` (valor padrão) Alinha as linhas quebradas ao início do eixo cruzado do contêiner. +* `flex-end` Alinhe as linhas quebradas ao final do eixo cruzado do contêiner. +* `stretch` (valor padrão ao usar o Yoga na Web) Estica as linhas quebradas para corresponder à altura do eixo transversal do contêiner. +* `center` Alinhe as linhas quebradas no centro do eixo transversal do contêiner. +* `space-between` Espaçar uniformemente as linhas agrupadas ao longo do eixo cruzado do contêiner, distribuindo o espaço restante entre as linhas. +* `space-around` Espaça uniformemente as linhas quebradas ao longo do eixo cruzado do contêiner, distribuindo o espaço restante ao redor das linhas. Comparado ao `space-between`, usar `space-around` resultará na distribuição do espaço no início da primeira linha e no final da última linha. + +Você pode aprender [mais aqui](https://yogalayout.com/docs/align-content). + +```tsx +import React, {useState} from 'react'; +import {View, TouchableOpacity, Text, StyleSheet} from 'react-native'; +import type {PropsWithChildren} from 'react'; + +const AlignContentLayout = () => { + const [alignContent, setAlignContent] = useState('flex-start'); + + return ( + + + + + + + + + + ); +}; + +type PreviewLayoutProps = PropsWithChildren<{ + label: string; + values: string[]; + selectedValue: string; + setSelectedValue: (value: string) => void; +}>; + +const PreviewLayout = ({ + label, + children, + values, + selectedValue, + setSelectedValue, +}: PreviewLayoutProps) => ( + + {label} + + {values.map(value => ( + setSelectedValue(value)} + style={[styles.button, selectedValue === value && styles.selected]}> + + {value} + + + ))} + + {children} + +); + +const styles = StyleSheet.create({ + container: { + flex: 1, + flexWrap: 'wrap', + marginTop: 8, + backgroundColor: 'aliceblue', + maxHeight: 400, + }, + box: { + width: 50, + height: 80, + }, + row: { + flexDirection: 'row', + flexWrap: 'wrap', + }, + button: { + paddingHorizontal: 8, + paddingVertical: 6, + borderRadius: 4, + backgroundColor: 'oldlace', + alignSelf: 'flex-start', + marginHorizontal: '1%', + marginBottom: 6, + minWidth: '48%', + textAlign: 'center', + }, + selected: { + backgroundColor: 'coral', + borderWidth: 0, + }, + buttonLabel: { + fontSize: 12, + fontWeight: '500', + color: 'coral', + }, + selectedLabel: { + color: 'white', + }, + label: { + textAlign: 'center', + marginBottom: 10, + fontSize: 24, + }, +}); + +export default AlignContentLayout; +``` + +![image](/docs/assets/292776889-1c43a42c-e7d9-4023-ba05-acdc68054c4d.png) + +## Flex Wrap + +A propriedade [`flexWrap`](/docs/layout-props.md#flexwrap) é definida em contêineres e controla o que acontece quando os filhos excedem o tamanho do contêiner ao longo do eixo principal. Por padrão, os filhos são forçados a formar uma única linha (o que pode reduzir os elementos). Se o agrupamento for permitido, os itens serão agrupados em diversas linhas ao longo do eixo principal, se necessário. + +Ao agrupar linhas, `alignContent` pode ser usado para especificar como as linhas são colocadas no contêiner. Saiba [mais aqui](https://yogalayout.com/docs/flex-wrap). + +```tsx +import React, {useState} from 'react'; +import {View, TouchableOpacity, Text, StyleSheet} from 'react-native'; +import type {PropsWithChildren} from 'react'; + +const FlexWrapLayout = () => { + const [flexWrap, setFlexWrap] = useState('wrap'); + + return ( + + + + + + + + + + ); +}; + +type PreviewLayoutProps = PropsWithChildren<{ + label: string; + values: string[]; + selectedValue: string; + setSelectedValue: (value: string) => void; +}>; + +const PreviewLayout = ({ + label, + children, + values, + selectedValue, + setSelectedValue, +}: PreviewLayoutProps) => ( + + {label} + + {values.map(value => ( + setSelectedValue(value)} + style={[styles.button, selectedValue === value && styles.selected]}> + + {value} + + + ))} + + {children} + +); + +const styles = StyleSheet.create({ + container: { + flex: 1, + marginTop: 8, + backgroundColor: 'aliceblue', + maxHeight: 400, + }, + box: { + width: 50, + height: 80, + }, + row: { + flexDirection: 'row', + flexWrap: 'wrap', + }, + button: { + paddingHorizontal: 8, + paddingVertical: 6, + borderRadius: 4, + backgroundColor: 'oldlace', + marginHorizontal: '1%', + marginBottom: 6, + minWidth: '48%', + textAlign: 'center', + }, + selected: { + backgroundColor: 'coral', + borderWidth: 0, + }, + buttonLabel: { + fontSize: 12, + fontWeight: '500', + color: 'coral', + }, + selectedLabel: { + color: 'white', + }, + label: { + textAlign: 'center', + marginBottom: 10, + fontSize: 24, + }, +}); + +export default FlexWrapLayout; +``` + +![image](/docs/assets/292777024-b01e455d-d2d3-435e-9208-6b8fc11c3afb.png) + +## Base Flexível, Crescer e Encolher + +* [`flexBasis`](/docs/layout-props.md#flexbasis) é uma forma independente de eixo de fornecer o tamanho padrão de um item ao longo do eixo principal. Definir o `flexBasis` de um filho é semelhante a definir o `width` desse filho se seu pai for um contêiner com `flexDirection: row` ou definir o `height` de um filho se seu pai for um contêiner com `flexDirection: column`. O `flexBasis` de um item é o tamanho padrão desse item, o tamanho do item antes de qualquer cálculo de `flexGrow` e `flexShrink` ser executado. +* [`flexGrow`](/docs/layout-props.md#flexgrow) descreve quanto espaço dentro de um contêiner deve ser distribuído entre seus filhos ao longo do eixo principal. Depois de dispor seus filhos, um contêiner distribuirá qualquer espaço restante de acordo com os valores flex grow especificados por seus filhos. + +`flexGrow` aceita qualquer valor de ponto flutuante >= 0, sendo 0 o valor padrão. Um contêiner distribuirá qualquer espaço restante entre seus filhos, ponderado pelos valores `flexGrow` dos filhos. + +* [`flexShrink`](/docs/layout-props.md#flexshrink) descreve como reduzir os filhos ao longo do eixo principal no caso em que o tamanho total dos filhos excede o tamanho do contêiner no eixo principal. `flexShrink` é muito semelhante ao `flexGrow` e pode ser pensado da mesma maneira se qualquer tamanho excedente for considerado espaço restante negativo. Essas duas propriedades também funcionam bem juntas, permitindo que as crianças cresçam e diminuam conforme necessário. + +`flexShrink` aceita qualquer valor de ponto flutuante >= 0, sendo 0 o valor padrão (na web, o padrão é 1). Um contêiner reduzirá seus filhos ponderados pelos valores `flexShrink` dos filhos. + +Você pode aprender [mais aqui](https://yogalayout.com/docs/flex). + +```tsx +import React, {useState} from 'react'; +import {View, Text, TextInput, StyleSheet} from 'react-native'; +import type {ViewStyle} from 'react-native'; + +const App = () => { + const [powderblue, setPowderblue] = useState({ + flexGrow: 0, + flexShrink: 1, + flexBasis: 'auto', + }); + const [skyblue, setSkyblue] = useState({ + flexGrow: 1, + flexShrink: 0, + flexBasis: 100, + }); + const [steelblue, setSteelblue] = useState({ + flexGrow: 0, + flexShrink: 1, + flexBasis: 200, + }); + return ( + + + + + + + + + + + + + ); +}; + +type BoxInfoProps = ViewStyle & { + color: string; + setStyle: React.Dispatch>; +}; + +const BoxInfo = ({ + color, + flexBasis, + flexShrink, + setStyle, + flexGrow, +}: BoxInfoProps) => ( + + + + Box + + + flexBasis + + setStyle(value => ({ + ...value, + flexBasis: isNaN(parseInt(fB, 10)) ? 'auto' : parseInt(fB, 10), + })) + } + /> + flexShrink + + setStyle(value => ({ + ...value, + flexShrink: isNaN(parseInt(fS, 10)) ? undefined : parseInt(fS, 10), + })) + } + /> + flexGrow + + setStyle(value => ({ + ...value, + flexGrow: isNaN(parseInt(fG, 10)) ? undefined : parseInt(fG, 10), + })) + } + /> + +); + +const styles = StyleSheet.create({ + container: { + flex: 1, + paddingHorizontal: 10, + }, + box: { + flex: 1, + height: 50, + width: 50, + }, + boxLabel: { + minWidth: 80, + padding: 8, + borderRadius: 4, + marginTop: 8, + }, + label: { + marginTop: 6, + fontSize: 16, + fontWeight: '100', + }, + previewContainer: { + flex: 1, + flexDirection: 'row', + backgroundColor: 'aliceblue', + }, + row: { + flex: 1, + flexDirection: 'row', + flexWrap: 'wrap', + alignItems: 'center', + marginBottom: 10, + }, + input: { + borderBottomWidth: 1, + paddingVertical: 3, + width: 50, + textAlign: 'center', + }, +}); + +export default App; +``` + +![image](/docs/assets/292777301-a9a5c486-b7e3-4f15-964d-678cc622e8d7.png) + +# Lacuna de linha, lacuna de coluna e lacuna + +* [`rowGap`](/docs/layout-props.md#rowgap) define o tamanho da lacuna (gutter) entre as linhas de um elemento. +* [`columnGap`](/docs/layout-props.md#columngap) define o tamanho da lacuna (gutter) entre as colunas de um elemento. +* [`gap`](/docs/layout-props.md#gap) define o tamanho do intervalo (gutter) entre linhas e colunas. É uma abreviação de `rowGap` e `columnGap`. + +Você pode usar `flexWrap` e `alignContent` junto com `gap` para adicionar espaçamento consistente entre os itens. + +```tsx +import React, {useState} from 'react'; +import {View, Text, StyleSheet, TextInput} from 'react-native'; +import type {PropsWithChildren} from 'react'; + +const RowGapAndColumnGap = () => { + const [rowGap, setRowGap] = useState(10); + const [columnGap, setColumnGap] = useState(10); + + return ( + + + + + + + + ); +}; + +type PreviewLayoutProps = PropsWithChildren<{ + columnGap: number; + handleColumnGapChange: (gap: number) => void; + rowGap: number; + handleRowGapChange: (gap: number) => void; +}>; + +const PreviewLayout = ({ + children, + handleColumnGapChange, + handleRowGapChange, + rowGap, + columnGap, +}: PreviewLayoutProps) => ( + + + + Row Gap + handleRowGapChange(Number(v))} + /> + + + Column Gap + handleColumnGapChange(Number(v))} + /> + + + {children} + +); + +const styles = StyleSheet.create({ + itemsCenter: {alignItems: 'center'}, + inputContainer: { + gap: 4, + flexDirection: 'row', + justifyContent: 'space-around', + }, + previewContainer: {padding: 10, flex: 1}, + input: { + borderBottomWidth: 1, + paddingVertical: 3, + width: 50, + textAlign: 'center', + }, + container: { + flex: 1, + marginTop: 8, + backgroundColor: 'aliceblue', + maxHeight: 400, + flexWrap: 'wrap', + alignContent: 'flex-start', + }, + box: { + width: 50, + height: 80, + }, + box1: { + backgroundColor: 'orangered', + }, + box2: { + backgroundColor: 'orange', + }, + box3: { + backgroundColor: 'mediumseagreen', + }, + box4: { + backgroundColor: 'deepskyblue', + }, + box5: { + backgroundColor: 'mediumturquoise', + }, +}); + +export default RowGapAndColumnGap; +``` + +![image](/docs/assets/292777538-c0bbee71-c62d-4873-8d20-e04598d39a8a.png) + +## Largura e altura + +A propriedade `width` especifica a largura da área de conteúdo de um elemento. Da mesma forma, a propriedade `height` especifica a altura da área de conteúdo de um elemento. + +Tanto a largura quanto a altura podem assumir os seguintes valores: + +* `auto` (valor padrão) React Native calcula a largura/altura do elemento com base em seu conteúdo, seja ele outros filhos, texto ou uma imagem. +* `pixels` Define a largura/altura em pixels absolutos. Dependendo de outros estilos definidos no componente, esta pode ou não ser a dimensão final do nó. +* `percentage` Define a largura ou altura em porcentagem da largura ou altura do pai, respectivamente. + +```tsx +import React, {useState} from 'react'; +import { + View, + SafeAreaView, + TouchableOpacity, + Text, + StyleSheet, +} from 'react-native'; +import type {PropsWithChildren} from 'react'; + +type Dimension = 'auto' | `${number}%` | number; + +const WidthHeightBasics = () => { + const [widthType, setWidthType] = useState('auto'); + const [heightType, setHeightType] = useState('auto'); + + return ( + + + + + + + + ); +}; + +type PreviewLayoutProps = PropsWithChildren<{ + widthType: Dimension; + heightType: Dimension; + widthValues: Dimension[]; + heightValues: Dimension[]; + setWidthType: (value: Dimension) => void; + setHeightType: (value: Dimension) => void; +}>; + +const PreviewLayout = ({ + children, + widthType, + heightType, + widthValues, + heightValues, + setWidthType, + setHeightType, +}: PreviewLayoutProps) => ( + + + width + {widthValues.map(value => ( + setWidthType(value)} + style={[styles.button, widthType === value && styles.selected]}> + + {value} + + + ))} + + + height + {heightValues.map(value => ( + setHeightType(value)} + style={[styles.button, heightType === value && styles.selected]}> + + {value} + + + ))} + + {children} + +); + +const styles = StyleSheet.create({ + box: { + width: 50, + height: 50, + }, + row: { + flexDirection: 'row', + flexWrap: 'wrap', + }, + button: { + padding: 8, + borderRadius: 4, + backgroundColor: 'oldlace', + alignSelf: 'flex-start', + marginRight: 10, + marginBottom: 10, + }, + selected: { + backgroundColor: 'coral', + shadowOpacity: 0, + borderWidth: 0, + }, + buttonLabel: { + fontSize: 12, + fontWeight: '500', + color: 'coral', + }, + selectedLabel: { + color: 'white', + }, + label: { + textAlign: 'center', + marginBottom: 10, + fontSize: 24, + }, +}); + +export default WidthHeightBasics; +``` + +![image](/docs/assets/292777602-6f4ee12a-ddac-4dfb-9516-c093cc9282f0.png) + +## Layout Absoluto e Relativo + +O tipo de `position` de um elemento define como ele é posicionado em seu pai. + +* `relative` (valor padrão) Por padrão, um elemento é posicionado relativamente. Isso significa que um elemento é posicionado de acordo com o fluxo normal do layout e, em seguida, deslocado em relação a essa posição com base nos valores `top`, `right`, `bottom` e `left`. O deslocamento não afeta a posição de nenhum elemento irmão ou pai. +* `absolute` Quando posicionado de forma absoluta, um elemento não participa do fluxo normal do layout. Em vez disso, é apresentado independente de seus irmãos. A posição é determinada com base nos valores superior, direito, inferior e esquerdo. + +```tsx +import React, {useState} from 'react'; +import {View, TouchableOpacity, Text, StyleSheet} from 'react-native'; +import type {PropsWithChildren} from 'react'; + +const PositionLayout = () => { + const [position, setPosition] = useState<'relative' | 'absolute'>('relative'); + + return ( + + + + + + ); +}; + +type PreviewLayoutProps = PropsWithChildren<{ + label: string; + values: Array<'relative' | 'absolute'>; + selectedValue: string; + setSelectedValue: (value: 'relative' | 'absolute') => void; +}>; + +const PreviewLayout = ({ + label, + children, + values, + selectedValue, + setSelectedValue, +}: PreviewLayoutProps) => ( + + {label} + + {values.map(value => ( + setSelectedValue(value)} + style={[styles.button, selectedValue === value && styles.selected]}> + + {value} + + + ))} + + {children} + +); + +const styles = StyleSheet.create({ + container: { + flex: 1, + marginTop: 8, + backgroundColor: 'aliceblue', + minHeight: 200, + }, + box: { + width: 50, + height: 50, + }, + row: { + flexDirection: 'row', + flexWrap: 'wrap', + }, + button: { + paddingHorizontal: 8, + paddingVertical: 6, + borderRadius: 4, + backgroundColor: 'oldlace', + alignSelf: 'flex-start', + marginHorizontal: '1%', + marginBottom: 6, + minWidth: '48%', + textAlign: 'center', + }, + selected: { + backgroundColor: 'coral', + borderWidth: 0, + }, + buttonLabel: { + fontSize: 12, + fontWeight: '500', + color: 'coral', + }, + selectedLabel: { + color: 'white', + }, + label: { + textAlign: 'center', + marginBottom: 10, + fontSize: 24, + }, +}); + +export default PositionLayout; +``` + +![image](/docs/assets/292777671-998be8d3-8e5f-4541-a938-0b3c016991ea.png) + +## Indo mais fundo + +Confira o playground [interativo de ioga](https://yogalayout.com/playground) que você pode usar para entender melhor o flexbox. + +Abordamos o básico, mas existem muitos outros estilos que você pode precisar para layouts. A lista completa de adereços que controlam o layout está documentada [aqui](/docs/layout-props.md). + +Além disso, você pode ver alguns exemplos dos [Engenheiros da Wix](https://medium.com/wix-engineering/the-full-react-native-layout-cheat-sheet-a4147802405c). diff --git a/vitepress/docs/docs/gesture-responder-system.md b/vitepress/docs/docs/gesture-responder-system.md new file mode 100644 index 0000000..4640f61 --- /dev/null +++ b/vitepress/docs/docs/gesture-responder-system.md @@ -0,0 +1,57 @@ +# Sistema de resposta por gestos +O sistema de resposta por gestos gerencia o ciclo de vida dos gestos no seu aplicativo. Um toque pode passar por diversas fases enquanto o app determina qual é a intenção do usuário. Por exemplo, o aplicativo precisa determinar se o toque está rolando, deslizando em um widget ou tocando. Isso pode até mudar durante um toque. Também pode haver vários toques simultâneos. + +O sistema de resposta ao toque é necessário para permitir que os componentes negociem essas interações por toque sem qualquer conhecimento adicional sobre seus componentes pai ou filho. + +## Melhores Práticas +Para que seu aplicativo seja ótimo, cada ação deve ter os seguintes atributos: + +* Feedback/destaque – mostre ao usuário o que está acontecendo com seu toque e o que acontecerá quando ele liberar o gesto +* Capacidade de cancelamento - ao realizar uma ação, o usuário deve ser capaz de abortá-la no meio do toque, arrastando o dedo para longe + +Esses recursos deixam os usuários mais confortáveis ao usar um aplicativo, pois permitem que as pessoas experimentem e interajam sem medo de cometer erros. + +## TouchableHighlight and Touchable* +O sistema de resposta pode ser complicado de usar. Portanto, fornecemos uma implementação abstrata `Touchable` para coisas que deveriam ser "tocáveis". Isso usa o sistema de resposta e permite configurar interações de toque de forma declarativa. Use `TouchableHighlight` em qualquer lugar onde você usaria um botão ou link na web. + +## Ciclo de vida do Respondente +Uma visualização pode se tornar a resposta ao toque, implementando os métodos de negociação corretos. Existem dois métodos para perguntar à visualização se ela deseja se tornar respondente: + +* `View.props.onStartShouldSetResponder: evt => true,` - Esta visualização deseja se tornar respondente no início de um toque? +* `View.props.onMoveShouldSetResponder: evt => true,` - Chamado para cada movimento de toque na Visualização quando não é o respondedor: esta visualização deseja "reivindicar" capacidade de resposta ao toque? + +Se a View retornar `true` e tentar se tornar o respondente, uma das seguintes situações acontecerá: + +* `View.props.onResponderGrant: evt => {}` - A visualização agora está respondendo a eventos de toque. Este é o momento de destacar e mostrar ao usuário o que está acontecendo +* `View.props.onResponderReject: evt => {}` - Outra coisa está respondendo agora e não irá liberá-la + +Se a visualização estiver respondendo, os seguintes manipuladores poderão ser chamados: + +* `View.props.onResponderMove: evt => {}` - O usuário está movendo o dedo +* `View.props.onResponderRelease: evt => {}` - Disparado no final do toque, ou seja, "touchUp" +* `View.props.onResponderTerminationRequest: evt => true` - Outra coisa deseja se tornar respondedor. Essa visão deve liberar o respondedor? Retornar verdadeiro permite a liberação +* `View.props.onResponderTerminate: evt => {}` - O respondente foi retirado da Visualização. Pode ser obtido por outras visualizações após uma chamada para `onResponderTerminationRequest` ou pode ser obtido pelo sistema operacional sem perguntar (acontece com o centro de controle/centro de notificação no iOS) + +`evt` é um evento de toque sintético com o seguinte formato: + +* `nativeEvent` + * `changeTouches` - Matriz de todos os eventos de toque que foram alterados desde o último evento + * `identifier` - O ID do toque + * `locationX` - A posição X do toque, em relação ao elemento + * `locationY` - A posição Y do toque, em relação ao elemento + * `pageX` - A posição X do toque, em relação ao elemento raiz + * `pageY` - A posição Y do toque, em relação ao elemento raiz + * `target` - O ID do nó do elemento que recebe o evento de toque + * `timestamp` - Um identificador de tempo para o toque, útil para cálculo de velocidade + * `touches` - Matriz de todos os toques atuais na tela + +### Capturar manipuladores ShouldSet +`onStartShouldSetResponder` e `onMoveShouldSetResponder` são chamados com um padrão de bolha, onde o nó mais profundo é chamado primeiro. Isso significa que o componente mais profundo se tornará respondedor quando múltiplas Views retornarem `true` para manipuladores `*ShouldSetResponder`. Isso é desejável na maioria dos casos, porque garante que todos os controles e botões possam ser usados. + +No entanto, às vezes um pai vai querer ter certeza de que ele responderá. Isso pode ser resolvido usando a fase de captura. Antes que o sistema de resposta surja do componente mais profundo, ele fará uma fase de captura, disparando em `*ShouldSetResponderCapture`. Portanto, se uma visualização pai quiser evitar que o filho se torne respondedor em uma inicialização por toque, ela deverá ter um manipulador `onStartShouldSetResponderCapture` que retorne verdadeiro. + +* `View.props.onStartShouldSetResponderCapture: evt => true`, +* `View.props.onMoveShouldSetResponderCapture: evt => true`, + +## PanResponder +Para interpretação de gestos de nível superior, confira [PanResponder](/docs/panresponder.md). diff --git a/vitepress/docs/docs/getting-started.md b/vitepress/docs/docs/getting-started.md new file mode 100644 index 0000000..f0e1dbd --- /dev/null +++ b/vitepress/docs/docs/getting-started.md @@ -0,0 +1,47 @@ +# Introdução + +> Bem-vindo ao início de sua jornada React Native! Se você estiver procurando instruções de configuração do ambiente, elas [foram movidas para sua própria seção](/docs/environment-setup.md). Continue lendo para obter uma introdução à documentação, componentes nativos, React e muito mais! + +Muitos tipos diferentes de pessoas usam React Native: desde desenvolvedores iOS avançados até iniciantes em React, até pessoas que estão começando a programar pela primeira vez em suas carreiras. Esses documentos foram escritos para todos os alunos, independentemente do nível de experiência ou formação. + +## Como usar esses documentos +Você pode começar aqui e ler esses documentos linearmente como um livro; ou você pode ler as seções específicas de que precisa. Já conhece o React? Você pode pular para [essa seção](/docs/intro-react.md) - ou lê-la para uma atualização leve. + +## Pré-requisitos +Para trabalhar com React Native, você precisará entender os fundamentos do JavaScript. Se você é novo em JavaScript ou precisa de uma atualização, você pode [mergulhar](https://developer.mozilla.org/en-US/docs/Web/JavaScript) ou se [atualizar](https://developer.mozilla.org/en-US/docs/Web/JavaScript/A_re-introduction_to_JavaScript) na Mozilla Developer Network. + +## Exemplos interativos +Esta introdução permite que você comece imediatamente em seu navegador com exemplos interativos como este: + +```js +// Hello World +import React from 'react'; +import {Text, View} from 'react-native'; + +const YourApp = () => { + return ( + + Try editing me! 🎉 + + ); +}; + +export default YourApp; +``` + +::: tip Opcionalmente +Se desejar [configurar um ambiente de desenvolvimento local](/docs/environment-setup.md), você pode seguir nosso guia para configurar seu ambiente em sua máquina local e colar os exemplos de código em seu arquivo `App.js`. (Se você é um desenvolvedor web, talvez já tenha um ambiente local configurado para testes de navegadores móveis!) +::: + +## Notas do desenvolvedor +Pessoas de diversas origens de desenvolvimento estão aprendendo React Native. Você pode ter experiência com uma variedade de tecnologias, desde web até Android, iOS e muito mais. Tentamos escrever para desenvolvedores de todas as origens. + +## Formatação +Os caminhos dos menus são escritos em negrito e usam sinais de intercalação para navegar nos submenus. Exemplo: **Android Studio > Preference** + +Agora que você sabe como funciona este guia, é hora de conhecer a base do React Native: [Native Components](/docs/intro-react-native-components.md). diff --git a/vitepress/docs/docs/handling-text-input.md b/vitepress/docs/docs/handling-text-input.md new file mode 100644 index 0000000..ba606ac --- /dev/null +++ b/vitepress/docs/docs/handling-text-input.md @@ -0,0 +1,38 @@ +# Tratamento de entrada de texto + +`TextInput` é um componente principal que permite ao usuário inserir texto. Ele tem uma propriedade `onChangeText` que leva uma função a ser chamada toda vez que o texto é alterado, e uma propriedade `onSubmitEditing` que leva uma função a ser chamada quando o texto é enviado. + +Por exemplo, digamos que enquanto o usuário digita, você traduz as palavras dele para um idioma diferente. Neste novo idioma, cada palavra é escrita da mesma maneira: 🍕. Portanto, a frase "Olá, Bob" seria traduzida como "🍕 🍕 🍕". + +```jsx +import React, {useState} from 'react'; +import {Text, TextInput, View} from 'react-native'; + +const PizzaTranslator = () => { + const [text, setText] = useState(''); + return ( + + setText(newText)} + defaultValue={text} + /> + + {text + .split(' ') + .map(word => word && '🍕') + .join(' ')} + + + ); +}; + +export default PizzaTranslator; +``` + +Neste exemplo, armazenamos texto no estado, pois ele muda com o tempo. + +Há muito mais coisas que você pode querer fazer com uma entrada de texto. Por exemplo, você pode validar o texto interno enquanto o usuário digita. Para exemplos mais detalhados, consulte a documentação do React sobre [componentes controlados](https://reactjs.org/docs/forms.html#controlled-components) ou a documentação de referência para [TextInput](/docs/textinput.md). + +A entrada de texto é uma das maneiras pelas quais o usuário interage com o aplicativo. A seguir, vamos examinar outro tipo de entrada e aprender como lidar com toques. diff --git a/vitepress/docs/docs/handling-touches.md b/vitepress/docs/docs/handling-touches.md new file mode 100644 index 0000000..110f653 --- /dev/null +++ b/vitepress/docs/docs/handling-touches.md @@ -0,0 +1,185 @@ +# Lidando com toques + +Os usuários interagem com aplicativos móveis principalmente por meio do toque. Eles podem usar uma combinação de gestos, como tocar em um botão, rolar uma lista ou ampliar um mapa. O React Native fornece componentes para lidar com todos os [tipos de gestos comuns](/docs/gesture-responder-system.md), bem como um sistema abrangente de resposta a gestos para permitir um reconhecimento de gestos mais avançado, mas o componente no qual você provavelmente estará interessado é o botão básico. + +## Exibindo um botão básico + +`Button` fornece um componente básico de botão que é bem renderizado em todas as plataformas. O exemplo mínimo para exibir um botão é assim: + +```tsx +