@txstate-mws/svelte-components 1.1.0 → 1.1.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 (131) hide show
  1. package/actions/buttonify.d.ts +8 -0
  2. package/actions/buttonify.js +26 -0
  3. package/actions/glue.d.ts +16 -0
  4. package/actions/glue.js +82 -0
  5. package/actions/index.d.ts +7 -0
  6. package/actions/index.js +7 -0
  7. package/actions/offset.d.ts +15 -0
  8. package/actions/offset.js +35 -0
  9. package/actions/portal.d.ts +4 -0
  10. package/actions/portal.js +13 -0
  11. package/actions/resize.d.ts +20 -0
  12. package/actions/resize.js +57 -0
  13. package/actions/sticky.d.ts +33 -0
  14. package/actions/sticky.js +85 -0
  15. package/actions/stickyfixed.d.ts +25 -0
  16. package/actions/stickyfixed.js +157 -0
  17. package/components/Card.svelte +23 -0
  18. package/components/Card.svelte.d.ts +18 -0
  19. package/components/CardLayout.svelte +197 -0
  20. package/components/CardLayout.svelte.d.ts +21 -0
  21. package/{src/lib/components → components}/CollapsingTable.svelte +63 -65
  22. package/components/CollapsingTable.svelte.d.ts +59 -0
  23. package/{src/lib/components → components}/ConditionalWrapper.svelte +6 -7
  24. package/components/ConditionalWrapper.svelte.d.ts +23 -0
  25. package/components/FocusLock.svelte +107 -0
  26. package/components/FocusLock.svelte.d.ts +26 -0
  27. package/{src/lib/components → components}/Modal.svelte +22 -24
  28. package/components/Modal.svelte.d.ts +27 -0
  29. package/components/MultiSelect.svelte +179 -0
  30. package/components/MultiSelect.svelte.d.ts +35 -0
  31. package/components/PopupMenu.svelte +287 -0
  32. package/components/PopupMenu.svelte.d.ts +45 -0
  33. package/{src/lib/components → components}/ScreenReaderOnly.svelte +3 -4
  34. package/components/ScreenReaderOnly.svelte.d.ts +20 -0
  35. package/components/index.d.ts +9 -0
  36. package/components/index.js +9 -0
  37. package/index.d.ts +4 -0
  38. package/index.js +4 -0
  39. package/package.json +34 -13
  40. package/types/CardLayout.d.ts +14 -0
  41. package/types/CardLayout.js +1 -0
  42. package/types/CollapsingTable.d.ts +8 -0
  43. package/types/CollapsingTable.js +1 -0
  44. package/types/PopupMenu.d.ts +5 -0
  45. package/types/PopupMenu.js +1 -0
  46. package/types/index.d.ts +3 -0
  47. package/types/index.js +3 -0
  48. package/util/bodyoffset.d.ts +14 -0
  49. package/util/bodyoffset.js +72 -0
  50. package/util/index.d.ts +3 -0
  51. package/util/index.js +3 -0
  52. package/util/repositioned.d.ts +12 -0
  53. package/util/repositioned.js +81 -0
  54. package/util/util.d.ts +5 -0
  55. package/util/util.js +33 -0
  56. package/.eslintrc.cjs +0 -37
  57. package/docs/CollapsingTable.md +0 -79
  58. package/docs/ConditionalWrapper.md +0 -35
  59. package/docs/Modal.md +0 -63
  60. package/docs/PopupMenu.md +0 -31
  61. package/docs/ScreenReaderOnly.md +0 -10
  62. package/docs/actions.md +0 -84
  63. package/docs/stores.md +0 -203
  64. package/playwright.config.js +0 -112
  65. package/src/app.html +0 -14
  66. package/src/global.d.ts +0 -1
  67. package/src/lib/actions/buttonify.ts +0 -27
  68. package/src/lib/actions/glue.ts +0 -96
  69. package/src/lib/actions/index.ts +0 -7
  70. package/src/lib/actions/offset.ts +0 -43
  71. package/src/lib/actions/portal.ts +0 -13
  72. package/src/lib/actions/resize.ts +0 -72
  73. package/src/lib/actions/sticky.ts +0 -105
  74. package/src/lib/actions/stickyfixed.ts +0 -160
  75. package/src/lib/components/Card.svelte +0 -25
  76. package/src/lib/components/CardLayout.svelte +0 -188
  77. package/src/lib/components/FocusLock.svelte +0 -102
  78. package/src/lib/components/MultiSelect.svelte +0 -174
  79. package/src/lib/components/PopupMenu.svelte +0 -285
  80. package/src/lib/components/index.ts +0 -9
  81. package/src/lib/index.ts +0 -4
  82. package/src/lib/types/CardLayout.ts +0 -14
  83. package/src/lib/types/CollapsingTable.ts +0 -8
  84. package/src/lib/types/PopupMenu.ts +0 -5
  85. package/src/lib/types/index.ts +0 -3
  86. package/src/lib/util/bodyoffset.ts +0 -77
  87. package/src/lib/util/index.ts +0 -3
  88. package/src/lib/util/repositioned.ts +0 -91
  89. package/src/lib/util/util.ts +0 -36
  90. package/src/routes/__layout.svelte +0 -125
  91. package/src/routes/actions/index.svelte +0 -1
  92. package/src/routes/actions/offset.svelte +0 -4
  93. package/src/routes/actions/offsetdebounce.svelte +0 -4
  94. package/src/routes/actions/resize.svelte +0 -4
  95. package/src/routes/actions/resizedebounce.svelte +0 -4
  96. package/src/routes/actions/sticky.svelte +0 -4
  97. package/src/routes/cards/index.svelte +0 -4
  98. package/src/routes/cards/preserve.svelte +0 -4
  99. package/src/routes/collapsingtable/index.svelte +0 -4
  100. package/src/routes/collapsingtable/stickyheader.svelte +0 -4
  101. package/src/routes/index.svelte +0 -2
  102. package/src/routes/modal.svelte +0 -4
  103. package/src/routes/multiselect.svelte +0 -4
  104. package/src/routes/popupmenu/body.svelte +0 -4
  105. package/src/routes/popupmenu/complex.svelte +0 -4
  106. package/src/routes/popupmenu/empty.svelte +0 -5
  107. package/src/routes/popupmenu/index.svelte +0 -4
  108. package/src/routes/popupmenu/parent.svelte +0 -4
  109. package/src/routes/popupmenu/scrollable.svelte +0 -27
  110. package/src/routes/popupmenu/showselected.svelte +0 -4
  111. package/src/test/Cards.svelte +0 -64
  112. package/src/test/CollapsingTableTest.svelte +0 -36
  113. package/src/test/ModalTest.svelte +0 -58
  114. package/src/test/MultiSelectTest.svelte +0 -26
  115. package/src/test/Offset.svelte +0 -32
  116. package/src/test/PopupMenuBody.svelte +0 -34
  117. package/src/test/PopupMenuButtonIsParent.svelte +0 -36
  118. package/src/test/PopupMenuComplex.svelte +0 -34
  119. package/src/test/PopupMenuSimple.svelte +0 -36
  120. package/src/test/Resize.svelte +0 -29
  121. package/src/test/Sticky.svelte +0 -65
  122. package/static/layout.css +0 -263
  123. package/svelte.config.js +0 -15
  124. package/tests/.eslintrc.cjs +0 -19
  125. package/tests/CardLayout.test.js +0 -41
  126. package/tests/CollapsingTable.test.js +0 -37
  127. package/tests/Modal.test.js +0 -18
  128. package/tests/MultiSelect.test.js +0 -58
  129. package/tests/PopupMenu.test.js +0 -55
  130. package/tests/common.js +0 -4
  131. package/tsconfig.json +0 -31
