roks-rjsc 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2025 rokku
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,105 @@
1
+ # roks-rjsc
2
+
3
+ A small React component library exposing a few UI helpers and modal/loading utilities.
4
+
5
+ ## Installation
6
+
7
+ Install from npm (after publishing):
8
+
9
+ ```bash
10
+ npm install roks-rjsc
11
+ ```
12
+
13
+ During development you can also install directly from GitHub:
14
+
15
+ ```bash
16
+ npm install github:rokku-x/roks-rjsc
17
+ ```
18
+
19
+ ## Usage
20
+
21
+ Import named exports from the package root. Examples below assume React 18.
22
+
23
+ Basic component:
24
+
25
+ ```tsx
26
+ import React from 'react';
27
+ import { Button } from 'roks-rjsc';
28
+
29
+ export default function App() {
30
+ return <Button onClick={() => alert('clicked')}>Click me</Button>;
31
+ }
32
+ ```
33
+
34
+ Loading provider and hook:
35
+
36
+ ```tsx
37
+ import React from 'react';
38
+ import { LoadingProvider, useLoading } from 'roks-rjsc';
39
+
40
+ function Example() {
41
+ const { startLoading, stopLoading, asyncUseLoading } = useLoading();
42
+
43
+ const handle = async () => {
44
+ startLoading();
45
+ await new Promise(r => setTimeout(r, 1000));
46
+ stopLoading();
47
+ }
48
+
49
+ return <button onClick={handle}>Load</button>
50
+ }
51
+
52
+ export default function AppWrapper() {
53
+ return (
54
+ <LoadingProvider>
55
+ <Example />
56
+ </LoadingProvider>
57
+ )
58
+ }
59
+ ```
60
+
61
+ Modal helpers (BaseModalProvider + hooks):
62
+
63
+ ```tsx
64
+ import React from 'react';
65
+ import { BaseModalProvider, useStaticModal, useDynamicModal } from 'roks-rjsc';
66
+
67
+ function StaticExample() {
68
+ const [show, close, id] = useStaticModal();
69
+
70
+ return (
71
+ <>
72
+ <button onClick={() => show(<div>Static content</div>)}>Open static modal</button>
73
+ </>
74
+ )
75
+ }
76
+
77
+ function DynamicExample() {
78
+ const [render, show, close, focus] = useDynamicModal();
79
+
80
+ return (
81
+ <>
82
+ <button onClick={() => show()}>Open dynamic modal</button>
83
+ {render(<div>Rendered into dynamic modal</div>)}
84
+ </>
85
+ )
86
+ }
87
+
88
+ export default function App() {
89
+ return (
90
+ <BaseModalProvider>
91
+ <StaticExample />
92
+ <DynamicExample />
93
+ </BaseModalProvider>
94
+ )
95
+ }
96
+ ```
97
+
98
+ API (top-level exports)
99
+ - `Button` - basic button component
100
+ - `LoadingProvider`, `useLoading`, `Loading`, `AnimationType` - loading utilities
101
+ - `BaseModalProvider`, `useBaseModal`, `useStaticModal`, `useDynamicModal`, `RenderMode` - modal system
102
+
103
+ ## License
104
+
105
+ MIT
@@ -0,0 +1,54 @@
1
+ "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const c=require("react/jsx-runtime"),a=require("react"),N=require("react-dom"),F=({children:o,onClick:e})=>c.jsx("button",{onClick:e,children:o});class T extends EventTarget{constructor(){super(...arguments),this.controller=new AbortController}on(e,n){return this.addEventListener(e,f=>n(f.detail),{signal:this.controller.signal}),this}once(e,n){return this.addEventListener(e,f=>n(f.detail),{signal:this.controller.signal,once:!0}),this}emit(e,n){return this.dispatchEvent(new CustomEvent(e,{detail:n}))}removeAllListeners(){this.controller.abort(),this.controller=new AbortController}}const C=new T,w={Spin:"spin",FadeInOut:"fadeInOut",None:"none"},I=({animationType:o=w.Spin,animationDuration:e,children:n,style:f,className:g,id:r})=>{const u=o,h=o===w.Spin?1:o===w.FadeInOut?2:0,d=e||h,s=o===w.Spin?"linear":o===w.FadeInOut?"ease-in-out":"linear",m=o===w.None?"none":`${u} ${d}s ${s} infinite`;return c.jsx("div",{style:{animation:m,...f},className:g,id:r,children:n})},$=()=>c.jsx("div",{id:"loading-circle",style:{width:"60px",height:"60px",border:"10px solid #f3f3f3",borderTop:"10px solid #009b4bff",borderRadius:"50%"}}),U=()=>c.jsx("div",{style:{padding:"20px",fontSize:"25px",color:"#333",fontFamily:"system-ui, sans-serif"},children:"Please wait..."}),P=a.createContext(void 0),W=({children:o,loadingComponent:e,animationType:n=w.FadeInOut,animationDuration:f,wrapperStyle:g,wrapperClassName:r,wrapperId:u,animationWrapperStyle:h,animationWrapperClassName:d,animationWrapperId:s})=>{e=e||(n===w.Spin?$:U);const[m,p]=a.useState(0),[R,E]=a.useState(null),b=R??m>0,j=M=>E(M),k=()=>p(M=>M+1),A=()=>p(M=>Math.max(0,M-1)),L=a.useRef(null);a.useEffect(()=>{C.emit("change",{isLoading:b}),C.emit(b?"start":"stop",null),b?(L.current?.showModal(),document.body.setAttribute("inert","")):b||document.body.removeAttribute("inert")},[m]),a.useEffect(()=>()=>{p(0),C.removeAllListeners()},[]);const y=u||"loading-dialog";return c.jsxs(P.Provider,{value:{get isLoading(){return b},startLoading:k,stopLoading:A,loadingEventTarget:C,overrideLoading:j},children:[o,b&&N.createPortal(c.jsxs(c.Fragment,{children:[c.jsx("style",{children:`
2
+ dialog#${y}[open] {
3
+ display: flex !important;
4
+ justify-content: center;
5
+ align-items: center;
6
+ width: 100vw;
7
+ height: 100vh;
8
+ max-width: 100%;
9
+ max-height: 100%;
10
+ }
11
+ @keyframes spin {
12
+ 0% { transform: rotate(0deg); }
13
+ 100% { transform: rotate(360deg); }
14
+ }
15
+ @keyframes fadeInOut {
16
+ 0%, 100% { opacity: 0.2; }
17
+ 50% { opacity: 1; }
18
+ }
19
+ body:has(dialog#${y}[open]) {
20
+ overflow: hidden;
21
+ }
22
+ body {
23
+ scrollbar-gutter: stable;
24
+ }
25
+ `}),c.jsx("dialog",{ref:L,style:{border:"none",padding:0,backgroundColor:"rgba(0, 0, 0, 0.5)",backdropFilter:"blur(2px)",...g},className:r,id:y,children:c.jsx(I,{animationType:n,animationDuration:f,style:h,className:d,id:s,children:a.isValidElement(e)?e:a.createElement(e)})})]}),document.body)]})},B=()=>{const o=a.useContext(P);if(!o)throw new Error("useLoading must be used within a LoadingProvider");const e=a.useRef(0),{startLoading:n,stopLoading:f,isLoading:g,...r}=o,u=()=>{n(),e.current+=1},h=()=>{e.current>0&&(f(),e.current-=1)};return{startLoading:u,stopLoading:h,get isLocalLoading(){return e.current>0},...r,asyncUseLoading:async s=>{u();try{return await s}finally{h()}},isLoading:g}};function _({isLoading:o=!1}){const e=B();return a.useEffect(()=>(o?e.startLoading():e.stopLoading(),()=>{o&&e.stopLoading()}),[o]),null}const S=a.createContext(void 0),x={STACKED:0,CURRENT_ONLY:1,CURRENT_HIDDEN_STACK:2};function K({children:o,wrapperId:e,renderMode:n=x.STACKED,wrapperStyle:f}){const g=a.useRef(null),r=a.useRef(new Map),[u,h]=a.useState(r.current),d=Array.from(u.values()),s=Array.from(u.keys()),m=a.useRef(new Map),[p,R]=a.useState(void 0),E=(t,i=Math.random().toString(36).substring(2,6),l=!1)=>{if(s.indexOf(i)!==-1)return console.warn(`Modal with id ${i} already exists. Choose a different id.`),i;let D=[t,l];return r.current=new Map(r.current),r.current.set(i,D),h(new Map(r.current)),i},b=t=>{let i="";if(typeof t!="string"){for(let[l,v]of r.current.entries())if(v[0]===t){i=l;break}}else typeof t=="string"&&(i=t);return r.current.has(i)?(r.current=new Map(r.current),r.current.delete(i),h(new Map(r.current)),!0):!1},j=(t,i)=>{if(r.current.has(t)){let l=r.current.get(t);if(l[1]===!1){console.warn(`Modal with id ${t} is dynamic. Cannot update content.`);return}l[0]=i,r.current.set(t,l),h(new Map(r.current))}},k=t=>{if(!u.has(t))return!1;let i=r.current.get(t);return r.current.delete(t),r.current.set(t,i),h(new Map(r.current)),!0},A=t=>s.indexOf(t),L=t=>m.current.get(t);a.useEffect(()=>{const t=s[s.length-1];t!==void 0?(g.current?.showModal(),document.body.setAttribute("inert","")):t===void 0&&(g.current?.close(),document.body.removeAttribute("inert")),R(t)},[u]);const y=e||"base-modal-wrapper",M=a.useCallback((t,i)=>{t?m.current.set(i,t):m.current.delete(i)},[]),O=()=>{switch(n){case x.STACKED:return d.map(([t,i],l)=>c.jsx("div",{ref:v=>M(v,s[l]),className:"modal-window",id:s[l],style:{display:"block",zIndex:s[l]===p?1e3:100},...p!==s[l]?{inert:""}:{},children:i?null:t},s[l]));case x.CURRENT_ONLY:return d.length>0?c.jsx("div",{id:s[d.length-1],ref:t=>M(t,s[d.length-1]),className:"modal-window",style:{display:"block"},children:d[d.length-1][1]?null:d[d.length-1][0]},s[d.length-1]):null;case x.CURRENT_HIDDEN_STACK:return d.length>0?d.map(([t,i],l)=>c.jsx("div",{ref:v=>M(v,s[l]),id:s[l],className:"modal-window",style:{display:p===s[l]?"block":"none"},...p!==s[l]?{inert:""}:{},children:i?null:t},s[l])):null}};return c.jsxs(S.Provider,{value:{modalCount:0,get renderMode(){return n},pushModal:E,popModal:b,currentModalId:p,updateModalContent:j,getModalWindowRef:L,focusModal:k,getModalOrderIndex:A},children:[o,s.length===0?null:N.createPortal(c.jsxs(c.Fragment,{children:[c.jsx("style",{children:`
26
+ dialog#${y}[open] {
27
+ display: flex !important;
28
+ justify-content: center;
29
+ align-items: center;
30
+ width: 100vw;
31
+ height: 100vh;
32
+ max-width: 100%;
33
+ max-height: 100%;
34
+ }
35
+ body:has(dialog#${y}[open]) {
36
+ overflow: hidden;
37
+ }
38
+ body {
39
+ scrollbar-gutter: stable;
40
+ }
41
+ .modal-wrapper{
42
+ border: none;
43
+ padding: 0;
44
+ background: unset;
45
+ }
46
+ .modal-window {
47
+ position: absolute;
48
+ width: 100%;
49
+ height: 100%;
50
+ display: none;
51
+ background-color: rgba(0, 0, 0, 0.1);
52
+ backdrop-filter: blur(2px);
53
+ }
54
+ `}),c.jsx("dialog",{className:"modal-wrapper",ref:g,id:y,style:f,children:O()})]}),document.body)]})}function q(){const o=a.useContext(S);if(!o)throw new Error("useBaseModal must be used within a BaseModalProvider");return o}function z(o=Math.random().toString(36).substring(2,6)){const e=a.useContext(S);if(!e)throw new Error("useBaseModal must be used within a BaseModalProvider");let n=a.useRef(o);const f=u=>(e.pushModal(u,n.current),g),g=()=>e.popModal(n.current),r=u=>{e.updateModalContent(n.current,u)};return[f,g,n.current,e.currentModalId===n.current,r]}function H(o=Math.random().toString(36).substring(2,6)){const e=a.useContext(S);if(!e)throw new Error("useBaseModal must be used within a BaseModalProvider");let n=a.useRef(o);const f=e.currentModalId===n.current;return[d=>e.getModalWindowRef(n.current)?N.createPortal(d,e.getModalWindowRef(n.current)):null,()=>{e.pushModal(null,n.current,!0)[1]},()=>{e.popModal(n.current)},()=>{e.focusModal(n.current)},n.current,f]}exports.AnimationType=w;exports.BaseModalProvider=K;exports.Button=F;exports.Loading=_;exports.LoadingProvider=W;exports.RenderMode=x;exports.useBaseModal=q;exports.useDynamicModal=H;exports.useLoading=B;exports.useStaticModal=z;
@@ -0,0 +1,96 @@
1
+ import { default as default_2 } from 'react';
2
+ import { JSX as JSX_2 } from 'react/jsx-runtime';
3
+ import { ReactNode } from 'react';
4
+
5
+ export declare const AnimationType: {
6
+ readonly Spin: "spin";
7
+ readonly FadeInOut: "fadeInOut";
8
+ readonly None: "none";
9
+ };
10
+
11
+ export declare type AnimationType = (typeof AnimationType)[keyof typeof AnimationType];
12
+
13
+ declare interface BaseModalContextType {
14
+ modalCount: number;
15
+ renderMode?: RenderMode;
16
+ currentModalId?: string;
17
+ pushModal: (el: default_2.ReactNode, modalId?: string, isDynamic?: boolean) => string;
18
+ popModal: (idEl: string | default_2.ReactNode) => boolean;
19
+ updateModalContent: (modalId: string, newContent: default_2.ReactNode) => void;
20
+ getModalWindowRef: (modalId: string) => HTMLDivElement | undefined;
21
+ focusModal: (modalId: string) => boolean;
22
+ getModalOrderIndex: (modalId: string) => number;
23
+ }
24
+
25
+ export declare function BaseModalProvider({ children, wrapperId, renderMode, wrapperStyle }: {
26
+ children: default_2.ReactNode;
27
+ wrapperId?: string;
28
+ renderMode?: RenderMode;
29
+ wrapperStyle?: default_2.CSSProperties;
30
+ }): JSX_2.Element;
31
+
32
+ export declare const Button: ({ children, onClick }: ButtonProps) => JSX_2.Element;
33
+
34
+ declare interface ButtonProps {
35
+ children: default_2.ReactNode;
36
+ onClick?: () => void;
37
+ }
38
+
39
+ declare class EventEmitter<T extends EventMap> extends EventTarget {
40
+ private controller;
41
+ on<K extends keyof T>(type: K, callback: (detail: T[K]) => void): this;
42
+ once<K extends keyof T>(type: K, callback: (detail: T[K]) => void): this;
43
+ emit<K extends keyof T>(type: K, detail: T[K]): boolean;
44
+ removeAllListeners(): void;
45
+ }
46
+
47
+ declare type EventMap = Record<string, any>;
48
+
49
+ export declare function Loading({ isLoading }: {
50
+ isLoading: boolean;
51
+ }): null;
52
+
53
+ export declare const LoadingProvider: default_2.FC<{
54
+ children: ReactNode;
55
+ loadingComponent?: default_2.ComponentType | default_2.ReactElement;
56
+ animationType?: AnimationType;
57
+ animationDuration?: number;
58
+ wrapperStyle?: default_2.CSSProperties;
59
+ wrapperClassName?: string;
60
+ wrapperId?: string;
61
+ animationWrapperStyle?: default_2.CSSProperties;
62
+ animationWrapperClassName?: string;
63
+ animationWrapperId?: string;
64
+ }>;
65
+
66
+ export declare const RenderMode: {
67
+ STACKED: number;
68
+ CURRENT_ONLY: number;
69
+ CURRENT_HIDDEN_STACK: number;
70
+ };
71
+
72
+ export declare type RenderMode = (typeof RenderMode)[keyof typeof RenderMode];
73
+
74
+ export declare function useBaseModal(): BaseModalContextType;
75
+
76
+ export declare function useDynamicModal(id?: string): [(el: JSX.Element) => ReactNode, () => void, () => void, () => void, string, boolean];
77
+
78
+ export declare const useLoading: () => {
79
+ asyncUseLoading: <R, _ extends any[]>(asyncFunction: Promise<R>) => Promise<R>;
80
+ isLoading: boolean;
81
+ loadingEventTarget: EventEmitter< {
82
+ change: {
83
+ isLoading: boolean;
84
+ } | null;
85
+ start: null;
86
+ stop: null;
87
+ }>;
88
+ overrideLoading: (state: boolean) => void;
89
+ startLoading: () => void;
90
+ stopLoading: () => void;
91
+ isLocalLoading: boolean;
92
+ };
93
+
94
+ export declare function useStaticModal(id?: string): [(el: React.ReactNode) => () => boolean, () => boolean, string, boolean, (newContent: React.ReactNode) => void];
95
+
96
+ export { }
@@ -0,0 +1,309 @@
1
+ import { jsx as f, jsxs as S, Fragment as $ } from "react/jsx-runtime";
2
+ import I, { useState as E, useRef as y, useEffect as R, createContext as T, useContext as k, useCallback as K } from "react";
3
+ import { createPortal as D } from "react-dom";
4
+ const Q = ({ children: o, onClick: e }) => /* @__PURE__ */ f("button", { onClick: e, children: o });
5
+ class j extends EventTarget {
6
+ constructor() {
7
+ super(...arguments), this.controller = new AbortController();
8
+ }
9
+ on(e, n) {
10
+ return this.addEventListener(
11
+ e,
12
+ (c) => n(c.detail),
13
+ { signal: this.controller.signal }
14
+ ), this;
15
+ }
16
+ once(e, n) {
17
+ return this.addEventListener(
18
+ e,
19
+ (c) => n(c.detail),
20
+ {
21
+ signal: this.controller.signal,
22
+ once: !0
23
+ }
24
+ ), this;
25
+ }
26
+ emit(e, n) {
27
+ return this.dispatchEvent(new CustomEvent(e, { detail: n }));
28
+ }
29
+ removeAllListeners() {
30
+ this.controller.abort(), this.controller = new AbortController();
31
+ }
32
+ }
33
+ const C = new j(), M = {
34
+ Spin: "spin",
35
+ FadeInOut: "fadeInOut",
36
+ None: "none"
37
+ }, z = ({ animationType: o = M.Spin, animationDuration: e, children: n, style: c, className: u, id: r }) => {
38
+ const d = o, g = o === M.Spin ? 1 : o === M.FadeInOut ? 2 : 0, l = e || g, a = o === M.Spin ? "linear" : o === M.FadeInOut ? "ease-in-out" : "linear", w = o === M.None ? "none" : `${d} ${l}s ${a} infinite`;
39
+ return /* @__PURE__ */ f("div", { style: { animation: w, ...c }, className: u, id: r, children: n });
40
+ }, H = () => /* @__PURE__ */ f("div", { id: "loading-circle", style: { width: "60px", height: "60px", border: "10px solid #f3f3f3", borderTop: "10px solid #009b4bff", borderRadius: "50%" } }), Y = () => /* @__PURE__ */ f("div", { style: { padding: "20px", fontSize: "25px", color: "#333", fontFamily: "system-ui, sans-serif" }, children: "Please wait..." }), U = T(void 0), X = ({ children: o, loadingComponent: e, animationType: n = M.FadeInOut, animationDuration: c, wrapperStyle: u, wrapperClassName: r, wrapperId: d, animationWrapperStyle: g, animationWrapperClassName: l, animationWrapperId: a }) => {
41
+ e = e || (n === M.Spin ? H : Y);
42
+ const [w, h] = E(0), [N, O] = E(null), m = N ?? w > 0, P = (p) => O(p), B = () => h((p) => p + 1), F = () => h((p) => Math.max(0, p - 1)), L = y(null);
43
+ R(() => {
44
+ C.emit("change", { isLoading: m }), C.emit(m ? "start" : "stop", null), m ? (L.current?.showModal(), document.body.setAttribute("inert", "")) : m || document.body.removeAttribute("inert");
45
+ }, [w]), R(() => () => {
46
+ h(0), C.removeAllListeners();
47
+ }, []);
48
+ const b = d || "loading-dialog";
49
+ return /* @__PURE__ */ S(U.Provider, { value: { get isLoading() {
50
+ return m;
51
+ }, startLoading: B, stopLoading: F, loadingEventTarget: C, overrideLoading: P }, children: [
52
+ o,
53
+ m && D(
54
+ /* @__PURE__ */ S($, { children: [
55
+ /* @__PURE__ */ f("style", { children: `
56
+ dialog#${b}[open] {
57
+ display: flex !important;
58
+ justify-content: center;
59
+ align-items: center;
60
+ width: 100vw;
61
+ height: 100vh;
62
+ max-width: 100%;
63
+ max-height: 100%;
64
+ }
65
+ @keyframes spin {
66
+ 0% { transform: rotate(0deg); }
67
+ 100% { transform: rotate(360deg); }
68
+ }
69
+ @keyframes fadeInOut {
70
+ 0%, 100% { opacity: 0.2; }
71
+ 50% { opacity: 1; }
72
+ }
73
+ body:has(dialog#${b}[open]) {
74
+ overflow: hidden;
75
+ }
76
+ body {
77
+ scrollbar-gutter: stable;
78
+ }
79
+ ` }),
80
+ /* @__PURE__ */ f(
81
+ "dialog",
82
+ {
83
+ ref: L,
84
+ style: {
85
+ border: "none",
86
+ padding: 0,
87
+ backgroundColor: "rgba(0, 0, 0, 0.5)",
88
+ backdropFilter: "blur(2px)",
89
+ ...u
90
+ },
91
+ className: r,
92
+ id: b,
93
+ children: /* @__PURE__ */ f(z, { animationType: n, animationDuration: c, style: g, className: l, id: a, children: I.isValidElement(e) ? e : I.createElement(e) })
94
+ }
95
+ )
96
+ ] }),
97
+ document.body
98
+ )
99
+ ] });
100
+ }, V = () => {
101
+ const o = k(U);
102
+ if (!o) throw new Error("useLoading must be used within a LoadingProvider");
103
+ const e = y(0), { startLoading: n, stopLoading: c, isLoading: u, ...r } = o, d = () => {
104
+ n(), e.current += 1;
105
+ }, g = () => {
106
+ e.current > 0 && (c(), e.current -= 1);
107
+ };
108
+ return {
109
+ startLoading: d,
110
+ stopLoading: g,
111
+ get isLocalLoading() {
112
+ return e.current > 0;
113
+ },
114
+ ...r,
115
+ asyncUseLoading: async (a) => {
116
+ d();
117
+ try {
118
+ return await a;
119
+ } finally {
120
+ g();
121
+ }
122
+ },
123
+ isLoading: u
124
+ };
125
+ };
126
+ function Z({ isLoading: o = !1 }) {
127
+ const e = V();
128
+ return R(() => (o ? e.startLoading() : e.stopLoading(), () => {
129
+ o && e.stopLoading();
130
+ }), [o]), null;
131
+ }
132
+ const A = T(void 0), x = {
133
+ STACKED: 0,
134
+ CURRENT_ONLY: 1,
135
+ CURRENT_HIDDEN_STACK: 2
136
+ };
137
+ function ee({ children: o, wrapperId: e, renderMode: n = x.STACKED, wrapperStyle: c }) {
138
+ const u = y(null), r = y(/* @__PURE__ */ new Map()), [d, g] = E(r.current), l = Array.from(d.values()), a = Array.from(d.keys()), w = y(/* @__PURE__ */ new Map()), [h, N] = E(void 0), O = (t, s = Math.random().toString(36).substring(2, 6), i = !1) => {
139
+ if (a.indexOf(s) !== -1)
140
+ return console.warn(`Modal with id ${s} already exists. Choose a different id.`), s;
141
+ let _ = [t, i];
142
+ return r.current = new Map(r.current), r.current.set(s, _), g(new Map(r.current)), s;
143
+ }, m = (t) => {
144
+ let s = "";
145
+ if (typeof t != "string") {
146
+ for (let [i, v] of r.current.entries())
147
+ if (v[0] === t) {
148
+ s = i;
149
+ break;
150
+ }
151
+ } else typeof t == "string" && (s = t);
152
+ return r.current.has(s) ? (r.current = new Map(r.current), r.current.delete(s), g(new Map(r.current)), !0) : !1;
153
+ }, P = (t, s) => {
154
+ if (r.current.has(t)) {
155
+ let i = r.current.get(t);
156
+ if (i[1] === !1) {
157
+ console.warn(`Modal with id ${t} is dynamic. Cannot update content.`);
158
+ return;
159
+ }
160
+ i[0] = s, r.current.set(t, i), g(new Map(r.current));
161
+ }
162
+ }, B = (t) => {
163
+ if (!d.has(t)) return !1;
164
+ let s = r.current.get(t);
165
+ return r.current.delete(t), r.current.set(t, s), g(new Map(r.current)), !0;
166
+ }, F = (t) => a.indexOf(t), L = (t) => w.current.get(t);
167
+ R(() => {
168
+ const t = a[a.length - 1];
169
+ t !== void 0 ? (u.current?.showModal(), document.body.setAttribute("inert", "")) : t === void 0 && (u.current?.close(), document.body.removeAttribute("inert")), N(t);
170
+ }, [d]);
171
+ const b = e || "base-modal-wrapper", p = K((t, s) => {
172
+ t ? w.current.set(s, t) : w.current.delete(s);
173
+ }, []), W = () => {
174
+ switch (n) {
175
+ case x.STACKED:
176
+ return l.map(([t, s], i) => /* @__PURE__ */ f(
177
+ "div",
178
+ {
179
+ ref: (v) => p(v, a[i]),
180
+ className: "modal-window",
181
+ id: a[i],
182
+ style: { display: "block", zIndex: a[i] === h ? 1e3 : 100 },
183
+ ...h !== a[i] ? { inert: "" } : {},
184
+ children: s ? null : t
185
+ },
186
+ a[i]
187
+ ));
188
+ case x.CURRENT_ONLY:
189
+ return l.length > 0 ? /* @__PURE__ */ f(
190
+ "div",
191
+ {
192
+ id: a[l.length - 1],
193
+ ref: (t) => p(t, a[l.length - 1]),
194
+ className: "modal-window",
195
+ style: { display: "block" },
196
+ children: l[l.length - 1][1] ? null : l[l.length - 1][0]
197
+ },
198
+ a[l.length - 1]
199
+ ) : null;
200
+ case x.CURRENT_HIDDEN_STACK:
201
+ return l.length > 0 ? l.map(([t, s], i) => /* @__PURE__ */ f(
202
+ "div",
203
+ {
204
+ ref: (v) => p(v, a[i]),
205
+ id: a[i],
206
+ className: "modal-window",
207
+ style: {
208
+ display: h === a[i] ? "block" : "none"
209
+ },
210
+ ...h !== a[i] ? { inert: "" } : {},
211
+ children: s ? null : t
212
+ },
213
+ a[i]
214
+ )) : null;
215
+ }
216
+ };
217
+ return /* @__PURE__ */ S(A.Provider, { value: { modalCount: 0, get renderMode() {
218
+ return n;
219
+ }, pushModal: O, popModal: m, currentModalId: h, updateModalContent: P, getModalWindowRef: L, focusModal: B, getModalOrderIndex: F }, children: [
220
+ o,
221
+ a.length === 0 ? null : D(
222
+ /* @__PURE__ */ S($, { children: [
223
+ /* @__PURE__ */ f("style", { children: `
224
+ dialog#${b}[open] {
225
+ display: flex !important;
226
+ justify-content: center;
227
+ align-items: center;
228
+ width: 100vw;
229
+ height: 100vh;
230
+ max-width: 100%;
231
+ max-height: 100%;
232
+ }
233
+ body:has(dialog#${b}[open]) {
234
+ overflow: hidden;
235
+ }
236
+ body {
237
+ scrollbar-gutter: stable;
238
+ }
239
+ .modal-wrapper{
240
+ border: none;
241
+ padding: 0;
242
+ background: unset;
243
+ }
244
+ .modal-window {
245
+ position: absolute;
246
+ width: 100%;
247
+ height: 100%;
248
+ display: none;
249
+ background-color: rgba(0, 0, 0, 0.1);
250
+ backdrop-filter: blur(2px);
251
+ }
252
+ ` }),
253
+ /* @__PURE__ */ f(
254
+ "dialog",
255
+ {
256
+ className: "modal-wrapper",
257
+ ref: u,
258
+ id: b,
259
+ style: c,
260
+ children: W()
261
+ }
262
+ )
263
+ ] }),
264
+ document.body
265
+ )
266
+ ] });
267
+ }
268
+ function te() {
269
+ const o = k(A);
270
+ if (!o) throw new Error("useBaseModal must be used within a BaseModalProvider");
271
+ return o;
272
+ }
273
+ function ne(o = Math.random().toString(36).substring(2, 6)) {
274
+ const e = k(A);
275
+ if (!e) throw new Error("useBaseModal must be used within a BaseModalProvider");
276
+ let n = y(o);
277
+ const c = (d) => (e.pushModal(d, n.current), u), u = () => e.popModal(n.current), r = (d) => {
278
+ e.updateModalContent(n.current, d);
279
+ };
280
+ return [c, u, n.current, e.currentModalId === n.current, r];
281
+ }
282
+ function re(o = Math.random().toString(36).substring(2, 6)) {
283
+ const e = k(A);
284
+ if (!e) throw new Error("useBaseModal must be used within a BaseModalProvider");
285
+ let n = y(o);
286
+ const c = e.currentModalId === n.current;
287
+ return [(l) => e.getModalWindowRef(n.current) ? D(
288
+ l,
289
+ e.getModalWindowRef(n.current)
290
+ ) : null, () => {
291
+ e.pushModal(null, n.current, !0)[1];
292
+ }, () => {
293
+ e.popModal(n.current);
294
+ }, () => {
295
+ e.focusModal(n.current);
296
+ }, n.current, c];
297
+ }
298
+ export {
299
+ M as AnimationType,
300
+ ee as BaseModalProvider,
301
+ Q as Button,
302
+ Z as Loading,
303
+ X as LoadingProvider,
304
+ x as RenderMode,
305
+ te as useBaseModal,
306
+ re as useDynamicModal,
307
+ V as useLoading,
308
+ ne as useStaticModal
309
+ };
package/package.json ADDED
@@ -0,0 +1,63 @@
1
+ {
2
+ "name": "roks-rjsc",
3
+ "version": "0.1.0",
4
+ "description": "A React component library",
5
+ "main": "dist/index.cjs.js",
6
+ "module": "dist/index.esm.js",
7
+ "types": "dist/index.d.ts",
8
+ "files": [
9
+ "dist",
10
+ "README.md"
11
+ ],
12
+ "scripts": {
13
+ "build": "vite build",
14
+ "prepare": "npm run build",
15
+ "dev": "vite",
16
+ "preview": "vite preview",
17
+ "test": "vitest"
18
+ },
19
+ "peerDependencies": {
20
+ "react": "^18.0.0",
21
+ "react-dom": "^18.0.0"
22
+ },
23
+ "devDependencies": {
24
+ "@testing-library/jest-dom": "^6.0.0",
25
+ "@testing-library/react": "^14.0.0",
26
+ "@types/jest": "^30.0.0",
27
+ "@types/react": "^18.0.0",
28
+ "@types/react-dom": "^18.0.0",
29
+ "@vitejs/plugin-react": "^5.0.4",
30
+ "jsdom": "^27.4.0",
31
+ "typescript": "^5.0.0",
32
+ "vite": "^7.1.9",
33
+ "vite-plugin-dts": "^4.5.4",
34
+ "vitest": "^1.0.0"
35
+ },
36
+ "sideEffects": false,
37
+ "publishConfig": {
38
+ "access": "public"
39
+ },
40
+ "repository": {
41
+ "type": "git",
42
+ "url": "https://github.com/rokku-x/roks-rjsc.git"
43
+ },
44
+ "bugs": {
45
+ "url": "https://github.com/rokku-x/roks-rjsc/issues"
46
+ },
47
+ "homepage": "https://github.com/rokku-x/roks-rjsc#readme",
48
+ "exports": {
49
+ ".": {
50
+ "types": "./dist/index.d.ts",
51
+ "import": "./dist/index.esm.js",
52
+ "require": "./dist/index.cjs.js"
53
+ },
54
+ "./package.json": "./package.json"
55
+ },
56
+ "keywords": [
57
+ "react",
58
+ "component",
59
+ "library"
60
+ ],
61
+ "author": "rokku",
62
+ "license": "MIT"
63
+ }