carbon-components-svelte 0.98.4 → 0.98.6

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.98.4",
3
+ "version": "0.98.6",
4
4
  "license": "Apache-2.0",
5
5
  "description": "Svelte implementation of the Carbon Design System",
6
6
  "type": "module",
@@ -1,8 +1,6 @@
1
1
  <script>
2
2
  /**
3
3
  * @generics {Value extends string | number = string | number} Value
4
- * @template {string | number} Value
5
- * @typedef {string | number} SelectValue
6
4
  * @event {Value} update The selected value.
7
5
  */
8
6
 
@@ -65,7 +65,7 @@
65
65
 
66
66
  /**
67
67
  * Override the default select props.
68
- * @type {import("../Select/Select.svelte").SelectProps & { themes?: CarbonTheme[]; }}
68
+ * @type {import("../Select/Select.svelte").SelectProps<CarbonTheme> & { themes?: CarbonTheme[]; }}
69
69
  */
70
70
  export let select = {
71
71
  themes: themeKeys,
@@ -281,19 +281,19 @@
281
281
  /** @type {ReadonlyArray<TreeNodeId>} */
282
282
  let lastExpandedIdsRef = expandedIds;
283
283
 
284
- /** @type {(node: TreeNode) => void} */
284
+ /** @type {(node: Node) => void} */
285
285
  const clickNode = (node) => {
286
286
  activeId = node.id;
287
287
  selectedIds = [node.id];
288
288
  dispatch("select", node);
289
289
  };
290
290
 
291
- /** @type {(node: TreeNode) => void} */
291
+ /** @type {(node: Node) => void} */
292
292
  const selectNode = (node) => {
293
293
  selectedIds = [node.id];
294
294
  };
295
295
 
296
- /** @type {(node: TreeNode, expanded: boolean) => void} */
296
+ /** @type {(node: Node, expanded: boolean) => void} */
297
297
  const expandNode = (node, expanded) => {
298
298
  if (expanded) {
299
299
  expandedIdsSet.add(node.id);
@@ -304,10 +304,10 @@
304
304
  lastExpandedIdsRef = expandedIds;
305
305
  };
306
306
 
307
- /** @type {(node: TreeNode) => void} */
307
+ /** @type {(node: Node) => void} */
308
308
  const focusNode = (node) => dispatch("focus", node);
309
309
 
310
- /** @type {(node: TreeNode) => void} */
310
+ /** @type {(node: Node) => void} */
311
311
  const toggleNode = (node) => dispatch("toggle", node);
312
312
 
313
313
  setContext("TreeView", {
@@ -2,11 +2,11 @@ interface TruncateOptions {
2
2
  clamp?: "end" | "front";
3
3
  }
4
4
 
5
- export function TruncateAction(
5
+ export function truncate(
6
6
  node: HTMLElement,
7
7
  options?: TruncateOptions,
8
8
  ): {
9
9
  update: (options?: TruncateOptions) => void;
10
10
  };
11
11
 
12
- export default TruncateAction;
12
+ export default truncate;
@@ -2,16 +2,22 @@
2
2
  /** Specify the id for the main element */
3
3
  export let id = "main-content";
4
4
 
5
- import { isSideNavCollapsed, isSideNavRail } from "./navStore";
5
+ import {
6
+ isSideNavCollapsed,
7
+ isSideNavMobile,
8
+ isSideNavRail,
9
+ } from "./navStore";
6
10
 
7
11
  /**
8
12
  * By default, the `SideNav` applies a left margin of `3rem` to `Content`
9
13
  * if it's a sibling component (e.g., .bx--side-nav ~ .bx--content).
10
14
  *
11
- * We manually unset the left margin if the `SideNav`
12
- * is collapsed and if it's not the `rail` variant.
15
+ * Unset the left margin if:
16
+ * - `SideNav` is collapsed and it's not the `rail` variant, OR
17
+ * - `SideNav` overlays content on mobile (below the breakpoint)
13
18
  */
14
- $: unsetLeftMargin = $isSideNavCollapsed && !$isSideNavRail;
19
+ $: unsetLeftMargin =
20
+ ($isSideNavCollapsed && !$isSideNavRail) || $isSideNavMobile;
15
21
  </script>
16
22
 
17
23
  <main
@@ -84,12 +84,33 @@
84
84
  import HamburgerMenu from "./HamburgerMenu.svelte";
85
85
  import { shouldRenderHamburgerMenu } from "./navStore";
86
86
 
87
+ /** @type {undefined | number} */
87
88
  let winWidth = undefined;
89
+ let wasAboveBreakpoint = undefined;
90
+ let userExplicitlySet = false;
91
+
92
+ $: isAboveBreakpoint =
93
+ winWidth !== undefined && winWidth >= expansionBreakpoint;
94
+
95
+ // Only auto-set isSideNavOpen on initial mount or when crossing the breakpoint threshold.
96
+ // This prevents mobile browser scroll events (which cause minor width changes
97
+ // due to address bar hide/show) from unexpectedly closing the nav.
98
+ $: {
99
+ const shouldAutoExpand =
100
+ expandedByDefault && isAboveBreakpoint && !persistentHamburgerMenu;
101
+
102
+ if (wasAboveBreakpoint === undefined) {
103
+ // Initial mount: set based on current viewport
104
+ isSideNavOpen = shouldAutoExpand;
105
+ } else if (wasAboveBreakpoint !== isAboveBreakpoint) {
106
+ // Crossed breakpoint threshold - reset user flag and auto-expand if appropriate
107
+ userExplicitlySet = false;
108
+ isSideNavOpen = shouldAutoExpand;
109
+ }
110
+
111
+ wasAboveBreakpoint = isAboveBreakpoint;
112
+ }
88
113
 
89
- $: isSideNavOpen =
90
- expandedByDefault &&
91
- winWidth >= expansionBreakpoint &&
92
- !persistentHamburgerMenu;
93
114
  $: ariaLabel = companyName
94
115
  ? companyName
95
116
  : `${uiShellAriaLabel || $$props["aria-label"] || platformName}`;
@@ -104,6 +125,9 @@
104
125
  {#if ($shouldRenderHamburgerMenu && winWidth < expansionBreakpoint) || persistentHamburgerMenu}
105
126
  <HamburgerMenu
106
127
  bind:isOpen={isSideNavOpen}
128
+ on:click={() => {
129
+ userExplicitlySet = true;
130
+ }}
107
131
  {iconClose}
108
132
  {iconMenu}
109
133
  ariaLabel={hamburgerAriaLabel}
@@ -34,6 +34,7 @@
34
34
  import { createEventDispatcher, onMount } from "svelte";
35
35
  import {
36
36
  isSideNavCollapsed,
37
+ isSideNavMobile,
37
38
  isSideNavRail,
38
39
  shouldRenderHamburgerMenu,
39
40
  } from "./navStore";
@@ -45,10 +46,28 @@
45
46
  $: dispatch(isOpen ? "open" : "close");
46
47
  $: $isSideNavCollapsed = !isOpen;
47
48
  $: $isSideNavRail = rail;
49
+ $: $isSideNavMobile =
50
+ winWidth !== undefined && winWidth < expansionBreakpoint;
51
+
52
+ // Lock body scroll when SideNav is open on mobile (below breakpoint).
53
+ // Only applies to non-fixed, non-rail variants.
54
+ $: if (typeof document !== "undefined") {
55
+ const shouldLockScroll = isOpen && !fixed && !rail && $isSideNavMobile;
56
+ document.body.classList.toggle(
57
+ "bx--body--with-modal-open",
58
+ shouldLockScroll,
59
+ );
60
+ }
48
61
 
49
62
  onMount(() => {
50
63
  shouldRenderHamburgerMenu.set(true);
51
- return () => shouldRenderHamburgerMenu.set(false);
64
+ return () => {
65
+ shouldRenderHamburgerMenu.set(false);
66
+ isSideNavMobile.set(false);
67
+ if (typeof document !== "undefined") {
68
+ document.body.classList.remove("bx--body--with-modal-open");
69
+ }
70
+ };
52
71
  });
53
72
  </script>
54
73
 
@@ -5,3 +5,5 @@ export const shouldRenderHamburgerMenu = writable(false);
5
5
  export const isSideNavCollapsed = writable(false);
6
6
 
7
7
  export const isSideNavRail = writable(false);
8
+
9
+ export const isSideNavMobile = writable(false);
@@ -42,7 +42,8 @@ export type DataTableCell<Row = DataTableRow> = {
42
42
  value: DataTableValue;
43
43
  display?: (item: DataTableValue, row: DataTableRow) => DataTableValue;
44
44
  };
45
- export type DataTableContext = {
45
+
46
+ export type DataTableContext<Row extends DataTableRow = DataTableRow> = {
46
47
  batchSelectedIds: import("svelte/store").Writable<
47
48
  ReadonlyArray<DataTableRowId>
48
49
  >;
@@ -1,6 +1,7 @@
1
1
  import { SvelteComponentTyped } from "svelte";
2
2
 
3
3
  export type SectionLevel = 1 | 2 | 3 | 4 | 5 | 6;
4
+
4
5
  export type SectionContext = {
5
6
  $internalLevel: any;
6
7
  };
@@ -10,6 +10,7 @@ export type MultiSelectItem = {
10
10
  text: MultiSelectItemText;
11
11
  /** Whether the item is disabled */ disabled?: boolean;
12
12
  };
13
+
13
14
  export type MultiSelectContext = {
14
15
  declareRef: (data: {
15
16
  key: "field" | "selection";
@@ -1,7 +1,6 @@
1
1
  import { SvelteComponentTyped } from "svelte";
2
2
  import type { SvelteHTMLElements } from "svelte/elements";
3
3
 
4
- export type SelectValue = string | number;
5
4
  export type SelectContext = {
6
5
  selectedValue: import("svelte/store").Writable<string | number | undefined>;
7
6
  /** Use the first `SelectItem` value as the
@@ -48,7 +48,7 @@ export type ThemeProps = {
48
48
  * Override the default select props.
49
49
  * @default { themes: themeKeys, labelText: "Themes", hideLabel: false, }
50
50
  */
51
- select?: import("../Select/Select.svelte").SelectProps & {
51
+ select?: import("../Select/Select.svelte").SelectProps<CarbonTheme> & {
52
52
  themes?: CarbonTheme[];
53
53
  };
54
54
 
@@ -1,7 +1,7 @@
1
1
  import { SvelteComponentTyped } from "svelte";
2
2
  import type { SvelteHTMLElements } from "svelte/elements";
3
3
 
4
- export type SelectableTileGroupContext = {
4
+ export type SelectableTileGroupContext<T extends string = string> = {
5
5
  selectedValues: import("svelte/store").Writable<T[]>;
6
6
  groupName: import("svelte/store").Readable<string | undefined>;
7
7
  add: (data: { selected: boolean; value: T }) => void;
@@ -1,7 +1,7 @@
1
1
  import { SvelteComponentTyped } from "svelte";
2
2
  import type { SvelteHTMLElements } from "svelte/elements";
3
3
 
4
- export type TileGroupContext = {
4
+ export type TileGroupContext<T extends string = string> = {
5
5
  selectedValue: import("svelte/store").Writable<T | undefined>;
6
6
  groupName: import("svelte/store").Readable<string | undefined>;
7
7
  groupRequired: import("svelte/store").Readable<boolean | undefined>;
@@ -16,15 +16,16 @@ export type ShowNodeOptions = {
16
16
  /** Whether to select the node (default: true) */ select?: boolean;
17
17
  /** Whether to focus the node (default: true) */ focus?: boolean;
18
18
  };
19
- export type TreeViewContext = {
19
+
20
+ export type TreeViewContext<Node extends TreeNode = TreeNode> = {
20
21
  activeNodeId: import("svelte/store").Writable<TreeNodeId>;
21
22
  selectedNodeIds: import("svelte/store").Writable<ReadonlyArray<TreeNodeId>>;
22
23
  expandedNodeIds: import("svelte/store").Writable<ReadonlyArray<TreeNodeId>>;
23
- clickNode: (node: TreeNode) => void;
24
- selectNode: (node: TreeNode) => void;
25
- expandNode: (node: TreeNode, expanded: boolean) => void;
26
- focusNode: (node: TreeNode) => void;
27
- toggleNode: (node: TreeNode) => void;
24
+ clickNode: (node: Node) => void;
25
+ selectNode: (node: Node) => void;
26
+ expandNode: (node: Node, expanded: boolean) => void;
27
+ focusNode: (node: Node) => void;
28
+ toggleNode: (node: Node) => void;
28
29
  };
29
30
 
30
31
  type $RestProps = SvelteHTMLElements["ul"];
@@ -2,11 +2,11 @@ interface TruncateOptions {
2
2
  clamp?: "end" | "front";
3
3
  }
4
4
 
5
- export function TruncateAction(
5
+ export function truncate(
6
6
  node: HTMLElement,
7
7
  options?: TruncateOptions,
8
8
  ): {
9
9
  update: (options?: TruncateOptions) => void;
10
10
  };
11
11
 
12
- export default TruncateAction;
12
+ export default truncate;