@geoffcox/sterling-svelte 0.0.23 → 0.0.25

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/ListItem.svelte CHANGED
@@ -1,15 +1,18 @@
1
1
  <script>import { getContext } from "svelte";
2
2
  import { LIST_CONTEXT_KEY } from "./List.constants";
3
+ import { readable } from "svelte/store";
3
4
  export let disabled = false;
4
5
  export let value;
5
6
  const {
6
7
  disabled: listDisabled,
7
8
  selectedValue,
8
9
  horizontal
9
- } = getContext(LIST_CONTEXT_KEY);
10
+ } = getContext(LIST_CONTEXT_KEY) || {
11
+ disabled: readable(false),
12
+ selectedValue: void 0,
13
+ horizontal: false
14
+ };
10
15
  let itemRef;
11
- $:
12
- _disabled = disabled || $listDisabled;
13
16
  $:
14
17
  selected = $selectedValue === value;
15
18
  export const click = () => {
@@ -27,7 +30,8 @@ export const focus = (options) => {
27
30
  aria-selected={selected}
28
31
  bind:this={itemRef}
29
32
  class="sterling-list-item"
30
- class:disabled={_disabled}
33
+ class:disabled={disabled || $listDisabled}
34
+ class:item-disabled={disabled && !$listDisabled}
31
35
  class:selected
32
36
  data-value={value}
33
37
  role="listitem"
@@ -75,13 +79,14 @@ export const focus = (options) => {
75
79
  cursor: pointer;
76
80
  margin: 0;
77
81
  padding: 0.5em;
82
+ position: relative;
78
83
  outline: none;
79
84
  text-overflow: ellipsis;
80
85
  transition: background-color 250ms, color 250ms, border-color 250ms;
81
86
  white-space: nowrap;
82
87
  }
83
88
 
84
- .sterling-list-item:not(.disabled):hover {
89
+ .sterling-list-item:not(.disabled):not(.selected):hover {
85
90
  background-color: var(--stsv-Button__background-color--hover);
86
91
  color: var(--stsv-Button__color--hover);
87
92
  }
@@ -92,12 +97,30 @@ export const focus = (options) => {
92
97
  }
93
98
 
94
99
  .sterling-list-item.disabled {
95
- color: var(--stsv-Common__color--disabled);
96
100
  cursor: not-allowed;
101
+ outline: none;
102
+ }
103
+
104
+ .sterling-list-item::after {
105
+ background: var(--stsv-Disabled__background);
106
+ bottom: 0;
107
+ content: '';
108
+ left: 0;
109
+ opacity: 0;
110
+ position: absolute;
111
+ right: 0;
112
+ top: 0;
113
+ pointer-events: none;
114
+ transition: opacity 250ms;
115
+ }
116
+
117
+ .sterling-list-item.item-disabled::after {
118
+ opacity: 1;
97
119
  }
98
120
 
99
121
  @media (prefers-reduced-motion) {
100
- .sterling-list-item {
122
+ .sterling-list-item,
123
+ .sterling-list-item::after {
101
124
  transition: none;
102
125
  }
103
126
  }
package/MenuItem.svelte CHANGED
@@ -110,7 +110,7 @@ afterUpdate(() => {
110
110
  prevOpen = open;
111
111
  });
112
112
  const onKeyDown = (event) => {
113
- if (!event.altKey && !event.ctrlKey && !event.shiftKey) {
113
+ if (!disabled && !event.altKey && !event.ctrlKey && !event.shiftKey) {
114
114
  switch (event.key) {
115
115
  case "ArrowDown":
116
116
  if (depth === 0 && hasChildren) {
@@ -277,8 +277,11 @@ setContext(MENU_ITEM_CONTEXT_KEY, {
277
277
  >
278
278
  <div class="item" id={displayId}>
279
279
  <slot name="item" {checked} {depth} {disabled} {hasChildren} {open} {role} {text} {value}>
280
- <MenuItemDisplay {checked} hasChildren={depth > 0 && hasChildren} menuItemRole={role}
281
- >{text}</MenuItemDisplay
280
+ <MenuItemDisplay
281
+ {checked}
282
+ {disabled}
283
+ hasChildren={depth > 0 && hasChildren}
284
+ menuItemRole={role}>{text}</MenuItemDisplay
282
285
  >
283
286
  </slot>
284
287
  </div>
@@ -333,10 +336,6 @@ setContext(MENU_ITEM_CONTEXT_KEY, {
333
336
  background-color: var(--stsv-Input__background-color--selected);
334
337
  }
335
338
 
336
- .sterling-menu-item.disabled {
337
- color: var(--stsv-Common__color--disabled);
338
- }
339
-
340
339
  .sterling-menu-item.composed,
341
340
  .sterling-menu-item.composed:focus,
342
341
  .sterling-menu-item.composed:hover {
@@ -1,9 +1,10 @@
1
1
  <script>export let checked = false;
2
+ export let disabled = false;
2
3
  export let hasChildren = false;
3
4
  export let menuItemRole = "menuitem";
4
5
  </script>
5
6
 
6
- <div class="menu-item-display">
7
+ <div class="sterling-menu-item-display" class:disabled>
7
8
  <div
8
9
  class="check"
9
10
  class:checkmark={menuItemRole === 'menuitemcheckbox'}
@@ -23,7 +24,7 @@ export let menuItemRole = "menuitem";
23
24
  </div>
24
25
 
25
26
  <style>
26
- .menu-item-display {
27
+ .sterling-menu-item-display {
27
28
  align-items: center;
28
29
  justify-items: flex-start;
29
30
  display: grid;
@@ -94,4 +95,34 @@ export let menuItemRole = "menuitem";
94
95
  border-top: 3px solid currentColor;
95
96
  transform: translate(-50%, -50%) rotate(45deg);
96
97
  }
98
+
99
+ .sterling-menu-item-display.disabled {
100
+ cursor: not-allowed;
101
+ outline: none;
102
+ }
103
+
104
+ .sterling-menu-item-display::after {
105
+ background: var(--stsv-Disabled__background);
106
+ bottom: 0;
107
+ content: '';
108
+ left: 0;
109
+ opacity: 0;
110
+ position: absolute;
111
+ right: 0;
112
+ top: 0;
113
+ pointer-events: none;
114
+ transition: opacity 250ms;
115
+ }
116
+
117
+ .sterling-menu-item-display.disabled::after {
118
+ opacity: 1;
119
+ }
120
+
121
+ @media (prefers-reduced-motion) {
122
+ .sterling-menu-item-display::after,
123
+ .check,
124
+ .check::after {
125
+ transition: none;
126
+ }
127
+ }
97
128
  </style>
@@ -2,6 +2,7 @@ import { SvelteComponentTyped } from "svelte";
2
2
  declare const __propDef: {
3
3
  props: {
4
4
  checked?: boolean | undefined;
5
+ disabled?: boolean | undefined;
5
6
  hasChildren?: boolean | undefined;
6
7
  menuItemRole?: "menuitem" | "menuitemcheckbox" | "menuitemradio" | undefined;
7
8
  };
package/Popover.svelte ADDED
@@ -0,0 +1,135 @@
1
+ <script>import { onMount } from "svelte";
2
+ import { autoUpdate, computePosition, flip, offset, shift } from "@floating-ui/dom";
3
+ import { portal } from "./actions/portal";
4
+ export let placement = "bottom-start";
5
+ export let open = false;
6
+ export let reference;
7
+ export let portalHost = void 0;
8
+ let popupRef;
9
+ let popupPosition = { x: 0, y: 0 };
10
+ const hostId = "SterlingPopoverPortal";
11
+ const ensurePortalHost = () => {
12
+ if (portalHost) {
13
+ return portalHost;
14
+ }
15
+ let host = document.querySelector(`#${hostId}`);
16
+ if (!host) {
17
+ host = document.createElement("div");
18
+ host.id = hostId;
19
+ host.style.overflow = "visible";
20
+ document.body.append(host);
21
+ }
22
+ portalHost = host;
23
+ };
24
+ let bodyHeight = 0;
25
+ const resizeObserver = new ResizeObserver((entries) => {
26
+ bodyHeight = entries[0].target.clientHeight;
27
+ });
28
+ const middleware = [
29
+ offset({ mainAxis: -2 }),
30
+ flip(),
31
+ shift({ padding: 0, mainAxis: true, crossAxis: true })
32
+ ];
33
+ const computePopupPosition = async () => {
34
+ if (reference && popupRef) {
35
+ popupPosition = await computePosition(reference, popupRef, {
36
+ placement,
37
+ middleware
38
+ });
39
+ } else {
40
+ popupPosition = { x: 0, y: 0 };
41
+ }
42
+ };
43
+ let cleanupAutoUpdate = () => {
44
+ };
45
+ const autoUpdateMenuPosition = () => {
46
+ cleanupAutoUpdate();
47
+ if (reference && popupRef) {
48
+ cleanupAutoUpdate = autoUpdate(reference, popupRef, computePopupPosition);
49
+ }
50
+ };
51
+ $:
52
+ popupRef, reference, autoUpdateMenuPosition();
53
+ $:
54
+ open, bodyHeight, placement, computePopupPosition();
55
+ onMount(() => {
56
+ ensurePortalHost();
57
+ resizeObserver.observe(document.body);
58
+ return () => {
59
+ resizeObserver.unobserve(document.body);
60
+ };
61
+ });
62
+ </script>
63
+
64
+ <div use:portal={{ target: portalHost ?? document.body }} class="sterling-popover-portal">
65
+ <div
66
+ bind:this={popupRef}
67
+ class="sterling-popover"
68
+ class:open
69
+ on:blur
70
+ on:click
71
+ on:copy
72
+ on:cut
73
+ on:dblclick
74
+ on:dragend
75
+ on:dragenter
76
+ on:dragleave
77
+ on:dragover
78
+ on:dragstart
79
+ on:drop
80
+ on:focus
81
+ on:focusin
82
+ on:focusout
83
+ on:keydown
84
+ on:keypress
85
+ on:keyup
86
+ on:mousedown
87
+ on:mouseenter
88
+ on:mouseleave
89
+ on:mousemove
90
+ on:mouseover
91
+ on:mouseout
92
+ on:mouseup
93
+ on:scroll
94
+ on:wheel
95
+ on:paste
96
+ {...$$restProps}
97
+ style="left:{popupPosition.x}px; top:{popupPosition.y}px"
98
+ >
99
+ <slot />
100
+ </div>
101
+ </div>
102
+
103
+ <style>
104
+ .sterling-popover-portal {
105
+ position: relative;
106
+ overflow: visible;
107
+ background: rgba(255, 0, 0, 0.1);
108
+ }
109
+
110
+ .sterling-popover {
111
+ background-color: var(--stsv-Common__background-color);
112
+ border-color: var(--stsv-Common__border-color);
113
+ border-radius: var(--stsv-Common__border-radius);
114
+ border-style: var(--stsv-Common__border-style);
115
+ border-width: var(--stsv-Common__border-width);
116
+ box-shadow: rgba(0, 0, 0, 0.4) 2px 2px 4px -1px;
117
+ box-sizing: border-box;
118
+ display: none;
119
+ grid-template-columns: 1fr;
120
+ grid-template-rows: 1fr;
121
+ height: fit-content;
122
+ left: 0;
123
+ max-height: calc(50vh);
124
+ overflow: auto;
125
+ overscroll-behavior: contain;
126
+ position: absolute;
127
+ top: 0;
128
+ width: max-content;
129
+ z-index: 1;
130
+ }
131
+
132
+ .sterling-popover.open {
133
+ display: grid;
134
+ }
135
+ </style>
@@ -0,0 +1,51 @@
1
+ import { SvelteComponentTyped } from "svelte";
2
+ import type { Placement } from '@floating-ui/dom';
3
+ declare const __propDef: {
4
+ props: {
5
+ [x: string]: any;
6
+ placement?: Placement | undefined;
7
+ open?: boolean | undefined;
8
+ reference: HTMLElement;
9
+ portalHost?: HTMLElement | undefined;
10
+ };
11
+ events: {
12
+ blur: FocusEvent;
13
+ click: MouseEvent;
14
+ copy: ClipboardEvent;
15
+ cut: ClipboardEvent;
16
+ dblclick: MouseEvent;
17
+ dragend: DragEvent;
18
+ dragenter: DragEvent;
19
+ dragleave: DragEvent;
20
+ dragover: DragEvent;
21
+ dragstart: DragEvent;
22
+ drop: DragEvent;
23
+ focus: FocusEvent;
24
+ focusin: FocusEvent;
25
+ focusout: FocusEvent;
26
+ keydown: KeyboardEvent;
27
+ keypress: KeyboardEvent;
28
+ keyup: KeyboardEvent;
29
+ mousedown: MouseEvent;
30
+ mouseenter: MouseEvent;
31
+ mouseleave: MouseEvent;
32
+ mousemove: MouseEvent;
33
+ mouseover: MouseEvent;
34
+ mouseout: MouseEvent;
35
+ mouseup: MouseEvent;
36
+ scroll: Event;
37
+ wheel: WheelEvent;
38
+ paste: ClipboardEvent;
39
+ } & {
40
+ [evt: string]: CustomEvent<any>;
41
+ };
42
+ slots: {
43
+ default: {};
44
+ };
45
+ };
46
+ export type PopoverProps = typeof __propDef.props;
47
+ export type PopoverEvents = typeof __propDef.events;
48
+ export type PopoverSlots = typeof __propDef.slots;
49
+ export default class Popover extends SvelteComponentTyped<PopoverProps, PopoverEvents, PopoverSlots> {
50
+ }
51
+ export {};
package/Progress.svelte CHANGED
@@ -105,7 +105,6 @@ $:
105
105
  justify-content: flex-start;
106
106
  width: 100%;
107
107
  height: 100%;
108
- min-width: 100px;
109
108
  }
110
109
 
111
110
  .indicator {
@@ -129,7 +128,6 @@ $:
129
128
  flex-direction: column;
130
129
  justify-content: flex-end;
131
130
  min-width: unset;
132
- min-height: 100px;
133
131
  }
134
132
 
135
133
  .sterling-progress.vertical .indicator {
package/Radio.svelte CHANGED
@@ -1,54 +1,71 @@
1
- <script>import { onMount } from "svelte";
2
- import { idGenerator } from "./idGenerator";
1
+ <script>import { idGenerator } from "./idGenerator";
3
2
  import Label from "./Label.svelte";
4
3
  export let checked = false;
5
4
  export let disabled = false;
6
5
  export let group = void 0;
7
6
  export let id = void 0;
8
- let mounted = false;
9
- let radioRef;
7
+ if (checked && $$restProps.value !== group) {
8
+ group = $$restProps.value;
9
+ } else if (!checked && $$restProps.value === group) {
10
+ checked = true;
11
+ }
12
+ let inputRef;
13
+ let previousChecked = checked;
14
+ let previousGroup = group;
15
+ const reconcile = () => {
16
+ if (checked !== previousChecked) {
17
+ if (checked && $$restProps.value) {
18
+ group = $$restProps.value;
19
+ previousGroup = $$restProps.value;
20
+ }
21
+ previousChecked = checked;
22
+ } else if (group !== previousGroup) {
23
+ if ($$restProps.value) {
24
+ checked = $$restProps.value === group;
25
+ previousChecked = checked;
26
+ }
27
+ previousGroup = group;
28
+ }
29
+ };
30
+ $:
31
+ checked, group, $$restProps.value, reconcile();
10
32
  $: {
11
- if ($$slots.default && id === void 0) {
12
- id = idGenerator.nextId("Radio");
33
+ if (inputRef && checked && !inputRef.checked) {
34
+ inputRef.click();
13
35
  }
14
36
  }
15
37
  $: {
16
- if (mounted) {
17
- checked = group === $$restProps.value;
38
+ if ($$slots.default && id === void 0) {
39
+ id = idGenerator.nextId("Radio");
18
40
  }
19
41
  }
20
- const onChange = (e) => {
21
- if (e.currentTarget.checked) {
22
- group = $$restProps.value;
23
- }
24
- };
25
42
  export const blur = () => {
26
- radioRef?.blur();
43
+ inputRef?.blur();
27
44
  };
28
45
  export const click = () => {
29
- radioRef?.click();
46
+ inputRef?.click();
30
47
  };
31
48
  export const focus = (options) => {
32
- radioRef?.focus(options);
49
+ inputRef?.focus(options);
33
50
  };
34
- onMount(() => {
35
- if (checked) {
51
+ const onChange = (e) => {
52
+ if (e.currentTarget.checked) {
36
53
  group = $$restProps.value;
37
54
  }
38
- mounted = true;
39
- });
55
+ };
40
56
  </script>
41
57
 
42
58
  <!--
43
59
  @component
44
60
  A styled HTML input type=radio element with optional label.
45
61
  -->
46
- <div class="sterling-radio">
62
+ <div class="sterling-radio" class:disabled>
47
63
  <div class="container">
48
64
  <input
49
- bind:this={radioRef}
50
- checked={group === $$restProps.value}
65
+ bind:this={inputRef}
66
+ {checked}
51
67
  {disabled}
68
+ {group}
52
69
  {id}
53
70
  type="radio"
54
71
  on:blur
@@ -154,6 +171,11 @@ onMount(() => {
154
171
  border-color: var(--stsv-Input__border-color);
155
172
  }
156
173
 
174
+ .sterling-radio:not(.disabled):hover .indicator {
175
+ background-color: var(--stsv-Input__background-color--hover);
176
+ border-color: var(--stsv-Input__border-color--hover);
177
+ }
178
+
157
179
  input:focus-visible + .indicator {
158
180
  outline-color: var(--stsv-Common__outline-color);
159
181
  outline-offset: var(--stsv-Common__outline-offset);
@@ -161,11 +183,6 @@ onMount(() => {
161
183
  outline-width: var(--stsv-Common__outline-width);
162
184
  }
163
185
 
164
- input:disabled + .indicator {
165
- background-color: var(--stsv-Common__background-color--disabled);
166
- border-color: var(--stsv-Common__border-color--disabled);
167
- }
168
-
169
186
  .indicator::after {
170
187
  background-color: transparent;
171
188
  border-radius: 10000px;
@@ -183,13 +200,32 @@ onMount(() => {
183
200
  background-color: var(--stsv-Input__color);
184
201
  }
185
202
 
186
- input:checked:disabled + .indicator::after {
187
- background-color: var(--stsv-Common__color--disabled);
203
+ .sterling-radio.disabled * {
204
+ cursor: not-allowed;
205
+ }
206
+
207
+ .container::after {
208
+ background: var(--stsv-Disabled__background);
209
+ border-radius: 10000px;
210
+ bottom: 0;
211
+ content: '';
212
+ left: 0;
213
+ opacity: 0;
214
+ position: absolute;
215
+ right: 0;
216
+ top: 0;
217
+ pointer-events: none;
218
+ transition: opacity 250ms;
219
+ }
220
+
221
+ .sterling-radio.disabled .container::after {
222
+ opacity: 1;
188
223
  }
189
224
 
190
225
  @media (prefers-reduced-motion) {
191
226
  .indicator,
192
- .indicator::after {
227
+ .indicator::after,
228
+ .container::after {
193
229
  transition: none;
194
230
  }
195
231
  }