@lavalogic/scoria 0.5.7 → 0.6.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.
@@ -1,19 +1,24 @@
1
1
  <svelte:options runes />
2
2
 
3
3
  <script lang="ts" module>
4
- import type { Snippet } from 'svelte';
4
+ import { DraggableCard } from '../../index.js';
5
+ import { tick, type Snippet } from 'svelte';
5
6
 
6
7
  export interface Draggable<T> {
7
8
  id: string;
8
- name: string;
9
+ title: string;
10
+ subtitle: string;
9
11
  original: T;
12
+ selected?: boolean;
13
+ toggleSelected?: () => void;
10
14
  }
11
15
 
12
16
  export interface DragMenuHolderProps<T> {
13
- items: Draggable<T>[];
14
- consider: (items: Draggable<T>[]) => void;
15
- finalise: (items: Draggable<T>[]) => void;
16
- snippet: Snippet<[Draggable<T>, number]>;
17
+ items: T[];
18
+ transformToDraggable: (item: T) => Draggable<T>;
19
+ snippet?: Snippet<[Draggable<T>, number]>;
20
+
21
+ onUpdate: (items: T[]) => void;
17
22
 
18
23
  label?: string;
19
24
  flipDurationMS?: number;
@@ -25,15 +30,68 @@
25
30
  import { flip } from 'svelte/animate';
26
31
 
27
32
  const {
28
- items,
29
- consider,
30
- finalise,
31
- snippet,
33
+ items: originalItems,
34
+ onUpdate,
35
+ snippet: customSnippet,
36
+ transformToDraggable,
32
37
  flipDurationMS = 60,
33
38
  label
34
39
  }: DragMenuHolderProps<T> = $props();
40
+
41
+ let items: Draggable<T>[] = $state([]);
42
+
43
+ function consider(newItems: Draggable<T>[]) {
44
+ items = newItems;
45
+ }
46
+ function finalise(newItems: Draggable<T>[]) {
47
+ items = newItems;
48
+ onUpdate(items.map((it) => it.original));
49
+ }
50
+
51
+ $effect.pre(() => {
52
+ void originalItems;
53
+ items = originalItems.map(transformToDraggable);
54
+ });
55
+
56
+ const snippet = $derived(customSnippet ?? draggableWithSelect);
57
+
58
+ function up(item: Draggable<T>, index: number) {
59
+ const before = items.slice(0, index);
60
+ const next = before.pop();
61
+ const [removed, ...after] = items.slice(index);
62
+
63
+ before.push(removed);
64
+ if (next) {
65
+ before.push(next);
66
+ }
67
+ before.push(...after);
68
+ items = before;
69
+ }
70
+
71
+ function down(item: Draggable<T>, index: number) {
72
+ const before = items.slice(0, index);
73
+
74
+ const [removed, previous, ...after] = items.slice(index);
75
+
76
+ if (previous) {
77
+ before.push(previous);
78
+ }
79
+ before.push(removed);
80
+ before.push(...after);
81
+ items = before;
82
+ }
35
83
  </script>
36
84
 
85
+ {#snippet draggableWithSelect<T>(item: Draggable, index: number)}
86
+ <DraggableCard
87
+ title={item.title}
88
+ subtitle={item.subtitle}
89
+ {index}
90
+ selectable
91
+ selected={item.selected}
92
+ />
93
+ {/snippet}
94
+
37
95
  <div class="wrapper">
38
96
  {#if label}
39
97
  <span class="top-label">{label}</span>
@@ -49,14 +107,49 @@
49
107
  finalise(e.detail.items);
50
108
  }}
51
109
  >
110
+ <!-- svelte-ignore a11y_no_static_element_interactions -->
52
111
  {#each items as item, index (item.id)}
53
- <div class="contents" animate:flip={{ duration: flipDurationMS }}>
112
+ <!-- svelte-ignore a11y_click_events_have_key_events -->
113
+ <div
114
+ class="contents"
115
+ onclick={(e) => {
116
+ if (item.toggleSelected) {
117
+ e.stopPropagation();
118
+ item.toggleSelected();
119
+ }
120
+ }}
121
+ animate:flip={{ duration: flipDurationMS }}
122
+ >
54
123
  {@render snippet(item, index)}
55
124
  </div>
56
125
  {/each}
57
126
  </div>
58
127
  </div>
59
128
 
129
+ <!--
130
+ tabindex="0"
131
+ role="button"
132
+ onkeydown={(e) => {
133
+ const prevTarget = e.target;
134
+ console.log(e.key);
135
+ if (e.key == 'ArrowUp') {
136
+ e.stopPropagation();
137
+ up(item, index);
138
+ } else if (e.key == 'ArrowDown') {
139
+ e.stopPropagation();
140
+ down(item, index);
141
+ } else if (e.key == ' ') {
142
+ alert('SPACEBAR');
143
+ }
144
+ tick().then(() => {
145
+ if (prevTarget && 'focus' in prevTarget) {
146
+ (prevTarget as HTMLElement).focus();
147
+ } else {
148
+ console.warn(`prev target is undefined`);
149
+ }
150
+ });
151
+ }} -->
152
+
60
153
  <style>.top-label {
61
154
  position: absolute;
62
155
  left: 0.5rem;
@@ -1,14 +1,17 @@
1
- import type { Snippet } from 'svelte';
1
+ import { type Snippet } from 'svelte';
2
2
  export interface Draggable<T> {
3
3
  id: string;
4
- name: string;
4
+ title: string;
5
+ subtitle: string;
5
6
  original: T;
7
+ selected?: boolean;
8
+ toggleSelected?: () => void;
6
9
  }
7
10
  export interface DragMenuHolderProps<T> {
8
- items: Draggable<T>[];
9
- consider: (items: Draggable<T>[]) => void;
10
- finalise: (items: Draggable<T>[]) => void;
11
- snippet: Snippet<[Draggable<T>, number]>;
11
+ items: T[];
12
+ transformToDraggable: (item: T) => Draggable<T>;
13
+ snippet?: Snippet<[Draggable<T>, number]>;
14
+ onUpdate: (items: T[]) => void;
12
15
  label?: string;
13
16
  flipDurationMS?: number;
14
17
  }
@@ -9,13 +9,11 @@
9
9
 
10
10
  touch?: boolean;
11
11
  selected?: boolean; // default false
12
- disabled?: boolean; // default false
12
+ toggleSelected?: () => void;
13
13
  }
14
14
  </script>
15
15
 
16
16
  <script lang="ts">
17
- import { Size } from '../../Types/Internal/Size.js';
18
-
19
17
  import Checkbox from '../Checkbox.svelte';
20
18
 
21
19
  let {
@@ -25,14 +23,20 @@
25
23
  index,
26
24
  selected = $bindable(false),
27
25
  touch = false,
28
- disabled = false
26
+ toggleSelected
29
27
  }: DraggableCardProps = $props();
30
28
  </script>
31
29
 
32
30
  <div class="card" class:touch>
33
31
  {#if selectable}
34
32
  <div class="limit-size" class:touch>
35
- <Checkbox value={selected} onchange={() => (selected = !selected)} />
33
+ <Checkbox
34
+ value={selected}
35
+ onchange={(e) => {
36
+ e.stopPropagation();
37
+ toggleSelected?.();
38
+ }}
39
+ />
36
40
  </div>
37
41
  {/if}
38
42
  <div class="text" class:touch>
@@ -5,7 +5,7 @@ export interface DraggableCardProps {
5
5
  index: number;
6
6
  touch?: boolean;
7
7
  selected?: boolean;
8
- disabled?: boolean;
8
+ toggleSelected?: () => void;
9
9
  }
10
10
  declare const DraggableCard: import("svelte").Component<DraggableCardProps, {}, "selected">;
11
11
  type DraggableCard = ReturnType<typeof DraggableCard>;
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@lavalogic/scoria",
3
3
  "description": "Svelte components used for the FloWMS Web Frontend",
4
- "version": "0.5.7",
4
+ "version": "0.6.0",
5
5
  "publishConfig": {
6
6
  "access": "restricted"
7
7
  },
@@ -31,23 +31,23 @@
31
31
  "devDependencies": {
32
32
  "@chromatic-com/storybook": "^4.1.3",
33
33
  "@eslint/compat": "^2.0.0",
34
- "@eslint/js": "^9.39.1",
34
+ "@eslint/js": "^9.39.2",
35
35
  "@playwright/test": "^1.57.0",
36
- "@storybook/addon-a11y": "^10.1.7",
37
- "@storybook/addon-docs": "^10.1.7",
36
+ "@storybook/addon-a11y": "^10.1.10",
37
+ "@storybook/addon-docs": "^10.1.10",
38
38
  "@storybook/addon-svelte-csf": "^5.0.10",
39
- "@storybook/addon-vitest": "^10.1.7",
40
- "@storybook/sveltekit": "^10.1.7",
39
+ "@storybook/addon-vitest": "^10.1.10",
40
+ "@storybook/sveltekit": "^10.1.10",
41
41
  "@sveltejs/adapter-node": "^5.4.0",
42
42
  "@sveltejs/kit": "^2.49.2",
43
43
  "@sveltejs/package": "^2.5.7",
44
44
  "@sveltejs/vite-plugin-svelte": "^6.2.1",
45
45
  "@types/eslint": "^9.6.1",
46
- "@types/node": "^24.10.3",
47
- "@typescript-eslint/eslint-plugin": "^8.49.0",
48
- "@typescript-eslint/parser": "^8.49.0",
49
- "@vitest/browser": "^4.0.15",
50
- "eslint": "^9.39.1",
46
+ "@types/node": "^24.10.4",
47
+ "@typescript-eslint/eslint-plugin": "^8.50.0",
48
+ "@typescript-eslint/parser": "^8.50.0",
49
+ "@vitest/browser": "^4.0.16",
50
+ "eslint": "^9.39.2",
51
51
  "eslint-config-prettier": "^10.1.8",
52
52
  "eslint-plugin-storybook": "10.1.4",
53
53
  "eslint-plugin-svelte": "^3.13.1",
@@ -55,18 +55,18 @@
55
55
  "mdsvex": "^0.12.6",
56
56
  "playwright": "^1.57.0",
57
57
  "prettier": "^3.7.4",
58
- "prettier-plugin-svelte": "^3.4.0",
58
+ "prettier-plugin-svelte": "^3.4.1",
59
59
  "publint": "^0.3.16",
60
- "sass-embedded": "^1.96.0",
61
- "storybook": "^10.1.7",
62
- "svelte": "^5.45.10",
60
+ "sass-embedded": "^1.97.0",
61
+ "storybook": "^10.1.10",
62
+ "svelte": "^5.46.0",
63
63
  "svelte-check": "^4.3.4",
64
64
  "svelte-render-scan": "^1.1.0",
65
65
  "typescript": "^5.9.3",
66
- "typescript-eslint": "^8.49.0",
67
- "vite": "^7.2.7",
66
+ "typescript-eslint": "^8.50.0",
67
+ "vite": "^7.3.0",
68
68
  "vite-plugin-devtools-json": "^1.0.0",
69
- "vitest": "^4.0.15",
69
+ "vitest": "^4.0.16",
70
70
  "vitest-browser-svelte": "^2.0.1"
71
71
  },
72
72
  "keywords": [