@dosgato/dialog 0.0.45 → 0.0.47

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 (55) hide show
  1. package/dist/ButtonGroup.svelte +1 -0
  2. package/dist/Checkbox.svelte +1 -4
  3. package/dist/Checkbox.svelte.d.ts +0 -2
  4. package/dist/Container.svelte +41 -6
  5. package/dist/Container.svelte.d.ts +2 -0
  6. package/dist/Dialog.svelte +2 -2
  7. package/dist/FieldAutocomplete.svelte +4 -2
  8. package/dist/FieldAutocomplete.svelte.d.ts +2 -0
  9. package/dist/FieldCheckbox.svelte +5 -2
  10. package/dist/FieldCheckbox.svelte.d.ts +2 -0
  11. package/dist/FieldChoices.svelte +5 -2
  12. package/dist/FieldChoices.svelte.d.ts +2 -0
  13. package/dist/FieldChooserLink.svelte +4 -2
  14. package/dist/FieldChooserLink.svelte.d.ts +2 -0
  15. package/dist/FieldCodeEditor.svelte +4 -2
  16. package/dist/FieldCodeEditor.svelte.d.ts +2 -0
  17. package/dist/FieldDate.svelte +4 -2
  18. package/dist/FieldDate.svelte.d.ts +2 -0
  19. package/dist/FieldDateTime.svelte +4 -2
  20. package/dist/FieldDateTime.svelte.d.ts +2 -0
  21. package/dist/FieldDualListbox.svelte +9 -5
  22. package/dist/FieldDualListbox.svelte.d.ts +3 -0
  23. package/dist/FieldMultiple.svelte +11 -3
  24. package/dist/FieldMultiple.svelte.d.ts +3 -0
  25. package/dist/FieldMultiselect.svelte +7 -3
  26. package/dist/FieldMultiselect.svelte.d.ts +3 -0
  27. package/dist/FieldNumber.svelte +4 -2
  28. package/dist/FieldNumber.svelte.d.ts +2 -0
  29. package/dist/FieldRadio.svelte +3 -1
  30. package/dist/FieldRadio.svelte.d.ts +2 -0
  31. package/dist/FieldSelect.svelte +4 -2
  32. package/dist/FieldSelect.svelte.d.ts +2 -0
  33. package/dist/FieldStandard.svelte +2 -1
  34. package/dist/FieldStandard.svelte.d.ts +1 -0
  35. package/dist/FieldText.svelte +4 -2
  36. package/dist/FieldText.svelte.d.ts +2 -0
  37. package/dist/FieldTextArea.svelte +4 -2
  38. package/dist/FieldTextArea.svelte.d.ts +2 -0
  39. package/dist/Input.svelte +2 -1
  40. package/dist/Input.svelte.d.ts +1 -0
  41. package/dist/Listbox.svelte +1 -0
  42. package/dist/Radio.svelte +2 -1
  43. package/dist/Radio.svelte.d.ts +1 -0
  44. package/dist/Switcher.svelte +4 -2
  45. package/dist/Switcher.svelte.d.ts +2 -0
  46. package/dist/Tabs.svelte +1 -0
  47. package/dist/chooser/Chooser.svelte +32 -18
  48. package/dist/chooser/Details.svelte +54 -12
  49. package/dist/helpers.d.ts +1 -1
  50. package/dist/helpers.js +1 -1
  51. package/dist/tree/Tree.svelte +14 -8
  52. package/dist/tree/TreeNode.svelte +3 -3
  53. package/dist/tree/treestore.d.ts +3 -1
  54. package/dist/tree/treestore.js +21 -12
  55. package/package.json +7 -4
@@ -13,6 +13,8 @@ export let defaultValue = notNull ? choices[0].value : undefined;
13
13
  export let conditional = undefined;
14
14
  export let required = false;
15
15
  export let inputelement = undefined;
16
+ export let related = 0;
17
+ export let extradescid = undefined;
16
18
  export let helptext = undefined;
17
19
  export let number = false;
18
20
  export let date = false;
@@ -22,8 +24,8 @@ export let serialize = undefined;
22
24
  export let deserialize = undefined;
23
25
  </script>
24
26
 
