svelte-flexiboards 0.1.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 (44) hide show
  1. package/LICENSE.md +21 -0
  2. package/dist/components/flexi-add.svelte +35 -0
  3. package/dist/components/flexi-add.svelte.d.ts +16 -0
  4. package/dist/components/flexi-board.svelte +30 -0
  5. package/dist/components/flexi-board.svelte.d.ts +11 -0
  6. package/dist/components/flexi-delete.svelte +22 -0
  7. package/dist/components/flexi-delete.svelte.d.ts +13 -0
  8. package/dist/components/flexi-grab.svelte +20 -0
  9. package/dist/components/flexi-grab.svelte.d.ts +12 -0
  10. package/dist/components/flexi-grid.svelte +19 -0
  11. package/dist/components/flexi-grid.svelte.d.ts +8 -0
  12. package/dist/components/flexi-layout-loader.svelte +10 -0
  13. package/dist/components/flexi-layout-loader.svelte.d.ts +18 -0
  14. package/dist/components/flexi-resize.svelte +20 -0
  15. package/dist/components/flexi-resize.svelte.d.ts +12 -0
  16. package/dist/components/flexi-target-loader.svelte +10 -0
  17. package/dist/components/flexi-target-loader.svelte.d.ts +18 -0
  18. package/dist/components/flexi-target.svelte +93 -0
  19. package/dist/components/flexi-target.svelte.d.ts +42 -0
  20. package/dist/components/flexi-widget.svelte +37 -0
  21. package/dist/components/flexi-widget.svelte.d.ts +9 -0
  22. package/dist/components/index.d.ts +1 -0
  23. package/dist/components/index.js +1 -0
  24. package/dist/components/rendered-flexi-widget.svelte +44 -0
  25. package/dist/components/rendered-flexi-widget.svelte.d.ts +7 -0
  26. package/dist/index.d.ts +16 -0
  27. package/dist/index.js +10 -0
  28. package/dist/system/grid.svelte.d.ts +146 -0
  29. package/dist/system/grid.svelte.js +815 -0
  30. package/dist/system/index.d.ts +1 -0
  31. package/dist/system/index.js +1 -0
  32. package/dist/system/manage.svelte.d.ts +25 -0
  33. package/dist/system/manage.svelte.js +54 -0
  34. package/dist/system/provider.svelte.d.ts +51 -0
  35. package/dist/system/provider.svelte.js +290 -0
  36. package/dist/system/target.svelte.d.ts +179 -0
  37. package/dist/system/target.svelte.js +397 -0
  38. package/dist/system/types.d.ts +91 -0
  39. package/dist/system/types.js +1 -0
  40. package/dist/system/utils.svelte.d.ts +21 -0
  41. package/dist/system/utils.svelte.js +156 -0
  42. package/dist/system/widget.svelte.d.ts +225 -0
  43. package/dist/system/widget.svelte.js +447 -0
  44. package/package.json +57 -0
