svelte-flexiboards 0.3.2 → 0.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 (46) hide show
  1. package/dist/components/flexi-add.svelte +0 -1
  2. package/dist/components/flexi-delete.svelte +3 -4
  3. package/dist/components/flexi-delete.svelte.d.ts +0 -12
  4. package/dist/components/flexi-grab.svelte +2 -2
  5. package/dist/components/flexi-target.svelte +8 -19
  6. package/dist/components/flexi-widget.svelte +2 -2
  7. package/dist/components/responsive-flexi-board.svelte +83 -0
  8. package/dist/components/responsive-flexi-board.svelte.d.ts +34 -0
  9. package/dist/index.d.ts +4 -1
  10. package/dist/index.js +4 -1
  11. package/dist/system/board/base.svelte.d.ts +15 -0
  12. package/dist/system/board/controller.svelte.d.ts +26 -4
  13. package/dist/system/board/controller.svelte.js +233 -28
  14. package/dist/system/board/types.d.ts +26 -0
  15. package/dist/system/grid/base.svelte.d.ts +9 -0
  16. package/dist/system/grid/base.svelte.js +12 -1
  17. package/dist/system/grid/flow-grid.svelte.js +105 -36
  18. package/dist/system/grid/free-grid.svelte.d.ts +6 -2
  19. package/dist/system/grid/free-grid.svelte.js +139 -20
  20. package/dist/system/misc/deleter.svelte.d.ts +0 -4
  21. package/dist/system/misc/deleter.svelte.js +1 -6
  22. package/dist/system/portal.js +0 -1
  23. package/dist/system/responsive/base.svelte.d.ts +46 -0
  24. package/dist/system/responsive/base.svelte.js +1 -0
  25. package/dist/system/responsive/controller.svelte.d.ts +78 -0
  26. package/dist/system/responsive/controller.svelte.js +264 -0
  27. package/dist/system/responsive/index.d.ts +16 -0
  28. package/dist/system/responsive/index.js +36 -0
  29. package/dist/system/responsive/types.d.ts +56 -0
  30. package/dist/system/responsive/types.js +1 -0
  31. package/dist/system/shared/event-bus.d.ts +3 -1
  32. package/dist/system/target/controller.svelte.d.ts +7 -2
  33. package/dist/system/target/controller.svelte.js +91 -21
  34. package/dist/system/types.d.ts +13 -2
  35. package/dist/system/widget/base.svelte.d.ts +40 -1
  36. package/dist/system/widget/base.svelte.js +84 -2
  37. package/dist/system/widget/controller.svelte.d.ts +4 -1
  38. package/dist/system/widget/controller.svelte.js +106 -17
  39. package/dist/system/widget/events.js +10 -3
  40. package/dist/system/widget/interpolation-utils.d.ts +14 -0
  41. package/dist/system/widget/interpolation-utils.js +32 -0
  42. package/dist/system/widget/interpolator.svelte.d.ts +2 -1
  43. package/dist/system/widget/interpolator.svelte.js +63 -22
  44. package/dist/system/widget/triggers.svelte.js +1 -1
  45. package/dist/system/widget/types.d.ts +51 -6
  46. package/package.json +1 -1
@@ -64,7 +64,6 @@
64
64
  });
65
65
  </script>
66
66
 
67
- <!-- TODO: will probably need a breaking change, because we need a ref to get the start widget position -->
68
67
  <button
69
68
  class={derivedClassName}
70
69
  bind:this={adder.ref}
@@ -22,7 +22,7 @@
22
22
 
23
23
  export type FlexiDeleteProps = FlexiCommonProps<FlexiDeleteController> & {
24
24
  class?: FlexiDeleteClasses;
25
- children?: Snippet<[{ deleter: FlexiDeleteController; props: FlexiDeleteChildrenProps }]>;
25
+ children?: Snippet<[{ deleter: FlexiDeleteController }]>;
26
26
  };
27
27
  </script>
28
28
 
@@ -34,8 +34,7 @@
34
34
  onfirstcreate
35
35
  }: FlexiDeleteProps = $props();
36
36
 
