@dosgato/dialog 0.0.19 → 0.0.21

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 (95) hide show
  1. package/Button.svelte +77 -0
  2. package/Button.svelte.d.ts +30 -0
  3. package/ButtonGroup.svelte.d.ts +3 -3
  4. package/Checkbox.svelte +2 -1
  5. package/Checkbox.svelte.d.ts +4 -3
  6. package/Container.svelte +18 -19
  7. package/Container.svelte.d.ts +5 -3
  8. package/Dialog.svelte +155 -0
  9. package/Dialog.svelte.d.ts +50 -0
  10. package/FieldAutocomplete.svelte +4 -7
  11. package/FieldAutocomplete.svelte.d.ts +4 -4
  12. package/FieldCheckbox.svelte +3 -2
  13. package/FieldCheckbox.svelte.d.ts +5 -4
  14. package/FieldChoices.svelte +3 -2
  15. package/FieldChoices.svelte.d.ts +4 -3
  16. package/FieldChooserLink.svelte +17 -13
  17. package/FieldChooserLink.svelte.d.ts +4 -5
  18. package/FieldDate.svelte +3 -2
  19. package/FieldDate.svelte.d.ts +4 -3
  20. package/FieldDateTime.svelte +3 -2
  21. package/FieldDateTime.svelte.d.ts +4 -3
  22. package/FieldDualListbox.svelte.d.ts +3 -3
  23. package/FieldHidden.svelte.d.ts +3 -3
  24. package/FieldIdentifier.svelte.d.ts +3 -3
  25. package/FieldMultiple.svelte +14 -7
  26. package/FieldMultiple.svelte.d.ts +6 -3
  27. package/FieldMultiselect.svelte +29 -22
  28. package/FieldMultiselect.svelte.d.ts +3 -3
  29. package/FieldNumber.svelte +3 -2
  30. package/FieldNumber.svelte.d.ts +4 -3
  31. package/FieldRadio.svelte +9 -4
  32. package/FieldRadio.svelte.d.ts +9 -3
  33. package/FieldSelect.svelte +9 -3
  34. package/FieldSelect.svelte.d.ts +9 -3
  35. package/FieldStandard.svelte +8 -3
  36. package/FieldStandard.svelte.d.ts +9 -3
  37. package/FieldText.svelte +3 -2
  38. package/FieldText.svelte.d.ts +4 -3
  39. package/FieldTextArea.svelte +5 -3
  40. package/FieldTextArea.svelte.d.ts +4 -3
  41. package/FileIcon.svelte.d.ts +3 -3
  42. package/Form.svelte +3 -3
  43. package/Form.svelte.d.ts +3 -3
  44. package/FormDialog.svelte +34 -0
  45. package/FormDialog.svelte.d.ts +38 -0
  46. package/Icon.svelte.d.ts +3 -3
  47. package/InlineMessage.svelte.d.ts +3 -3
  48. package/InlineMessages.svelte.d.ts +3 -3
  49. package/Input.svelte +4 -1
  50. package/Input.svelte.d.ts +4 -3
  51. package/Listbox.svelte.d.ts +3 -3
  52. package/Radio.svelte +5 -2
  53. package/Radio.svelte.d.ts +4 -3
  54. package/Tab.svelte +3 -2
  55. package/Tab.svelte.d.ts +3 -3
  56. package/TabStore.d.ts +11 -1
  57. package/TabStore.js +30 -3
  58. package/Tabs.svelte +66 -18
  59. package/Tabs.svelte.d.ts +5 -7
  60. package/chooser/Chooser.svelte +76 -99
  61. package/chooser/Chooser.svelte.d.ts +5 -5
  62. package/chooser/ChooserAPI.d.ts +10 -3
  63. package/chooser/ChooserStore.d.ts +15 -33
  64. package/chooser/ChooserStore.js +32 -149
  65. package/chooser/Details.svelte.d.ts +6 -5
  66. package/chooser/Thumbnail.svelte +9 -2
  67. package/chooser/Thumbnail.svelte.d.ts +6 -5
  68. package/colorpicker/FieldColorPicker.svelte +78 -24
  69. package/colorpicker/FieldColorPicker.svelte.d.ts +5 -6
  70. package/fileIcons.d.ts +2 -1
  71. package/helpers.d.ts +1 -0
  72. package/helpers.js +5 -0
  73. package/iconpicker/FieldIconPicker.svelte +4 -2
  74. package/iconpicker/FieldIconPicker.svelte.d.ts +4 -3
  75. package/index.d.ts +7 -0
  76. package/index.js +7 -0
  77. package/package.json +20 -13
  78. package/tree/LoadIcon.svelte +24 -0
  79. package/tree/LoadIcon.svelte.d.ts +23 -0
  80. package/tree/Tree.svelte +203 -0
  81. package/tree/Tree.svelte.d.ts +28 -0
  82. package/tree/TreeCell.svelte +18 -0
  83. package/tree/TreeCell.svelte.d.ts +18 -0
  84. package/tree/TreeNode.svelte +418 -0
  85. package/tree/TreeNode.svelte.d.ts +30 -0
  86. package/tree/index.d.ts +3 -0
  87. package/tree/index.js +3 -0
  88. package/tree/treestore.d.ts +117 -0
  89. package/tree/treestore.js +336 -0
  90. package/chooser/Asset.svelte +0 -83
  91. package/chooser/Asset.svelte.d.ts +0 -25
  92. package/chooser/AssetFolder.svelte +0 -127
  93. package/chooser/AssetFolder.svelte.d.ts +0 -25
  94. package/chooser/Page.svelte +0 -121
  95. package/chooser/Page.svelte.d.ts +0 -25