@@ -0,0 +1,197 @@
1
+ <script >import { onDestroy, tick, setContext, onMount } from 'svelte';
2
+ import { writable } from 'svelte/store';
3
+ import { browser } from '$app/env';
4
+ import { resize } from '../actions';
5
+ import { CARDLAYOUT } from '../types';
6
+ export let maxwidth = 500;
7
+ export let preserveorder = false;
8
+ export let gutter = 10;
9
+ export let className = '';
10
+ const blocks = [];
11
+ const gutterstore = writable(gutter);
12
+ let defaultOrder = 0;
13
+ setContext(CARDLAYOUT, {
14
+ registerBlock: (block) => {
15
+ blocks.push(block);
16
+ hardrecalc();
17
+ onDestroy(() => {
18
+ blocks.splice(blocks.indexOf(block), 1);
19
+ hardrecalc();
20
+ });
21
+ block.order = writable(defaultOrder++);
22
+ block.linebreak = writable(false);
23
+ const cols = savecolumns || Math.ceil(1024 / maxwidth);
24
+ block.width = writable(`calc(${100.0 / cols}% - ${gutter * (cols - 1) / cols}px)`);
25
+ return block;
26
+ },
27
+ recalculate: () => {
28
+ hardrecalc();
29
+ },
30
+ gutter: gutterstore
31
+ });
32
+ $: gutterstore.set(gutter);
33
+ let layoutelement;
34
+ let cycle1 = 0;
35
+ let cycle2 = 0;
36
+ function detectcycle(w) {
37
+ if (cycle1 === 0 && Math.abs(w - cycle2) > 5) {
38
+ cycle1 = w;
39
+ }
40
+ else if (cycle2 === 0 && Math.abs(w - cycle1) > 5) {
41
+ cycle2 = w;
42
+ }
43
+ else if (w === cycle1 || w === cycle2) {
44
+ return true;
45
+ }
46
+ else {
47
+ cycle1 = 0;
48
+ cycle2 = 0;
49
+ }
50
+ return false;
51
+ }
52
+ let savecolumns = 0;
53
+ let optimal;
54
+ let fullheight = 0;
55
+ let hardrequired = false;
56
+ async function recalculate(realw) {
57
+ const columns = Math.ceil(realw / maxwidth);
58
+ const guttereach = gutter * (columns - 1) / columns;
59
+ const cycling = detectcycle(realw);
60
+ if (columns !== savecolumns) {
61
+ for (const block of blocks)
62
+ block.width.set(`calc(${100.0 / columns}% - ${guttereach}px`);
63
+ await tick();
64
+ }
65
+ // collect all the card heights at this new column width
66
+ for (const block of blocks)
67
+ block.height = block.element?.offsetHeight ?? 200;
68
+ if (columns !== savecolumns || hardrequired) { // only do real work if number of columns has changed, recalculate triggers on resize
69
+ if (preserveorder) {
70
+ optimal = [blocks];
71
+ if (columns > 1) {
72
+ const totalheight = blocks.reduce((totalheight, block) => totalheight + block.height + gutter, 0);
73
+ const tallestblock = Math.max(...blocks.map(b => b.height));
74
+ const minheight = Math.max(totalheight / columns, tallestblock);
75
+ let shortestoverall = totalheight;
76
+ // 2d packing problem is NP-hard so this is an O(n) heuristic
77
+ // optimal configuration would be if each column is `minheight` so start there
78
+ // then relax it in increments and see if the overall height shrinks
79
+ const increment = Math.max(1, Math.floor(Math.min(minheight, tallestblock) * 0.05));
80
+ for (let colmaxheight = minheight; colmaxheight < minheight + tallestblock + gutter; colmaxheight += increment) {
81
+ let colheight = 0;
82
+ let colidx = 0;
83
+ let tallestcol = 0;
84
+ let tallestcolidx = 0;
85
+ const arrangement = [];
86
+ for (const block of blocks) {
87
+ if (colheight + block.height > colmaxheight && colidx < columns - 1) {
88
+ if (colheight > tallestcol) {
89
+ tallestcol = colheight;
90
+ tallestcolidx = colidx;
91
+ }
92
+ colidx++;
93
+ colheight = 0;
94
+ }
95
+ if (!arrangement[colidx])
96
+ arrangement[colidx] = [];
97
+ arrangement[colidx].push(block);
98
+ colheight += block.height + gutter;
99
+ }
100
+ if (colheight > tallestcol) {
101
+ tallestcol = colheight;
102
+ tallestcolidx = colidx;
103
+ }
104
+ if (tallestcol < shortestoverall) {
105
+ shortestoverall = tallestcol;
106
+ optimal = arrangement;
107
+ }
108
+ // if leftmost column is tallest, increasing the allowable height can never make the overall height shorter
109
+ if (tallestcolidx === 0)
110
+ break;
111
+ }
112
+ }
113
+ }
114
+ else {
115
+ optimal = [];
116
+ const heights = Array.apply(null, Array(columns)).map((_) => 0); // initializes heights to an array of zeroes
117
+ // begin sorting blocks into columns
118
+ for (const block of blocks) {
119
+ // find the column with the smallest current height
120
+ const colidx = heights.reduce((acc, curr, curridx) => curr < heights[acc] ? curridx : acc, 0);
121
+ // record the height we are adding to the chosen column
122
+ heights[colidx] += block.height + gutter;
123
+ // move the current card to the chosen column
124
+ if (!optimal[colidx])
125
+ optimal[colidx] = [];
126
+ optimal[colidx].push(block);
127
+ }
128
+ }
129
+ // we created the optimal arrangement, now move the block elements to
130
+ // reflect it
131
+ let order = 0;
132
+ for (let i = 0; i < optimal.length; i++) {
133
+ for (let j = 0; j < optimal[i].length; j++) {
134
+ const block = optimal[i][j];
135
+ block.order.set(order++);
136
+ block.linebreak.set(j === optimal[i].length - 1 && i < optimal.length - 1);
137
+ }
138
+ }
139
+ savecolumns = columns;
140
+ hardrequired = false;
141
+ }
142
+ // re-adjust container height
143
+ const saveheight = fullheight;
144
+ fullheight = 0;
145
+ for (let i = 0; i < optimal.length; i++) {
146
+ let top = 0;
147
+ for (const block of optimal[i]) {
148
+ top += block.height + gutter;
149
+ }
150
+ fullheight = Math.max(fullheight, top);
151
+ }
152
+ if (cycling && saveheight < fullheight)
153
+ fullheight = saveheight;
154
+ }
155
+ let savewidth = 0;
156
+ let timer = 0;
157
+ function triggerrecalc(width) {
158
+ if (width === savewidth && !hardrequired)
159
+ return;
160
+ cancelAnimationFrame(timer);
161
+ timer = requestAnimationFrame(() => {
162
+ recalculate(width);
163
+ savewidth = width;
164
+ });
165
+ }
166
+ function hardrecalc() {
167
+ if (!layoutelement)
168
+ return;
169
+ hardrequired = true;
170
+ cycle1 = 0;
171
+ cycle2 = 0;
172
+ triggerrecalc(layoutelement.clientWidth);
173
+ }
174
+ function onResize(e) {
175
+ triggerrecalc(e.detail.clientWidth);
176
+ }
177
+ onMount(() => triggerrecalc(layoutelement.clientWidth));
178
+ </script>
179
+
180
+ <ul class="cardlayout {className}" class:ssr={!browser} style:height={browser ? `${fullheight + gutter}px` : undefined} bind:this={layoutelement} use:resize on:resize={onResize}>
181
+ <slot></slot>
182
+ </ul>
183
+
184
+ <style>
185
+ .cardlayout {
186
+ list-style: none;
187
+ padding: 0;
188
+ margin: 0;
189
+ display: flex;
190
+ flex-wrap: wrap;
191
+ flex-direction: column;
192
+ align-content: space-between;
193
+ }
194
+ .cardlayout.ssr {
195
+ flex-direction: row;
196
+ }
197
+ </style>
@@ -0,0 +1,21 @@
1
+ import { SvelteComponentTyped } from "svelte";
2
+ declare const __propDef: {
3
+ props: {
4
+ maxwidth?: number;
5
+ preserveorder?: boolean;
6
+ gutter?: number;
7
+ className?: string;
8
+ };
9
+ events: {
10
+ [evt: string]: CustomEvent<any>;
11
+ };
12
+ slots: {
13
+ default: {};
14
+ };
15
+ };
16
+ export declare type CardLayoutProps = typeof __propDef.props;
17
+ export declare type CardLayoutEvents = typeof __propDef.events;
18
+ export declare type CardLayoutSlots = typeof __propDef.slots;
19
+ export default class CardLayout extends SvelteComponentTyped<CardLayoutProps, CardLayoutEvents, CardLayoutSlots> {
20
+ }
21
+ export {};
@@ -1,77 +1,75 @@
1
- <script lang="ts">
2
- import { Store } from '@txstate-mws/svelte-store'
3
- import { derived } from 'svelte/store'
4
- import type { CollapsingTableColumn, PopupMenuItem } from '$lib/types'
5
- import { classes } from '$lib/util'
6
- import DefaultPopupMenu from './PopupMenu.svelte'
7
- import ScreenReaderOnly from './ScreenReaderOnly.svelte'
8
-
9
- export let tableClass = ''
10
- export let bodyRowClass = ''
11
- export let bodyCellClass = ''
12
- export let headerRowClass = ''
13
- export let headerCellClass = ''
14
- export let menuContainerClass = ''
15
- export let menuClass = ''
16
- export let menuItemClass = ''
17
- export let menuItemHilitedClass = ''
18
- export let items: any[]
19
- export let config: CollapsingTableColumn[]|undefined = undefined
20
- export let defaultCellWidth = 150
21
- export let PopupMenu = DefaultPopupMenu
22
- export let slots: Record<string, boolean> = $$slots
23
- export let stickyheader: boolean = false
24
- let columns: CollapsingTableColumn[]
25
- let width: number = 320
26
- let selected: PopupMenuItem | undefined
27
- let identifyingkeys: string[] = []
28
- $: firstrow = items?.[0] ?? {}
29
- $: columns = config ?? Object.keys(firstrow).map(key => ({ key }))
30
- function reactToColumns (columns: CollapsingTableColumn[]) {
1
+ <script >import { Store } from '@txstate-mws/svelte-store';
2
+ import { derived } from 'svelte/store';
3
+ import { classes } from '../util';
4
+ import DefaultPopupMenu from './PopupMenu.svelte';
5
+ import ScreenReaderOnly from './ScreenReaderOnly.svelte';
6
+ export let tableClass = '';
7
+ export let bodyRowClass = '';
8
+ export let bodyCellClass = '';
9
+ export let headerRowClass = '';
10
+ export let headerCellClass = '';
11
+ export let menuContainerClass = '';
12
+ export let menuClass = '';
13
+ export let menuItemClass = '';
14
+ export let menuItemHilitedClass = '';
15
+ export let items;
16
+ export let config = undefined;
17
+ export let defaultCellWidth = 150;
18
+ export let PopupMenu = DefaultPopupMenu;
19
+ export let slots = $$slots;
20
+ export let stickyheader = false;
21
+ let columns;
22
+ let width = 320;
23
+ let selected;
24
+ let identifyingkeys = [];
25
+ $: firstrow = items?.[0] ?? {};
26
+ $: columns = config ?? Object.keys(firstrow).map(key => ({ key }));
27
+ function reactToColumns(columns) {
31
28
  if (!columns.some(c => c.neverhide)) {
32
- columns[0].neverhide = true
29
+ columns[0].neverhide = true;
33
30
  }
34
31
  const sortedcolumns = columns // stable sort
35
- .map((c, i) => ({ col: c, idx: i }))
36
- .sort((a, b) => ((a.col.neverhide ? 0 : 1) - (b.col.neverhide ? 0 : 1)) || a.idx - b.idx)
37
- .map(o => o.col)
32
+ .map((c, i) => ({ col: c, idx: i }))
33
+ .sort((a, b) => ((a.col.neverhide ? 0 : 1) - (b.col.neverhide ? 0 : 1)) || a.idx - b.idx)
34
+ .map(o => o.col);
38
35
  if (!selected) {
39
- const firstcol = sortedcolumns.find(c => !c.neverhide)
40
- selected = firstcol ? { value: firstcol.key } : undefined
36
+ const firstcol = sortedcolumns.find(c => !c.neverhide);
37
+ selected = firstcol ? { value: firstcol.key } : undefined;
41
38
  }
42
- identifyingkeys = sortedcolumns.filter(c => c.neverhide).map(c => c.key)
43
- return sortedcolumns
44
- }
45
- $: sortedcolumns = reactToColumns(columns)
46
-
47
- $: itemkeys = items.map(item => item.id ?? item._id ?? identifyingkeys.map(k => item[k]).join('.'))
48
-
49
- const state = new Store({
50
- keepcolumns: [] as (CollapsingTableColumn & { widthPercent?: number })[],
51
- hiddencolumns: [] as CollapsingTableColumn[],
52
- dropdowncolumn: undefined as (CollapsingTableColumn & { widthPercent?: number }) | undefined
53
- })
54
- const menuitems = derived(state, obj => obj.hiddencolumns.map(c => ({ value: c.key, label: c.title })))
55
- function react (..._: any[]) {
56
- const selectedcol = sortedcolumns.find(c => c.key === selected?.value) ?? columns[1]
57
- const keepcolumns: CollapsingTableColumn[] = []
58
- const hiddencolumns: CollapsingTableColumn[] = []
59
- let used = sortedcolumns.filter(c => c.neverhide || c === selectedcol).reduce((sum, col) => sum + (col.width ?? defaultCellWidth), 0)
39
+ identifyingkeys = sortedcolumns.filter(c => c.neverhide).map(c => c.key);
40
+ return sortedcolumns;
41
+ }
42
+ $: sortedcolumns = reactToColumns(columns);
43
+ $: itemkeys = items.map(item => item.id ?? item._id ?? identifyingkeys.map(k => item[k]).join('.'));
44
+ const state = new Store({
45
+ keepcolumns: [],
46
+ hiddencolumns: [],
47
+ dropdowncolumn: undefined
48
+ });
49
+ const menuitems = derived(state, obj => obj.hiddencolumns.map(c => ({ value: c.key, label: c.title })));
50
+ function react(..._) {
51
+ const selectedcol = sortedcolumns.find(c => c.key === selected?.value) ?? columns[1];
52
+ const keepcolumns = [];
53
+ const hiddencolumns = [];
54
+ let used = sortedcolumns.filter(c => c.neverhide || c === selectedcol).reduce((sum, col) => sum + (col.width ?? defaultCellWidth), 0);
60
55
  for (const col of sortedcolumns) {
61
- if (col.neverhide || col === selectedcol || used + (col.width ?? defaultCellWidth) < width) {
62
- keepcolumns.push(col)
63
- if (col !== selectedcol && !col.neverhide) used += col.width ?? defaultCellWidth
64
- } else hiddencolumns.push(col)
56
+ if (col.neverhide || col === selectedcol || used + (col.width ?? defaultCellWidth) < width) {
57
+ keepcolumns.push(col);
58
+ if (col !== selectedcol && !col.neverhide)
59
+ used += col.width ?? defaultCellWidth;
60
+ }
61
+ else
62
+ hiddencolumns.push(col);
65
63
  }
66
64
  for (const col of keepcolumns) {
67
- (col as any).widthPercent = 100 * (col.width ?? defaultCellWidth) / used
65
+ col.widthPercent = 100 * (col.width ?? defaultCellWidth) / used;
68
66
  }
69
- const dropdowncolumn = hiddencolumns.length ? keepcolumns[keepcolumns.length - 1] : undefined
70
- state.set({ keepcolumns, hiddencolumns, dropdowncolumn })
71
- }
72
- $: react(width, selected)
73
- const headers: HTMLElement[] = []
74
- $: menubuttonelement = headers[$state.keepcolumns.length - 1]
67
+ const dropdowncolumn = hiddencolumns.length ? keepcolumns[keepcolumns.length - 1] : undefined;
68
+ state.set({ keepcolumns, hiddencolumns, dropdowncolumn });
69
+ }
70
+ $: react(width, selected);
71
+ const headers = [];
72
+ $: menubuttonelement = headers[$state.keepcolumns.length - 1];
75
73
  </script>