37
- // TODO: remove pointer events in v0.4
38
- const { deleter, onpointerenter, onpointerleave } = flexidelete();
37
+ const { deleter } = flexidelete();
39
38
  controller = deleter;
40
39
  onfirstcreate?.(deleter);
41
40
 
@@ -63,5 +62,5 @@
63
62
  <span style={assistiveTextStyle} id={assistiveTextId}>
64
63
  Drag a widget here and press Enter to delete it.
65
64
  </span>
66
- {@render children?.({ deleter, props: { onpointerenter, onpointerleave } })}
65
+ {@render children?.({ deleter })}
67
66
  </div>
@@ -1,22 +1,10 @@
1
1
  import type { Snippet } from 'svelte';
2
2
  import type { FlexiCommonProps } from '../system/types.js';
3
3
  import { FlexiDeleteController, type FlexiDeleteClasses } from '../system/misc/deleter.svelte.js';
4
- /** @deprecated FlexiDelete's children props are now redundant and will be removed in v0.4. */
5
- type FlexiDeleteChildrenProps = {
6
- /**
7
- * @deprecated This has been replaced with internal pointer management and is redundant. These events will be removed in v0.4.
8
- */
9
- onpointerenter: (event: PointerEvent) => void;
10
- /**
11
- * @deprecated This has been replaced with internal pointer management and is redundant. These events will be removed in v0.4.
12
- */
13
- onpointerleave: (event: PointerEvent) => void;
14
- };
15
4
  export type FlexiDeleteProps = FlexiCommonProps<FlexiDeleteController> & {
16
5
  class?: FlexiDeleteClasses;
17
6
  children?: Snippet<[{
18
7
  deleter: FlexiDeleteController;
19
- props: FlexiDeleteChildrenProps;
20
8
  }]>;
21
9
  };
22
10
  declare const FlexiDelete: import("svelte").Component<FlexiDeleteProps, {}, "controller">;
@@ -18,8 +18,8 @@
18
18
 
19
19
  <button
20
20
  style={'user-select: none; touch-action: none;' +
21
- (widget.draggable && widget.mounted ? 'cursor: grab;' : 'cursor: not-allowed;')}
22
- disabled={!widget.draggable || !widget.mounted}
21
+ (widget.isGrabbable && widget.mounted ? 'cursor: grab;' : 'cursor: not-allowed;')}
22
+ disabled={!widget.isGrabbable || !widget.mounted}
23
23
  class={className}
24
24
  {onpointerdown}
25
25
  {onkeydown}
@@ -70,21 +70,6 @@
70
70
  controller = target;
71
71
  onfirstcreate?.(target);
72
72
 
73
- // TODO: probable Svelte bug, causes browser freeze on production builds.
74
- // Haven't been able to repro on REPL as yet.
75
- // let orderedWidgets: InternalFlexiWidgetController[] = $derived.by(() => {
76
- // return Array.from(target.internalWidgets).toSorted((a, b) => {
77
- // if (a.y !== b.y) {
78
- // return a.y - b.y;
79
- // }
80
-
81
- // if (a.x == b.x) {
82
- // console.warn('[warning] collision detected between widgets ', a.id, ' and ', b.id);
83
- // }
84
- // return a.x - b.x;
85
- // });
86
- // });
87
-
88
73
  // Cleanup target subscriptions when component is destroyed
