react-unique-id-generator
Version:
A lightweight, zero-dependency library for generating unique, sequential IDs in React — with hooks, custom prefix/suffix, SSR support, and stable CSS selector generation
2 lines • 16.4 kB
JavaScript
;Object.defineProperty(exports,'__esModule',{value:true});var react=require('react'),jsxRuntime=require('react/jsx-runtime');var B="",K="",p=0,I=typeof process<"u"&&process.env?.NODE_ENV!=="production",j=new Set,E=1e6,A=false;function X(e){I&&e>=E&&!A&&(A=true,console.warn(`[react-unique-id-generator] ID counter has exceeded ${E}. This may indicate a memory leak or unintended usage pattern. Consider using resetId() or scoped ID management.`));}function Z(e,t){I&&!j.has(e)&&(j.add(e),console.warn(`[react-unique-id-generator] DEPRECATED: ${e}() uses global state. Use ${t} instead for SSR safety. Global API will be removed in a future major version.`));}function f(e){return I&&e!==void 0&&e!==null&&typeof e!="string"&&console.warn(`[react-unique-id-generator] nextId() expected a string prefix, but received ${typeof e}. The value will be coerced to a string.`),p++,X(p),`${e??B}${p}${K}`}var be=()=>{p=0,A=false;},Ce=e=>{Z("setGlobalPrefix",'<IdProvider prefix="...">'),I&&e!==void 0&&e!==null&&typeof e!="string"&&console.warn(`[react-unique-id-generator] setGlobalPrefix() expected a string, but received ${typeof e}.`),B=e||"";},$e=e=>{Z("setGlobalSuffix",'<IdProvider suffix="...">'),I&&e!==void 0&&e!==null&&typeof e!="string"&&console.warn(`[react-unique-id-generator] setGlobalSuffix() expected a string, but received ${typeof e}.`),K=e||"";},Re=()=>p,De=e=>{I&&(typeof e!="number"||Number.isNaN(e))&&console.warn(`[react-unique-id-generator] setId() expected a number, but received ${typeof e}.`),p=Math.max(0,Math.floor(e));},Ee=(e="",t="")=>(p++,X(p),`${e}${p}${t}`);var Pe=typeof process<"u"&&process.env?.NODE_ENV!=="production",J=1e6,w=react.createContext(null);function qe({prefix:e="",suffix:t="",startId:r=0,children:n}){let o=react.useRef(r),i=react.useRef(false),s=react.useRef({prefix:e,suffix:t});s.current={prefix:e,suffix:t};let u=react.useMemo(()=>({nextId:a=>(o.current++,Pe&&o.current>=J&&!i.current&&(i.current=true,console.warn(`[react-unique-id-generator] IdProvider counter has exceeded ${J}. This may indicate a memory leak or unintended usage pattern.`)),`${a??s.current.prefix}${o.current}${s.current.suffix}`),prefix:e,suffix:t}),[e,t]);return jsxRuntime.jsx(w.Provider,{value:u,children:n})}function d(){return react.useContext(w)}var Me=typeof process<"u"&&process.env?.NODE_ENV!=="production",Q={current:false};function ee(e){Me&&!Q.current&&(Q.current=true,console.warn(`[react-unique-id-generator] ${e}() called without an <IdProvider>. Falling back to global state (deprecated). Wrap your app in <IdProvider> for SSR safety.`));}function Ne(e){let t=d(),r=react.useRef(null);return r.current===null&&(t?r.current=t.nextId(e):(ee("useUniqueId"),r.current=f(e))),r.current}function Te(e,t){let r=d(),n=react.useRef(null);return n.current===null&&(r?n.current=Array.from({length:e},()=>r.nextId(t)):(ee("useUniqueIds"),n.current=Array.from({length:e},()=>f(t)))),n.current}var Ve=typeof process<"u"&&process.env?.NODE_ENV!=="production",te=1e6;function Le(e={}){let{prefix:t="",suffix:r="",startId:n=0}=e,o=n,i=false;return {nextId(s){return o++,Ve&&o>=te&&!i&&(i=true,console.warn(`[react-unique-id-generator] Server ID manager counter has exceeded ${te}. This may indicate a memory leak or unintended usage pattern.`)),`${s??t}${o}${r}`},resetId(){o=0,i=false;},getCurrentId(){return o},setId(s){o=Math.max(0,Math.floor(s));}}}var b=0;function ke(e){return e.replace(/([a-z])([A-Z])/g,"$1-$2").replace(/[\s_]+/g,"-").toLowerCase()}function Fe(e){return e.replace(/[-_\s]+(.)?/g,(t,r)=>r?r.toUpperCase():"").replace(/^[A-Z]/,t=>t.toLowerCase())}function re(e,t){switch(t){case "kebab-case":return ke(e);case "camelCase":return Fe(e);default:return e}}function ne(e,t={}){let{strategy:r="sequential",prefix:n="",separator:o="-",customFn:i}=t;if(b++,r==="custom"){if(!i)throw new Error('[react-unique-id-generator] customFn is required when using the "custom" automation strategy.');return i(e,b)}let s=re(e,r);return `${n}${s}${o}${b}`}function ze(){b=0;}function We(e,t){let r=react.useRef(null);return r.current===null&&(r.current=ne(e,t)),r.current}var P=class{constructor(t,r="auto",n={}){this.available=[];this.released=[];this.counter=0;this.componentName=r,this.strategy=n.strategy??"sequential",this.prefix=n.prefix??"",this.separator=n.separator??"-",this.fill(t);}createId(){this.counter++;let t=re(this.componentName,this.strategy);return `${this.prefix}${t}${this.separator}${this.counter}`}fill(t){for(let r=0;r<t;r++)this.available.push(this.createId());}acquire(){return this.released.length>0?this.released.pop():this.available.length>0?this.available.shift():this.createId()}release(t){this.released.push(t);}drain(){this.available=[],this.released=[];}get size(){return this.available.length+this.released.length}};var q="0123456789abcdef";function Ge(e){let t="";for(let r=0;r<e.length;r++)t+=q[e[r]>>4]+q[e[r]&15];return t}function He(e=32){if(typeof crypto<"u"&&typeof crypto.randomUUID=="function")return crypto.randomUUID();let t=Math.ceil(e/2);if(typeof crypto<"u"&&typeof crypto.getRandomValues=="function"){let n=new Uint8Array(t);return crypto.getRandomValues(n),Ge(n).slice(0,e)}let r="";for(let n=0;n<e;n++)r+=q[Math.floor(Math.random()*16)];return r}var x=new Map;function je(e,t=""){let r=(x.get(e)??0)+1;return x.set(e,r),`${t}${r}`}function Be(e){x.delete(e);}function Ke(){x.clear();}function Xe(e){return x.get(e)??0}function Ze(){return Array.from(x.keys())}var m=new Set,M=0,C=0,N={totalGenerated:0,activeCount:0,peakActiveCount:0},$=new Set;function ue(){N={totalGenerated:M,activeCount:m.size,peakActiveCount:C};}function T(){ue(),$.forEach(e=>e());}function _(e){m.add(e),M++,m.size>C&&(C=m.size),T();}function ae(e){m.delete(e),T();}function Qe(){return N}function Ye(){M=0,C=m.size,ue(),$.forEach(e=>e());}function et(){return m.size}function tt(e){let t=d(),r=react.useRef(null);return r.current===null&&(t?r.current=t.nextId(e):r.current=f(e),_(r.current)),react.useEffect(()=>()=>{r.current&&ae(r.current);},[]),r.current}function rt(e,t){let r=d(),n=react.useRef(null);return n.current===null&&(r?n.current=Array.from({length:e},()=>{let o=r.nextId(t);return _(o),o}):n.current=Array.from({length:e},()=>{let o=f(t);return _(o),o})),react.useEffect(()=>()=>{n.current&&n.current.forEach(ae);},[]),n.current}function nt(e){return $.add(e),()=>{$.delete(e);}}function oe(){return N}function ot(){return react.useSyncExternalStore(nt,oe,oe)}function it(){m.clear(),T();}var v=0,V=false,ut=typeof process<"u"&&process.env?.NODE_ENV!=="production",ce=1e6;function L(){return v++,ut&&v>=ce&&!V&&(V=true,console.warn(`[react-unique-id-generator] Strategy counter has exceeded ${ce}. This may indicate a memory leak or unintended usage pattern.`)),v}function at(){v=0,V=false;}function ct(){return v}var lt={generate(e,t,r){return `${e}${r}${t}`}},dt=(e=4)=>({generate(t,r,n){return `${t}${String(n).padStart(e,"0")}${r}`}}),ft={generate(e,t,r){return `${e}${Date.now()}-${r}${t}`}},gt={generate(e,t,r){let n=r;n=(n>>16^n)*73244475,n=(n>>16^n)*73244475,n=n>>16^n;let o=(n>>>0).toString(16).padStart(8,"0");return `${e}${o}${t}`}};function pt(e,t="",r=""){let n=L();return e.generate(t,r,n)}function mt(e,t="",r=""){let n=d(),o=react.useRef(null);if(o.current===null)if(n){let i=n.nextId(),s=parseInt(i.replace(/\D/g,""),10)||L();o.current=e.generate(t||n.prefix,r||n.suffix,s);}else {let i=L();o.current=e.generate(t,r,i);}return o.current}var le=typeof process<"u"&&process.env?.NODE_ENV!=="production",R=class{constructor(t={}){this.registry=new Set;this.collisionCount=0;this.action=t.action??"warn",this.maxSize=t.maxSize??1e5;}register(t){if(this.registry.has(t)){this.collisionCount++;let r=`[react-unique-id-generator] ID collision detected: "${t}" has already been registered.`;if(this.action==="throw")throw new Error(r);return this.action==="warn"&&le&&console.warn(r),false}return this.registry.size>=this.maxSize&&le&&console.warn(`[react-unique-id-generator] CollisionDetector registry has reached maxSize (${this.maxSize}). Oldest entries are not evicted. Consider calling clear() or increasing maxSize.`),this.registry.add(t),true}has(t){return this.registry.has(t)}unregister(t){return this.registry.delete(t)}clear(){this.registry.clear(),this.collisionCount=0;}get size(){return this.registry.size}get collisions(){return this.collisionCount}getRegisteredIds(){return Array.from(this.registry)}},h=null;function de(e){return h||(h=new R(e)),h}function It(){h&&h.clear(),h=null;}function xt(e,t="warn"){return de({action:t}).register(e)}var St=typeof process<"u"&&process.env?.NODE_ENV!=="production",U=class{constructor(t,r={}){this.available=[];this.released=[];this.generated=0;this.prefix=r.prefix??"",this.suffix=r.suffix??"",this.autoRefill=r.autoRefill??true,this.generator=r.generator,this.fill(t);}createId(){return this.generated++,this.generator?this.generator(this.generated):`${this.prefix}${this.generated}${this.suffix}`}fill(t){for(let r=0;r<t;r++)this.available.push(this.createId());}acquire(){return this.released.length>0?this.released.pop():this.available.length>0?this.available.shift():this.autoRefill?this.createId():(St&&console.warn("[react-unique-id-generator] IdPool exhausted and autoRefill is disabled. Returning a newly generated ID."),this.createId())}release(t){this.released.push(t);}drain(){this.available=[],this.released=[];}refill(t){this.fill(t);}get size(){return this.available.length+this.released.length}get totalGenerated(){return this.generated}};function vt(e,t){let r=d(),n=react.useRef(null),o=react.useRef(0);return n.current===null&&(r?n.current=Array.from({length:e},()=>r.nextId(t)):n.current=Array.from({length:e},()=>f(t))),react.useCallback(()=>{let s=n.current;if(o.current<s.length)return s[o.current++];if(r){let a=r.nextId(t);return s.push(a),o.current++,a}let u=f(t);return s.push(u),o.current++,u},[r,t])}var pe=typeof process<"u"&&process.env?.NODE_ENV!=="production",ge=1e6,k=react.createContext(null);function me(){return react.useContext(k)}function Rt({prefix:e="",suffix:t="",requestId:r,children:n}){let o=react.useRef(0),i=react.useRef(false),s=react.useRef({prefix:e,suffix:t,requestId:r});s.current={prefix:e,suffix:t,requestId:r};let u=react.useMemo(()=>({nextId(a){o.current++,pe&&o.current>=ge&&!i.current&&(i.current=true,console.warn(`[react-unique-id-generator] SSRProvider counter has exceeded ${ge}.`));let l=a??s.current.prefix,S=s.current.requestId?`${s.current.requestId}-`:"";return `${l}${S}${o.current}${s.current.suffix}`},resetId(){o.current=0,i.current=false;},getCurrentId(){return o.current}}),[]);return react.createElement(k.Provider,{value:u},n)}function Dt(e){let t=me(),r=react.useRef(null);return r.current===null&&(t?r.current=t.nextId(e):pe?(console.warn("[react-unique-id-generator] useSSRSafeId() called without <SSRProvider>. Wrap your server render in <SSRProvider> for request-scoped IDs."),r.current=`${e??""}${Date.now()}-${Math.floor(Math.random()*1e4)}`):r.current=`${e??""}${Date.now()}-${Math.floor(Math.random()*1e4)}`),r.current}function Et(e,t="",r=""){let n=0;return {nextId(o){return n++,`${o??t}${e}-${n}${r}`},resetId(){n=0;},getCurrentId(){return n}}}var y=0,F=false,Ot=typeof process<"u"&&process.env?.NODE_ENV!=="production",Ie=1e6;function z(){return y++,Ot&&y>=Ie&&!F&&(F=true,console.warn(`[react-unique-id-generator] Delimiter counter has exceeded ${Ie}. This may indicate a memory leak or unintended usage pattern.`)),y}function wt(){y=0,F=false;}function Pt(){return y}function qt(e={}){let{prefix:t="",suffix:r="",delimiter:n="-"}=e,o=z(),i=[];return t&&i.push(t),i.push(String(o)),r&&i.push(r),i.join(n)}function _t(e="",t="-",r=""){let n=d(),o=react.useRef(null);if(o.current===null)if(n){let i=n.nextId(),s=parseInt(i.replace(/\D/g,""),10)||z(),u=[];(e||n.prefix)&&u.push(e||n.prefix),u.push(String(s)),(r||n.suffix)&&u.push(r||n.suffix),o.current=u.join(t);}else {let i=z(),s=[];e&&s.push(e),s.push(String(i)),r&&s.push(r),o.current=s.join(t);}return o.current}var he=["data-testid","data-test-id","data-cy"],Se=/^[:.]|^\d/,Vt=5,ve=["name","type","href","for","aria-label","placeholder","alt","title"],Lt=new Set(["header","main","nav","footer","aside","article","section"]);function c(e){return e.replace(/([\\!"#$%&'()*+,.:;<=>?@[\]^`{|}~])/g,"\\$1")}function g(e,t){try{return t.querySelectorAll(e).length===1}catch{return false}}function Ut(e){return e.root??document}function kt(e,t,r){let n=e.id;if(!n||r.test(n))return null;let o=`#${c(n)}`;return g(o,t)?o:null}function Ft(e,t,r){for(let n of r){let o=e.getAttribute(n);if(!o)continue;let i=`[${n}="${c(o)}"]`;if(g(i,t))return i}return null}function zt(e,t){let r=e.getAttribute("role");if(!r)return null;let n=e.getAttribute("aria-label");if(n){let i=`[role="${c(r)}"][aria-label="${c(n)}"]`;if(g(i,t))return i}let o=`[role="${c(r)}"]`;return g(o,t)?o:null}function Wt(e,t){let r=e.tagName.toLowerCase();for(let n of ve){let o=e.getAttribute(n);if(!o)continue;let i=`${r}[${n}="${c(o)}"]`;if(g(i,t))return i}return null}function Gt(e,t,r){let n=Array.from(e.classList).filter(i=>!r||!r.test(i));if(n.length===0)return null;let o=e.tagName.toLowerCase();for(let i of n){let s=`${o}.${c(i)}`;if(g(s,t))return s}for(let i=0;i<n.length;i++)for(let s=i+1;s<n.length;s++){let u=`${o}.${c(n[i])}.${c(n[s])}`;if(g(u,t))return u}return null}function Ht(e,t){let r=e.tagName.toLowerCase();return Lt.has(r)&&g(r,t)?r:null}function xe(e,t,r){let n=r.ignoreIdPattern??Se,o=r.dataAttributes??he;return kt(e,t,n)??Ft(e,t,o)??zt(e,t)??Wt(e,t)??Gt(e,t,r.ignoreClassPattern)??Ht(e,t)}function W(e,t){let r=t.ignoreIdPattern??Se,n=t.dataAttributes??he;if(e.id&&!r.test(e.id))return `#${c(e.id)}`;for(let a of n){let l=e.getAttribute(a);if(l)return `[${a}="${c(l)}"]`}let o=e.getAttribute("role"),i=e.getAttribute("aria-label");if(o&&i)return `[role="${c(o)}"][aria-label="${c(i)}"]`;if(o)return `[role="${c(o)}"]`;let s=e.tagName.toLowerCase();for(let a of ve){let l=e.getAttribute(a);if(l)return `${s}[${a}="${c(l)}"]`}let u=Array.from(e.classList).filter(a=>!t.ignoreClassPattern||!t.ignoreClassPattern.test(a));return u.length>0?`${s}.${u.map(c).join(".")}`:s}function ye(e,t={}){let r=Ut(t),n=t.maxDepth??Vt,o=xe(e,r,t);if(o)return o;let i=e.parentElement,s=0,u=W(e,t);for(;i&&i!==r&&s<n;){let l=xe(i,r,t);if(l){let H=`${l} ${u}`;if(g(H,r))return H}let G=`${W(i,t)} ${u}`;if(g(G,r))return G;i=i.parentElement,s++;}i=e.parentElement,s=0;let a=[u];for(;i&&i!==r&&s<n;){let l=W(i,t);a.unshift(l);let S=a.join(" ");if(g(S,r))return S;i=i.parentElement,s++;}return a.join(" ")}function jt(e,t={}){let[r,n]=react.useState(null),o=react.useRef(false);return react.useEffect(()=>{e.current&&!o.current&&(o.current=true,n(ye(e.current,t)));}),r}function Bt(){}exports.AutomationIdPool=P;exports.CollisionDetector=R;exports.IdContext=w;exports.IdPool=U;exports.IdProvider=qe;exports.OVERFLOW_THRESHOLD=E;exports.SSRContext=k;exports.SSRProvider=Rt;exports.checkCollision=xt;exports.cleanupInactiveIds=it;exports.createSSRIdFactory=Et;exports.createServerIdManager=Le;exports.default=f;exports.generateAutomationId=ne;exports.generateDelimitedId=qt;exports.generateId=Ee;exports.generateIdWithStrategy=pt;exports.generateSecureId=He;exports.generateSelector=ye;exports.getActiveIdCount=et;exports.getActiveScopes=Ze;exports.getCurrentId=Re;exports.getDelimiterCounter=Pt;exports.getGlobalCollisionDetector=de;exports.getIdMetrics=Qe;exports.getScopeCounter=Xe;exports.getStrategyCounter=ct;exports.hashStrategy=gt;exports.nextIdForScope=je;exports.numericStrategy=lt;exports.resetAllScopes=Ke;exports.resetAutomationCounter=ze;exports.resetDelimiterCounter=wt;exports.resetGlobalCollisionDetector=It;exports.resetId=be;exports.resetIdForScope=Be;exports.resetIdMetrics=Ye;exports.resetSelectorCache=Bt;exports.resetStrategyCounter=at;exports.setGlobalPrefix=Ce;exports.setGlobalSuffix=$e;exports.setId=De;exports.timestampStrategy=ft;exports.useAutomationId=We;exports.useDelimitedId=_t;exports.useIdContext=d;exports.useIdMetrics=ot;exports.useIdPool=vt;exports.useIdWithStrategy=mt;exports.useSSRContext=me;exports.useSSRSafeId=Dt;exports.useStableSelector=jt;exports.useTrackedUniqueId=tt;exports.useTrackedUniqueIds=rt;exports.useUniqueId=Ne;exports.useUniqueIds=Te;exports.zeroPaddedStrategy=dt;//# sourceMappingURL=index.cjs.js.map
//# sourceMappingURL=index.cjs.js.map