76
74
 
77
75
  <div bind:clientWidth={width}>
@@ -0,0 +1,59 @@
1
+ import { SvelteComponentTyped } from "svelte";
2
+ import type { CollapsingTableColumn } from '../types';
3
+ import DefaultPopupMenu from './PopupMenu.svelte';
4
+ declare const __propDef: {
5
+ props: {
6
+ tableClass?: string;
7
+ bodyRowClass?: string;
8
+ bodyCellClass?: string;
9
+ headerRowClass?: string;
10
+ headerCellClass?: string;
11
+ menuContainerClass?: string;
12
+ menuClass?: string;
13
+ menuItemClass?: string;
14
+ menuItemHilitedClass?: string;
15
+ items: any[];
16
+ config?: CollapsingTableColumn[] | undefined;
17
+ defaultCellWidth?: number;
18
+ PopupMenu?: typeof DefaultPopupMenu;
19
+ slots?: Record<string, boolean>;
20
+ stickyheader?: boolean;
21
+ };
22
+ events: {
23
+ [evt: string]: CustomEvent<any>;
24
+ };
25
+ slots: {
26
+ headercell: {
27
+ column: CollapsingTableColumn & {
28
+ widthPercent?: number;
29
+ };
30
+ key: string;
31
+ title: string;
32
+ item: any;
33
+ value: any;
34
+ };
35
+ dropicon: {
36
+ column: CollapsingTableColumn & {
37
+ widthPercent?: number;
38
+ };
39
+ item: any;
40
+ value: any;
41
+ };
42
+ default: {
43
+ key: string;
44
+ value: any;
45
+ item: any;
46
+ };
47
+ footer: {
48
+ item: any;
49
+ key: any;
50
+ value: any;
51
+ };
52
+ };
53
+ };
54
+ export declare type CollapsingTableProps = typeof __propDef.props;
55
+ export declare type CollapsingTableEvents = typeof __propDef.events;
56
+ export declare type CollapsingTableSlots = typeof __propDef.slots;
57
+ export default class CollapsingTable extends SvelteComponentTyped<CollapsingTableProps, CollapsingTableEvents, CollapsingTableSlots> {
58
+ }
59
+ export {};
@@ -1,10 +1,9 @@
1
- <script lang="ts">
2
- export let condition: boolean|undefined
3
- export let component: Function|undefined = undefined
4
- export let a = false
5
- export let span = false
6
- export let element: HTMLElement|undefined = undefined
7
- $: passthrough = (({ condition, component, a, span, element, ...passthrough }) => passthrough)($$props)
1
+ <script >export let condition;
2
+ export let component = undefined;
3
+ export let a = false;
4
+ export let span = false;
5
+ export let element = undefined;
6
+ $: passthrough = (({ condition, component, a, span, element, ...passthrough }) => passthrough)($$props);
8
7
  </script>
