@moyarich/console-addon-resizable 0.0.0-stage → 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.cjs ADDED
@@ -0,0 +1,377 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
3
+ const jsxRuntime = require("react/jsx-runtime");
4
+ const lucideReact = require("lucide-react");
5
+ const react = require("react");
6
+ const consoleCore = require("@moyarich/console-core");
7
+ const horizontal$3 = "Resize console horizontally";
8
+ const horizontalTitle$3 = "Drag to resize horizontally";
9
+ const vertical$3 = "Resize console vertically";
10
+ const verticalTitle$3 = "Drag to resize vertically";
11
+ const both$3 = "Resize console in both directions";
12
+ const bothTitle$3 = "Drag to resize width and height";
13
+ const en = {
14
+ horizontal: horizontal$3,
15
+ horizontalTitle: horizontalTitle$3,
16
+ vertical: vertical$3,
17
+ verticalTitle: verticalTitle$3,
18
+ both: both$3,
19
+ bothTitle: bothTitle$3
20
+ };
21
+ const horizontal$2 = "Redimensionar horizontalmente";
22
+ const horizontalTitle$2 = "Arrastrar para cambiar el ancho";
23
+ const vertical$2 = "Redimensionar verticalmente";
24
+ const verticalTitle$2 = "Arrastrar para cambiar la altura";
25
+ const both$2 = "Redimensionar en ambas direcciones";
26
+ const bothTitle$2 = "Arrastrar para cambiar ancho y altura";
27
+ const es = {
28
+ horizontal: horizontal$2,
29
+ horizontalTitle: horizontalTitle$2,
30
+ vertical: vertical$2,
31
+ verticalTitle: verticalTitle$2,
32
+ both: both$2,
33
+ bothTitle: bothTitle$2
34
+ };
35
+ const horizontal$1 = "Redimensionner horizontalement";
36
+ const horizontalTitle$1 = "Glisser pour modifier la largeur";
37
+ const vertical$1 = "Redimensionner verticalement";
38
+ const verticalTitle$1 = "Glisser pour modifier la hauteur";
39
+ const both$1 = "Redimensionner dans les deux sens";
40
+ const bothTitle$1 = "Glisser pour modifier largeur et hauteur";
41
+ const fr = {
42
+ horizontal: horizontal$1,
43
+ horizontalTitle: horizontalTitle$1,
44
+ vertical: vertical$1,
45
+ verticalTitle: verticalTitle$1,
46
+ both: both$1,
47
+ bothTitle: bothTitle$1
48
+ };
49
+ const horizontal = "Redimensionar o console horizontalmente";
50
+ const horizontalTitle = "Arraste para redimensionar horizontalmente";
51
+ const vertical = "Redimensionar o console verticalmente";
52
+ const verticalTitle = "Arraste para redimensionar verticalmente";
53
+ const both = "Redimensionar o console nas duas direções";
54
+ const bothTitle = "Arraste para alterar a largura e a altura";
55
+ const pt = {
56
+ horizontal,
57
+ horizontalTitle,
58
+ vertical,
59
+ verticalTitle,
60
+ both,
61
+ bothTitle
62
+ };
63
+ const locales = { en, es, fr, pt };
64
+ function resolveAddonMessages(locale = "en", overrides) {
65
+ const tag = locale.replace(/_/g, "-").toLowerCase();
66
+ return {
67
+ ...en,
68
+ ...locales[tag] ?? locales[tag.split("-")[0]] ?? {},
69
+ ...overrides
70
+ };
71
+ }
72
+ function resolveConsoleResizeAxes(direction) {
73
+ return {
74
+ horizontal: direction === "horizontal" || direction === "both" || direction === "inline",
75
+ vertical: direction === "vertical" || direction === "both" || direction === "block"
76
+ };
77
+ }
78
+ function clamp(value, min, max) {
79
+ return Math.min(Math.max(value, min), Math.max(min, max));
80
+ }
81
+ function getCornerCursor(horizontalEdge, verticalEdge) {
82
+ return horizontalEdge === verticalEdge ? "nwse-resize" : "nesw-resize";
83
+ }
84
+ function toCssSize(value) {
85
+ return typeof value === "number" ? `${value}px` : value;
86
+ }
87
+ function ResizableConsoleFrame({
88
+ mode,
89
+ options,
90
+ children
91
+ }) {
92
+ const {
93
+ direction = "both",
94
+ defaultWidth = 720,
95
+ defaultHeight = 300,
96
+ minWidth = 320,
97
+ minHeight = 180,
98
+ maxWidth,
99
+ maxHeight,
100
+ horizontalEdge = "end",
101
+ verticalEdge = "end",
102
+ className = "",
103
+ style,
104
+ onResize,
105
+ locale = "en",
106
+ translations
107
+ } = options;
108
+ const labels = resolveAddonMessages(locale, translations);
109
+ const axes = resolveConsoleResizeAxes(direction);
110
+ const frameRef = react.useRef(null);
111
+ const dragRef = react.useRef(null);
112
+ const bodyStyleRef = react.useRef(
113
+ null
114
+ );
115
+ const [width, setWidth] = react.useState(defaultWidth);
116
+ const [height, setHeight] = react.useState(defaultHeight);
117
+ const [activeAxis, setActiveAxis] = react.useState(null);
118
+ const restoreBodyStyles = react.useCallback(() => {
119
+ if (typeof document === "undefined" || !bodyStyleRef.current) {
120
+ return;
121
+ }
122
+ document.body.style.cursor = bodyStyleRef.current.cursor;
123
+ document.body.style.userSelect = bodyStyleRef.current.userSelect;
124
+ bodyStyleRef.current = null;
125
+ }, []);
126
+ const stopResize = react.useCallback(
127
+ (event) => {
128
+ const drag = dragRef.current;
129
+ if (drag && event && drag.pointerId === event.pointerId && drag.target.hasPointerCapture(event.pointerId)) {
130
+ drag.target.releasePointerCapture(event.pointerId);
131
+ }
132
+ dragRef.current = null;
133
+ setActiveAxis(null);
134
+ restoreBodyStyles();
135
+ },
136
+ [restoreBodyStyles]
137
+ );
138
+ react.useEffect(
139
+ () => () => {
140
+ dragRef.current = null;
141
+ restoreBodyStyles();
142
+ },
143
+ [restoreBodyStyles]
144
+ );
145
+ react.useEffect(() => {
146
+ if (!dragRef.current) {
147
+ return;
148
+ }
149
+ dragRef.current = null;
150
+ setActiveAxis(null);
151
+ restoreBodyStyles();
152
+ }, [direction, restoreBodyStyles]);
153
+ const startResize = (event, axis) => {
154
+ event.preventDefault();
155
+ const frame = frameRef.current;
156
+ if (!frame) {
157
+ return;
158
+ }
159
+ const bounds = frame.getBoundingClientRect();
160
+ const parentBounds = frame.parentElement?.getBoundingClientRect();
161
+ const parentMaxWidth = parentBounds?.width ?? Number.POSITIVE_INFINITY;
162
+ const resolvedMaxWidth = Math.min(
163
+ maxWidth ?? parentMaxWidth,
164
+ parentMaxWidth
165
+ );
166
+ const resolvedMaxHeight = maxHeight ?? Number.POSITIVE_INFINITY;
167
+ event.currentTarget.setPointerCapture(event.pointerId);
168
+ dragRef.current = {
169
+ axis,
170
+ pointerId: event.pointerId,
171
+ target: event.currentTarget,
172
+ startX: event.clientX,
173
+ startY: event.clientY,
174
+ startWidth: bounds.width,
175
+ startHeight: bounds.height,
176
+ maxWidth: resolvedMaxWidth,
177
+ maxHeight: resolvedMaxHeight
178
+ };
179
+ setActiveAxis(axis);
180
+ if (typeof document !== "undefined") {
181
+ bodyStyleRef.current = {
182
+ cursor: document.body.style.cursor,
183
+ userSelect: document.body.style.userSelect
184
+ };
185
+ document.body.style.cursor = axis === "both" ? getCornerCursor(horizontalEdge, verticalEdge) : axis === "horizontal" ? "col-resize" : "row-resize";
186
+ document.body.style.userSelect = "none";
187
+ }
188
+ };
189
+ const moveResize = (event) => {
190
+ const drag = dragRef.current;
191
+ if (!drag || drag.pointerId !== event.pointerId) {
192
+ return;
193
+ }
194
+ let nextWidth = drag.startWidth;
195
+ let nextHeight = drag.startHeight;
196
+ if (drag.axis === "horizontal" || drag.axis === "both") {
197
+ const directionMultiplier = horizontalEdge === "end" ? 1 : -1;
198
+ nextWidth = clamp(
199
+ drag.startWidth + (event.clientX - drag.startX) * directionMultiplier,
200
+ minWidth,
201
+ drag.maxWidth
202
+ );
203
+ setWidth(nextWidth);
204
+ }
205
+ if (drag.axis === "vertical" || drag.axis === "both") {
206
+ const directionMultiplier = verticalEdge === "end" ? 1 : -1;
207
+ nextHeight = clamp(
208
+ drag.startHeight + (event.clientY - drag.startY) * directionMultiplier,
209
+ minHeight,
210
+ drag.maxHeight
211
+ );
212
+ setHeight(nextHeight);
213
+ }
214
+ onResize?.({
215
+ width: nextWidth,
216
+ height: nextHeight
217
+ });
218
+ };
219
+ const resizeWithKeyboard = (event, axis) => {
220
+ const horizontal2 = axis !== "vertical" && (event.key === "ArrowLeft" || event.key === "ArrowRight");
221
+ const vertical2 = axis !== "horizontal" && (event.key === "ArrowUp" || event.key === "ArrowDown");
222
+ const frame = frameRef.current;
223
+ if (!frame || !horizontal2 && !vertical2) return;
224
+ event.preventDefault();
225
+ event.stopPropagation();
226
+ const bounds = frame.getBoundingClientRect();
227
+ const parentWidth = frame.parentElement?.getBoundingClientRect().width ?? Infinity;
228
+ const step = event.shiftKey ? 50 : 10;
229
+ let nextWidth = bounds.width;
230
+ let nextHeight = bounds.height;
231
+ if (horizontal2) {
232
+ const sign = (event.key === "ArrowRight" ? 1 : -1) * (horizontalEdge === "end" ? 1 : -1);
233
+ nextWidth = clamp(
234
+ bounds.width + sign * step,
235
+ minWidth,
236
+ Math.min(maxWidth ?? parentWidth, parentWidth)
237
+ );
238
+ setWidth(nextWidth);
239
+ }
240
+ if (vertical2) {
241
+ const sign = (event.key === "ArrowDown" ? 1 : -1) * (verticalEdge === "end" ? 1 : -1);
242
+ nextHeight = clamp(
243
+ bounds.height + sign * step,
244
+ minHeight,
245
+ maxHeight ?? Infinity
246
+ );
247
+ setHeight(nextHeight);
248
+ }
249
+ onResize?.({ width: nextWidth, height: nextHeight });
250
+ };
251
+ const renderHorizontalHandle = () => {
252
+ if (!axes.horizontal) {
253
+ return null;
254
+ }
255
+ return /* @__PURE__ */ jsxRuntime.jsx(
256
+ "div",
257
+ {
258
+ className: "console-resize-handle",
259
+ role: "separator",
260
+ "aria-orientation": "vertical",
261
+ "aria-valuemin": minWidth,
262
+ "aria-valuemax": maxWidth,
263
+ "aria-valuenow": typeof width === "number" ? width : void 0,
264
+ "aria-label": labels.horizontal,
265
+ title: labels.horizontalTitle,
266
+ tabIndex: 0,
267
+ "data-console-resize-axis": "horizontal",
268
+ onKeyDown: (event) => resizeWithKeyboard(event, "horizontal"),
269
+ "data-active": activeAxis === "horizontal" || void 0,
270
+ onPointerDown: (event) => startResize(event, "horizontal"),
271
+ onPointerMove: moveResize,
272
+ onPointerUp: stopResize,
273
+ onPointerCancel: stopResize,
274
+ children: /* @__PURE__ */ jsxRuntime.jsx("span", { className: "console-resize-grip", "aria-hidden": "true", children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.GripVertical, { size: 14 }) })
275
+ }
276
+ );
277
+ };
278
+ const renderVerticalHandle = () => {
279
+ if (!axes.vertical) {
280
+ return null;
281
+ }
282
+ return /* @__PURE__ */ jsxRuntime.jsx(
283
+ "div",
284
+ {
285
+ className: "console-resize-handle",
286
+ role: "separator",
287
+ "aria-orientation": "horizontal",
288
+ "aria-valuemin": minHeight,
289
+ "aria-valuemax": maxHeight,
290
+ "aria-valuenow": typeof height === "number" ? height : void 0,
291
+ "aria-label": labels.vertical,
292
+ title: labels.verticalTitle,
293
+ tabIndex: 0,
294
+ "data-console-resize-axis": "vertical",
295
+ onKeyDown: (event) => resizeWithKeyboard(event, "vertical"),
296
+ "data-active": activeAxis === "vertical" || void 0,
297
+ onPointerDown: (event) => startResize(event, "vertical"),
298
+ onPointerMove: moveResize,
299
+ onPointerUp: stopResize,
300
+ onPointerCancel: stopResize,
301
+ children: /* @__PURE__ */ jsxRuntime.jsx("span", { className: "console-resize-grip", "aria-hidden": "true", children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.GripHorizontal, { size: 14 }) })
302
+ }
303
+ );
304
+ };
305
+ const renderCornerHandle = () => {
306
+ if (direction !== "both") {
307
+ return null;
308
+ }
309
+ return /* @__PURE__ */ jsxRuntime.jsx(
310
+ "div",
311
+ {
312
+ className: "console-resize-corner-handle",
313
+ role: "separator",
314
+ "aria-label": labels.both,
315
+ title: labels.bothTitle,
316
+ tabIndex: 0,
317
+ "data-console-resize-axis": "both",
318
+ onKeyDown: (event) => resizeWithKeyboard(event, "both"),
319
+ "data-active": activeAxis === "both" || void 0,
320
+ onPointerDown: (event) => startResize(event, "both"),
321
+ onPointerMove: moveResize,
322
+ onPointerUp: stopResize,
323
+ onPointerCancel: stopResize,
324
+ children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.MoveDiagonal2, { size: 15, "aria-hidden": "true" })
325
+ }
326
+ );
327
+ };
328
+ return /* @__PURE__ */ jsxRuntime.jsxs(
329
+ "div",
330
+ {
331
+ ref: frameRef,
332
+ className: `console-resizable-frame ${className}`.trim(),
333
+ "data-console-resize-direction": direction,
334
+ "data-console-resize-horizontal-edge": horizontalEdge,
335
+ "data-console-resize-vertical-edge": verticalEdge,
336
+ "data-console-mode": mode,
337
+ style: {
338
+ "--_console-resizable-width": toCssSize(width),
339
+ "--_console-resizable-height": toCssSize(height),
340
+ "--_console-resizable-min-width": `${minWidth}px`,
341
+ "--_console-resizable-min-height": `${minHeight}px`,
342
+ "--_console-resizable-max-width": maxWidth === void 0 ? "100%" : `${maxWidth}px`,
343
+ "--_console-resizable-max-height": maxHeight === void 0 ? "100%" : `${maxHeight}px`,
344
+ ...style
345
+ },
346
+ children: [
347
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "console-resizable-frame-content", children }),
348
+ renderHorizontalHandle(),
349
+ renderVerticalHandle(),
350
+ renderCornerHandle()
351
+ ]
352
+ }
353
+ );
354
+ }
355
+ const RESIZABLE_CONSOLE_ADDON_ID = "@moyarich/console-addon-resizable";
356
+ function createResizableConsoleAddon(options = {}) {
357
+ const decorator = {
358
+ render(context) {
359
+ return /* @__PURE__ */ jsxRuntime.jsx(ResizableConsoleFrame, { mode: context.mode, options, children: context.renderDefault() });
360
+ }
361
+ };
362
+ return {
363
+ id: RESIZABLE_CONSOLE_ADDON_ID,
364
+ activate(host) {
365
+ host.extensions.register(
366
+ consoleCore.consoleExtensionPoints.frameDecorator,
367
+ decorator,
368
+ {
369
+ id: `${RESIZABLE_CONSOLE_ADDON_ID}:frame`
370
+ }
371
+ );
372
+ }
373
+ };
374
+ }
375
+ exports.RESIZABLE_CONSOLE_ADDON_ID = RESIZABLE_CONSOLE_ADDON_ID;
376
+ exports.createResizableConsoleAddon = createResizableConsoleAddon;
377
+ exports.resolveConsoleResizeAxes = resolveConsoleResizeAxes;
@@ -0,0 +1,13 @@
1
+ /** Stable package-qualified identity for the resizable frame addon. */
2
+ export declare const RESIZABLE_CONSOLE_ADDON_ID = "@moyarich/console-addon-resizable";
3
+ export { resolveConsoleResizeAxes } from "./components/ResizableConsoleFrame/ResizableConsoleFrame.cjs";
4
+ export type { ConsoleResizeDirection, ConsoleResizeEdge, ConsoleResizeSize, ResizableConsoleAddonOptions, } from "./components/ResizableConsoleFrame/ResizableConsoleFrame.cjs";
5
+ import type { ResizableConsoleAddonOptions } from "./components/ResizableConsoleFrame/ResizableConsoleFrame.cjs";
6
+ import { type ConsoleAddon } from "@moyarich/console-core";
7
+ /**
8
+ * Creates a first-party frame-resizing addon.
9
+ *
10
+ * The addon contributes a generic frame decorator and leaves message/output
11
+ * rendering, viewport state, and host layout ownership unchanged.
12
+ */
13
+ export declare function createResizableConsoleAddon(options?: ResizableConsoleAddonOptions): ConsoleAddon;
@@ -0,0 +1,13 @@
1
+ /** Stable package-qualified identity for the resizable frame addon. */
2
+ export declare const RESIZABLE_CONSOLE_ADDON_ID = "@moyarich/console-addon-resizable";
3
+ export { resolveConsoleResizeAxes } from "./components/ResizableConsoleFrame/ResizableConsoleFrame.js";
4
+ export type { ConsoleResizeDirection, ConsoleResizeEdge, ConsoleResizeSize, ResizableConsoleAddonOptions, } from "./components/ResizableConsoleFrame/ResizableConsoleFrame.js";
5
+ import type { ResizableConsoleAddonOptions } from "./components/ResizableConsoleFrame/ResizableConsoleFrame.js";
6
+ import { type ConsoleAddon } from "@moyarich/console-core";
7
+ /**
8
+ * Creates a first-party frame-resizing addon.
9
+ *
10
+ * The addon contributes a generic frame decorator and leaves message/output
11
+ * rendering, viewport state, and host layout ownership unchanged.
12
+ */
13
+ export declare function createResizableConsoleAddon(options?: ResizableConsoleAddonOptions): ConsoleAddon;