@dosgato/dialog 0.0.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.
- package/ButtonGroup.svelte +74 -0
- package/ButtonGroup.svelte.d.ts +28 -0
- package/Checkbox.svelte +68 -0
- package/Checkbox.svelte.d.ts +25 -0
- package/Container.svelte +86 -0
- package/Container.svelte.d.ts +25 -0
- package/FieldCheckbox.svelte +28 -0
- package/FieldCheckbox.svelte.d.ts +23 -0
- package/FieldChoices.svelte +75 -0
- package/FieldChoices.svelte.d.ts +28 -0
- package/FieldChooserLink.svelte +100 -0
- package/FieldChooserLink.svelte.d.ts +30 -0
- package/FieldDate.svelte +19 -0
- package/FieldDate.svelte.d.ts +29 -0
- package/FieldDateTime.svelte +19 -0
- package/FieldDateTime.svelte.d.ts +29 -0
- package/FieldMultiple.svelte +83 -0
- package/FieldMultiple.svelte.d.ts +33 -0
- package/FieldMultiselect.svelte +50 -0
- package/FieldMultiselect.svelte.d.ts +25 -0
- package/FieldNumber.svelte +20 -0
- package/FieldNumber.svelte.d.ts +26 -0
- package/FieldRadio.svelte +52 -0
- package/FieldRadio.svelte.d.ts +29 -0
- package/FieldSelect.svelte +24 -0
- package/FieldSelect.svelte.d.ts +30 -0
- package/FieldStandard.svelte +19 -0
- package/FieldStandard.svelte.d.ts +36 -0
- package/FieldText.svelte +20 -0
- package/FieldText.svelte.d.ts +26 -0
- package/FileIcon.svelte +56 -0
- package/FileIcon.svelte.d.ts +21 -0
- package/Form.svelte +56 -0
- package/Form.svelte.d.ts +9 -0
- package/Icon.svelte +16 -0
- package/Icon.svelte.d.ts +22 -0
- package/InlineMessage.svelte +42 -0
- package/InlineMessage.svelte.d.ts +17 -0
- package/InlineMessages.svelte +21 -0
- package/InlineMessages.svelte.d.ts +18 -0
- package/Input.svelte +33 -0
- package/Input.svelte.d.ts +36 -0
- package/LICENSE +21 -0
- package/README.md +38 -0
- package/Radio.svelte +65 -0
- package/Radio.svelte.d.ts +25 -0
- package/Tab.svelte +57 -0
- package/Tab.svelte.d.ts +18 -0
- package/TabStore.d.ts +28 -0
- package/TabStore.js +42 -0
- package/Tabs.svelte +105 -0
- package/Tabs.svelte.d.ts +25 -0
- package/chooser/Asset.svelte +77 -0
- package/chooser/Asset.svelte.d.ts +25 -0
- package/chooser/AssetFolder.svelte +124 -0
- package/chooser/AssetFolder.svelte.d.ts +25 -0
- package/chooser/Chooser.svelte +169 -0
- package/chooser/Chooser.svelte.d.ts +30 -0
- package/chooser/ChooserAPI.d.ts +48 -0
- package/chooser/ChooserAPI.js +1 -0
- package/chooser/ChooserStore.d.ts +72 -0
- package/chooser/ChooserStore.js +200 -0
- package/chooser/Details.svelte +29 -0
- package/chooser/Details.svelte.d.ts +19 -0
- package/chooser/Page.svelte +118 -0
- package/chooser/Page.svelte.d.ts +25 -0
- package/chooser/Thumbnail.svelte +40 -0
- package/chooser/Thumbnail.svelte.d.ts +17 -0
- package/chooser/index.d.ts +6 -0
- package/chooser/index.js +6 -0
- package/index.d.ts +24 -0
- package/index.js +24 -0
- package/package.json +63 -0
package/Icon.svelte
ADDED
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
<script >import Icon from '@iconify/svelte/dist/OfflineIcon.svelte';
|
|
2
|
+
import { ScreenReaderOnly } from '@txstate-mws/svelte-components';
|
|
3
|
+
export let icon;
|
|
4
|
+
export let hiddenLabel = undefined;
|
|
5
|
+
export let inline = false;
|
|
6
|
+
export let width = '1em';
|
|
7
|
+
export let height = width;
|
|
8
|
+
export let vAlign = 'middle';
|
|
9
|
+
</script>
|
|
10
|
+
|
|
11
|
+
{#if icon}
|
|
12
|
+
<Icon {icon} {inline} {width} {height} {vAlign} aria-hidden={!hiddenLabel} />
|
|
13
|
+
{#if hiddenLabel}
|
|
14
|
+
<ScreenReaderOnly>{hiddenLabel}</ScreenReaderOnly>
|
|
15
|
+
{/if}
|
|
16
|
+
{/if}
|
package/Icon.svelte.d.ts
ADDED
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import { SvelteComponentTyped } from "svelte";
|
|
2
|
+
import type { IconifyIcon } from '@iconify/svelte';
|
|
3
|
+
declare const __propDef: {
|
|
4
|
+
props: {
|
|
5
|
+
icon: IconifyIcon | undefined;
|
|
6
|
+
hiddenLabel?: string;
|
|
7
|
+
inline?: boolean;
|
|
8
|
+
width?: string | number;
|
|
9
|
+
height?: string | number;
|
|
10
|
+
vAlign?: 'top' | 'middle' | 'bottom';
|
|
11
|
+
};
|
|
12
|
+
events: {
|
|
13
|
+
[evt: string]: CustomEvent<any>;
|
|
14
|
+
};
|
|
15
|
+
slots: {};
|
|
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;
|
|
20
|
+
export default class Icon extends SvelteComponentTyped<IconProps, IconEvents, IconSlots> {
|
|
21
|
+
}
|
|
22
|
+
export {};
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
<script >import alertCircleOutline from '@iconify/icons-mdi/alert-circle-outline.js';
|
|
2
|
+
import checkCircleOutline from '@iconify/icons-mdi/check-circle-outline.js';
|
|
3
|
+
import informationOutline from '@iconify/icons-mdi/information-outline.js';
|
|
4
|
+
import closeOctagonOutline from '@iconify/icons-mdi/close-octagon-outline.js';
|
|
5
|
+
import Icon from './Icon.svelte';
|
|
6
|
+
export let message;
|
|
7
|
+
const icons = {
|
|
8
|
+
error: alertCircleOutline,
|
|
9
|
+
warning: informationOutline,
|
|
10
|
+
success: checkCircleOutline,
|
|
11
|
+
system: closeOctagonOutline
|
|
12
|
+
};
|
|
13
|
+
$: icon = icons[message.type] ?? alertCircleOutline;
|
|
14
|
+
</script>
|
|
15
|
+
|
|
16
|
+
<div class={message.type}><Icon width='1.5em' {icon} hiddenLabel='Error' /><span>{message.message}</span></div>
|
|
17
|
+
|
|
18
|
+
<style>
|
|
19
|
+
div {
|
|
20
|
+
font-size: 0.9em;
|
|
21
|
+
padding: 5px;
|
|
22
|
+
margin-top: 0.5em;
|
|
23
|
+
display: flex;
|
|
24
|
+
align-items: center;
|
|
25
|
+
}
|
|
26
|
+
span {
|
|
27
|
+
display: block;
|
|
28
|
+
margin-left: 0.5em;
|
|
29
|
+
}
|
|
30
|
+
div.error, div.system {
|
|
31
|
+
background-color: #9a3332;
|
|
32
|
+
color: white;
|
|
33
|
+
}
|
|
34
|
+
div.warning {
|
|
35
|
+
background-color: #ffc107;
|
|
36
|
+
color: black;
|
|
37
|
+
}
|
|
38
|
+
div.success {
|
|
39
|
+
background-color: #218739;
|
|
40
|
+
color: white;
|
|
41
|
+
}
|
|
42
|
+
</style>
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { SvelteComponentTyped } from "svelte";
|
|
2
|
+
import type { Feedback } from '@txstate-mws/svelte-forms';
|
|
3
|
+
declare const __propDef: {
|
|
4
|
+
props: {
|
|
5
|
+
message: Feedback;
|
|
6
|
+
};
|
|
7
|
+
events: {
|
|
8
|
+
[evt: string]: CustomEvent<any>;
|
|
9
|
+
};
|
|
10
|
+
slots: {};
|
|
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;
|
|
15
|
+
export default class InlineMessage extends SvelteComponentTyped<InlineMessageProps, InlineMessageEvents, InlineMessageSlots> {
|
|
16
|
+
}
|
|
17
|
+
export {};
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
<script >import { randomid } from 'txstate-utils';
|
|
2
|
+
import InlineMessage from './InlineMessage.svelte';
|
|
3
|
+
export let id = randomid();
|
|
4
|
+
export let messages;
|
|
5
|
+
const savedid = id;
|
|
6
|
+
$: id = messages.length ? savedid : undefined;
|
|
7
|
+
</script>
|
|
8
|
+
|
|
9
|
+
{#if id}
|
|
10
|
+
<div {id}>
|
|
11
|
+
{#each messages as message}
|
|
12
|
+
<InlineMessage {message} />
|
|
13
|
+
{/each}
|
|
14
|
+
</div>
|
|
15
|
+
{/if}
|
|
16
|
+
|
|
17
|
+
<style>
|
|
18
|
+
div {
|
|
19
|
+
width: 100%;
|
|
20
|
+
}
|
|
21
|
+
</style>
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { SvelteComponentTyped } from "svelte";
|
|
2
|
+
import type { Feedback } from '@txstate-mws/svelte-forms';
|
|
3
|
+
declare const __propDef: {
|
|
4
|
+
props: {
|
|
5
|
+
id?: string | undefined;
|
|
6
|
+
messages: Feedback[];
|
|
7
|
+
};
|
|
8
|
+
events: {
|
|
9
|
+
[evt: string]: CustomEvent<any>;
|
|
10
|
+
};
|
|
11
|
+
slots: {};
|
|
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;
|
|
16
|
+
export default class InlineMessages extends SvelteComponentTyped<InlineMessagesProps, InlineMessagesEvents, InlineMessagesSlots> {
|
|
17
|
+
}
|
|
18
|
+
export {};
|
package/Input.svelte
ADDED
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
<script >import { dateSerialize, datetimeSerialize } from '@txstate-mws/svelte-forms';
|
|
2
|
+
let className = '';
|
|
3
|
+
export { className as class };
|
|
4
|
+
export let name;
|
|
5
|
+
export let value;
|
|
6
|
+
export let type = 'text';
|
|
7
|
+
export let allowlastpass = false;
|
|
8
|
+
export let maxlength = undefined;
|
|
9
|
+
export let min = undefined;
|
|
10
|
+
export let max = undefined;
|
|
11
|
+
export let step = undefined;
|
|
12
|
+
export let id = undefined;
|
|
13
|
+
export let disabled = false;
|
|
14
|
+
export let messagesid = undefined;
|
|
15
|
+
export let valid = false;
|
|
16
|
+
export let invalid = false;
|
|
17
|
+
export let onChange;
|
|
18
|
+
export let onBlur;
|
|
19
|
+
export let onSelect = undefined;
|
|
20
|
+
function resolveMinMax(dt) {
|
|
21
|
+
if (typeof dt === 'undefined')
|
|
22
|
+
return undefined;
|
|
23
|
+
if ('toJSDate' in dt)
|
|
24
|
+
dt = dt.toJSDate();
|
|
25
|
+
if (dt instanceof Date)
|
|
26
|
+
return type === 'date' ? dateSerialize(dt) : datetimeSerialize(dt);
|
|
27
|
+
return dt;
|
|
28
|
+
}
|
|
29
|
+
$: minStr = resolveMinMax(min);
|
|
30
|
+
$: maxStr = resolveMinMax(max);
|
|
31
|
+
</script>
|
|
32
|
+
|
|
33
|
+
<input {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}>
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import { SvelteComponentTyped } from "svelte";
|
|
2
|
+
declare const __propDef: {
|
|
3
|
+
props: {
|
|
4
|
+
class?: string;
|
|
5
|
+
name: string;
|
|
6
|
+
value: string;
|
|
7
|
+
type?: string;
|
|
8
|
+
allowlastpass?: boolean;
|
|
9
|
+
maxlength?: number | undefined;
|
|
10
|
+
min?: string | Date | {
|
|
11
|
+
toJSDate: () => Date;
|
|
12
|
+
} | number | undefined;
|
|
13
|
+
max?: string | Date | {
|
|
14
|
+
toJSDate: () => Date;
|
|
15
|
+
} | number | undefined;
|
|
16
|
+
step?: number | undefined;
|
|
17
|
+
id?: string | undefined;
|
|
18
|
+
disabled?: boolean;
|
|
19
|
+
messagesid?: string | undefined;
|
|
20
|
+
valid?: boolean;
|
|
21
|
+
invalid?: boolean;
|
|
22
|
+
onChange: any;
|
|
23
|
+
onBlur: any;
|
|
24
|
+
onSelect?: any;
|
|
25
|
+
};
|
|
26
|
+
events: {
|
|
27
|
+
[evt: string]: CustomEvent<any>;
|
|
28
|
+
};
|
|
29
|
+
slots: {};
|
|
30
|
+
};
|
|
31
|
+
export declare type InputProps = typeof __propDef.props;
|
|
32
|
+
export declare type InputEvents = typeof __propDef.events;
|
|
33
|
+
export declare type InputSlots = typeof __propDef.slots;
|
|
34
|
+
export default class Input extends SvelteComponentTyped<InputProps, InputEvents, InputSlots> {
|
|
35
|
+
}
|
|
36
|
+
export {};
|
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2021 Texas State ETC
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
# create-svelte
|
|
2
|
+
|
|
3
|
+
Everything you need to build a Svelte project, powered by [`create-svelte`](https://github.com/sveltejs/kit/tree/master/packages/create-svelte);
|
|
4
|
+
|
|
5
|
+
## Creating a project
|
|
6
|
+
|
|
7
|
+
If you're seeing this, you've probably already done this step. Congrats!
|
|
8
|
+
|
|
9
|
+
```bash
|
|
10
|
+
# create a new project in the current directory
|
|
11
|
+
npm init svelte@next
|
|
12
|
+
|
|
13
|
+
# create a new project in my-app
|
|
14
|
+
npm init svelte@next my-app
|
|
15
|
+
```
|
|
16
|
+
|
|
17
|
+
> Note: the `@next` is temporary
|
|
18
|
+
|
|
19
|
+
## Developing
|
|
20
|
+
|
|
21
|
+
Once you've created a project and installed dependencies with `npm install` (or `pnpm install` or `yarn`), start a development server:
|
|
22
|
+
|
|
23
|
+
```bash
|
|
24
|
+
npm run dev
|
|
25
|
+
|
|
26
|
+
# or start the server and open the app in a new browser tab
|
|
27
|
+
npm run dev -- --open
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
## Building
|
|
31
|
+
|
|
32
|
+
Before creating a production version of your app, install an [adapter](https://kit.svelte.dev/docs#adapters) for your target environment. Then:
|
|
33
|
+
|
|
34
|
+
```bash
|
|
35
|
+
npm run build
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
> You can preview the built app with `npm run preview`, regardless of whether you installed an adapter. This should _not_ be used to serve your app in production.
|
package/Radio.svelte
ADDED
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
<script >export let id = undefined;
|
|
2
|
+
export let name;
|
|
3
|
+
export let value;
|
|
4
|
+
export let selected = false;
|
|
5
|
+
export let onChange = undefined;
|
|
6
|
+
export let onBlur = undefined;
|
|
7
|
+
export let messagesid = undefined;
|
|
8
|
+
export let disabled = false;
|
|
9
|
+
export let valid = false;
|
|
10
|
+
export let invalid = false;
|
|
11
|
+
</script>
|
|
12
|
+
|
|
13
|
+
<input {id} type="radio" {name} class:valid class:invalid checked={selected} {disabled} aria-describedby={messagesid} {value} on:change={onChange} on:blur={onBlur}>
|
|
14
|
+
|
|
15
|
+
<style>
|
|
16
|
+
input, input:before, input:after {
|
|
17
|
+
box-sizing: border-box;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
input[type="radio"] {
|
|
21
|
+
-webkit-appearance: none;
|
|
22
|
+
appearance: none;
|
|
23
|
+
background-color: var(--dialog-checkbox-bg, #ffffff);
|
|
24
|
+
margin: 0;
|
|
25
|
+
|
|
26
|
+
font: inherit;
|
|
27
|
+
color: var(--dialog-checkbox-border, currentColor);
|
|
28
|
+
width: 1.15em;
|
|
29
|
+
height: 1.15em;
|
|
30
|
+
border: 0.15em solid currentColor;
|
|
31
|
+
border-radius: 50%;
|
|
32
|
+
transform: translateY(-0.075em);
|
|
33
|
+
|
|
34
|
+
display: inline-grid;
|
|
35
|
+
place-content: center;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
input[type="radio"]::before {
|
|
39
|
+
content: "";
|
|
40
|
+
width: 0.65em;
|
|
41
|
+
height: 0.65em;
|
|
42
|
+
border-radius: 50%;
|
|
43
|
+
transform: scale(0);
|
|
44
|
+
transition: 120ms transform ease-in-out;
|
|
45
|
+
box-shadow: inset 1em 1em var(--dialog-checkbox-color, currentColor);
|
|
46
|
+
/* Windows High Contrast Mode */
|
|
47
|
+
background-color: CanvasText;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
input[type="radio"]:checked::before {
|
|
51
|
+
transform: scale(1);
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
input[type="radio"]:focus {
|
|
55
|
+
outline: max(2px, 0.15em) solid var(--dialog-checkbox-focus, #4D90FE);
|
|
56
|
+
outline-offset: max(2px, 0.15em);
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
input[type="radio"]:disabled {
|
|
60
|
+
--dialog-checkbox-color: var(--dialog-checkbox-disabled, #999999);
|
|
61
|
+
|
|
62
|
+
color: var(--dialog-checkbox-color);
|
|
63
|
+
cursor: not-allowed;
|
|
64
|
+
}
|
|
65
|
+
</style>
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import { SvelteComponentTyped } from "svelte";
|
|
2
|
+
declare const __propDef: {
|
|
3
|
+
props: {
|
|
4
|
+
id?: string | undefined;
|
|
5
|
+
name: string;
|
|
6
|
+
value: string;
|
|
7
|
+
selected?: boolean;
|
|
8
|
+
onChange?: any;
|
|
9
|
+
onBlur?: any;
|
|
10
|
+
messagesid?: string | undefined;
|
|
11
|
+
disabled?: boolean;
|
|
12
|
+
valid?: boolean;
|
|
13
|
+
invalid?: boolean;
|
|
14
|
+
};
|
|
15
|
+
events: {
|
|
16
|
+
[evt: string]: CustomEvent<any>;
|
|
17
|
+
};
|
|
18
|
+
slots: {};
|
|
19
|
+
};
|
|
20
|
+
export declare type RadioProps = typeof __propDef.props;
|
|
21
|
+
export declare type RadioEvents = typeof __propDef.events;
|
|
22
|
+
export declare type RadioSlots = typeof __propDef.slots;
|
|
23
|
+
export default class Radio extends SvelteComponentTyped<RadioProps, RadioEvents, RadioSlots> {
|
|
24
|
+
}
|
|
25
|
+
export {};
|
package/Tab.svelte
ADDED
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
<script >import { getContext } from 'svelte';
|
|
2
|
+
import Icon from './Icon.svelte';
|
|
3
|
+
import { TabStore, TAB_CONTEXT } from './TabStore';
|
|
4
|
+
export let title;
|
|
5
|
+
const { store, onClick, onKeyDown, tabelements } = getContext(TAB_CONTEXT);
|
|
6
|
+
const accordion = store.accordion();
|
|
7
|
+
const current = store.currentTitle();
|
|
8
|
+
$: active = $current === title;
|
|
9
|
+
const idx = $store.tabs.findIndex(t => t.title === title);
|
|
10
|
+
const last = idx === $store.tabs.length - 1;
|
|
11
|
+
</script>
|
|
12
|
+
|
|
13
|
+
{#if $accordion}
|
|
14
|
+
<div bind:this={tabelements[idx]} id={$store.tabids[title]} class="tabs-tab" class:last aria-selected={active} aria-controls={$store.panelids[title]} role="tab" tabindex={0} on:click={onClick(idx)} on:keydown={onKeyDown(idx)}><Icon icon={$store.tabs[idx].icon} inline />{title}<i class="tabs-accordion-arrow" aria-hidden="true"></i></div>
|
|
15
|
+
{/if}
|
|
16
|
+
<div id={$store.panelids[title]} hidden={!active} role="tabpanel" tabindex="0" aria-labelledby={$store.tabids[title]} class="tabs-panel" class:accordion={$accordion}>
|
|
17
|
+
<slot />
|
|
18
|
+
</div>
|
|
19
|
+
|
|
20
|
+
<style>
|
|
21
|
+
.tabs-panel {
|
|
22
|
+
width: 100%;
|
|
23
|
+
border: var(--tabs-panel-border, var(--tabs-border, 1px solid #666666));
|
|
24
|
+
padding: var(--tabs-panel-padding, 1em);
|
|
25
|
+
}
|
|
26
|
+
.tabs-panel.accordion {
|
|
27
|
+
border-left: 0;
|
|
28
|
+
border-right: 0;
|
|
29
|
+
}
|
|
30
|
+
.tabs-panel:not(.accordion) {
|
|
31
|
+
border-bottom-left-radius: var(--tabs-panel-radius, var(--tabs-radius, 0.3em));
|
|
32
|
+
border-bottom-right-radius: var(--tabs-panel-radius, var(--tabs-radius, 0.3em));
|
|
33
|
+
overflow: hidden;
|
|
34
|
+
margin-bottom: var(--tabs-margin-bottom, 0.8em);
|
|
35
|
+
margin-top: -1px;
|
|
36
|
+
}
|
|
37
|
+
.tabs-tab {
|
|
38
|
+
position: relative;
|
|
39
|
+
width: 100%;
|
|
40
|
+
}
|
|
41
|
+
.tabs-tab:not(.last) {
|
|
42
|
+
border-bottom: var(--tabs-border, 1px solid #666666);
|
|
43
|
+
}
|
|
44
|
+
i.tabs-accordion-arrow {
|
|
45
|
+
transform: translateY(-50%) rotate(45deg);
|
|
46
|
+
border: solid currentColor;
|
|
47
|
+
border-width: 0 .2em .2em 0;
|
|
48
|
+
padding: .15em;
|
|
49
|
+
position: absolute;
|
|
50
|
+
right: 0.6em;
|
|
51
|
+
top: calc(50% - 0.08em);
|
|
52
|
+
}
|
|
53
|
+
.tabs-tab[aria-selected="true"] i.tabs-accordion-arrow {
|
|
54
|
+
transform: translateY(-50%) rotate(225deg);
|
|
55
|
+
top: calc(50% + 0.08em);
|
|
56
|
+
}
|
|
57
|
+
</style>
|
package/Tab.svelte.d.ts
ADDED
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { SvelteComponentTyped } from "svelte";
|
|
2
|
+
declare const __propDef: {
|
|
3
|
+
props: {
|
|
4
|
+
title: string;
|
|
5
|
+
};
|
|
6
|
+
events: {
|
|
7
|
+
[evt: string]: CustomEvent<any>;
|
|
8
|
+
};
|
|
9
|
+
slots: {
|
|
10
|
+
default: {};
|
|
11
|
+
};
|
|
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;
|
|
16
|
+
export default class Tab extends SvelteComponentTyped<TabProps, TabEvents, TabSlots> {
|
|
17
|
+
}
|
|
18
|
+
export {};
|
package/TabStore.d.ts
ADDED
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import { Store } from '@txstate-mws/svelte-store';
|
|
2
|
+
import type { ElementSize } from '@txstate-mws/svelte-components';
|
|
3
|
+
import type { IconifyIcon } from '@iconify/svelte';
|
|
4
|
+
export declare const TAB_CONTEXT: {};
|
|
5
|
+
interface TabDef {
|
|
6
|
+
title: string;
|
|
7
|
+
icon?: IconifyIcon;
|
|
8
|
+
}
|
|
9
|
+
interface ITabStore extends ElementSize {
|
|
10
|
+
current?: number;
|
|
11
|
+
tabs: TabDef[];
|
|
12
|
+
tabids: Record<string, string>;
|
|
13
|
+
panelids: Record<string, string>;
|
|
14
|
+
}
|
|
15
|
+
export declare class TabStore extends Store<ITabStore> {
|
|
16
|
+
initialTab?: string | undefined;
|
|
17
|
+
constructor(tabs: TabDef[], initialTab?: string | undefined);
|
|
18
|
+
currentTitle(): import("@txstate-mws/svelte-store").DerivedStore<string, ITabStore>;
|
|
19
|
+
currentTabId(): import("@txstate-mws/svelte-store").DerivedStore<string, ITabStore>;
|
|
20
|
+
currentPanelId(): import("@txstate-mws/svelte-store").DerivedStore<string, ITabStore>;
|
|
21
|
+
accordion(): import("@txstate-mws/svelte-store").DerivedStore<boolean, ITabStore>;
|
|
22
|
+
left(): void;
|
|
23
|
+
right(): void;
|
|
24
|
+
home(): void;
|
|
25
|
+
end(): void;
|
|
26
|
+
activate(idx: number): void;
|
|
27
|
+
}
|
|
28
|
+
export {};
|
package/TabStore.js
ADDED
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import { Store, derivedStore } from '@txstate-mws/svelte-store';
|
|
2
|
+
import { findIndex, randomid } from 'txstate-utils';
|
|
3
|
+
export const TAB_CONTEXT = {};
|
|
4
|
+
export class TabStore extends Store {
|
|
5
|
+
constructor(tabs, initialTab) {
|
|
6
|
+
super({
|
|
7
|
+
tabs,
|
|
8
|
+
current: findIndex(tabs, t => t.title === initialTab, 0),
|
|
9
|
+
tabids: tabs.reduce((acc, curr) => ({ ...acc, [curr.title]: randomid() }), {}),
|
|
10
|
+
panelids: tabs.reduce((acc, curr) => ({ ...acc, [curr.title]: randomid() }), {}),
|
|
11
|
+
clientWidth: 1024
|
|
12
|
+
});
|
|
13
|
+
this.initialTab = initialTab;
|
|
14
|
+
}
|
|
15
|
+
currentTitle() {
|
|
16
|
+
return derivedStore(this, v => v.tabs[v.current].title);
|
|
17
|
+
}
|
|
18
|
+
currentTabId() {
|
|
19
|
+
return derivedStore(this, v => v.tabids[v.tabs[v.current].title]);
|
|
20
|
+
}
|
|
21
|
+
currentPanelId() {
|
|
22
|
+
return derivedStore(this, v => v.panelids[v.tabs[v.current].title]);
|
|
23
|
+
}
|
|
24
|
+
accordion() {
|
|
25
|
+
return derivedStore(this, v => v.clientWidth < 500);
|
|
26
|
+
}
|
|
27
|
+
left() {
|
|
28
|
+
this.update(v => ({ ...v, current: Math.max(0, v.current - 1) }));
|
|
29
|
+
}
|
|
30
|
+
right() {
|
|
31
|
+
this.update(v => ({ ...v, current: Math.min(v.tabs.length - 1, v.current + 1) }));
|
|
32
|
+
}
|
|
33
|
+
home() {
|
|
34
|
+
this.update(v => ({ ...v, current: 0 }));
|
|
35
|
+
}
|
|
36
|
+
end() {
|
|
37
|
+
this.update(v => ({ ...v, current: v.tabs.length - 1 }));
|
|
38
|
+
}
|
|
39
|
+
activate(idx) {
|
|
40
|
+
this.update(v => ({ ...v, current: Math.min(v.tabs.length, Math.max(0, idx)) }));
|
|
41
|
+
}
|
|
42
|
+
}
|
package/Tabs.svelte
ADDED
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
<script >import { modifierKey, resize } from '@txstate-mws/svelte-components';
|
|
2
|
+
import { setContext } from 'svelte';
|
|
3
|
+
import { roundTo } from 'txstate-utils';
|
|
4
|
+
import Icon from './Icon.svelte';
|
|
5
|
+
import { TabStore, TAB_CONTEXT } from './TabStore';
|
|
6
|
+
export let tabs;
|
|
7
|
+
export let active = undefined;
|
|
8
|
+
export let store = new TabStore(tabs, active);
|
|
9
|
+
const tabelements = [];
|
|
10
|
+
setContext(TAB_CONTEXT, { store, onClick, onKeyDown, tabelements });
|
|
11
|
+
const current = store.currentTitle();
|
|
12
|
+
const accordion = store.accordion();
|
|
13
|
+
$: cols = Math.min(Math.floor($store.clientWidth / 90), $store.tabs.length);
|
|
14
|
+
$: scalefactor = Math.min(roundTo($store.clientWidth / (cols * 130), 4), 1);
|
|
15
|
+
$: width = `calc(${100 / cols}% + 1px)`;
|
|
16
|
+
$: widthleft = `${100 / cols}%`;
|
|
17
|
+
$: wrapping = cols !== $store.tabs.length;
|
|
18
|
+
function onClick(idx) {
|
|
19
|
+
return () => store.activate(idx);
|
|
20
|
+
}
|
|
21
|
+
function onKeyDown(idx) {
|
|
22
|
+
return async (e) => {
|
|
23
|
+
if (modifierKey(e))
|
|
24
|
+
return;
|
|
25
|
+
if (['Enter', ' ', 'ArrowLeft', 'ArrowRight', 'Home', 'End'].includes(e.key)) {
|
|
26
|
+
e.preventDefault();
|
|
27
|
+
e.stopPropagation();
|
|
28
|
+
}
|
|
29
|
+
if (e.key === 'Enter' || e.key === ' ') {
|
|
30
|
+
store.activate(idx);
|
|
31
|
+
}
|
|
32
|
+
else if (e.key === 'ArrowLeft' && $store.current > 0) {
|
|
33
|
+
store.left();
|
|
34
|
+
tabelements[$store.current].focus();
|
|
35
|
+
}
|
|
36
|
+
else if (e.key === 'ArrowRight' && $store.current < $store.tabs.length - 1) {
|
|
37
|
+
store.right();
|
|
38
|
+
tabelements[$store.current].focus();
|
|
39
|
+
}
|
|
40
|
+
else if (e.key === 'Home' && $store.current > 0) {
|
|
41
|
+
store.home();
|
|
42
|
+
tabelements[$store.current].focus();
|
|
43
|
+
}
|
|
44
|
+
else if (e.key === 'End' && $store.current < $store.tabs.length - 1) {
|
|
45
|
+
store.end();
|
|
46
|
+
tabelements[$store.current].focus();
|
|
47
|
+
}
|
|
48
|
+
};
|
|
49
|
+
}
|
|
50
|
+
function isActive(idx, activeidx) {
|
|
51
|
+
return idx === (activeidx ?? 0);
|
|
52
|
+
}
|
|
53
|
+
$: active = $current;
|
|
54
|
+
</script>
|
|
55
|
+
|
|
56
|
+
{#if !$accordion}
|
|
57
|
+
<ul use:resize={{ store }} class="dialog-tab-buttons" role="tablist">
|
|
58
|
+
{#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>
|
|
62
|
+
{/each}
|
|
63
|
+
</ul>
|
|
64
|
+
<slot current={$store.current} />
|
|
65
|
+
{:else}
|
|
66
|
+
<div use:resize={{ store }} class="tabs-container">
|
|
67
|
+
<slot current={$store.current} />
|
|
68
|
+
</div>
|
|
69
|
+
{/if}
|
|
70
|
+
|
|
71
|
+
<style>
|
|
72
|
+
.tabs-container {
|
|
73
|
+
display: flex;
|
|
74
|
+
flex-wrap: wrap;
|
|
75
|
+
border-radius: var(--tabs-radius, 0.6em);
|
|
76
|
+
overflow: hidden;
|
|
77
|
+
border: var(--tabs-border, 1px solid #666666);
|
|
78
|
+
margin-bottom: var(--tabs-margin-bottom, 0.8em);
|
|
79
|
+
}
|
|
80
|
+
ul {
|
|
81
|
+
width: 100%;
|
|
82
|
+
padding: 0;
|
|
83
|
+
margin: 0;
|
|
84
|
+
list-style-type: none;
|
|
85
|
+
display: flex;
|
|
86
|
+
flex-wrap: wrap;
|
|
87
|
+
}
|
|
88
|
+
li, .tabs-container :global(.tabs-tab) {
|
|
89
|
+
padding: var(--tabs-padding, 0.7em 1em);
|
|
90
|
+
cursor: pointer;
|
|
91
|
+
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);
|
|
97
|
+
}
|
|
98
|
+
li:not(.left) {
|
|
99
|
+
margin-left: -1px;
|
|
100
|
+
}
|
|
101
|
+
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);
|
|
104
|
+
}
|
|
105
|
+
</style>
|
package/Tabs.svelte.d.ts
ADDED
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import { SvelteComponentTyped } from "svelte";
|
|
2
|
+
import { TabStore } from './TabStore';
|
|
3
|
+
declare const __propDef: {
|
|
4
|
+
props: {
|
|
5
|
+
tabs: {
|
|
6
|
+
title: string;
|
|
7
|
+
}[];
|
|
8
|
+
active?: string | undefined;
|
|
9
|
+
store?: TabStore;
|
|
10
|
+
};
|
|
11
|
+
events: {
|
|
12
|
+
[evt: string]: CustomEvent<any>;
|
|
13
|
+
};
|
|
14
|
+
slots: {
|
|
15
|
+
default: {
|
|
16
|
+
current: number;
|
|
17
|
+
};
|
|
18
|
+
};
|
|
19
|
+
};
|
|
20
|
+
export declare type TabsProps = typeof __propDef.props;
|
|
21
|
+
export declare type TabsEvents = typeof __propDef.events;
|
|
22
|
+
export declare type TabsSlots = typeof __propDef.slots;
|
|
23
|
+
export default class Tabs extends SvelteComponentTyped<TabsProps, TabsEvents, TabsSlots> {
|
|
24
|
+
}
|
|
25
|
+
export {};
|