@@ -15,15 +15,16 @@ declare const __propDef: {
15
15
  required?: boolean;
16
16
  use?: HTMLActionEntry[];
17
17
  inputelement?: HTMLInputElement;
18
+ helptext?: string | undefined;
18
19
  };
19
20
  events: {
20
21
  [evt: string]: CustomEvent<any>;
21
22
  };
22
23
  slots: {};
23
24
  };
24
- export declare type FieldTextProps = typeof __propDef.props;
25
- export declare type FieldTextEvents = typeof __propDef.events;
26
- export declare type FieldTextSlots = typeof __propDef.slots;
25
+ export type FieldTextProps = typeof __propDef.props;
26
+ export type FieldTextEvents = typeof __propDef.events;
27
+ export type FieldTextSlots = typeof __propDef.slots;
27
28
  export default class FieldText extends SvelteComponentTyped<FieldTextProps, FieldTextEvents, FieldTextSlots> {
28
29
  }
29
30
  export {};
@@ -1,4 +1,5 @@
1
- <script>import { passActions } from '@txstate-mws/svelte-components';
1
+ <script>import { getDescribedBy } from './';
2
+ import { passActions } from '@txstate-mws/svelte-components';
2
3
  import { nullableSerialize, nullableDeserialize } from '@txstate-mws/svelte-forms';
3
4
  import FieldStandard from './FieldStandard.svelte';
4
5
  let className = '';
@@ -14,10 +15,11 @@ export let conditional = undefined;
14
15
  export let required = false;
15
16
  export let use = [];
16
17
  export let inputelement = undefined;
18
+ export let helptext = undefined;
17
19
  </script>
18
20
 
19
- <FieldStandard bind:id {label} {path} {required} {defaultValue} {conditional} serialize={!notNull && nullableSerialize} deserialize={!notNull && nullableDeserialize} let:value let:valid let:invalid let:id let:onBlur let:onChange let:messagesid>
20
- <textarea bind:this={inputelement} name={path} {value} {id} {rows} class="dialog-input dialog-textarea {className}" class:valid class:invalid aria-invalid={invalid} aria-describedby={messagesid} on:change={onChange} on:blur={onBlur} on:keyup={onChange} on:paste {maxlength} use:passActions={use}></textarea>
21
+ <FieldStandard bind:id {label} {path} {required} {defaultValue} {conditional} {helptext} serialize={!notNull && nullableSerialize} deserialize={!notNull && nullableDeserialize} 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>
21
23
  </FieldStandard>
22
24
 
23
25
  <style>
@@ -14,6 +14,7 @@ declare const __propDef: {
14
14
  required?: boolean;
15
15
  use?: HTMLActionEntry[];
16
16
  inputelement?: HTMLTextAreaElement;
17
+ helptext?: string | undefined;
17
18
  };
18
19
  events: {
19
20
  paste: ClipboardEvent;
@@ -22,9 +23,9 @@ declare const __propDef: {
22
23
  };
23
24
  slots: {};
24
25
  };
25
- export declare type FieldTextAreaProps = typeof __propDef.props;
26
- export declare type FieldTextAreaEvents = typeof __propDef.events;
27
- export declare type FieldTextAreaSlots = typeof __propDef.slots;
26
+ export type FieldTextAreaProps = typeof __propDef.props;
27
+ export type FieldTextAreaEvents = typeof __propDef.events;
28
+ export type FieldTextAreaSlots = typeof __propDef.slots;
28
29
  export default class FieldTextArea extends SvelteComponentTyped<FieldTextAreaProps, FieldTextAreaEvents, FieldTextAreaSlots> {
29
30
  }
30
31
  export {};
@@ -13,9 +13,9 @@ declare const __propDef: {
13
13
  };
14
14
  slots: {};
15
15
  };
