@blcklab/freedom 0.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/README.md ADDED
@@ -0,0 +1,240 @@
1
+ # freeDOM
2
+
3
+ A lightweight, framework-agnostic TypeScript library for draggable and resizable DOM windows.
4
+
5
+ - Draggable windows
6
+ - Optional resizing from edges and corners
7
+ - Safe first-render positioning, including centered windows
8
+ - Position-agnostic initialization: CSS `top/right`, `bottom/left`, `absolute`, `fixed`, `relative`, and normal-flow elements can be used as the starting point
9
+ - Zero runtime dependencies
10
+ - Pointer Events support: mouse, touch, and pen
11
+ - Works with any framework or vanilla JavaScript
12
+ - SSR-safe imports: DOM access only happens when you create a window
13
+ - Tree-shaking friendly subpath exports
14
+
15
+ ## Installation
16
+
17
+ ```bash
18
+ npm install @blcklab/freedom
19
+ ```
20
+
21
+ ## Quick start
22
+
23
+ ```ts
24
+ import { freedom } from '@blcklab/freedom'
25
+
26
+ const element = document.getElementById('window')!
27
+
28
+ const win = freedom.window(element, {
29
+ resizable: false
30
+ })
31
+ ```
32
+
33
+ ## Center without first-render flicker
34
+
35
+ Use `initialPosition: 'center'` to place the window in the center synchronously during initialization.
36
+
37
+ ```ts
38
+ import { freedom } from '@blcklab/freedom'
39
+
40
+ const win = freedom.window(element, {
41
+ initialPosition: 'center',
42
+ initialSize: {
43
+ width: 500,
44
+ height: 320
45
+ },
46
+ resizable: false
47
+ })
48
+ ```
49
+
50
+ For the strongest zero-flicker setup, hide the element before JavaScript runs:
51
+
52
+ ```css
53
+ .my-window {
54
+ position: fixed;
55
+ visibility: hidden;
56
+ }
57
+ ```
58
+
59
+ Then initialize it:
60
+
61
+ ```ts
62
+ freedom.window(element, {
63
+ initialPosition: 'center',
64
+ initialSize: { width: 500, height: 320 }
65
+ })
66
+ ```
67
+
68
+ By default, freeDOM will reveal an element that starts with `visibility: hidden` after it has synchronously written the initial size and position. Disable that behavior with `autoReveal: false`.
69
+
70
+ ```ts
71
+ freedom.window(element, {
72
+ initialPosition: 'center',
73
+ autoReveal: false
74
+ })
75
+ ```
76
+
77
+ ## Custom initial position and size
78
+
79
+ ```ts
80
+ freedom.window(element, {
81
+ initialPosition: { x: 100, y: 100 },
82
+ initialSize: { width: 500, height: 320 }
83
+ })
84
+ ```
85
+
86
+ ## Drag only
87
+
88
+ ```ts
89
+ const win = freedom.window(element, {
90
+ resizable: false
91
+ })
92
+ ```
93
+
94
+ ## Drag and resize
95
+
96
+ ```ts
97
+ const win = freedom.window(element, {
98
+ draggable: true,
99
+ resizable: true,
100
+ minWidth: 200,
101
+ minHeight: 150,
102
+ maxWidth: 800,
103
+ maxHeight: 600
104
+ })
105
+ ```
106
+
107
+ ## Drag handle
108
+
109
+ Restrict dragging to a title bar or any child element.
110
+
111
+ ```ts
112
+ freedom.window(element, {
113
+ dragHandle: '.window-titlebar',
114
+ resizable: true
115
+ })
116
+ ```
117
+
118
+ ## Position-agnostic initialization
119
+
120
+ freeDOM does not require your CSS to use `top` and `left`. It can start from CSS such as `top/right`, `bottom/left`, an existing `fixed` or `absolute` panel, or even a normal-flow element. During initialization it reads the current rendered location, normalizes the managed window, and then uses transform deltas for smooth movement.
121
+
122
+ This works:
123
+
124
+ ```css
125
+ .my-window {
126
+ position: fixed;
127
+ top: 20px;
128
+ right: 20px;
129
+ }
130
+ ```
131
+
132
+ ```ts
133
+ const win = freedom.window(element, {
134
+ dragHandle: '.header',
135
+ resizable: true
136
+ })
137
+
138
+ console.log(win.getPosition()) // the real visual x/y after CSS is resolved
139
+ ```
140
+
141
+ Normal-flow elements are preserved by switching them to `position: relative` and moving with transform deltas, so the library does not need to force everything to `top: 0; left: 0`.
142
+
143
+ You can still force a mode when needed:
144
+
145
+ ```ts
146
+ freedom.window(element, {
147
+ positioning: 'fixed', // 'fixed' | 'absolute' | 'relative'
148
+ initialPosition: 'center'
149
+ })
150
+ ```
151
+
152
+ Available modes are `fixed`, `absolute`, and `relative`.
153
+
154
+ ## Public imports
155
+
156
+ Root import for the main window API:
157
+
158
+ ```ts
159
+ import { freedom, createWindow } from '@blcklab/freedom'
160
+ ```
161
+
162
+ Tree-shaking friendly subpath import:
163
+
164
+ ```ts
165
+ import { createWindow } from '@blcklab/freedom/window'
166
+ ```
167
+
168
+ Optional manager:
169
+
170
+ ```ts
171
+ import { createManager } from '@blcklab/freedom/manager'
172
+ ```
173
+
174
+ Optional snap plugin:
175
+
176
+ ```ts
177
+ import { snapPlugin } from '@blcklab/freedom/plugins/snap'
178
+ ```
179
+
180
+ ## API
181
+
182
+ ```ts
183
+ const win = freedom.window(element)
184
+
185
+ win.setPosition({ x: 100, y: 100 })
186
+ win.setSize({ width: 400, height: 300 })
187
+
188
+ win.getPosition()
189
+ win.getSize()
190
+
191
+ win.enableDrag()
192
+ win.disableDrag()
193
+
194
+ win.enableResize()
195
+ win.disableResize()
196
+
197
+ win.destroy()
198
+ ```
199
+
200
+ ## Options
201
+
202
+ ```ts
203
+ freedom.window(element, {
204
+ id: 'settings-panel',
205
+
206
+ draggable: true,
207
+ resizable: true,
208
+
209
+ initialPosition: 'center',
210
+ initialSize: { width: 500, height: 320 },
211
+
212
+ positioning: 'fixed', // 'fixed' | 'absolute' | 'relative'
213
+ autoReveal: true,
214
+
215
+ minWidth: 200,
216
+ minHeight: 150,
217
+ maxWidth: 800,
218
+ maxHeight: 600,
219
+
220
+ dragHandle: '.titlebar',
221
+ bounds: 'viewport'
222
+ })
223
+ ```
224
+
225
+ ## Browser support
226
+
227
+ Modern browsers supporting the Pointer Events API.
228
+
229
+ ## Notes
230
+
231
+ - Importing the package is SSR-safe.
232
+ - Creating a window must happen in the browser.
233
+ - freeDOM does not inject global CSS.
234
+ - Runtime styles are applied only to the controlled element and generated resize handles.
235
+ - Existing CSS positioning can be used as the initial source of truth; after initialization, freeDOM owns the managed position.
236
+ - Resize handles win over dragging, so resizing does not accidentally start a drag.
237
+
238
+ ## License
239
+
240
+ MIT