89
74
  onDestroy(() => {
90
75
  target.destroy();
@@ -96,15 +81,19 @@
96
81
 
97
82
  <!-- Allow user to specify components directly via a registration component. Once that's done, mount them to the actual target list dynamically -->
98
83
  <FlexiGrid class={className}>
99
- {#if !target.prepared && children}
100
- {@render children()}
101
- {:else if target.prepared}
84
+ {#if children}
85
+ <!-- Keep the initial widgets 'rendered' so that state inside children snippet doesn't get lost -->
86
+ <div style={target.prepared ? 'visibility: hidden;' : ''}>
87
+ {@render children()}
88
+ </div>
89
+ {/if}
90
+ {#if target.prepared}
102
91
  <!-- Render widgets in deterministic order for tabbing and consistent DOM ordering -->
103
92
  {#each target.orderedWidgets as widget (widget.id)}
104
93
  <RenderedFlexiWidget {widget} />
105
94
  {/each}
106
95
 
107
- {#if target.dropzoneWidget}
96
+ {#if target.dropzoneWidget && target.shouldRenderDropzoneWidget}
108
97
  <RenderedFlexiWidget widget={target.dropzoneWidget} />
109
98
  {/if}
110
99
  {/if}
@@ -28,8 +28,8 @@
28
28
 
29
29
  let config: FlexiWidgetConfiguration = $state({
30
30
  ...propsConfig,
31
- className: className,
32
- snippet: children
31
+ ...(className !== undefined && { className }),
32
+ ...(children !== undefined && { snippet: children })
33
33
  });
34
34
 
35
35
  // Callback so that we still fulfil these props.
@@ -0,0 +1,83 @@
1
+ <script module lang="ts">
2
+ import { onDestroy, type Snippet } from 'svelte';
3
+ import type { FlexiCommonProps } from '../system/types.js';
4
+ import type { ResponsiveFlexiBoardController } from '../system/responsive/base.svelte.js';
5
+ import type { ResponsiveFlexiBoardConfiguration } from '../system/responsive/types.js';
6
+
7
+ export type BreakpointSnippetParams = { currentBreakpoint: string };
8
+
9
+ export type ResponsiveFlexiBoardProps = FlexiCommonProps<ResponsiveFlexiBoardController> & {
10
+ config?: ResponsiveFlexiBoardConfiguration;
11
+ /**
12
+ * Snippet for large breakpoint (no params - breakpoint is implicit).
13
+ */
14
+ lg?: Snippet;
15
+ /**
16
+ * Snippet for medium breakpoint (no params - breakpoint is implicit).
17
+ */
18
+ md?: Snippet;
19
+ /**
20
+ * Snippet for small breakpoint (no params - breakpoint is implicit).
21
+ */
22
+ sm?: Snippet;
23
+ /**
24
+ * Snippet for extra-small breakpoint (no params - breakpoint is implicit).
25
+ */
26
+ xs?: Snippet;
27
+ /**
28
+ * Children snippet used as fallback when no specific breakpoint snippet matches.
29
+ * Receives `{ currentBreakpoint: string }` as a parameter.
30
+ */
31
+ children?: Snippet<[BreakpointSnippetParams]>;
32
+ };
33
+ </script>
34
+
35
+ <script lang="ts">
36
+ import { responsiveflexiboard } from '../system/responsive/index.js';
37
+
38
+ let {
39
+ controller = $bindable(),
40
+ onfirstcreate,
41
+ config,
42
+ lg,
43
+ md,
44
+ sm,
45
+ xs,
46
+ children
47
+ }: ResponsiveFlexiBoardProps = $props();
48
+
49
+ const board = responsiveflexiboard({ config });
50
+ controller = board;
51
+
52
+ // Load layouts immediately so child FlexiBoards can access them
53
+ board.oninitialloadcomplete();
54
+
55
+ onfirstcreate?.(board);
56
+
57
+ // Map breakpoint names to snippets (without params)
58
+ const snippets: Record<string, Snippet | undefined> = $derived({
59
+ lg,
60
+ md,
61
+ sm,
62
+ xs
63
+ });
64
+
65
+ // Cleanup when component is destroyed
66
+ onDestroy(() => {
67
+ board.destroy();
68
+ });
69
+ </script>
70
+
71
+ <!--
72
+ Key on currentBreakpoint to force re-render when breakpoint changes.
73
+ This ensures the board is re-created with the correct breakpoint context.
74
+ -->
75
+ {#key board.currentBreakpoint}
76
+ {#if snippets[board.currentBreakpoint]}
77
+ <!-- Specific breakpoint snippet (no params) -->
78
+ {@render snippets[board.currentBreakpoint]!()}
79
+ {:else if children}
80
+ <!-- Children snippet receives { currentBreakpoint } -->
81
+ {@render children({ currentBreakpoint: board.currentBreakpoint })}
82
+ {/if}
83
+ {/key}
@@ -0,0 +1,34 @@
1
+ import { type Snippet } from 'svelte';
2
+ import type { FlexiCommonProps } from '../system/types.js';
3
+ import type { ResponsiveFlexiBoardController } from '../system/responsive/base.svelte.js';
4
+ import type { ResponsiveFlexiBoardConfiguration } from '../system/responsive/types.js';
5
+ export type BreakpointSnippetParams = {
6
+ currentBreakpoint: string;
7
+ };
8
+ export type ResponsiveFlexiBoardProps = FlexiCommonProps<ResponsiveFlexiBoardController> & {
9
+ config?: ResponsiveFlexiBoardConfiguration;
10
+ /**
11
+ * Snippet for large breakpoint (no params - breakpoint is implicit).
12
+ */
13
+ lg?: Snippet;
14
+ /**
15
+ * Snippet for medium breakpoint (no params - breakpoint is implicit).
16
+ */
17
+ md?: Snippet;
18
+ /**
19
+ * Snippet for small breakpoint (no params - breakpoint is implicit).
20
+ */
21
+ sm?: Snippet;
22
+ /**
23
+ * Snippet for extra-small breakpoint (no params - breakpoint is implicit).
24
+ */
25
+ xs?: Snippet;
26
+ /**
27
+ * Children snippet used as fallback when no specific breakpoint snippet matches.
28
+ * Receives `{ currentBreakpoint: string }` as a parameter.
29
+ */
30
+ children?: Snippet<[BreakpointSnippetParams]>;
31
+ };
32
+ declare const ResponsiveFlexiBoard: import("svelte").Component<ResponsiveFlexiBoardProps, {}, "controller">;
33
+ type ResponsiveFlexiBoard = ReturnType<typeof ResponsiveFlexiBoard>;
34
+ export default ResponsiveFlexiBoard;
package/dist/index.d.ts CHANGED
@@ -5,10 +5,13 @@ import FlexiGrab from './components/flexi-grab.svelte';
5
5
  import FlexiResize from './components/flexi-resize.svelte';
6
6
  import FlexiAdd from './components/flexi-add.svelte';
7
7
  import FlexiDelete from './components/flexi-delete.svelte';
8
+ import ResponsiveFlexiBoard, { type ResponsiveFlexiBoardProps, type BreakpointSnippetParams } from './components/responsive-flexi-board.svelte';
8
9
  import type { FlexiBoardConfiguration, FlexiBoardController } from './system/board/index.js';
9
10
  import type { FlexiTargetConfiguration, FlexiTargetController } from './system/target/index.js';
10
11
  import { type FlexiWidgetController, type FlexiWidgetChildrenSnippet, type FlexiWidgetChildrenSnippetParameters, type FlexiWidgetConfiguration, type FlexiWidgetTransitionConfiguration, type FlexiWidgetTransitionTypeConfiguration, type FlexiWidgetTriggerConfiguration, simpleTransitionConfig, getFlexiwidgetCtx } from './system/widget/index.js';
11
12
  import type { AdderWidgetConfiguration, FlexiAddController, FlexiAddWidgetFn } from './system/misc/adder.svelte.js';
12
13
  import { immediateTriggerConfig, longPressTriggerConfig, type PointerTriggerCondition } from './system/widget/triggers.svelte.js';
14
+ import type { FlexiLayout, FlexiRegistryEntry, FlexiWidgetLayoutEntry, FlexiLoadLayoutFn, FlexiLayoutChangeFn } from './system/board/types.js';
15
+ import type { ResponsiveFlexiBoardController, ResponsiveFlexiBoardConfiguration, ResponsiveFlexiLayout } from './system/responsive/index.js';
13
16
  export * from './system/types.js';
14
- export { FlexiBoard, type FlexiBoardConfiguration, type FlexiBoardProps, FlexiTarget, type FlexiTargetConfiguration, type FlexiTargetProps, FlexiWidget, type FlexiWidgetConfiguration, type FlexiWidgetProps, FlexiGrab, FlexiResize, FlexiAdd, FlexiDelete, type FlexiAddWidgetFn, type AdderWidgetConfiguration, type FlexiWidgetController, type FlexiBoardController, type FlexiTargetController, type FlexiAddController, type FlexiWidgetChildrenSnippet, type FlexiWidgetChildrenSnippetParameters, type PointerTriggerCondition, type FlexiWidgetTriggerConfiguration, type FlexiWidgetTransitionTypeConfiguration, type FlexiWidgetTransitionConfiguration, immediateTriggerConfig, longPressTriggerConfig, getFlexiwidgetCtx, simpleTransitionConfig };
17
+ export { FlexiBoard, type FlexiBoardConfiguration, type FlexiBoardProps, type FlexiLayout, type FlexiWidgetLayoutEntry, type FlexiRegistryEntry, type FlexiLoadLayoutFn, type FlexiLayoutChangeFn, FlexiTarget, type FlexiTargetConfiguration, type FlexiTargetProps, FlexiWidget, type FlexiWidgetConfiguration, type FlexiWidgetProps, FlexiGrab, FlexiResize, FlexiAdd, FlexiDelete, type FlexiAddWidgetFn, type AdderWidgetConfiguration, type FlexiWidgetController, type FlexiBoardController, type FlexiTargetController, type FlexiAddController, type FlexiWidgetChildrenSnippet, type FlexiWidgetChildrenSnippetParameters, type PointerTriggerCondition, type FlexiWidgetTriggerConfiguration, type FlexiWidgetTransitionTypeConfiguration, type FlexiWidgetTransitionConfiguration, immediateTriggerConfig, longPressTriggerConfig, getFlexiwidgetCtx, simpleTransitionConfig, ResponsiveFlexiBoard, type ResponsiveFlexiBoardProps, type ResponsiveFlexiBoardController, type ResponsiveFlexiBoardConfiguration, type ResponsiveFlexiLayout, type BreakpointSnippetParams };
package/dist/index.js CHANGED
@@ -7,7 +7,10 @@ import FlexiGrab from './components/flexi-grab.svelte';
7
7
  import FlexiResize from './components/flexi-resize.svelte';
8
8
  import FlexiAdd from './components/flexi-add.svelte';
9
9
  import FlexiDelete from './components/flexi-delete.svelte';
10
+ import ResponsiveFlexiBoard, {} from './components/responsive-flexi-board.svelte';
10
11
  import { simpleTransitionConfig, getFlexiwidgetCtx } from './system/widget/index.js';
11
12
  import { immediateTriggerConfig, longPressTriggerConfig } from './system/widget/triggers.svelte.js';
12
13
  export * from './system/types.js';
13
- export { FlexiBoard, FlexiTarget, FlexiWidget, FlexiGrab, FlexiResize, FlexiAdd, FlexiDelete, immediateTriggerConfig, longPressTriggerConfig, getFlexiwidgetCtx, simpleTransitionConfig };
14
+ export { FlexiBoard, FlexiTarget, FlexiWidget, FlexiGrab, FlexiResize, FlexiAdd, FlexiDelete, immediateTriggerConfig, longPressTriggerConfig, getFlexiwidgetCtx, simpleTransitionConfig,
15
+ // Responsive FlexiBoard
16
+ ResponsiveFlexiBoard };
@@ -1,5 +1,6 @@
1
1
  import type { FlexiTargetController } from '../target/base.svelte.js';
2
2
  import type { FlexiWidgetController } from '../widget/base.svelte.js';
3
+ import type { FlexiLayout } from './types.js';
3
4
  export interface FlexiBoardController {
4
5
  /**
5
6
  * The reactive styling to apply to the board's root element.
@@ -9,6 +10,10 @@ export interface FlexiBoardController {
9
10
  * The reactive DOM reference to the board's root element.
10
11
  */
11
12
  ref: HTMLElement | null;
13
+ /**
14
+ * The breakpoint that the board corresponds to, if the board is responsive.
15
+ */
16
+ readonly breakpoint?: string;
12
17
  /**
13
18
  * Moves an existing widget from one target to another.
14
19
  * @param widget The widget to move.
@@ -16,4 +21,14 @@ export interface FlexiBoardController {
16
21
  * @param to The target to move the widget to.
17
22
  */
18
23
  moveWidget(widget: FlexiWidgetController, from: FlexiTargetController | undefined, to: FlexiTargetController): void;
24
+ /**
25
+ * Imports a widget layout into the board.
26
+ * @param layout The widget layout to import.
27
+ */
28
+ importLayout(layout: FlexiLayout): void;
29
+ /**
30
+ * Exports the current widget layout of the board.
31
+ * @returns The current widget layout of the board.
32
+ */
33
+ exportLayout(): FlexiLayout;
19
34
  }
@@ -1,20 +1,24 @@
1
1
  import type { FlexiBoardProps } from '../../components/flexi-board.svelte';
2
2
  import type { AriaPoliteness, FlexiAnnouncerController } from '../announcer.svelte.js';
3
3
  import type { FlexiPortalController } from '../portal.js';
4
- import type { FlexiTargetController } from '../target/base.svelte.js';
5
4
  import { InternalFlexiTargetController } from '../target/controller.svelte.js';
6
5
  import type { FlexiTargetPartialConfiguration } from '../target/types.js';
7
6
  import type { TargetEvent, WidgetAction, WidgetEvent, WidgetGrabbedEvent, WidgetResizingEvent } from '../types.js';
8
- import type { FlexiWidgetController } from '../widget/base.svelte.js';
9
7
  import type { FlexiBoardController } from './base.svelte.js';
10
- import type { FlexiBoardConfiguration } from './types.js';
8
+ import type { FlexiBoardConfiguration, FlexiRegistryEntry, FlexiLayout } from './types.js';
9
+ import type { InternalFlexiWidgetController } from '../widget/controller.svelte.js';
10
+ import type { InternalResponsiveFlexiBoardController } from '../responsive/controller.svelte.js';
11
11
  export declare class InternalFlexiBoardController implements FlexiBoardController {
12
12
  #private;
13
13
  hoveredTarget: InternalFlexiTargetController | null;
14
14
  config?: FlexiBoardConfiguration;
15
+ registry?: Record<string, FlexiRegistryEntry>;
15
16
  portal: FlexiPortalController | null;
17
+ readonly breakpoint?: string;
16
18
  constructor(props: FlexiBoardProps);
17
19
  style: string;
20
+ notifyInterpolationStarted(): void;
21
+ notifyInterpolationEnded(): void;
18
22
  get ref(): HTMLElement | null;
19
23
  set ref(ref: HTMLElement | null);
20
24
  createTarget(config?: FlexiTargetPartialConfiguration, key?: string): InternalFlexiTargetController;
@@ -29,14 +33,32 @@ export declare class InternalFlexiBoardController implements FlexiBoardControlle
29
33
  attachAnnouncer(announcer: FlexiAnnouncerController): void;
30
34
  announce(message: string, politeness?: AriaPoliteness): void;
31
35
  oninitialloadcomplete(): void;
36
+ /**
37
+ * Imports a layout into this board.
38
+ *
39
+ * **Note**: If this board is under a ResponsiveFlexiBoard, prefer using
40
+ * `responsiveBoard.importLayout()` to import layouts for all breakpoints.
41
+ */
42
+ importLayout(layout: FlexiLayout): void;
43
+ /**
44
+ * Exports the current layout from this board.
45
+ *
46
+ * **Note**: If this board is under a ResponsiveFlexiBoard, prefer using
47
+ * `responsiveBoard.exportLayout()` to export layouts for all breakpoints.
48
+ */
49
+ exportLayout(): FlexiLayout;
32
50
  /**
33
51
  * Moves a widget from one target to another.
34
52
  * @param widget The widget to move.
35
53
  * @param from The target to move the widget from.
36
54
  * @param to The target to move the widget to.
37
55
  */
38
- moveWidget(widget: FlexiWidgetController, from: FlexiTargetController | undefined, to: FlexiTargetController): boolean;
56
+ moveWidget(widget: InternalFlexiWidgetController, from: InternalFlexiTargetController | undefined, to: InternalFlexiTargetController): boolean;
39
57
  get currentWidgetAction(): WidgetAction | null;
58
+ /**
59
+ * Returns the parent responsive controller if this board is within a ResponsiveFlexiBoard.
60
+ */
61
+ get responsiveController(): InternalResponsiveFlexiBoardController | null;
40
62
  /**
41
63
  * Cleanup method to be called when the board is destroyed
42
64
  */