16
- export declare type FileIconProps = typeof __propDef.props;
17
- export declare type FileIconEvents = typeof __propDef.events;
18
- export declare type FileIconSlots = typeof __propDef.slots;
16
+ export type FileIconProps = typeof __propDef.props;
17
+ export type FileIconEvents = typeof __propDef.events;
18
+ export type FileIconSlots = typeof __propDef.slots;
19
19
  export default class FileIcon extends SvelteComponentTyped<FileIconProps, FileIconEvents, FileIconSlots> {
20
20
  }
21
21
  export {};
package/Form.svelte CHANGED
@@ -13,8 +13,8 @@ export let preload = undefined;
13
13
  setContext(CHOOSER_API_CONTEXT, chooserClient);
14
14
  </script>
15
15
 
16
- <Form bind:store class="{className} dialog-form" {submit} {validate} on:saved {autocomplete} {name} {preload} let:messages let:showingInlineErrors let:saved let:valid let:invalid let:validating let:submitting>
17
- <slot {messages} {saved} {validating} {submitting} {valid} {invalid} />
16
+ <Form bind:store class="{className} dialog-form" {submit} {validate} on:saved {autocomplete} {name} {preload} let:messages let:showingInlineErrors let:saved let:valid let:invalid let:validating let:submitting let:data>
17
+ <slot {messages} {saved} {validating} {submitting} {valid} {invalid} {data} />
18
18
  <div class="form-errors" aria-live='assertive'>
19
19
  {#if messages.length}
20
20
  <ul>
@@ -40,7 +40,7 @@ setContext(CHOOSER_API_CONTEXT, chooserClient);
40
40
  padding: 0;
41
41
  }
42
42
  .form-errors {
43
- color: #9a3332;
43
+ color: var(--dg-danger-bg, #9a3332);
44
44
  padding: 1em;
45
45
  }
46
46
  </style>
package/Form.svelte.d.ts CHANGED
@@ -6,9 +6,9 @@ declare class __sveltets_Render<T, F> {
6
6
  };
7
7
  slots(): any;
8
8
  }
9
- export declare type FormProps<T, F> = ReturnType<__sveltets_Render<T, F>['props']>;
10
- export declare type FormEvents<T, F> = ReturnType<__sveltets_Render<T, F>['events']>;
11
- export declare type FormSlots<T, F> = ReturnType<__sveltets_Render<T, F>['slots']>;
9
+ export type FormProps<T, F> = ReturnType<__sveltets_Render<T, F>['props']>;
10
+ export type FormEvents<T, F> = ReturnType<__sveltets_Render<T, F>['events']>;
11
+ export type FormSlots<T, F> = ReturnType<__sveltets_Render<T, F>['slots']>;
12
12
  export default class Form<T, F> extends SvelteComponentTyped<FormProps<T, F>, FormEvents<T, F>, FormSlots<T, F>> {
13
13
  }
14
14
  export {};
@@ -0,0 +1,34 @@
1
+ <script>import contentSave from '@iconify-icons/mdi/content-save';
2
+ import { createEventDispatcher, setContext } from 'svelte';
3
+ import { CHOOSER_API_CONTEXT, Form } from './';
4
+ import Dialog from './Dialog.svelte';
5
+ export let submit;
6
+ export let validate = undefined;
7
+ export let store = undefined;
8
+ export let chooserClient = undefined;
9
+ export let autocomplete = undefined;
10
+ export let name = undefined;
11
+ export let title = '';
12
+ export let icon = undefined;
13
+ export let size = 'normal';
14
+ export let preload = undefined;
15
+ const dispatch = createEventDispatcher();
16
+ async function onSubmit() {
17
+ const resp = await store.submit();
18
+ if (resp.success)
19
+ dispatch('saved', resp.data);
20
+ }
21
+ setContext(CHOOSER_API_CONTEXT, chooserClient);
22
+ </script>
23
+
24
+ <Dialog continueText="Save" continueIcon={contentSave} cancelText="Cancel" on:escape on:continue={onSubmit} {title} {icon} {size}>
25
+ <Form bind:store {submit} {validate} {chooserClient} {autocomplete} {name} {preload} on:saved let:messages let:saved let:valid let:invalid let:validating let:submitting let:data>
26
+ <slot {messages} {saved} {validating} {submitting} {valid} {invalid} {data} />
27
+ </Form>
28
+ </Dialog>
29
+
30
+ <style>
31
+ :global(:root) {
32
+ --ck-z-default: var(--popup-z, 3001);
33
+ }
34
+ </style>
@@ -0,0 +1,38 @@
1
+ import { SvelteComponentTyped } from "svelte";
2
+ import type { IconifyIcon } from '@iconify/svelte';
3
+ import type { Feedback, FormStore, SubmitResponse } from '@txstate-mws/svelte-forms';
4
+ declare class __sveltets_Render<T> {
5
+ props(): {
6
+ submit: (state: T) => Promise<SubmitResponse<T>>;
7
+ validate?: (state: T) => Promise<Feedback[]>;
8
+ store?: FormStore<T>;
9
+ chooserClient?: any;
10
+ autocomplete?: string;
11
+ name?: string;
12
+ title?: string;
13
+ icon?: IconifyIcon;
14
+ size?: "small" | "normal" | "tiny" | "large";
15
+ preload?: T;
16
+ };
17
+ events(): {
18
+ saved: CustomEvent<T>;
19
+ escape: CustomEvent<undefined>;
20
+ };
21
+ slots(): {
22
+ default: {
23
+ messages: any;
24
+ saved: any;
25
+ validating: any;
26
+ submitting: any;
27
+ valid: any;
28
+ invalid: any;
29
+ data: any;
30
+ };
31
+ };
32
+ }
33
+ export type FormDialogProps<T> = ReturnType<__sveltets_Render<T>['props']>;
34
+ export type FormDialogEvents<T> = ReturnType<__sveltets_Render<T>['events']>;
35
+ export type FormDialogSlots<T> = ReturnType<__sveltets_Render<T>['slots']>;
36
+ export default class FormDialog<T> extends SvelteComponentTyped<FormDialogProps<T>, FormDialogEvents<T>, FormDialogSlots<T>> {
37
+ }
38
+ export {};
package/Icon.svelte.d.ts CHANGED
@@ -14,9 +14,9 @@ declare const __propDef: {
14
14
  };
