@themodcraft/addon-packs 1.1.0 → 1.1.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/addons/animations/animated-number/AnimatedNumber.js +1 -29
- package/dist/addons/animations/animated-number/AnimatedNumber.types.js +0 -1
- package/dist/addons/animations/animated-number/index.js +1 -1
- package/dist/addons/animations/index.js +1 -1
- package/dist/addons/artstyles/colors/color-utils.js +1 -141
- package/dist/addons/artstyles/colors/index.js +1 -1
- package/dist/addons/artstyles/index.js +1 -1
- package/dist/addons/charts/index.js +1 -1
- package/dist/addons/charts/mini-bar-chart/MiniBarChart.js +1 -72
- package/dist/addons/charts/mini-bar-chart/MiniBarChart.types.js +0 -1
- package/dist/addons/charts/mini-bar-chart/index.js +1 -1
- package/dist/addons/configs/index.js +1 -1
- package/dist/addons/index.js +1 -8
- package/dist/addons/integrations/better-auth/better-auth.js +1 -11
- package/dist/addons/integrations/better-auth/index.js +1 -1
- package/dist/addons/integrations/index.js +1 -1
- package/dist/addons/paywall/Paywall.js +1 -145
- package/dist/addons/paywall/Paywall.types.js +0 -1
- package/dist/addons/paywall/index.js +1 -1
- package/dist/addons/providers/auth/index.js +1 -1
- package/dist/addons/providers/index.js +1 -1
- package/dist/addons/providers/keyboard/index.js +1 -1
- package/dist/addons/providers/nexus/index.js +1 -1
- package/dist/addons/providers/runtime/auth-provider.js +1 -172
- package/dist/addons/providers/runtime/config-provider.js +1 -11
- package/dist/addons/providers/runtime/index.js +1 -6
- package/dist/addons/providers/runtime/keyboard-provider.js +1 -106
- package/dist/addons/providers/runtime/nexus-provider.js +1 -10
- package/dist/addons/providers/runtime/theme-provider.js +1 -131
- package/dist/addons/providers/runtime/ui-overlay-provider.js +1 -36
- package/dist/addons/providers/theme/index.js +1 -1
- package/dist/addons/themes/index.js +1 -1
- package/dist/artstyles.js +1 -1
- package/dist/configs/themodcraft-v3/index.js +1 -1
- package/dist/index.js +1 -9
- package/dist/paywall.js +1 -1
- package/dist/providers/auth.js +1 -1
- package/dist/providers/keyboard.js +1 -1
- package/dist/providers/nexus.js +1 -1
- package/dist/providers/theme.js +1 -1
- package/dist/providers.js +1 -1
- package/dist/theme-packs/themodcraft-v3/color-scheme.css +1 -106
- package/dist/theme-packs/themodcraft-v3/index.js +1 -1
- package/package.json +12 -12
|
@@ -1,29 +1 @@
|
|
|
1
|
-
"use client";
|
|
2
|
-
import { jsx as _jsx } from "react/jsx-runtime";
|
|
3
|
-
import { useEffect, useRef, useState } from "react";
|
|
4
|
-
export function AnimatedNumber({ className, durationMs = 800, format = (value) => String(Math.round(value)), value, }) {
|
|
5
|
-
const [displayValue, setDisplayValue] = useState(value);
|
|
6
|
-
const displayValueRef = useRef(value);
|
|
7
|
-
useEffect(() => {
|
|
8
|
-
displayValueRef.current = displayValue;
|
|
9
|
-
}, [displayValue]);
|
|
10
|
-
useEffect(() => {
|
|
11
|
-
const start = performance.now();
|
|
12
|
-
const from = displayValueRef.current;
|
|
13
|
-
const delta = value - from;
|
|
14
|
-
let frame = 0;
|
|
15
|
-
function tick(now) {
|
|
16
|
-
const progress = Math.min((now - start) / durationMs, 1);
|
|
17
|
-
const eased = 1 - Math.pow(1 - progress, 3);
|
|
18
|
-
const nextValue = from + delta * eased;
|
|
19
|
-
displayValueRef.current = nextValue;
|
|
20
|
-
setDisplayValue(nextValue);
|
|
21
|
-
if (progress < 1) {
|
|
22
|
-
frame = requestAnimationFrame(tick);
|
|
23
|
-
}
|
|
24
|
-
}
|
|
25
|
-
frame = requestAnimationFrame(tick);
|
|
26
|
-
return () => cancelAnimationFrame(frame);
|
|
27
|
-
}, [durationMs, value]);
|
|
28
|
-
return _jsx("span", { className: className, children: format(displayValue) });
|
|
29
|
-
}
|
|
1
|
+
"use client";import{jsx as A}from"react/jsx-runtime";import{useEffect as m,useRef as V,useState as y}from"react";function j({className:u,durationMs:s=800,format:f=e=>String(Math.round(e)),value:t}){const[e,l]=y(t),n=V(t);return m(()=>{n.current=e},[e]),m(()=>{const p=performance.now(),a=n.current,d=t-a;let r=0;function o(h){const c=Math.min((h-p)/s,1),x=1-Math.pow(1-c,3),i=a+d*x;n.current=i,l(i),c<1&&(r=requestAnimationFrame(o))}return r=requestAnimationFrame(o),()=>cancelAnimationFrame(r)},[s,t]),A("span",{className:u,children:f(e)})}export{j as AnimatedNumber};
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export {};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
|
|
1
|
+
import{AnimatedNumber as r}from"./AnimatedNumber";export{r as AnimatedNumber};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
export
|
|
1
|
+
export*from"@themodcraft/addon-animations";
|
|
@@ -1,141 +1 @@
|
|
|
1
|
-
function
|
|
2
|
-
return Math.max(0, Math.min(255, Math.round(value)));
|
|
3
|
-
}
|
|
4
|
-
function clampAlpha(value) {
|
|
5
|
-
return Math.max(0, Math.min(1, value));
|
|
6
|
-
}
|
|
7
|
-
function toHexChannel(value) {
|
|
8
|
-
return clampChannel(value).toString(16).padStart(2, "0").toUpperCase();
|
|
9
|
-
}
|
|
10
|
-
function normalizeHex(hex) {
|
|
11
|
-
const value = hex.trim();
|
|
12
|
-
if (/^#([0-9A-Fa-f]{3})$/.test(value)) {
|
|
13
|
-
const [, shortHex] = value.match(/^#([0-9A-Fa-f]{3})$/) ?? [];
|
|
14
|
-
return `#${shortHex.split("").map((channel) => `${channel}${channel}`).join("")}`.toUpperCase();
|
|
15
|
-
}
|
|
16
|
-
if (/^#([0-9A-Fa-f]{6}|[0-9A-Fa-f]{8})$/.test(value)) {
|
|
17
|
-
return value.toUpperCase();
|
|
18
|
-
}
|
|
19
|
-
return null;
|
|
20
|
-
}
|
|
21
|
-
function hslToRgb({ h, l, s }) {
|
|
22
|
-
const hue = ((h % 360) + 360) % 360;
|
|
23
|
-
const saturation = Math.max(0, Math.min(100, s)) / 100;
|
|
24
|
-
const lightness = Math.max(0, Math.min(100, l)) / 100;
|
|
25
|
-
const chroma = (1 - Math.abs(2 * lightness - 1)) * saturation;
|
|
26
|
-
const x = chroma * (1 - Math.abs(((hue / 60) % 2) - 1));
|
|
27
|
-
const m = lightness - chroma / 2;
|
|
28
|
-
let r = 0;
|
|
29
|
-
let g = 0;
|
|
30
|
-
let b = 0;
|
|
31
|
-
if (hue < 60) {
|
|
32
|
-
r = chroma;
|
|
33
|
-
g = x;
|
|
34
|
-
}
|
|
35
|
-
else if (hue < 120) {
|
|
36
|
-
r = x;
|
|
37
|
-
g = chroma;
|
|
38
|
-
}
|
|
39
|
-
else if (hue < 180) {
|
|
40
|
-
g = chroma;
|
|
41
|
-
b = x;
|
|
42
|
-
}
|
|
43
|
-
else if (hue < 240) {
|
|
44
|
-
g = x;
|
|
45
|
-
b = chroma;
|
|
46
|
-
}
|
|
47
|
-
else if (hue < 300) {
|
|
48
|
-
r = x;
|
|
49
|
-
b = chroma;
|
|
50
|
-
}
|
|
51
|
-
else {
|
|
52
|
-
r = chroma;
|
|
53
|
-
b = x;
|
|
54
|
-
}
|
|
55
|
-
return {
|
|
56
|
-
b: clampChannel((b + m) * 255),
|
|
57
|
-
g: clampChannel((g + m) * 255),
|
|
58
|
-
r: clampChannel((r + m) * 255),
|
|
59
|
-
};
|
|
60
|
-
}
|
|
61
|
-
export function isValidHex(hex) {
|
|
62
|
-
return Boolean(normalizeHex(hex));
|
|
63
|
-
}
|
|
64
|
-
export function rgbToHex(rgb) {
|
|
65
|
-
const channels = rgb.match(/-?\d+(\.\d+)?/g)?.map(Number);
|
|
66
|
-
if (!channels || channels.length < 3) {
|
|
67
|
-
return null;
|
|
68
|
-
}
|
|
69
|
-
const [r, g, b] = channels;
|
|
70
|
-
return `#${toHexChannel(r)}${toHexChannel(g)}${toHexChannel(b)}`;
|
|
71
|
-
}
|
|
72
|
-
export function rgbaToHex({ a, b, g, r }) {
|
|
73
|
-
const alpha = typeof a === "number" ? toHexChannel(clampAlpha(a) * 255) : "";
|
|
74
|
-
return `#${toHexChannel(r)}${toHexChannel(g)}${toHexChannel(b)}${alpha}`;
|
|
75
|
-
}
|
|
76
|
-
export function hexToRgb(hex) {
|
|
77
|
-
const normalized = normalizeHex(hex);
|
|
78
|
-
if (!normalized) {
|
|
79
|
-
return null;
|
|
80
|
-
}
|
|
81
|
-
return {
|
|
82
|
-
b: parseInt(normalized.slice(5, 7), 16),
|
|
83
|
-
g: parseInt(normalized.slice(3, 5), 16),
|
|
84
|
-
r: parseInt(normalized.slice(1, 3), 16),
|
|
85
|
-
};
|
|
86
|
-
}
|
|
87
|
-
export function convertToHex(color) {
|
|
88
|
-
if (typeof color === "string") {
|
|
89
|
-
const normalizedHex = normalizeHex(color);
|
|
90
|
-
if (normalizedHex) {
|
|
91
|
-
return normalizedHex;
|
|
92
|
-
}
|
|
93
|
-
return rgbToHex(color);
|
|
94
|
-
}
|
|
95
|
-
if ("r" in color) {
|
|
96
|
-
return rgbaToHex(color);
|
|
97
|
-
}
|
|
98
|
-
const rgb = hslToRgb(color);
|
|
99
|
-
const alpha = typeof color.a === "number" ? toHexChannel(clampAlpha(color.a) * 255) : "";
|
|
100
|
-
return `${rgbaToHex(rgb)}${alpha}`;
|
|
101
|
-
}
|
|
102
|
-
export function shiftColorLightness(hex, amount) {
|
|
103
|
-
const rgb = hexToRgb(hex);
|
|
104
|
-
if (!rgb) {
|
|
105
|
-
return "#000000";
|
|
106
|
-
}
|
|
107
|
-
return rgbaToHex({
|
|
108
|
-
b: rgb.b + amount,
|
|
109
|
-
g: rgb.g + amount,
|
|
110
|
-
r: rgb.r + amount,
|
|
111
|
-
});
|
|
112
|
-
}
|
|
113
|
-
export function darken(hex, amount) {
|
|
114
|
-
return shiftColorLightness(hex, -Math.abs(amount));
|
|
115
|
-
}
|
|
116
|
-
export function lighten(hex, amount) {
|
|
117
|
-
return shiftColorLightness(hex, Math.abs(amount));
|
|
118
|
-
}
|
|
119
|
-
export function transformColor(hex, mode) {
|
|
120
|
-
const rgb = hexToRgb(hex);
|
|
121
|
-
if (!rgb) {
|
|
122
|
-
return "#000000";
|
|
123
|
-
}
|
|
124
|
-
if (mode === "contrast") {
|
|
125
|
-
const yiq = (rgb.r * 299 + rgb.g * 587 + rgb.b * 114) / 1000;
|
|
126
|
-
return yiq >= 128 ? "#000000" : "#FFFFFF";
|
|
127
|
-
}
|
|
128
|
-
if (mode === "invert") {
|
|
129
|
-
return rgbaToHex({
|
|
130
|
-
b: 255 - rgb.b,
|
|
131
|
-
g: 255 - rgb.g,
|
|
132
|
-
r: 255 - rgb.r,
|
|
133
|
-
});
|
|
134
|
-
}
|
|
135
|
-
const luma = 0.2126 * rgb.r + 0.7152 * rgb.g + 0.0722 * rgb.b;
|
|
136
|
-
return rgbaToHex({
|
|
137
|
-
b: luma,
|
|
138
|
-
g: luma,
|
|
139
|
-
r: luma,
|
|
140
|
-
});
|
|
141
|
-
}
|
|
1
|
+
function h(t){return Math.max(0,Math.min(255,Math.round(t)))}function x(t){return Math.max(0,Math.min(1,t))}function i(t){return h(t).toString(16).padStart(2,"0").toUpperCase()}function b(t){const n=t.trim();if(/^#([0-9A-Fa-f]{3})$/.test(n)){const[,r]=n.match(/^#([0-9A-Fa-f]{3})$/)??[];return`#${r.split("").map(e=>`${e}${e}`).join("")}`.toUpperCase()}return/^#([0-9A-Fa-f]{6}|[0-9A-Fa-f]{8})$/.test(n)?n.toUpperCase():null}function M({h:t,l:n,s:r}){const e=(t%360+360)%360,o=Math.max(0,Math.min(100,r))/100,g=Math.max(0,Math.min(100,n))/100,a=(1-Math.abs(2*g-1))*o,s=a*(1-Math.abs(e/60%2-1)),p=g-a/2;let u=0,f=0,c=0;return e<60?(u=a,f=s):e<120?(u=s,f=a):e<180?(f=a,c=s):e<240?(f=s,c=a):e<300?(u=s,c=a):(u=a,c=s),{b:h((c+p)*255),g:h((f+p)*255),r:h((u+p)*255)}}function H(t){return!!b(t)}function F(t){const n=t.match(/-?\d+(\.\d+)?/g)?.map(Number);if(!n||n.length<3)return null;const[r,e,o]=n;return`#${i(r)}${i(e)}${i(o)}`}function l({a:t,b:n,g:r,r:e}){const o=typeof t=="number"?i(x(t)*255):"";return`#${i(e)}${i(r)}${i(n)}${o}`}function m(t){const n=b(t);return n?{b:parseInt(n.slice(5,7),16),g:parseInt(n.slice(3,5),16),r:parseInt(n.slice(1,3),16)}:null}function d(t){if(typeof t=="string"){const e=b(t);return e||F(t)}if("r"in t)return l(t);const n=M(t),r=typeof t.a=="number"?i(x(t.a)*255):"";return`${l(n)}${r}`}function $(t,n){const r=m(t);return r?l({b:r.b+n,g:r.g+n,r:r.r+n}):"#000000"}function C(t,n){return $(t,-Math.abs(n))}function y(t,n){return $(t,Math.abs(n))}function A(t,n){const r=m(t);if(!r)return"#000000";if(n==="contrast")return(r.r*299+r.g*587+r.b*114)/1e3>=128?"#000000":"#FFFFFF";if(n==="invert")return l({b:255-r.b,g:255-r.g,r:255-r.r});const e=.2126*r.r+.7152*r.g+.0722*r.b;return l({b:e,g:e,r:e})}export{d as convertToHex,C as darken,m as hexToRgb,H as isValidHex,y as lighten,F as rgbToHex,l as rgbaToHex,$ as shiftColorLightness,A as transformColor};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
|
|
1
|
+
import{convertToHex as r,darken as t,hexToRgb as x,isValidHex as g,lighten as i,rgbaToHex as n,rgbToHex as s,shiftColorLightness as a,transformColor as h}from"./color-utils";export{r as convertToHex,t as darken,x as hexToRgb,g as isValidHex,i as lighten,s as rgbToHex,n as rgbaToHex,a as shiftColorLightness,h as transformColor};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
export
|
|
1
|
+
export*from"@themodcraft/addon-artstyles";
|
|
@@ -1 +1 @@
|
|
|
1
|
-
export
|
|
1
|
+
export*from"@themodcraft/addon-charts";
|
|
@@ -1,72 +1 @@
|
|
|
1
|
-
"use client";
|
|
2
|
-
import { jsx as _jsx } from "react/jsx-runtime";
|
|
3
|
-
import { BarElement, CategoryScale, Chart as ChartJS, LinearScale, Tooltip, } from "chart.js";
|
|
4
|
-
import { useMemo } from "react";
|
|
5
|
-
import { Bar } from "react-chartjs-2";
|
|
6
|
-
ChartJS.register(CategoryScale, LinearScale, BarElement, Tooltip);
|
|
7
|
-
function mergeChartOptions(baseOptions, chartOptions) {
|
|
8
|
-
return {
|
|
9
|
-
...baseOptions,
|
|
10
|
-
...chartOptions,
|
|
11
|
-
plugins: {
|
|
12
|
-
...baseOptions.plugins,
|
|
13
|
-
...chartOptions?.plugins,
|
|
14
|
-
},
|
|
15
|
-
scales: {
|
|
16
|
-
...baseOptions.scales,
|
|
17
|
-
...chartOptions?.scales,
|
|
18
|
-
},
|
|
19
|
-
};
|
|
20
|
-
}
|
|
21
|
-
export function MiniBarChart({ ariaLabel = "Mini bar chart", chartOptions, className, data, height, maxValue, showXAxis = false, showYAxis = true, }) {
|
|
22
|
-
const chartMax = maxValue ?? Math.max(...data.map((item) => item.value), 1);
|
|
23
|
-
const resolvedHeight = height ?? Math.max(data.length * 42, 120);
|
|
24
|
-
const chartData = useMemo(() => ({
|
|
25
|
-
labels: data.map((item) => item.label),
|
|
26
|
-
datasets: [
|
|
27
|
-
{
|
|
28
|
-
backgroundColor: data.map((item) => item.color ?? "#0b63ce"),
|
|
29
|
-
borderRadius: 6,
|
|
30
|
-
borderSkipped: false,
|
|
31
|
-
data: data.map((item) => item.value),
|
|
32
|
-
label: ariaLabel,
|
|
33
|
-
},
|
|
34
|
-
],
|
|
35
|
-
}), [ariaLabel, data]);
|
|
36
|
-
const options = useMemo(() => mergeChartOptions({
|
|
37
|
-
animation: {
|
|
38
|
-
duration: 220,
|
|
39
|
-
},
|
|
40
|
-
indexAxis: "y",
|
|
41
|
-
maintainAspectRatio: false,
|
|
42
|
-
plugins: {
|
|
43
|
-
legend: {
|
|
44
|
-
display: false,
|
|
45
|
-
},
|
|
46
|
-
tooltip: {
|
|
47
|
-
enabled: true,
|
|
48
|
-
},
|
|
49
|
-
},
|
|
50
|
-
responsive: true,
|
|
51
|
-
scales: {
|
|
52
|
-
x: {
|
|
53
|
-
beginAtZero: true,
|
|
54
|
-
display: showXAxis,
|
|
55
|
-
grid: {
|
|
56
|
-
display: showXAxis,
|
|
57
|
-
},
|
|
58
|
-
max: chartMax,
|
|
59
|
-
ticks: {
|
|
60
|
-
precision: 0,
|
|
61
|
-
},
|
|
62
|
-
},
|
|
63
|
-
y: {
|
|
64
|
-
display: showYAxis,
|
|
65
|
-
grid: {
|
|
66
|
-
display: false,
|
|
67
|
-
},
|
|
68
|
-
},
|
|
69
|
-
},
|
|
70
|
-
}, chartOptions), [chartMax, chartOptions, showXAxis, showYAxis]);
|
|
71
|
-
return (_jsx("div", { "aria-label": ariaLabel, className: className, role: "img", style: { height: resolvedHeight }, children: _jsx(Bar, { data: chartData, options: options }) }));
|
|
72
|
-
}
|
|
1
|
+
"use client";import{jsx as o}from"react/jsx-runtime";import{BarElement as f,CategoryScale as y,Chart as h,LinearScale as b,Tooltip as x}from"chart.js";import{useMemo as n}from"react";import{Bar as C}from"react-chartjs-2";h.register(y,b,f,x);function M(e,r){return{...e,...r,plugins:{...e.plugins,...r?.plugins},scales:{...e.scales,...r?.scales}}}function j({ariaLabel:e="Mini bar chart",chartOptions:r,className:p,data:l,height:m,maxValue:c,showXAxis:i=!1,showYAxis:t=!0}){const s=c??Math.max(...l.map(a=>a.value),1),u=m??Math.max(l.length*42,120),d=n(()=>({labels:l.map(a=>a.label),datasets:[{backgroundColor:l.map(a=>a.color??"#0b63ce"),borderRadius:6,borderSkipped:!1,data:l.map(a=>a.value),label:e}]}),[e,l]),g=n(()=>M({animation:{duration:220},indexAxis:"y",maintainAspectRatio:!1,plugins:{legend:{display:!1},tooltip:{enabled:!0}},responsive:!0,scales:{x:{beginAtZero:!0,display:i,grid:{display:i},max:s,ticks:{precision:0}},y:{display:t,grid:{display:!1}}}},r),[s,r,i,t]);return o("div",{"aria-label":e,className:p,role:"img",style:{height:u},children:o(C,{data:d,options:g})})}export{j as MiniBarChart};
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export {};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
|
|
1
|
+
import{MiniBarChart as i}from"./MiniBarChart";export{i as MiniBarChart};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
export
|
|
1
|
+
export*from"@themodcraft/addon-configs";
|
package/dist/addons/index.js
CHANGED
|
@@ -1,8 +1 @@
|
|
|
1
|
-
export
|
|
2
|
-
export * from "./animations";
|
|
3
|
-
export * from "./charts";
|
|
4
|
-
export * from "./configs";
|
|
5
|
-
export * from "./integrations";
|
|
6
|
-
export * from "./paywall";
|
|
7
|
-
export * from "./providers";
|
|
8
|
-
export * from "./themes";
|
|
1
|
+
export*from"./artstyles";export*from"./animations";export*from"./charts";export*from"./configs";export*from"./integrations";export*from"./paywall";export*from"./providers";export*from"./themes";
|
|
@@ -1,11 +1 @@
|
|
|
1
|
-
|
|
2
|
-
if (!session?.user) {
|
|
3
|
-
return null;
|
|
4
|
-
}
|
|
5
|
-
return {
|
|
6
|
-
email: session.user.email ?? null,
|
|
7
|
-
image: session.user.image ?? null,
|
|
8
|
-
name: session.user.name ?? null,
|
|
9
|
-
username: session.user.username ?? null,
|
|
10
|
-
};
|
|
11
|
-
}
|
|
1
|
+
function u(e){return e?.user?{email:e.user.email??null,image:e.user.image??null,name:e.user.name??null,username:e.user.username??null}:null}export{u as profileFromBetterAuthSession};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
export
|
|
1
|
+
export*from"@themodcraft/addon-integrations/better-auth";
|
|
@@ -1 +1 @@
|
|
|
1
|
-
export
|
|
1
|
+
export*from"@themodcraft/addon-integrations";
|
|
@@ -1,145 +1 @@
|
|
|
1
|
-
"use client";
|
|
2
|
-
import { jsxs as _jsxs, jsx as _jsx } from "react/jsx-runtime";
|
|
3
|
-
import { createContext, isValidElement, useCallback, useContext, useEffect, useMemo, useState, } from "react";
|
|
4
|
-
const PaywallContext = createContext(null);
|
|
5
|
-
function normalizeEntitlements(requiredEntitlements) {
|
|
6
|
-
if (!requiredEntitlements) {
|
|
7
|
-
return [];
|
|
8
|
-
}
|
|
9
|
-
return Array.isArray(requiredEntitlements)
|
|
10
|
-
? requiredEntitlements.filter(Boolean)
|
|
11
|
-
: [requiredEntitlements].filter(Boolean);
|
|
12
|
-
}
|
|
13
|
-
function checkEntitlements(entitlements, requiredEntitlements, mode = "all") {
|
|
14
|
-
const required = normalizeEntitlements(requiredEntitlements);
|
|
15
|
-
if (!required.length) {
|
|
16
|
-
return true;
|
|
17
|
-
}
|
|
18
|
-
if (mode === "any") {
|
|
19
|
-
return required.some((entitlement) => entitlements.includes(entitlement));
|
|
20
|
-
}
|
|
21
|
-
return required.every((entitlement) => entitlements.includes(entitlement));
|
|
22
|
-
}
|
|
23
|
-
function missingEntitlements(entitlements, requiredEntitlements, mode = "all") {
|
|
24
|
-
const required = normalizeEntitlements(requiredEntitlements);
|
|
25
|
-
if (mode === "any" && required.some((entitlement) => entitlements.includes(entitlement))) {
|
|
26
|
-
return [];
|
|
27
|
-
}
|
|
28
|
-
return required.filter((entitlement) => !entitlements.includes(entitlement));
|
|
29
|
-
}
|
|
30
|
-
function renderFallback(fallback, decision, actions) {
|
|
31
|
-
if (typeof fallback === "function" && !isValidElement(fallback)) {
|
|
32
|
-
return fallback(decision, actions);
|
|
33
|
-
}
|
|
34
|
-
return fallback;
|
|
35
|
-
}
|
|
36
|
-
function DefaultPaywallFallback({ decision, startCheckout, }) {
|
|
37
|
-
const planLabel = decision.plan?.label ?? "Pro";
|
|
38
|
-
return (_jsxs("div", { role: "group", style: { border: "1px solid var(--tmc-color-border, #d7dde5)", borderRadius: "8px", padding: "16px" }, children: [_jsxs("p", { style: { color: "var(--tmc-color-text, #111827)", fontWeight: 600, margin: 0 }, children: [planLabel, " access required"] }), _jsx("p", { style: { color: "var(--tmc-color-text-muted, #5f6b7a)", margin: "8px 0 0" }, children: "This package area is locked until the required entitlement is active." }), _jsx("button", { onClick: () => void startCheckout(), style: { background: "var(--tmc-color-accent, #0b63ce)", border: 0, borderRadius: "6px", color: "var(--tmc-color-accent-text, #ffffff)", cursor: "pointer", marginTop: "12px", padding: "8px 12px" }, type: "button", children: "Unlock" })] }));
|
|
39
|
-
}
|
|
40
|
-
export function PaywallProvider({ checkoutUrl, children, defaultFallback, entitlements = [], onCheckout, plans = [], resolveEntitlements, status = "ready", }) {
|
|
41
|
-
const [resolvedEntitlements, setResolvedEntitlements] = useState(entitlements);
|
|
42
|
-
const [resolvedStatus, setResolvedStatus] = useState(status);
|
|
43
|
-
useEffect(() => {
|
|
44
|
-
setResolvedEntitlements(entitlements);
|
|
45
|
-
setResolvedStatus(status);
|
|
46
|
-
}, [entitlements, status]);
|
|
47
|
-
const refreshEntitlements = useCallback(async () => {
|
|
48
|
-
if (!resolveEntitlements) {
|
|
49
|
-
return resolvedEntitlements;
|
|
50
|
-
}
|
|
51
|
-
setResolvedStatus("loading");
|
|
52
|
-
try {
|
|
53
|
-
const nextEntitlements = await resolveEntitlements();
|
|
54
|
-
setResolvedEntitlements(nextEntitlements);
|
|
55
|
-
setResolvedStatus("ready");
|
|
56
|
-
return nextEntitlements;
|
|
57
|
-
}
|
|
58
|
-
catch {
|
|
59
|
-
setResolvedStatus("error");
|
|
60
|
-
return [];
|
|
61
|
-
}
|
|
62
|
-
}, [resolveEntitlements, resolvedEntitlements]);
|
|
63
|
-
useEffect(() => {
|
|
64
|
-
if (!resolveEntitlements) {
|
|
65
|
-
return;
|
|
66
|
-
}
|
|
67
|
-
void refreshEntitlements();
|
|
68
|
-
}, [refreshEntitlements, resolveEntitlements]);
|
|
69
|
-
const getDecision = useCallback((requiredEntitlements, mode = "all", planId) => {
|
|
70
|
-
const required = normalizeEntitlements(requiredEntitlements);
|
|
71
|
-
const plan = plans.find((currentPlan) => currentPlan.id === planId) ?? plans.find((currentPlan) => currentPlan.entitlements?.some((entitlement) => required.includes(entitlement)));
|
|
72
|
-
const allowed = resolvedStatus === "ready" && checkEntitlements(resolvedEntitlements, required, mode);
|
|
73
|
-
return {
|
|
74
|
-
allowed,
|
|
75
|
-
missingEntitlements: missingEntitlements(resolvedEntitlements, required, mode),
|
|
76
|
-
plan,
|
|
77
|
-
requiredEntitlements: required,
|
|
78
|
-
status: resolvedStatus,
|
|
79
|
-
};
|
|
80
|
-
}, [plans, resolvedEntitlements, resolvedStatus]);
|
|
81
|
-
const hasEntitlements = useCallback((requiredEntitlements, mode = "all") => (getDecision(requiredEntitlements, mode).allowed), [getDecision]);
|
|
82
|
-
const startCheckout = useCallback(async (planId, decision) => {
|
|
83
|
-
const plan = plans.find((currentPlan) => currentPlan.id === planId) ?? decision?.plan;
|
|
84
|
-
const nextDecision = decision ?? getDecision(plan?.entitlements, "all", plan?.id);
|
|
85
|
-
if (onCheckout) {
|
|
86
|
-
await onCheckout(plan, nextDecision);
|
|
87
|
-
return;
|
|
88
|
-
}
|
|
89
|
-
const url = plan?.checkoutUrl ?? checkoutUrl;
|
|
90
|
-
if (url && typeof window !== "undefined") {
|
|
91
|
-
window.location.href = url;
|
|
92
|
-
}
|
|
93
|
-
}, [checkoutUrl, getDecision, onCheckout, plans]);
|
|
94
|
-
const value = useMemo(() => ({
|
|
95
|
-
checkoutUrl,
|
|
96
|
-
defaultFallback,
|
|
97
|
-
entitlements: resolvedEntitlements,
|
|
98
|
-
getDecision,
|
|
99
|
-
hasEntitlements,
|
|
100
|
-
plans,
|
|
101
|
-
refreshEntitlements,
|
|
102
|
-
startCheckout,
|
|
103
|
-
status: resolvedStatus,
|
|
104
|
-
}), [
|
|
105
|
-
checkoutUrl,
|
|
106
|
-
defaultFallback,
|
|
107
|
-
getDecision,
|
|
108
|
-
hasEntitlements,
|
|
109
|
-
plans,
|
|
110
|
-
refreshEntitlements,
|
|
111
|
-
resolvedEntitlements,
|
|
112
|
-
resolvedStatus,
|
|
113
|
-
startCheckout,
|
|
114
|
-
]);
|
|
115
|
-
return _jsx(PaywallContext.Provider, { value: value, children: children });
|
|
116
|
-
}
|
|
117
|
-
export function usePaywall() {
|
|
118
|
-
const context = useContext(PaywallContext);
|
|
119
|
-
if (!context) {
|
|
120
|
-
throw new Error("usePaywall must be used inside PaywallProvider.");
|
|
121
|
-
}
|
|
122
|
-
return context;
|
|
123
|
-
}
|
|
124
|
-
export function useOptionalPaywall() {
|
|
125
|
-
return useContext(PaywallContext);
|
|
126
|
-
}
|
|
127
|
-
export function PaywallGate({ children, fallback, loadingFallback = null, mode = "all", planId, required, }) {
|
|
128
|
-
const paywall = usePaywall();
|
|
129
|
-
const decision = paywall.getDecision(required, mode, planId);
|
|
130
|
-
const actions = {
|
|
131
|
-
refreshEntitlements: paywall.refreshEntitlements,
|
|
132
|
-
startCheckout: () => paywall.startCheckout(planId, decision),
|
|
133
|
-
};
|
|
134
|
-
if (decision.status === "loading") {
|
|
135
|
-
return loadingFallback;
|
|
136
|
-
}
|
|
137
|
-
if (decision.allowed) {
|
|
138
|
-
return children;
|
|
139
|
-
}
|
|
140
|
-
const renderedFallback = renderFallback(fallback ?? paywall.defaultFallback, decision, actions);
|
|
141
|
-
if (renderedFallback) {
|
|
142
|
-
return renderedFallback;
|
|
143
|
-
}
|
|
144
|
-
return _jsx(DefaultPaywallFallback, { decision: decision, startCheckout: actions.startCheckout });
|
|
145
|
-
}
|
|
1
|
+
"use client";import{jsxs as D,jsx as g}from"react/jsx-runtime";import{createContext as B,isValidElement as T,useCallback as v,useContext as R,useEffect as q,useMemo as _,useState as F}from"react";const P=B(null);function k(e){return e?Array.isArray(e)?e.filter(Boolean):[e].filter(Boolean):[]}function z(e,o,r="all"){const n=k(o);return n.length?r==="any"?n.some(t=>e.includes(t)):n.every(t=>e.includes(t)):!0}function G(e,o,r="all"){const n=k(o);return r==="any"&&n.some(t=>e.includes(t))?[]:n.filter(t=>!e.includes(t))}function L(e,o,r){return typeof e=="function"&&!T(e)?e(o,r):e}function M({decision:e,startCheckout:o}){const r=e.plan?.label??"Pro";return D("div",{role:"group",style:{border:"1px solid var(--tmc-color-border, #d7dde5)",borderRadius:"8px",padding:"16px"},children:[D("p",{style:{color:"var(--tmc-color-text, #111827)",fontWeight:600,margin:0},children:[r," access required"]}),g("p",{style:{color:"var(--tmc-color-text-muted, #5f6b7a)",margin:"8px 0 0"},children:"This package area is locked until the required entitlement is active."}),g("button",{onClick:()=>{o()},style:{background:"var(--tmc-color-accent, #0b63ce)",border:0,borderRadius:"6px",color:"var(--tmc-color-accent-text, #ffffff)",cursor:"pointer",marginTop:"12px",padding:"8px 12px"},type:"button",children:"Unlock"})]})}function H({checkoutUrl:e,children:o,defaultFallback:r,entitlements:n=[],onCheckout:t,plans:a=[],resolveEntitlements:i,status:s="ready"}){const[l,m]=F(n),[p,x]=F(s);q(()=>{m(n),x(s)},[n,s]);const w=v(async()=>{if(!i)return l;x("loading");try{const c=await i();return m(c),x("ready"),c}catch{return x("error"),[]}},[i,l]);q(()=>{i&&w()},[w,i]);const d=v((c,u="all",f)=>{const y=k(c),h=a.find(b=>b.id===f)??a.find(b=>b.entitlements?.some(A=>y.includes(A)));return{allowed:p==="ready"&&z(l,y,u),missingEntitlements:G(l,y,u),plan:h,requiredEntitlements:y,status:p}},[a,l,p]),C=v((c,u="all")=>d(c,u).allowed,[d]),E=v(async(c,u)=>{const f=a.find(j=>j.id===c)??u?.plan,y=u??d(f?.entitlements,"all",f?.id);if(t){await t(f,y);return}const h=f?.checkoutUrl??e;h&&typeof window<"u"&&(window.location.href=h)},[e,d,t,a]),S=_(()=>({checkoutUrl:e,defaultFallback:r,entitlements:l,getDecision:d,hasEntitlements:C,plans:a,refreshEntitlements:w,startCheckout:E,status:p}),[e,r,d,C,a,w,l,p,E]);return g(P.Provider,{value:S,children:o})}function O(){const e=R(P);if(!e)throw new Error("usePaywall must be used inside PaywallProvider.");return e}function J(){return R(P)}function K({children:e,fallback:o,loadingFallback:r=null,mode:n="all",planId:t,required:a}){const i=O(),s=i.getDecision(a,n,t),l={refreshEntitlements:i.refreshEntitlements,startCheckout:()=>i.startCheckout(t,s)};if(s.status==="loading")return r;if(s.allowed)return e;const m=L(o??i.defaultFallback,s,l);return m||g(M,{decision:s,startCheckout:l.startCheckout})}export{K as PaywallGate,H as PaywallProvider,J as useOptionalPaywall,O as usePaywall};
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export {};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
export
|
|
1
|
+
export*from"@themodcraft/addon-paywall";
|
|
@@ -1 +1 @@
|
|
|
1
|
-
export
|
|
1
|
+
export*from"@themodcraft/addon-providers/auth";
|
|
@@ -1 +1 @@
|
|
|
1
|
-
export
|
|
1
|
+
export*from"@themodcraft/addon-providers";
|
|
@@ -1 +1 @@
|
|
|
1
|
-
export
|
|
1
|
+
export*from"@themodcraft/addon-providers/keyboard";
|
|
@@ -1 +1 @@
|
|
|
1
|
-
export
|
|
1
|
+
export*from"@themodcraft/addon-providers/nexus";
|
|
@@ -1,172 +1 @@
|
|
|
1
|
-
"use client";
|
|
2
|
-
import { jsx as _jsx } from "react/jsx-runtime";
|
|
3
|
-
import { createContext, useCallback, useContext, useEffect, useMemo, useState, } from "react";
|
|
4
|
-
const AuthContext = createContext(null);
|
|
5
|
-
const authEventName = "tmc:nexus-auth";
|
|
6
|
-
function statusFromUser(user, fallback) {
|
|
7
|
-
if (fallback) {
|
|
8
|
-
return fallback;
|
|
9
|
-
}
|
|
10
|
-
return user ? "authenticated" : "anonymous";
|
|
11
|
-
}
|
|
12
|
-
function readStoredAuthSnapshot(storageKey) {
|
|
13
|
-
if (!storageKey || typeof window === "undefined") {
|
|
14
|
-
return null;
|
|
15
|
-
}
|
|
16
|
-
try {
|
|
17
|
-
const rawSnapshot = window.localStorage.getItem(storageKey);
|
|
18
|
-
return rawSnapshot ? JSON.parse(rawSnapshot) : null;
|
|
19
|
-
}
|
|
20
|
-
catch {
|
|
21
|
-
return null;
|
|
22
|
-
}
|
|
23
|
-
}
|
|
24
|
-
function writeStoredAuthSnapshot(storageKey, snapshot) {
|
|
25
|
-
if (!storageKey || typeof window === "undefined") {
|
|
26
|
-
return;
|
|
27
|
-
}
|
|
28
|
-
if (!snapshot) {
|
|
29
|
-
window.localStorage.removeItem(storageKey);
|
|
30
|
-
window.dispatchEvent(new CustomEvent(authEventName, { detail: null }));
|
|
31
|
-
return;
|
|
32
|
-
}
|
|
33
|
-
window.localStorage.setItem(storageKey, JSON.stringify(snapshot));
|
|
34
|
-
window.dispatchEvent(new CustomEvent(authEventName, { detail: snapshot }));
|
|
35
|
-
}
|
|
36
|
-
export function AuthProvider({ children, loginUrl, logoutUrl, onLogout, profileImage, refreshOnMount = true, resolveProfileImage, resolveUser, settingsUrl, status, storageKey = "tmc-nexus-auth", user: initialUser = null, }) {
|
|
37
|
-
const [user, setUserState] = useState(initialUser);
|
|
38
|
-
const [resolvedProfileImage, setResolvedProfileImage] = useState(profileImage ?? initialUser?.image ?? null);
|
|
39
|
-
const [resolvedStatus, setResolvedStatus] = useState(statusFromUser(initialUser, status));
|
|
40
|
-
useEffect(() => {
|
|
41
|
-
const storedSnapshot = readStoredAuthSnapshot(storageKey);
|
|
42
|
-
if (storedSnapshot) {
|
|
43
|
-
setUserState(storedSnapshot.user);
|
|
44
|
-
setResolvedProfileImage(storedSnapshot.profileImage);
|
|
45
|
-
setResolvedStatus(storedSnapshot.status);
|
|
46
|
-
return;
|
|
47
|
-
}
|
|
48
|
-
setUserState(initialUser);
|
|
49
|
-
setResolvedProfileImage(profileImage ?? initialUser?.image ?? null);
|
|
50
|
-
setResolvedStatus(statusFromUser(initialUser, status));
|
|
51
|
-
}, [initialUser, profileImage, status, storageKey]);
|
|
52
|
-
useEffect(() => {
|
|
53
|
-
function handleStorage(event) {
|
|
54
|
-
if (event.key !== storageKey) {
|
|
55
|
-
return;
|
|
56
|
-
}
|
|
57
|
-
const snapshot = readStoredAuthSnapshot(storageKey);
|
|
58
|
-
setUserState(snapshot?.user ?? null);
|
|
59
|
-
setResolvedProfileImage(snapshot?.profileImage ?? null);
|
|
60
|
-
setResolvedStatus(snapshot?.status ?? "anonymous");
|
|
61
|
-
}
|
|
62
|
-
function handleAuthEvent(event) {
|
|
63
|
-
const snapshot = event.detail;
|
|
64
|
-
setUserState(snapshot?.user ?? null);
|
|
65
|
-
setResolvedProfileImage(snapshot?.profileImage ?? null);
|
|
66
|
-
setResolvedStatus(snapshot?.status ?? "anonymous");
|
|
67
|
-
}
|
|
68
|
-
window.addEventListener("storage", handleStorage);
|
|
69
|
-
window.addEventListener(authEventName, handleAuthEvent);
|
|
70
|
-
return () => {
|
|
71
|
-
window.removeEventListener("storage", handleStorage);
|
|
72
|
-
window.removeEventListener(authEventName, handleAuthEvent);
|
|
73
|
-
};
|
|
74
|
-
}, [storageKey]);
|
|
75
|
-
const refreshUser = useCallback(async () => {
|
|
76
|
-
if (!resolveUser) {
|
|
77
|
-
return user;
|
|
78
|
-
}
|
|
79
|
-
setResolvedStatus("loading");
|
|
80
|
-
const nextUser = await resolveUser();
|
|
81
|
-
const nextProfileImage = resolveProfileImage
|
|
82
|
-
? await resolveProfileImage(nextUser)
|
|
83
|
-
: nextUser?.image ?? null;
|
|
84
|
-
setUserState(nextUser);
|
|
85
|
-
setResolvedProfileImage(nextProfileImage);
|
|
86
|
-
setResolvedStatus(nextUser ? "authenticated" : "anonymous");
|
|
87
|
-
writeStoredAuthSnapshot(storageKey, {
|
|
88
|
-
profileImage: nextProfileImage,
|
|
89
|
-
status: nextUser ? "authenticated" : "anonymous",
|
|
90
|
-
user: nextUser,
|
|
91
|
-
});
|
|
92
|
-
return nextUser;
|
|
93
|
-
}, [resolveProfileImage, resolveUser, storageKey, user]);
|
|
94
|
-
useEffect(() => {
|
|
95
|
-
if (!refreshOnMount || !resolveUser) {
|
|
96
|
-
return;
|
|
97
|
-
}
|
|
98
|
-
let cancelled = false;
|
|
99
|
-
async function refresh() {
|
|
100
|
-
const nextUser = await resolveUser?.();
|
|
101
|
-
if (cancelled) {
|
|
102
|
-
return;
|
|
103
|
-
}
|
|
104
|
-
const nextProfileImage = resolveProfileImage
|
|
105
|
-
? await resolveProfileImage(nextUser ?? null)
|
|
106
|
-
: nextUser?.image ?? null;
|
|
107
|
-
if (!cancelled) {
|
|
108
|
-
setUserState(nextUser ?? null);
|
|
109
|
-
setResolvedProfileImage(nextProfileImage);
|
|
110
|
-
setResolvedStatus(nextUser ? "authenticated" : "anonymous");
|
|
111
|
-
writeStoredAuthSnapshot(storageKey, {
|
|
112
|
-
profileImage: nextProfileImage,
|
|
113
|
-
status: nextUser ? "authenticated" : "anonymous",
|
|
114
|
-
user: nextUser ?? null,
|
|
115
|
-
});
|
|
116
|
-
}
|
|
117
|
-
}
|
|
118
|
-
refresh();
|
|
119
|
-
return () => {
|
|
120
|
-
cancelled = true;
|
|
121
|
-
};
|
|
122
|
-
}, [refreshOnMount, resolveProfileImage, resolveUser, storageKey]);
|
|
123
|
-
const setUser = useCallback((nextUser) => {
|
|
124
|
-
const nextProfileImage = nextUser?.image ?? null;
|
|
125
|
-
const nextStatus = nextUser ? "authenticated" : "anonymous";
|
|
126
|
-
setUserState(nextUser);
|
|
127
|
-
setResolvedProfileImage(nextProfileImage);
|
|
128
|
-
setResolvedStatus(nextStatus);
|
|
129
|
-
writeStoredAuthSnapshot(storageKey, {
|
|
130
|
-
profileImage: nextProfileImage,
|
|
131
|
-
status: nextStatus,
|
|
132
|
-
user: nextUser,
|
|
133
|
-
});
|
|
134
|
-
}, [storageKey]);
|
|
135
|
-
const logout = useCallback(async () => {
|
|
136
|
-
await onLogout?.();
|
|
137
|
-
setUser(null);
|
|
138
|
-
writeStoredAuthSnapshot(storageKey, null);
|
|
139
|
-
}, [onLogout, setUser, storageKey]);
|
|
140
|
-
const value = useMemo(() => ({
|
|
141
|
-
loginUrl,
|
|
142
|
-
logout,
|
|
143
|
-
logoutUrl,
|
|
144
|
-
profileImage: resolvedProfileImage,
|
|
145
|
-
refreshUser,
|
|
146
|
-
setUser,
|
|
147
|
-
settingsUrl,
|
|
148
|
-
status: resolvedStatus,
|
|
149
|
-
user,
|
|
150
|
-
}), [
|
|
151
|
-
loginUrl,
|
|
152
|
-
logout,
|
|
153
|
-
logoutUrl,
|
|
154
|
-
refreshUser,
|
|
155
|
-
resolvedProfileImage,
|
|
156
|
-
resolvedStatus,
|
|
157
|
-
setUser,
|
|
158
|
-
settingsUrl,
|
|
159
|
-
user,
|
|
160
|
-
]);
|
|
161
|
-
return _jsx(AuthContext.Provider, { value: value, children: children });
|
|
162
|
-
}
|
|
163
|
-
export function useAuth() {
|
|
164
|
-
const context = useContext(AuthContext);
|
|
165
|
-
if (!context) {
|
|
166
|
-
throw new Error("useAuth must be used inside AuthProvider.");
|
|
167
|
-
}
|
|
168
|
-
return context;
|
|
169
|
-
}
|
|
170
|
-
export function useOptionalAuth() {
|
|
171
|
-
return useContext(AuthContext);
|
|
172
|
-
}
|
|
1
|
+
"use client";import{jsx as F}from"react/jsx-runtime";import{createContext as _,useCallback as v,useContext as b,useEffect as E,useMemo as q,useState as A}from"react";const I=_(null),h="tmc:nexus-auth";function g(n,o){return o||(n?"authenticated":"anonymous")}function k(n){if(!n||typeof window>"u")return null;try{const o=window.localStorage.getItem(n);return o?JSON.parse(o):null}catch{return null}}function p(n,o){if(!(!n||typeof window>"u")){if(!o){window.localStorage.removeItem(n),window.dispatchEvent(new CustomEvent(h,{detail:null}));return}window.localStorage.setItem(n,JSON.stringify(o)),window.dispatchEvent(new CustomEvent(h,{detail:o}))}}function D({children:n,loginUrl:o,logoutUrl:C,onLogout:L,profileImage:S,refreshOnMount:N=!0,resolveProfileImage:d,resolveUser:m,settingsUrl:P,status:x,storageKey:u="tmc-nexus-auth",user:i=null}){const[f,c]=A(i),[j,l]=A(S??i?.image??null),[J,r]=A(g(i,x));E(()=>{const t=k(u);if(t){c(t.user),l(t.profileImage),r(t.status);return}c(i),l(S??i?.image??null),r(g(i,x))},[i,S,x,u]),E(()=>{function t(e){if(e.key!==u)return;const s=k(u);c(s?.user??null),l(s?.profileImage??null),r(s?.status??"anonymous")}function a(e){const s=e.detail;c(s?.user??null),l(s?.profileImage??null),r(s?.status??"anonymous")}return window.addEventListener("storage",t),window.addEventListener(h,a),()=>{window.removeEventListener("storage",t),window.removeEventListener(h,a)}},[u]);const O=v(async()=>{if(!m)return f;r("loading");const t=await m(),a=d?await d(t):t?.image??null;return c(t),l(a),r(t?"authenticated":"anonymous"),p(u,{profileImage:a,status:t?"authenticated":"anonymous",user:t}),t},[d,m,u,f]);E(()=>{if(!N||!m)return;let t=!1;async function a(){const e=await m?.();if(t)return;const s=d?await d(e??null):e?.image??null;t||(c(e??null),l(s),r(e?"authenticated":"anonymous"),p(u,{profileImage:s,status:e?"authenticated":"anonymous",user:e??null}))}return a(),()=>{t=!0}},[N,d,m,u]);const w=v(t=>{const a=t?.image??null,e=t?"authenticated":"anonymous";c(t),l(a),r(e),p(u,{profileImage:a,status:e,user:t})},[u]),R=v(async()=>{await L?.(),w(null),p(u,null)},[L,w,u]),y=q(()=>({loginUrl:o,logout:R,logoutUrl:C,profileImage:j,refreshUser:O,setUser:w,settingsUrl:P,status:J,user:f}),[o,R,C,O,j,J,w,P,f]);return F(I.Provider,{value:y,children:n})}function G(){const n=b(I);if(!n)throw new Error("useAuth must be used inside AuthProvider.");return n}function H(){return b(I)}export{D as AuthProvider,G as useAuth,H as useOptionalAuth};
|
|
@@ -1,11 +1 @@
|
|
|
1
|
-
"use client";
|
|
2
|
-
import { jsx as _jsx } from "react/jsx-runtime";
|
|
3
|
-
import { createContext, useContext, useMemo, } from "react";
|
|
4
|
-
const ConfigContext = createContext({});
|
|
5
|
-
export function ConfigProvider({ children, config = {} }) {
|
|
6
|
-
const value = useMemo(() => config, [config]);
|
|
7
|
-
return _jsx(ConfigContext.Provider, { value: value, children: children });
|
|
8
|
-
}
|
|
9
|
-
export function useConfig() {
|
|
10
|
-
return useContext(ConfigContext);
|
|
11
|
-
}
|
|
1
|
+
"use client";import{jsx as n}from"react/jsx-runtime";import{createContext as i,useContext as u,useMemo as s}from"react";const o=i({});function f({children:t,config:e={}}){const r=s(()=>e,[e]);return n(o.Provider,{value:r,children:t})}function C(){return u(o)}export{f as ConfigProvider,C as useConfig};
|
|
@@ -1,6 +1 @@
|
|
|
1
|
-
export
|
|
2
|
-
export * from "./config-provider";
|
|
3
|
-
export * from "./keyboard-provider";
|
|
4
|
-
export * from "./nexus-provider";
|
|
5
|
-
export * from "./theme-provider";
|
|
6
|
-
export * from "./ui-overlay-provider";
|
|
1
|
+
export*from"./auth-provider";export*from"./config-provider";export*from"./keyboard-provider";export*from"./nexus-provider";export*from"./theme-provider";export*from"./ui-overlay-provider";
|
|
@@ -1,106 +1 @@
|
|
|
1
|
-
"use client";
|
|
2
|
-
import { jsx as _jsx } from "react/jsx-runtime";
|
|
3
|
-
import { createContext, useCallback, useContext, useEffect, useMemo, useRef, } from "react";
|
|
4
|
-
const defaultFocusSelector = [
|
|
5
|
-
"a[href]",
|
|
6
|
-
"button:not([disabled])",
|
|
7
|
-
"input:not([disabled])",
|
|
8
|
-
"select:not([disabled])",
|
|
9
|
-
"textarea:not([disabled])",
|
|
10
|
-
"[tabindex]:not([tabindex='-1'])",
|
|
11
|
-
"[data-keyboard-focusable='true']",
|
|
12
|
-
].join(",");
|
|
13
|
-
const KeyboardContext = createContext(null);
|
|
14
|
-
function isEditableTarget(target) {
|
|
15
|
-
if (!(target instanceof HTMLElement)) {
|
|
16
|
-
return false;
|
|
17
|
-
}
|
|
18
|
-
return (target.isContentEditable ||
|
|
19
|
-
target instanceof HTMLInputElement ||
|
|
20
|
-
target instanceof HTMLSelectElement ||
|
|
21
|
-
target instanceof HTMLTextAreaElement);
|
|
22
|
-
}
|
|
23
|
-
function matchesShortcut(event, shortcut) {
|
|
24
|
-
return (shortcut.enabled !== false &&
|
|
25
|
-
event.key.toLowerCase() === shortcut.key.toLowerCase() &&
|
|
26
|
-
Boolean(event.altKey) === Boolean(shortcut.altKey) &&
|
|
27
|
-
Boolean(event.ctrlKey) === Boolean(shortcut.ctrlKey) &&
|
|
28
|
-
Boolean(event.metaKey) === Boolean(shortcut.metaKey) &&
|
|
29
|
-
Boolean(event.shiftKey) === Boolean(shortcut.shiftKey));
|
|
30
|
-
}
|
|
31
|
-
function getFocusableElements(selector) {
|
|
32
|
-
return Array.from(document.querySelectorAll(selector)).filter((element) => {
|
|
33
|
-
const style = window.getComputedStyle(element);
|
|
34
|
-
return !element.hasAttribute("disabled") && style.display !== "none" && style.visibility !== "hidden";
|
|
35
|
-
});
|
|
36
|
-
}
|
|
37
|
-
export function KeyboardProvider({ children, focusSelector = defaultFocusSelector, shortcuts = [], }) {
|
|
38
|
-
const shortcutsRef = useRef(new Map());
|
|
39
|
-
useEffect(() => {
|
|
40
|
-
shortcutsRef.current = new Map(shortcuts.map((shortcut) => [shortcut.id, shortcut]));
|
|
41
|
-
}, [shortcuts]);
|
|
42
|
-
useEffect(() => {
|
|
43
|
-
function handleKeyDown(event) {
|
|
44
|
-
for (const shortcut of shortcutsRef.current.values()) {
|
|
45
|
-
if (!matchesShortcut(event, shortcut)) {
|
|
46
|
-
continue;
|
|
47
|
-
}
|
|
48
|
-
if (!shortcut.allowInEditable && isEditableTarget(event.target)) {
|
|
49
|
-
continue;
|
|
50
|
-
}
|
|
51
|
-
if (shortcut.preventDefault ?? true) {
|
|
52
|
-
event.preventDefault();
|
|
53
|
-
}
|
|
54
|
-
shortcut.handler(event);
|
|
55
|
-
}
|
|
56
|
-
}
|
|
57
|
-
window.addEventListener("keydown", handleKeyDown);
|
|
58
|
-
return () => window.removeEventListener("keydown", handleKeyDown);
|
|
59
|
-
}, []);
|
|
60
|
-
const registerShortcut = useCallback((shortcut) => {
|
|
61
|
-
shortcutsRef.current.set(shortcut.id, shortcut);
|
|
62
|
-
return () => {
|
|
63
|
-
shortcutsRef.current.delete(shortcut.id);
|
|
64
|
-
};
|
|
65
|
-
}, []);
|
|
66
|
-
const focusByOffset = useCallback((offset, selector = focusSelector) => {
|
|
67
|
-
const elements = getFocusableElements(selector);
|
|
68
|
-
if (!elements.length) {
|
|
69
|
-
return;
|
|
70
|
-
}
|
|
71
|
-
const currentIndex = document.activeElement instanceof HTMLElement
|
|
72
|
-
? elements.indexOf(document.activeElement)
|
|
73
|
-
: -1;
|
|
74
|
-
const nextIndex = currentIndex === -1
|
|
75
|
-
? 0
|
|
76
|
-
: (currentIndex + offset + elements.length) % elements.length;
|
|
77
|
-
elements[nextIndex]?.focus();
|
|
78
|
-
}, [focusSelector]);
|
|
79
|
-
const value = useMemo(() => ({
|
|
80
|
-
focusFirst: (selector = focusSelector) => getFocusableElements(selector)[0]?.focus(),
|
|
81
|
-
focusNext: (selector = focusSelector) => focusByOffset(1, selector),
|
|
82
|
-
focusPrevious: (selector = focusSelector) => focusByOffset(-1, selector),
|
|
83
|
-
registerShortcut,
|
|
84
|
-
}), [focusByOffset, focusSelector, registerShortcut]);
|
|
85
|
-
return _jsx(KeyboardContext.Provider, { value: value, children: children });
|
|
86
|
-
}
|
|
87
|
-
export function useKeyboard() {
|
|
88
|
-
const context = useContext(KeyboardContext);
|
|
89
|
-
if (!context) {
|
|
90
|
-
throw new Error("useKeyboard must be used inside KeyboardProvider.");
|
|
91
|
-
}
|
|
92
|
-
return context;
|
|
93
|
-
}
|
|
94
|
-
export function useOptionalKeyboard() {
|
|
95
|
-
return useContext(KeyboardContext);
|
|
96
|
-
}
|
|
97
|
-
export function useKeyboardShortcut(shortcut) {
|
|
98
|
-
const keyboard = useKeyboard();
|
|
99
|
-
useEffect(() => keyboard.registerShortcut(shortcut), [keyboard, shortcut]);
|
|
100
|
-
}
|
|
101
|
-
export function handleKeyboardClick(event, callback) {
|
|
102
|
-
if (event.key === "Enter" || event.key === " ") {
|
|
103
|
-
event.preventDefault();
|
|
104
|
-
callback();
|
|
105
|
-
}
|
|
106
|
-
}
|
|
1
|
+
"use client";import{jsx as p}from"react/jsx-runtime";import{createContext as K,useCallback as f,useContext as y,useEffect as s,useMemo as w,useRef as E}from"react";const h=["a[href]","button:not([disabled])","input:not([disabled])","select:not([disabled])","textarea:not([disabled])","[tabindex]:not([tabindex='-1'])","[data-keyboard-focusable='true']"].join(","),u=K(null);function k(e){return e instanceof HTMLElement?e.isContentEditable||e instanceof HTMLInputElement||e instanceof HTMLSelectElement||e instanceof HTMLTextAreaElement:!1}function B(e,n){return n.enabled!==!1&&e.key.toLowerCase()===n.key.toLowerCase()&&!!e.altKey==!!n.altKey&&!!e.ctrlKey==!!n.ctrlKey&&!!e.metaKey==!!n.metaKey&&!!e.shiftKey==!!n.shiftKey}function b(e){return Array.from(document.querySelectorAll(e)).filter(n=>{const a=window.getComputedStyle(n);return!n.hasAttribute("disabled")&&a.display!=="none"&&a.visibility!=="hidden"})}function v({children:e,focusSelector:n=h,shortcuts:a=[]}){const i=E(new Map);s(()=>{i.current=new Map(a.map(t=>[t.id,t]))},[a]),s(()=>{function t(r){for(const o of i.current.values())B(r,o)&&(!o.allowInEditable&&k(r.target)||((o.preventDefault??!0)&&r.preventDefault(),o.handler(r)))}return window.addEventListener("keydown",t),()=>window.removeEventListener("keydown",t)},[]);const d=f(t=>(i.current.set(t.id,t),()=>{i.current.delete(t.id)}),[]),l=f((t,r=n)=>{const o=b(r);if(!o.length)return;const c=document.activeElement instanceof HTMLElement?o.indexOf(document.activeElement):-1,x=c===-1?0:(c+t+o.length)%o.length;o[x]?.focus()},[n]),m=w(()=>({focusFirst:(t=n)=>b(t)[0]?.focus(),focusNext:(t=n)=>l(1,t),focusPrevious:(t=n)=>l(-1,t),registerShortcut:d}),[l,n,d]);return p(u.Provider,{value:m,children:e})}function C(){const e=y(u);if(!e)throw new Error("useKeyboard must be used inside KeyboardProvider.");return e}function T(){return y(u)}function g(e){const n=C();s(()=>n.registerShortcut(e),[n,e])}function H(e,n){(e.key==="Enter"||e.key===" ")&&(e.preventDefault(),n())}export{v as KeyboardProvider,H as handleKeyboardClick,C as useKeyboard,g as useKeyboardShortcut,T as useOptionalKeyboard};
|
|
@@ -1,10 +1 @@
|
|
|
1
|
-
"use client";
|
|
2
|
-
import { jsx as _jsx } from "react/jsx-runtime";
|
|
3
|
-
import { AuthProvider, } from "./auth-provider";
|
|
4
|
-
import { ConfigProvider, } from "./config-provider";
|
|
5
|
-
import { KeyboardProvider, } from "./keyboard-provider";
|
|
6
|
-
import { ThemeProvider, } from "./theme-provider";
|
|
7
|
-
import { UIOverlayProvider, } from "./ui-overlay-provider";
|
|
8
|
-
export function NexusProvider({ auth, children, config, keyboard, overlay, theme, }) {
|
|
9
|
-
return (_jsx(ConfigProvider, { ...config, children: _jsx(ThemeProvider, { ...theme, children: _jsx(AuthProvider, { ...auth, children: _jsx(KeyboardProvider, { ...keyboard, children: _jsx(UIOverlayProvider, { ...overlay, children: children }) }) }) }) }));
|
|
10
|
-
}
|
|
1
|
+
"use client";import{jsx as r}from"react/jsx-runtime";import{AuthProvider as n}from"./auth-provider";import{ConfigProvider as f}from"./config-provider";import{KeyboardProvider as c}from"./keyboard-provider";import{ThemeProvider as h}from"./theme-provider";import{UIOverlayProvider as l}from"./ui-overlay-provider";function a({auth:o,children:e,config:i,keyboard:m,overlay:d,theme:t}){return r(f,{...i,children:r(h,{...t,children:r(n,{...o,children:r(c,{...m,children:r(l,{...d,children:e})})})})})}export{a as NexusProvider};
|
|
@@ -1,131 +1 @@
|
|
|
1
|
-
"use client";
|
|
2
|
-
import { jsx as _jsx } from "react/jsx-runtime";
|
|
3
|
-
import { createContext, useCallback, useContext, useEffect, useMemo, useState, } from "react";
|
|
4
|
-
const ThemeContext = createContext(null);
|
|
5
|
-
const themeModeEventName = "tmc:nexus-theme-mode";
|
|
6
|
-
const themeIdEventName = "tmc:nexus-theme-id";
|
|
7
|
-
function toCssVariableName(tokenName) {
|
|
8
|
-
if (tokenName.startsWith("--")) {
|
|
9
|
-
return tokenName;
|
|
10
|
-
}
|
|
11
|
-
return `--tmc-${tokenName.replace(/[A-Z]/g, (match) => `-${match.toLowerCase()}`).replace(/[_\s]+/g, "-")}`;
|
|
12
|
-
}
|
|
13
|
-
function setRootAttribute(name, value) {
|
|
14
|
-
if (!value) {
|
|
15
|
-
document.documentElement.removeAttribute(name);
|
|
16
|
-
return;
|
|
17
|
-
}
|
|
18
|
-
document.documentElement.setAttribute(name, value);
|
|
19
|
-
}
|
|
20
|
-
export function ThemeProvider({ children, defaultMode = "system", defaultThemeId, storageKey, themes = [], }) {
|
|
21
|
-
const initialThemeId = defaultThemeId ?? themes[0]?.id ?? "default";
|
|
22
|
-
const [themeId, setThemeIdState] = useState(initialThemeId);
|
|
23
|
-
const [mode, setModeState] = useState(defaultMode);
|
|
24
|
-
const activeTheme = themes.find((theme) => theme.id === themeId) ?? themes[0];
|
|
25
|
-
useEffect(() => {
|
|
26
|
-
if (!storageKey) {
|
|
27
|
-
return;
|
|
28
|
-
}
|
|
29
|
-
const storedThemeId = window.localStorage.getItem(`${storageKey}:theme`);
|
|
30
|
-
const storedMode = window.localStorage.getItem(`${storageKey}:mode`);
|
|
31
|
-
if (storedThemeId) {
|
|
32
|
-
setThemeIdState(storedThemeId);
|
|
33
|
-
}
|
|
34
|
-
if (storedMode === "light" || storedMode === "dark" || storedMode === "system") {
|
|
35
|
-
setModeState(storedMode);
|
|
36
|
-
}
|
|
37
|
-
}, [storageKey]);
|
|
38
|
-
useEffect(() => {
|
|
39
|
-
if (!storageKey) {
|
|
40
|
-
return;
|
|
41
|
-
}
|
|
42
|
-
function handleStorage(event) {
|
|
43
|
-
if (event.key === `${storageKey}:theme` && event.newValue) {
|
|
44
|
-
setThemeIdState(event.newValue);
|
|
45
|
-
}
|
|
46
|
-
if (event.key === `${storageKey}:mode` &&
|
|
47
|
-
(event.newValue === "light" || event.newValue === "dark" || event.newValue === "system")) {
|
|
48
|
-
setModeState(event.newValue);
|
|
49
|
-
}
|
|
50
|
-
}
|
|
51
|
-
function handleThemeMode(event) {
|
|
52
|
-
const nextMode = event.detail?.mode;
|
|
53
|
-
if (nextMode === "light" || nextMode === "dark" || nextMode === "system") {
|
|
54
|
-
setModeState(nextMode);
|
|
55
|
-
}
|
|
56
|
-
}
|
|
57
|
-
function handleThemeId(event) {
|
|
58
|
-
const nextThemeId = event.detail?.themeId;
|
|
59
|
-
if (nextThemeId) {
|
|
60
|
-
setThemeIdState(nextThemeId);
|
|
61
|
-
}
|
|
62
|
-
}
|
|
63
|
-
window.addEventListener("storage", handleStorage);
|
|
64
|
-
window.addEventListener(themeModeEventName, handleThemeMode);
|
|
65
|
-
window.addEventListener(themeIdEventName, handleThemeId);
|
|
66
|
-
return () => {
|
|
67
|
-
window.removeEventListener("storage", handleStorage);
|
|
68
|
-
window.removeEventListener(themeModeEventName, handleThemeMode);
|
|
69
|
-
window.removeEventListener(themeIdEventName, handleThemeId);
|
|
70
|
-
};
|
|
71
|
-
}, [storageKey]);
|
|
72
|
-
useEffect(() => {
|
|
73
|
-
const root = document.documentElement;
|
|
74
|
-
const appliedVariableNames = [];
|
|
75
|
-
setRootAttribute("data-tmc-theme", activeTheme?.id);
|
|
76
|
-
setRootAttribute("data-tmc-theme-mode", mode);
|
|
77
|
-
if (activeTheme?.className) {
|
|
78
|
-
root.classList.add(activeTheme.className);
|
|
79
|
-
}
|
|
80
|
-
if (activeTheme?.colorScheme) {
|
|
81
|
-
root.style.colorScheme = activeTheme.colorScheme;
|
|
82
|
-
}
|
|
83
|
-
Object.entries(activeTheme?.cssVariables ?? {}).forEach(([name, value]) => {
|
|
84
|
-
const variableName = toCssVariableName(name);
|
|
85
|
-
appliedVariableNames.push(variableName);
|
|
86
|
-
root.style.setProperty(variableName, String(value));
|
|
87
|
-
});
|
|
88
|
-
return () => {
|
|
89
|
-
appliedVariableNames.forEach((name) => root.style.removeProperty(name));
|
|
90
|
-
if (activeTheme?.className) {
|
|
91
|
-
root.classList.remove(activeTheme.className);
|
|
92
|
-
}
|
|
93
|
-
if (activeTheme?.colorScheme) {
|
|
94
|
-
root.style.removeProperty("color-scheme");
|
|
95
|
-
}
|
|
96
|
-
};
|
|
97
|
-
}, [activeTheme, mode]);
|
|
98
|
-
const setThemeId = useCallback((nextThemeId) => {
|
|
99
|
-
setThemeIdState(nextThemeId);
|
|
100
|
-
if (storageKey) {
|
|
101
|
-
window.localStorage.setItem(`${storageKey}:theme`, nextThemeId);
|
|
102
|
-
window.dispatchEvent(new CustomEvent(themeIdEventName, { detail: { themeId: nextThemeId } }));
|
|
103
|
-
}
|
|
104
|
-
}, [storageKey]);
|
|
105
|
-
const setMode = useCallback((nextMode) => {
|
|
106
|
-
setModeState(nextMode);
|
|
107
|
-
if (storageKey) {
|
|
108
|
-
window.localStorage.setItem(`${storageKey}:mode`, nextMode);
|
|
109
|
-
window.dispatchEvent(new CustomEvent(themeModeEventName, { detail: { mode: nextMode } }));
|
|
110
|
-
}
|
|
111
|
-
}, [storageKey]);
|
|
112
|
-
const value = useMemo(() => ({
|
|
113
|
-
activeTheme,
|
|
114
|
-
mode,
|
|
115
|
-
setMode,
|
|
116
|
-
setThemeId,
|
|
117
|
-
themeId,
|
|
118
|
-
themes,
|
|
119
|
-
}), [activeTheme, mode, setMode, setThemeId, themeId, themes]);
|
|
120
|
-
return _jsx(ThemeContext.Provider, { value: value, children: children });
|
|
121
|
-
}
|
|
122
|
-
export function useTheme() {
|
|
123
|
-
const context = useContext(ThemeContext);
|
|
124
|
-
if (!context) {
|
|
125
|
-
throw new Error("useTheme must be used inside ThemeProvider.");
|
|
126
|
-
}
|
|
127
|
-
return context;
|
|
128
|
-
}
|
|
129
|
-
export function useOptionalTheme() {
|
|
130
|
-
return useContext(ThemeContext);
|
|
131
|
-
}
|
|
1
|
+
"use client";import{jsx as $}from"react/jsx-runtime";import{createContext as N,useCallback as I,useContext as T,useEffect as w,useMemo as P,useState as b}from"react";const f=N(null),E="tmc:nexus-theme-mode",v="tmc:nexus-theme-id";function M(i){return i.startsWith("--")?i:`--tmc-${i.replace(/[A-Z]/g,m=>`-${m.toLowerCase()}`).replace(/[_\s]+/g,"-")}`}function x(i,m){if(!m){document.documentElement.removeAttribute(i);return}document.documentElement.setAttribute(i,m)}function j({children:i,defaultMode:m="system",defaultThemeId:L,storageKey:t,themes:c=[]}){const V=L??c[0]?.id??"default",[h,a]=b(V),[l,u]=b(m),n=c.find(e=>e.id===h)??c[0];w(()=>{if(!t)return;const e=window.localStorage.getItem(`${t}:theme`),s=window.localStorage.getItem(`${t}:mode`);e&&a(e),(s==="light"||s==="dark"||s==="system")&&u(s)},[t]),w(()=>{if(!t)return;function e(o){o.key===`${t}:theme`&&o.newValue&&a(o.newValue),o.key===`${t}:mode`&&(o.newValue==="light"||o.newValue==="dark"||o.newValue==="system")&&u(o.newValue)}function s(o){const r=o.detail?.mode;(r==="light"||r==="dark"||r==="system")&&u(r)}function d(o){const r=o.detail?.themeId;r&&a(r)}return window.addEventListener("storage",e),window.addEventListener(E,s),window.addEventListener(v,d),()=>{window.removeEventListener("storage",e),window.removeEventListener(E,s),window.removeEventListener(v,d)}},[t]),w(()=>{const e=document.documentElement,s=[];return x("data-tmc-theme",n?.id),x("data-tmc-theme-mode",l),n?.className&&e.classList.add(n.className),n?.colorScheme&&(e.style.colorScheme=n.colorScheme),Object.entries(n?.cssVariables??{}).forEach(([d,o])=>{const r=M(d);s.push(r),e.style.setProperty(r,String(o))}),()=>{s.forEach(d=>e.style.removeProperty(d)),n?.className&&e.classList.remove(n.className),n?.colorScheme&&e.style.removeProperty("color-scheme")}},[n,l]);const p=I(e=>{a(e),t&&(window.localStorage.setItem(`${t}:theme`,e),window.dispatchEvent(new CustomEvent(v,{detail:{themeId:e}})))},[t]),S=I(e=>{u(e),t&&(window.localStorage.setItem(`${t}:mode`,e),window.dispatchEvent(new CustomEvent(E,{detail:{mode:e}})))},[t]),C=P(()=>({activeTheme:n,mode:l,setMode:S,setThemeId:p,themeId:h,themes:c}),[n,l,S,p,h,c]);return $(f.Provider,{value:C,children:i})}function g(){const i=T(f);if(!i)throw new Error("useTheme must be used inside ThemeProvider.");return i}function O(){return T(f)}export{j as ThemeProvider,O as useOptionalTheme,g as useTheme};
|
|
@@ -1,36 +1 @@
|
|
|
1
|
-
"use client";
|
|
2
|
-
import { jsx as _jsx } from "react/jsx-runtime";
|
|
3
|
-
import { createContext, useCallback, useContext, useMemo, useState, } from "react";
|
|
4
|
-
const UIOverlayContext = createContext(null);
|
|
5
|
-
export function UIOverlayProvider({ children }) {
|
|
6
|
-
const [openOverlayIds, setOpenOverlayIds] = useState([]);
|
|
7
|
-
const openOverlay = useCallback((id) => {
|
|
8
|
-
setOpenOverlayIds((current) => (current.includes(id) ? current : [...current, id]));
|
|
9
|
-
}, []);
|
|
10
|
-
const closeOverlay = useCallback((id) => {
|
|
11
|
-
setOpenOverlayIds((current) => current.filter((currentId) => currentId !== id));
|
|
12
|
-
}, []);
|
|
13
|
-
const toggleOverlay = useCallback((id) => {
|
|
14
|
-
setOpenOverlayIds((current) => (current.includes(id)
|
|
15
|
-
? current.filter((currentId) => currentId !== id)
|
|
16
|
-
: [...current, id]));
|
|
17
|
-
}, []);
|
|
18
|
-
const value = useMemo(() => ({
|
|
19
|
-
closeOverlay,
|
|
20
|
-
isOverlayOpen: (id) => openOverlayIds.includes(id),
|
|
21
|
-
openOverlay,
|
|
22
|
-
openOverlayIds,
|
|
23
|
-
toggleOverlay,
|
|
24
|
-
}), [closeOverlay, openOverlay, openOverlayIds, toggleOverlay]);
|
|
25
|
-
return _jsx(UIOverlayContext.Provider, { value: value, children: children });
|
|
26
|
-
}
|
|
27
|
-
export function useUIOverlay() {
|
|
28
|
-
const context = useContext(UIOverlayContext);
|
|
29
|
-
if (!context) {
|
|
30
|
-
throw new Error("useUIOverlay must be used inside UIOverlayProvider.");
|
|
31
|
-
}
|
|
32
|
-
return context;
|
|
33
|
-
}
|
|
34
|
-
export function useOptionalUIOverlay() {
|
|
35
|
-
return useContext(UIOverlayContext);
|
|
36
|
-
}
|
|
1
|
+
"use client";import{jsx as y}from"react/jsx-runtime";import{createContext as p,useCallback as l,useContext as c,useMemo as x,useState as d}from"react";const a=p(null);function m({children:o}){const[r,n]=d([]),u=l(e=>{n(t=>t.includes(e)?t:[...t,e])},[]),i=l(e=>{n(t=>t.filter(s=>s!==e))},[]),v=l(e=>{n(t=>t.includes(e)?t.filter(s=>s!==e):[...t,e])},[]),O=x(()=>({closeOverlay:i,isOverlayOpen:e=>r.includes(e),openOverlay:u,openOverlayIds:r,toggleOverlay:v}),[i,u,r,v]);return y(a.Provider,{value:O,children:o})}function U(){const o=c(a);if(!o)throw new Error("useUIOverlay must be used inside UIOverlayProvider.");return o}function C(){return c(a)}export{m as UIOverlayProvider,C as useOptionalUIOverlay,U as useUIOverlay};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
export
|
|
1
|
+
export*from"@themodcraft/addon-providers/theme";
|
|
@@ -1 +1 @@
|
|
|
1
|
-
export
|
|
1
|
+
export*from"@themodcraft/addon-themes";
|
package/dist/artstyles.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
export
|
|
1
|
+
export*from"@themodcraft/addon-artstyles";
|
|
@@ -1 +1 @@
|
|
|
1
|
-
export
|
|
1
|
+
export*from"@themodcraft/addon-configs/themodcraft-v3";
|
package/dist/index.js
CHANGED
|
@@ -1,9 +1 @@
|
|
|
1
|
-
export
|
|
2
|
-
export * from "@themodcraft/addon-artstyles";
|
|
3
|
-
export * from "@themodcraft/addon-charts";
|
|
4
|
-
export * from "@themodcraft/addon-configs";
|
|
5
|
-
export * from "@themodcraft/addon-integrations";
|
|
6
|
-
export * from "@themodcraft/addon-paywall";
|
|
7
|
-
export * from "@themodcraft/addon-providers";
|
|
8
|
-
export * from "@themodcraft/addon-themes";
|
|
9
|
-
export * from "@themodcraft/license-client";
|
|
1
|
+
export*from"@themodcraft/addon-animations";export*from"@themodcraft/addon-artstyles";export*from"@themodcraft/addon-charts";export*from"@themodcraft/addon-configs";export*from"@themodcraft/addon-integrations";export*from"@themodcraft/addon-paywall";export*from"@themodcraft/addon-providers";export*from"@themodcraft/addon-themes";export*from"@themodcraft/license-client";
|
package/dist/paywall.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
export
|
|
1
|
+
export*from"@themodcraft/addon-paywall";
|
package/dist/providers/auth.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
export
|
|
1
|
+
export*from"@themodcraft/addon-providers/auth";
|
|
@@ -1 +1 @@
|
|
|
1
|
-
export
|
|
1
|
+
export*from"@themodcraft/addon-providers/keyboard";
|
package/dist/providers/nexus.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
export
|
|
1
|
+
export*from"@themodcraft/addon-providers/nexus";
|
package/dist/providers/theme.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
export
|
|
1
|
+
export*from"@themodcraft/addon-providers/theme";
|
package/dist/providers.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
export
|
|
1
|
+
export*from"@themodcraft/addon-providers";
|
|
@@ -1,106 +1 @@
|
|
|
1
|
-
:root {
|
|
2
|
-
/* GRASCALE / NEUTRAL RAMP (MAPPED FROM YOUR PRIMARY VARIABLES 8-19) */
|
|
3
|
-
--neutral-50: #FFFFFF; /* Pure White */
|
|
4
|
-
--neutral-100: #D9D9D9; /* Very Light Gray */
|
|
5
|
-
--neutral-200: #9E9E9E; /* Light Gray */
|
|
6
|
-
--neutral-300: #828282; /* Mid-Light Gray */
|
|
7
|
-
--neutral-400: #696969; /* Mid-Gray (from original primary12) */
|
|
8
|
-
--neutral-500: #4A4A4A; /* Medium Dark Gray */
|
|
9
|
-
--neutral-600: #3c3c3c; /* Dark Gray */
|
|
10
|
-
--neutral-700: #212121; /* Very Dark Gray */
|
|
11
|
-
--neutral-800: #161616; /* Near-Black (Dark Mode Card BG) */
|
|
12
|
-
--neutral-850: #131313;
|
|
13
|
-
--neutral-900: #121212; /* Off-Black */
|
|
14
|
-
--neutral-999: #000000; /* Pure Black */
|
|
15
|
-
|
|
16
|
-
/* --- ACCENT GREEN (Vibrant & Neon) --- */
|
|
17
|
-
--accent-green-400: #5DFF33;
|
|
18
|
-
--accent-green-500: #30FA00; /* Primary Action */
|
|
19
|
-
--accent-green-600: #28D900;
|
|
20
|
-
--accent-green-700: #21BA00;
|
|
21
|
-
--accent-green-800: #137D00;
|
|
22
|
-
--accent-green-900: #064600;
|
|
23
|
-
--accent-green-999: #000300;
|
|
24
|
-
|
|
25
|
-
/* BLUE ACCENT RAMP (FROM COLORKIT.CO) */
|
|
26
|
-
--accent-blue-500: #005EFE;
|
|
27
|
-
--accent-blue-600: #0051DD;
|
|
28
|
-
--accent-blue-700: #0044BD;
|
|
29
|
-
--accent-blue-800: #002B80;
|
|
30
|
-
--accent-blue-900: #001447;
|
|
31
|
-
--accent-blue-999: #000003;
|
|
32
|
-
|
|
33
|
-
--accent-cyan-400: #00f2ff; /* Brightest Neon */
|
|
34
|
-
--accent-cyan-500: #00d2de; /* Primary Teal */
|
|
35
|
-
--accent-cyan-600: #00b4be;
|
|
36
|
-
--accent-cyan-700: #00969e;
|
|
37
|
-
--accent-cyan-750: #007980; /* Mid-point */
|
|
38
|
-
--accent-cyan-800: #005e63;
|
|
39
|
-
--accent-cyan-850: #004348;
|
|
40
|
-
--accent-cyan-900: #002b2e;
|
|
41
|
-
--accent-cyan-950: #001416;
|
|
42
|
-
--accent-cyan-999: #000303; /* Near-Black Teal */
|
|
43
|
-
|
|
44
|
-
/* ---
|
|
45
|
-
GLOBAL LAYOUT DEFAULTS
|
|
46
|
-
--- */
|
|
47
|
-
--border-radius: 15px;
|
|
48
|
-
/* --- DEFAULTS --- */
|
|
49
|
-
--border-radius-sm: 6px;
|
|
50
|
-
--font-mono: 'JetBrains Mono', 'Fira Code', monospace;
|
|
51
|
-
--font-main: 'Inter', system-ui, sans-serif;
|
|
52
|
-
--font-family: system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, Cantarell, 'Open Sans', 'Helvetica Neue', sans-serif;
|
|
53
|
-
|
|
54
|
-
/* --- NEW: GLOW & GLASS UTILITIES --- */
|
|
55
|
-
--glass-border: rgba(255, 255, 255, 0.08);
|
|
56
|
-
--glass-bg: rgba(10, 10, 10, 0.6);
|
|
57
|
-
--glow-green: 0 0 15px rgba(48, 250, 0, 0.3);
|
|
58
|
-
--glow-blue: 0 0 15px rgba(0, 94, 254, 0.3);
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
}
|
|
63
|
-
|
|
64
|
-
/* --- DARK MODE MAPPINGS (The "TheModCraft" Look) --- */
|
|
65
|
-
@media (prefers-color-scheme: dark) {
|
|
66
|
-
:root {
|
|
67
|
-
/* BACKGROUNDS */
|
|
68
|
-
--primary-background: var(--neutral-700); /* Very Dark Gray */
|
|
69
|
-
--secondary-background: var(--neutral-800); /* Near-Black */
|
|
70
|
-
|
|
71
|
-
/* TEXT */
|
|
72
|
-
--primary-text: var(--neutral-50); /* White */
|
|
73
|
-
--secondary-text: var(--neutral-300); /* Mid-Light Gray */
|
|
74
|
-
--tertiary-text: var(--neutral-500); /* Medium Dark Gray */
|
|
75
|
-
|
|
76
|
-
/* INTERACTIVE ELEMENTS */
|
|
77
|
-
--border-color: var(--neutral-600); /* Dark Gray */
|
|
78
|
-
--cta-color: var(--accent-green-500); /* Primary Green */
|
|
79
|
-
--link-color: var(--accent-blue-500); /* Primary Blue */
|
|
80
|
-
--hover-overlay: rgba(0, 0, 0, 0.49); /* Subtle light hover */
|
|
81
|
-
}
|
|
82
|
-
}
|
|
83
|
-
|
|
84
|
-
:root[data-tmc-theme-mode="light"] {
|
|
85
|
-
--primary-background: #f3f5f8;
|
|
86
|
-
--secondary-background: #fbfcfe;
|
|
87
|
-
--primary-text: #151821;
|
|
88
|
-
--secondary-text: #5f6b7a;
|
|
89
|
-
--tertiary-text: #7a8795;
|
|
90
|
-
--border-color: #d7dde5;
|
|
91
|
-
--cta-color: var(--accent-blue-500);
|
|
92
|
-
--link-color: var(--accent-blue-700);
|
|
93
|
-
--hover-overlay: rgba(0, 94, 254, 0.08);
|
|
94
|
-
}
|
|
95
|
-
|
|
96
|
-
:root[data-tmc-theme-mode="dark"] {
|
|
97
|
-
--primary-background: var(--neutral-700);
|
|
98
|
-
--secondary-background: var(--neutral-800);
|
|
99
|
-
--primary-text: var(--neutral-50);
|
|
100
|
-
--secondary-text: var(--neutral-300);
|
|
101
|
-
--tertiary-text: var(--neutral-500);
|
|
102
|
-
--border-color: var(--neutral-600);
|
|
103
|
-
--cta-color: var(--accent-green-500);
|
|
104
|
-
--link-color: var(--accent-blue-500);
|
|
105
|
-
--hover-overlay: rgba(0, 0, 0, 0.49);
|
|
106
|
-
}
|
|
1
|
+
:root{--neutral-50: #FFFFFF;--neutral-100: #D9D9D9;--neutral-200: #9E9E9E;--neutral-300: #828282;--neutral-400: #696969;--neutral-500: #4A4A4A;--neutral-600: #3c3c3c;--neutral-700: #212121;--neutral-800: #161616;--neutral-850: #131313;--neutral-900: #121212;--neutral-999: #000000;--accent-green-400: #5DFF33;--accent-green-500: #30FA00;--accent-green-600: #28D900;--accent-green-700: #21BA00;--accent-green-800: #137D00;--accent-green-900: #064600;--accent-green-999: #000300;--accent-blue-500: #005EFE;--accent-blue-600: #0051DD;--accent-blue-700: #0044BD;--accent-blue-800: #002B80;--accent-blue-900: #001447;--accent-blue-999: #000003;--accent-cyan-400: #00f2ff;--accent-cyan-500: #00d2de;--accent-cyan-600: #00b4be;--accent-cyan-700: #00969e;--accent-cyan-750: #007980;--accent-cyan-800: #005e63;--accent-cyan-850: #004348;--accent-cyan-900: #002b2e;--accent-cyan-950: #001416;--accent-cyan-999: #000303;--border-radius: 15px;--border-radius-sm: 6px;--font-mono: "JetBrains Mono", "Fira Code", monospace;--font-main: "Inter", system-ui, sans-serif;--font-family: system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Oxygen, Ubuntu, Cantarell, "Open Sans", "Helvetica Neue", sans-serif;--glass-border: rgba(255, 255, 255, .08);--glass-bg: rgba(10, 10, 10, .6);--glow-green: 0 0 15px rgba(48, 250, 0, .3);--glow-blue: 0 0 15px rgba(0, 94, 254, .3)}@media(prefers-color-scheme:dark){:root{--primary-background: var(--neutral-700);--secondary-background: var(--neutral-800);--primary-text: var(--neutral-50);--secondary-text: var(--neutral-300);--tertiary-text: var(--neutral-500);--border-color: var(--neutral-600);--cta-color: var(--accent-green-500);--link-color: var(--accent-blue-500);--hover-overlay: rgba(0, 0, 0, .49)}}:root[data-tmc-theme-mode=light]{--primary-background: #f3f5f8;--secondary-background: #fbfcfe;--primary-text: #151821;--secondary-text: #5f6b7a;--tertiary-text: #7a8795;--border-color: #d7dde5;--cta-color: var(--accent-blue-500);--link-color: var(--accent-blue-700);--hover-overlay: rgba(0, 94, 254, .08)}:root[data-tmc-theme-mode=dark]{--primary-background: var(--neutral-700);--secondary-background: var(--neutral-800);--primary-text: var(--neutral-50);--secondary-text: var(--neutral-300);--tertiary-text: var(--neutral-500);--border-color: var(--neutral-600);--cta-color: var(--accent-green-500);--link-color: var(--accent-blue-500);--hover-overlay: rgba(0, 0, 0, .49)}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
export
|
|
1
|
+
export*from"@themodcraft/addon-themes/themodcraft-v3";
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@themodcraft/addon-packs",
|
|
3
|
-
"version": "1.1.
|
|
3
|
+
"version": "1.1.1",
|
|
4
4
|
"publishConfig": {
|
|
5
5
|
"access": "public"
|
|
6
6
|
},
|
|
@@ -80,19 +80,19 @@
|
|
|
80
80
|
"typecheck": "tsc -p tsconfig.json --noEmit"
|
|
81
81
|
},
|
|
82
82
|
"dependencies": {
|
|
83
|
-
"@themodcraft/addon-animations": "1.1.
|
|
84
|
-
"@themodcraft/addon-artstyles": "1.1.
|
|
85
|
-
"@themodcraft/addon-charts": "1.1.
|
|
86
|
-
"@themodcraft/addon-configs": "1.1.
|
|
87
|
-
"@themodcraft/addon-integrations": "1.1.
|
|
88
|
-
"@themodcraft/addon-paywall": "1.1.
|
|
89
|
-
"@themodcraft/addon-providers": "1.1.
|
|
90
|
-
"@themodcraft/addon-themes": "1.1.
|
|
91
|
-
"@themodcraft/license-client": "1.1.
|
|
83
|
+
"@themodcraft/addon-animations": "1.1.1",
|
|
84
|
+
"@themodcraft/addon-artstyles": "1.1.1",
|
|
85
|
+
"@themodcraft/addon-charts": "1.1.1",
|
|
86
|
+
"@themodcraft/addon-configs": "1.1.1",
|
|
87
|
+
"@themodcraft/addon-integrations": "1.1.1",
|
|
88
|
+
"@themodcraft/addon-paywall": "1.1.1",
|
|
89
|
+
"@themodcraft/addon-providers": "1.1.1",
|
|
90
|
+
"@themodcraft/addon-themes": "1.1.1",
|
|
91
|
+
"@themodcraft/license-client": "1.1.1"
|
|
92
92
|
},
|
|
93
93
|
"peerDependencies": {
|
|
94
|
-
"@themodcraft/core-ui": "1.1.
|
|
95
|
-
"@themodcraft/pro-kit": "1.1.
|
|
94
|
+
"@themodcraft/core-ui": "1.1.1",
|
|
95
|
+
"@themodcraft/pro-kit": "1.1.1",
|
|
96
96
|
"better-auth": "*",
|
|
97
97
|
"react": "^19.0.0",
|
|
98
98
|
"react-dom": "^19.0.0"
|