carbon-components-svelte 0.94.0 → 0.94.2

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "carbon-components-svelte",
3
- "version": "0.94.0",
3
+ "version": "0.94.2",
4
4
  "license": "Apache-2.0",
5
5
  "description": "Svelte implementation of the Carbon Design System",
6
6
  "type": "module",
@@ -15,6 +15,11 @@
15
15
  */
16
16
  const overflowVisible = writable(false);
17
17
 
18
+ /**
19
+ * @type {import("svelte/store").Writable<boolean>}
20
+ */
21
+ const batchActionsActive = writable(false);
22
+
18
23
  /**
19
24
  * @type {(visible: boolean) => void}
20
25
  */
@@ -26,6 +31,7 @@
26
31
  setContext("Toolbar", {
27
32
  overflowVisible,
28
33
  setOverflowVisible,
34
+ batchActionsActive,
29
35
  });
30
36
  </script>
31
37
 
@@ -82,6 +82,10 @@
82
82
  });
83
83
  }
84
84
 
85
+ $: if (ctxToolbar?.batchActionsActive) {
86
+ ctxToolbar.batchActionsActive.set(showActions);
87
+ }
88
+
85
89
  onMount(() => {
86
90
  return () => {
87
91
  unsubscribe?.();
@@ -1,18 +1,17 @@
1
1
  <script>
2
2
  import { getContext } from "svelte";
3
3
 
4
- const ctx = getContext("DataTable") ?? {};
4
+ const ctx = getContext("Toolbar") ?? {};
5
5
 
6
- let batchSelectedIds = [];
6
+ let batchActionsActive = false;
7
7
 
8
- if (ctx?.batchSelectedIds) {
9
- ctx.batchSelectedIds.subscribe((value) => {
10
- batchSelectedIds = value;
8
+ if (ctx?.batchActionsActive) {
9
+ ctx.batchActionsActive.subscribe((value) => {
10
+ batchActionsActive = value;
11
11
  });
12
12
  }
13
13
 
14
- $: hasBatchSelection = batchSelectedIds.length > 0;
15
- $: inertProps = hasBatchSelection ? { inert: true } : {};
14
+ $: inertProps = batchActionsActive ? { inert: true } : {};
16
15
  </script>
17
16
 
18
17
  <div class:bx--toolbar-content={true} {...inertProps}>
@@ -16,8 +16,8 @@
16
16
  });
17
17
 
18
18
  $: selected = $selectedContent === id;
19
- $: index = $contentById[id].index;
20
- $: tabId = $tabs[index].id;
19
+ $: index = $contentById[id]?.index ?? 0;
20
+ $: tabId = $tabs[index]?.id;
21
21
  </script>
22
22
 
23
23
  <div
@@ -69,44 +69,40 @@
69
69
  let refTabList = null;
70
70
  let refRoot = null;
71
71
 
72
+ // Flag to trigger DOM reordering only when tabs change.
73
+ // This is necessary to avoid infinite loops in Svelte 5.
74
+ let needsDomSync = false;
75
+
72
76
  /**
73
77
  * @type {(data: { id: string; label: string; disabled: boolean }) => void}
74
78
  */
75
79
  const add = (data) => {
76
- tabs.update((_) => {
77
- const newTabs = [..._, { ...data, index: _.length }];
78
- return newTabs.map((tab, index) => ({ ...tab, index }));
79
- });
80
+ needsDomSync = true;
81
+ tabs.update((_) => [..._, { ...data, index: _.length }]);
80
82
  };
81
83
 
82
84
  /**
83
85
  * @type {(id: string) => void}
84
86
  */
85
87
  const remove = (id) => {
86
- tabs.update((_) => {
87
- const filtered = _.filter((tab) => tab.id !== id);
88
- return filtered.map((tab, index) => ({ ...tab, index }));
89
- });
88
+ needsDomSync = true;
89
+ tabs.update((_) => _.filter((tab) => tab.id !== id));
90
90
  };
91
91
 
92
92
  /**
93
93
  * @type {(data: { id: string }) => void}
94
94
  */
95
95
  const addContent = (data) => {
96
- content.update((_) => {
97
- const newContent = [..._, { ...data, index: _.length }];
98
- return newContent.map((item, index) => ({ ...item, index }));
99
- });
96
+ needsDomSync = true;
97
+ content.update((_) => [..._, { ...data, index: _.length }]);
100
98
  };
101
99
 
102
100
  /**
103
101
  * @type {(id: string) => void}
104
102
  */
105
103
  const removeContent = (id) => {
106
- content.update((_) => {
107
- const filtered = _.filter((item) => item.id !== id);
108
- return filtered.map((item, index) => ({ ...item, index }));
109
- });
104
+ needsDomSync = true;
105
+ content.update((_) => _.filter((item) => item.id !== id));
110
106
  };
111
107
 
112
108
  /**
@@ -165,44 +161,41 @@
165
161
  });
166
162
 
167
163
  afterUpdate(() => {
168
- // We need to use the DOM order of the tabs to update
169
- // the indices of the tabs in the store. This is because
170
- // the current implementation uses an implicit index approach
171
- // where order matters. A more robust solution would be to
172
- // require explicit keys specified by the consumer.
173
- if (refTabList) {
164
+ // Sync DOM order with stores only when tabs are added/removed.
165
+ // This avoids infinite loops in Svelte 5 by not running on every update.
166
+ if (needsDomSync && refTabList) {
167
+ needsDomSync = false;
168
+
174
169
  const domTabs = Array.from(refTabList.querySelectorAll("[role='tab']"));
175
- const domIds = domTabs.map((el) => el.id);
170
+ const domTabIds = domTabs.map((el) => el.id);
176
171
 
177
172
  tabs.update((currentTabs) => {
178
173
  const tabsMap = new Map(currentTabs.map((tab) => [tab.id, tab]));
179
- const reorderedTabs = domIds
174
+ return domTabIds
180
175
  .map((id, index) => {
181
176
  const tab = tabsMap.get(id);
182
177
  return tab ? { ...tab, index } : undefined;
183
178
  })
184
179
  .filter(Boolean);
185
-
186
- return reorderedTabs;
187
180
  });
188
- }
189
-
190
- const contentElements = refRoot?.parentElement
191
- ? Array.from(refRoot.parentElement.querySelectorAll("[role='tabpanel']"))
192
- : [];
193
- const contentIds = contentElements.map((el) => el.id);
194
181
 
195
- content.update((currentContent) => {
196
- const contentMap = new Map(currentContent.map((c) => [c.id, c]));
197
- const reorderedContent = contentIds
198
- .map((id, index) => {
199
- const c = contentMap.get(id);
200
- return c ? { ...c, index } : undefined;
201
- })
202
- .filter(Boolean);
182
+ const contentElements = refRoot?.parentElement
183
+ ? Array.from(
184
+ refRoot.parentElement.querySelectorAll("[role='tabpanel']"),
185
+ )
186
+ : [];
187
+ const contentIds = contentElements.map((el) => el.id);
203
188
 
204
- return reorderedContent;
205
- });
189
+ content.update((currentContent) => {
190
+ const contentMap = new Map(currentContent.map((c) => [c.id, c]));
191
+ return contentIds
192
+ .map((id, index) => {
193
+ const c = contentMap.get(id);
194
+ return c ? { ...c, index } : undefined;
195
+ })
196
+ .filter(Boolean);
197
+ });
198
+ }
206
199
 
207
200
  if (selected !== currentIndex) {
208
201
  selected = currentIndex;
@@ -280,4 +273,4 @@
280
273
  <slot />
281
274
  </ul>
282
275
  </div>
283
- <slot name="content" />
276
+ <slot name="content" />
@@ -4,6 +4,7 @@ import type { SvelteHTMLElements } from "svelte/elements";
4
4
  export type ToolbarContext = {
5
5
  overflowVisible: import("svelte/store").Writable<boolean>;
6
6
  setOverflowVisible: (visible: boolean) => void;
7
+ batchActionsActive: import("svelte/store").Writable<boolean>;
7
8
  };
8
9
 
9
10
  type $RestProps = SvelteHTMLElements["section"];