@cloudvoyant/helical-svelte 0.20.1 → 0.21.1

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 (39) hide show
  1. package/dist/Kbd.svelte +86 -0
  2. package/dist/Kbd.svelte.d.ts +10 -0
  3. package/dist/Page.svelte +28 -3
  4. package/dist/Page.svelte.d.ts +2 -1
  5. package/dist/PageContent.svelte +33 -4
  6. package/dist/PageContent.svelte.d.ts +2 -1
  7. package/dist/PageGutter.svelte +34 -3
  8. package/dist/PageGutter.svelte.d.ts +2 -1
  9. package/dist/PageSection.svelte +33 -4
  10. package/dist/PageSection.svelte.d.ts +2 -1
  11. package/dist/SplitterPanel.svelte +29 -3
  12. package/dist/SplitterPanel.svelte.d.ts +3 -1
  13. package/dist/index.d.ts +2 -0
  14. package/dist/index.js +2 -0
  15. package/dist/listbox/ListboxItemGroup.svelte +17 -0
  16. package/dist/listbox/ListboxItemGroup.svelte.d.ts +9 -0
  17. package/dist/listbox/ListboxItemGroupLabel.svelte +17 -0
  18. package/dist/listbox/ListboxItemGroupLabel.svelte.d.ts +9 -0
  19. package/dist/listbox/index.d.ts +2 -0
  20. package/dist/listbox/index.js +2 -0
  21. package/dist/sidebar/Root.svelte +34 -9
  22. package/dist/sidebar/Root.svelte.d.ts +2 -1
  23. package/dist/which-key/Pane.svelte +49 -0
  24. package/dist/which-key/Pane.svelte.d.ts +10 -0
  25. package/dist/which-key/WhichKey.svelte +197 -0
  26. package/dist/which-key/WhichKey.svelte.d.ts +8 -0
  27. package/dist/which-key/WhichKeyExplorer.svelte +269 -0
  28. package/dist/which-key/WhichKeyExplorer.svelte.d.ts +8 -0
  29. package/dist/which-key/WhichKeyMode.svelte +44 -0
  30. package/dist/which-key/WhichKeyMode.svelte.d.ts +9 -0
  31. package/dist/which-key/WhichKeyProvider.svelte +136 -0
  32. package/dist/which-key/WhichKeyProvider.svelte.d.ts +9 -0
  33. package/dist/which-key/context.svelte.d.ts +57 -0
  34. package/dist/which-key/context.svelte.js +177 -0
  35. package/dist/which-key/index.d.ts +7 -0
  36. package/dist/which-key/index.js +7 -0
  37. package/dist/window/Window.svelte +30 -4
  38. package/dist/window/Window.svelte.d.ts +2 -1
  39. package/package.json +5 -2