15
15
  slots: {};
16
16
  };
17
- export declare type IconProps = typeof __propDef.props;
18
- export declare type IconEvents = typeof __propDef.events;
19
- export declare type IconSlots = typeof __propDef.slots;
17
+ export type IconProps = typeof __propDef.props;
18
+ export type IconEvents = typeof __propDef.events;
19
+ export type IconSlots = typeof __propDef.slots;
20
20
  export default class Icon extends SvelteComponentTyped<IconProps, IconEvents, IconSlots> {
21
21
  }
22
22
  export {};
@@ -9,9 +9,9 @@ declare const __propDef: {
9
9
  };
10
10
  slots: {};
11
11
  };
12
- export declare type InlineMessageProps = typeof __propDef.props;
13
- export declare type InlineMessageEvents = typeof __propDef.events;
14
- export declare type InlineMessageSlots = typeof __propDef.slots;
12
+ export type InlineMessageProps = typeof __propDef.props;
13
+ export type InlineMessageEvents = typeof __propDef.events;
14
+ export type InlineMessageSlots = typeof __propDef.slots;
15
15
  export default class InlineMessage extends SvelteComponentTyped<InlineMessageProps, InlineMessageEvents, InlineMessageSlots> {
16
16
  }
17
17
  export {};
@@ -10,9 +10,9 @@ declare const __propDef: {
10
10
  };
11
11
  slots: {};
12
12
  };
13
- export declare type InlineMessagesProps = typeof __propDef.props;
14
- export declare type InlineMessagesEvents = typeof __propDef.events;
15
- export declare type InlineMessagesSlots = typeof __propDef.slots;
13
+ export type InlineMessagesProps = typeof __propDef.props;
14
+ export type InlineMessagesEvents = typeof __propDef.events;
15
+ export type InlineMessagesSlots = typeof __propDef.slots;
16
16
  export default class InlineMessages extends SvelteComponentTyped<InlineMessagesProps, InlineMessagesEvents, InlineMessagesSlots> {
17
17
  }
18
18
  export {};
package/Input.svelte CHANGED
@@ -1,5 +1,6 @@
1
1
  <script>import { passActions } from '@txstate-mws/svelte-components';
2
2
  import { dateSerialize, datetimeSerialize } from '@txstate-mws/svelte-forms';
3
+ import { isNotBlank } from 'txstate-utils';
3
4
  let className = '';
4
5
  export { className as class };
5
6
  export let name;
@@ -13,6 +14,7 @@ export let step = undefined;
13
14
  export let id = undefined;
14
15
  export let disabled = false;
15
16
  export let messagesid = undefined;
17
+ export let helptextid = undefined;
16
18
  export let valid = false;
17
19
  export let invalid = false;
18
20
  export let onChange;
@@ -20,6 +22,7 @@ export let onBlur;
20
22
  export let onSelect = undefined;
21
23
  export let use = [];
22
24
  export let inputelement = undefined;
