@berenjena/react-dev-panel 2.3.0 → 2.4.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.
Files changed (37) hide show
  1. package/README.md +97 -260
  2. package/dist/assets/index11.css +1 -1
  3. package/dist/assets/index12.css +1 -1
  4. package/dist/assets/index13.css +1 -1
  5. package/dist/assets/index14.css +1 -1
  6. package/dist/assets/index15.css +1 -1
  7. package/dist/assets/index16.css +1 -0
  8. package/dist/assets/index7.css +1 -1
  9. package/dist/components/ControlRenderer/controls/BooleanControl/index.js +1 -1
  10. package/dist/components/ControlRenderer/controls/ButtonControl/index.js +1 -1
  11. package/dist/components/ControlRenderer/controls/ButtonGroupControl/index.js +1 -1
  12. package/dist/components/ControlRenderer/controls/ColorControl/index.js +1 -1
  13. package/dist/components/ControlRenderer/controls/DragAndDropControl/index.js +1 -1
  14. package/dist/components/ControlRenderer/controls/LocalStorageControl/index.d.ts +23 -0
  15. package/dist/components/ControlRenderer/controls/LocalStorageControl/index.js +252 -0
  16. package/dist/components/ControlRenderer/controls/LocalStorageControl/types.d.ts +14 -0
  17. package/dist/components/ControlRenderer/controls/SelectControl/index.js +15 -5
  18. package/dist/components/ControlRenderer/controls/SelectControl/types.d.ts +2 -0
  19. package/dist/components/ControlRenderer/controls/index.d.ts +1 -0
  20. package/dist/components/ControlRenderer/controls/index.js +2 -1
  21. package/dist/components/ControlRenderer/controls/types.d.ts +2 -0
  22. package/dist/components/ControlRenderer/index.js +12 -12
  23. package/dist/components/Select/index.d.ts +3 -1
  24. package/dist/components/Select/index.js +124 -89
  25. package/dist/utils/copyToClipboard/copyToClipboard.d.ts +17 -0
  26. package/dist/utils/copyToClipboard/copyToClipboard.js +10 -0
  27. package/dist/utils/copyToClipboard/index.d.ts +1 -0
  28. package/dist/utils/copyToClipboard/index.js +4 -0
  29. package/dist/utils/getStringPreview/getStringPreview.d.ts +14 -0
  30. package/dist/utils/getStringPreview/getStringPreview.js +6 -0
  31. package/dist/utils/getStringPreview/index.d.ts +1 -0
  32. package/dist/utils/getStringPreview/index.js +4 -0
  33. package/dist/utils/prettifyJson/index.d.ts +1 -0
  34. package/dist/utils/prettifyJson/index.js +4 -0
  35. package/dist/utils/prettifyJson/prettifyJson.d.ts +13 -0
  36. package/dist/utils/prettifyJson/prettifyJson.js +11 -0
  37. package/package.json +9 -3
