react-wip-ui 1.0.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/README.md ADDED
@@ -0,0 +1,155 @@
1
+ # react-wip-ui
2
+
3
+ Production-ready UI components for marking features as "Work In Progress" (WIP). Designed for modern React ecosystems and compatible with Next.js App Router.
4
+
5
+ ## Features
6
+
7
+ - Beautiful default theme with a warm minimal visual style.
8
+ - Server-friendly visual components for `Ribbon`, `Badge`, `Overlay`, and `Block`.
9
+ - Separate client entry for `WIP`, `Modal`, `Banner`, `WIPProvider`, and `useWIP`.
10
+ - Lightweight with a single bundled stylesheet.
11
+ - Accessible basics including Escape handling, dialog semantics, and ARIA labels.
12
+
13
+ ## Installation
14
+
15
+ ```bash
16
+ npm install react-wip-ui
17
+ ```
18
+
19
+ This package expects `react` and `react-dom` as peer dependencies.
20
+
21
+ ## Setup
22
+
23
+ Import the stylesheet once near the root of your app:
24
+
25
+ ```tsx
26
+ import 'react-wip-ui/styles.css';
27
+ ```
28
+
29
+ Server-friendly visual components can be imported from the root package:
30
+
31
+ ```tsx
32
+ import { Badge, Ribbon, Overlay, Block } from 'react-wip-ui';
33
+ ```
34
+
35
+ Interactive and stateful exports live under the client entry:
36
+
37
+ ```tsx
38
+ "use client";
39
+
40
+ import { WIP, WIPProvider, Modal, Banner, useWIP } from 'react-wip-ui/client';
41
+ ```
42
+
43
+ ## Global Configuration
44
+
45
+ Wrap your app with `<WIPProvider>` if you want to change the default variant, theme, or disable all WIP UI globally.
46
+
47
+ ```tsx
48
+ import { WIP, WIPProvider } from 'react-wip-ui/client';
49
+
50
+ function App({ children }) {
51
+ return (
52
+ <WIPProvider theme="light" defaultVariant="overlay" globalDisabled={false}>
53
+ {children}
54
+ </WIPProvider>
55
+ );
56
+ }
57
+ ```
58
+
59
+ ## Root Components
60
+
61
+ ### Ribbon
62
+
63
+ ```tsx
64
+ import { Ribbon } from 'react-wip-ui';
65
+
66
+ <Ribbon position="top-right" text="BETA" variant="outline" />
67
+ ```
68
+
69
+ ### Overlay
70
+
71
+ ```tsx
72
+ import { Overlay } from 'react-wip-ui';
73
+
74
+ <Overlay message="Coming Soon">
75
+ <BillingSection />
76
+ </Overlay>
77
+ ```
78
+
79
+ ### Badge
80
+
81
+ ```tsx
82
+ import { Badge } from 'react-wip-ui';
83
+
84
+ <Badge>
85
+ <button disabled>Pro Feature</button>
86
+ </Badge>
87
+ ```
88
+
89
+ ### Block
90
+
91
+ ```tsx
92
+ import { Block } from 'react-wip-ui';
93
+
94
+ <Block>
95
+ <SubscriptionForm />
96
+ </Block>
97
+ ```
98
+
99
+ ## Client Components
100
+
101
+ ### WIP Wrapper
102
+
103
+ ```tsx
104
+ "use client";
105
+
106
+ import { WIP } from 'react-wip-ui/client';
107
+
108
+ <WIP when={isFeaturePending}>
109
+ <NewDashboard />
110
+ </WIP>
111
+ ```
112
+
113
+ ### Modal
114
+
115
+ ```tsx
116
+ "use client";
117
+
118
+ import { Modal } from 'react-wip-ui/client';
119
+
120
+ <Modal
121
+ isOpen={showModal}
122
+ onClose={() => setShowModal(false)}
123
+ title="Feature Under Construction"
124
+ description="This module is not ready yet."
125
+ />
126
+ ```
127
+
128
+ ### Banner
129
+
130
+ ```tsx
131
+ "use client";
132
+
133
+ import { Banner } from 'react-wip-ui/client';
134
+
135
+ <Banner message="Our store is currently under maintenance." dismissible />
136
+ ```
137
+
138
+ ## Programmatic Control
139
+
140
+ The `useWIP()` hook reads the current config. Without a provider, it falls back to the built-in defaults.
141
+
142
+ ```tsx
143
+ "use client";
144
+
145
+ import { useWIP } from 'react-wip-ui/client';
146
+
147
+ function CheckStatus() {
148
+ const { globalDisabled, theme } = useWIP();
149
+ return <div>Active Theme: {theme}</div>;
150
+ }
151
+ ```
152
+
153
+ ## License
154
+
155
+ MIT
@@ -0,0 +1,67 @@
1
+ import { Construction } from 'lucide-react';
2
+ import { jsx, Fragment, jsxs } from 'react/jsx-runtime';
3
+
4
+ // src/components/Overlay.tsx
5
+ var Overlay = ({
6
+ children,
7
+ message = "Under Construction",
8
+ className = "",
9
+ disabled = false,
10
+ ...props
11
+ }) => {
12
+ if (disabled) {
13
+ return /* @__PURE__ */ jsx(Fragment, { children });
14
+ }
15
+ return /* @__PURE__ */ jsxs("div", { className: `rwip-overlay-container ${className}`, ...props, children: [
16
+ children,
17
+ /* @__PURE__ */ jsx("div", { className: "rwip-overlay", "aria-hidden": "true", children: /* @__PURE__ */ jsxs("div", { className: "rwip-overlay-message", children: [
18
+ /* @__PURE__ */ jsx(Construction, { size: 18 }),
19
+ /* @__PURE__ */ jsx("span", { children: message })
20
+ ] }) })
21
+ ] });
22
+ };
23
+ var Block = ({
24
+ children,
25
+ className = "",
26
+ disabled = false,
27
+ ...props
28
+ }) => {
29
+ if (disabled) {
30
+ return /* @__PURE__ */ jsx(Fragment, { children });
31
+ }
32
+ return /* @__PURE__ */ jsx("div", { className: `rwip-block ${className}`, "aria-disabled": "true", ...props, children });
33
+ };
34
+ var Badge = ({
35
+ text = "WIP",
36
+ className = "",
37
+ disabled = false,
38
+ ...props
39
+ }) => {
40
+ if (disabled) return null;
41
+ return /* @__PURE__ */ jsxs("span", { className: "rwip-badge-wrapper", title: "Work in Progress", children: [
42
+ props.children,
43
+ /* @__PURE__ */ jsx("span", { className: `rwip-badge ${className}`, ...props, children: text })
44
+ ] });
45
+ };
46
+ var Ribbon = ({
47
+ position = "top-right",
48
+ text = "WIP",
49
+ variant = "solid",
50
+ className = "",
51
+ disabled = false,
52
+ ...props
53
+ }) => {
54
+ if (disabled) return null;
55
+ return /* @__PURE__ */ jsx("div", { className: "rwip-ribbon-container", children: /* @__PURE__ */ jsx(
56
+ "div",
57
+ {
58
+ className: `rwip-ribbon ${position} ${variant} ${className}`,
59
+ ...props,
60
+ children: text
61
+ }
62
+ ) });
63
+ };
64
+
65
+ export { Badge, Block, Overlay, Ribbon };
66
+ //# sourceMappingURL=chunk-46OHJMTB.mjs.map
67
+ //# sourceMappingURL=chunk-46OHJMTB.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/components/Overlay.tsx","../src/components/Block.tsx","../src/components/Badge.tsx","../src/components/Ribbon.tsx"],"names":["jsx","Fragment","jsxs"],"mappings":";;;;AASO,IAAM,UAAkC,CAAC;AAAA,EAC9C,QAAA;AAAA,EACA,OAAA,GAAU,oBAAA;AAAA,EACV,SAAA,GAAY,EAAA;AAAA,EACZ,QAAA,GAAW,KAAA;AAAA,EACX,GAAG;AACL,CAAA,KAAM;AACJ,EAAA,IAAI,QAAA,EAAU;AACZ,IAAA,uCAAU,QAAA,EAAS,CAAA;AAAA,EACrB;AAEA,EAAA,4BACG,KAAA,EAAA,EAAI,SAAA,EAAW,0BAA0B,SAAS,CAAA,CAAA,EAAK,GAAG,KAAA,EACxD,QAAA,EAAA;AAAA,IAAA,QAAA;AAAA,oBACD,GAAA,CAAC,SAAI,SAAA,EAAU,cAAA,EAAe,eAAY,MAAA,EACxC,QAAA,kBAAA,IAAA,CAAC,KAAA,EAAA,EAAI,SAAA,EAAU,sBAAA,EACb,QAAA,EAAA;AAAA,sBAAA,GAAA,CAAC,YAAA,EAAA,EAAa,MAAM,EAAA,EAAI,CAAA;AAAA,sBACxB,GAAA,CAAC,UAAM,QAAA,EAAA,OAAA,EAAQ;AAAA,KAAA,EACjB,CAAA,EACF;AAAA,GAAA,EACF,CAAA;AAEJ;ACxBO,IAAM,QAA8B,CAAC;AAAA,EAC1C,QAAA;AAAA,EACA,SAAA,GAAY,EAAA;AAAA,EACZ,QAAA,GAAW,KAAA;AAAA,EACX,GAAG;AACL,CAAA,KAAM;AACJ,EAAA,IAAI,QAAA,EAAU;AACZ,IAAA,uBAAOA,GAAAA,CAAAC,QAAAA,EAAA,EAAG,QAAA,EAAS,CAAA;AAAA,EACrB;AAEA,EAAA,uBACED,GAAAA,CAAC,KAAA,EAAA,EAAI,SAAA,EAAW,CAAA,WAAA,EAAc,SAAS,CAAA,CAAA,EAAI,eAAA,EAAc,MAAA,EAAQ,GAAG,KAAA,EACjE,QAAA,EACH,CAAA;AAEJ;ACdO,IAAM,QAA8B,CAAC;AAAA,EAC1C,IAAA,GAAO,KAAA;AAAA,EACP,SAAA,GAAY,EAAA;AAAA,EACZ,QAAA,GAAW,KAAA;AAAA,EACX,GAAG;AACL,CAAA,KAAM;AACJ,EAAA,IAAI,UAAU,OAAO,IAAA;AAErB,EAAA,uBACEE,IAAAA,CAAC,MAAA,EAAA,EAAK,SAAA,EAAU,oBAAA,EAAqB,OAAM,kBAAA,EACxC,QAAA,EAAA;AAAA,IAAA,KAAA,CAAM,QAAA;AAAA,oBACPF,IAAC,MAAA,EAAA,EAAK,SAAA,EAAW,cAAc,SAAS,CAAA,CAAA,EAAK,GAAG,KAAA,EAC7C,QAAA,EAAA,IAAA,EACH;AAAA,GAAA,EACF,CAAA;AAEJ;ACdO,IAAM,SAAgC,CAAC;AAAA,EAC5C,QAAA,GAAW,WAAA;AAAA,EACX,IAAA,GAAO,KAAA;AAAA,EACP,OAAA,GAAU,OAAA;AAAA,EACV,SAAA,GAAY,EAAA;AAAA,EACZ,QAAA,GAAW,KAAA;AAAA,EACX,GAAG;AACL,CAAA,KAAM;AACJ,EAAA,IAAI,UAAU,OAAO,IAAA;AAErB,EAAA,uBACEA,GAAAA,CAAC,KAAA,EAAA,EAAI,SAAA,EAAU,yBACb,QAAA,kBAAAA,GAAAA;AAAA,IAAC,KAAA;AAAA,IAAA;AAAA,MACC,WAAW,CAAA,YAAA,EAAe,QAAQ,CAAA,CAAA,EAAI,OAAO,IAAI,SAAS,CAAA,CAAA;AAAA,MACzD,GAAG,KAAA;AAAA,MAEH,QAAA,EAAA;AAAA;AAAA,GACH,EACF,CAAA;AAEJ","file":"chunk-46OHJMTB.mjs","sourcesContent":["import React, { HTMLAttributes } from 'react';\nimport { Construction } from 'lucide-react';\n\nexport interface OverlayProps extends HTMLAttributes<HTMLDivElement> {\n message?: string;\n className?: string;\n disabled?: boolean;\n}\n\nexport const Overlay: React.FC<OverlayProps> = ({ \n children, \n message = 'Under Construction', \n className = '',\n disabled = false,\n ...props \n}) => {\n if (disabled) {\n return <>{children}</>;\n }\n\n return (\n <div className={`rwip-overlay-container ${className}`} {...props}>\n {children}\n <div className=\"rwip-overlay\" aria-hidden=\"true\">\n <div className=\"rwip-overlay-message\">\n <Construction size={18} />\n <span>{message}</span>\n </div>\n </div>\n </div>\n );\n};\n","import React, { HTMLAttributes } from 'react';\n\nexport interface BlockProps extends HTMLAttributes<HTMLDivElement> {\n className?: string;\n disabled?: boolean;\n}\n\nexport const Block: React.FC<BlockProps> = ({ \n children, \n className = '',\n disabled = false,\n ...props \n}) => {\n if (disabled) {\n return <>{children}</>;\n }\n\n return (\n <div className={`rwip-block ${className}`} aria-disabled=\"true\" {...props}>\n {children}\n </div>\n );\n};\n","import React, { HTMLAttributes } from 'react';\n\nexport interface BadgeProps extends HTMLAttributes<HTMLSpanElement> {\n text?: string;\n className?: string;\n disabled?: boolean;\n}\n\nexport const Badge: React.FC<BadgeProps> = ({ \n text = 'WIP', \n className = '',\n disabled = false,\n ...props \n}) => {\n if (disabled) return null;\n\n return (\n <span className=\"rwip-badge-wrapper\" title=\"Work in Progress\">\n {props.children}\n <span className={`rwip-badge ${className}`} {...props}>\n {text}\n </span>\n </span>\n );\n};\n","import React, { HTMLAttributes } from 'react';\n\nexport interface RibbonProps extends HTMLAttributes<HTMLDivElement> {\n position?: 'top-left' | 'top-right';\n text?: string;\n variant?: 'solid' | 'outline';\n className?: string;\n disabled?: boolean;\n}\n\nexport const Ribbon: React.FC<RibbonProps> = ({ \n position = 'top-right', \n text = 'WIP', \n variant = 'solid',\n className = '',\n disabled = false,\n ...props \n}) => {\n if (disabled) return null;\n\n return (\n <div className=\"rwip-ribbon-container\">\n <div \n className={`rwip-ribbon ${position} ${variant} ${className}`} \n {...props}\n >\n {text}\n </div>\n </div>\n );\n};\n"]}
@@ -0,0 +1,27 @@
1
+ import { Badge } from './components/Badge';
2
+ import { Ribbon } from './components/Ribbon';
3
+ import { Overlay } from './components/Overlay';
4
+ import { Block } from './components/Block';
5
+ import { Modal } from './components/Modal';
6
+ import { Banner } from './components/Banner';
7
+ import { WIPProvider } from './provider/WIPProvider';
8
+ import { useWIP } from './hooks/useWIP';
9
+ export declare const WIP: import("react").FC<import("./components/WIPWrapper").WIPWrapperProps> & {
10
+ Badge: import("react").FC<import("./components/Badge").BadgeProps>;
11
+ Ribbon: import("react").FC<import("./components/Ribbon").RibbonProps>;
12
+ Overlay: import("react").FC<import("./components/Overlay").OverlayProps>;
13
+ Block: import("react").FC<import("./components/Block").BlockProps>;
14
+ Modal: import("react").FC<import("./components/Modal").ModalProps>;
15
+ Banner: import("react").FC<import("./components/Banner").BannerProps>;
16
+ Provider: typeof WIPProvider;
17
+ };
18
+ export { Badge, Ribbon, Overlay, Block, Modal, Banner, WIPProvider, useWIP, };
19
+ export type { WIPConfig, WIPTheme, WIPVariant } from './provider/WIPProvider';
20
+ export type { BadgeProps } from './components/Badge';
21
+ export type { RibbonProps } from './components/Ribbon';
22
+ export type { OverlayProps } from './components/Overlay';
23
+ export type { BlockProps } from './components/Block';
24
+ export type { ModalProps } from './components/Modal';
25
+ export type { BannerProps } from './components/Banner';
26
+ export type { WIPWrapperProps } from './components/WIPWrapper';
27
+ //# sourceMappingURL=client.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../src/client.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,KAAK,EAAE,MAAM,oBAAoB,CAAC;AAC3C,OAAO,EAAE,MAAM,EAAE,MAAM,qBAAqB,CAAC;AAC7C,OAAO,EAAE,OAAO,EAAE,MAAM,sBAAsB,CAAC;AAC/C,OAAO,EAAE,KAAK,EAAE,MAAM,oBAAoB,CAAC;AAC3C,OAAO,EAAE,KAAK,EAAE,MAAM,oBAAoB,CAAC;AAC3C,OAAO,EAAE,MAAM,EAAE,MAAM,qBAAqB,CAAC;AAC7C,OAAO,EAAE,WAAW,EAAE,MAAM,wBAAwB,CAAC;AACrD,OAAO,EAAE,MAAM,EAAE,MAAM,gBAAgB,CAAC;AAExC,eAAO,MAAM,GAAG;;;;;;;;CAQd,CAAC;AAEH,OAAO,EACL,KAAK,EACL,MAAM,EACN,OAAO,EACP,KAAK,EACL,KAAK,EACL,MAAM,EACN,WAAW,EACX,MAAM,GACP,CAAC;AAEF,YAAY,EAAE,SAAS,EAAE,QAAQ,EAAE,UAAU,EAAE,MAAM,wBAAwB,CAAC;AAC9E,YAAY,EAAE,UAAU,EAAE,MAAM,oBAAoB,CAAC;AACrD,YAAY,EAAE,WAAW,EAAE,MAAM,qBAAqB,CAAC;AACvD,YAAY,EAAE,YAAY,EAAE,MAAM,sBAAsB,CAAC;AACzD,YAAY,EAAE,UAAU,EAAE,MAAM,oBAAoB,CAAC;AACrD,YAAY,EAAE,UAAU,EAAE,MAAM,oBAAoB,CAAC;AACrD,YAAY,EAAE,WAAW,EAAE,MAAM,qBAAqB,CAAC;AACvD,YAAY,EAAE,eAAe,EAAE,MAAM,yBAAyB,CAAC"}
package/dist/client.js ADDED
@@ -0,0 +1,235 @@
1
+ "use client";
2
+ 'use strict';
3
+
4
+ var React = require('react');
5
+ var jsxRuntime = require('react/jsx-runtime');
6
+ var lucideReact = require('lucide-react');
7
+ var reactDom = require('react-dom');
8
+
9
+ function _interopDefault (e) { return e && e.__esModule ? e : { default: e }; }
10
+
11
+ var React__default = /*#__PURE__*/_interopDefault(React);
12
+
13
+ var defaultContext = {
14
+ theme: "light",
15
+ defaultVariant: "badge",
16
+ globalDisabled: false
17
+ };
18
+ var WIPContext = React.createContext(defaultContext);
19
+ function WIPProvider({
20
+ children,
21
+ theme = "light",
22
+ defaultVariant = "badge",
23
+ globalDisabled = false
24
+ }) {
25
+ const value = React__default.default.useMemo(
26
+ () => ({ theme, defaultVariant, globalDisabled }),
27
+ [theme, defaultVariant, globalDisabled]
28
+ );
29
+ return /* @__PURE__ */ jsxRuntime.jsx(WIPContext.Provider, { value, children: /* @__PURE__ */ jsxRuntime.jsx(
30
+ "div",
31
+ {
32
+ className: "rwip-base",
33
+ "data-rwip-theme": theme === "dark" ? "dark" : "light",
34
+ style: { display: "contents" },
35
+ children
36
+ }
37
+ ) });
38
+ }
39
+
40
+ // src/hooks/useWIP.ts
41
+ function useWIP() {
42
+ return React.useContext(WIPContext);
43
+ }
44
+ var Overlay = ({
45
+ children,
46
+ message = "Under Construction",
47
+ className = "",
48
+ disabled = false,
49
+ ...props
50
+ }) => {
51
+ if (disabled) {
52
+ return /* @__PURE__ */ jsxRuntime.jsx(jsxRuntime.Fragment, { children });
53
+ }
54
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: `rwip-overlay-container ${className}`, ...props, children: [
55
+ children,
56
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "rwip-overlay", "aria-hidden": "true", children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "rwip-overlay-message", children: [
57
+ /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Construction, { size: 18 }),
58
+ /* @__PURE__ */ jsxRuntime.jsx("span", { children: message })
59
+ ] }) })
60
+ ] });
61
+ };
62
+ var Block = ({
63
+ children,
64
+ className = "",
65
+ disabled = false,
66
+ ...props
67
+ }) => {
68
+ if (disabled) {
69
+ return /* @__PURE__ */ jsxRuntime.jsx(jsxRuntime.Fragment, { children });
70
+ }
71
+ return /* @__PURE__ */ jsxRuntime.jsx("div", { className: `rwip-block ${className}`, "aria-disabled": "true", ...props, children });
72
+ };
73
+ var Badge = ({
74
+ text = "WIP",
75
+ className = "",
76
+ disabled = false,
77
+ ...props
78
+ }) => {
79
+ if (disabled) return null;
80
+ return /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "rwip-badge-wrapper", title: "Work in Progress", children: [
81
+ props.children,
82
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: `rwip-badge ${className}`, ...props, children: text })
83
+ ] });
84
+ };
85
+ var WIPWrapper = ({ children, when = true }) => {
86
+ const { globalDisabled, defaultVariant } = useWIP();
87
+ if (globalDisabled || !when) {
88
+ return /* @__PURE__ */ jsxRuntime.jsx(jsxRuntime.Fragment, { children });
89
+ }
90
+ switch (defaultVariant) {
91
+ case "overlay":
92
+ return /* @__PURE__ */ jsxRuntime.jsx(Overlay, { children });
93
+ case "block":
94
+ return /* @__PURE__ */ jsxRuntime.jsx(Block, { children });
95
+ case "badge":
96
+ return /* @__PURE__ */ jsxRuntime.jsx(Badge, { children });
97
+ case "hidden":
98
+ return null;
99
+ default:
100
+ return /* @__PURE__ */ jsxRuntime.jsx(Block, { children });
101
+ }
102
+ };
103
+ var Ribbon = ({
104
+ position = "top-right",
105
+ text = "WIP",
106
+ variant = "solid",
107
+ className = "",
108
+ disabled = false,
109
+ ...props
110
+ }) => {
111
+ if (disabled) return null;
112
+ return /* @__PURE__ */ jsxRuntime.jsx("div", { className: "rwip-ribbon-container", children: /* @__PURE__ */ jsxRuntime.jsx(
113
+ "div",
114
+ {
115
+ className: `rwip-ribbon ${position} ${variant} ${className}`,
116
+ ...props,
117
+ children: text
118
+ }
119
+ ) });
120
+ };
121
+
122
+ // src/utils/ssr.ts
123
+ var isClient = typeof window !== "undefined" && typeof document !== "undefined";
124
+ var Modal = ({
125
+ isOpen,
126
+ onClose,
127
+ title = "Feature Under Construction",
128
+ description = "This feature is currently being developed and is not yet available.",
129
+ className = "",
130
+ ...props
131
+ }) => {
132
+ const { globalDisabled } = useWIP();
133
+ const [mounted, setMounted] = React.useState(false);
134
+ const titleId = React.useId();
135
+ React.useEffect(() => {
136
+ setMounted(true);
137
+ }, []);
138
+ React.useEffect(() => {
139
+ if (isOpen) {
140
+ const handleEsc = (e) => {
141
+ if (e.key === "Escape") onClose();
142
+ };
143
+ window.addEventListener("keydown", handleEsc);
144
+ return () => window.removeEventListener("keydown", handleEsc);
145
+ }
146
+ }, [isOpen, onClose]);
147
+ if (globalDisabled || !isOpen || !mounted || !isClient) return null;
148
+ return reactDom.createPortal(
149
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "rwip-modal-backdrop", onClick: onClose, children: /* @__PURE__ */ jsxRuntime.jsxs(
150
+ "div",
151
+ {
152
+ className: `rwip-modal ${className}`,
153
+ onClick: (e) => e.stopPropagation(),
154
+ role: "dialog",
155
+ "aria-modal": "true",
156
+ "aria-labelledby": titleId,
157
+ ...props,
158
+ children: [
159
+ /* @__PURE__ */ jsxRuntime.jsx(
160
+ "button",
161
+ {
162
+ className: "rwip-modal-close",
163
+ onClick: onClose,
164
+ "aria-label": "Close",
165
+ children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.X, { size: 20 })
166
+ }
167
+ ),
168
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { style: { display: "flex", gap: "12px", alignItems: "flex-start" }, children: [
169
+ /* @__PURE__ */ jsxRuntime.jsx(lucideReact.AlertCircle, { size: 24, style: { color: "var(--rwip-color-primary)", flexShrink: 0, marginTop: "2px" } }),
170
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
171
+ /* @__PURE__ */ jsxRuntime.jsx("h2", { id: titleId, className: "rwip-modal-title", children: title }),
172
+ /* @__PURE__ */ jsxRuntime.jsx("p", { className: "rwip-modal-desc", children: description })
173
+ ] })
174
+ ] })
175
+ ]
176
+ }
177
+ ) }),
178
+ document.body
179
+ );
180
+ };
181
+ var Banner = ({
182
+ message = "Parts of this application are currently under construction.",
183
+ dismissible = true,
184
+ position = "sticky",
185
+ className = "",
186
+ ...props
187
+ }) => {
188
+ const { globalDisabled } = useWIP();
189
+ const [isVisible, setIsVisible] = React.useState(true);
190
+ if (globalDisabled || !isVisible) return null;
191
+ return /* @__PURE__ */ jsxRuntime.jsxs(
192
+ "div",
193
+ {
194
+ className: `rwip-banner ${position === "sticky" ? "sticky" : ""} ${className}`,
195
+ role: "alert",
196
+ ...props,
197
+ children: [
198
+ /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Info, { size: 16 }),
199
+ /* @__PURE__ */ jsxRuntime.jsx("span", { children: message }),
200
+ dismissible && /* @__PURE__ */ jsxRuntime.jsx(
201
+ "button",
202
+ {
203
+ className: "rwip-banner-close",
204
+ onClick: () => setIsVisible(false),
205
+ "aria-label": "Dismiss banner",
206
+ children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.X, { size: 16 })
207
+ }
208
+ )
209
+ ]
210
+ }
211
+ );
212
+ };
213
+
214
+ // src/client.ts
215
+ var WIP = Object.assign(WIPWrapper, {
216
+ Badge,
217
+ Ribbon,
218
+ Overlay,
219
+ Block,
220
+ Modal,
221
+ Banner,
222
+ Provider: WIPProvider
223
+ });
224
+
225
+ exports.Badge = Badge;
226
+ exports.Banner = Banner;
227
+ exports.Block = Block;
228
+ exports.Modal = Modal;
229
+ exports.Overlay = Overlay;
230
+ exports.Ribbon = Ribbon;
231
+ exports.WIP = WIP;
232
+ exports.WIPProvider = WIPProvider;
233
+ exports.useWIP = useWIP;
234
+ //# sourceMappingURL=client.js.map
235
+ //# sourceMappingURL=client.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/provider/WIPProvider.tsx","../src/hooks/useWIP.ts","../src/components/Overlay.tsx","../src/components/Block.tsx","../src/components/Badge.tsx","../src/components/WIPWrapper.tsx","../src/components/Ribbon.tsx","../src/utils/ssr.ts","../src/components/Modal.tsx","../src/components/Banner.tsx","../src/client.ts"],"names":["createContext","React","jsx","useContext","Fragment","jsxs","Construction","useState","useId","useEffect","createPortal","X","AlertCircle","Info"],"mappings":"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","file":"client.js","sourcesContent":["\"use client\";\n\nimport React, { createContext, ReactNode } from 'react';\n\nexport type WIPTheme = 'light' | 'dark' | 'system';\nexport type WIPVariant = 'overlay' | 'badge' | 'block' | 'hidden';\n\nexport interface WIPConfig {\n theme: WIPTheme;\n defaultVariant: WIPVariant;\n globalDisabled: boolean;\n}\n\nconst defaultContext: WIPConfig = {\n theme: 'light',\n defaultVariant: 'badge',\n globalDisabled: false,\n};\n\nexport const WIPContext = createContext<WIPConfig>(defaultContext);\n\nexport interface WIPProviderProps {\n children: ReactNode;\n theme?: WIPTheme;\n defaultVariant?: WIPVariant;\n /** Disable all WIP components globally (e.g. for production override) */\n globalDisabled?: boolean;\n}\n\nexport function WIPProvider({\n children,\n theme = 'light',\n defaultVariant = 'badge',\n globalDisabled = false,\n}: WIPProviderProps) {\n const value = React.useMemo(\n () => ({ theme, defaultVariant, globalDisabled }),\n [theme, defaultVariant, globalDisabled]\n );\n\n return (\n <WIPContext.Provider value={value}>\n <div \n className=\"rwip-base\" \n data-rwip-theme={theme === 'dark' ? 'dark' : 'light'} \n style={{ display: 'contents' }}\n >\n {children}\n </div>\n </WIPContext.Provider>\n );\n}\n","import { useContext } from 'react';\nimport { WIPContext, WIPConfig } from '../provider/WIPProvider';\n\nexport function useWIP(): WIPConfig {\n return useContext(WIPContext);\n}\n","import React, { HTMLAttributes } from 'react';\nimport { Construction } from 'lucide-react';\n\nexport interface OverlayProps extends HTMLAttributes<HTMLDivElement> {\n message?: string;\n className?: string;\n disabled?: boolean;\n}\n\nexport const Overlay: React.FC<OverlayProps> = ({ \n children, \n message = 'Under Construction', \n className = '',\n disabled = false,\n ...props \n}) => {\n if (disabled) {\n return <>{children}</>;\n }\n\n return (\n <div className={`rwip-overlay-container ${className}`} {...props}>\n {children}\n <div className=\"rwip-overlay\" aria-hidden=\"true\">\n <div className=\"rwip-overlay-message\">\n <Construction size={18} />\n <span>{message}</span>\n </div>\n </div>\n </div>\n );\n};\n","import React, { HTMLAttributes } from 'react';\n\nexport interface BlockProps extends HTMLAttributes<HTMLDivElement> {\n className?: string;\n disabled?: boolean;\n}\n\nexport const Block: React.FC<BlockProps> = ({ \n children, \n className = '',\n disabled = false,\n ...props \n}) => {\n if (disabled) {\n return <>{children}</>;\n }\n\n return (\n <div className={`rwip-block ${className}`} aria-disabled=\"true\" {...props}>\n {children}\n </div>\n );\n};\n","import React, { HTMLAttributes } from 'react';\n\nexport interface BadgeProps extends HTMLAttributes<HTMLSpanElement> {\n text?: string;\n className?: string;\n disabled?: boolean;\n}\n\nexport const Badge: React.FC<BadgeProps> = ({ \n text = 'WIP', \n className = '',\n disabled = false,\n ...props \n}) => {\n if (disabled) return null;\n\n return (\n <span className=\"rwip-badge-wrapper\" title=\"Work in Progress\">\n {props.children}\n <span className={`rwip-badge ${className}`} {...props}>\n {text}\n </span>\n </span>\n );\n};\n","import React from 'react';\nimport { useWIP } from '../hooks/useWIP';\nimport { Overlay } from './Overlay';\nimport { Block } from './Block';\nimport { Badge } from './Badge';\n\nexport interface WIPWrapperProps {\n children: React.ReactNode;\n when?: boolean;\n}\n\nexport const WIPWrapper: React.FC<WIPWrapperProps> = ({ children, when = true }) => {\n const { globalDisabled, defaultVariant } = useWIP();\n\n if (globalDisabled || !when) {\n return <>{children}</>;\n }\n\n switch (defaultVariant) {\n case 'overlay':\n return <Overlay>{children}</Overlay>;\n case 'block':\n return <Block>{children}</Block>;\n case 'badge':\n return <Badge>{children}</Badge>;\n case 'hidden':\n return null;\n default:\n return <Block>{children}</Block>;\n }\n};\n","import React, { HTMLAttributes } from 'react';\n\nexport interface RibbonProps extends HTMLAttributes<HTMLDivElement> {\n position?: 'top-left' | 'top-right';\n text?: string;\n variant?: 'solid' | 'outline';\n className?: string;\n disabled?: boolean;\n}\n\nexport const Ribbon: React.FC<RibbonProps> = ({ \n position = 'top-right', \n text = 'WIP', \n variant = 'solid',\n className = '',\n disabled = false,\n ...props \n}) => {\n if (disabled) return null;\n\n return (\n <div className=\"rwip-ribbon-container\">\n <div \n className={`rwip-ribbon ${position} ${variant} ${className}`} \n {...props}\n >\n {text}\n </div>\n </div>\n );\n};\n","export const isClient = typeof window !== 'undefined' && typeof document !== 'undefined';\n","\"use client\";\n\nimport React, { HTMLAttributes, useEffect, useId, useState } from 'react';\nimport { X, AlertCircle } from 'lucide-react';\nimport { useWIP } from '../hooks/useWIP';\nimport { isClient } from '../utils/ssr';\nimport { createPortal } from 'react-dom';\n\nexport interface ModalProps extends HTMLAttributes<HTMLDivElement> {\n isOpen: boolean;\n onClose: () => void;\n title?: string;\n description?: string;\n className?: string;\n}\n\nexport const Modal: React.FC<ModalProps> = ({ \n isOpen, \n onClose, \n title = 'Feature Under Construction', \n description = 'This feature is currently being developed and is not yet available.',\n className = '',\n ...props \n}) => {\n const { globalDisabled } = useWIP();\n const [mounted, setMounted] = useState(false);\n const titleId = useId();\n\n useEffect(() => {\n setMounted(true);\n }, []);\n\n useEffect(() => {\n if (isOpen) {\n const handleEsc = (e: KeyboardEvent) => {\n if (e.key === 'Escape') onClose();\n };\n window.addEventListener('keydown', handleEsc);\n return () => window.removeEventListener('keydown', handleEsc);\n }\n }, [isOpen, onClose]);\n\n if (globalDisabled || !isOpen || !mounted || !isClient) return null;\n\n return createPortal(\n <div className=\"rwip-modal-backdrop\" onClick={onClose}>\n <div \n className={`rwip-modal ${className}`} \n onClick={(e) => e.stopPropagation()}\n role=\"dialog\"\n aria-modal=\"true\"\n aria-labelledby={titleId}\n {...props}\n >\n <button \n className=\"rwip-modal-close\" \n onClick={onClose} \n aria-label=\"Close\"\n >\n <X size={20} />\n </button>\n <div style={{ display: 'flex', gap: '12px', alignItems: 'flex-start' }}>\n <AlertCircle size={24} style={{ color: 'var(--rwip-color-primary)', flexShrink: 0, marginTop: '2px' }} />\n <div>\n <h2 id={titleId} className=\"rwip-modal-title\">{title}</h2>\n <p className=\"rwip-modal-desc\">{description}</p>\n </div>\n </div>\n </div>\n </div>,\n document.body\n );\n};\n","\"use client\";\n\nimport React, { HTMLAttributes, useState } from 'react';\nimport { X, Info } from 'lucide-react';\nimport { useWIP } from '../hooks/useWIP';\n\nexport interface BannerProps extends HTMLAttributes<HTMLDivElement> {\n message?: string;\n dismissible?: boolean;\n position?: 'sticky' | 'relative';\n className?: string;\n}\n\nexport const Banner: React.FC<BannerProps> = ({ \n message = 'Parts of this application are currently under construction.', \n dismissible = true,\n position = 'sticky',\n className = '',\n ...props \n}) => {\n const { globalDisabled } = useWIP();\n const [isVisible, setIsVisible] = useState(true);\n\n if (globalDisabled || !isVisible) return null;\n\n return (\n <div \n className={`rwip-banner ${position === 'sticky' ? 'sticky' : ''} ${className}`} \n role=\"alert\"\n {...props}\n >\n <Info size={16} />\n <span>{message}</span>\n {dismissible && (\n <button \n className=\"rwip-banner-close\" \n onClick={() => setIsVisible(false)}\n aria-label=\"Dismiss banner\"\n >\n <X size={16} />\n </button>\n )}\n </div>\n );\n};\n","\"use client\";\n\nimport { WIPWrapper } from './components/WIPWrapper';\nimport { Badge } from './components/Badge';\nimport { Ribbon } from './components/Ribbon';\nimport { Overlay } from './components/Overlay';\nimport { Block } from './components/Block';\nimport { Modal } from './components/Modal';\nimport { Banner } from './components/Banner';\nimport { WIPProvider } from './provider/WIPProvider';\nimport { useWIP } from './hooks/useWIP';\n\nexport const WIP = Object.assign(WIPWrapper, {\n Badge,\n Ribbon,\n Overlay,\n Block,\n Modal,\n Banner,\n Provider: WIPProvider,\n});\n\nexport {\n Badge,\n Ribbon,\n Overlay,\n Block,\n Modal,\n Banner,\n WIPProvider,\n useWIP,\n};\n\nexport type { WIPConfig, WIPTheme, WIPVariant } from './provider/WIPProvider';\nexport type { BadgeProps } from './components/Badge';\nexport type { RibbonProps } from './components/Ribbon';\nexport type { OverlayProps } from './components/Overlay';\nexport type { BlockProps } from './components/Block';\nexport type { ModalProps } from './components/Modal';\nexport type { BannerProps } from './components/Banner';\nexport type { WIPWrapperProps } from './components/WIPWrapper';\n"]}
@@ -0,0 +1,164 @@
1
+ "use client";
2
+ import { Block, Overlay, Ribbon, Badge } from './chunk-46OHJMTB.mjs';
3
+ export { Badge, Block, Overlay, Ribbon } from './chunk-46OHJMTB.mjs';
4
+ import React, { createContext, useState, useId, useEffect, useContext } from 'react';
5
+ import { jsx, Fragment, jsxs } from 'react/jsx-runtime';
6
+ import { Info, X, AlertCircle } from 'lucide-react';
7
+ import { createPortal } from 'react-dom';
8
+
9
+ var defaultContext = {
10
+ theme: "light",
11
+ defaultVariant: "badge",
12
+ globalDisabled: false
13
+ };
14
+ var WIPContext = createContext(defaultContext);
15
+ function WIPProvider({
16
+ children,
17
+ theme = "light",
18
+ defaultVariant = "badge",
19
+ globalDisabled = false
20
+ }) {
21
+ const value = React.useMemo(
22
+ () => ({ theme, defaultVariant, globalDisabled }),
23
+ [theme, defaultVariant, globalDisabled]
24
+ );
25
+ return /* @__PURE__ */ jsx(WIPContext.Provider, { value, children: /* @__PURE__ */ jsx(
26
+ "div",
27
+ {
28
+ className: "rwip-base",
29
+ "data-rwip-theme": theme === "dark" ? "dark" : "light",
30
+ style: { display: "contents" },
31
+ children
32
+ }
33
+ ) });
34
+ }
35
+
36
+ // src/hooks/useWIP.ts
37
+ function useWIP() {
38
+ return useContext(WIPContext);
39
+ }
40
+ var WIPWrapper = ({ children, when = true }) => {
41
+ const { globalDisabled, defaultVariant } = useWIP();
42
+ if (globalDisabled || !when) {
43
+ return /* @__PURE__ */ jsx(Fragment, { children });
44
+ }
45
+ switch (defaultVariant) {
46
+ case "overlay":
47
+ return /* @__PURE__ */ jsx(Overlay, { children });
48
+ case "block":
49
+ return /* @__PURE__ */ jsx(Block, { children });
50
+ case "badge":
51
+ return /* @__PURE__ */ jsx(Badge, { children });
52
+ case "hidden":
53
+ return null;
54
+ default:
55
+ return /* @__PURE__ */ jsx(Block, { children });
56
+ }
57
+ };
58
+
59
+ // src/utils/ssr.ts
60
+ var isClient = typeof window !== "undefined" && typeof document !== "undefined";
61
+ var Modal = ({
62
+ isOpen,
63
+ onClose,
64
+ title = "Feature Under Construction",
65
+ description = "This feature is currently being developed and is not yet available.",
66
+ className = "",
67
+ ...props
68
+ }) => {
69
+ const { globalDisabled } = useWIP();
70
+ const [mounted, setMounted] = useState(false);
71
+ const titleId = useId();
72
+ useEffect(() => {
73
+ setMounted(true);
74
+ }, []);
75
+ useEffect(() => {
76
+ if (isOpen) {
77
+ const handleEsc = (e) => {
78
+ if (e.key === "Escape") onClose();
79
+ };
80
+ window.addEventListener("keydown", handleEsc);
81
+ return () => window.removeEventListener("keydown", handleEsc);
82
+ }
83
+ }, [isOpen, onClose]);
84
+ if (globalDisabled || !isOpen || !mounted || !isClient) return null;
85
+ return createPortal(
86
+ /* @__PURE__ */ jsx("div", { className: "rwip-modal-backdrop", onClick: onClose, children: /* @__PURE__ */ jsxs(
87
+ "div",
88
+ {
89
+ className: `rwip-modal ${className}`,
90
+ onClick: (e) => e.stopPropagation(),
91
+ role: "dialog",
92
+ "aria-modal": "true",
93
+ "aria-labelledby": titleId,
94
+ ...props,
95
+ children: [
96
+ /* @__PURE__ */ jsx(
97
+ "button",
98
+ {
99
+ className: "rwip-modal-close",
100
+ onClick: onClose,
101
+ "aria-label": "Close",
102
+ children: /* @__PURE__ */ jsx(X, { size: 20 })
103
+ }
104
+ ),
105
+ /* @__PURE__ */ jsxs("div", { style: { display: "flex", gap: "12px", alignItems: "flex-start" }, children: [
106
+ /* @__PURE__ */ jsx(AlertCircle, { size: 24, style: { color: "var(--rwip-color-primary)", flexShrink: 0, marginTop: "2px" } }),
107
+ /* @__PURE__ */ jsxs("div", { children: [
108
+ /* @__PURE__ */ jsx("h2", { id: titleId, className: "rwip-modal-title", children: title }),
109
+ /* @__PURE__ */ jsx("p", { className: "rwip-modal-desc", children: description })
110
+ ] })
111
+ ] })
112
+ ]
113
+ }
114
+ ) }),
115
+ document.body
116
+ );
117
+ };
118
+ var Banner = ({
119
+ message = "Parts of this application are currently under construction.",
120
+ dismissible = true,
121
+ position = "sticky",
122
+ className = "",
123
+ ...props
124
+ }) => {
125
+ const { globalDisabled } = useWIP();
126
+ const [isVisible, setIsVisible] = useState(true);
127
+ if (globalDisabled || !isVisible) return null;
128
+ return /* @__PURE__ */ jsxs(
129
+ "div",
130
+ {
131
+ className: `rwip-banner ${position === "sticky" ? "sticky" : ""} ${className}`,
132
+ role: "alert",
133
+ ...props,
134
+ children: [
135
+ /* @__PURE__ */ jsx(Info, { size: 16 }),
136
+ /* @__PURE__ */ jsx("span", { children: message }),
137
+ dismissible && /* @__PURE__ */ jsx(
138
+ "button",
139
+ {
140
+ className: "rwip-banner-close",
141
+ onClick: () => setIsVisible(false),
142
+ "aria-label": "Dismiss banner",
143
+ children: /* @__PURE__ */ jsx(X, { size: 16 })
144
+ }
145
+ )
146
+ ]
147
+ }
148
+ );
149
+ };
150
+
151
+ // src/client.ts
152
+ var WIP = Object.assign(WIPWrapper, {
153
+ Badge,
154
+ Ribbon,
155
+ Overlay,
156
+ Block,
157
+ Modal,
158
+ Banner,
159
+ Provider: WIPProvider
160
+ });
161
+
162
+ export { Banner, Modal, WIP, WIPProvider, useWIP };
163
+ //# sourceMappingURL=client.mjs.map
164
+ //# sourceMappingURL=client.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/provider/WIPProvider.tsx","../src/hooks/useWIP.ts","../src/components/WIPWrapper.tsx","../src/utils/ssr.ts","../src/components/Modal.tsx","../src/components/Banner.tsx","../src/client.ts"],"names":["jsx","useState","jsxs","X"],"mappings":";;;;;;;AAaA,IAAM,cAAA,GAA4B;AAAA,EAChC,KAAA,EAAO,OAAA;AAAA,EACP,cAAA,EAAgB,OAAA;AAAA,EAChB,cAAA,EAAgB;AAClB,CAAA;AAEO,IAAM,UAAA,GAAa,cAAyB,cAAc,CAAA;AAU1D,SAAS,WAAA,CAAY;AAAA,EAC1B,QAAA;AAAA,EACA,KAAA,GAAQ,OAAA;AAAA,EACR,cAAA,GAAiB,OAAA;AAAA,EACjB,cAAA,GAAiB;AACnB,CAAA,EAAqB;AACnB,EAAA,MAAM,QAAQ,KAAA,CAAM,OAAA;AAAA,IAClB,OAAO,EAAE,KAAA,EAAO,cAAA,EAAgB,cAAA,EAAe,CAAA;AAAA,IAC/C,CAAC,KAAA,EAAO,cAAA,EAAgB,cAAc;AAAA,GACxC;AAEA,EAAA,uBACE,GAAA,CAAC,UAAA,CAAW,QAAA,EAAX,EAAoB,KAAA,EACnB,QAAA,kBAAA,GAAA;AAAA,IAAC,KAAA;AAAA,IAAA;AAAA,MACC,SAAA,EAAU,WAAA;AAAA,MACV,iBAAA,EAAiB,KAAA,KAAU,MAAA,GAAS,MAAA,GAAS,OAAA;AAAA,MAC7C,KAAA,EAAO,EAAE,OAAA,EAAS,UAAA,EAAW;AAAA,MAE5B;AAAA;AAAA,GACH,EACF,CAAA;AAEJ;;;AChDO,SAAS,MAAA,GAAoB;AAClC,EAAA,OAAO,WAAW,UAAU,CAAA;AAC9B;ACMO,IAAM,aAAwC,CAAC,EAAE,QAAA,EAAU,IAAA,GAAO,MAAK,KAAM;AAClF,EAAA,MAAM,EAAE,cAAA,EAAgB,cAAA,EAAe,GAAI,MAAA,EAAO;AAElD,EAAA,IAAI,cAAA,IAAkB,CAAC,IAAA,EAAM;AAC3B,IAAA,uBAAOA,GAAAA,CAAA,QAAA,EAAA,EAAG,QAAA,EAAS,CAAA;AAAA,EACrB;AAEA,EAAA,QAAQ,cAAA;AAAgB,IACtB,KAAK,SAAA;AACH,MAAA,uBAAOA,GAAAA,CAAC,OAAA,EAAA,EAAS,QAAA,EAAS,CAAA;AAAA,IAC5B,KAAK,OAAA;AACH,MAAA,uBAAOA,GAAAA,CAAC,KAAA,EAAA,EAAO,QAAA,EAAS,CAAA;AAAA,IAC1B,KAAK,OAAA;AACH,MAAA,uBAAOA,GAAAA,CAAC,KAAA,EAAA,EAAO,QAAA,EAAS,CAAA;AAAA,IAC1B,KAAK,QAAA;AACH,MAAA,OAAO,IAAA;AAAA,IACT;AACE,MAAA,uBAAOA,GAAAA,CAAC,KAAA,EAAA,EAAO,QAAA,EAAS,CAAA;AAAA;AAE9B,CAAA;;;AC9BO,IAAM,QAAA,GAAW,OAAO,MAAA,KAAW,WAAA,IAAe,OAAO,QAAA,KAAa,WAAA;ACgBtE,IAAM,QAA8B,CAAC;AAAA,EAC1C,MAAA;AAAA,EACA,OAAA;AAAA,EACA,KAAA,GAAQ,4BAAA;AAAA,EACR,WAAA,GAAc,qEAAA;AAAA,EACd,SAAA,GAAY,EAAA;AAAA,EACZ,GAAG;AACL,CAAA,KAAM;AACJ,EAAA,MAAM,EAAE,cAAA,EAAe,GAAI,MAAA,EAAO;AAClC,EAAA,MAAM,CAAC,OAAA,EAAS,UAAU,CAAA,GAAI,SAAS,KAAK,CAAA;AAC5C,EAAA,MAAM,UAAU,KAAA,EAAM;AAEtB,EAAA,SAAA,CAAU,MAAM;AACd,IAAA,UAAA,CAAW,IAAI,CAAA;AAAA,EACjB,CAAA,EAAG,EAAE,CAAA;AAEL,EAAA,SAAA,CAAU,MAAM;AACd,IAAA,IAAI,MAAA,EAAQ;AACV,MAAA,MAAM,SAAA,GAAY,CAAC,CAAA,KAAqB;AACtC,QAAA,IAAI,CAAA,CAAE,GAAA,KAAQ,QAAA,EAAU,OAAA,EAAQ;AAAA,MAClC,CAAA;AACA,MAAA,MAAA,CAAO,gBAAA,CAAiB,WAAW,SAAS,CAAA;AAC5C,MAAA,OAAO,MAAM,MAAA,CAAO,mBAAA,CAAoB,SAAA,EAAW,SAAS,CAAA;AAAA,IAC9D;AAAA,EACF,CAAA,EAAG,CAAC,MAAA,EAAQ,OAAO,CAAC,CAAA;AAEpB,EAAA,IAAI,kBAAkB,CAAC,MAAA,IAAU,CAAC,OAAA,IAAW,CAAC,UAAU,OAAO,IAAA;AAE/D,EAAA,OAAO,YAAA;AAAA,oBACLA,GAAAA,CAAC,KAAA,EAAA,EAAI,SAAA,EAAU,qBAAA,EAAsB,SAAS,OAAA,EAC5C,QAAA,kBAAA,IAAA;AAAA,MAAC,KAAA;AAAA,MAAA;AAAA,QACC,SAAA,EAAW,cAAc,SAAS,CAAA,CAAA;AAAA,QAClC,OAAA,EAAS,CAAC,CAAA,KAAM,CAAA,CAAE,eAAA,EAAgB;AAAA,QAClC,IAAA,EAAK,QAAA;AAAA,QACL,YAAA,EAAW,MAAA;AAAA,QACX,iBAAA,EAAiB,OAAA;AAAA,QAChB,GAAG,KAAA;AAAA,QAEJ,QAAA,EAAA;AAAA,0BAAAA,GAAAA;AAAA,YAAC,QAAA;AAAA,YAAA;AAAA,cACC,SAAA,EAAU,kBAAA;AAAA,cACV,OAAA,EAAS,OAAA;AAAA,cACT,YAAA,EAAW,OAAA;AAAA,cAEX,QAAA,kBAAAA,GAAAA,CAAC,CAAA,EAAA,EAAE,IAAA,EAAM,EAAA,EAAI;AAAA;AAAA,WACf;AAAA,0BACA,IAAA,CAAC,KAAA,EAAA,EAAI,KAAA,EAAO,EAAE,OAAA,EAAS,QAAQ,GAAA,EAAK,MAAA,EAAQ,UAAA,EAAY,YAAA,EAAa,EACnE,QAAA,EAAA;AAAA,4BAAAA,GAAAA,CAAC,WAAA,EAAA,EAAY,IAAA,EAAM,EAAA,EAAI,KAAA,EAAO,EAAE,KAAA,EAAO,2BAAA,EAA6B,UAAA,EAAY,CAAA,EAAG,SAAA,EAAW,KAAA,EAAM,EAAG,CAAA;AAAA,iCACtG,KAAA,EAAA,EACC,QAAA,EAAA;AAAA,8BAAAA,IAAC,IAAA,EAAA,EAAG,EAAA,EAAI,OAAA,EAAS,SAAA,EAAU,oBAAoB,QAAA,EAAA,KAAA,EAAM,CAAA;AAAA,8BACrDA,GAAAA,CAAC,GAAA,EAAA,EAAE,SAAA,EAAU,mBAAmB,QAAA,EAAA,WAAA,EAAY;AAAA,aAAA,EAC9C;AAAA,WAAA,EACF;AAAA;AAAA;AAAA,KACF,EACF,CAAA;AAAA,IACA,QAAA,CAAS;AAAA,GACX;AACF;AC3DO,IAAM,SAAgC,CAAC;AAAA,EAC5C,OAAA,GAAU,6DAAA;AAAA,EACV,WAAA,GAAc,IAAA;AAAA,EACd,QAAA,GAAW,QAAA;AAAA,EACX,SAAA,GAAY,EAAA;AAAA,EACZ,GAAG;AACL,CAAA,KAAM;AACJ,EAAA,MAAM,EAAE,cAAA,EAAe,GAAI,MAAA,EAAO;AAClC,EAAA,MAAM,CAAC,SAAA,EAAW,YAAY,CAAA,GAAIC,SAAS,IAAI,CAAA;AAE/C,EAAA,IAAI,cAAA,IAAkB,CAAC,SAAA,EAAW,OAAO,IAAA;AAEzC,EAAA,uBACEC,IAAAA;AAAA,IAAC,KAAA;AAAA,IAAA;AAAA,MACC,WAAW,CAAA,YAAA,EAAe,QAAA,KAAa,WAAW,QAAA,GAAW,EAAE,IAAI,SAAS,CAAA,CAAA;AAAA,MAC5E,IAAA,EAAK,OAAA;AAAA,MACJ,GAAG,KAAA;AAAA,MAEJ,QAAA,EAAA;AAAA,wBAAAF,GAAAA,CAAC,IAAA,EAAA,EAAK,IAAA,EAAM,EAAA,EAAI,CAAA;AAAA,wBAChBA,GAAAA,CAAC,MAAA,EAAA,EAAM,QAAA,EAAA,OAAA,EAAQ,CAAA;AAAA,QACd,+BACCA,GAAAA;AAAA,UAAC,QAAA;AAAA,UAAA;AAAA,YACC,SAAA,EAAU,mBAAA;AAAA,YACV,OAAA,EAAS,MAAM,YAAA,CAAa,KAAK,CAAA;AAAA,YACjC,YAAA,EAAW,gBAAA;AAAA,YAEX,QAAA,kBAAAA,GAAAA,CAACG,CAAAA,EAAA,EAAE,MAAM,EAAA,EAAI;AAAA;AAAA;AACf;AAAA;AAAA,GAEJ;AAEJ;;;AChCO,IAAM,GAAA,GAAM,MAAA,CAAO,MAAA,CAAO,UAAA,EAAY;AAAA,EAC3C,KAAA;AAAA,EACA,MAAA;AAAA,EACA,OAAA;AAAA,EACA,KAAA;AAAA,EACA,KAAA;AAAA,EACA,MAAA;AAAA,EACA,QAAA,EAAU;AACZ,CAAC","file":"client.mjs","sourcesContent":["\"use client\";\n\nimport React, { createContext, ReactNode } from 'react';\n\nexport type WIPTheme = 'light' | 'dark' | 'system';\nexport type WIPVariant = 'overlay' | 'badge' | 'block' | 'hidden';\n\nexport interface WIPConfig {\n theme: WIPTheme;\n defaultVariant: WIPVariant;\n globalDisabled: boolean;\n}\n\nconst defaultContext: WIPConfig = {\n theme: 'light',\n defaultVariant: 'badge',\n globalDisabled: false,\n};\n\nexport const WIPContext = createContext<WIPConfig>(defaultContext);\n\nexport interface WIPProviderProps {\n children: ReactNode;\n theme?: WIPTheme;\n defaultVariant?: WIPVariant;\n /** Disable all WIP components globally (e.g. for production override) */\n globalDisabled?: boolean;\n}\n\nexport function WIPProvider({\n children,\n theme = 'light',\n defaultVariant = 'badge',\n globalDisabled = false,\n}: WIPProviderProps) {\n const value = React.useMemo(\n () => ({ theme, defaultVariant, globalDisabled }),\n [theme, defaultVariant, globalDisabled]\n );\n\n return (\n <WIPContext.Provider value={value}>\n <div \n className=\"rwip-base\" \n data-rwip-theme={theme === 'dark' ? 'dark' : 'light'} \n style={{ display: 'contents' }}\n >\n {children}\n </div>\n </WIPContext.Provider>\n );\n}\n","import { useContext } from 'react';\nimport { WIPContext, WIPConfig } from '../provider/WIPProvider';\n\nexport function useWIP(): WIPConfig {\n return useContext(WIPContext);\n}\n","import React from 'react';\nimport { useWIP } from '../hooks/useWIP';\nimport { Overlay } from './Overlay';\nimport { Block } from './Block';\nimport { Badge } from './Badge';\n\nexport interface WIPWrapperProps {\n children: React.ReactNode;\n when?: boolean;\n}\n\nexport const WIPWrapper: React.FC<WIPWrapperProps> = ({ children, when = true }) => {\n const { globalDisabled, defaultVariant } = useWIP();\n\n if (globalDisabled || !when) {\n return <>{children}</>;\n }\n\n switch (defaultVariant) {\n case 'overlay':\n return <Overlay>{children}</Overlay>;\n case 'block':\n return <Block>{children}</Block>;\n case 'badge':\n return <Badge>{children}</Badge>;\n case 'hidden':\n return null;\n default:\n return <Block>{children}</Block>;\n }\n};\n","export const isClient = typeof window !== 'undefined' && typeof document !== 'undefined';\n","\"use client\";\n\nimport React, { HTMLAttributes, useEffect, useId, useState } from 'react';\nimport { X, AlertCircle } from 'lucide-react';\nimport { useWIP } from '../hooks/useWIP';\nimport { isClient } from '../utils/ssr';\nimport { createPortal } from 'react-dom';\n\nexport interface ModalProps extends HTMLAttributes<HTMLDivElement> {\n isOpen: boolean;\n onClose: () => void;\n title?: string;\n description?: string;\n className?: string;\n}\n\nexport const Modal: React.FC<ModalProps> = ({ \n isOpen, \n onClose, \n title = 'Feature Under Construction', \n description = 'This feature is currently being developed and is not yet available.',\n className = '',\n ...props \n}) => {\n const { globalDisabled } = useWIP();\n const [mounted, setMounted] = useState(false);\n const titleId = useId();\n\n useEffect(() => {\n setMounted(true);\n }, []);\n\n useEffect(() => {\n if (isOpen) {\n const handleEsc = (e: KeyboardEvent) => {\n if (e.key === 'Escape') onClose();\n };\n window.addEventListener('keydown', handleEsc);\n return () => window.removeEventListener('keydown', handleEsc);\n }\n }, [isOpen, onClose]);\n\n if (globalDisabled || !isOpen || !mounted || !isClient) return null;\n\n return createPortal(\n <div className=\"rwip-modal-backdrop\" onClick={onClose}>\n <div \n className={`rwip-modal ${className}`} \n onClick={(e) => e.stopPropagation()}\n role=\"dialog\"\n aria-modal=\"true\"\n aria-labelledby={titleId}\n {...props}\n >\n <button \n className=\"rwip-modal-close\" \n onClick={onClose} \n aria-label=\"Close\"\n >\n <X size={20} />\n </button>\n <div style={{ display: 'flex', gap: '12px', alignItems: 'flex-start' }}>\n <AlertCircle size={24} style={{ color: 'var(--rwip-color-primary)', flexShrink: 0, marginTop: '2px' }} />\n <div>\n <h2 id={titleId} className=\"rwip-modal-title\">{title}</h2>\n <p className=\"rwip-modal-desc\">{description}</p>\n </div>\n </div>\n </div>\n </div>,\n document.body\n );\n};\n","\"use client\";\n\nimport React, { HTMLAttributes, useState } from 'react';\nimport { X, Info } from 'lucide-react';\nimport { useWIP } from '../hooks/useWIP';\n\nexport interface BannerProps extends HTMLAttributes<HTMLDivElement> {\n message?: string;\n dismissible?: boolean;\n position?: 'sticky' | 'relative';\n className?: string;\n}\n\nexport const Banner: React.FC<BannerProps> = ({ \n message = 'Parts of this application are currently under construction.', \n dismissible = true,\n position = 'sticky',\n className = '',\n ...props \n}) => {\n const { globalDisabled } = useWIP();\n const [isVisible, setIsVisible] = useState(true);\n\n if (globalDisabled || !isVisible) return null;\n\n return (\n <div \n className={`rwip-banner ${position === 'sticky' ? 'sticky' : ''} ${className}`} \n role=\"alert\"\n {...props}\n >\n <Info size={16} />\n <span>{message}</span>\n {dismissible && (\n <button \n className=\"rwip-banner-close\" \n onClick={() => setIsVisible(false)}\n aria-label=\"Dismiss banner\"\n >\n <X size={16} />\n </button>\n )}\n </div>\n );\n};\n","\"use client\";\n\nimport { WIPWrapper } from './components/WIPWrapper';\nimport { Badge } from './components/Badge';\nimport { Ribbon } from './components/Ribbon';\nimport { Overlay } from './components/Overlay';\nimport { Block } from './components/Block';\nimport { Modal } from './components/Modal';\nimport { Banner } from './components/Banner';\nimport { WIPProvider } from './provider/WIPProvider';\nimport { useWIP } from './hooks/useWIP';\n\nexport const WIP = Object.assign(WIPWrapper, {\n Badge,\n Ribbon,\n Overlay,\n Block,\n Modal,\n Banner,\n Provider: WIPProvider,\n});\n\nexport {\n Badge,\n Ribbon,\n Overlay,\n Block,\n Modal,\n Banner,\n WIPProvider,\n useWIP,\n};\n\nexport type { WIPConfig, WIPTheme, WIPVariant } from './provider/WIPProvider';\nexport type { BadgeProps } from './components/Badge';\nexport type { RibbonProps } from './components/Ribbon';\nexport type { OverlayProps } from './components/Overlay';\nexport type { BlockProps } from './components/Block';\nexport type { ModalProps } from './components/Modal';\nexport type { BannerProps } from './components/Banner';\nexport type { WIPWrapperProps } from './components/WIPWrapper';\n"]}
@@ -0,0 +1,8 @@
1
+ import React, { HTMLAttributes } from 'react';
2
+ export interface BadgeProps extends HTMLAttributes<HTMLSpanElement> {
3
+ text?: string;
4
+ className?: string;
5
+ disabled?: boolean;
6
+ }
7
+ export declare const Badge: React.FC<BadgeProps>;
8
+ //# sourceMappingURL=Badge.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Badge.d.ts","sourceRoot":"","sources":["../../src/components/Badge.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,EAAE,cAAc,EAAE,MAAM,OAAO,CAAC;AAE9C,MAAM,WAAW,UAAW,SAAQ,cAAc,CAAC,eAAe,CAAC;IACjE,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,QAAQ,CAAC,EAAE,OAAO,CAAC;CACpB;AAED,eAAO,MAAM,KAAK,EAAE,KAAK,CAAC,EAAE,CAAC,UAAU,CAgBtC,CAAC"}
@@ -0,0 +1,9 @@
1
+ import React, { HTMLAttributes } from 'react';
2
+ export interface BannerProps extends HTMLAttributes<HTMLDivElement> {
3
+ message?: string;
4
+ dismissible?: boolean;
5
+ position?: 'sticky' | 'relative';
6
+ className?: string;
7
+ }
8
+ export declare const Banner: React.FC<BannerProps>;
9
+ //# sourceMappingURL=Banner.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Banner.d.ts","sourceRoot":"","sources":["../../src/components/Banner.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,EAAE,cAAc,EAAY,MAAM,OAAO,CAAC;AAIxD,MAAM,WAAW,WAAY,SAAQ,cAAc,CAAC,cAAc,CAAC;IACjE,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB,QAAQ,CAAC,EAAE,QAAQ,GAAG,UAAU,CAAC;IACjC,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED,eAAO,MAAM,MAAM,EAAE,KAAK,CAAC,EAAE,CAAC,WAAW,CA+BxC,CAAC"}
@@ -0,0 +1,7 @@
1
+ import React, { HTMLAttributes } from 'react';
2
+ export interface BlockProps extends HTMLAttributes<HTMLDivElement> {
3
+ className?: string;
4
+ disabled?: boolean;
5
+ }
6
+ export declare const Block: React.FC<BlockProps>;
7
+ //# sourceMappingURL=Block.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Block.d.ts","sourceRoot":"","sources":["../../src/components/Block.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,EAAE,cAAc,EAAE,MAAM,OAAO,CAAC;AAE9C,MAAM,WAAW,UAAW,SAAQ,cAAc,CAAC,cAAc,CAAC;IAChE,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,QAAQ,CAAC,EAAE,OAAO,CAAC;CACpB;AAED,eAAO,MAAM,KAAK,EAAE,KAAK,CAAC,EAAE,CAAC,UAAU,CAetC,CAAC"}
@@ -0,0 +1,10 @@
1
+ import React, { HTMLAttributes } from 'react';
2
+ export interface ModalProps extends HTMLAttributes<HTMLDivElement> {
3
+ isOpen: boolean;
4
+ onClose: () => void;
5
+ title?: string;
6
+ description?: string;
7
+ className?: string;
8
+ }
9
+ export declare const Modal: React.FC<ModalProps>;
10
+ //# sourceMappingURL=Modal.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Modal.d.ts","sourceRoot":"","sources":["../../src/components/Modal.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,EAAE,cAAc,EAA8B,MAAM,OAAO,CAAC;AAM1E,MAAM,WAAW,UAAW,SAAQ,cAAc,CAAC,cAAc,CAAC;IAChE,MAAM,EAAE,OAAO,CAAC;IAChB,OAAO,EAAE,MAAM,IAAI,CAAC;IACpB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED,eAAO,MAAM,KAAK,EAAE,KAAK,CAAC,EAAE,CAAC,UAAU,CAwDtC,CAAC"}
@@ -0,0 +1,8 @@
1
+ import React, { HTMLAttributes } from 'react';
2
+ export interface OverlayProps extends HTMLAttributes<HTMLDivElement> {
3
+ message?: string;
4
+ className?: string;
5
+ disabled?: boolean;
6
+ }
7
+ export declare const Overlay: React.FC<OverlayProps>;
8
+ //# sourceMappingURL=Overlay.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Overlay.d.ts","sourceRoot":"","sources":["../../src/components/Overlay.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,EAAE,cAAc,EAAE,MAAM,OAAO,CAAC;AAG9C,MAAM,WAAW,YAAa,SAAQ,cAAc,CAAC,cAAc,CAAC;IAClE,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,QAAQ,CAAC,EAAE,OAAO,CAAC;CACpB;AAED,eAAO,MAAM,OAAO,EAAE,KAAK,CAAC,EAAE,CAAC,YAAY,CAsB1C,CAAC"}
@@ -0,0 +1,10 @@
1
+ import React, { HTMLAttributes } from 'react';
2
+ export interface RibbonProps extends HTMLAttributes<HTMLDivElement> {
3
+ position?: 'top-left' | 'top-right';
4
+ text?: string;
5
+ variant?: 'solid' | 'outline';
6
+ className?: string;
7
+ disabled?: boolean;
8
+ }
9
+ export declare const Ribbon: React.FC<RibbonProps>;
10
+ //# sourceMappingURL=Ribbon.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Ribbon.d.ts","sourceRoot":"","sources":["../../src/components/Ribbon.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,EAAE,cAAc,EAAE,MAAM,OAAO,CAAC;AAE9C,MAAM,WAAW,WAAY,SAAQ,cAAc,CAAC,cAAc,CAAC;IACjE,QAAQ,CAAC,EAAE,UAAU,GAAG,WAAW,CAAC;IACpC,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,OAAO,CAAC,EAAE,OAAO,GAAG,SAAS,CAAC;IAC9B,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,QAAQ,CAAC,EAAE,OAAO,CAAC;CACpB;AAED,eAAO,MAAM,MAAM,EAAE,KAAK,CAAC,EAAE,CAAC,WAAW,CAoBxC,CAAC"}
@@ -0,0 +1,7 @@
1
+ import React from 'react';
2
+ export interface WIPWrapperProps {
3
+ children: React.ReactNode;
4
+ when?: boolean;
5
+ }
6
+ export declare const WIPWrapper: React.FC<WIPWrapperProps>;
7
+ //# sourceMappingURL=WIPWrapper.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"WIPWrapper.d.ts","sourceRoot":"","sources":["../../src/components/WIPWrapper.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAC;AAM1B,MAAM,WAAW,eAAe;IAC9B,QAAQ,EAAE,KAAK,CAAC,SAAS,CAAC;IAC1B,IAAI,CAAC,EAAE,OAAO,CAAC;CAChB;AAED,eAAO,MAAM,UAAU,EAAE,KAAK,CAAC,EAAE,CAAC,eAAe,CAmBhD,CAAC"}
@@ -0,0 +1,3 @@
1
+ import { WIPConfig } from '../provider/WIPProvider';
2
+ export declare function useWIP(): WIPConfig;
3
+ //# sourceMappingURL=useWIP.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"useWIP.d.ts","sourceRoot":"","sources":["../../src/hooks/useWIP.ts"],"names":[],"mappings":"AACA,OAAO,EAAc,SAAS,EAAE,MAAM,yBAAyB,CAAC;AAEhE,wBAAgB,MAAM,IAAI,SAAS,CAElC"}
package/dist/index.css ADDED
@@ -0,0 +1,225 @@
1
+ :root {
2
+ --rwip-color-bg: #FDFBF7;
3
+ --rwip-color-text: #4A4641;
4
+ --rwip-color-primary: #D1BFAe;
5
+ --rwip-color-ribbon-bg: #E8DDCE;
6
+ --rwip-color-ribbon-text: #6A5D4D;
7
+ --rwip-radius: 8px;
8
+ --rwip-shadow: 0 4px 12px rgba(80, 75, 70, 0.08);
9
+ --rwip-blur: blur(4px);
10
+ --rwip-font-family: 'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Helvetica, Arial, sans-serif;
11
+ }
12
+
13
+ [data-rwip-theme="dark"] {
14
+ --rwip-color-bg: #1A1918;
15
+ --rwip-color-text: #E8E6E1;
16
+ --rwip-color-primary: #857B71;
17
+ --rwip-color-ribbon-bg: #2C2A28;
18
+ --rwip-color-ribbon-text: #C4B9AD;
19
+ --rwip-shadow: 0 4px 12px rgba(0, 0, 0, 0.4);
20
+ }
21
+
22
+ .rwip-base {
23
+ font-family: var(--rwip-font-family);
24
+ box-sizing: border-box;
25
+ }
26
+
27
+ /* Ribbon */
28
+ .rwip-ribbon-container {
29
+ position: absolute;
30
+ top: 0;
31
+ width: 100%;
32
+ height: 100%;
33
+ overflow: hidden;
34
+ pointer-events: none;
35
+ z-index: 50;
36
+ }
37
+
38
+ .rwip-ribbon {
39
+ position: absolute;
40
+ background-color: var(--rwip-color-ribbon-bg);
41
+ color: var(--rwip-color-ribbon-text);
42
+ font-size: 0.75rem;
43
+ font-weight: 600;
44
+ text-transform: uppercase;
45
+ letter-spacing: 0.05em;
46
+ padding: 4px 40px;
47
+ box-shadow: var(--rwip-shadow);
48
+ pointer-events: auto;
49
+ }
50
+
51
+ .rwip-ribbon.top-left {
52
+ top: 16px;
53
+ left: -28px;
54
+ transform: rotate(-45deg);
55
+ }
56
+
57
+ .rwip-ribbon.top-right {
58
+ top: 16px;
59
+ right: -28px;
60
+ transform: rotate(45deg);
61
+ }
62
+
63
+ .rwip-ribbon.outline {
64
+ background-color: transparent;
65
+ border: 1px solid var(--rwip-color-ribbon-bg);
66
+ backdrop-filter: var(--rwip-blur);
67
+ }
68
+
69
+ /* Badge */
70
+ .rwip-badge-wrapper {
71
+ display: inline-flex;
72
+ align-items: center;
73
+ gap: 8px;
74
+ position: relative;
75
+ }
76
+
77
+ .rwip-badge {
78
+ display: inline-flex;
79
+ align-items: center;
80
+ gap: 4px;
81
+ background-color: var(--rwip-color-ribbon-bg);
82
+ color: var(--rwip-color-ribbon-text);
83
+ border-radius: 9999px;
84
+ padding: 2px 8px;
85
+ font-size: 0.7rem;
86
+ font-weight: 500;
87
+ white-space: nowrap;
88
+ }
89
+
90
+ /* Overlay & Block */
91
+ .rwip-overlay-container {
92
+ position: relative;
93
+ display: inline-block;
94
+ width: 100%;
95
+ }
96
+
97
+ .rwip-overlay {
98
+ position: absolute;
99
+ inset: 0;
100
+ background-color: rgba(253, 251, 247, 0.4);
101
+ backdrop-filter: var(--rwip-blur);
102
+ z-index: 40;
103
+ display: flex;
104
+ align-items: center;
105
+ justify-content: center;
106
+ border-radius: inherit;
107
+ transition: opacity 0.3s ease;
108
+ }
109
+
110
+ [data-rwip-theme="dark"] .rwip-overlay {
111
+ background-color: rgba(26, 25, 24, 0.4);
112
+ }
113
+
114
+ .rwip-overlay-message {
115
+ background-color: var(--rwip-color-bg);
116
+ color: var(--rwip-color-text);
117
+ padding: 8px 16px;
118
+ border-radius: var(--rwip-radius);
119
+ font-size: 0.875rem;
120
+ font-weight: 500;
121
+ box-shadow: var(--rwip-shadow);
122
+ display: inline-flex;
123
+ align-items: center;
124
+ gap: 6px;
125
+ }
126
+
127
+ .rwip-block {
128
+ pointer-events: none;
129
+ user-select: none;
130
+ }
131
+
132
+ /* Modal */
133
+ .rwip-modal-backdrop {
134
+ position: fixed;
135
+ inset: 0;
136
+ background-color: rgba(0, 0, 0, 0.2);
137
+ backdrop-filter: var(--rwip-blur);
138
+ z-index: 1000;
139
+ display: flex;
140
+ align-items: center;
141
+ justify-content: center;
142
+ animation: rwip-fade-in 0.2s ease-out;
143
+ }
144
+
145
+ .rwip-modal {
146
+ background-color: var(--rwip-color-bg);
147
+ color: var(--rwip-color-text);
148
+ border-radius: var(--rwip-radius);
149
+ box-shadow: var(--rwip-shadow);
150
+ padding: 24px;
151
+ max-width: 400px;
152
+ width: 90%;
153
+ animation: rwip-slide-up 0.3s cubic-bezier(0.16, 1, 0.3, 1);
154
+ position: relative;
155
+ }
156
+
157
+ .rwip-modal-close {
158
+ position: absolute;
159
+ top: 12px;
160
+ right: 12px;
161
+ background: none;
162
+ border: none;
163
+ color: var(--rwip-color-text);
164
+ cursor: pointer;
165
+ opacity: 0.6;
166
+ transition: opacity 0.2s;
167
+ padding: 4px;
168
+ }
169
+ .rwip-modal-close:hover {
170
+ opacity: 1;
171
+ }
172
+
173
+ .rwip-modal-title {
174
+ margin: 0 0 8px 0;
175
+ font-size: 1.125rem;
176
+ font-weight: 600;
177
+ }
178
+ .rwip-modal-desc {
179
+ margin: 0;
180
+ font-size: 0.875rem;
181
+ opacity: 0.8;
182
+ line-height: 1.5;
183
+ }
184
+
185
+ /* Banner */
186
+ .rwip-banner {
187
+ background-color: var(--rwip-color-ribbon-bg);
188
+ color: var(--rwip-color-ribbon-text);
189
+ padding: 12px 24px;
190
+ font-size: 0.875rem;
191
+ display: flex;
192
+ align-items: center;
193
+ justify-content: center;
194
+ gap: 8px;
195
+ position: relative;
196
+ }
197
+
198
+ .rwip-banner.sticky {
199
+ position: sticky;
200
+ top: 0;
201
+ z-index: 100;
202
+ }
203
+
204
+ .rwip-banner-close {
205
+ position: absolute;
206
+ right: 16px;
207
+ background: none;
208
+ border: none;
209
+ color: inherit;
210
+ cursor: pointer;
211
+ opacity: 0.7;
212
+ }
213
+ .rwip-banner-close:hover {
214
+ opacity: 1;
215
+ }
216
+
217
+ @keyframes rwip-fade-in {
218
+ from { opacity: 0; }
219
+ to { opacity: 1; }
220
+ }
221
+
222
+ @keyframes rwip-slide-up {
223
+ from { opacity: 0; transform: translateY(10px); }
224
+ to { opacity: 1; transform: translateY(0); }
225
+ }
@@ -0,0 +1,10 @@
1
+ import { Badge } from './components/Badge';
2
+ import { Ribbon } from './components/Ribbon';
3
+ import { Overlay } from './components/Overlay';
4
+ import { Block } from './components/Block';
5
+ export { Badge, Ribbon, Overlay, Block };
6
+ export type { BadgeProps } from './components/Badge';
7
+ export type { RibbonProps } from './components/Ribbon';
8
+ export type { OverlayProps } from './components/Overlay';
9
+ export type { BlockProps } from './components/Block';
10
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,MAAM,oBAAoB,CAAC;AAC3C,OAAO,EAAE,MAAM,EAAE,MAAM,qBAAqB,CAAC;AAC7C,OAAO,EAAE,OAAO,EAAE,MAAM,sBAAsB,CAAC;AAC/C,OAAO,EAAE,KAAK,EAAE,MAAM,oBAAoB,CAAC;AAE3C,OAAO,EAAE,KAAK,EAAE,MAAM,EAAE,OAAO,EAAE,KAAK,EAAE,CAAC;AACzC,YAAY,EAAE,UAAU,EAAE,MAAM,oBAAoB,CAAC;AACrD,YAAY,EAAE,WAAW,EAAE,MAAM,qBAAqB,CAAC;AACvD,YAAY,EAAE,YAAY,EAAE,MAAM,sBAAsB,CAAC;AACzD,YAAY,EAAE,UAAU,EAAE,MAAM,oBAAoB,CAAC"}
package/dist/index.js ADDED
@@ -0,0 +1,72 @@
1
+ 'use strict';
2
+
3
+ var jsxRuntime = require('react/jsx-runtime');
4
+ var lucideReact = require('lucide-react');
5
+
6
+ // src/components/Badge.tsx
7
+ var Badge = ({
8
+ text = "WIP",
9
+ className = "",
10
+ disabled = false,
11
+ ...props
12
+ }) => {
13
+ if (disabled) return null;
14
+ return /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "rwip-badge-wrapper", title: "Work in Progress", children: [
15
+ props.children,
16
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: `rwip-badge ${className}`, ...props, children: text })
17
+ ] });
18
+ };
19
+ var Ribbon = ({
20
+ position = "top-right",
21
+ text = "WIP",
22
+ variant = "solid",
23
+ className = "",
24
+ disabled = false,
25
+ ...props
26
+ }) => {
27
+ if (disabled) return null;
28
+ return /* @__PURE__ */ jsxRuntime.jsx("div", { className: "rwip-ribbon-container", children: /* @__PURE__ */ jsxRuntime.jsx(
29
+ "div",
30
+ {
31
+ className: `rwip-ribbon ${position} ${variant} ${className}`,
32
+ ...props,
33
+ children: text
34
+ }
35
+ ) });
36
+ };
37
+ var Overlay = ({
38
+ children,
39
+ message = "Under Construction",
40
+ className = "",
41
+ disabled = false,
42
+ ...props
43
+ }) => {
44
+ if (disabled) {
45
+ return /* @__PURE__ */ jsxRuntime.jsx(jsxRuntime.Fragment, { children });
46
+ }
47
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: `rwip-overlay-container ${className}`, ...props, children: [
48
+ children,
49
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "rwip-overlay", "aria-hidden": "true", children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "rwip-overlay-message", children: [
50
+ /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Construction, { size: 18 }),
51
+ /* @__PURE__ */ jsxRuntime.jsx("span", { children: message })
52
+ ] }) })
53
+ ] });
54
+ };
55
+ var Block = ({
56
+ children,
57
+ className = "",
58
+ disabled = false,
59
+ ...props
60
+ }) => {
61
+ if (disabled) {
62
+ return /* @__PURE__ */ jsxRuntime.jsx(jsxRuntime.Fragment, { children });
63
+ }
64
+ return /* @__PURE__ */ jsxRuntime.jsx("div", { className: `rwip-block ${className}`, "aria-disabled": "true", ...props, children });
65
+ };
66
+
67
+ exports.Badge = Badge;
68
+ exports.Block = Block;
69
+ exports.Overlay = Overlay;
70
+ exports.Ribbon = Ribbon;
71
+ //# sourceMappingURL=index.js.map
72
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/components/Badge.tsx","../src/components/Ribbon.tsx","../src/components/Overlay.tsx","../src/components/Block.tsx"],"names":["jsxs","jsx","Fragment","Construction"],"mappings":";;;;;;AAQO,IAAM,QAA8B,CAAC;AAAA,EAC1C,IAAA,GAAO,KAAA;AAAA,EACP,SAAA,GAAY,EAAA;AAAA,EACZ,QAAA,GAAW,KAAA;AAAA,EACX,GAAG;AACL,CAAA,KAAM;AACJ,EAAA,IAAI,UAAU,OAAO,IAAA;AAErB,EAAA,uBACEA,eAAA,CAAC,MAAA,EAAA,EAAK,SAAA,EAAU,oBAAA,EAAqB,OAAM,kBAAA,EACxC,QAAA,EAAA;AAAA,IAAA,KAAA,CAAM,QAAA;AAAA,oBACPC,cAAA,CAAC,UAAK,SAAA,EAAW,CAAA,WAAA,EAAc,SAAS,CAAA,CAAA,EAAK,GAAG,OAC7C,QAAA,EAAA,IAAA,EACH;AAAA,GAAA,EACF,CAAA;AAEJ;ACdO,IAAM,SAAgC,CAAC;AAAA,EAC5C,QAAA,GAAW,WAAA;AAAA,EACX,IAAA,GAAO,KAAA;AAAA,EACP,OAAA,GAAU,OAAA;AAAA,EACV,SAAA,GAAY,EAAA;AAAA,EACZ,QAAA,GAAW,KAAA;AAAA,EACX,GAAG;AACL,CAAA,KAAM;AACJ,EAAA,IAAI,UAAU,OAAO,IAAA;AAErB,EAAA,uBACEA,cAAAA,CAAC,KAAA,EAAA,EAAI,SAAA,EAAU,yBACb,QAAA,kBAAAA,cAAAA;AAAA,IAAC,KAAA;AAAA,IAAA;AAAA,MACC,WAAW,CAAA,YAAA,EAAe,QAAQ,CAAA,CAAA,EAAI,OAAO,IAAI,SAAS,CAAA,CAAA;AAAA,MACzD,GAAG,KAAA;AAAA,MAEH,QAAA,EAAA;AAAA;AAAA,GACH,EACF,CAAA;AAEJ;ACrBO,IAAM,UAAkC,CAAC;AAAA,EAC9C,QAAA;AAAA,EACA,OAAA,GAAU,oBAAA;AAAA,EACV,SAAA,GAAY,EAAA;AAAA,EACZ,QAAA,GAAW,KAAA;AAAA,EACX,GAAG;AACL,CAAA,KAAM;AACJ,EAAA,IAAI,QAAA,EAAU;AACZ,IAAA,uBAAOA,cAAAA,CAAAC,mBAAA,EAAA,EAAG,QAAA,EAAS,CAAA;AAAA,EACrB;AAEA,EAAA,uBACEF,gBAAC,KAAA,EAAA,EAAI,SAAA,EAAW,0BAA0B,SAAS,CAAA,CAAA,EAAK,GAAG,KAAA,EACxD,QAAA,EAAA;AAAA,IAAA,QAAA;AAAA,oBACDC,cAAAA,CAAC,KAAA,EAAA,EAAI,SAAA,EAAU,cAAA,EAAe,aAAA,EAAY,MAAA,EACxC,QAAA,kBAAAD,eAAAA,CAAC,KAAA,EAAA,EAAI,SAAA,EAAU,sBAAA,EACb,QAAA,EAAA;AAAA,sBAAAC,cAAAA,CAACE,wBAAA,EAAA,EAAa,IAAA,EAAM,EAAA,EAAI,CAAA;AAAA,sBACxBF,cAAAA,CAAC,MAAA,EAAA,EAAM,QAAA,EAAA,OAAA,EAAQ;AAAA,KAAA,EACjB,CAAA,EACF;AAAA,GAAA,EACF,CAAA;AAEJ;ACxBO,IAAM,QAA8B,CAAC;AAAA,EAC1C,QAAA;AAAA,EACA,SAAA,GAAY,EAAA;AAAA,EACZ,QAAA,GAAW,KAAA;AAAA,EACX,GAAG;AACL,CAAA,KAAM;AACJ,EAAA,IAAI,QAAA,EAAU;AACZ,IAAA,uBAAOA,cAAAA,CAAAC,mBAAAA,EAAA,EAAG,QAAA,EAAS,CAAA;AAAA,EACrB;AAEA,EAAA,uBACED,cAAAA,CAAC,KAAA,EAAA,EAAI,SAAA,EAAW,CAAA,WAAA,EAAc,SAAS,CAAA,CAAA,EAAI,eAAA,EAAc,MAAA,EAAQ,GAAG,KAAA,EACjE,QAAA,EACH,CAAA;AAEJ","file":"index.js","sourcesContent":["import React, { HTMLAttributes } from 'react';\n\nexport interface BadgeProps extends HTMLAttributes<HTMLSpanElement> {\n text?: string;\n className?: string;\n disabled?: boolean;\n}\n\nexport const Badge: React.FC<BadgeProps> = ({ \n text = 'WIP', \n className = '',\n disabled = false,\n ...props \n}) => {\n if (disabled) return null;\n\n return (\n <span className=\"rwip-badge-wrapper\" title=\"Work in Progress\">\n {props.children}\n <span className={`rwip-badge ${className}`} {...props}>\n {text}\n </span>\n </span>\n );\n};\n","import React, { HTMLAttributes } from 'react';\n\nexport interface RibbonProps extends HTMLAttributes<HTMLDivElement> {\n position?: 'top-left' | 'top-right';\n text?: string;\n variant?: 'solid' | 'outline';\n className?: string;\n disabled?: boolean;\n}\n\nexport const Ribbon: React.FC<RibbonProps> = ({ \n position = 'top-right', \n text = 'WIP', \n variant = 'solid',\n className = '',\n disabled = false,\n ...props \n}) => {\n if (disabled) return null;\n\n return (\n <div className=\"rwip-ribbon-container\">\n <div \n className={`rwip-ribbon ${position} ${variant} ${className}`} \n {...props}\n >\n {text}\n </div>\n </div>\n );\n};\n","import React, { HTMLAttributes } from 'react';\nimport { Construction } from 'lucide-react';\n\nexport interface OverlayProps extends HTMLAttributes<HTMLDivElement> {\n message?: string;\n className?: string;\n disabled?: boolean;\n}\n\nexport const Overlay: React.FC<OverlayProps> = ({ \n children, \n message = 'Under Construction', \n className = '',\n disabled = false,\n ...props \n}) => {\n if (disabled) {\n return <>{children}</>;\n }\n\n return (\n <div className={`rwip-overlay-container ${className}`} {...props}>\n {children}\n <div className=\"rwip-overlay\" aria-hidden=\"true\">\n <div className=\"rwip-overlay-message\">\n <Construction size={18} />\n <span>{message}</span>\n </div>\n </div>\n </div>\n );\n};\n","import React, { HTMLAttributes } from 'react';\n\nexport interface BlockProps extends HTMLAttributes<HTMLDivElement> {\n className?: string;\n disabled?: boolean;\n}\n\nexport const Block: React.FC<BlockProps> = ({ \n children, \n className = '',\n disabled = false,\n ...props \n}) => {\n if (disabled) {\n return <>{children}</>;\n }\n\n return (\n <div className={`rwip-block ${className}`} aria-disabled=\"true\" {...props}>\n {children}\n </div>\n );\n};\n"]}
package/dist/index.mjs ADDED
@@ -0,0 +1,3 @@
1
+ export { Badge, Block, Overlay, Ribbon } from './chunk-46OHJMTB.mjs';
2
+ //# sourceMappingURL=index.mjs.map
3
+ //# sourceMappingURL=index.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":[],"names":[],"mappings":"","file":"index.mjs"}
@@ -0,0 +1,18 @@
1
+ import React, { ReactNode } from 'react';
2
+ export type WIPTheme = 'light' | 'dark' | 'system';
3
+ export type WIPVariant = 'overlay' | 'badge' | 'block' | 'hidden';
4
+ export interface WIPConfig {
5
+ theme: WIPTheme;
6
+ defaultVariant: WIPVariant;
7
+ globalDisabled: boolean;
8
+ }
9
+ export declare const WIPContext: React.Context<WIPConfig>;
10
+ export interface WIPProviderProps {
11
+ children: ReactNode;
12
+ theme?: WIPTheme;
13
+ defaultVariant?: WIPVariant;
14
+ /** Disable all WIP components globally (e.g. for production override) */
15
+ globalDisabled?: boolean;
16
+ }
17
+ export declare function WIPProvider({ children, theme, defaultVariant, globalDisabled, }: WIPProviderProps): import("react/jsx-runtime").JSX.Element;
18
+ //# sourceMappingURL=WIPProvider.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"WIPProvider.d.ts","sourceRoot":"","sources":["../../src/provider/WIPProvider.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,EAAiB,SAAS,EAAE,MAAM,OAAO,CAAC;AAExD,MAAM,MAAM,QAAQ,GAAG,OAAO,GAAG,MAAM,GAAG,QAAQ,CAAC;AACnD,MAAM,MAAM,UAAU,GAAG,SAAS,GAAG,OAAO,GAAG,OAAO,GAAG,QAAQ,CAAC;AAElE,MAAM,WAAW,SAAS;IACxB,KAAK,EAAE,QAAQ,CAAC;IAChB,cAAc,EAAE,UAAU,CAAC;IAC3B,cAAc,EAAE,OAAO,CAAC;CACzB;AAQD,eAAO,MAAM,UAAU,0BAA2C,CAAC;AAEnE,MAAM,WAAW,gBAAgB;IAC/B,QAAQ,EAAE,SAAS,CAAC;IACpB,KAAK,CAAC,EAAE,QAAQ,CAAC;IACjB,cAAc,CAAC,EAAE,UAAU,CAAC;IAC5B,yEAAyE;IACzE,cAAc,CAAC,EAAE,OAAO,CAAC;CAC1B;AAED,wBAAgB,WAAW,CAAC,EAC1B,QAAQ,EACR,KAAe,EACf,cAAwB,EACxB,cAAsB,GACvB,EAAE,gBAAgB,2CAiBlB"}
@@ -0,0 +1,2 @@
1
+ export declare const isClient: boolean;
2
+ //# sourceMappingURL=ssr.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ssr.d.ts","sourceRoot":"","sources":["../../src/utils/ssr.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,QAAQ,SAAmE,CAAC"}
package/package.json ADDED
@@ -0,0 +1,63 @@
1
+ {
2
+ "name": "react-wip-ui",
3
+ "version": "1.0.0",
4
+ "description": "Production-ready UI components for marking features as Work In Progress",
5
+ "main": "./dist/index.js",
6
+ "module": "./dist/index.mjs",
7
+ "types": "./dist/index.d.ts",
8
+ "exports": {
9
+ ".": {
10
+ "types": "./dist/index.d.ts",
11
+ "import": "./dist/index.mjs",
12
+ "require": "./dist/index.js"
13
+ },
14
+ "./client": {
15
+ "types": "./dist/client.d.ts",
16
+ "import": "./dist/client.mjs",
17
+ "require": "./dist/client.js"
18
+ },
19
+ "./styles.css": "./dist/index.css"
20
+ },
21
+ "files": [
22
+ "dist"
23
+ ],
24
+ "scripts": {
25
+ "build": "tsup && tsc --emitDeclarationOnly && node scripts/prepare-dist.mjs",
26
+ "dev": "tsup --watch",
27
+ "prepublishOnly": "npm run build"
28
+ },
29
+ "peerDependencies": {
30
+ "react": "^18.0.0 || ^19.0.0",
31
+ "react-dom": "^18.0.0 || ^19.0.0"
32
+ },
33
+ "dependencies": {
34
+ "lucide-react": "^1.7.0"
35
+ },
36
+ "devDependencies": {
37
+ "@types/react": "^19.2.0",
38
+ "@types/react-dom": "^19.2.0",
39
+ "tsup": "^8.0.0",
40
+ "typescript": "^6.0.0"
41
+ },
42
+ "keywords": [
43
+ "react",
44
+ "wip",
45
+ "work in progress",
46
+ "feature-flag",
47
+ "ui",
48
+ "nextjs",
49
+ "ssr",
50
+ "overlay",
51
+ "badge"
52
+ ],
53
+ "author": "Nihal K",
54
+ "repository": {
55
+ "type": "git",
56
+ "url": "git+https://github.com/ioNihal/react-wip-ui.git"
57
+ },
58
+ "homepage": "https://react-wip-ui.vercel.app",
59
+ "bugs": {
60
+ "url": "https://github.com/ioNihal/react-wip-ui/issues"
61
+ },
62
+ "license": "MIT"
63
+ }