@geoffcox/sterling-svelte 2.0.11 → 2.0.12

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.
@@ -0,0 +1,186 @@
1
+ <script lang="ts">
2
+ import type { KeyboardEventHandler, PointerEventHandler } from 'svelte/elements';
3
+ import type { SplitterProps } from './Splitter.types';
4
+
5
+ const constrainPercent = (value: number) => {
6
+ return Math.max(0.0, Math.min(value, 100.0));
7
+ };
8
+
9
+ let {
10
+ horizontal,
11
+ initialPrimarySize,
12
+ minPrimarySize,
13
+ minSecondarySize,
14
+ resetOnDoubleClick,
15
+ primary,
16
+ split,
17
+ secondary,
18
+ change
19
+ }: SplitterProps = $props();
20
+
21
+ let clientWidth: number | undefined = $state();
22
+ let clientHeight: number | undefined = $state();
23
+ let primaryClientWidth: number | undefined = $state();
24
+ let primaryClientHeight: number | undefined = $state();
25
+ let splitterClientWidth: number | undefined = $state();
26
+ let splitterClientHeight: number | undefined = $state();
27
+ let secondaryClientWidth: number | undefined = $state();
28
+ let secondaryClientHeight: number | undefined = $state();
29
+
30
+ let clientSize = $derived(horizontal ? clientHeight : clientWidth);
31
+ let primaryClientSize = $derived(horizontal ? primaryClientHeight : primaryClientWidth);
32
+ let splitterClientSize = $derived(horizontal ? splitterClientHeight : splitterClientWidth);
33
+ let secondaryClientSize = $derived(horizontal ? secondaryClientHeight : secondaryClientWidth);
34
+
35
+ let percent: number | undefined = $state();
36
+
37
+ let measuredPercent = $derived.by(() => {
38
+ if (primaryClientSize && splitterClientSize && clientSize) {
39
+ return constrainPercent(
40
+ Math.ceil(
41
+ ((primaryClientSize - splitterClientSize) / (clientSize - splitterClientSize)) * 100
42
+ )
43
+ );
44
+ }
45
+ return 0;
46
+ });
47
+
48
+ let startPosition: number | undefined = $state();
49
+ let startPrimarySize: number | undefined = $state();
50
+ let dragging: boolean = $state(false);
51
+
52
+ let primarySize = $derived(percent !== undefined ? `${percent}%` : initialPrimarySize);
53
+
54
+ let splitCssVars = $derived({
55
+ '--primary-size': `${primarySize || '50%'}`,
56
+ '--min-primary-size': `${minPrimarySize || 0}`,
57
+ '--min-secondary-size': `${minSecondarySize || 0}`
58
+ });
59
+
60
+ let splitStyle = $derived(
61
+ Object.entries(splitCssVars)
62
+ .map(([key, value]) => `${key}:${value}`)
63
+ .join(';')
64
+ );
65
+
66
+ $effect(() => {
67
+ change?.({
68
+ percent: measuredPercent,
69
+ primarySize: primaryClientSize,
70
+ secondarySize: secondaryClientSize,
71
+ dragging
72
+ });
73
+ });
74
+
75
+ $effect(() => {
76
+ if (initialPrimarySize) {
77
+ percent = undefined;
78
+ }
79
+ });
80
+
81
+ const onPointerDown: PointerEventHandler<HTMLDivElement> = (event) => {
82
+ event.currentTarget.setPointerCapture(event.pointerId);
83
+ startPosition = horizontal ? event.clientY : event.clientX;
84
+ startPrimarySize = primaryClientSize;
85
+ dragging = true;
86
+ };
87
+
88
+ const onPointerMove: PointerEventHandler<HTMLDivElement> = (event) => {
89
+ if (
90
+ event.currentTarget.hasPointerCapture(event.pointerId) &&
91
+ startPosition !== undefined &&
92
+ startPrimarySize !== undefined &&
93
+ clientSize !== undefined &&
94
+ splitterClientSize !== undefined
95
+ ) {
96
+ const position = horizontal ? event.clientY : event.clientX;
97
+ let newPrimarySize = startPrimarySize + (position - startPosition);
98
+ newPrimarySize = Math.max(0, Math.min(newPrimarySize, clientSize - splitterClientSize));
99
+ const newPercent = (newPrimarySize / clientSize) * 100;
100
+ percent = newPercent;
101
+ }
102
+ };
103
+
104
+ const onPointerUp: PointerEventHandler<HTMLDivElement> = (event) => {
105
+ event.currentTarget.releasePointerCapture(event.pointerId);
106
+ startPosition = undefined;
107
+ startPrimarySize = undefined;
108
+ dragging = false;
109
+ };
110
+
111
+ const onDoubleClick = () => {
112
+ resetOnDoubleClick && (percent = undefined);
113
+ };
114
+
115
+ const onKeyDown: KeyboardEventHandler<HTMLDivElement> = (event) => {
116
+ const origPercent = percent || measuredPercent;
117
+
118
+ // only move for vanilla keys
119
+ if (!event.ctrlKey && !event.shiftKey && !event.altKey) {
120
+ switch (event.code) {
121
+ case 'Space':
122
+ percent = undefined;
123
+ return;
124
+ }
125
+
126
+ if (horizontal) {
127
+ switch (event.code) {
128
+ case 'ArrowUp':
129
+ percent = constrainPercent(origPercent - 1);
130
+ return;
131
+ case 'ArrowDown':
132
+ percent = constrainPercent(origPercent + 1);
133
+ return;
134
+ }
135
+ } else {
136
+ switch (event.code) {
137
+ case 'ArrowLeft':
138
+ percent = constrainPercent(origPercent - 1);
139
+ return;
140
+ case 'ArrowRight':
141
+ percent = constrainPercent(origPercent + 1);
142
+ return;
143
+ }
144
+ }
145
+ }
146
+ };
147
+ </script>
148
+
149
+ <div
150
+ class={['sterling-splitter', horizontal ? 'horizontal' : 'vertical']}
151
+ bind:clientWidth
152
+ bind:clientHeight
153
+ style={splitStyle}
154
+ >
155
+ <div
156
+ class="primary"
157
+ bind:clientWidth={primaryClientWidth}
158
+ bind:clientHeight={primaryClientHeight}
159
+ >
160
+ {@render primary?.()}
161
+ </div>
162
+ <!-- svelte-ignore a11y_no_static_element_interactions -->
163
+ <div
164
+ class="split"
165
+ bind:clientWidth={splitterClientWidth}
166
+ bind:clientHeight={splitterClientHeight}
167
+ onpointerdown={onPointerDown}
168
+ onpointermove={onPointerMove}
169
+ onpointerup={onPointerUp}
170
+ ondblclick={onDoubleClick}
171
+ onkeydown={onKeyDown}
172
+ >
173
+ {#if split}
174
+ {@render split()}
175
+ {:else}
176
+ <div class="default-split-line"></div>
177
+ {/if}
178
+ </div>
179
+ <div
180
+ class="secondary"
181
+ bind:clientWidth={secondaryClientWidth}
182
+ bind:clientHeight={secondaryClientHeight}
183
+ >
184
+ {@render secondary?.()}
185
+ </div>
186
+ </div>
@@ -0,0 +1,4 @@
1
+ import type { SplitterProps } from './Splitter.types';
2
+ declare const Splitter: import("svelte").Component<SplitterProps, {}, "">;
3
+ type Splitter = ReturnType<typeof Splitter>;
4
+ export default Splitter;
@@ -0,0 +1,20 @@
1
+ import type { Snippet } from 'svelte';
2
+ import type { HTMLAttributes } from 'svelte/elements';
3
+ type SplitterChangeArgs = {
4
+ percent?: number;
5
+ primarySize?: number;
6
+ secondarySize?: number;
7
+ dragging?: boolean;
8
+ };
9
+ export type SplitterProps = HTMLAttributes<HTMLDivElement> & {
10
+ horizontal?: boolean | null;
11
+ initialPrimarySize?: string;
12
+ minPrimarySize?: string;
13
+ minSecondarySize?: string;
14
+ resetOnDoubleClick?: boolean | null;
15
+ primary?: Snippet;
16
+ split?: Snippet;
17
+ secondary?: Snippet;
18
+ change?: (value: SplitterChangeArgs) => void;
19
+ };
20
+ export {};
@@ -0,0 +1 @@
1
+ export {};
package/dist/index.d.ts CHANGED
@@ -42,6 +42,7 @@ export type { ProgressOrientation, ProgressProps } from './Progress.types';
42
42
  export type { RadioProps } from './Radio.types';
43
43
  export type { SelectProps } from './Select.types';
44
44
  export type { SliderProps } from './Slider.types';
45
+ export type { SplitterProps } from './Splitter.types';
45
46
  export type { SwitchProps } from './Switch.types';
46
47
  export type { TabListContext, TabListProps } from './TabList.types';
47
48
  export type { TabProps } from './Tab.types';
@@ -72,6 +73,7 @@ import Progress from './Progress.svelte';
72
73
  import Radio from './Radio.svelte';
73
74
  import Select from './Select.svelte';
74
75
  import Slider from './Slider.svelte';
76
+ import Splitter from './Splitter.svelte';
75
77
  import Switch from './Switch.svelte';
76
78
  import Tab from './Tab.svelte';
77
79
  import TabList from './TabList.svelte';
@@ -80,4 +82,4 @@ import Tooltip from './Tooltip.svelte';
80
82
  import Tree from './Tree.svelte';
81
83
  import TreeChevron from './TreeChevron.svelte';
82
84
  import TreeItem from './TreeItem.svelte';
83
- export { Autocomplete, Button, Callout, Checkbox, Dialog, Dropdown, Input, Label, Link, List, ListItem, Menu, MenuBar, MenuButton, MenuItem, MenuSeparator, Pagination, Popover, Progress, Radio, Select, Slider, Switch, Tab, TabList, TextArea, Tooltip, Tree, TreeChevron, TreeItem };
85
+ export { Autocomplete, Button, Callout, Checkbox, Dialog, Dropdown, Input, Label, Link, List, ListItem, Menu, MenuBar, MenuButton, MenuItem, MenuSeparator, Pagination, Popover, Progress, Radio, Select, Slider, Splitter, Switch, Tab, TabList, TextArea, Tooltip, Tree, TreeChevron, TreeItem };
package/dist/index.js CHANGED
@@ -46,6 +46,7 @@ import Progress from './Progress.svelte';
46
46
  import Radio from './Radio.svelte';
47
47
  import Select from './Select.svelte';
48
48
  import Slider from './Slider.svelte';
49
+ import Splitter from './Splitter.svelte';
49
50
  import Switch from './Switch.svelte';
50
51
  import Tab from './Tab.svelte';
51
52
  import TabList from './TabList.svelte';
@@ -54,4 +55,4 @@ import Tooltip from './Tooltip.svelte';
54
55
  import Tree from './Tree.svelte';
55
56
  import TreeChevron from './TreeChevron.svelte';
56
57
  import TreeItem from './TreeItem.svelte';
57
- export { Autocomplete, Button, Callout, Checkbox, Dialog, Dropdown, Input, Label, Link, List, ListItem, Menu, MenuBar, MenuButton, MenuItem, MenuSeparator, Pagination, Popover, Progress, Radio, Select, Slider, Switch, Tab, TabList, TextArea, Tooltip, Tree, TreeChevron, TreeItem };
58
+ export { Autocomplete, Button, Callout, Checkbox, Dialog, Dropdown, Input, Label, Link, List, ListItem, Menu, MenuBar, MenuButton, MenuItem, MenuSeparator, Pagination, Popover, Progress, Radio, Select, Slider, Splitter, Switch, Tab, TabList, TextArea, Tooltip, Tree, TreeChevron, TreeItem };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@geoffcox/sterling-svelte",
3
- "version": "2.0.11",
3
+ "version": "2.0.12",
4
4
  "author": "Geoff Cox",
5
5
  "description": "A modern, accessible, and lightweight component library for Svelte.",
6
6
  "license": "MIT",
@@ -74,7 +74,7 @@
74
74
  "@eslint/js": "^9.18.0",
75
75
  "@fontsource/atkinson-hyperlegible": "^5.1.1",
76
76
  "@fontsource/source-code-pro": "^4.5.14",
77
- "@geoffcox/sterling-svelte-themes": "^2.0.4",
77
+ "@geoffcox/sterling-svelte-themes": "^2.0.7",
78
78
  "@sveltejs/adapter-static": "^3.0.8",
79
79
  "@sveltejs/kit": "^2.16.0",
80
80
  "@sveltejs/package": "^2.0.0",