9
8
 
10
9
  {#if condition || (typeof condition === 'undefined' && component)}
@@ -0,0 +1,23 @@
1
+ import { SvelteComponentTyped } from "svelte";
2
+ declare const __propDef: {
3
+ props: {
4
+ [x: string]: any;
5
+ condition: boolean | undefined;
6
+ component?: Function | undefined;
7
+ a?: boolean;
8
+ span?: boolean;
9
+ element?: HTMLElement | undefined;
10
+ };
11
+ events: {
12
+ [evt: string]: CustomEvent<any>;
13
+ };
14
+ slots: {
15
+ default: {};
16
+ };
17
+ };
18
+ export declare type ConditionalWrapperProps = typeof __propDef.props;
19
+ export declare type ConditionalWrapperEvents = typeof __propDef.events;
20
+ export declare type ConditionalWrapperSlots = typeof __propDef.slots;
21
+ export default class ConditionalWrapper extends SvelteComponentTyped<ConditionalWrapperProps, ConditionalWrapperEvents, ConditionalWrapperSlots> {
22
+ }
23
+ export {};
@@ -0,0 +1,107 @@
1
+ <script context="module" >const FocusLockStack = [];
2
+ </script>
3
+
4
+ <script >export let returnfocusto = undefined;
5
+ export let initialfocus = undefined;
6
+ export let hidefocus = true;
7
+ export let hidefocuslabel = 'focus is above modal dialog, start tabbing';
8
+ export let escapable = true;
9
+ let className = '';
10
+ export { className as class };
11
+ import { onMount, onDestroy, createEventDispatcher, tick } from 'svelte';
12
+ import { tabbable } from 'tabbable';
13
+ import { sleep } from 'txstate-utils';
14
+ import { buttonify } from '../actions';
15
+ import ScreenReaderOnly from './ScreenReaderOnly.svelte';
16
+ const dispatch = createEventDispatcher();
17
+ let lockelement;
18
+ let abovelockelement;
19
+ let active = true;
20
+ let listenforescape = false;
21
+ if (initialfocus)
22
+ hidefocus = false;
23
+ onMount(async () => {
24
+ const prevFocusLock = FocusLockStack.slice(-1)[0];
25
+ if (prevFocusLock)
26
+ prevFocusLock.pause();
27
+ FocusLockStack.push({
28
+ pause: () => { active = false; },
29
+ unpause: () => { active = true; }
30
+ });
31
+ if (typeof returnfocusto === 'undefined') {
32
+ returnfocusto = document.querySelector(':focus');
33
+ }
34
+ await sleep(1); // sapper resets focus on page load, so we'll wait a millisecond in case our modal is on screen at load
35
+ if (!lockelement)
36
+ return; // in case we already unmounted
37
+ if (initialfocus) {
38
+ const focusEl = lockelement.querySelector(initialfocus);
39
+ if (focusEl instanceof HTMLElement)
40
+ focusEl.focus();
41
+ }
42
+ else {
43
+ setInitialFocus();
44
+ }
45
+ setTimeout(() => { listenforescape = true; }, 0);
46
+ });
47
+ onDestroy(async () => {
48
+ const wasactive = active;
49
+ active = false;
50
+ await tick();
51
+ if (returnfocusto && wasactive) {
52
+ returnfocusto.focus();
53
+ }
54
+ FocusLockStack.pop();
55
+ const prevFocusLock = FocusLockStack.slice(-1)[0];
56
+ if (prevFocusLock)
57
+ prevFocusLock.unpause();
58
+ });
59
+ const setInitialFocus = () => {
60
+ const firstfocus = lockelement ? tabbable(lockelement)[0] : undefined;
61
+ if (firstfocus && firstfocus.focus) {
62
+ firstfocus.focus();
63
+ }
64
+ };
65
+ const setLastFocus = () => {
66
+ const lastfocus = lockelement ? tabbable(lockelement).slice(-1)[0] : undefined;
67
+ if (lastfocus && lastfocus.focus) {
68
+ lastfocus.focus();
69
+ }
70
+ };
71
+ const keydown = (e) => {
72
+ if (active && e.key === 'Escape' && escapable) {
73
+ e.preventDefault();
74
+ dispatch('escape');
75
+ }
76
+ };
77
+ const focusin = (e) => {
78
+ if (active && e.target instanceof HTMLElement && !lockelement?.contains(e.target)) {
79
+ if (e.target === abovelockelement)
80
+ setLastFocus();
81
+ else
82
+ setInitialFocus();
83
+ }
84
+ };
85
+ const windowclick = (_) => {
86
+ if (listenforescape && active) {
87
+ returnfocusto = undefined;
88
+ dispatch('escape');
89
+ }
90
+ };
91
+ </script>
92
+ <svelte:window on:click={windowclick} />
93
+ <div class={className} role="alertdialog" aria-modal="true" on:click|stopPropagation on:keydown|stopPropagation={keydown} on:focusin={focusin}>
94
+ <div bind:this={abovelockelement} tabindex="0"></div>
95
+ <div bind:this={lockelement} on:keydown={keydown}>
96
+ {#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
+ <slot></slot>
98
+ </div>
99
+ <div tabindex="0"></div>
100
+ </div>
101
+
102
+ <style>
103
+ .hiddenfocus {
104
+ opacity: 0;
105
+ outline: 0;
106
+ }
107
+ </style>
@@ -0,0 +1,26 @@
1
+ import { SvelteComponentTyped } from "svelte";
2
+ declare const __propDef: {
3
+ props: {
4
+ returnfocusto?: HTMLElement | null | undefined;
5
+ initialfocus?: string | undefined;
6
+ hidefocus?: boolean;
7
+ hidefocuslabel?: string;
8
+ escapable?: boolean;
9
+ class?: string;
10
+ };
11
+ events: {
12
+ click: MouseEvent;
13
+ escape: CustomEvent<any>;
14
+ } & {
15
+ [evt: string]: CustomEvent<any>;
16
+ };
17
+ slots: {
18
+ default: {};
19
+ };
20
+ };
21
+ export declare type FocusLockProps = typeof __propDef.props;
22
+ export declare type FocusLockEvents = typeof __propDef.events;
23
+ export declare type FocusLockSlots = typeof __propDef.slots;
24
+ export default class FocusLock extends SvelteComponentTyped<FocusLockProps, FocusLockEvents, FocusLockSlots> {
25
+ }
26
+ export {};
@@ -1,28 +1,26 @@
1
- <script lang="ts">
2
- export let escapable = true
3
- export let hidefocus = true
4
- export let hidefocuslabel: string|undefined = undefined
5
- export let returnfocusto: HTMLElement|undefined = undefined
6
- export let initialfocus: string|undefined = undefined
7
- export let containerClass = ''
8
- export let opaque = false
9
- export let usePortal: HTMLElement|undefined = undefined
10
- import { createEventDispatcher, onMount } from 'svelte'
11
- import FocusLock from './FocusLock.svelte'
12
- import { portal } from '$lib/actions'
13
-
14
- const dispatch = createEventDispatcher()
15
- const endmodal = () => {
16
- dispatch('escape')
17
- }
18
- onMount(() => {
19
- document.body.style.marginRight = (window.innerWidth - document.body.clientWidth) + 'px'
20
- document.body.style.overflow = 'hidden'
1
+ <script >export let escapable = true;
2
+ export let hidefocus = true;
3
+ export let hidefocuslabel = undefined;
4
+ export let returnfocusto = undefined;
5
+ export let initialfocus = undefined;
6
+ export let containerClass = '';
7
+ export let opaque = false;
8
+ export let usePortal = undefined;
9
+ import { createEventDispatcher, onMount } from 'svelte';
10
+ import FocusLock from './FocusLock.svelte';
11
+ import { portal } from '../actions';
12
+ const dispatch = createEventDispatcher();
13
+ const endmodal = () => {
14
+ dispatch('escape');
15
+ };
16
+ onMount(() => {
17
+ document.body.style.marginRight = (window.innerWidth - document.body.clientWidth) + 'px';
18
+ document.body.style.overflow = 'hidden';
21
19
  return () => {
22
- document.body.style.overflow = ''
23
- document.body.style.marginRight = ''
24
- }
25
- })
20
+ document.body.style.overflow = '';
21
+ document.body.style.marginRight = '';
22
+ };
23
+ });
26
24
  </script>
27
25
 
28
26
  <div use:portal={usePortal} class="modal-backdrop" class:opaque on:click|stopPropagation|preventDefault={() => escapable && endmodal()}>