25
- <FieldStandard bind:id {label} {path} {required} {defaultValue} {conditional} {helptext} {notNull} {number} {date} {datetime} {boolean} {serialize} {deserialize} let:value let:valid let:invalid let:id let:onBlur let:onChange let:messagesid let:helptextid let:serialize>
26
- <select bind:this={inputelement} {id} name={path} {disabled} class="dialog-input dialog-select {className}" on:change={onChange} on:blur={onBlur} class:valid class:invalid aria-describedby={getDescribedBy([messagesid, helptextid])}>
27
+ <FieldStandard bind:id {label} {path} {required} {defaultValue} {conditional} {related} {helptext} {notNull} {number} {date} {datetime} {boolean} {serialize} {deserialize} let:value let:valid let:invalid let:id let:onBlur let:onChange let:messagesid let:helptextid let:serialize>
28
+ <select bind:this={inputelement} {id} name={path} {disabled} class="dialog-input dialog-select {className}" on:change={onChange} on:blur={onBlur} class:valid class:invalid aria-describedby={getDescribedBy([messagesid, helptextid, extradescid])}>
27
29
  {#if !notNull}<option value="" selected={!value}>{placeholder}</option>{/if}
28
30
  {#each choices as choice (choice.value)}
29
31
  {@const serializedValue = serialize(choice.value)}
@@ -17,6 +17,8 @@ declare const __propDef: {
17
17
  conditional?: boolean | undefined;
18
18
  required?: boolean | undefined;
19
19
  inputelement?: HTMLSelectElement | undefined;
20
+ related?: number | true | undefined;
21
+ extradescid?: string | undefined;
20
22
  helptext?: string | undefined;
21
23
  number?: boolean | undefined;
22
24
  date?: boolean | undefined;
@@ -16,11 +16,12 @@ export let deserialize = undefined;
16
16
  export let finalize = undefined;
17
17
  export let conditional = undefined;
18
18
  export let required = false;
19
+ export let related = 0;
19
20
  export let helptext = undefined;
20
21
  </script>
21
22
 
22
23
  <Field {path} {defaultValue} {conditional} {notNull} {number} {date} {datetime} {boolean} {serialize} {deserialize} {finalize} let:path let:value let:onBlur let:onChange let:setVal let:messages let:valid let:invalid let:serialize let:deserialize>
23
- <Container {id} {label} {messages} {descid} {required} {helptext} let:messagesid let:helptextid>
24
+ <Container {id} {label} {messages} {descid} {required} {related} {helptext} let:messagesid let:helptextid>
24
25
  <slot {id} {path} {value} {onBlur} {onChange} {setVal} {valid} {invalid} {messagesid} {helptextid} {serialize} {deserialize} />
25
26
  </Container>
26
27
  </Field>
@@ -16,6 +16,7 @@ declare const __propDef: {
16
16
  finalize?: ((value: any) => any) | undefined;
17
17
  conditional?: boolean | undefined;
18
18
  required?: boolean | undefined;
19
+ related?: number | true | undefined;
19
20
  helptext?: string | undefined;
20
21
  };
21
22
  events: {
@@ -15,9 +15,11 @@ export let conditional = undefined;
15
15
  export let required = false;
16
16
  export let use = [];
17
17
  export let inputelement = undefined;
18
+ export let related = 0;
19
+ export let extradescid = undefined;
18
20
  export let helptext = undefined;
19
21
  </script>
20
22
 
21
- <FieldStandard bind:id {label} {path} {required} {defaultValue} {conditional} {helptext} serialize={!notNull ? nullableSerialize : undefined} deserialize={!notNull ? nullableDeserialize : undefined} let:value let:valid let:invalid let:id let:onBlur let:onChange let:messagesid let:helptextid>
22
- <Input bind:inputelement {type} name={path} {value} {id} class="dialog-input {className}" {allowlastpass} {onChange} {onBlur} {valid} {invalid} {maxlength} {messagesid} {helptextid} {use}></Input>
23
+ <FieldStandard bind:id {label} {path} {required} {defaultValue} {conditional} {related} {helptext} serialize={!notNull ? nullableSerialize : undefined} deserialize={!notNull ? nullableDeserialize : undefined} let:value let:valid let:invalid let:id let:onBlur let:onChange let:messagesid let:helptextid>
24
+ <Input bind:inputelement {type} name={path} {value} {id} class="dialog-input {className}" {allowlastpass} {onChange} {onBlur} {valid} {invalid} {maxlength} {messagesid} {helptextid} {extradescid} {use}></Input>
23
25
  </FieldStandard>
@@ -15,6 +15,8 @@ declare const __propDef: {
15
15
  required?: boolean | undefined;
16
16
  use?: HTMLActionEntry<any>[] | undefined;
17
17
  inputelement?: HTMLInputElement | undefined;
18
+ related?: number | true | undefined;
19
+ extradescid?: string | undefined;
18
20
  helptext?: string | undefined;
19
21
  };
20
22
  events: {
@@ -15,11 +15,13 @@ export let conditional = undefined;
15
15
  export let required = false;
16
16
  export let use = [];
17
17
  export let inputelement = undefined;
18
+ export let related = 0;
19
+ export let extradescid = undefined;
18
20
  export let helptext = undefined;
19
21
  </script>
20
22
 
21
- <FieldStandard bind:id {label} {path} {required} {defaultValue} {conditional} {helptext} serialize={!notNull ? nullableSerialize : undefined} deserialize={!notNull ? nullableDeserialize : undefined} let:value let:valid let:invalid let:id let:onBlur let:onChange let:messagesid let:helptextid>
22
- <textarea bind:this={inputelement} name={path} {value} {id} {rows} class="dialog-input dialog-textarea {className}" class:valid class:invalid aria-invalid={invalid} aria-describedby={getDescribedBy([messagesid, helptextid])} on:change={onChange} on:blur={onBlur} on:keyup={onChange} on:paste {maxlength} use:passActions={use}></textarea>
23
+ <FieldStandard bind:id {label} {path} {required} {defaultValue} {conditional} {related} {helptext} serialize={!notNull ? nullableSerialize : undefined} deserialize={!notNull ? nullableDeserialize : undefined} let:value let:valid let:invalid let:id let:onBlur let:onChange let:messagesid let:helptextid>
24
+ <textarea bind:this={inputelement} name={path} {value} {id} {rows} class="dialog-input dialog-textarea {className}" class:valid class:invalid aria-invalid={invalid} aria-describedby={getDescribedBy([messagesid, helptextid, extradescid])} on:change={onChange} on:blur={onBlur} on:keyup={onChange} on:paste {maxlength} use:passActions={use}></textarea>
23
25
  </FieldStandard>
24
26
 
25
27
  <style>
@@ -14,6 +14,8 @@ declare const __propDef: {
14
14
  required?: boolean | undefined;
15
15
  use?: HTMLActionEntry<any>[] | undefined;
16
16
  inputelement?: HTMLTextAreaElement | undefined;
17
+ related?: number | true | undefined;
18
+ extradescid?: string | undefined;
17
19
  helptext?: string | undefined;
18
20
  };
19
21
  events: {
package/dist/Input.svelte CHANGED
@@ -13,6 +13,7 @@ export let max = undefined;
13
13
  export let step = undefined;
14
14
  export let id = undefined;
15
15
  export let disabled = false;
16
+ export let extradescid = undefined;
16
17
  export let messagesid = undefined;
17
18
  export let helptextid = undefined;
18
19
  export let valid = false;
@@ -22,7 +23,7 @@ export let onBlur;
22
23
  export let onSelect = undefined;
23
24
  export let use = [];
24
25
  export let inputelement = undefined;
25
- $: descby = [helptextid, messagesid].filter(isNotBlank).join(' ');
26
+ $: descby = [messagesid, helptextid, extradescid].filter(isNotBlank).join(' ');
26
27
  function resolveMinMax(dt) {
27
28
  if (typeof dt === 'undefined')
28
29
  return undefined;
@@ -17,6 +17,7 @@ declare const __propDef: {
17
17
  step?: number | undefined;
18
18
  id?: string | undefined;
19
19
  disabled?: boolean | undefined;
20
+ extradescid?: string | undefined;
20
21
  messagesid?: string | undefined;
21
22
  helptextid?: string | undefined;
22
23
  valid?: boolean | undefined;
@@ -120,6 +120,7 @@ function focusListbox() {
120
120
 
121
121
  <div class="listbox-container" class:valid class:invalid>
122
122
  <span id={labelId}>{label}</span>
123
+ <!-- svelte-ignore a11y-no-noninteractive-element-to-interactive-role -->
123
124
  <ul bind:this={listboxElement} role="listbox" id={listId} class="listbox-items" tabindex="0" aria-describedby={descid} aria-labelledby={labelId} aria-multiselectable={multiselect} on:keydown={onkeydown} on:focus={focusListbox}>
124
125
  {#each items as item, i (item.value)}
125
126
  <!-- svelte-ignore a11y-click-events-have-key-events -->
package/dist/Radio.svelte CHANGED
@@ -7,10 +7,11 @@ export let onChange = undefined;
7
7
  export let onBlur = undefined;
8
8
  export let messagesid = undefined;
9
9
  export let helptextid = undefined;
10
+ export let extradescid = undefined;
10
11
  export let disabled = false;
11
12
  export let valid = false;
12
13
  export let invalid = false;
13
- $: descby = [messagesid, helptextid].filter(isNotBlank).join(' ');
14
+ $: descby = [messagesid, helptextid, extradescid].filter(isNotBlank).join(' ');
14
15
  </script>
15
16
 
16
17
  <input {id} type="radio" {name} class:valid class:invalid checked={selected} {disabled} aria-describedby={descby} {value} on:change={onChange} on:blur={onBlur}>
@@ -9,6 +9,7 @@ declare const __propDef: {
9
9
  onBlur?: any;
10
10
  messagesid?: string | undefined;
11
11
  helptextid?: string | undefined;
12
+ extradescid?: string | undefined;
12
13
  disabled?: boolean | undefined;
13
14
  valid?: boolean | undefined;
14
15
  invalid?: boolean | undefined;
@@ -12,6 +12,8 @@ export let choices;
12
12
  export let horizontal = false;
13
13
  export let label;
14
14
  export let required = false;
15
+ export let related = 0;
16
+ export let extradescid = undefined;
15
17
  export let helptext = undefined;
16
18
  export let messages = [];
17
19
  export let iptValue = choices[0].value;
@@ -28,12 +30,12 @@ function onChange(e) {
28
30
  $: columns = Math.floor($store.width / 250);
29
31
  $: width = (horizontal ? 100 / Math.min(choices.length, choices.length === 4 && columns === 3 ? 2 : columns) : 100) + '%';
30
32
  </script>
31
- <Container {id} {label} {messages} descid={groupid} {required} {helptext} let:helptextid>
33
+ <Container {id} {label} {messages} descid={groupid} {required} {related} {helptext} let:helptextid>
32
34
  <div class="dialog-radio {className}" use:eq={{ store }} class:horizontal role="radiogroup" aria-labelledby={groupid} class:valid class:invalid>
33
35
  {#each choices as choice, idx}
34
36
  {@const radioid = `${groupid}.${idx}`}
35
37
  <label for={radioid} style:width>
36
- <Radio id={radioid} {name} value={choice.value} selected={iptValue === choice.value} disabled={choice.disabled} {onChange} {onBlur} {helptextid}/>
38
+ <Radio id={radioid} {name} value={choice.value} selected={iptValue === choice.value} disabled={choice.disabled} {onChange} {onBlur} {helptextid} {extradescid} />
37
39
  <span>{choice.label || choice.value}</span>
38
40
  </label>
39
41
  {/each}
@@ -13,6 +13,8 @@ declare const __propDef: {
13
13
  horizontal?: boolean | undefined;
14
14
  label: string;
15
15
  required?: boolean | undefined;
16
+ related?: number | true | undefined;
17
+ extradescid?: string | undefined;
16
18
  helptext?: string | undefined;
17
19
  messages?: Feedback[] | undefined;
18
20
  iptValue?: string | undefined;
package/dist/Tabs.svelte CHANGED
@@ -87,6 +87,7 @@ onMount(reactToCurrent);
87
87
 
88
88
  {#if $store.tabs.length > 1}
89
89
  {#if !$accordion}
90
+ <!-- svelte-ignore a11y-no-noninteractive-element-to-interactive-role -->
90
91
  <ul use:resize={{ store }} class="tabs-buttons" role="tablist">
91
92
  {#each $store.tabs as tab, idx (tab.name)}
92
93
  {@const active = isActive(idx, $store.current)}
@@ -91,23 +91,28 @@ onMount(async () => {
91
91
  <Tabs bind:store={tabStore} tabs={$sources.map(s => ({ name: s.name, title: s.label ?? s.name }))} />
92
92
  {/if}
93
93
  </header>
94
- <section class="dialog-chooser-chooser">
95
- {#if $store.initialized}
96
- <Tree headers={[
97
- { label: 'Path', id: 'name', grow: 4, icon: item => item.type === 'asset' ? iconForMime(item.mime) : (item.type === 'folder' ? (item.open ? folderNotchOpen : folderIcon) : applicationOutline), get: 'name' }
98
- ]} singleSelect store={treeStore} on:deselect={onDeselect} on:choose={onChoose} />
99
- {/if}
100
- </section>
101
- <section class="dialog-chooser-preview" tabindex="-1">
102
- {#if $preview}
103
- <Thumbnail item={$preview} larger />
104
- <Details item={$preview}>
105
- {#if $preview.type === 'folder'}
106
- <li>{$selected?.children?.length ?? 0} sub-items</li>
107
- {/if}
108
- </Details>
109
- {/if}
110
- </section>
94
+ <div class="dialog-chooser-body">
95
+ <section class="dialog-chooser-chooser">
96
+ {#if $store.initialized}
97
+ <Tree headers={[
98
+ { label: 'Path', id: 'name', grow: 4, icon: item => item.type === 'asset' ? iconForMime(item.mime) : (item.type === 'folder' ? (item.open ? folderNotchOpen : folderIcon) : applicationOutline), get: 'name' }
99
+ ]} singleSelect store={treeStore} on:deselect={onDeselect} on:choose={onChoose} />
100
+ {/if}
101
+ </section>
102
+ <section class="dialog-chooser-preview" tabindex="-1">
103
+ {#if $preview}
104
+ <Thumbnail item={$preview} larger />
105
+ <Details item={$preview}>
106
+ {#if $preview.type === 'folder'}
107
+ <div class="folder-info">
108
+ <dt>Contents:</dt>
109
+ <dd>{$selected?.children?.length ?? 0} sub-items</dd>
110
+ </div>
111
+ {/if}
112
+ </Details>
113
+ {/if}
114
+ </section>
115
+ </div>
111
116
  </section>
112
117
  </Dialog>
113
118
 
@@ -115,7 +120,6 @@ onMount(async () => {
115
120
  .dialog-chooser-window {
116
121
  position: relative;
117
122
  height: 80vh;
118
- display: flex;
119
123
  flex-wrap: wrap;
120
124
  align-items: stretch;
121
125
  justify-content: flex-end;
@@ -124,6 +128,10 @@ onMount(async () => {
124
128
  .dialog-chooser-window * {
125
129
  box-sizing: border-box;
126
130
  }
131
+
132
+ .dialog-chooser-body {
133
+ display: flex;
134
+ }
127
135
  .dialog-chooser-chooser {
128
136
  position: relative;
129
137
  width: 75%;
@@ -140,6 +148,12 @@ onMount(async () => {
140
148
  padding: 1em;
141
149
  overflow-y: auto;
142
150
  }
151
+ .folder-info dt {
152
+ font-weight: bold;
153
+ }
154
+ .folder-info dd {
155
+ margin: 0;
156
+ }
143
157
  header {
144
158
  position: relative;
145
159
  width: 100%;
@@ -2,25 +2,48 @@
2
2
  export let item;
3
3
  </script>
4
4
 
5
- <ul class="dialog-chooser-info" aria-live="polite">
5
+ <dl class="dialog-chooser-info" aria-live="polite">
6
6
  {#if item.type !== 'raw'}
7
- <li>{item.path}</li>
7
+ <div class="top-row">
8
+ <dt>Name:</dt>
9
+ <dd>{item.path}</dd>
10
+ </div>
8
11
  {:else if item.id}
9
- <li>External Link<br>{item.url}</li>
12
+ <div>
13
+ <dt>External Link:</dt>
14
+ <dd>{item.url}</dd>
15
+ </div>
10
16
  {/if}
11
- {#if item.type === 'asset' && item.image}
12
- <li>{item.image.width}x{item.image.height}</li>
17
+ {#if item.type === 'asset'}
18
+ <div class="asset-properties">
19
+ {#if item.image}
20
+ <div>
21
+ <dt>Dimensions:</dt>
22
+ <dd>{item.image.width}x{item.image.height}</dd>
23
+ </div>
24
+ {/if}
25
+ <div>
26
+ <dt>File Type:</dt>
27
+ <dd>{item.mime}</dd>
28
+ </div>
29
+ <div>
30
+ <dt>File Size:</dt>
31
+ <dd>{bytesToHuman(item.bytes)}</dd>
32
+ </div>
33
+ </div>
13
34
  {:else if item.type === 'page' && item.title}
14
- <li>{item.title}</li>
35
+ <div>
36
+ <dt>Title:</dt>
37
+ <dd>{item.title}</dd>
38
+ </div>
15
39
  {:else if item.type === 'folder'}
16
- <li>{item.path}</li>
17
- {/if}
18
- {#if item.type === 'asset'}
19
- <li>{item.mime}</li>
20
- <li>{bytesToHuman(item.bytes)}</li>
40
+ <div>
41
+ <dt>Path:</dt>
42
+ <dd>{item.path}</dd>
43
+ </div>
21
44
  {/if}
22
45
  <slot />
23
- </ul>
46
+ </dl>
24
47
 
25
48
  <style>
26
49
  .dialog-chooser-info {
@@ -28,5 +51,24 @@ export let item;
28
51
  margin: 0;
29
52
  list-style: none;
30
53
  }
54
+ .dialog-chooser-info dt {
55
+ font-weight: bold;
56
+ }
57
+ .dialog-chooser-info dd {
58
+ margin: 0;
59
+ }
60
+ .top-row {
61
+ margin-bottom: 1em;
62
+ }
63
+ .asset-properties {
64
+ display: flex;
65
+ justify-content: space-between;
66
+ }
67
+ :global([data-eq~="1400px"]) .asset-properties {
68
+ flex-direction: column;
69
+ }
70
+ :global([data-eq~="1400px"]) .asset-properties div:not(:last-child){
71
+ margin-bottom: 1em;
72
+ }
31
73
 
32
74
  </style>
package/dist/helpers.d.ts CHANGED
@@ -1 +1 @@
1
- export declare function getDescribedBy(ids: (string | undefined)[]): string | null;
1
+ export declare function getDescribedBy(ids: (string | undefined)[]): string | undefined;
package/dist/helpers.js CHANGED
@@ -1,5 +1,5 @@
1
1
  import { isNotBlank } from 'txstate-utils';
2
2
  export function getDescribedBy(ids) {
3
3
  const descby = ids.filter(isNotBlank).join(' ');
4
- return isNotBlank(descby) ? descby : null;
4
+ return isNotBlank(descby) ? descby : undefined;
5
5
  }
@@ -1,10 +1,9 @@
1
1
  <script>import { resize } from '@txstate-mws/svelte-components';
2
2
  import { derivedStore, Store } from '@txstate-mws/svelte-store';
3
- import { afterUpdate, beforeUpdate, onDestroy, onMount, setContext } from 'svelte';
4
- import { hashid } from 'txstate-utils';
3
+ import { afterUpdate, beforeUpdate, onDestroy, onMount, setContext, tick } from 'svelte';
5
4
  import LoadIcon from './LoadIcon.svelte';
6
5
  import TreeNode from './TreeNode.svelte';
7
- import { TreeStore, TREE_STORE_CONTEXT } from './treestore';
6
+ import { getHashId, TreeStore, TREE_STORE_CONTEXT } from './treestore';
8
7
  export let headers;
9
8
  export let nodeClass = undefined;
10
9
  export let singleSelect = undefined;
@@ -93,18 +92,24 @@ function headerDragEnd() {
93
92
  function headerDragReset() {
94
93
  store.resetHeaderOverride();
95
94
  }
95
+ let mounted = false;
96
96
  onMount(async () => {
97
97
  document.addEventListener('dragend', onDragEnd);
98
98
  const saveFocusId = $store.focused?.id;
99
+ headerSizes.set(calcHeaderSizes()); // seems to need a kick on first mount
100
+ await new Promise(resolve => requestAnimationFrame(resolve));
101
+ // need to wait long enough for headers to redraw before trying to mount the rows
102
+ await new Promise(resolve => requestAnimationFrame(resolve));
103
+ mounted = true;
99
104
  await store.refresh();
100
105
  if ($store.focused?.id && $store.focused.id === saveFocusId) {
101
- const el = document.getElementById(hashid($store.focused.id));
106
+ const el = document.getElementById(getHashId($store.focused.id));
102
107
  el?.scrollIntoView({ block: 'center' });
103
108
  }
104
- headerSizes.set(calcHeaderSizes()); // seems to need a kick on first mount
105
109
  });
106
110
  onDestroy(() => {
107
- document.removeEventListener('dragend', onDragEnd);
111
+ if (typeof document !== 'undefined')
112
+ document.removeEventListener('dragend', onDragEnd);
108
113
  });
109
114
  let hadFocus = false;
110
115
  beforeUpdate(() => {
@@ -112,7 +117,7 @@ beforeUpdate(() => {
112
117
  });
113
118
  afterUpdate(() => {
114
119
  if ($store.focused?.id) {
115
- const el = document.getElementById(hashid($store.focused.id));
120
+ const el = document.getElementById(getHashId($store.focused.id));
116
121
  if (el && hadFocus) {
117
122
  if (el !== document.activeElement)
118
123
  el.focus();
@@ -130,7 +135,8 @@ afterUpdate(() => {
130
135
  {#if enableResize && i !== headers.length - 1}<div class="tree-separator" on:mousedown={headerDragStart(header, i)} on:touchstart={headerDragStart(header, i)} on:dblclick={headerDragReset}>&nbsp;</div>{/if}
131
136
  {/each}
132
137
  </div>
133
- {#if $rootItems?.length}
138
+ {#if mounted && $rootItems?.length}
139
+ <!-- svelte-ignore a11y-no-noninteractive-element-to-interactive-role -->
134
140
  <ul bind:this={store.treeElement} role="tree" class:resizing={!!dragheaderid} on:mousemove={dragheaderid ? headerDrag : undefined} on:touchmove={dragheaderid ? headerDrag : undefined} on:mouseup={headerDragEnd} on:touchend={headerDragEnd}>
135
141
  {#each $rootItems as item, i (item.id)}
136
142
  <TreeNode
@@ -4,9 +4,9 @@ import menuDown from '@iconify-icons/mdi/menu-down';
4
4
  import menuRight from '@iconify-icons/mdi/menu-right';
5
5
  import { modifierKey, ScreenReaderOnly } from '@txstate-mws/svelte-components';
6
6
  import { createEventDispatcher, getContext } from 'svelte';
7
- import { hashid, isNotBlank, toArray } from 'txstate-utils';
7
+ import { isNotBlank, toArray } from 'txstate-utils';
8
8
  import { Icon } from '..';
9
- import { TREE_STORE_CONTEXT } from './treestore';
9
+ import { TREE_STORE_CONTEXT, getHashId } from './treestore';
10
10
  import LoadIcon from './LoadIcon.svelte';
11
11
  import TreeCell from './TreeCell.svelte';
12
12
  export let headers;
@@ -26,7 +26,7 @@ let nodeelement;
26
26
  let userWantsCopy = false;
27
27
  $: isSelected = $selected.has(item.id);
28
28
  $: showChildren = !!item.open && !!item.children?.length;
29
- $: hashedId = hashid(item.id);
29
+ $: hashedId = getHashId(item.id);
30
30
  $: isDraggable = $draggable && ((isSelected && !$selectedUndraggable) || store.dragEligible([item], true) || store.dragEligible([item], false));
31
31
  $: dropZone = $dragging && store.dropEffect(item, false, userWantsCopy) !== 'none';
32
32
  $: dropDisabled = $dragging && !dropZone;
@@ -48,7 +48,7 @@ export declare class TreeStore<T extends TreeItemFromDB> extends ActiveStore<ITr
48
48
  #private;
49
49
  fetchChildren: FetchChildrenFn<T>;
50
50
  treeElement?: HTMLElement;
51
- rootItems: import("@txstate-mws/svelte-store").DerivedStore<TypedTreeItem<T>[] | undefined, ITreeStore<T>>;
51
+ rootItems: import("svelte/store").Readable<any>;
52
52
  draggable: import("@txstate-mws/svelte-store").DerivedStore<boolean, ITreeStore<T>>;
53
53
  dragging: import("@txstate-mws/svelte-store").DerivedStore<boolean, ITreeStore<T>>;
54
54
  selectedUndraggable: import("@txstate-mws/svelte-store").DerivedStore<boolean | undefined, ITreeStore<T>>;
@@ -115,3 +115,5 @@ export declare class TreeStore<T extends TreeItemFromDB> extends ActiveStore<ITr
115
115
  setHeaderOverride(id: string, width: string): void;
116
116
  resetHeaderOverride(): void;
117
117
  }
118
+ export declare const hashedIds: Record<string, string>;
119
+ export declare function getHashId(str: string): string;
@@ -1,10 +1,12 @@
1
1
  import { ActiveStore, derivedStore } from '@txstate-mws/svelte-store';
2
- import { keyby } from 'txstate-utils';
2
+ import { derived } from 'svelte/store';
3
+ import { hashid, keyby } from 'txstate-utils';
3
4
  export const TREE_STORE_CONTEXT = {};
5
+ const rootItems = v => v.rootItems;
4
6
  export class TreeStore extends ActiveStore {
5
7
  fetchChildren;
6
8
  treeElement;
7
- rootItems = derivedStore(this, 'rootItems');
9
+ rootItems = derived(this, rootItems);
8
10
  draggable = derivedStore(this, v => v.draggable && !v.loading);
9
11
  dragging = derivedStore(this, 'dragging');
10
12
  selectedUndraggable = derivedStore(this, 'selectedUndraggable');
@@ -29,7 +31,7 @@ export class TreeStore extends ActiveStore {
29
31
  }
30
32
  async visit(item, cb) {
31
33
  await cb(item);
32
- await Promise.all((item.children ?? []).map(async (child) => await this.visit(child, cb)));
34
+ await Promise.all((item.children ?? []).map(async (child) => { await this.visit(child, cb); }));
33
35
  }
34
36
  visitSync(item, cb) {
35
37
  cb(item);
@@ -77,15 +79,17 @@ export class TreeStore extends ActiveStore {
77
79
  try {
78
80
  const children = await this.fetch(item);
79
81
  // re-open any open children
80
- await Promise.all(children.map(async (child) => await this.visit(child, async (child) => {
81
- child.open = this.value.itemsById[child.id]?.open;
82
- if (child.open) {
83
- child.children = await this.fetch(child);
84
- child.hasChildren = child.children.length > 0;
85
- if (!child.hasChildren)
86
- child.open = false;
87
- }
88
- })));
82
+ await Promise.all(children.map(async (child) => {
83
+ await this.visit(child, async (child) => {
84
+ child.open = this.value.itemsById[child.id]?.open;
85
+ if (child.open) {
86
+ child.children = await this.fetch(child);
87
+ child.hasChildren = child.children.length > 0;
88
+ if (!child.hasChildren)
89
+ child.open = false;
90
+ }
91
+ });
92
+ }));
89
93
  if (item) {
90
94
  this.visitSync(item, itm => { if (itm.id !== item.id)
91
95
  this.value.itemsById[itm.id] = undefined; });
@@ -336,3 +340,8 @@ export class TreeStore extends ActiveStore {
336
340
  this.trigger();
337
341
  }
338
342
  }
343
+ export const hashedIds = {};
344
+ export function getHashId(str) {
345
+ hashedIds[str] ??= hashid(str);
346
+ return hashedIds[str];
347
+ }
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@dosgato/dialog",
3
3
  "description": "A component library for building forms that edit a JSON document.",
4
- "version": "0.0.45",
4
+ "version": "0.0.47",
5
5
  "scripts": {
6
6
  "prepublishOnly": "svelte-package",
7
7
  "dev": "vite dev --force",
@@ -10,14 +10,17 @@
10
10
  "check:watch": "svelte-check --tsconfig ./tsconfig.json --watch",
11
11
  "lint": "eslint --ignore-path .gitignore ."
12
12
  },
13
+ "main": "./dist/index.js",
13
14
  "exports": {
14
15
  ".": {
15
16
  "types": "./dist/index.d.ts",
16
- "svelte": "./dist/index.js"
17
- }
17
+ "svelte": "./dist/index.js",
18
+ "import": "./dist/index.js"
19
+ },
20
+ "./package.json": "./package.json"
18
21
  },
19
22
  "dependencies": {
20
- "@txstate-mws/svelte-components": "^1.3.9",
23
+ "@txstate-mws/svelte-components": "^1.4.5",
21
24
  "@txstate-mws/svelte-forms": "^1.3.4",
22
25
  "@iconify/svelte": "^3.0.0",
23
26
  "@iconify-icons/mdi": "^1.2.22",