@@ -1,33 +1,51 @@
1
- import { jsxs as y, Fragment as q, jsx as a } from "react/jsx-runtime";
2
- import { useRef as x, useState as C, useCallback as z, useEffect as P } from "react";
3
- import { createPortal as T } from "react-dom";
4
- import { Icon as j } from "../Icon/index.js";
5
- import { useDevPanelPosition as B } from "../../store/UIStore.js";
6
- import { className as F } from "../../utils/className/className.js";
7
- import '../../assets/index7.css';const W = "_select_ug510_217", U = "_trigger_ug510_222", G = "_open_ug510_271", J = "_value_ug510_275", K = "_placeholder_ug510_284", Q = "_arrow_ug510_288", X = "_dropdownPortal_ug510_303", Y = "_dropdown_ug510_303", Z = "_option_ug510_342", ee = "_selected_ug510_361", te = "_checkbox_ug510_370", ne = "_label_ug510_391", r = {
8
- select: W,
9
- trigger: U,
10
- open: G,
11
- value: J,
12
- placeholder: K,
13
- arrow: Q,
14
- dropdownPortal: X,
15
- dropdown: Y,
16
- option: Z,
17
- selected: ee,
18
- checkbox: te,
19
- label: ne
1
+ import { jsxs as x, Fragment as W, jsx as i } from "react/jsx-runtime";
2
+ import { useRef as P, useState as N, useMemo as U, useCallback as G, useEffect as R } from "react";
3
+ import { createPortal as J } from "react-dom";
4
+ import { Icon as K } from "../Icon/index.js";
5
+ import { useDevPanelPosition as X } from "../../store/UIStore.js";
6
+ import { className as Y } from "../../utils/className/className.js";
7
+ import '../../assets/index7.css';const Z = "_select_15gl5_217", ee = "_trigger_15gl5_222", te = "_open_15gl5_271", ne = "_value_15gl5_275", oe = "_placeholder_15gl5_284", re = "_arrow_15gl5_288", se = "_dropdownPortal_15gl5_303", ce = "_dropdown_15gl5_303", ie = "_searchContainer_15gl5_323", le = "_searchInput_15gl5_329", ae = "_optionsList_15gl5_371", de = "_noResults_15gl5_397", ue = "_option_15gl5_371", pe = "_selected_15gl5_423", he = "_checkbox_15gl5_432", fe = "_label_15gl5_453", r = {
8
+ select: Z,
9
+ trigger: ee,
10
+ open: te,
11
+ value: ne,
12
+ placeholder: oe,
13
+ arrow: re,
14
+ dropdownPortal: se,
15
+ dropdown: ce,
16
+ searchContainer: ie,
17
+ searchInput: le,
18
+ optionsList: ae,
19
+ noResults: de,
20
+ option: ue,
21
+ selected: pe,
22
+ checkbox: he,
23
+ label: fe
20
24
  };
21
- function ae({ value: f, options: v, onChange: L, disabled: h = !1, multiple: u = !1, placeholder: k = "Select..." }) {
22
- const g = B(), w = x(null), p = x(null), E = x(null), [i, m] = C(!1), [_, N] = C({
25
+ function ye({
26
+ value: f,
27
+ options: h,
28
+ onChange: k,
29
+ disabled: g = !1,
30
+ multiple: u = !1,
31
+ placeholder: I = "Select...",
32
+ searchable: w = !1,
33
+ searchPlaceholder: V = "Search..."
34
+ }) {
35
+ const m = X(), _ = P(null), p = P(null), O = P(null), E = P(null), [l, v] = N(!1), [b, L] = N(""), [y, S] = N({
23
36
  top: 0,
24
37
  left: 0,
25
38
  width: 0,
26
39
  maxHeight: 200
27
- }), d = u ? Array.isArray(f) ? f : [] : typeof f == "string" ? f : "", D = A(), S = u ? d.length === 0 : !d, c = z(() => {
28
- i && N(O());
29
- }, [i]);
30
- function O() {
40
+ }), d = u ? Array.isArray(f) ? f : [] : typeof f == "string" ? f : "", $ = T(), q = u ? d.length === 0 : !d, H = U(() => {
41
+ if (!w || !b)
42
+ return h;
43
+ const e = b.toLowerCase();
44
+ return h.filter((t) => (typeof t == "string" ? t : t.label).toLowerCase().includes(e));
45
+ }, [h, w, b]), c = G(() => {
46
+ l && S(D());
47
+ }, [l]);
48
+ function D() {
31
49
  if (!p.current)
32
50
  return {
33
51
  top: 0,
@@ -35,46 +53,49 @@ function ae({ value: f, options: v, onChange: L, disabled: h = !1, multiple: u =
35
53
  width: 0,
36
54
  maxHeight: 200
37
55
  };
38
- const e = p.current.getBoundingClientRect(), t = window.innerHeight, n = window.innerWidth, o = 200, l = 4, s = t - e.bottom - l, b = e.top - l, H = s < o && b > s, $ = H ? e.top - Math.min(o, b) : e.bottom + l, I = Math.max(8, Math.min(e.left, n - e.width - 8)), M = H ? Math.min(o, b) : Math.min(o, s);
56
+ const e = p.current.getBoundingClientRect(), t = window.innerHeight, n = window.innerWidth, o = 200, a = 4, s = t - e.bottom - a, C = e.top - a, M = s < o && C > s, B = M ? e.top - Math.min(o, C) : e.bottom + a, F = Math.max(8, Math.min(e.left, n - e.width - 8)), Q = M ? Math.min(o, C) : Math.min(o, s);
39
57
  return {
40
- top: $,
41
- left: I,
58
+ top: B,
59
+ left: F,
42
60
  width: e.width,
43
- maxHeight: M
61
+ maxHeight: Q
44
62
  };
45
63
  }
46
- function R(e) {
64
+ function A(e) {
47
65
  if (u) {
48
66
  const t = d, n = t.includes(e) ? t.filter((o) => o !== e) : [...t, e];
49
- L(n);
67
+ k(n);
50
68
  } else
51
- L(e), m(!1);
69
+ k(e), v(!1);
52
70
  }
53
- function A() {
71
+ function T() {
54
72
  if (u) {
55
73
  const e = d;
56
74
  if (e.length === 0)
57
- return k;
75
+ return I;
58
76
  if (e.length === 1) {
59
- const t = v.find((o) => (typeof o == "string" ? o : o.value) === e[0]);
77
+ const t = h.find((o) => (typeof o == "string" ? o : o.value) === e[0]);
60
78
  return (typeof t == "string" ? t : t?.label) || e[0];
61
79
  }
62
80
  return `${e.length} selected`;
63
81
  } else {
64
82
  const e = d;
65
83
  if (!e)
66
- return k;
67
- const t = v.find((o) => (typeof o == "string" ? o : o.value) === e);
84
+ return I;
85
+ const t = h.find((o) => (typeof o == "string" ? o : o.value) === e);
68
86
  return (typeof t == "string" ? t : t?.label) || e;
69
87
  }
70
88
  }
71
- function V() {
72
- h || (i ? m(!1) : (N(O()), m(!0)));
89
+ function z() {
90
+ g || (l ? (v(!1), L("")) : (S(D()), v(!0), L(""), w && setTimeout(() => O.current?.focus(), 0)));
73
91
  }
74
- return P(() => {
75
- if (!i) return;
92
+ function j(e) {
93
+ L(e.target.value);
94
+ }
95
+ return R(() => {
96
+ if (!l) return;
76
97
  c(), window.addEventListener("resize", c), window.addEventListener("scroll", c, !0);
77
- const e = w.current?.closest("[data-dev-panel]") || document.querySelector("[data-dev-panel]");
98
+ const e = _.current?.closest("[data-dev-panel]") || document.querySelector("[data-dev-panel]");
78
99
  e && e.addEventListener("scroll", c, !0);
79
100
  let t = null;
80
101
  if (p.current && "IntersectionObserver" in window) {
@@ -86,9 +107,9 @@ function ae({ value: f, options: v, onChange: L, disabled: h = !1, multiple: u =
86
107
  };
87
108
  t = new IntersectionObserver(
88
109
  (o) => {
89
- const l = o[0];
90
- if (l && l.target === p.current) {
91
- const s = l.boundingClientRect;
110
+ const a = o[0];
111
+ if (a && a.target === p.current) {
112
+ const s = a.boundingClientRect;
92
113
  (s.top !== n.top || s.left !== n.left || s.width !== n.width || s.height !== n.height) && (n.top = s.top, n.left = s.left, n.width = s.width, n.height = s.height, c());
93
114
  }
94
115
  },
@@ -100,73 +121,87 @@ function ae({ value: f, options: v, onChange: L, disabled: h = !1, multiple: u =
100
121
  return () => {
101
122
  window.removeEventListener("resize", c), window.removeEventListener("scroll", c, !0), e && e.removeEventListener("scroll", c, !0), t && t.disconnect();
102
123
  };
103
- }, [i, c]), P(() => {
124
+ }, [l, c]), R(() => {
104
125
  const e = E.current;
105
- (!e || e.x !== g.x || e.y !== g.y) && (E.current = g, i && requestAnimationFrame(c));
106
- }, [i, g, c]), P(() => {
126
+ (!e || e.x !== m.x || e.y !== m.y) && (E.current = m, l && requestAnimationFrame(c));
127
+ }, [l, m, c]), R(() => {
107
128
  function e(t) {
108
- if (w.current && !w.current.contains(t.target)) {
129
+ if (_.current && !_.current.contains(t.target)) {
109
130
  const n = document.querySelector(`.${r.dropdownPortal}`);
110
131
  if (n && n.contains(t.target))
111
132
  return;
112
- m(!1);
133
+ v(!1);
113
134
  }
114
135
  }
115
136
  return document.addEventListener("mousedown", e), () => {
116
137
  document.removeEventListener("mousedown", e);
117
138
  };
118
- }, []), /* @__PURE__ */ y(q, { children: [
119
- /* @__PURE__ */ a(
139
+ }, []), /* @__PURE__ */ x(W, { children: [
140
+ /* @__PURE__ */ i(
120
141
  "div",
121
142
  {
122
- ref: w,
123
- ...F(r.select, {
124
- [r.disabled]: h,
125
- [r.open]: i
143
+ ref: _,
144
+ ...Y(r.select, {
145
+ [r.disabled]: g,
146
+ [r.open]: l
126
147
  }),
127
- children: /* @__PURE__ */ y("button", { ref: p, type: "button", className: r.trigger, onClick: V, disabled: h, children: [
128
- /* @__PURE__ */ a("span", { className: `${r.value} ${S ? r.placeholder : ""}`, children: D }),
129
- /* @__PURE__ */ a(j, { name: "ArrowDown", className: r.arrow })
148
+ children: /* @__PURE__ */ x("button", { ref: p, type: "button", className: r.trigger, onClick: z, disabled: g, children: [
149
+ /* @__PURE__ */ i("span", { className: `${r.value} ${q ? r.placeholder : ""}`, children: $ }),
150
+ /* @__PURE__ */ i(K, { name: "ArrowDown", className: r.arrow })
130
151
  ] })
131
152
  }
132
153
  ),
133
- typeof window < "u" && T(
134
- i && !h && /* @__PURE__ */ a(
154
+ typeof window < "u" && J(
155
+ l && !g && /* @__PURE__ */ i(
135
156
  "div",
136
157
  {
137
158
  className: r.dropdownPortal,
138
159
  style: {
139
160
  position: "fixed",
140
- top: _.top,
141
- left: _.left,
142
- width: _.width,
143
- maxHeight: _.maxHeight,
161
+ top: y.top,
162
+ left: y.left,
163
+ width: y.width,
164
+ maxHeight: y.maxHeight,
144
165
  zIndex: 9999
145
166
  },
146
- children: /* @__PURE__ */ a("div", { className: r.dropdown, children: v.map((e) => {
147
- const t = typeof e == "string" ? e : e.value, n = typeof e == "string" ? e : e.label, o = u ? d.includes(t) : d === t;
148
- return u ? /* @__PURE__ */ y("label", { className: r.option, children: [
149
- /* @__PURE__ */ a(
150
- "input",
151
- {
152
- type: "checkbox",
153
- checked: o,
154
- onChange: () => R(t),
155
- className: r.checkbox
156
- }
157
- ),
158
- /* @__PURE__ */ a("span", { className: r.label, children: n })
159
- ] }, t) : /* @__PURE__ */ a(
160
- "button",
167
+ children: /* @__PURE__ */ x("div", { className: r.dropdown, children: [
168
+ w && /* @__PURE__ */ i("div", { className: r.searchContainer, children: /* @__PURE__ */ i(
169
+ "input",
161
170
  {
162
- type: "button",
163
- className: `${r.option} ${o ? r.selected : ""}`,
164
- onClick: () => R(t),
165
- children: n
166
- },
167
- t
168
- );
169
- }) })
171
+ ref: O,
172
+ type: "text",
173
+ className: r.searchInput,
174
+ placeholder: V,
175
+ value: b,
176
+ onChange: j,
177
+ onClick: (e) => e.stopPropagation()
178
+ }
179
+ ) }),
180
+ /* @__PURE__ */ i("div", { className: r.optionsList, children: H.length === 0 ? /* @__PURE__ */ i("div", { className: r.noResults, children: "No results found" }) : H.map((e) => {
181
+ const t = typeof e == "string" ? e : e.value, n = typeof e == "string" ? e : e.label, o = u ? d.includes(t) : d === t;
182
+ return u ? /* @__PURE__ */ x("label", { className: r.option, children: [
183
+ /* @__PURE__ */ i(
184
+ "input",
185
+ {
186
+ type: "checkbox",
187
+ checked: o,
188
+ onChange: () => A(t),
189
+ className: r.checkbox
190
+ }
191
+ ),
192
+ /* @__PURE__ */ i("span", { className: r.label, children: n })
193
+ ] }, t) : /* @__PURE__ */ i(
194
+ "button",
195
+ {
196
+ type: "button",
197
+ className: `${r.option} ${o ? r.selected : ""}`,
198
+ onClick: () => A(t),
199
+ children: n
200
+ },
201
+ t
202
+ );
203
+ }) })
204
+ ] })
170
205
  }
171
206
  ),
172
207
  document.body
@@ -174,5 +209,5 @@ function ae({ value: f, options: v, onChange: L, disabled: h = !1, multiple: u =
174
209
  ] });
175
210
  }
176
211
  export {
177
- ae as Select
212
+ ye as Select
178
213
  };
@@ -0,0 +1,17 @@
1
+ /**
2
+ * Copies text to clipboard with optional feedback timing
3
+ *
4
+ * @param text - The text to copy to clipboard
5
+ * @returns Promise that resolves when text is copied, rejects if copy fails
6
+ *
7
+ * @example
8
+ * ```typescript
9
+ * try {
10
+ * await copyToClipboard("Hello World", 2000);
11
+ * console.log("Copied!");
12
+ * } catch {
13
+ * console.error("Failed to copy");
14
+ * }
15
+ * ```
16
+ */
17
+ export declare function copyToClipboard(text: string): Promise<void>;
@@ -0,0 +1,10 @@
1
+ async function t(o) {
2
+ try {
3
+ await navigator.clipboard.writeText(o);
4
+ } catch (r) {
5
+ throw new Error(`Failed to copy to clipboard: ${r instanceof Error ? r.message : String(r)}`);
6
+ }
7
+ }
8
+ export {
9
+ t as copyToClipboard
10
+ };
@@ -0,0 +1 @@
1
+ export { copyToClipboard } from './copyToClipboard';
@@ -0,0 +1,4 @@
1
+ import { copyToClipboard as r } from "./copyToClipboard.js";
2
+ export {
3
+ r as copyToClipboard
4
+ };
@@ -0,0 +1,14 @@
1
+ /**
2
+ * Returns a truncated preview of a string with ellipsis suffix if it exceeds max length
3
+ *
4
+ * @param text - The text to get preview from
5
+ * @param maxLength - Maximum length before truncating (default: 100)
6
+ * @returns Truncated text with "..." suffix if longer than maxLength, original text otherwise
7
+ *
8
+ * @example
9
+ * ```typescript
10
+ * getStringPreview("Hello World", 5) // Returns "Hello..."
11
+ * getStringPreview("Hi", 5) // Returns "Hi"
12
+ * ```
13
+ */
14
+ export declare function getStringPreview(text: string, maxLength?: number): string;
@@ -0,0 +1,6 @@
1
+ function i(r, e = 100) {
2
+ return r.length <= e ? r : r.slice(0, e) + "...";
3
+ }
4
+ export {
5
+ i as getStringPreview
6
+ };
@@ -0,0 +1 @@
1
+ export { getStringPreview } from './getStringPreview';
@@ -0,0 +1,4 @@
1
+ import { getStringPreview as t } from "./getStringPreview.js";
2
+ export {
3
+ t as getStringPreview
4
+ };
@@ -0,0 +1 @@
1
+ export { prettifyJson } from './prettifyJson';
@@ -0,0 +1,4 @@
1
+ import { prettifyJson as t } from "./prettifyJson.js";
2
+ export {
3
+ t as prettifyJson
4
+ };
@@ -0,0 +1,13 @@
1
+ /**
2
+ * Prettifies a JSON string by formatting it with indentation or returning it as-is if not valid JSON
3
+ *
4
+ * @param value - The JSON string to prettify
5
+ * @returns Prettified JSON string or original value if parsing fails
6
+ *
7
+ * @example
8
+ * ```typescript
9
+ * prettifyJson('{"name":"John"}') // Returns '{\n "name": "John"\n}'
10
+ * prettifyJson('invalid') // Returns 'invalid'
11
+ * ```
12
+ */
13
+ export declare function prettifyJson(value: string): string;
@@ -0,0 +1,11 @@
1
+ function n(r) {
2
+ try {
3
+ const t = JSON.parse(r);
4
+ return JSON.stringify(t, null, 2);
5
+ } catch {
6
+ return r;
7
+ }
8
+ }
9
+ export {
10
+ n as prettifyJson
11
+ };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "private": false,
3
- "version": "2.3.0",
3
+ "version": "2.4.0",
4
4
  "license": "MIT",
5
5
  "name": "@berenjena/react-dev-panel",
6
6
  "description": "A React development panel with various tools and utilities.",
@@ -65,9 +65,12 @@
65
65
  "test": "vitest",
66
66
  "test:ui": "vitest --ui",
67
67
  "coverage": "vitest run --coverage",
68
- "prepublishOnly": "vitest run && npm run build",
68
+ "size": "size-limit",
69
+ "size:analyze": "npm run build && size-limit --json > .size-limit-output.json && node scripts/analyze-bundle.js",
70
+ "size:watch": "bundlewatch",
71
+ "prepublishOnly": "vitest run && npm run build && npm run size",
69
72
  "changeset": "changeset",
70
- "prerelease": "vitest run && npm run build",
73
+ "prerelease": "vitest run && npm run build && npm run size",
71
74
  "release": "changeset publish",
72
75
  "prepare": "npx husky",
73
76
  "commit": "git-cz"
@@ -86,6 +89,7 @@
86
89
  "@commitlint/cz-commitlint": "^19.8.1",
87
90
  "@eslint/js": "^9.32.0",
88
91
  "@rollup/plugin-terser": "^0.4.4",
92
+ "@size-limit/preset-small-lib": "^12.0.0",
89
93
  "@storybook/addon-docs": "^9.1.0",
90
94
  "@storybook/react-vite": "^9.1.0",
91
95
  "@types/node": "^24.1.0",
@@ -94,6 +98,7 @@
94
98
  "@vitejs/plugin-react-swc": "^3.11.0",
95
99
  "@vitest/coverage-v8": "^3.2.4",
96
100
  "@vitest/ui": "^3.2.4",
101
+ "bundlewatch": "^0.4.1",
97
102
  "commitizen": "^4.3.1",
98
103
  "eslint": "^9.32.0",
99
104
  "eslint-plugin-react": "^7.37.5",
@@ -109,6 +114,7 @@
109
114
  "react": "^19.1.1",
110
115
  "react-dom": "^19.1.1",
111
116
  "sass-embedded": "^1.89.2",
117
+ "size-limit": "^12.0.0",
112
118
  "storybook": "^9.1.0",
113
119
  "stylelint": "^16.23.0",
114
120
  "typescript": "^5.9.2",