@@ -0,0 +1,225 @@
1
+ import { type Component, type Snippet } from "svelte";
2
+ import { type InternalFlexiTargetController, type FlexiTargetController } from "./target.svelte.js";
3
+ import type { WidgetAction, SvelteClassValue, WidgetResizability } from "./types.js";
4
+ import type { FlexiAddController } from "./manage.svelte.js";
5
+ export type FlexiWidgetChildrenSnippetParameters = {
6
+ widget: FlexiWidgetController;
7
+ component?: Component;
8
+ componentProps?: Record<string, any>;
9
+ };
10
+ export type FlexiWidgetChildrenSnippet = Snippet<[FlexiWidgetChildrenSnippetParameters]>;
11
+ export type FlexiWidgetClassFunction = (widget: FlexiWidgetController) => SvelteClassValue;
12
+ export type FlexiWidgetClasses = SvelteClassValue | FlexiWidgetClassFunction;
13
+ export type FlexiWidgetDefaults = {
14
+ /**
15
+ * Whether the widget is draggable.
16
+ */
17
+ draggable?: boolean;
18
+ /**
19
+ * The resizability of the widget.
20
+ */
21
+ resizability?: WidgetResizability;
22
+ /**
23
+ * The width of the widget in units.
24
+ */
25
+ width?: number;
26
+ /**
27
+ * The height of the widget in units.
28
+ */
29
+ height?: number;
30
+ /**
31
+ * The snippet that is rendered by this widget.
32
+ */
33
+ snippet?: FlexiWidgetChildrenSnippet;
34
+ /**
35
+ * The component that is rendered by this widget.
36
+ */
37
+ component?: Component<any, any, any>;
38
+ /**
39
+ * The props applied to the component rendered, if it has one.
40
+ */
41
+ componentProps?: Record<string, any>;
42
+ /**
43
+ * The class names to apply to this widget.
44
+ */
45
+ className?: FlexiWidgetClasses;
46
+ };
47
+ export type FlexiWidgetConfiguration = FlexiWidgetDefaults & {
48
+ x?: number;
49
+ y?: number;
50
+ metadata?: Record<string, any>;
51
+ };
52
+ type FlexiWidgetUnderAdderConstructor = {
53
+ type: "adder";
54
+ adder: FlexiAddController;
55
+ widthPx: number;
56
+ heightPx: number;
57
+ };
58
+ type FlexiWidgetUnderTargetConstructor = {
59
+ type: "target";
60
+ target: InternalFlexiTargetController;
61
+ isShadow?: boolean;
62
+ };
63
+ type FlexiWidgetConstructor = (FlexiWidgetUnderAdderConstructor | FlexiWidgetUnderTargetConstructor) & {
64
+ config: FlexiWidgetConfiguration;
65
+ };
66
+ export declare class FlexiWidgetController implements FlexiWidgetController {
67
+ #private;
68
+ /**
69
+ * The target this widget is under, if any.
70
+ */
71
+ target?: FlexiTargetController;
72
+ /**
73
+ * The adder this widget is currently being created under, if any.
74
+ */
75
+ adder?: FlexiAddController;
76
+ /**
77
+ * The DOM element bound to this widget.
78
+ */
79
+ ref?: HTMLElement;
80
+ /**
81
+ * Whether this widget is a shadow dropzone widget.
82
+ */
83
+ isShadow: boolean;
84
+ /**
85
+ * Whether this widget is grabbed.
86
+ */
87
+ isGrabbed: boolean;
88
+ /**
89
+ * Whether this widget is being resized.
90
+ */
91
+ isResizing: boolean;
92
+ /**
93
+ * The styling to apply to the widget.
94
+ */
95
+ style: string;
96
+ constructor(ctor: FlexiWidgetConstructor);
97
+ /**
98
+ * Event handler for when the widget receives a pointerdown event.
99
+ * @param event The event object.
100
+ */
101
+ onpointerdown(event: PointerEvent): void;
102
+ /**
103
+ * Event handler for when one of the widget's grabbers receives a pointerdown event.
104
+ * @param event The event object.
105
+ */
106
+ ongrabberpointerdown(event: PointerEvent): void;
107
+ /**
108
+ * Event handler for when one of the widget's resizers receives a pointerdown event.
109
+ * @param event The event object.
110
+ */
111
+ onresizerpointerdown(event: PointerEvent): void;
112
+ /**
113
+ * Sets the bounds of the widget.
114
+ * @remarks This is not intended for use externally.
115
+ * @param x The x-coordinate of the widget.
116
+ * @param y The y-coordinate of the widget.
117
+ * @param width The width of the widget.
118
+ * @param height The height of the widget.
119
+ */
120
+ setBounds(x: number, y: number, width: number, height: number): void;
121
+ /**
122
+ * Registers a grabber to the widget and returns an object with an `onpointerdown` event handler.
123
+ * @returns An object with an `onpointerdown` event handler.
124
+ */
125
+ addGrabber(): {
126
+ onpointerdown: (event: PointerEvent) => void;
127
+ };
128
+ /**
129
+ * Unregisters a grabber from the widget.
130
+ */
131
+ removeGrabber(): void;
132
+ /**
133
+ * Registers a resizer to the widget and returns an object with an `onpointerdown` event handler.
134
+ * @returns An object with an `onpointerdown` event handler.
135
+ */
136
+ addResizer(): {
137
+ onpointerdown: (event: PointerEvent) => void;
138
+ };
139
+ /**
140
+ * Unregisters a resizer from the widget.
141
+ */
142
+ removeResizer(): void;
143
+ /**
144
+ * Deletes this widget from its target and board.
145
+ */
146
+ delete(): void;
147
+ /**
148
+ * When the widget is being grabbed, this contains information that includes its position, size and offset.
149
+ * When this is null, the widget is not being grabbed.
150
+ */
151
+ get currentAction(): WidgetAction | null;
152
+ set currentAction(value: WidgetAction | null);
153
+ /**
154
+ * Whether the widget is draggable.
155
+ */
156
+ get draggable(): boolean;
157
+ set draggable(value: boolean);
158
+ /**
159
+ * The resizability of the widget.
160
+ */
161
+ get resizability(): WidgetResizability;
162
+ set resizability(value: WidgetResizability);
163
+ /**
164
+ * Whether the widget is resizable.
165
+ */
166
+ get resizable(): boolean;
167
+ /**
168
+ * The width in units of the widget.
169
+ */
170
+ get width(): number;
171
+ /**
172
+ * The height in units of the widget.
173
+ */
174
+ get height(): number;
175
+ /**
176
+ * The component that is rendered by this widget.
177
+ */
178
+ get component(): Component | undefined;
179
+ set component(value: Component | undefined);
180
+ /**
181
+ * The props applied to the component rendered, if it has one.
182
+ */
183
+ get componentProps(): Record<string, any> | undefined;
184
+ set componentProps(value: Record<string, any> | undefined);
185
+ /**
186
+ * The snippet that is rendered by this widget.
187
+ */
188
+ get snippet(): FlexiWidgetChildrenSnippet | undefined;
189
+ set snippet(value: FlexiWidgetChildrenSnippet | undefined);
190
+ /**
191
+ * The class name that is applied to this widget.
192
+ */
193
+ get className(): FlexiWidgetClasses | undefined;
194
+ set className(value: FlexiWidgetClasses | undefined);
195
+ /**
196
+ * Gets the column (x-coordinate) of the widget. This value is readonly and is managed by the target.
197
+ */
198
+ get x(): number;
199
+ /**
200
+ * Gets the row (y-coordinate) of the widget. This value is readonly and is managed by the target.
201
+ */
202
+ get y(): number;
203
+ /**
204
+ * The metadata associated with this widget, if any.
205
+ */
206
+ get metadata(): Record<string, any> | undefined;
207
+ set metadata(value: Record<string, any> | undefined);
208
+ }
209
+ export declare function flexiwidget(config: FlexiWidgetConfiguration): {
210
+ widget: FlexiWidgetController;
211
+ };
212
+ export declare function renderedflexiwidget(widget: FlexiWidgetController): {
213
+ widget: FlexiWidgetController;
214
+ onpointerdown: (event: PointerEvent) => void;
215
+ };
216
+ export declare function flexigrab(): {
217
+ widget: FlexiWidgetController;
218
+ onpointerdown: (event: PointerEvent) => void;
219
+ };
220
+ export declare function flexiresize(): {
221
+ widget: FlexiWidgetController;
222
+ onpointerdown: (event: PointerEvent) => void;
223
+ };
224
+ export declare function getFlexiwidgetCtx(): FlexiWidgetController;
225
+ export {};
@@ -0,0 +1,447 @@
1
+ import { getContext, onDestroy, setContext } from "svelte";
2
+ import { getInternalFlexitargetCtx } from "./target.svelte.js";
3
+ export class FlexiWidgetController {
4
+ /**
5
+ * The target this widget is under, if any.
6
+ */
7
+ target = $state(undefined);
8
+ /**
9
+ * The adder this widget is currently being created under, if any.
10
+ */
11
+ adder = $state(undefined);
12
+ #providerWidgetDefaults = $derived(this.target?.providerWidgetDefaults);
13
+ #targetWidgetDefaults = $derived(this.target?.config.widgetDefaults);
14
+ #rawConfig = $state();
15
+ /**
16
+ * The DOM element bound to this widget.
17
+ */
18
+ ref = $state(undefined);
19
+ /**
20
+ * The reactive configuration of the widget. When these properties are changed, either due to a change in the widget's configuration,
21
+ * or a change in the target's, or the board's, they will be updated to reflect the new values.
22
+ */
23
+ #config = $derived({
24
+ component: this.#rawConfig.component ?? this.#targetWidgetDefaults?.component ?? this.#providerWidgetDefaults?.component,
25
+ componentProps: this.#rawConfig.componentProps ?? this.#targetWidgetDefaults?.componentProps ?? this.#providerWidgetDefaults?.componentProps,
26
+ snippet: this.#rawConfig.snippet ?? this.#targetWidgetDefaults?.snippet ?? this.#providerWidgetDefaults?.snippet,
27
+ resizability: this.#rawConfig.resizability ?? this.#targetWidgetDefaults?.resizability ?? this.#providerWidgetDefaults?.resizability ?? "none",
28
+ draggable: this.#rawConfig.draggable ?? this.#targetWidgetDefaults?.draggable ?? this.#providerWidgetDefaults?.draggable ?? true,
29
+ className: this.#rawConfig.className ?? this.#targetWidgetDefaults?.className ?? this.#providerWidgetDefaults?.className,
30
+ metadata: this.#rawConfig.metadata
31
+ });
32
+ /**
33
+ * Stores the underlying state of the widget. This differs to the derived config above, because it contains configuration items that
34
+ * are only written to once when the widget is created. Properties stored in here do not react to changes in the config.
35
+ */
36
+ #state = $state({
37
+ currentAction: null,
38
+ width: 1,
39
+ height: 1,
40
+ x: 0,
41
+ y: 0
42
+ });
43
+ /**
44
+ * Whether this widget is a shadow dropzone widget.
45
+ */
46
+ isShadow = $state(false);
47
+ /**
48
+ * Whether this widget is grabbed.
49
+ */
50
+ isGrabbed = $derived(this.currentAction?.action == "grab");
51
+ /**
52
+ * Whether this widget is being resized.
53
+ */
54
+ isResizing = $derived(this.currentAction?.action == "resize");
55
+ #grabbers = $state(0);
56
+ #resizers = $state(0);
57
+ /**
58
+ * The styling to apply to the widget.
59
+ */
60
+ style = $derived.by(() => {
61
+ const currentAction = this.currentAction;
62
+ if (!currentAction) {
63
+ return `grid-column: ${this.x + 1} / span ${this.width}; grid-row: ${this.y + 1} / span ${this.height};` +
64
+ this.#getCursorStyle();
65
+ }
66
+ // Grab action
67
+ if (currentAction.action == "grab") {
68
+ return this.#getGrabbedWidgetStyle(currentAction);
69
+ }
70
+ // Resize action
71
+ return this.#getResizingWidgetStyle(currentAction);
72
+ });
73
+ #getCursorStyle() {
74
+ if (!this.draggable) {
75
+ return '';
76
+ }
77
+ if (this.isGrabbed) {
78
+ return 'pointer-events: none; user-select: none; cursor: grabbing;';
79
+ }
80
+ if (this.isResizing) {
81
+ return 'pointer-events: none; user-select: none; cursor: nwse-resize;';
82
+ }
83
+ if (this.#grabbers == 0) {
84
+ return 'user-select: none; cursor: grab; touch-action: none;';
85
+ }
86
+ return '';
87
+ }
88
+ #getGrabbedWidgetStyle(action) {
89
+ const locationOffsetX = action.positionWatcher.position.x - action.offsetX;
90
+ const locationOffsetY = action.positionWatcher.position.y - action.offsetY;
91
+ // Fixed when it's a grabbed widget.
92
+ const height = action.capturedHeightPx;
93
+ const width = action.capturedWidthPx;
94
+ return `pointer-events: none; user-select: none; cursor: grabbing; position: absolute; top: ${locationOffsetY}px; left: ${locationOffsetX}px; height: ${height}px; width: ${width}px;`;
95
+ }
96
+ #getResizingWidgetStyle(action) {
97
+ const unitSizeY = action.heightPx / action.initialHeightUnits;
98
+ const unitSizeX = action.widthPx / action.initialWidthUnits;
99
+ const top = action.top;
100
+ const left = action.left;
101
+ // Calculate new dimensions based on resizability
102
+ let height = action.heightPx;
103
+ let width = action.widthPx;
104
+ switch (this.resizability) {
105
+ case 'horizontal':
106
+ width = Math.max(action.widthPx + (action.positionWatcher.position.x - action.offsetX), unitSizeX);
107
+ break;
108
+ case 'vertical':
109
+ height = Math.max(action.heightPx + (action.positionWatcher.position.y - action.offsetY), unitSizeY);
110
+ break;
111
+ case 'both':
112
+ height = Math.max(action.heightPx + (action.positionWatcher.position.y - action.offsetY), unitSizeY);
113
+ width = Math.max(action.widthPx + (action.positionWatcher.position.x - action.offsetX), unitSizeX);
114
+ break;
115
+ }
116
+ return `pointer-events: none; user-select: none; cursor: nwse-resize; position: absolute; top: ${top}px; left: ${left}px; height: ${height}px; width: ${width}px;`;
117
+ }
118
+ // Constructor for widget creation directly under a FlexiTarget
119
+ constructor(ctor) {
120
+ this.#rawConfig = ctor.config;
121
+ // Populate the state proxy with the configuration values.
122
+ this.#state.width = ctor.config.width ?? 1;
123
+ this.#state.height = ctor.config.height ?? 1;
124
+ if (ctor.type == "target") {
125
+ this.target = ctor.target;
126
+ this.isShadow = ctor.isShadow ?? false;
127
+ }
128
+ else if (ctor.type == "adder") {
129
+ this.adder = ctor.adder;
130
+ // Start the widget drag in event
131
+ this.currentAction = this.adder.onstartwidgetdragin({
132
+ widget: this,
133
+ xOffset: 0,
134
+ yOffset: 0,
135
+ // Pass through the base size of the widget.
136
+ capturedHeight: ctor.heightPx,
137
+ capturedWidth: ctor.widthPx
138
+ });
139
+ }
140
+ // Allows the event handlers to be called without binding to the widget instance.
141
+ this.onpointerdown = this.onpointerdown.bind(this);
142
+ this.ongrabberpointerdown = this.ongrabberpointerdown.bind(this);
143
+ this.onresizerpointerdown = this.onresizerpointerdown.bind(this);
144
+ }
145
+ /**
146
+ * Event handler for when the widget receives a pointerdown event.
147
+ * @param event The event object.
148
+ */
149
+ onpointerdown(event) {
150
+ if (!this.draggable || !event.target || this.#grabbers) {
151
+ return;
152
+ }
153
+ ;
154
+ this.#grabWidget(event.clientX, event.clientY);
155
+ // Don't implicitly keep the pointer capture, as then mobile can't move the widget in and out of targets.
156
+ event.target.releasePointerCapture(event.pointerId);
157
+ event.preventDefault();
158
+ }
159
+ /**
160
+ * Event handler for when one of the widget's grabbers receives a pointerdown event.
161
+ * @param event The event object.
162
+ */
163
+ ongrabberpointerdown(event) {
164
+ if (!this.draggable || !event.target) {
165
+ return;
166
+ }
167
+ ;
168
+ this.#grabWidget(event.clientX, event.clientY);
169
+ // Don't implicitly keep the pointer capture, as then mobile can't move the widget in and out of targets.
170
+ event.target.releasePointerCapture(event.pointerId);
171
+ event.preventDefault();
172
+ }
173
+ /**
174
+ * Event handler for when one of the widget's resizers receives a pointerdown event.
175
+ * @param event The event object.
176
+ */
177
+ onresizerpointerdown(event) {
178
+ if (this.resizability == "none" || !event.target) {
179
+ return;
180
+ }
181
+ ;
182
+ this.#startResizeWidget(event.clientX, event.clientY);
183
+ // Don't implicitly keep the pointer capture, as then mobile can't properly maintain correct focuses.
184
+ event.target.releasePointerCapture(event.pointerId);
185
+ event.preventDefault();
186
+ }
187
+ #grabWidget(clientX, clientY) {
188
+ if (!this.ref) {
189
+ throw new Error("A FlexiWidget was instantiated without a bound reference element.");
190
+ }
191
+ // If the widget is new, then this event shouldn't fire yet.
192
+ if (!this.target) {
193
+ return;
194
+ }
195
+ const rect = this.ref.getBoundingClientRect();
196
+ // Get the offset of the cursor relative to the widget's bounds.
197
+ const xOffset = clientX - rect.left;
198
+ const yOffset = clientY - rect.top;
199
+ // Propagate an event up to the parent target, indicating that the widget has been grabbed.
200
+ this.currentAction = this.target.grabWidget({
201
+ widget: this,
202
+ xOffset,
203
+ yOffset,
204
+ // Capture the current size of the widget so that we can fix this once it's moving.
205
+ capturedHeight: rect.height,
206
+ capturedWidth: rect.width
207
+ });
208
+ }
209
+ #startResizeWidget(clientX, clientY) {
210
+ if (!this.ref) {
211
+ throw new Error("A FlexiWidget was instantiated without a bound reference element.");
212
+ }
213
+ // If the widget is new, then this event shouldn't fire yet.
214
+ if (!this.target) {
215
+ return;
216
+ }
217
+ const rect = this.ref.getBoundingClientRect();
218
+ // Propagate an event up to the parent target, indicating that the widget has started resizing.
219
+ this.currentAction = this.target.startResizeWidget({
220
+ widget: this,
221
+ xOffset: clientX,
222
+ yOffset: clientY,
223
+ left: rect.left,
224
+ top: rect.top,
225
+ heightPx: rect.height,
226
+ widthPx: rect.width
227
+ });
228
+ }
229
+ /**
230
+ * Sets the bounds of the widget.
231
+ * @remarks This is not intended for use externally.
232
+ * @param x The x-coordinate of the widget.
233
+ * @param y The y-coordinate of the widget.
234
+ * @param width The width of the widget.
235
+ * @param height The height of the widget.
236
+ */
237
+ setBounds(x, y, width, height) {
238
+ this.#state.x = x;
239
+ this.#state.y = y;
240
+ this.#state.width = width;
241
+ this.#state.height = height;
242
+ }
243
+ /**
244
+ * Registers a grabber to the widget and returns an object with an `onpointerdown` event handler.
245
+ * @returns An object with an `onpointerdown` event handler.
246
+ */
247
+ addGrabber() {
248
+ this.#grabbers++;
249
+ return {
250
+ onpointerdown: this.ongrabberpointerdown
251
+ };
252
+ }
253
+ /**
254
+ * Unregisters a grabber from the widget.
255
+ */
256
+ removeGrabber() {
257
+ this.#grabbers--;
258
+ }
259
+ /**
260
+ * Registers a resizer to the widget and returns an object with an `onpointerdown` event handler.
261
+ * @returns An object with an `onpointerdown` event handler.
262
+ */
263
+ addResizer() {
264
+ this.#resizers++;
265
+ return {
266
+ onpointerdown: this.onresizerpointerdown
267
+ };
268
+ }
269
+ /**
270
+ * Unregisters a resizer from the widget.
271
+ */
272
+ removeResizer() {
273
+ this.#resizers--;
274
+ }
275
+ /**
276
+ * Deletes this widget from its target and board.
277
+ */
278
+ delete() {
279
+ // If the widget hasn't been assigned to a target yet, then we just need to take it off the adder that
280
+ // created it.
281
+ if (this.adder) {
282
+ this.adder.onstopwidgetdragin();
283
+ return;
284
+ }
285
+ // Otherwise it should have a target.
286
+ if (!this.target) {
287
+ throw new Error("A FlexiWidget was deleted without a bound target. This is likely a Flexiboards bug.");
288
+ }
289
+ this.target.deleteWidget(this);
290
+ this.currentAction = null;
291
+ }
292
+ // Getters and setters
293
+ /**
294
+ * When the widget is being grabbed, this contains information that includes its position, size and offset.
295
+ * When this is null, the widget is not being grabbed.
296
+ */
297
+ get currentAction() {
298
+ return this.#state.currentAction;
299
+ }
300
+ set currentAction(value) {
301
+ this.#state.currentAction = value;
302
+ }
303
+ /**
304
+ * Whether the widget is draggable.
305
+ */
306
+ get draggable() {
307
+ return this.#config.draggable;
308
+ }
309
+ set draggable(value) {
310
+ this.#rawConfig.draggable = value;
311
+ }
312
+ /**
313
+ * The resizability of the widget.
314
+ */
315
+ get resizability() {
316
+ return this.#config.resizability;
317
+ }
318
+ set resizability(value) {
319
+ this.#rawConfig.resizability = value;
320
+ }
321
+ /**
322
+ * Whether the widget is resizable.
323
+ */
324
+ get resizable() {
325
+ return this.resizability !== 'none';
326
+ }
327
+ /**
328
+ * The width in units of the widget.
329
+ */
330
+ get width() {
331
+ return this.#state.width;
332
+ }
333
+ /**
334
+ * The height in units of the widget.
335
+ */
336
+ get height() {
337
+ return this.#state.height;
338
+ }
339
+ /**
340
+ * The component that is rendered by this widget.
341
+ */
342
+ get component() {
343
+ return this.#config.component;
344
+ }
345
+ set component(value) {
346
+ this.#rawConfig.component = value;
347
+ }
348
+ /**
349
+ * The props applied to the component rendered, if it has one.
350
+ */
351
+ get componentProps() {
352
+ return this.#config.componentProps;
353
+ }
354
+ set componentProps(value) {
355
+ this.#rawConfig.componentProps = value;
356
+ }
357
+ /**
358
+ * The snippet that is rendered by this widget.
359
+ */
360
+ get snippet() {
361
+ return this.#config.snippet;
362
+ }
363
+ set snippet(value) {
364
+ this.#rawConfig.snippet = value;
365
+ }
366
+ /**
367
+ * The class name that is applied to this widget.
368
+ */
369
+ get className() {
370
+ return this.#config.className;
371
+ }
372
+ set className(value) {
373
+ this.#rawConfig.className = value;
374
+ }
375
+ /**
376
+ * Gets the column (x-coordinate) of the widget. This value is readonly and is managed by the target.
377
+ */
378
+ get x() {
379
+ return this.#state.x;
380
+ }
381
+ /**
382
+ * Gets the row (y-coordinate) of the widget. This value is readonly and is managed by the target.
383
+ */
384
+ get y() {
385
+ return this.#state.y;
386
+ }
387
+ /**
388
+ * The metadata associated with this widget, if any.
389
+ */
390
+ get metadata() {
391
+ return this.#config.metadata;
392
+ }
393
+ set metadata(value) {
394
+ this.#rawConfig.metadata = value;
395
+ }
396
+ }
397
+ const contextKey = Symbol('flexiwidget');
398
+ export function flexiwidget(config) {
399
+ const target = getInternalFlexitargetCtx();
400
+ if (!target) {
401
+ throw new Error("A FlexiWidget was instantiated outside of a FlexiTarget context. Ensure that flexiwidget() (or <FlexiWidget>) is called within a <FlexiTarget> component.");
402
+ }
403
+ const widget = target.createWidget(config);
404
+ if (!widget) {
405
+ throw new Error("Failed to create widget. Check that the widget's x and y coordinates do not lead to an unresolvable collision.");
406
+ }
407
+ setContext(contextKey, widget);
408
+ return {
409
+ widget
410
+ };
411
+ }
412
+ export function renderedflexiwidget(widget) {
413
+ setContext(contextKey, widget);
414
+ return {
415
+ widget,
416
+ onpointerdown: (event) => widget.onpointerdown(event)
417
+ };
418
+ }
419
+ export function flexigrab() {
420
+ const widget = getFlexiwidgetCtx();
421
+ if (!widget) {
422
+ throw new Error("A FlexiGrab was instantiated outside of a FlexiWidget context. Ensure that flexigrab() (or <FlexiGrab>) is called within a <FlexiWidget> component.");
423
+ }
424
+ const { onpointerdown } = widget.addGrabber();
425
+ onDestroy(() => {
426
+ widget.removeGrabber();
427
+ });
428
+ return { widget, onpointerdown };
429
+ }
430
+ export function flexiresize() {
431
+ const widget = getFlexiwidgetCtx();
432
+ if (!widget) {
433
+ throw new Error("A FlexiResize was instantiated outside of a FlexiWidget context. Ensure that flexiresize() (or <FlexiResize>) is called within a <FlexiWidget> component.");
434
+ }
435
+ const { onpointerdown } = widget.addResizer();
436
+ onDestroy(() => {
437
+ widget.removeResizer();
438
+ });
439
+ return { widget, onpointerdown };
440
+ }
441
+ export function getFlexiwidgetCtx() {
442
+ const widget = getContext(contextKey);
443
+ if (!widget) {
444
+ throw new Error("Attempt to get FlexiWidget context outside of a <FlexiWidget> component. Ensure that getFlexiwidgetCtx() is called within a <FlexiWidget> component.");
445
+ }
446
+ return widget;
447
+ }