@@ -0,0 +1,86 @@
1
+ <!-- libs/helical-svelte/src/Kbd.svelte -->
2
+ <!-- Closely based on: @ark-ui/svelte/factory (Ark UI), mirrored from @cloudvoyant/helical-react -->
3
+ <script lang="ts">
4
+ import { Ark } from '@ark-ui/svelte/factory';
5
+ import {
6
+ cn,
7
+ formatKeyChord,
8
+ formatKeySequence,
9
+ kbdGroupBase,
10
+ kbdVariants,
11
+ type KbdProps as CoreKbdProps,
12
+ } from '@cloudvoyant/helical-ui';
13
+ import type { Snippet } from 'svelte';
14
+ import type { HTMLAttributes } from 'svelte/elements';
15
+
16
+ type Props = Omit<CoreKbdProps, 'className' | 'children'> & {
17
+ class?: string;
18
+ children?: Snippet;
19
+ } & HTMLAttributes<HTMLElement>;
20
+
21
+ let {
22
+ variant = 'outline',
23
+ size = 'md',
24
+ hotkey,
25
+ platform,
26
+ useSymbols = true,
27
+ class: className = '',
28
+ children,
29
+ ...rest
30
+ }: Props = $props();
31
+
32
+ const isMultiStep = $derived(
33
+ Boolean(
34
+ hotkey &&
35
+ !children &&
36
+ (Array.isArray(hotkey) || (typeof hotkey === 'string' && /\s+/.test(hotkey.trim()))),
37
+ ),
38
+ );
39
+ const steps = $derived(isMultiStep && hotkey ? formatKeySequence(hotkey, { platform, useSymbols }) : []);
40
+ const formattedChord = $derived(
41
+ hotkey && !children && !isMultiStep && typeof hotkey === 'string'
42
+ ? formatKeyChord(hotkey, { platform, useSymbols })
43
+ : null,
44
+ );
45
+ const itemClasses = $derived(cn(kbdVariants({ variant, size })));
46
+ const singleClasses = $derived(cn(kbdVariants({ variant, size }), className));
47
+ </script>
48
+
49
+ {#if isMultiStep}
50
+ <span data-slot="kbd-sequence" class={cn(kbdGroupBase, className)}>
51
+ {#each steps as step, idx (`${step}-${idx}`)}
52
+ <Ark
53
+ as="kbd"
54
+ data-slot="kbd"
55
+ data-variant={variant}
56
+ data-size={size}
57
+ class={itemClasses}
58
+ {...rest}
59
+ >
60
+ {step}
61
+ </Ark>
62
+ {/each}
63
+ </span>
64
+ {:else if formattedChord !== null}
65
+ <Ark
66
+ as="kbd"
67
+ data-slot="kbd"
68
+ data-variant={variant}
69
+ data-size={size}
70
+ class={singleClasses}
71
+ {...rest}
72
+ >
73
+ {formattedChord}
74
+ </Ark>
75
+ {:else}
76
+ <Ark
77
+ as="kbd"
78
+ data-slot="kbd"
79
+ data-variant={variant}
80
+ data-size={size}
81
+ class={singleClasses}
82
+ {...rest}
83
+ >
84
+ {@render children?.()}
85
+ </Ark>
86
+ {/if}
@@ -0,0 +1,10 @@
1
+ import { type KbdProps as CoreKbdProps } from '@cloudvoyant/helical-ui';
2
+ import type { Snippet } from 'svelte';
3
+ import type { HTMLAttributes } from 'svelte/elements';
4
+ type Props = Omit<CoreKbdProps, 'className' | 'children'> & {
5
+ class?: string;
6
+ children?: Snippet;
7
+ } & HTMLAttributes<HTMLElement>;
8
+ declare const Kbd: import("svelte").Component<Props, {}, "">;
9
+ type Kbd = ReturnType<typeof Kbd>;
10
+ export default Kbd;
package/dist/Page.svelte CHANGED
@@ -2,11 +2,12 @@
2
2
  <!-- No upstream component; composed from @cloudvoyant/helical-ui page classes, mirrored from @cloudvoyant/helical-react -->
3
3
  <script lang="ts">
4
4
  import { Ark } from '@ark-ui/svelte/factory';
5
- import { pageVariants, cn } from '@cloudvoyant/helical-ui';
5
+ import { pageVariants, cn, type PagePaneRegistrationProps } from '@cloudvoyant/helical-ui';
6
+ import { useOptionalPaneRegistration } from './which-key/context.svelte';
6
7
  import type { Snippet } from 'svelte';
7
8
  import type { HTMLAttributes } from 'svelte/elements';
8
9
 
9
- type Props = {
10
+ type Props = PagePaneRegistrationProps & {
10
11
  class?: string;
11
12
  variant?: 'default' | 'landing';
12
13
  children?: Snippet;
@@ -15,13 +16,37 @@
15
16
  let {
16
17
  class: className = '',
17
18
  variant = 'default',
19
+ paneId,
20
+ paneTitle,
21
+ paneDisabled,
22
+ paneOrder,
18
23
  children,
19
24
  ...rest
20
25
  }: Props = $props();
21
26
 
27
+ let pageRef: Element | null = $state(null);
28
+
29
+ const pane = useOptionalPaneRegistration(
30
+ () => (pageRef instanceof HTMLElement ? pageRef : null),
31
+ () => ({
32
+ paneId,
33
+ paneTitle,
34
+ paneDisabled: paneDisabled ?? !paneId,
35
+ paneOrder,
36
+ defaultTitle: 'Page',
37
+ }),
38
+ );
39
+
22
40
  const rootClasses = $derived(cn(pageVariants({ variant }), className));
23
41
  </script>
24
42
 
25
- <Ark as="div" data-slot="page" class={rootClasses} {...rest}>
43
+ <Ark
44
+ as="div"
45
+ bind:ref={pageRef}
46
+ data-slot="page"
47
+ {...pane.dataAttributes}
48
+ class={rootClasses}
49
+ {...rest}
50
+ >
26
51
  {@render children?.()}
27
52
  </Ark>
@@ -1,6 +1,7 @@
1
+ import { type PagePaneRegistrationProps } from '@cloudvoyant/helical-ui';
1
2
  import type { Snippet } from 'svelte';
2
3
  import type { HTMLAttributes } from 'svelte/elements';
3
- type Props = {
4
+ type Props = PagePaneRegistrationProps & {
4
5
  class?: string;
5
6
  variant?: 'default' | 'landing';
6
7
  children?: Snippet;
@@ -2,20 +2,49 @@
2
2
  <!-- No upstream component; composed from @cloudvoyant/helical-ui page classes, mirrored from @cloudvoyant/helical-react -->
3
3
  <script lang="ts">
4
4
  import { Ark } from '@ark-ui/svelte/factory';
5
- import { pageContentBase, cn } from '@cloudvoyant/helical-ui';
5
+ import { pageContentBase, cn, type PagePaneRegistrationProps } from '@cloudvoyant/helical-ui';
6
+ import { useOptionalPaneRegistration } from './which-key/context.svelte';
6
7
  import type { Snippet } from 'svelte';
7
8
  import type { HTMLAttributes } from 'svelte/elements';
8
9
 
9
- type Props = {
10
+ type Props = PagePaneRegistrationProps & {
10
11
  class?: string;
11
12
  children?: Snippet;
12
13
  } & HTMLAttributes<HTMLElement>;
13
14
 
14
- let { class: className = '', children, ...rest }: Props = $props();
15
+ let {
16
+ class: className = '',
17
+ paneId,
18
+ paneTitle,
19
+ paneDisabled,
20
+ paneOrder,
21
+ children,
22
+ ...rest
23
+ }: Props = $props();
24
+
25
+ let mainRef: Element | null = $state(null);
26
+
27
+ const pane = useOptionalPaneRegistration(
28
+ () => (mainRef instanceof HTMLElement ? mainRef : null),
29
+ () => ({
30
+ paneId,
31
+ paneTitle,
32
+ paneDisabled,
33
+ paneOrder,
34
+ defaultTitle: 'Main Content',
35
+ }),
36
+ );
15
37
 
16
38
  const classes = $derived(cn(pageContentBase, className));
17
39
  </script>
18
40
 
19
- <Ark as="main" data-slot="page-content" class={classes} {...rest}>
41
+ <Ark
42
+ as="main"
43
+ bind:ref={mainRef}
44
+ data-slot="page-content"
45
+ {...pane.dataAttributes}
46
+ class={classes}
47
+ {...rest}
48
+ >
20
49
  {@render children?.()}
21
50
  </Ark>
@@ -1,6 +1,7 @@
1
+ import { type PagePaneRegistrationProps } from '@cloudvoyant/helical-ui';
1
2
  import type { Snippet } from 'svelte';
2
3
  import type { HTMLAttributes } from 'svelte/elements';
3
- type Props = {
4
+ type Props = PagePaneRegistrationProps & {
4
5
  class?: string;
5
6
  children?: Snippet;
6
7
  } & HTMLAttributes<HTMLElement>;
@@ -2,11 +2,18 @@
2
2
  <!-- No upstream component; composed from @cloudvoyant/helical-ui page classes, mirrored from @cloudvoyant/helical-react -->
3
3
  <script lang="ts">
4
4
  import { Ark } from '@ark-ui/svelte/factory';
5
- import { pageGutterAreaBase, pageGutterVariants, pageGutterContentVariants, cn } from '@cloudvoyant/helical-ui';
5
+ import {
6
+ pageGutterAreaBase,
7
+ pageGutterVariants,
8
+ pageGutterContentVariants,
9
+ cn,
10
+ type PagePaneRegistrationProps,
11
+ } from '@cloudvoyant/helical-ui';
12
+ import { useOptionalPaneRegistration } from './which-key/context.svelte';
6
13
  import type { Snippet } from 'svelte';
7
14
  import type { HTMLAttributes } from 'svelte/elements';
8
15
 
9
- type Props = {
16
+ type Props = PagePaneRegistrationProps & {
10
17
  class?: string;
11
18
  contentClass?: string;
12
19
  side?: 'left' | 'right';
@@ -19,17 +26,41 @@
19
26
  contentClass = '',
20
27
  side = 'left',
21
28
  align = 'start',
29
+ paneId,
30
+ paneTitle,
31
+ paneDisabled,
32
+ paneOrder,
22
33
  children,
23
34
  ...rest
24
35
  }: Props = $props();
25
36
 
37
+ let gutterRef: Element | null = $state(null);
38
+
39
+ const pane = useOptionalPaneRegistration(
40
+ () => (gutterRef instanceof HTMLElement ? gutterRef : null),
41
+ () => ({
42
+ paneId,
43
+ paneTitle,
44
+ paneDisabled,
45
+ paneOrder,
46
+ defaultTitle: side === 'right' ? 'Right Gutter' : 'Left Gutter',
47
+ }),
48
+ );
49
+
26
50
  const areaClasses = $derived(cn(pageGutterAreaBase, side === 'right' && '[grid-area:right]'));
27
51
  const gutterClasses = $derived(cn(pageGutterVariants({ side }), className));
28
52
  const contentClasses = $derived(cn(pageGutterContentVariants({ align }), contentClass));
29
53
  </script>
30
54
 
31
55
  <div data-slot="page-gutter-area" class={areaClasses}>
32
- <Ark as="div" data-slot="page-gutter" class={gutterClasses} {...rest}>
56
+ <Ark
57
+ as="div"
58
+ bind:ref={gutterRef}
59
+ data-slot="page-gutter"
60
+ {...pane.dataAttributes}
61
+ class={gutterClasses}
62
+ {...rest}
63
+ >
33
64
  <div data-slot="page-gutter-content" class={contentClasses}>
34
65
  {@render children?.()}
35
66
  </div>
@@ -1,6 +1,7 @@
1
+ import { type PagePaneRegistrationProps } from '@cloudvoyant/helical-ui';
1
2
  import type { Snippet } from 'svelte';
2
3
  import type { HTMLAttributes } from 'svelte/elements';
3
- type Props = {
4
+ type Props = PagePaneRegistrationProps & {
4
5
  class?: string;
5
6
  contentClass?: string;
6
7
  side?: 'left' | 'right';
@@ -2,20 +2,49 @@
2
2
  <!-- No upstream component; composed from @cloudvoyant/helical-ui page classes, mirrored from @cloudvoyant/helical-react -->
3
3
  <script lang="ts">
4
4
  import { Ark } from '@ark-ui/svelte/factory';
5
- import { pageSectionBase, cn } from '@cloudvoyant/helical-ui';
5
+ import { pageSectionBase, cn, type PagePaneRegistrationProps } from '@cloudvoyant/helical-ui';
6
+ import { useOptionalPaneRegistration } from './which-key/context.svelte';
6
7
  import type { Snippet } from 'svelte';
7
8
  import type { HTMLAttributes } from 'svelte/elements';
8
9
 
9
- type Props = {
10
+ type Props = PagePaneRegistrationProps & {
10
11
  class?: string;
11
12
  children?: Snippet;
12
13
  } & HTMLAttributes<HTMLElement>;
13
14
 
14
- let { class: className = '', children, ...rest }: Props = $props();
15
+ let {
16
+ class: className = '',
17
+ paneId,
18
+ paneTitle,
19
+ paneDisabled,
20
+ paneOrder,
21
+ children,
22
+ ...rest
23
+ }: Props = $props();
24
+
25
+ let sectionRef: Element | null = $state(null);
26
+
27
+ const pane = useOptionalPaneRegistration(
28
+ () => (sectionRef instanceof HTMLElement ? sectionRef : null),
29
+ () => ({
30
+ paneId,
31
+ paneTitle,
32
+ paneDisabled: paneDisabled ?? !paneId,
33
+ paneOrder,
34
+ defaultTitle: 'Section',
35
+ }),
36
+ );
15
37
 
16
38
  const classes = $derived(cn(pageSectionBase, className));
17
39
  </script>
18
40
 
19
- <Ark as="section" data-slot="page-section" class={classes} {...rest}>
41
+ <Ark
42
+ as="section"
43
+ bind:ref={sectionRef}
44
+ data-slot="page-section"
45
+ {...pane.dataAttributes}
46
+ class={classes}
47
+ {...rest}
48
+ >
20
49
  {@render children?.()}
21
50
  </Ark>
@@ -1,6 +1,7 @@
1
+ import { type PagePaneRegistrationProps } from '@cloudvoyant/helical-ui';
1
2
  import type { Snippet } from 'svelte';
2
3
  import type { HTMLAttributes } from 'svelte/elements';
3
- type Props = {
4
+ type Props = PagePaneRegistrationProps & {
4
5
  class?: string;
5
6
  children?: Snippet;
6
7
  } & HTMLAttributes<HTMLElement>;
@@ -2,11 +2,37 @@
2
2
  <!-- Closely based on: @ark-ui/svelte/splitter (Ark UI), Chakra UI Splitter, mirrored from @cloudvoyant/helical-react -->
3
3
  <script lang="ts">
4
4
  import { SplitterPanel, type SplitterPanelProps } from '@ark-ui/svelte/splitter';
5
- import { splitterPanelBase, cn } from '@cloudvoyant/helical-ui';
5
+ import {
6
+ splitterPanelBase,
7
+ cn,
8
+ type SplitterPanelPaneRegistrationProps,
9
+ } from '@cloudvoyant/helical-ui';
10
+ import { useOptionalPaneRegistration } from './which-key/context.svelte';
6
11
 
7
- let { class: className = '', ...rest }: SplitterPanelProps = $props();
12
+ type Props = SplitterPanelProps & SplitterPanelPaneRegistrationProps;
13
+
14
+ let {
15
+ class: className = '',
16
+ id,
17
+ paneId,
18
+ paneTitle,
19
+ paneDisabled,
20
+ ...rest
21
+ }: Props = $props();
22
+
23
+ let panelRef: Element | null = $state(null);
24
+
25
+ const pane = useOptionalPaneRegistration(
26
+ () => (panelRef instanceof HTMLElement ? panelRef : null),
27
+ () => ({
28
+ paneId: paneId ?? (typeof id === 'string' ? `splitter-${id}` : undefined),
29
+ paneTitle: paneTitle ?? (typeof id === 'string' ? `Panel ${id}` : 'Splitter Panel'),
30
+ paneDisabled,
31
+ defaultTitle: 'Splitter Panel',
32
+ }),
33
+ );
8
34
 
9
35
  const classes = $derived(cn(splitterPanelBase, className));
10
36
  </script>
11
37
 
12
- <SplitterPanel class={classes} {...rest} />
38
+ <SplitterPanel bind:ref={panelRef} {id} {...pane.dataAttributes} class={classes} {...rest} />
@@ -1,4 +1,6 @@
1
1
  import { SplitterPanel, type SplitterPanelProps } from '@ark-ui/svelte/splitter';
2
- declare const SplitterPanel: import("svelte").Component<SplitterPanelProps, {}, "">;
2
+ import { type SplitterPanelPaneRegistrationProps } from '@cloudvoyant/helical-ui';
3
+ type Props = SplitterPanelProps & SplitterPanelPaneRegistrationProps;
4
+ declare const SplitterPanel: import("svelte").Component<Props, {}, "">;
3
5
  type SplitterPanel = ReturnType<typeof SplitterPanel>;
4
6
  export default SplitterPanel;
package/dist/index.d.ts CHANGED
@@ -59,3 +59,5 @@ export * from './prose';
59
59
  export * from './toggle-group';
60
60
  export * from './listbox';
61
61
  export * from './editor';
62
+ export { default as Kbd } from './Kbd.svelte';
63
+ export * from './which-key';
package/dist/index.js CHANGED
@@ -60,3 +60,5 @@ export * from './prose';
60
60
  export * from './toggle-group';
61
61
  export * from './listbox';
62
62
  export * from './editor';
63
+ export { default as Kbd } from './Kbd.svelte';
64
+ export * from './which-key';
@@ -0,0 +1,17 @@
1
+ <!-- libs/helical-svelte/src/listbox/ListboxItemGroup.svelte -->
2
+ <script lang="ts">
3
+ import { ListboxItemGroup, type ListboxItemGroupProps } from '@ark-ui/svelte/listbox';
4
+ import { listboxItemGroupBase, cn } from '@cloudvoyant/helical-ui';
5
+ import type { Snippet } from 'svelte';
6
+
7
+ type Props = ListboxItemGroupProps & {
8
+ class?: string;
9
+ children?: Snippet;
10
+ };
11
+
12
+ let { class: className = '', children, ...rest }: Props = $props();
13
+ </script>
14
+
15
+ <ListboxItemGroup class={cn(listboxItemGroupBase, className)} {...rest}>
16
+ {@render children?.()}
17
+ </ListboxItemGroup>
@@ -0,0 +1,9 @@
1
+ import { ListboxItemGroup, type ListboxItemGroupProps } from '@ark-ui/svelte/listbox';
2
+ import type { Snippet } from 'svelte';
3
+ type Props = ListboxItemGroupProps & {
4
+ class?: string;
5
+ children?: Snippet;
6
+ };
7
+ declare const ListboxItemGroup: import("svelte").Component<Props, {}, "">;
8
+ type ListboxItemGroup = ReturnType<typeof ListboxItemGroup>;
9
+ export default ListboxItemGroup;
@@ -0,0 +1,17 @@
1
+ <!-- libs/helical-svelte/src/listbox/ListboxItemGroupLabel.svelte -->
2
+ <script lang="ts">
3
+ import { ListboxItemGroupLabel, type ListboxItemGroupLabelProps } from '@ark-ui/svelte/listbox';
4
+ import { listboxItemGroupLabelBase, cn } from '@cloudvoyant/helical-ui';
5
+ import type { Snippet } from 'svelte';
6
+
7
+ type Props = ListboxItemGroupLabelProps & {
8
+ class?: string;
9
+ children?: Snippet;
10
+ };
11
+
12
+ let { class: className = '', children, ...rest }: Props = $props();
13
+ </script>
14
+
15
+ <ListboxItemGroupLabel class={cn(listboxItemGroupLabelBase, className)} {...rest}>
16
+ {@render children?.()}
17
+ </ListboxItemGroupLabel>
@@ -0,0 +1,9 @@
1
+ import { ListboxItemGroupLabel, type ListboxItemGroupLabelProps } from '@ark-ui/svelte/listbox';
2
+ import type { Snippet } from 'svelte';
3
+ type Props = ListboxItemGroupLabelProps & {
4
+ class?: string;
5
+ children?: Snippet;
6
+ };
7
+ declare const ListboxItemGroupLabel: import("svelte").Component<Props, {}, "">;
8
+ type ListboxItemGroupLabel = ReturnType<typeof ListboxItemGroupLabel>;
9
+ export default ListboxItemGroupLabel;
@@ -1,6 +1,8 @@
1
1
  export { default as Listbox } from './Listbox.svelte';
2
2
  export { default as ListboxContent } from './ListboxContent.svelte';
3
3
  export { default as ListboxItem } from './ListboxItem.svelte';
4
+ export { default as ListboxItemGroup } from './ListboxItemGroup.svelte';
5
+ export { default as ListboxItemGroupLabel } from './ListboxItemGroupLabel.svelte';
4
6
  export { default as ListboxItemText } from './ListboxItemText.svelte';
5
7
  export { default as ListboxItemIndicator } from './ListboxItemIndicator.svelte';
6
8
  export { default as ListboxInput } from './ListboxInput.svelte';
@@ -2,6 +2,8 @@
2
2
  export { default as Listbox } from './Listbox.svelte';
3
3
  export { default as ListboxContent } from './ListboxContent.svelte';
4
4
  export { default as ListboxItem } from './ListboxItem.svelte';
5
+ export { default as ListboxItemGroup } from './ListboxItemGroup.svelte';
6
+ export { default as ListboxItemGroupLabel } from './ListboxItemGroupLabel.svelte';
5
7
  export { default as ListboxItemText } from './ListboxItemText.svelte';
6
8
  export { default as ListboxItemIndicator } from './ListboxItemIndicator.svelte';
7
9
  export { default as ListboxInput } from './ListboxInput.svelte';
@@ -1,4 +1,4 @@
1
- <!-- libs/helical-svelte/src/Sidebar.svelte -->
1
+ <!-- libs/helical-svelte/src/sidebar/Root.svelte -->
2
2
  <!-- Source: @ark-ui/svelte/drawer (Ark UI), mirrored from @cloudvoyant/helical-react -->
3
3
  <script lang="ts">
4
4
  import {
@@ -18,13 +18,15 @@
18
18
  SIDEBAR_WIDGET_DEFAULT_SNAP_POINT,
19
19
  sidebarStyles,
20
20
  cn,
21
+ type SidebarPaneRegistrationProps,
21
22
  } from '@cloudvoyant/helical-ui';
22
23
  import Col from '../Col.svelte';
24
+ import { useOptionalPaneRegistration } from '../which-key/context.svelte';
23
25
  import { getSidebarContext } from './context.svelte';
24
26
  import type { Snippet } from 'svelte';
25
27
  import type { HTMLAttributes } from 'svelte/elements';
26
28
 
27
- type Props = {
29
+ type Props = SidebarPaneRegistrationProps & {
28
30
  side?: 'left' | 'right';
29
31
  variant?: 'sidebar' | 'floating' | 'inset';
30
32
  collapsible?: 'offcanvas' | 'icon' | 'none';
@@ -36,13 +38,16 @@
36
38
  side = 'left',
37
39
  variant = 'sidebar',
38
40
  collapsible = 'offcanvas',
41
+ paneId,
42
+ paneTitle,
43
+ paneDisabled,
39
44
  class: className = '',
40
45
  children,
41
46
  ...rest
42
47
  }: Props = $props();
43
48
 
44
49
  const sidebar = getSidebarContext();
45
- const state = $derived(sidebar.state);
50
+ const sidebarState = $derived(sidebar.state);
46
51
  const isMobile = $derived(sidebar.isMobile);
47
52
  const open = $derived(sidebar.open);
48
53
  const setOpen = sidebar.setOpen;
@@ -57,6 +62,18 @@
57
62
  const defaultSnapPoint = $derived(isBottomWidgetSheet ? SIDEBAR_WIDGET_DEFAULT_SNAP_POINT : undefined);
58
63
  const snapToSequentialPoints = $derived(isBottomWidgetSheet);
59
64
 
65
+ let containerRef: HTMLDivElement | null = $state(null);
66
+
67
+ const pane = useOptionalPaneRegistration(
68
+ () => containerRef,
69
+ () => ({
70
+ paneId,
71
+ paneTitle,
72
+ paneDisabled: paneDisabled || sidebarState === 'collapsed',
73
+ defaultTitle: 'Sidebar',
74
+ }),
75
+ );
76
+
60
77
  const containerClasses = $derived(
61
78
  cn(
62
79
  sidebarStyles.containerClass,
@@ -82,14 +99,16 @@
82
99
  </script>
83
100
 
84
101
  {#if collapsible === 'none'}
85
- <Col
102
+ <div
103
+ bind:this={containerRef}
86
104
  data-slot="sidebar"
87
105
  data-sidebar="sidebar"
88
- class={cn('h-full w-(--sidebar-width) bg-sidebar text-sidebar-foreground', className)}
106
+ {...pane.dataAttributes}
107
+ class={cn('flex flex-col h-full w-(--sidebar-width) bg-sidebar text-sidebar-foreground', className)}
89
108
  {...rest}
90
109
  >
91
110
  {@render children?.()}
92
- </Col>
111
+ </div>
93
112
  {:else if isMobile}
94
113
  <DrawerRoot
95
114
  open={mobileSheetOpen}
@@ -130,14 +149,20 @@
130
149
  {:else}
131
150
  <div
132
151
  class="group peer hidden text-sidebar-foreground md:block"
133
- data-state={state}
134
- data-collapsible={state === 'collapsed' ? collapsible : ''}
152
+ data-state={sidebarState}
153
+ data-collapsible={sidebarState === 'collapsed' ? collapsible : ''}
135
154
  data-variant={variant}
136
155
  data-side={side}
137
156
  data-slot="sidebar"
138
157
  >
139
158
  <div data-slot="sidebar-gap" class={gapClasses}></div>
140
- <div data-slot="sidebar-container" class={containerClasses} {...rest}>
159
+ <div
160
+ bind:this={containerRef}
161
+ data-slot="sidebar-container"
162
+ {...pane.dataAttributes}
163
+ class={containerClasses}
164
+ {...rest}
165
+ >
141
166
  <Col data-sidebar="sidebar" data-slot="sidebar-inner" data-variant={variant} class={cn(sidebarStyles.innerClass)}>
142
167
  {@render children?.()}
143
168
  </Col>
@@ -1,6 +1,7 @@
1
+ import { type SidebarPaneRegistrationProps } from '@cloudvoyant/helical-ui';
1
2
  import type { Snippet } from 'svelte';
2
3
  import type { HTMLAttributes } from 'svelte/elements';
3
- type Props = {
4
+ type Props = SidebarPaneRegistrationProps & {
4
5
  side?: 'left' | 'right';
5
6
  variant?: 'sidebar' | 'floating' | 'inset';
6
7
  collapsible?: 'offcanvas' | 'icon' | 'none';
@@ -0,0 +1,49 @@
1
+ <!-- libs/helical-svelte/src/which-key/Pane.svelte -->
2
+ <script lang="ts">
3
+ import { Ark } from '@ark-ui/svelte/factory';
4
+ import { cn, paneVariants, type PaneProps as CorePaneProps } from '@cloudvoyant/helical-ui';
5
+ import { useOptionalPaneRegistration } from './context.svelte';
6
+ import type { Snippet } from 'svelte';
7
+ import type { HTMLAttributes } from 'svelte/elements';
8
+
9
+ type Props = Omit<CorePaneProps, 'className' | 'children'> & {
10
+ class?: string;
11
+ children?: Snippet;
12
+ } & HTMLAttributes<HTMLDivElement>;
13
+
14
+ let {
15
+ paneId,
16
+ paneTitle = 'Pane',
17
+ paneDisabled = false,
18
+ paneOrder,
19
+ class: className = '',
20
+ children,
21
+ ...rest
22
+ }: Props = $props();
23
+
24
+ let elementRef: Element | null = $state(null);
25
+
26
+ const pane = useOptionalPaneRegistration(
27
+ () => (elementRef instanceof HTMLElement ? elementRef : null),
28
+ () => ({
29
+ paneId,
30
+ paneTitle,
31
+ paneDisabled,
32
+ paneOrder,
33
+ defaultTitle: paneTitle,
34
+ }),
35
+ );
36
+
37
+ const classes = $derived(cn(paneVariants({ active: pane.isActive }), className));
38
+ </script>
39
+
40
+ <Ark
41
+ as="div"
42
+ bind:ref={elementRef}
43
+ data-slot="pane"
44
+ {...pane.dataAttributes}
45
+ class={classes}
46
+ {...rest}
47
+ >
48
+ {@render children?.()}
49
+ </Ark>