@sohanemon/utils 7.3.0 → 7.3.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
|
@@ -1 +1 @@
|
|
|
1
|
-
"use client";const e=require(`../hooks-B_cSW9vB.cjs`),t=require(`../functions-Dp2CwvmB.cjs`);let n=require(`react`);n=e.A(n);let r=require(`react/jsx-runtime`),
|
|
1
|
+
"use client";const e=require(`../hooks-B_cSW9vB.cjs`),t=require(`../functions-Dp2CwvmB.cjs`);let n=require(`react`);n=e.A(n);let r=require(`@radix-ui/react-slot`),i=require(`react/jsx-runtime`),a=require(`@iconify/react`),o=require(`react-dom`);function s({selector:e,children:t}){let a=(0,n.useRef)(null),[o,s]=(0,n.useState)(!1),[c,l]=(0,n.useState)({hasClosest:!1,closestElement:null});return(0,n.useLayoutEffect)(()=>{if(a.current){let t=a.current.closest(e);l({hasClosest:t!==null,closestElement:t})}s(!0)},[e]),o?(0,i.jsx)(r.Slot,{ref:a,children:t(c)}):(0,i.jsx)(`span`,{ref:a})}function c({className:r,html:a,sanitize:o=!1,executeScripts:s=!0,...c}){let l=n.useRef([]),u=n.useRef(null);e.k(()=>{if(l.current.forEach(e=>{e.parentNode&&e.parentNode.removeChild(e)}),l.current=[],!(!s||!a))try{let e=document.createElement(`div`);e.innerHTML=a,e.querySelectorAll(`script`).forEach(e=>{let t=document.createElement(`script`);e.textContent&&(t.textContent=e.textContent),Array.from(e.attributes).forEach(e=>{t.setAttribute(e.name,e.value)}),t.onerror=e=>{console.error(`Script injection error:`,e)},document.body.appendChild(t),l.current.push(t)})}catch(e){console.error(`HTML injection error:`,e)}},[a,s]),n.useEffect(()=>()=>{l.current.forEach(e=>{e.parentNode&&e.parentNode.removeChild(e)})},[]);let d=n.useMemo(()=>{if(!a)return``;if(o){let e=document.createElement(`div`);e.innerHTML=a,e.querySelectorAll(`script`).forEach(e=>e.remove());let t=[`onclick`,`onload`,`onerror`,`onmouseover`];return e.querySelectorAll(`*`).forEach(e=>{t.forEach(t=>{e.hasAttribute(t)&&e.removeAttribute(t)})}),e.innerHTML}return a},[a,o]);return a?(0,i.jsx)(`div`,{ref:u,className:t.r(r),dangerouslySetInnerHTML:{__html:d},...c}):null}function l({breakpoint:t,as:r=`div`,fallback:a=n.Fragment,className:o,classNameFallback:s,...c}){let l=e.T(t.split(`-`).pop())===t.startsWith(`max`),u=l?a:r,d=l?s:o;return u===n.Fragment?(0,i.jsx)(u,{ref:c.ref,children:c.children},c.key):(0,i.jsx)(u,{className:d,...c})}function u({children:e,container:t}){let r=(0,n.useRef)(null),[i,a]=(0,n.useState)(!1);return(0,n.useLayoutEffect)(()=>{r.current=typeof t==`string`?document.querySelector(t):t.current,a(!0)},[]),!i||!r.current?null:(0,o.createPortal)(e,r.current)}const d=[`bottom-left`,`bottom-right`,`top-right`,`top-left`],f=({side:t,offset:r=2,unit:a=`rem`})=>{let[o,s]=n.useState(t??`bottom-left`),c=e.T({DEFAULT:`xs`,sm:`sm`,md:`md`,lg:`lg`,xl:`xl`,"2xl":`2xl`}),[l,u]=n.useState(typeof window<`u`?window.innerWidth:0);n.useEffect(()=>{if(typeof window>`u`)return;let e=()=>u(window.innerWidth);return window.addEventListener(`resize`,e),()=>window.removeEventListener(`resize`,e)},[]);let f=c===`2xl`&&l>=1792?a===`rem`?`${(l/16).toFixed(1)}rem`:`${l}${a}`:c,p={"bottom-left":{bottom:`${r}${a}`,left:`${r}${a}`},"bottom-right":{bottom:`${r}${a}`,right:`${r}${a}`},"top-right":{top:`${r}${a}`,right:`${r}${a}`},"top-left":{top:`${r}${a}`,left:`${r}${a}`}};return(0,i.jsx)(`button`,{type:`button`,onClick:()=>{s(d[(d.indexOf(o)+1)%d.length])},style:{position:`fixed`,zIndex:50,display:`grid`,height:`2.5rem`,minWidth:`2.5rem`,borderRadius:`30px`,placeContent:`center`,backgroundColor:`#2d3748`,fontFamily:`Courier New, Courier, monospace`,fontSize:`1rem`,color:`#ffffff`,border:`2px solid #4a5568`,boxShadow:`0 10px 15px -3px rgba(0, 0, 0, 0.1), 0 4px 6px -2px rgba(0, 0, 0, 0.05)`,padding:`0.5rem`,transition:`all 0.2s ease-in-out`,...p[o]},children:f})};function p(){return e.k(()=>{let e=document.body;if(!e)return;let t=e=>{let t=getComputedStyle(e);if(t.overflow===`hidden`&&t.overflowY===`hidden`&&t.overflowX===`hidden`)return!1;let n=(t.overflowY===`auto`||t.overflowY===`scroll`)&&e.scrollHeight>e.clientHeight,r=(t.overflowX===`auto`||t.overflowX===`scroll`)&&e.scrollWidth>e.clientWidth;return n||r},n=e=>{t(e)?e.dataset.scrollable=`true`:delete e.dataset.scrollable},r=e=>{n(e);for(let t=0;t<e.children.length;t++){let n=e.children[t];r(n)}};`requestIdleCallback`in window?window.requestIdleCallback(()=>r(e)):setTimeout(()=>r(e),0);let i=new MutationObserver(e=>{for(let t of e)t.type===`childList`?t.addedNodes.forEach(e=>{e instanceof HTMLElement&&r(e)}):t.type===`attributes`&&t.target instanceof HTMLElement&&n(t.target)});return i.observe(e,{subtree:!0,childList:!0,attributes:!0,attributeFilter:[`style`,`class`]}),()=>i.disconnect()},[]),null}exports.HtmlInjector=c,Object.defineProperty(exports,`Iconify`,{enumerable:!0,get:function(){return a.Icon}}),exports.MediaWrapper=l,exports.Portal=u,exports.ResponsiveIndicator=f,exports.TailwindIndicator=f,exports.ScrollTracker=e.C,exports.ScrollableMarker=p,exports.WithClosest=s;
|
|
@@ -2,6 +2,53 @@ import { Icon as Iconify } from "@iconify/react";
|
|
|
2
2
|
import * as react_jsx_runtime0 from "react/jsx-runtime";
|
|
3
3
|
import * as React$1 from "react";
|
|
4
4
|
|
|
5
|
+
//#region src/components/closest.d.ts
|
|
6
|
+
type ClosestResult = {
|
|
7
|
+
hasClosest: boolean;
|
|
8
|
+
closestElement: Element | null;
|
|
9
|
+
};
|
|
10
|
+
type WithClosestProps = {
|
|
11
|
+
selector: string;
|
|
12
|
+
children: (opts: ClosestResult) => React.ReactElement;
|
|
13
|
+
};
|
|
14
|
+
/**
|
|
15
|
+
* A component that finds the closest ancestor element matching a CSS selector.
|
|
16
|
+
*
|
|
17
|
+
* Uses the native `.closest()` method to traverse up the DOM tree from the
|
|
18
|
+
* rendered element and locate the nearest ancestor matching the provided selector.
|
|
19
|
+
* Returns the found element and a boolean indicating whether a match exists.
|
|
20
|
+
*
|
|
21
|
+
* @param selector - A valid CSS selector string to match against ancestors
|
|
22
|
+
* @param children - Render prop function that receives the closest element result
|
|
23
|
+
* @returns The rendered element with the ref attached for DOM traversal
|
|
24
|
+
*
|
|
25
|
+
* @example
|
|
26
|
+
* ```tsx
|
|
27
|
+
* // Find the closest parent with class "modal"
|
|
28
|
+
* <WithClosest selector=".modal">
|
|
29
|
+
* {({ hasClosest, closestElement }) => (
|
|
30
|
+
* <div>
|
|
31
|
+
* {hasClosest ? 'Inside modal' : 'Outside modal'}
|
|
32
|
+
* </div>
|
|
33
|
+
* )}
|
|
34
|
+
* </WithClosest>
|
|
35
|
+
* ```
|
|
36
|
+
*
|
|
37
|
+
* @example
|
|
38
|
+
* ```tsx
|
|
39
|
+
* // Find closest section ancestor
|
|
40
|
+
* <WithClosest selector="section">
|
|
41
|
+
* {({ hasClosest, closestElement }) => (
|
|
42
|
+
* <span data-section-id={closestElement?.id} />
|
|
43
|
+
* )}
|
|
44
|
+
* </WithClosest>
|
|
45
|
+
* ```
|
|
46
|
+
*/
|
|
47
|
+
declare function WithClosest({
|
|
48
|
+
selector,
|
|
49
|
+
children
|
|
50
|
+
}: WithClosestProps): react_jsx_runtime0.JSX.Element;
|
|
51
|
+
//#endregion
|
|
5
52
|
//#region src/components/html-injector.d.ts
|
|
6
53
|
/**
|
|
7
54
|
* Props for the HtmlInjector component
|
|
@@ -230,4 +277,4 @@ declare const ScrollTracker: ({
|
|
|
230
277
|
*/
|
|
231
278
|
declare function ScrollableMarker(): null;
|
|
232
279
|
//#endregion
|
|
233
|
-
export { HtmlInjector, Iconify, MediaWrapper, Portal, ResponsiveIndicator, ResponsiveIndicator as TailwindIndicator, ScrollTracker, ScrollableMarker };
|
|
280
|
+
export { HtmlInjector, Iconify, MediaWrapper, Portal, ResponsiveIndicator, ResponsiveIndicator as TailwindIndicator, ScrollTracker, ScrollableMarker, WithClosest };
|
|
@@ -1,7 +1,54 @@
|
|
|
1
1
|
import * as React$1 from "react";
|
|
2
|
-
import * as
|
|
2
|
+
import * as react_jsx_runtime1 from "react/jsx-runtime";
|
|
3
3
|
import { Icon as Iconify } from "@iconify/react";
|
|
4
4
|
|
|
5
|
+
//#region src/components/closest.d.ts
|
|
6
|
+
type ClosestResult = {
|
|
7
|
+
hasClosest: boolean;
|
|
8
|
+
closestElement: Element | null;
|
|
9
|
+
};
|
|
10
|
+
type WithClosestProps = {
|
|
11
|
+
selector: string;
|
|
12
|
+
children: (opts: ClosestResult) => React.ReactElement;
|
|
13
|
+
};
|
|
14
|
+
/**
|
|
15
|
+
* A component that finds the closest ancestor element matching a CSS selector.
|
|
16
|
+
*
|
|
17
|
+
* Uses the native `.closest()` method to traverse up the DOM tree from the
|
|
18
|
+
* rendered element and locate the nearest ancestor matching the provided selector.
|
|
19
|
+
* Returns the found element and a boolean indicating whether a match exists.
|
|
20
|
+
*
|
|
21
|
+
* @param selector - A valid CSS selector string to match against ancestors
|
|
22
|
+
* @param children - Render prop function that receives the closest element result
|
|
23
|
+
* @returns The rendered element with the ref attached for DOM traversal
|
|
24
|
+
*
|
|
25
|
+
* @example
|
|
26
|
+
* ```tsx
|
|
27
|
+
* // Find the closest parent with class "modal"
|
|
28
|
+
* <WithClosest selector=".modal">
|
|
29
|
+
* {({ hasClosest, closestElement }) => (
|
|
30
|
+
* <div>
|
|
31
|
+
* {hasClosest ? 'Inside modal' : 'Outside modal'}
|
|
32
|
+
* </div>
|
|
33
|
+
* )}
|
|
34
|
+
* </WithClosest>
|
|
35
|
+
* ```
|
|
36
|
+
*
|
|
37
|
+
* @example
|
|
38
|
+
* ```tsx
|
|
39
|
+
* // Find closest section ancestor
|
|
40
|
+
* <WithClosest selector="section">
|
|
41
|
+
* {({ hasClosest, closestElement }) => (
|
|
42
|
+
* <span data-section-id={closestElement?.id} />
|
|
43
|
+
* )}
|
|
44
|
+
* </WithClosest>
|
|
45
|
+
* ```
|
|
46
|
+
*/
|
|
47
|
+
declare function WithClosest({
|
|
48
|
+
selector,
|
|
49
|
+
children
|
|
50
|
+
}: WithClosestProps): react_jsx_runtime1.JSX.Element;
|
|
51
|
+
//#endregion
|
|
5
52
|
//#region src/components/html-injector.d.ts
|
|
6
53
|
/**
|
|
7
54
|
* Props for the HtmlInjector component
|
|
@@ -56,7 +103,7 @@ declare function HtmlInjector({
|
|
|
56
103
|
sanitize,
|
|
57
104
|
executeScripts,
|
|
58
105
|
...props
|
|
59
|
-
}: HtmlInjectorProps):
|
|
106
|
+
}: HtmlInjectorProps): react_jsx_runtime1.JSX.Element | null;
|
|
60
107
|
//#endregion
|
|
61
108
|
//#region src/components/media-wrapper.d.ts
|
|
62
109
|
/**
|
|
@@ -105,7 +152,7 @@ declare function MediaWrapper({
|
|
|
105
152
|
className: classNameOriginal,
|
|
106
153
|
classNameFallback,
|
|
107
154
|
...props
|
|
108
|
-
}: MediaWrapperProps):
|
|
155
|
+
}: MediaWrapperProps): react_jsx_runtime1.JSX.Element;
|
|
109
156
|
//#endregion
|
|
110
157
|
//#region src/components/portal.d.ts
|
|
111
158
|
/**
|
|
@@ -205,7 +252,7 @@ interface ScrollTrackerProps {
|
|
|
205
252
|
*/
|
|
206
253
|
declare const ScrollTracker: ({
|
|
207
254
|
children
|
|
208
|
-
}: ScrollTrackerProps) =>
|
|
255
|
+
}: ScrollTrackerProps) => react_jsx_runtime1.JSX.Element;
|
|
209
256
|
//#endregion
|
|
210
257
|
//#region src/components/scrollable-marker.d.ts
|
|
211
258
|
/**
|
|
@@ -230,4 +277,4 @@ declare const ScrollTracker: ({
|
|
|
230
277
|
*/
|
|
231
278
|
declare function ScrollableMarker(): null;
|
|
232
279
|
//#endregion
|
|
233
|
-
export { HtmlInjector, Iconify, MediaWrapper, Portal, ResponsiveIndicator, ResponsiveIndicator as TailwindIndicator, ScrollTracker, ScrollableMarker };
|
|
280
|
+
export { HtmlInjector, Iconify, MediaWrapper, Portal, ResponsiveIndicator, ResponsiveIndicator as TailwindIndicator, ScrollTracker, ScrollableMarker, WithClosest };
|
package/dist/components/index.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
"use client";import{r as e}from"../functions-CTMT4m8K.js";import{C as t,T as n,k as r}from"../hooks-CCFEDyEO.js";import*as i from"react";import{useLayoutEffect as a,useRef as o,useState as s}from"react";import{
|
|
1
|
+
"use client";import{r as e}from"../functions-CTMT4m8K.js";import{C as t,T as n,k as r}from"../hooks-CCFEDyEO.js";import*as i from"react";import{useLayoutEffect as a,useRef as o,useState as s}from"react";import{Slot as c}from"@radix-ui/react-slot";import{jsx as l}from"react/jsx-runtime";import{Icon as u}from"@iconify/react";import{createPortal as d}from"react-dom";function f({selector:e,children:t}){let n=o(null),[r,i]=s(!1),[u,d]=s({hasClosest:!1,closestElement:null});return a(()=>{if(n.current){let t=n.current.closest(e);d({hasClosest:t!==null,closestElement:t})}i(!0)},[e]),r?l(c,{ref:n,children:t(u)}):l(`span`,{ref:n})}function p({className:t,html:n,sanitize:a=!1,executeScripts:o=!0,...s}){let c=i.useRef([]),u=i.useRef(null);r(()=>{if(c.current.forEach(e=>{e.parentNode&&e.parentNode.removeChild(e)}),c.current=[],!(!o||!n))try{let e=document.createElement(`div`);e.innerHTML=n,e.querySelectorAll(`script`).forEach(e=>{let t=document.createElement(`script`);e.textContent&&(t.textContent=e.textContent),Array.from(e.attributes).forEach(e=>{t.setAttribute(e.name,e.value)}),t.onerror=e=>{console.error(`Script injection error:`,e)},document.body.appendChild(t),c.current.push(t)})}catch(e){console.error(`HTML injection error:`,e)}},[n,o]),i.useEffect(()=>()=>{c.current.forEach(e=>{e.parentNode&&e.parentNode.removeChild(e)})},[]);let d=i.useMemo(()=>{if(!n)return``;if(a){let e=document.createElement(`div`);e.innerHTML=n,e.querySelectorAll(`script`).forEach(e=>e.remove());let t=[`onclick`,`onload`,`onerror`,`onmouseover`];return e.querySelectorAll(`*`).forEach(e=>{t.forEach(t=>{e.hasAttribute(t)&&e.removeAttribute(t)})}),e.innerHTML}return n},[n,a]);return n?l(`div`,{ref:u,className:e(t),dangerouslySetInnerHTML:{__html:d},...s}):null}function m({breakpoint:e,as:t=`div`,fallback:r=i.Fragment,className:a,classNameFallback:o,...s}){let c=n(e.split(`-`).pop())===e.startsWith(`max`),u=c?r:t,d=c?o:a;return u===i.Fragment?l(u,{ref:s.ref,children:s.children},s.key):l(u,{className:d,...s})}function h({children:e,container:t}){let n=o(null),[r,i]=s(!1);return a(()=>{n.current=typeof t==`string`?document.querySelector(t):t.current,i(!0)},[]),!r||!n.current?null:d(e,n.current)}const g=[`bottom-left`,`bottom-right`,`top-right`,`top-left`],_=({side:e,offset:t=2,unit:r=`rem`})=>{let[a,o]=i.useState(e??`bottom-left`),s=n({DEFAULT:`xs`,sm:`sm`,md:`md`,lg:`lg`,xl:`xl`,"2xl":`2xl`}),[c,u]=i.useState(typeof window<`u`?window.innerWidth:0);i.useEffect(()=>{if(typeof window>`u`)return;let e=()=>u(window.innerWidth);return window.addEventListener(`resize`,e),()=>window.removeEventListener(`resize`,e)},[]);let d=s===`2xl`&&c>=1792?r===`rem`?`${(c/16).toFixed(1)}rem`:`${c}${r}`:s;return l(`button`,{type:`button`,onClick:()=>{o(g[(g.indexOf(a)+1)%g.length])},style:{position:`fixed`,zIndex:50,display:`grid`,height:`2.5rem`,minWidth:`2.5rem`,borderRadius:`30px`,placeContent:`center`,backgroundColor:`#2d3748`,fontFamily:`Courier New, Courier, monospace`,fontSize:`1rem`,color:`#ffffff`,border:`2px solid #4a5568`,boxShadow:`0 10px 15px -3px rgba(0, 0, 0, 0.1), 0 4px 6px -2px rgba(0, 0, 0, 0.05)`,padding:`0.5rem`,transition:`all 0.2s ease-in-out`,...{"bottom-left":{bottom:`${t}${r}`,left:`${t}${r}`},"bottom-right":{bottom:`${t}${r}`,right:`${t}${r}`},"top-right":{top:`${t}${r}`,right:`${t}${r}`},"top-left":{top:`${t}${r}`,left:`${t}${r}`}}[a]},children:d})};function v(){return r(()=>{let e=document.body;if(!e)return;let t=e=>{let t=getComputedStyle(e);if(t.overflow===`hidden`&&t.overflowY===`hidden`&&t.overflowX===`hidden`)return!1;let n=(t.overflowY===`auto`||t.overflowY===`scroll`)&&e.scrollHeight>e.clientHeight,r=(t.overflowX===`auto`||t.overflowX===`scroll`)&&e.scrollWidth>e.clientWidth;return n||r},n=e=>{t(e)?e.dataset.scrollable=`true`:delete e.dataset.scrollable},r=e=>{n(e);for(let t=0;t<e.children.length;t++){let n=e.children[t];r(n)}};`requestIdleCallback`in window?window.requestIdleCallback(()=>r(e)):setTimeout(()=>r(e),0);let i=new MutationObserver(e=>{for(let t of e)t.type===`childList`?t.addedNodes.forEach(e=>{e instanceof HTMLElement&&r(e)}):t.type===`attributes`&&t.target instanceof HTMLElement&&n(t.target)});return i.observe(e,{subtree:!0,childList:!0,attributes:!0,attributeFilter:[`style`,`class`]}),()=>i.disconnect()},[]),null}export{p as HtmlInjector,u as Iconify,m as MediaWrapper,h as Portal,_ as ResponsiveIndicator,_ as TailwindIndicator,t as ScrollTracker,v as ScrollableMarker,f as WithClosest};
|