colbrush 1.5.0 → 1.7.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.
@@ -0,0 +1,296 @@
1
+ "use strict";
2
+ var __defProp = Object.defineProperty;
3
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
+ var __getOwnPropNames = Object.getOwnPropertyNames;
5
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
6
+ var __export = (target, all) => {
7
+ for (var name in all)
8
+ __defProp(target, name, { get: all[name], enumerable: true });
9
+ };
10
+ var __copyProps = (to, from, except, desc) => {
11
+ if (from && typeof from === "object" || typeof from === "function") {
12
+ for (let key of __getOwnPropNames(from))
13
+ if (!__hasOwnProp.call(to, key) && key !== except)
14
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
15
+ }
16
+ return to;
17
+ };
18
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
19
+
20
+ // src/devtools/index.ts
21
+ var devtools_exports = {};
22
+ __export(devtools_exports, {
23
+ SimulationFilter: () => SimulationFilter
24
+ });
25
+ module.exports = __toCommonJS(devtools_exports);
26
+
27
+ // src/core/constants/simulation.ts
28
+ var FILTER_ID = "cb-vision-filter";
29
+ var FILTER_WRAPPER_ID = "cb-vision-filter-root";
30
+ var DEFAULT_OPTIONS = {
31
+ defaultMode: "none",
32
+ paramKey: "vision",
33
+ storageKey: "colbrush:vision",
34
+ toolbarPosition: "left-bottom",
35
+ hotkey: true,
36
+ allowInProd: false
37
+ };
38
+ var MATRICES = {
39
+ deuteranopia: `
40
+ 0.367 0.861 -0.228 0 0
41
+ 0.280 0.673 0.047 0 0
42
+ -0.012 0.043 0.969 0 0
43
+ 0.000 0.000 0.000 1 0
44
+ `,
45
+ protanopia: `
46
+ 0.152 1.052 -0.204 0 0
47
+ 0.115 0.786 0.099 0 0
48
+ -0.004 -0.048 1.052 0 0
49
+ 0.000 0.000 0.000 1 0
50
+ `,
51
+ tritanopia: `
52
+ 1.256 -0.077 -0.179 0 0
53
+ -0.078 0.931 0.148 0 0
54
+ 0.005 0.691 0.304 0 0
55
+ 0.000 0.000 0.000 1 0
56
+ `
57
+ };
58
+ var IDENTITY_MATRIX = `
59
+ 1 0 0 0 0
60
+ 0 1 0 0 0
61
+ 0 0 1 0 0
62
+ 0 0 0 1 0
63
+ `;
64
+ function getMatrixForMode(mode) {
65
+ if (mode === "none") return IDENTITY_MATRIX;
66
+ return MATRICES[mode];
67
+ }
68
+
69
+ // src/devtools/vision/modes.ts
70
+ var SIMULATION_MODES = [
71
+ "deuteranopia",
72
+ "protanopia",
73
+ "tritanopia"
74
+ ];
75
+ var MODE_LABELS = {
76
+ English: {
77
+ none: "default",
78
+ protanopia: "protanopia",
79
+ deuteranopia: "deuteranopia",
80
+ tritanopia: "tritanopia"
81
+ },
82
+ Korean: {
83
+ none: "\uAEBC\uC9D0",
84
+ protanopia: "\uC801\uC0C9\uB9F9",
85
+ deuteranopia: "\uB179\uC0C9\uB9F9",
86
+ tritanopia: "\uCCAD\uC0C9\uB9F9"
87
+ }
88
+ };
89
+
90
+ // src/react/SimulationFilter.tsx
91
+ var import_react3 = require("react");
92
+
93
+ // src/react/ThemeProvider.tsx
94
+ var import_react = require("react");
95
+ var import_jsx_runtime = require("react/jsx-runtime");
96
+ var ThemeContext = (0, import_react.createContext)({
97
+ theme: "default",
98
+ language: "English",
99
+ updateTheme: () => {
100
+ },
101
+ updateLanguage: () => {
102
+ },
103
+ simulationFilter: "none",
104
+ setSimulationFilter: () => {
105
+ }
106
+ });
107
+ var useTheme = () => (0, import_react.useContext)(ThemeContext);
108
+
109
+ // src/react/VisionPortal.tsx
110
+ var import_react2 = require("react");
111
+ var import_react_dom = require("react-dom");
112
+ var PORTAL_ID = "cb-vision-portal";
113
+ var portalEl = null;
114
+ var activeOwner = null;
115
+ function ensurePortal() {
116
+ if (typeof document === "undefined")
117
+ throw new Error("No document available");
118
+ if (portalEl && document.body.contains(portalEl)) return portalEl;
119
+ const existing = document.getElementById(PORTAL_ID);
120
+ portalEl = existing ?? Object.assign(document.createElement("div"), { id: PORTAL_ID });
121
+ if (!existing) document.body.appendChild(portalEl);
122
+ return portalEl;
123
+ }
124
+ function VisionFilterPortal({
125
+ visible = true,
126
+ children
127
+ }) {
128
+ const [container, setContainer] = (0, import_react2.useState)(null);
129
+ const ownerId = (0, import_react2.useRef)(Symbol("VisionFilterPortal"));
130
+ (0, import_react2.useEffect)(() => {
131
+ try {
132
+ const el = ensurePortal();
133
+ setContainer(el);
134
+ if (activeOwner === null) activeOwner = ownerId.current;
135
+ } catch {
136
+ setContainer(null);
137
+ }
138
+ return () => {
139
+ if (activeOwner === ownerId.current) {
140
+ activeOwner = null;
141
+ }
142
+ };
143
+ }, []);
144
+ const isPrimary = container !== null && activeOwner === ownerId.current;
145
+ const enabled = Boolean(isPrimary && visible);
146
+ (0, import_react2.useEffect)(() => {
147
+ if (!enabled || typeof document === "undefined") return;
148
+ const fallback = document.getElementById(FILTER_WRAPPER_ID);
149
+ if (fallback instanceof SVGSVGElement && fallback.dataset.cbVisionManaged === "fallback") {
150
+ fallback.remove();
151
+ }
152
+ }, [enabled]);
153
+ if (!container || !isPrimary) return null;
154
+ return (0, import_react_dom.createPortal)(isPrimary ? children : null, container);
155
+ }
156
+
157
+ // src/react/SimulationFilter.tsx
158
+ var import_jsx_runtime2 = require("react/jsx-runtime");
159
+ var import_meta = {};
160
+ var originalFilterMap = /* @__PURE__ */ new WeakMap();
161
+ var IS_DEV = (() => {
162
+ if (typeof process !== "undefined" && true) {
163
+ return true;
164
+ }
165
+ if (typeof import_meta !== "undefined" && typeof import_meta.env?.MODE === "string") {
166
+ return import_meta.env.MODE !== "production";
167
+ }
168
+ if (typeof window !== "undefined") {
169
+ const host = window.location.hostname;
170
+ return host === "localhost" || host === "127.0.0.1";
171
+ }
172
+ return false;
173
+ })();
174
+ function resolveOptions(props) {
175
+ const { visible = true, ...options } = props ?? {};
176
+ const merged = {
177
+ ...DEFAULT_OPTIONS,
178
+ ...options,
179
+ toolbarPosition: options.toolbarPosition ?? DEFAULT_OPTIONS.toolbarPosition,
180
+ hotkey: options.hotkey ?? DEFAULT_OPTIONS.hotkey,
181
+ allowInProd: options.allowInProd ?? DEFAULT_OPTIONS.allowInProd
182
+ };
183
+ return { config: merged, visible };
184
+ }
185
+ function SimulationFilter(props) {
186
+ const { config, visible } = resolveOptions(props);
187
+ const { toolbarPosition, allowInProd } = config;
188
+ const [open, setOpen] = (0, import_react3.useState)(false);
189
+ const { simulationFilter, setSimulationFilter, language } = useTheme();
190
+ if (!visible) return null;
191
+ if (!allowInProd && !IS_DEV) return null;
192
+ const ANCHOR_CLASSES = {
193
+ "left-bottom": "left-[16px] bottom-[16px]",
194
+ "right-bottom": "right-[16px] bottom-[16px]",
195
+ "left-top": "left-[16px] top-[16px]",
196
+ "right-top": "right-[16px] top-[16px]"
197
+ };
198
+ const MODES = ["none", ...SIMULATION_MODES];
199
+ const anchorClass = ANCHOR_CLASSES[toolbarPosition] ?? ANCHOR_CLASSES["left-bottom"];
200
+ (0, import_react3.useEffect)(() => {
201
+ if (typeof document === "undefined") return;
202
+ const resolveTarget = () => {
203
+ const preferred = document.querySelector("[data-cb-vision-target]") ?? document.getElementById("root") ?? document.getElementById("__next");
204
+ if (preferred instanceof HTMLElement) return preferred;
205
+ const bodyChildren = Array.from(
206
+ document.body?.children ?? []
207
+ );
208
+ const fallback = bodyChildren.find(
209
+ (child) => child.id !== PORTAL_ID
210
+ );
211
+ return fallback ?? document.body;
212
+ };
213
+ const target = resolveTarget();
214
+ if (!(target instanceof HTMLElement)) return;
215
+ const style = target.style;
216
+ if (!originalFilterMap.has(target)) {
217
+ originalFilterMap.set(target, {
218
+ filter: style.filter ?? "",
219
+ webkitFilter: style.webkitFilter ?? ""
220
+ });
221
+ }
222
+ const snapshot = originalFilterMap.get(target) ?? {
223
+ filter: "",
224
+ webkitFilter: ""
225
+ };
226
+ const applyFilter = () => {
227
+ const filterValue = `url(#${FILTER_ID})`;
228
+ style.filter = filterValue;
229
+ style.webkitFilter = filterValue;
230
+ };
231
+ const clearFilter = () => {
232
+ style.filter = snapshot.filter;
233
+ style.webkitFilter = snapshot.webkitFilter;
234
+ };
235
+ if (simulationFilter === "none") {
236
+ clearFilter();
237
+ return;
238
+ }
239
+ applyFilter();
240
+ return () => {
241
+ clearFilter();
242
+ };
243
+ }, [simulationFilter]);
244
+ return /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(VisionFilterPortal, { children: [
245
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
246
+ "svg",
247
+ {
248
+ id: FILTER_WRAPPER_ID,
249
+ "aria-hidden": "true",
250
+ "data-cb-vision-managed": "react",
251
+ preserveAspectRatio: "none",
252
+ style: {
253
+ position: "fixed",
254
+ inset: 0,
255
+ width: "100vw",
256
+ height: "100vh",
257
+ pointerEvents: "none",
258
+ zIndex: 2147483646
259
+ },
260
+ children: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("defs", { children: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("filter", { id: FILTER_ID, "data-cb-vision-managed": "true", children: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
261
+ "feColorMatrix",
262
+ {
263
+ type: "matrix",
264
+ values: getMatrixForMode(simulationFilter)
265
+ }
266
+ ) }) })
267
+ }
268
+ ),
269
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(
270
+ "div",
271
+ {
272
+ className: `cb-vision-toolbar h-[36px] fixed z-[100] inline-flex items-center gap-[6px] rounded-[10px] bg-[rgba(17,17,17,0.85)] p-[6px_8px] text-[12px] text-white opacity-90 shadow-[0_6px_18px_rgba(0,0,0,0.25)] backdrop-blur-[6px] ${anchorClass}`,
273
+ children: [
274
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
275
+ "span",
276
+ {
277
+ className: "font-medium hover:cursor-pointer",
278
+ onClick: () => setOpen(!open),
279
+ children: "Vision"
280
+ }
281
+ ),
282
+ open && MODES.map((value) => /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
283
+ "button",
284
+ {
285
+ type: "button",
286
+ className: `rounded-[6px] px-[6px] py-[3px] ${simulationFilter === value ? "bg-white text-black" : "hover:bg-[rgba(255,255,255,0.2)]"}`,
287
+ onClick: () => setSimulationFilter(value),
288
+ children: MODE_LABELS[language][value] ?? value
289
+ },
290
+ value
291
+ ))
292
+ ]
293
+ }
294
+ )
295
+ ] });
296
+ }
@@ -0,0 +1,26 @@
1
+ import * as react_jsx_runtime from 'react/jsx-runtime';
2
+
3
+ type VisionMode = 'deuteranopia' | 'protanopia' | 'tritanopia' | 'none';
4
+ interface VisionOptions {
5
+ /** 기본 모드. 기본값 'none' */
6
+ defaultMode?: VisionMode;
7
+ /** URL 토글 파라미터 키 (예: ?vision=deut), 기본값 'vision' */
8
+ paramKey?: string;
9
+ /** localStorage 키, 기본값 'colbrush:vision' */
10
+ storageKey?: string;
11
+ /** 개발 호스트 허용(정규식) — 기본: localhost/127/192.168.x */
12
+ devHostPattern?: RegExp;
13
+ /** 툴바 위치, 기본 'left-bottom' */
14
+ toolbarPosition?: 'left-bottom' | 'right-bottom' | 'left-top' | 'right-top';
15
+ /** 단축키 활성 여부, 기본 true (⌘/Ctrl + Alt + D) */
16
+ hotkey?: boolean;
17
+ /** 프로덕션에서도 강제로 허용(디버깅용). 기본 false */
18
+ allowInProd?: boolean;
19
+ }
20
+
21
+ type SimulationFilterProps = VisionOptions & {
22
+ visible?: boolean;
23
+ };
24
+ declare function SimulationFilter(props?: SimulationFilterProps): react_jsx_runtime.JSX.Element | null;
25
+
26
+ export { SimulationFilter };
@@ -0,0 +1,26 @@
1
+ import * as react_jsx_runtime from 'react/jsx-runtime';
2
+
3
+ type VisionMode = 'deuteranopia' | 'protanopia' | 'tritanopia' | 'none';
4
+ interface VisionOptions {
5
+ /** 기본 모드. 기본값 'none' */
6
+ defaultMode?: VisionMode;
7
+ /** URL 토글 파라미터 키 (예: ?vision=deut), 기본값 'vision' */
8
+ paramKey?: string;
9
+ /** localStorage 키, 기본값 'colbrush:vision' */
10
+ storageKey?: string;
11
+ /** 개발 호스트 허용(정규식) — 기본: localhost/127/192.168.x */
12
+ devHostPattern?: RegExp;
13
+ /** 툴바 위치, 기본 'left-bottom' */
14
+ toolbarPosition?: 'left-bottom' | 'right-bottom' | 'left-top' | 'right-top';
15
+ /** 단축키 활성 여부, 기본 true (⌘/Ctrl + Alt + D) */
16
+ hotkey?: boolean;
17
+ /** 프로덕션에서도 강제로 허용(디버깅용). 기본 false */
18
+ allowInProd?: boolean;
19
+ }
20
+
21
+ type SimulationFilterProps = VisionOptions & {
22
+ visible?: boolean;
23
+ };
24
+ declare function SimulationFilter(props?: SimulationFilterProps): react_jsx_runtime.JSX.Element | null;
25
+
26
+ export { SimulationFilter };
@@ -0,0 +1,260 @@
1
+ import {
2
+ useTheme
3
+ } from "./chunk-EFIJAMPH.js";
4
+
5
+ // src/core/constants/simulation.ts
6
+ var FILTER_ID = "cb-vision-filter";
7
+ var FILTER_WRAPPER_ID = "cb-vision-filter-root";
8
+ var DEFAULT_OPTIONS = {
9
+ defaultMode: "none",
10
+ paramKey: "vision",
11
+ storageKey: "colbrush:vision",
12
+ toolbarPosition: "left-bottom",
13
+ hotkey: true,
14
+ allowInProd: false
15
+ };
16
+ var MATRICES = {
17
+ deuteranopia: `
18
+ 0.367 0.861 -0.228 0 0
19
+ 0.280 0.673 0.047 0 0
20
+ -0.012 0.043 0.969 0 0
21
+ 0.000 0.000 0.000 1 0
22
+ `,
23
+ protanopia: `
24
+ 0.152 1.052 -0.204 0 0
25
+ 0.115 0.786 0.099 0 0
26
+ -0.004 -0.048 1.052 0 0
27
+ 0.000 0.000 0.000 1 0
28
+ `,
29
+ tritanopia: `
30
+ 1.256 -0.077 -0.179 0 0
31
+ -0.078 0.931 0.148 0 0
32
+ 0.005 0.691 0.304 0 0
33
+ 0.000 0.000 0.000 1 0
34
+ `
35
+ };
36
+ var IDENTITY_MATRIX = `
37
+ 1 0 0 0 0
38
+ 0 1 0 0 0
39
+ 0 0 1 0 0
40
+ 0 0 0 1 0
41
+ `;
42
+ function getMatrixForMode(mode) {
43
+ if (mode === "none") return IDENTITY_MATRIX;
44
+ return MATRICES[mode];
45
+ }
46
+
47
+ // src/devtools/vision/modes.ts
48
+ var SIMULATION_MODES = [
49
+ "deuteranopia",
50
+ "protanopia",
51
+ "tritanopia"
52
+ ];
53
+ var MODE_LABELS = {
54
+ English: {
55
+ none: "default",
56
+ protanopia: "protanopia",
57
+ deuteranopia: "deuteranopia",
58
+ tritanopia: "tritanopia"
59
+ },
60
+ Korean: {
61
+ none: "\uAEBC\uC9D0",
62
+ protanopia: "\uC801\uC0C9\uB9F9",
63
+ deuteranopia: "\uB179\uC0C9\uB9F9",
64
+ tritanopia: "\uCCAD\uC0C9\uB9F9"
65
+ }
66
+ };
67
+
68
+ // src/react/SimulationFilter.tsx
69
+ import { useEffect as useEffect2, useState as useState2 } from "react";
70
+
71
+ // src/react/VisionPortal.tsx
72
+ import { useEffect, useRef, useState } from "react";
73
+ import { createPortal } from "react-dom";
74
+ var PORTAL_ID = "cb-vision-portal";
75
+ var portalEl = null;
76
+ var activeOwner = null;
77
+ function ensurePortal() {
78
+ if (typeof document === "undefined")
79
+ throw new Error("No document available");
80
+ if (portalEl && document.body.contains(portalEl)) return portalEl;
81
+ const existing = document.getElementById(PORTAL_ID);
82
+ portalEl = existing ?? Object.assign(document.createElement("div"), { id: PORTAL_ID });
83
+ if (!existing) document.body.appendChild(portalEl);
84
+ return portalEl;
85
+ }
86
+ function VisionFilterPortal({
87
+ visible = true,
88
+ children
89
+ }) {
90
+ const [container, setContainer] = useState(null);
91
+ const ownerId = useRef(Symbol("VisionFilterPortal"));
92
+ useEffect(() => {
93
+ try {
94
+ const el = ensurePortal();
95
+ setContainer(el);
96
+ if (activeOwner === null) activeOwner = ownerId.current;
97
+ } catch {
98
+ setContainer(null);
99
+ }
100
+ return () => {
101
+ if (activeOwner === ownerId.current) {
102
+ activeOwner = null;
103
+ }
104
+ };
105
+ }, []);
106
+ const isPrimary = container !== null && activeOwner === ownerId.current;
107
+ const enabled = Boolean(isPrimary && visible);
108
+ useEffect(() => {
109
+ if (!enabled || typeof document === "undefined") return;
110
+ const fallback = document.getElementById(FILTER_WRAPPER_ID);
111
+ if (fallback instanceof SVGSVGElement && fallback.dataset.cbVisionManaged === "fallback") {
112
+ fallback.remove();
113
+ }
114
+ }, [enabled]);
115
+ if (!container || !isPrimary) return null;
116
+ return createPortal(isPrimary ? children : null, container);
117
+ }
118
+
119
+ // src/react/SimulationFilter.tsx
120
+ import { jsx, jsxs } from "react/jsx-runtime";
121
+ var originalFilterMap = /* @__PURE__ */ new WeakMap();
122
+ var IS_DEV = (() => {
123
+ if (typeof process !== "undefined" && true) {
124
+ return true;
125
+ }
126
+ if (typeof import.meta !== "undefined" && typeof import.meta.env?.MODE === "string") {
127
+ return import.meta.env.MODE !== "production";
128
+ }
129
+ if (typeof window !== "undefined") {
130
+ const host = window.location.hostname;
131
+ return host === "localhost" || host === "127.0.0.1";
132
+ }
133
+ return false;
134
+ })();
135
+ function resolveOptions(props) {
136
+ const { visible = true, ...options } = props ?? {};
137
+ const merged = {
138
+ ...DEFAULT_OPTIONS,
139
+ ...options,
140
+ toolbarPosition: options.toolbarPosition ?? DEFAULT_OPTIONS.toolbarPosition,
141
+ hotkey: options.hotkey ?? DEFAULT_OPTIONS.hotkey,
142
+ allowInProd: options.allowInProd ?? DEFAULT_OPTIONS.allowInProd
143
+ };
144
+ return { config: merged, visible };
145
+ }
146
+ function SimulationFilter(props) {
147
+ const { config, visible } = resolveOptions(props);
148
+ const { toolbarPosition, allowInProd } = config;
149
+ const [open, setOpen] = useState2(false);
150
+ const { simulationFilter, setSimulationFilter, language } = useTheme();
151
+ if (!visible) return null;
152
+ if (!allowInProd && !IS_DEV) return null;
153
+ const ANCHOR_CLASSES = {
154
+ "left-bottom": "left-[16px] bottom-[16px]",
155
+ "right-bottom": "right-[16px] bottom-[16px]",
156
+ "left-top": "left-[16px] top-[16px]",
157
+ "right-top": "right-[16px] top-[16px]"
158
+ };
159
+ const MODES = ["none", ...SIMULATION_MODES];
160
+ const anchorClass = ANCHOR_CLASSES[toolbarPosition] ?? ANCHOR_CLASSES["left-bottom"];
161
+ useEffect2(() => {
162
+ if (typeof document === "undefined") return;
163
+ const resolveTarget = () => {
164
+ const preferred = document.querySelector("[data-cb-vision-target]") ?? document.getElementById("root") ?? document.getElementById("__next");
165
+ if (preferred instanceof HTMLElement) return preferred;
166
+ const bodyChildren = Array.from(
167
+ document.body?.children ?? []
168
+ );
169
+ const fallback = bodyChildren.find(
170
+ (child) => child.id !== PORTAL_ID
171
+ );
172
+ return fallback ?? document.body;
173
+ };
174
+ const target = resolveTarget();
175
+ if (!(target instanceof HTMLElement)) return;
176
+ const style = target.style;
177
+ if (!originalFilterMap.has(target)) {
178
+ originalFilterMap.set(target, {
179
+ filter: style.filter ?? "",
180
+ webkitFilter: style.webkitFilter ?? ""
181
+ });
182
+ }
183
+ const snapshot = originalFilterMap.get(target) ?? {
184
+ filter: "",
185
+ webkitFilter: ""
186
+ };
187
+ const applyFilter = () => {
188
+ const filterValue = `url(#${FILTER_ID})`;
189
+ style.filter = filterValue;
190
+ style.webkitFilter = filterValue;
191
+ };
192
+ const clearFilter = () => {
193
+ style.filter = snapshot.filter;
194
+ style.webkitFilter = snapshot.webkitFilter;
195
+ };
196
+ if (simulationFilter === "none") {
197
+ clearFilter();
198
+ return;
199
+ }
200
+ applyFilter();
201
+ return () => {
202
+ clearFilter();
203
+ };
204
+ }, [simulationFilter]);
205
+ return /* @__PURE__ */ jsxs(VisionFilterPortal, { children: [
206
+ /* @__PURE__ */ jsx(
207
+ "svg",
208
+ {
209
+ id: FILTER_WRAPPER_ID,
210
+ "aria-hidden": "true",
211
+ "data-cb-vision-managed": "react",
212
+ preserveAspectRatio: "none",
213
+ style: {
214
+ position: "fixed",
215
+ inset: 0,
216
+ width: "100vw",
217
+ height: "100vh",
218
+ pointerEvents: "none",
219
+ zIndex: 2147483646
220
+ },
221
+ children: /* @__PURE__ */ jsx("defs", { children: /* @__PURE__ */ jsx("filter", { id: FILTER_ID, "data-cb-vision-managed": "true", children: /* @__PURE__ */ jsx(
222
+ "feColorMatrix",
223
+ {
224
+ type: "matrix",
225
+ values: getMatrixForMode(simulationFilter)
226
+ }
227
+ ) }) })
228
+ }
229
+ ),
230
+ /* @__PURE__ */ jsxs(
231
+ "div",
232
+ {
233
+ className: `cb-vision-toolbar h-[36px] fixed z-[100] inline-flex items-center gap-[6px] rounded-[10px] bg-[rgba(17,17,17,0.85)] p-[6px_8px] text-[12px] text-white opacity-90 shadow-[0_6px_18px_rgba(0,0,0,0.25)] backdrop-blur-[6px] ${anchorClass}`,
234
+ children: [
235
+ /* @__PURE__ */ jsx(
236
+ "span",
237
+ {
238
+ className: "font-medium hover:cursor-pointer",
239
+ onClick: () => setOpen(!open),
240
+ children: "Vision"
241
+ }
242
+ ),
243
+ open && MODES.map((value) => /* @__PURE__ */ jsx(
244
+ "button",
245
+ {
246
+ type: "button",
247
+ className: `rounded-[6px] px-[6px] py-[3px] ${simulationFilter === value ? "bg-white text-black" : "hover:bg-[rgba(255,255,255,0.2)]"}`,
248
+ onClick: () => setSimulationFilter(value),
249
+ children: MODE_LABELS[language][value] ?? value
250
+ },
251
+ value
252
+ ))
253
+ ]
254
+ }
255
+ )
256
+ ] });
257
+ }
258
+ export {
259
+ SimulationFilter
260
+ };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "colbrush",
3
- "version": "1.5.0",
3
+ "version": "1.7.0",
4
4
  "description": "A React theme switching library that makes it easy to apply color-blind accessible UI themes",
5
5
  "homepage": "https://colbrush.vercel.app",
6
6
  "repository": {
@@ -18,10 +18,21 @@
18
18
  "import": "./dist/client.js",
19
19
  "require": "./dist/client.cjs"
20
20
  },
21
+ "./devtools": {
22
+ "types": "./dist/devtools.d.ts",
23
+ "import": "./dist/devtools.js",
24
+ "require": "./dist/devtools.cjs"
25
+ },
21
26
  "./package.json": "./package.json"
22
27
  },
23
28
  "typesVersions": {
24
29
  "*": {
30
+ "devtools": [
31
+ "./dist/devtools.d.ts"
32
+ ],
33
+ "client": [
34
+ "./dist/client.d.ts"
35
+ ],
25
36
  "*": [
26
37
  "./dist/client.d.ts"
27
38
  ]