25
+ $: descby = [helptextid, messagesid].filter(isNotBlank).join(' ');
23
26
  function resolveMinMax(dt) {
24
27
  if (typeof dt === 'undefined')
25
28
  return undefined;
@@ -33,4 +36,4 @@ $: minStr = resolveMinMax(min);
33
36
  $: maxStr = resolveMinMax(max);
34
37
  </script>
35
38
 
36
- <input bind:this={inputelement} {type} {id} class={className} autocomplete="off" data-lpignore={!allowlastpass} {name} {value} {disabled} {maxlength} min={minStr} max={maxStr} {step} class:valid class:invalid aria-invalid={invalid} aria-describedby={messagesid} on:change={onChange} on:select={onSelect} on:blur={onBlur} on:keyup={onChange} use:passActions={use}>
39
+ <input bind:this={inputelement} {type} {id} class={className} autocomplete="off" data-lpignore={!allowlastpass} {name} {value} {disabled} {maxlength} min={minStr} max={maxStr} {step} class:valid class:invalid aria-invalid={invalid} aria-describedby={isNotBlank(descby) ? descby : null} on:change={onChange} on:select={onSelect} on:blur={onBlur} on:keyup={onChange} use:passActions={use}>
package/Input.svelte.d.ts CHANGED
@@ -18,6 +18,7 @@ declare const __propDef: {
18
18
  id?: string | undefined;
19
19
  disabled?: boolean;
20
20
  messagesid?: string | undefined;
21
+ helptextid?: string | undefined;
21
22
  valid?: boolean;
22
23
  invalid?: boolean;
23
24
  onChange: any;
@@ -31,9 +32,9 @@ declare const __propDef: {
31
32
  };
32
33
  slots: {};
33
34
  };
34
- export declare type InputProps = typeof __propDef.props;
35
- export declare type InputEvents = typeof __propDef.events;
36
- export declare type InputSlots = typeof __propDef.slots;
35
+ export type InputProps = typeof __propDef.props;
36
+ export type InputEvents = typeof __propDef.events;
37
+ export type InputSlots = typeof __propDef.slots;
37
38
  export default class Input extends SvelteComponentTyped<InputProps, InputEvents, InputSlots> {
38
39
  }
39
40
  export {};
@@ -20,9 +20,9 @@ declare const __propDef: {
20
20
  };
21
21
  slots: {};
22
22
  };
23
- export declare type ListboxProps = typeof __propDef.props;
24
- export declare type ListboxEvents = typeof __propDef.events;
25
- export declare type ListboxSlots = typeof __propDef.slots;
23
+ export type ListboxProps = typeof __propDef.props;
24
+ export type ListboxEvents = typeof __propDef.events;
25
+ export type ListboxSlots = typeof __propDef.slots;
26
26
  export default class Listbox extends SvelteComponentTyped<ListboxProps, ListboxEvents, ListboxSlots> {
27
27
  }
28
28
  export {};
package/Radio.svelte CHANGED
@@ -1,16 +1,19 @@
1
- <script>export let id = undefined;
1
+ <script>import { isNotBlank } from 'txstate-utils';
2
+ export let id = undefined;
2
3
  export let name;
3
4
  export let value;
4
5
  export let selected = false;
5
6
  export let onChange = undefined;
6
7
  export let onBlur = undefined;
7
8
  export let messagesid = undefined;
9
+ export let helptextid = undefined;
8
10
  export let disabled = false;
9
11
  export let valid = false;
10
12
  export let invalid = false;
13
+ $: descby = [messagesid, helptextid].filter(isNotBlank).join(' ');
11
14
  </script>
12
15
 
13
- <input {id} type="radio" {name} class:valid class:invalid checked={selected} {disabled} aria-describedby={messagesid} {value} on:change={onChange} on:blur={onBlur}>
16
+ <input {id} type="radio" {name} class:valid class:invalid checked={selected} {disabled} aria-describedby={descby} {value} on:change={onChange} on:blur={onBlur}>
14
17
 
15
18
  <style>
