@featherk/composables 0.13.8 → 0.14.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +1 -1
- package/dist/docs-manifest.js +24 -24
- package/dist/featherk-composables.es.js +1374 -1296
- package/dist/featherk-composables.es.js.map +1 -1
- package/dist/featherk-composables.umd.js +1 -1
- package/dist/featherk-composables.umd.js.map +1 -1
- package/dist/window/useWindow.d.ts +6 -0
- package/docs/window/useWindow.md +52 -5
- package/package.json +1 -1
|
@@ -29,6 +29,10 @@ export interface WindowSettings {
|
|
|
29
29
|
height?: number;
|
|
30
30
|
left?: number;
|
|
31
31
|
top?: number;
|
|
32
|
+
/** Minimum resize width in px. Unset/`null` falls back to Kendo's default (120). */
|
|
33
|
+
minWidth?: number | null;
|
|
34
|
+
/** Minimum resize height in px. Unset/`null` falls back to Kendo's default (100). */
|
|
35
|
+
minHeight?: number | null;
|
|
32
36
|
}
|
|
33
37
|
export declare const WINDOW_SETTINGS_DEFAULTS: WindowSettings;
|
|
34
38
|
export interface UseWindowOptions {
|
|
@@ -63,6 +67,8 @@ export interface WindowBindableProps {
|
|
|
63
67
|
initialHeight: number;
|
|
64
68
|
width?: number;
|
|
65
69
|
height?: number;
|
|
70
|
+
minWidth: number;
|
|
71
|
+
minHeight: number;
|
|
66
72
|
stage: WindowStage;
|
|
67
73
|
windowClass: string;
|
|
68
74
|
}
|
package/docs/window/useWindow.md
CHANGED
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
|
|
5
5
|
> Wraps Kendo UI for Vue's `Window` component - not the browser `window` object. If you were expecting something like VueUse's `useWindowSize`/`useWindowScroll`, this is unrelated to those.
|
|
6
6
|
|
|
7
|
-
Composable for a zero/low-config Kendo `Window`: viewport-clamped dragging
|
|
7
|
+
Composable for a zero/low-config Kendo `Window`: viewport-clamped dragging and resizing, stage transitions, and the pointerdown-capture resize/text-selection workaround are all handled internally. Every setting has a sensible default, so `useWindow()` with no arguments is a complete, working Window.
|
|
8
8
|
|
|
9
9
|
## Quick Start
|
|
10
10
|
|
|
@@ -67,6 +67,23 @@ A partially-populated ref is fine - any field `myLoadedSettings` doesn't have fa
|
|
|
67
67
|
|
|
68
68
|
Set `settings.initialLeft` and/or `settings.initialTop` to override the default 16px right/top inset on the first open and whenever `resetPosition` is true. Each coordinate can be overridden independently; an omitted coordinate keeps its computed inset default.
|
|
69
69
|
|
|
70
|
+
## Resizing Bounds
|
|
71
|
+
|
|
72
|
+
Resizing is clamped to the viewport (the scrolled document viewport when `settings.fixed` is `false`):
|
|
73
|
+
|
|
74
|
+
- The dragged edge stops at the viewport edge; the opposite edge stays anchored, so dragging the top or left edge past the viewport never grows the Window down or right.
|
|
75
|
+
- An edge that is already outside the viewport (for example, a bottom edge dragged below the fold) is never snapped back - it just cannot be pushed further out.
|
|
76
|
+
- The Window cannot shrink below `settings.minWidth`/`settings.minHeight`. Both are optional; unset or `null` falls back to Kendo's defaults (120px/100px).
|
|
77
|
+
- Keyboard resizing (Ctrl+Arrow) follows the same viewport and minimum-size limits.
|
|
78
|
+
|
|
79
|
+
`settings.left`/`top`/`width`/`height` and the `onResize` payload always hold these clamped values, not Kendo's raw resize geometry.
|
|
80
|
+
|
|
81
|
+
```ts
|
|
82
|
+
const win = useWindow({
|
|
83
|
+
settings: { minWidth: 320, minHeight: 200 },
|
|
84
|
+
});
|
|
85
|
+
```
|
|
86
|
+
|
|
70
87
|
## Extending Window Behavior
|
|
71
88
|
|
|
72
89
|
Use the `UseWindowOptions` callbacks when application code needs to react to Window behavior. These callbacks are extension hooks: they run after `useWindow` completes its internal handling, and they do not replace Kendo's event handlers.
|
|
@@ -74,7 +91,7 @@ Use the `UseWindowOptions` callbacks when application code needs to react to Win
|
|
|
74
91
|
This applies to every callback option:
|
|
75
92
|
|
|
76
93
|
- `onMove` runs after viewport clamping and position updates.
|
|
77
|
-
- `onResize` runs after size/position updates and resize-state tracking.
|
|
94
|
+
- `onResize` runs after viewport clamping, size/position updates, and resize-state tracking.
|
|
78
95
|
- `onStageChange` runs after a valid controlled stage transition.
|
|
79
96
|
- `onOpen` runs after `open()` has shown and sized the Window.
|
|
80
97
|
- `onClose` runs after `close()` has reset the stage and hidden the Window.
|
|
@@ -99,7 +116,7 @@ the titlebar toggles between `DEFAULT` and `FULLSCREEN`. Set `titlebarDoubleClic
|
|
|
99
116
|
disable both transitions. This option is independent of `settings.maximizeButton`; disabling the
|
|
100
117
|
maximize button does not automatically disable titlebar double-click behavior.
|
|
101
118
|
|
|
102
|
-
Keep binding `v-on="events"` on `<Window>` so viewport clamping
|
|
119
|
+
Keep binding `v-on="events"` on `<Window>` so viewport clamping (drag and resize), stage handling, and Kendo workarounds remain active:
|
|
103
120
|
|
|
104
121
|
```vue
|
|
105
122
|
<Window
|
|
@@ -122,7 +139,7 @@ Do not replace entries on `events` unless you intentionally opt out of the corre
|
|
|
122
139
|
| `initialStage` | `WindowStage` | Initial `stage` value. Defaults to `"DEFAULT"`. |
|
|
123
140
|
| `titlebarDoubleClick` | `MaybeRefOrGetter<boolean>` | Enables titlebar double-click stage changes. Defaults to `true`; pass `false` or a reactive ref/getter returning `false` to disable both maximize and restore transitions. |
|
|
124
141
|
| `onMove` | `(payload) => void` | Called after internal move handling. |
|
|
125
|
-
| `onResize` | `(payload) => void` | Called after internal resize handling
|
|
142
|
+
| `onResize` | `(payload) => void` | Called after internal resize handling, with the viewport-clamped `left`/`top`/`width`/`height`. |
|
|
126
143
|
| `onStageChange` | `(stage) => void` | Called after a valid stage transition. |
|
|
127
144
|
| `onOpen` | `() => void` | Called after `open()` finishes sizing the Window. |
|
|
128
145
|
| `onClose` | `() => void` | Called after `close()` hides the Window. |
|
|
@@ -143,7 +160,7 @@ Do not replace entries on `events` unless you intentionally opt out of the corre
|
|
|
143
160
|
|
|
144
161
|
## Inert Props
|
|
145
162
|
|
|
146
|
-
`props` only contains Kendo `Window` props that actually work: `title`, `draggable`, `resizable`, `left`, `top`, `initialLeft`, `initialTop`, `initialWidth`, `initialHeight`, `width`, `height`, `stage`, and `windowClass`. `settings.closable`, `settings.minimizeButton`, and `settings.maximizeButton` are deliberately **not** included in `props`.
|
|
163
|
+
`props` only contains Kendo `Window` props that actually work: `title`, `draggable`, `resizable`, `left`, `top`, `initialLeft`, `initialTop`, `initialWidth`, `initialHeight`, `width`, `height`, `minWidth`, `minHeight`, `stage`, and `windowClass`. `settings.closable`, `settings.minimizeButton`, and `settings.maximizeButton` are deliberately **not** included in `props`.
|
|
147
164
|
|
|
148
165
|
If you hand-wire raw Kendo props like `closeButton`/`minimizeButton`/`maximizeButton` directly on `<Window>` alongside `v-bind="props"`, they are **inert** - they will not hide the corresponding titlebar button. `useWindow` only ever suppresses those buttons via CSS (`fk-window-hide-minimize`/`fk-window-hide-maximize`/`fk-window-hide-close` classes folded into `windowClass`), never through Kendo's own button props. Toggle `settings.minimizeButton`/`settings.maximizeButton`/`settings.closable` instead.
|
|
149
166
|
|
|
@@ -151,6 +168,36 @@ If you hand-wire raw Kendo props like `closeButton`/`minimizeButton`/`maximizeBu
|
|
|
151
168
|
|
|
152
169
|
- **Titlebar button props are non-functional.** Kendo's `Window` types `minimizeButton`/`maximizeButton`/`closeButton`/`restoreButton` as `[String, Function]`, but the child `WindowTitlebar` that actually renders them types the same props `[String, Function, Object, Boolean]` and renders each button unconditionally regardless of value. There is no supported way to hide these buttons through Kendo's own props - see "Inert Props" above for the CSS-class workaround `useWindow` uses instead.
|
|
153
170
|
- **Resize-handle drag vs. text-selection race.** Kendo Window's resize handles use Kendo's own draggable implementation, which does not prevent the native browser default until after pointer movement begins. If text inside the Window is already selected, native selection-dragging can compete with a resize started from an inward-overlapping handle. `useWindow` prevents this internally with a capture-phase `pointerdown` listener scoped to `.k-resize-handle` elements - see [docs/design/composable-native-event-listener-tactic.md](https://github.com/NantHealth/featherk/blob/integration/docs/design/composable-native-event-listener-tactic.md) for the general pattern. This is fully internal; no `@pointerdown.capture` binding is needed (or exposed) in consumer templates.
|
|
171
|
+
- **Resize geometry is unbounded and self-compounding.** See "Kendo Window Resize Math Defect" below.
|
|
172
|
+
|
|
173
|
+
### Kendo Window Resize Math Defect
|
|
174
|
+
|
|
175
|
+
Observed in `@progress/kendo-vue-dialogs` 6.4.1 (`Window.mjs`, `handleResize`). Because of this, `useWindow` computes resize geometry itself rather than trusting the values Kendo emits on `resize`.
|
|
176
|
+
|
|
177
|
+
**Symptoms (without the workaround)**
|
|
178
|
+
|
|
179
|
+
- Dragging the right or bottom edge past the browser window keeps growing the Window indefinitely.
|
|
180
|
+
- After that, the left edge can be dragged offscreen too, leaving the whole Window offscreen and unrecoverable.
|
|
181
|
+
- Dragging the top edge up past the viewport makes the Window grow **down**; dragging the left edge past the viewport makes it grow **right**. Corner handles show both behaviors.
|
|
182
|
+
|
|
183
|
+
**Root cause**
|
|
184
|
+
|
|
185
|
+
- Kendo sets the dragged edge to the pointer's absolute `pageX`/`pageY` with no viewport bounds. Pointer capture keeps reporting coordinates beyond the browser window, so right/bottom edges follow indefinitely.
|
|
186
|
+
- For `n`/`w` handles Kendo sets `top = pageY` (negative past the viewport) and adds `computedTop - pageY` to the height. `computedTop` is `Math.max(top, 0)`, so the Window renders at `0` while the height grows again on every pointer move - growth leaks out the opposite edge. Same for `left`/width.
|
|
187
|
+
- The emitted `left`/`top`/`width`/`height` come from Kendo's internal state, not the controlled props: values for the axis not being resized can be stale (including unclamped values from a prior drag).
|
|
188
|
+
- Kendo mixes coordinate spaces: `pageX`/`pageY` are document coordinates, while a `position: fixed` Window's `top`/`left` are viewport coordinates, so resizing is off by the scroll offset on a scrolled page.
|
|
189
|
+
- Kendo reads `props.top || currentTop`, so a controlled `top`/`left` of `0` is treated as unset and falls back to internal state.
|
|
190
|
+
|
|
191
|
+
**Workaround in `useWindow`**
|
|
192
|
+
|
|
193
|
+
- The existing capture-phase `pointerdown` listener on `.k-resize-handle` also records the handle direction (from its `k-resize-<dir>` class), the starting rect, and the starting pointer position, then tracks the pointer with a capture-phase `window` `pointermove` listener.
|
|
194
|
+
- On each Kendo `resize` event, geometry is computed from the pointer delta and clamped per edge (viewport bounds, anchored opposite edge, `minWidth`/`minHeight`); Kendo's emitted geometry is ignored. Kendo's event still drives timing (`drag`/`end`).
|
|
195
|
+
- Keyboard resizing (Ctrl+Arrow) has no pointer, so it applies the change in Kendo's emitted size as a delta to the clamped size.
|
|
196
|
+
- See "Resizing Bounds" above for the resulting behavior.
|
|
197
|
+
|
|
198
|
+
**Removal criteria**
|
|
199
|
+
|
|
200
|
+
Revisit when upgrading `@progress/kendo-vue-dialogs`. The workaround can be dropped once Kendo's `handleResize` bounds edges to the viewport, anchors the opposite edge at the viewport, and emits geometry consistent with the controlled props. The `useWindow` resize tests (`useWindow.test.ts`) describe the expected behavior and can be used to verify.
|
|
154
201
|
|
|
155
202
|
## Styling
|
|
156
203
|
|