@txstate-mws/svelte-components 1.3.0 → 1.3.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/actions/glue.d.ts CHANGED
@@ -11,6 +11,6 @@ export interface GlueAlignStore {
11
11
  halign: 'left' | 'right';
12
12
  }
13
13
  export declare function glue(el: HTMLElement, { target, align, cover, store }: GlueArgs): {
14
- update({ target, align, cover, store }: GlueArgs): void;
14
+ update({ target: utarget, align: ualign, cover: ucover, store: ustore }: GlueArgs): void;
15
15
  destroy: () => void;
16
16
  };
@@ -1,4 +1,5 @@
1
1
  <script context="module">const FocusLockStack = [];
2
+ const waitAtick = typeof requestAnimationFrame !== 'undefined' ? resolve => requestAnimationFrame(resolve) : resolve => resolve(0);
2
3
  </script>
3
4
 
4
5
  <script>export let returnfocusto = undefined;
@@ -16,8 +17,7 @@ import ScreenReaderOnly from './ScreenReaderOnly.svelte';
16
17
  const dispatch = createEventDispatcher();
17
18
  let lockelement;
18
19
  let abovelockelement;
19
- let active = true;
20
- let listenforescape = false;
20
+ let state = 'init';
21
21
  if (initialfocus)
22
22
  hidefocus = false;
23
23
  onMount(async () => {
@@ -25,8 +25,9 @@ onMount(async () => {
25
25
  if (prevFocusLock)
26
26
  prevFocusLock.pause();
27
27
  FocusLockStack.push({
28
- pause: () => { active = false; },
29
- unpause: () => { active = true; }
28
+ pause: () => { state = 'paused'; },
29
+ unpause: () => { if (state === 'paused')
30
+ state = 'active'; }
30
31
  });
31
32
  if (typeof returnfocusto === 'undefined') {
32
33
  returnfocusto = document.querySelector(':focus');
@@ -42,12 +43,17 @@ onMount(async () => {
42
43
  else {
43
44
  setInitialFocus();
44
45
  }
45
- setTimeout(() => { listenforescape = true; }, 0);
46
+ setTimeout(() => { state = 'active'; }, 0);
46
47
  });
47
48
  onDestroy(async () => {
48
- const wasactive = active;
49
- active = false;
50
- await tick();
49
+ const wasactive = state !== 'paused';
50
+ state = 'destroyed';
51
+ // we need to allow the screen to redraw so that we can
52
+ // change focus back to where it was, and we need
53
+ // to allow the click event that destroyed us to finish bubbling
54
+ // before we unpause the next focuslock in the stack or else it
55
+ // will think it was an "outside" click and kill itself
56
+ await new Promise(waitAtick);
51
57
  if (returnfocusto && wasactive) {
52
58
  returnfocusto.focus();
53
59
  }
@@ -69,13 +75,13 @@ const setLastFocus = () => {
69
75
  }
70
76
  };
71
77
  const keydown = (e) => {
72
- if (active && e.key === 'Escape' && escapable) {
78
+ if (state === 'active' && e.key === 'Escape' && escapable) {
73
79
  e.preventDefault();
74
80
  dispatch('escape');
75
81
  }
76
82
  };
77
83
  const focusin = (e) => {
78
- if (active && e.target instanceof HTMLElement && !lockelement?.contains(e.target)) {
84
+ if (state === 'active' && e.target instanceof HTMLElement && !lockelement?.contains(e.target)) {
79
85
  if (e.target === abovelockelement)
80
86
  setLastFocus();
81
87
  else
@@ -83,7 +89,7 @@ const focusin = (e) => {
83
89
  }
84
90
  };
85
91
  const windowclick = (_) => {
86
- if (listenforescape && active) {
92
+ if (state === 'active') {
87
93
  returnfocusto = undefined;
88
94
  dispatch('escape');
89
95
  }
@@ -91,11 +97,14 @@ const windowclick = (_) => {
91
97
  </script>
92
98
  <svelte:window on:click={windowclick} />
93
99
  <div class={className} role="alertdialog" aria-modal="true" on:click|stopPropagation on:keydown|stopPropagation={keydown} on:focusin={focusin}>
100
+ <!-- svelte-ignore a11y-no-noninteractive-tabindex -->
94
101
  <div bind:this={abovelockelement} tabindex="0"></div>
95
102
  <div bind:this={lockelement} on:keydown={keydown}>
103
+ <!-- svelte-ignore a11y-click-events-have-key-events -->
96
104
  {#if hidefocus}<div class="hiddenfocus" use:buttonify on:blur={() => { hidefocus = false }} on:click={() => escapable && dispatch('escape')}><ScreenReaderOnly>{hidefocuslabel}{#if escapable}, click to escape or use escape key at any time{/if}</ScreenReaderOnly></div>{/if}
97
105
  <slot></slot>
98
106
  </div>
107
+ <!-- svelte-ignore a11y-no-noninteractive-tabindex -->
99
108
  <div tabindex="0"></div>
100
109
  </div>
101
110
 
@@ -23,6 +23,7 @@ onMount(() => {
23
23
  });
24
24
  </script>
25
25
 
26
+ <!-- svelte-ignore a11y-click-events-have-key-events -->
26
27
  <div use:portal={usePortal} class="modal-backdrop" class:opaque on:click|stopPropagation|preventDefault={() => escapable && endmodal()}>
27
28
  <FocusLock class="modal-container {containerClass}" {escapable} on:escape {hidefocus} {hidefocuslabel} {returnfocusto} {initialfocus}>
28
29
  <slot></slot>
@@ -104,6 +104,7 @@ $: dispatch('change', selected);
104
104
  <fieldset>
105
105
  <ul class="multiselect-selected" class:disabled role="listbox">
106
106
  {#each selected as option, i}
107
+ <!-- svelte-ignore a11y-click-events-have-key-events -->
107
108
  <li id={id + option.value} role="option" tabindex="-1" class="multiselect-pill" class:hilited={hilitedpill === option.value}
108
109
  on:click|preventDefault|stopPropagation={() => !disabled && removeSelection(option, i, 1)} on:mousedown={e => disabled && e.preventDefault()}
109
110
  aria-selected="true">
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@txstate-mws/svelte-components",
3
- "version": "1.3.0",
3
+ "version": "1.3.2",
4
4
  "description": "Svelte components that are generically useful.",
5
5
  "dependencies": {
6
6
  "@txstate-mws/svelte-store": "^1.0.3",