16
19
  input, input:before, input:after {
package/Radio.svelte.d.ts CHANGED
@@ -8,6 +8,7 @@ declare const __propDef: {
8
8
  onChange?: any;
9
9
  onBlur?: any;
10
10
  messagesid?: string | undefined;
11
+ helptextid?: string | undefined;
11
12
  disabled?: boolean;
12
13
  valid?: boolean;
13
14
  invalid?: boolean;
@@ -17,9 +18,9 @@ declare const __propDef: {
17
18
  };
18
19
  slots: {};
19
20
  };
20
- export declare type RadioProps = typeof __propDef.props;
21
- export declare type RadioEvents = typeof __propDef.events;
22
- export declare type RadioSlots = typeof __propDef.slots;
21
+ export type RadioProps = typeof __propDef.props;
22
+ export type RadioEvents = typeof __propDef.events;
23
+ export type RadioSlots = typeof __propDef.slots;
23
24
  export default class Radio extends SvelteComponentTyped<RadioProps, RadioEvents, RadioSlots> {
24
25
  }
25
26
  export {};
package/Tab.svelte CHANGED
@@ -20,8 +20,9 @@ const last = idx === $store.tabs.length - 1;
20
20
  <style>
21
21
  .tabs-panel {
22
22
  width: 100%;
23
- border: var(--tabs-panel-border, var(--tabs-border, 1px solid #666666));
24
- padding: var(--tabs-panel-padding, 1em);
23
+ min-height: 50vh;
24
+ border: var(--tabs-panel-border, var(--tabs-border, 0));
25
+ padding: var(--tabs-margin-top, 2em) var(--tabs-padding-hori, 0.7em) 0 var(--tabs-padding-hori, 0.7em);
25
26
  }
26
27
  .tabs-panel.accordion {
27
28
  border-left: 0;
package/Tab.svelte.d.ts CHANGED
@@ -10,9 +10,9 @@ declare const __propDef: {
10
10
  default: {};
11
11
  };
12
12
  };
13
- export declare type TabProps = typeof __propDef.props;
14
- export declare type TabEvents = typeof __propDef.events;
15
- export declare type TabSlots = typeof __propDef.slots;
13
+ export type TabProps = typeof __propDef.props;
14
+ export type TabEvents = typeof __propDef.events;
15
+ export type TabSlots = typeof __propDef.slots;
16
16
  export default class Tab extends SvelteComponentTyped<TabProps, TabEvents, TabSlots> {
17
17
  }
18
18
  export {};
package/TabStore.d.ts CHANGED
@@ -2,19 +2,28 @@ import { Store } from '@txstate-mws/svelte-store';
2
2
  import type { ElementSize } from '@txstate-mws/svelte-components';
3
3
  import type { IconifyIcon } from '@iconify/svelte';
4
4
  export declare const TAB_CONTEXT: {};
5
- interface TabDef {
5
+ export interface TabDef {
6
+ name?: string;
6
7
  title: string;
7
8
  icon?: IconifyIcon;
9
+ required?: boolean;
8
10
  }
9
11
  interface ITabStore extends ElementSize {
10
12
  current?: number;
13
+ prevTitle?: string;
14
+ nextTitle?: string;
15
+ requireNext: boolean;
11
16
  tabs: TabDef[];
17
+ visited: Record<string, boolean>;
12
18
  tabids: Record<string, string>;
13
19
  panelids: Record<string, string>;
14
20
  }
15
21
  export declare class TabStore extends Store<ITabStore> {
16
22
  initialTab?: string | undefined;
17
23
  constructor(tabs: TabDef[], initialTab?: string | undefined);
24
+ set(v: ITabStore): void;
25
+ currentIdx(): import("@txstate-mws/svelte-store").DerivedStore<number, ITabStore>;
26
+ currentName(): import("@txstate-mws/svelte-store").DerivedStore<string, ITabStore>;
18
27
  currentTitle(): import("@txstate-mws/svelte-store").DerivedStore<string, ITabStore>;
19
28
  currentTabId(): import("@txstate-mws/svelte-store").DerivedStore<string, ITabStore>;
20
29
  currentPanelId(): import("@txstate-mws/svelte-store").DerivedStore<string, ITabStore>;
@@ -24,5 +33,6 @@ export declare class TabStore extends Store<ITabStore> {
24
33
  home(): void;
25
34
  end(): void;
26
35
  activate(idx: number): void;
36
+ activateName(name: string): void;
27
37
  }
28
38
  export {};
package/TabStore.js CHANGED
@@ -1,18 +1,42 @@
1
1
  import { Store, derivedStore } from '@txstate-mws/svelte-store';
2
2
  import { findIndex, randomid } from 'txstate-utils';
3
3
  export const TAB_CONTEXT = {};
4
+ function checkNext(v) {
5
+ v.visited = { ...v.visited, [v.tabs[v.current].title]: true };
6
+ v.prevTitle = v.current > 0 ? v.tabs[v.current - 1].title : undefined;
7
+ v.nextTitle = v.tabs.length - 1 > v.current ? v.tabs[v.current + 1].title : undefined;
8
+ v.requireNext = v.tabs.some((t, i) => t.required && !v.visited[t.title]);
9
+ return v;
10
+ }
4
11
  export class TabStore extends Store {
5
12
  initialTab;
6
13
  constructor(tabs, initialTab) {
7
- super({
14
+ const current = findIndex(tabs, t => t.title === initialTab, 0);
15
+ super(checkNext({
8
16
  tabs,
9
- current: findIndex(tabs, t => t.title === initialTab, 0),
17
+ current,
18
+ visited: {},
10
19
  tabids: tabs.reduce((acc, curr) => ({ ...acc, [curr.title]: randomid() }), {}),
11
20
  panelids: tabs.reduce((acc, curr) => ({ ...acc, [curr.title]: randomid() }), {}),
12
21
  clientWidth: 1024
13
- });
22
+ }));
14
23
  this.initialTab = initialTab;
15
24
  }
25
+ set(v) {
26
+ v.tabids ??= {};
27
+ v.panelids ??= {};
28
+ for (const tab of v.tabs) {
29
+ v.tabids[tab.title] ??= randomid();
30
+ v.panelids[tab.title] ??= randomid();
31
+ }
32
+ super.set(checkNext(v));
33
+ }
34
+ currentIdx() {
35
+ return derivedStore(this, v => v.current);
36
+ }
37
+ currentName() {
38
+ return derivedStore(this, v => v.tabs[v.current].name ?? v.tabs[v.current].title);
39
+ }
16
40
  currentTitle() {
17
41
  return derivedStore(this, v => v.tabs[v.current].title);
18
42
  }
@@ -40,4 +64,7 @@ export class TabStore extends Store {
40
64
  activate(idx) {
41
65
  this.update(v => ({ ...v, current: Math.min(v.tabs.length, Math.max(0, idx)) }));
42
66
  }
67
+ activateName(name) {
68
+ this.update(v => ({ ...v, current: findIndex(v.tabs, t => t.name === name) ?? findIndex(v.tabs, t => t.title === name) ?? v.current }));
69
+ }
43
70
  }
package/Tabs.svelte CHANGED
@@ -1,20 +1,33 @@
1
- <script>import { modifierKey, resize } from '@txstate-mws/svelte-components';
2
- import { setContext } from 'svelte';
1
+ <script>import { modifierKey, resize, offset } from '@txstate-mws/svelte-components';
2
+ import { Store } from '@txstate-mws/svelte-store';
3
+ import { getContext, onMount, setContext } from 'svelte';
3
4
  import { roundTo } from 'txstate-utils';
5
+ import { DIALOG_TABS_CONTEXT } from './Dialog.svelte';
4
6
  import Icon from './Icon.svelte';
5
7
  import { TabStore, TAB_CONTEXT } from './TabStore';
6
8
  export let tabs;
7
9
  export let active = undefined;
8
10
  export let store = new TabStore(tabs, active);
11
+ $: store.update(v => ({ ...v, tabs }));
12
+ const activeStore = new Store({});
9
13
  const tabelements = [];
14
+ let activeelement;
10
15
  setContext(TAB_CONTEXT, { store, onClick, onKeyDown, tabelements });
11
- const current = store.currentTitle();
16
+ const dialogContext = getContext(DIALOG_TABS_CONTEXT) ?? { change: () => { } };
17
+ dialogContext.onNext = () => { store.right(); };
18
+ dialogContext.onPrev = () => { store.left(); };
19
+ $: dialogContext.prevTitle = $store.prevTitle;
20
+ $: dialogContext.nextTitle = $store.nextTitle;
21
+ $: dialogContext.hasRequired = $store.requireNext;
22
+ $: dialogContext.change($store);
23
+ setContext(DIALOG_TABS_CONTEXT, { change: () => { } }); // reset context so that any sub-tabs do NOT control the Dialog component
24
+ const currentTitle = store.currentTitle();
25
+ const currentIdx = store.currentIdx();
12
26
  const accordion = store.accordion();
13
27
  $: cols = Math.min(Math.floor($store.clientWidth / 90), $store.tabs.length);
14
28
  $: scalefactor = Math.min(roundTo($store.clientWidth / (cols * 130), 4), 1);
15
- $: width = `calc(${100 / cols}% + 1px)`;
16
- $: widthleft = `${100 / cols}%`;
17
29
  $: wrapping = cols !== $store.tabs.length;
30
+ $: dialogContext.hasTabs = !$accordion;
18
31
  function onClick(idx) {
19
32
  return () => store.activate(idx);
20
33
  }
@@ -50,17 +63,35 @@ function onKeyDown(idx) {
50
63
  function isActive(idx, activeidx) {
51
64
  return idx === (activeidx ?? 0);
52
65
  }
53
- $: active = $current;
66
+ const activeOversize = 2;
67
+ async function reactToCurrent(..._) {
68
+ if (!activeelement)
69
+ return;
70
+ const tabelement = tabelements[$currentIdx];
71
+ if (!tabelement)
72
+ return;
73
+ const span = tabelement.querySelector(':scope > span');
74
+ if (!span)
75
+ return;
76
+ const left = span.offsetLeft - activeelement.offsetLeft - activeOversize;
77
+ const width = span.offsetWidth + (activeOversize * 2);
78
+ activeelement.style.transform = `translateX(${left}px)`;
79
+ activeelement.style.width = `${width}px`;
80
+ }
81
+ $: active = $currentTitle;
82
+ $: reactToCurrent($activeStore);
83
+ onMount(reactToCurrent);
54
84
  </script>
55
85
 
56
86
  {#if !$accordion}
57
- <ul use:resize={{ store }} class="dialog-tab-buttons" role="tablist">
87
+ <ul use:resize={{ store }} class="tabs-buttons" role="tablist">
58
88
  {#each $store.tabs as tab, idx (tab.title)}
59
- {@const active = isActive(idx, $store.current)}
60
- {@const left = idx % cols === 0}
61
- <li bind:this={tabelements[idx]} id={$store.tabids[tab.title]} class="tabs-tab" class:left class:wrapping class:active style:font-size="{scalefactor}em" style:line-height={1.2 / scalefactor} style:width={left ? widthleft : width} aria-selected={active} aria-controls={$store.panelids[tab.title]} role="tab" tabindex={active ? 0 : -1} on:click={onClick(idx)} on:keydown={onKeyDown(idx)}><Icon icon={tab.icon} inline />{tab.title}</li>
89
+ {@const active = isActive(idx, $store.current)}
90
+ {@const left = idx % cols === 0}
91
+ <li bind:this={tabelements[idx]} use:offset={{ store: active ? activeStore : undefined }} id={$store.tabids[tab.title]} class="tabs-tab" class:left class:wrapping class:active style:font-size="{scalefactor}em" style:line-height={1.2 / scalefactor} aria-selected={active} aria-controls={$store.panelids[tab.title]} role="tab" tabindex={active ? 0 : -1} on:click={onClick(idx)} on:keydown={onKeyDown(idx)}><span><Icon icon={tab.icon} inline />{tab.title}</span></li>
62
92
  {/each}
63
93
  </ul>
94
+ <div bind:this={activeelement} class="tabs-active"></div>
64
95
  <slot current={$store.current} />
65
96
  {:else}
66
97
  <div use:resize={{ store }} class="tabs-container">
@@ -70,6 +101,7 @@ $: active = $current;
70
101
 
71
102
  <style>
72
103
  .tabs-container {
104
+ position: relative;
73
105
  display: flex;
74
106
  flex-wrap: wrap;
75
107
  border-radius: var(--tabs-radius, 0.6em);
@@ -84,22 +116,38 @@ $: active = $current;
84
116
  list-style-type: none;
85
117
  display: flex;
86
118
  flex-wrap: wrap;
119
+ justify-content: flex-start;
120
+ font-size: 0.9em;
87
121
  }
88
122
  li, .tabs-container :global(.tabs-tab) {
89
- padding: var(--tabs-padding, 0.7em 1em);
123
+ padding: var(--tabs-padding-vert, 0.7em) var(--tabs-padding-hori, 1em);
90
124
  cursor: pointer;
91
125
  word-break: break-word;
92
- }
93
- li {
94
- border: var(--tabs-border, 1px solid #666666);
95
- border-top-left-radius: var(--tabs-radius, 0.6em);
96
- border-top-right-radius: var(--tabs-radius, 0.6em);
126
+ text-transform: uppercase;
127
+ font-weight: 500;
128
+ color: var(--tabs-text, #363534)
97
129
  }
98
130
  li:not(.left) {
99
131
  margin-left: -1px;
100
132
  }
133
+
101
134
  li:global(.tabs-tab[aria-selected="true"]), .tabs-container :global(.tabs-tab[aria-selected="true"]) {
102
- color: var(--tabs-active-text, #ffffff);
103
- background-color: var(--tabs-active-bg, #333333);
135
+ font-weight: 700;
136
+ }
137
+
138
+ .tabs-active {
139
+ background: var(--dg-tabs-active, var(--dg-button-bg, #501214));
140
+ height: 3px;
141
+ border-radius: 2px;
142
+ overflow: hidden;
143
+ width: 0px;
144
+ margin-top: calc(-1 * var(--tabs-padding-vert, 0.7em));
145
+ margin-bottom: var(--tabs-padding-vert, 0.7em);
146
+ transition: 0.2s transform;
147
+ }
148
+ @media (prefers-reduced-motion) {
149
+ .tabs-active {
150
+ transition: none;
151
+ }
104
152
  }
105
153
  </style>
package/Tabs.svelte.d.ts CHANGED
@@ -1,10 +1,8 @@
1
1
  import { SvelteComponentTyped } from "svelte";
2
- import { TabStore } from './TabStore';
2
+ import { TabStore, type TabDef } from './TabStore';
3
3
  declare const __propDef: {
4
4
  props: {
5
- tabs: {
6
- title: string;
7
- }[];
5
+ tabs: TabDef[];
8
6
  active?: string | undefined;
9
7
  store?: TabStore;
10
8
  };
@@ -17,9 +15,9 @@ declare const __propDef: {
17
15
  };
18
16
  };
19
17
  };
20
- export declare type TabsProps = typeof __propDef.props;
21
- export declare type TabsEvents = typeof __propDef.events;
22
- export declare type TabsSlots = typeof __propDef.slots;
18
+ export type TabsProps = typeof __propDef.props;
19
+ export type TabsEvents = typeof __propDef.events;
20
+ export type TabsSlots = typeof __propDef.slots;
23
21
  export default class Tabs extends SvelteComponentTyped<TabsProps, TabsEvents, TabsSlots> {
24
22
  }
25
23
  export {};