terminoir 0.4.0 → 0.5.0
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/README.md +38 -28
- package/css/components.css +62 -0
- package/css/shell.css +32 -1
- package/dist/components/AccentSwatches.svelte +1 -1
- package/dist/components/AppShell.svelte +33 -5
- package/dist/components/AppShell.svelte.d.ts +10 -1
- package/dist/components/AppShellNavLink.svelte +2 -4
- package/dist/components/Button.svelte +32 -14
- package/dist/components/Button.svelte.d.ts +2 -0
- package/dist/components/CalendarGrid.svelte +245 -0
- package/dist/components/CalendarGrid.svelte.d.ts +12 -0
- package/dist/components/CanvasStage.svelte +81 -0
- package/dist/components/CanvasStage.svelte.d.ts +19 -0
- package/dist/components/Centered.svelte +36 -0
- package/dist/components/Centered.svelte.d.ts +10 -0
- package/dist/components/Checkbox.svelte +64 -12
- package/dist/components/Checkbox.svelte.d.ts +5 -0
- package/dist/components/Chip.svelte +90 -2
- package/dist/components/Chip.svelte.d.ts +8 -0
- package/dist/components/CommandPalette.svelte +178 -97
- package/dist/components/CommandPalette.svelte.d.ts +15 -8
- package/dist/components/ContextMenu.svelte +68 -0
- package/dist/components/ContextMenu.svelte.d.ts +12 -0
- package/dist/components/DataTable.svelte +139 -0
- package/dist/components/DataTable.svelte.d.ts +39 -0
- package/dist/components/DescriptionList.svelte +41 -0
- package/dist/components/DescriptionList.svelte.d.ts +8 -0
- package/dist/components/Dialog.svelte +2 -1
- package/dist/components/Disclosure.svelte +55 -0
- package/dist/components/Disclosure.svelte.d.ts +10 -0
- package/dist/components/DocumentViewer.svelte +105 -0
- package/dist/components/DocumentViewer.svelte.d.ts +23 -0
- package/dist/components/Drawer.svelte +119 -0
- package/dist/components/Drawer.svelte.d.ts +16 -0
- package/dist/components/DropdownMenu.svelte +46 -62
- package/dist/components/DropdownMenu.svelte.d.ts +7 -6
- package/dist/components/FieldMessage.svelte +9 -0
- package/dist/components/FieldMessage.svelte.d.ts +8 -0
- package/dist/components/FileButton.svelte +44 -0
- package/dist/components/FileButton.svelte.d.ts +16 -0
- package/dist/components/FormRow.svelte +62 -0
- package/dist/components/FormRow.svelte.d.ts +13 -0
- package/dist/components/IconField.svelte +80 -5
- package/dist/components/IconField.svelte.d.ts +2 -0
- package/dist/components/Inline.svelte +52 -0
- package/dist/components/Inline.svelte.d.ts +16 -0
- package/dist/components/Input.svelte +23 -3
- package/dist/components/Input.svelte.d.ts +9 -0
- package/dist/components/List.svelte +42 -0
- package/dist/components/List.svelte.d.ts +13 -0
- package/dist/components/ListItem.svelte +114 -0
- package/dist/components/ListItem.svelte.d.ts +17 -0
- package/dist/components/MenuItems.svelte +44 -0
- package/dist/components/MenuItems.svelte.d.ts +8 -0
- package/dist/components/NavSection.svelte +45 -0
- package/dist/components/NavSection.svelte.d.ts +12 -0
- package/dist/components/Page.svelte +53 -0
- package/dist/components/Page.svelte.d.ts +12 -0
- package/dist/components/PageHeader.svelte +91 -0
- package/dist/components/PageHeader.svelte.d.ts +15 -0
- package/dist/components/Prose.svelte +33 -0
- package/dist/components/Prose.svelte.d.ts +8 -0
- package/dist/components/RadioCards.svelte +68 -0
- package/dist/components/RadioCards.svelte.d.ts +11 -0
- package/dist/components/SearchPicker.svelte +171 -0
- package/dist/components/SearchPicker.svelte.d.ts +19 -0
- package/dist/components/Section.svelte +71 -0
- package/dist/components/Section.svelte.d.ts +12 -0
- package/dist/components/SegmentedControl.svelte +63 -0
- package/dist/components/SegmentedControl.svelte.d.ts +12 -0
- package/dist/components/Select.svelte +22 -4
- package/dist/components/Select.svelte.d.ts +9 -1
- package/dist/components/Spacer.svelte +6 -0
- package/dist/components/Spacer.svelte.d.ts +26 -0
- package/dist/components/Stack.svelte +37 -0
- package/dist/components/Stack.svelte.d.ts +12 -0
- package/dist/components/Switch.svelte +6 -2
- package/dist/components/Switch.svelte.d.ts +2 -0
- package/dist/components/Tabs.svelte +6 -4
- package/dist/components/Text.svelte +68 -0
- package/dist/components/Text.svelte.d.ts +15 -0
- package/dist/components/Textarea.svelte +19 -3
- package/dist/components/Textarea.svelte.d.ts +6 -0
- package/dist/components/TitleInput.svelte +62 -0
- package/dist/components/TitleInput.svelte.d.ts +10 -0
- package/dist/index.d.ts +35 -2
- package/dist/index.js +31 -0
- package/dist/utils/calendar.d.ts +35 -0
- package/dist/utils/calendar.js +61 -0
- package/dist/utils/commands.d.ts +22 -0
- package/dist/utils/commands.js +17 -0
- package/dist/utils/componentTypes.d.ts +41 -0
- package/dist/utils/componentTypes.js +1 -0
- package/dist/utils/listNav.d.ts +2 -0
- package/dist/utils/listNav.js +8 -0
- package/dist/utils/menu.d.ts +10 -0
- package/dist/utils/menu.js +1 -0
- package/package.json +5 -3
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
export default Spacer;
|
|
2
|
+
type Spacer = SvelteComponent<{
|
|
3
|
+
[x: string]: never;
|
|
4
|
+
}, {
|
|
5
|
+
[evt: string]: CustomEvent<any>;
|
|
6
|
+
}, {}> & {
|
|
7
|
+
$$bindings?: string | undefined;
|
|
8
|
+
};
|
|
9
|
+
declare const Spacer: $$__sveltets_2_IsomorphicComponent<{
|
|
10
|
+
[x: string]: never;
|
|
11
|
+
}, {
|
|
12
|
+
[evt: string]: CustomEvent<any>;
|
|
13
|
+
}, {}, {}, string>;
|
|
14
|
+
interface $$__sveltets_2_IsomorphicComponent<Props extends Record<string, any> = any, Events extends Record<string, any> = any, Slots extends Record<string, any> = any, Exports = {}, Bindings = string> {
|
|
15
|
+
new (options: import("svelte").ComponentConstructorOptions<Props>): import("svelte").SvelteComponent<Props, Events, Slots> & {
|
|
16
|
+
$$bindings?: Bindings;
|
|
17
|
+
} & Exports;
|
|
18
|
+
(internal: unknown, props: {
|
|
19
|
+
$$events?: Events;
|
|
20
|
+
$$slots?: Slots;
|
|
21
|
+
}): Exports & {
|
|
22
|
+
$set?: any;
|
|
23
|
+
$on?: any;
|
|
24
|
+
};
|
|
25
|
+
z_$$bindings?: Bindings;
|
|
26
|
+
}
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
import type { Snippet } from 'svelte';
|
|
3
|
+
import { cn } from '../utils/cn.js';
|
|
4
|
+
|
|
5
|
+
type Gap = 0 | 1 | 2 | 3 | 4 | 5 | 6 | 8 | 10 | 12;
|
|
6
|
+
|
|
7
|
+
let {
|
|
8
|
+
gap = 4,
|
|
9
|
+
align = 'stretch',
|
|
10
|
+
class: className = '',
|
|
11
|
+
children,
|
|
12
|
+
...rest
|
|
13
|
+
}: {
|
|
14
|
+
/** Spacing between children, as a `--space-*` step. */
|
|
15
|
+
gap?: Gap;
|
|
16
|
+
align?: 'stretch' | 'start' | 'center' | 'end';
|
|
17
|
+
class?: string;
|
|
18
|
+
children?: Snippet;
|
|
19
|
+
} & Record<string, unknown> = $props();
|
|
20
|
+
</script>
|
|
21
|
+
|
|
22
|
+
<div
|
|
23
|
+
class={cn('terminoir-stack', className)}
|
|
24
|
+
style:gap={`var(--space-${gap})`}
|
|
25
|
+
style:align-items={align === 'stretch' ? 'stretch' : align === 'center' ? 'center' : `flex-${align}`}
|
|
26
|
+
{...rest}
|
|
27
|
+
>
|
|
28
|
+
{@render children?.()}
|
|
29
|
+
</div>
|
|
30
|
+
|
|
31
|
+
<style>
|
|
32
|
+
.terminoir-stack {
|
|
33
|
+
display: flex;
|
|
34
|
+
flex-direction: column;
|
|
35
|
+
min-width: 0;
|
|
36
|
+
}
|
|
37
|
+
</style>
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import type { Snippet } from 'svelte';
|
|
2
|
+
type Gap = 0 | 1 | 2 | 3 | 4 | 5 | 6 | 8 | 10 | 12;
|
|
3
|
+
type $$ComponentProps = {
|
|
4
|
+
/** Spacing between children, as a `--space-*` step. */
|
|
5
|
+
gap?: Gap;
|
|
6
|
+
align?: 'stretch' | 'start' | 'center' | 'end';
|
|
7
|
+
class?: string;
|
|
8
|
+
children?: Snippet;
|
|
9
|
+
} & Record<string, unknown>;
|
|
10
|
+
declare const Stack: import("svelte").Component<$$ComponentProps, {}, "">;
|
|
11
|
+
type Stack = ReturnType<typeof Stack>;
|
|
12
|
+
export default Stack;
|
|
@@ -3,6 +3,7 @@
|
|
|
3
3
|
|
|
4
4
|
let {
|
|
5
5
|
label,
|
|
6
|
+
hideLabel = false,
|
|
6
7
|
checked = $bindable(false),
|
|
7
8
|
disabled = false,
|
|
8
9
|
class: className = '',
|
|
@@ -10,17 +11,20 @@
|
|
|
10
11
|
...rest
|
|
11
12
|
}: {
|
|
12
13
|
label: string;
|
|
14
|
+
/** Keep the label for screen readers only (e.g. a switch inside a list row). */
|
|
15
|
+
hideLabel?: boolean;
|
|
13
16
|
checked?: boolean;
|
|
14
17
|
disabled?: boolean;
|
|
15
18
|
class?: string;
|
|
16
19
|
id?: string;
|
|
17
20
|
} & Record<string, unknown> = $props();
|
|
18
21
|
|
|
19
|
-
const
|
|
22
|
+
const fallbackId = $props.id();
|
|
23
|
+
const inputId = $derived(id ?? fallbackId);
|
|
20
24
|
</script>
|
|
21
25
|
|
|
22
26
|
<label class={cn('terminoir-switch', className)}>
|
|
23
|
-
<span class=
|
|
27
|
+
<span class={cn('terminoir-field__label', hideLabel && 'terminoir-sr-only')}>{label}</span>
|
|
24
28
|
<input
|
|
25
29
|
id={inputId}
|
|
26
30
|
type="checkbox"
|
|
@@ -14,6 +14,8 @@
|
|
|
14
14
|
children?: Snippet;
|
|
15
15
|
} = $props();
|
|
16
16
|
|
|
17
|
+
const uid = $props.id();
|
|
18
|
+
|
|
17
19
|
$effect.pre(() => {
|
|
18
20
|
if (!value && tabs[0]) value = tabs[0].id;
|
|
19
21
|
});
|
|
@@ -25,9 +27,9 @@
|
|
|
25
27
|
<button
|
|
26
28
|
type="button"
|
|
27
29
|
role="tab"
|
|
28
|
-
id={
|
|
30
|
+
id={`${uid}-tab-${tab.id}`}
|
|
29
31
|
aria-selected={value === tab.id}
|
|
30
|
-
aria-controls={
|
|
32
|
+
aria-controls={`${uid}-panel-${tab.id}`}
|
|
31
33
|
class="terminoir-tabs__trigger terminoir-focusable"
|
|
32
34
|
onclick={() => (value = tab.id)}
|
|
33
35
|
>
|
|
@@ -38,8 +40,8 @@
|
|
|
38
40
|
{#each tabs as tab (tab.id)}
|
|
39
41
|
<div
|
|
40
42
|
role="tabpanel"
|
|
41
|
-
id={
|
|
42
|
-
aria-labelledby={
|
|
43
|
+
id={`${uid}-panel-${tab.id}`}
|
|
44
|
+
aria-labelledby={`${uid}-tab-${tab.id}`}
|
|
43
45
|
hidden={value !== tab.id}
|
|
44
46
|
class="terminoir-tabs__panel"
|
|
45
47
|
>
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
import type { Snippet } from 'svelte';
|
|
3
|
+
import { cn } from '../utils/cn.js';
|
|
4
|
+
|
|
5
|
+
let {
|
|
6
|
+
as = 'p',
|
|
7
|
+
tone = 'default',
|
|
8
|
+
size = 'md',
|
|
9
|
+
weight = 'normal',
|
|
10
|
+
truncate = false,
|
|
11
|
+
mono = false,
|
|
12
|
+
class: className = '',
|
|
13
|
+
children,
|
|
14
|
+
...rest
|
|
15
|
+
}: {
|
|
16
|
+
as?: 'p' | 'span' | 'div' | 'small';
|
|
17
|
+
tone?: 'default' | 'muted' | 'danger' | 'success' | 'warning';
|
|
18
|
+
size?: 'xs' | 'sm' | 'md' | 'lg';
|
|
19
|
+
weight?: 'normal' | 'medium' | 'semibold';
|
|
20
|
+
/** Single line with an ellipsis. */
|
|
21
|
+
truncate?: boolean;
|
|
22
|
+
mono?: boolean;
|
|
23
|
+
class?: string;
|
|
24
|
+
children?: Snippet;
|
|
25
|
+
} & Record<string, unknown> = $props();
|
|
26
|
+
</script>
|
|
27
|
+
|
|
28
|
+
<svelte:element
|
|
29
|
+
this={as}
|
|
30
|
+
class={cn(
|
|
31
|
+
'terminoir-text',
|
|
32
|
+
`terminoir-text--${tone}`,
|
|
33
|
+
`terminoir-text--${size}`,
|
|
34
|
+
`terminoir-text--${weight}`,
|
|
35
|
+
truncate && 'terminoir-text--truncate',
|
|
36
|
+
mono && 'terminoir-text--mono',
|
|
37
|
+
className,
|
|
38
|
+
)}
|
|
39
|
+
{...rest}
|
|
40
|
+
>
|
|
41
|
+
{@render children?.()}
|
|
42
|
+
</svelte:element>
|
|
43
|
+
|
|
44
|
+
<style>
|
|
45
|
+
.terminoir-text {
|
|
46
|
+
margin: 0;
|
|
47
|
+
min-width: 0;
|
|
48
|
+
line-height: 1.5;
|
|
49
|
+
}
|
|
50
|
+
.terminoir-text--default { color: var(--foreground); }
|
|
51
|
+
.terminoir-text--muted { color: var(--muted-foreground); }
|
|
52
|
+
.terminoir-text--danger { color: var(--destructive); }
|
|
53
|
+
.terminoir-text--success { color: var(--status-done); }
|
|
54
|
+
.terminoir-text--warning { color: var(--status-today); }
|
|
55
|
+
.terminoir-text--xs { font-size: 0.75rem; }
|
|
56
|
+
.terminoir-text--sm { font-size: 0.8125rem; }
|
|
57
|
+
.terminoir-text--md { font-size: 0.875rem; }
|
|
58
|
+
.terminoir-text--lg { font-size: 1rem; }
|
|
59
|
+
.terminoir-text--normal { font-weight: 400; }
|
|
60
|
+
.terminoir-text--medium { font-weight: 500; }
|
|
61
|
+
.terminoir-text--semibold { font-weight: 600; }
|
|
62
|
+
.terminoir-text--truncate {
|
|
63
|
+
overflow: hidden;
|
|
64
|
+
text-overflow: ellipsis;
|
|
65
|
+
white-space: nowrap;
|
|
66
|
+
}
|
|
67
|
+
.terminoir-text--mono { font-family: var(--font-mono); }
|
|
68
|
+
</style>
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import type { Snippet } from 'svelte';
|
|
2
|
+
type $$ComponentProps = {
|
|
3
|
+
as?: 'p' | 'span' | 'div' | 'small';
|
|
4
|
+
tone?: 'default' | 'muted' | 'danger' | 'success' | 'warning';
|
|
5
|
+
size?: 'xs' | 'sm' | 'md' | 'lg';
|
|
6
|
+
weight?: 'normal' | 'medium' | 'semibold';
|
|
7
|
+
/** Single line with an ellipsis. */
|
|
8
|
+
truncate?: boolean;
|
|
9
|
+
mono?: boolean;
|
|
10
|
+
class?: string;
|
|
11
|
+
children?: Snippet;
|
|
12
|
+
} & Record<string, unknown>;
|
|
13
|
+
declare const Text: import("svelte").Component<$$ComponentProps, {}, "">;
|
|
14
|
+
type Text = ReturnType<typeof Text>;
|
|
15
|
+
export default Text;
|
|
@@ -1,8 +1,13 @@
|
|
|
1
1
|
<script lang="ts">
|
|
2
2
|
import { cn } from '../utils/cn.js';
|
|
3
|
+
import FieldMessage from './FieldMessage.svelte';
|
|
3
4
|
|
|
4
5
|
let {
|
|
5
6
|
label,
|
|
7
|
+
hideLabel = false,
|
|
8
|
+
quiet = false,
|
|
9
|
+
hint,
|
|
10
|
+
error,
|
|
6
11
|
id,
|
|
7
12
|
value = $bindable(''),
|
|
8
13
|
rows = 4,
|
|
@@ -12,6 +17,12 @@
|
|
|
12
17
|
...rest
|
|
13
18
|
}: {
|
|
14
19
|
label: string;
|
|
20
|
+
/** Keep the label for screen readers only. */
|
|
21
|
+
hideLabel?: boolean;
|
|
22
|
+
/** Borderless until hovered or focused, for inline editing (property rows). */
|
|
23
|
+
quiet?: boolean;
|
|
24
|
+
hint?: string;
|
|
25
|
+
error?: string;
|
|
15
26
|
id?: string;
|
|
16
27
|
value?: string;
|
|
17
28
|
rows?: number;
|
|
@@ -20,11 +31,13 @@
|
|
|
20
31
|
class?: string;
|
|
21
32
|
} & Record<string, unknown> = $props();
|
|
22
33
|
|
|
23
|
-
const
|
|
34
|
+
const fallbackId = $props.id();
|
|
35
|
+
const inputId = $derived(id ?? fallbackId);
|
|
36
|
+
const messageId = $derived(`${inputId}-message`);
|
|
24
37
|
</script>
|
|
25
38
|
|
|
26
|
-
<div class={cn('terminoir-field', className)}>
|
|
27
|
-
<label class=
|
|
39
|
+
<div class={cn('terminoir-field', quiet && 'terminoir-field--quiet', className)}>
|
|
40
|
+
<label class={cn('terminoir-field__label', hideLabel && 'terminoir-sr-only')} for={inputId}>{label}</label>
|
|
28
41
|
<textarea
|
|
29
42
|
id={inputId}
|
|
30
43
|
class="terminoir-textarea terminoir-focusable"
|
|
@@ -32,6 +45,9 @@
|
|
|
32
45
|
{rows}
|
|
33
46
|
{placeholder}
|
|
34
47
|
{disabled}
|
|
48
|
+
aria-invalid={error ? true : undefined}
|
|
49
|
+
aria-describedby={error || hint ? messageId : undefined}
|
|
35
50
|
{...rest}
|
|
36
51
|
></textarea>
|
|
52
|
+
<FieldMessage id={messageId} {hint} {error} />
|
|
37
53
|
</div>
|
|
@@ -1,5 +1,11 @@
|
|
|
1
1
|
type $$ComponentProps = {
|
|
2
2
|
label: string;
|
|
3
|
+
/** Keep the label for screen readers only. */
|
|
4
|
+
hideLabel?: boolean;
|
|
5
|
+
/** Borderless until hovered or focused, for inline editing (property rows). */
|
|
6
|
+
quiet?: boolean;
|
|
7
|
+
hint?: string;
|
|
8
|
+
error?: string;
|
|
3
9
|
id?: string;
|
|
4
10
|
value?: string;
|
|
5
11
|
rows?: number;
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
import { cn } from '../utils/cn.js';
|
|
3
|
+
|
|
4
|
+
let {
|
|
5
|
+
label,
|
|
6
|
+
value = $bindable(''),
|
|
7
|
+
placeholder = 'Untitled',
|
|
8
|
+
class: className = '',
|
|
9
|
+
...rest
|
|
10
|
+
}: {
|
|
11
|
+
/** Accessible name; not shown (the title itself is the heading). */
|
|
12
|
+
label: string;
|
|
13
|
+
value?: string;
|
|
14
|
+
placeholder?: string;
|
|
15
|
+
class?: string;
|
|
16
|
+
} & Record<string, unknown> = $props();
|
|
17
|
+
|
|
18
|
+
/** Titles are one line: Enter commits instead of inserting a newline. */
|
|
19
|
+
function onkeydown(event: KeyboardEvent) {
|
|
20
|
+
if (event.key === 'Enter') {
|
|
21
|
+
event.preventDefault();
|
|
22
|
+
(event.currentTarget as HTMLTextAreaElement).blur();
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
</script>
|
|
26
|
+
|
|
27
|
+
<textarea
|
|
28
|
+
class={cn('terminoir-title-input terminoir-focusable', className)}
|
|
29
|
+
aria-label={label}
|
|
30
|
+
rows="1"
|
|
31
|
+
bind:value
|
|
32
|
+
{placeholder}
|
|
33
|
+
{onkeydown}
|
|
34
|
+
{...rest}
|
|
35
|
+
></textarea>
|
|
36
|
+
|
|
37
|
+
<style>
|
|
38
|
+
.terminoir-title-input {
|
|
39
|
+
width: 100%;
|
|
40
|
+
margin: 0;
|
|
41
|
+
padding: 0.1rem 0.25rem;
|
|
42
|
+
margin-inline: -0.25rem;
|
|
43
|
+
border: 1px solid transparent;
|
|
44
|
+
border-radius: var(--radius-control);
|
|
45
|
+
background: transparent;
|
|
46
|
+
color: var(--foreground);
|
|
47
|
+
font: inherit;
|
|
48
|
+
font-size: 1.75rem;
|
|
49
|
+
font-weight: 600;
|
|
50
|
+
line-height: 1.25;
|
|
51
|
+
letter-spacing: -0.01em;
|
|
52
|
+
resize: none;
|
|
53
|
+
field-sizing: content;
|
|
54
|
+
overflow: hidden;
|
|
55
|
+
}
|
|
56
|
+
.terminoir-title-input:hover { border-color: color-mix(in srgb, var(--foreground) 10%, transparent); }
|
|
57
|
+
.terminoir-title-input:focus-visible { outline: none; border-color: var(--ring); }
|
|
58
|
+
.terminoir-title-input::placeholder { color: var(--muted-foreground); }
|
|
59
|
+
@media (max-width: 700px) {
|
|
60
|
+
.terminoir-title-input { font-size: 1.375rem; }
|
|
61
|
+
}
|
|
62
|
+
</style>
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
type $$ComponentProps = {
|
|
2
|
+
/** Accessible name; not shown (the title itself is the heading). */
|
|
3
|
+
label: string;
|
|
4
|
+
value?: string;
|
|
5
|
+
placeholder?: string;
|
|
6
|
+
class?: string;
|
|
7
|
+
} & Record<string, unknown>;
|
|
8
|
+
declare const TitleInput: import("svelte").Component<$$ComponentProps, {}, "value">;
|
|
9
|
+
type TitleInput = ReturnType<typeof TitleInput>;
|
|
10
|
+
export default TitleInput;
|
package/dist/index.d.ts
CHANGED
|
@@ -17,10 +17,10 @@ export { default as CardGrid } from './components/CardGrid.svelte';
|
|
|
17
17
|
export { default as Checkbox } from './components/Checkbox.svelte';
|
|
18
18
|
export { default as Chip } from './components/Chip.svelte';
|
|
19
19
|
export { default as CommandPalette } from './components/CommandPalette.svelte';
|
|
20
|
-
export type { CommandItem } from './
|
|
20
|
+
export type { CommandItem } from './utils/commands.js';
|
|
21
21
|
export { default as Dialog } from './components/Dialog.svelte';
|
|
22
22
|
export { default as DropdownMenu } from './components/DropdownMenu.svelte';
|
|
23
|
-
export type { MenuItem } from './
|
|
23
|
+
export type { MenuItem } from './utils/menu.js';
|
|
24
24
|
export { default as EmptyState } from './components/EmptyState.svelte';
|
|
25
25
|
export { default as FontPicker } from './components/FontPicker.svelte';
|
|
26
26
|
export { default as NavIcon } from './components/NavIcon.svelte';
|
|
@@ -38,3 +38,36 @@ export { default as Tabs } from './components/Tabs.svelte';
|
|
|
38
38
|
export { default as Textarea } from './components/Textarea.svelte';
|
|
39
39
|
export { default as Toaster } from './components/Toaster.svelte';
|
|
40
40
|
export { default as Tooltip } from './components/Tooltip.svelte';
|
|
41
|
+
export { default as Page } from './components/Page.svelte';
|
|
42
|
+
export { default as PageHeader } from './components/PageHeader.svelte';
|
|
43
|
+
export { default as Section } from './components/Section.svelte';
|
|
44
|
+
export { default as Stack } from './components/Stack.svelte';
|
|
45
|
+
export { default as Inline } from './components/Inline.svelte';
|
|
46
|
+
export { default as Text } from './components/Text.svelte';
|
|
47
|
+
export { default as Disclosure } from './components/Disclosure.svelte';
|
|
48
|
+
export { default as NavSection } from './components/NavSection.svelte';
|
|
49
|
+
export { default as Spacer } from './components/Spacer.svelte';
|
|
50
|
+
export { default as Centered } from './components/Centered.svelte';
|
|
51
|
+
export { default as Prose } from './components/Prose.svelte';
|
|
52
|
+
export { default as CanvasStage } from './components/CanvasStage.svelte';
|
|
53
|
+
export { default as CalendarGrid } from './components/CalendarGrid.svelte';
|
|
54
|
+
export { default as DocumentViewer } from './components/DocumentViewer.svelte';
|
|
55
|
+
export type { ViewerMark } from './utils/componentTypes.js';
|
|
56
|
+
export { default as DataTable } from './components/DataTable.svelte';
|
|
57
|
+
export type { DataColumn } from './utils/componentTypes.js';
|
|
58
|
+
export { default as List } from './components/List.svelte';
|
|
59
|
+
export { default as ListItem } from './components/ListItem.svelte';
|
|
60
|
+
export { default as DescriptionList } from './components/DescriptionList.svelte';
|
|
61
|
+
export type { DescriptionItem } from './utils/componentTypes.js';
|
|
62
|
+
export { default as FormRow } from './components/FormRow.svelte';
|
|
63
|
+
export { default as SearchPicker } from './components/SearchPicker.svelte';
|
|
64
|
+
export { default as FileButton } from './components/FileButton.svelte';
|
|
65
|
+
export { default as TitleInput } from './components/TitleInput.svelte';
|
|
66
|
+
export type { PickerOption } from './utils/componentTypes.js';
|
|
67
|
+
export { default as RadioCards } from './components/RadioCards.svelte';
|
|
68
|
+
export type { RadioCardOption } from './utils/componentTypes.js';
|
|
69
|
+
export { default as SegmentedControl } from './components/SegmentedControl.svelte';
|
|
70
|
+
export type { SegmentOption } from './utils/componentTypes.js';
|
|
71
|
+
export { default as ContextMenu } from './components/ContextMenu.svelte';
|
|
72
|
+
export { default as Drawer } from './components/Drawer.svelte';
|
|
73
|
+
export { addDays, calendarRange, eventsOn, sameDay, shiftCalendar, startOfDay, startOfWeek, type CalendarEvent, type CalendarMode, } from './utils/calendar.js';
|
package/dist/index.js
CHANGED
|
@@ -36,3 +36,34 @@ export { default as Tabs } from './components/Tabs.svelte';
|
|
|
36
36
|
export { default as Textarea } from './components/Textarea.svelte';
|
|
37
37
|
export { default as Toaster } from './components/Toaster.svelte';
|
|
38
38
|
export { default as Tooltip } from './components/Tooltip.svelte';
|
|
39
|
+
// Layout
|
|
40
|
+
export { default as Page } from './components/Page.svelte';
|
|
41
|
+
export { default as PageHeader } from './components/PageHeader.svelte';
|
|
42
|
+
export { default as Section } from './components/Section.svelte';
|
|
43
|
+
export { default as Stack } from './components/Stack.svelte';
|
|
44
|
+
export { default as Inline } from './components/Inline.svelte';
|
|
45
|
+
export { default as Text } from './components/Text.svelte';
|
|
46
|
+
export { default as Disclosure } from './components/Disclosure.svelte';
|
|
47
|
+
export { default as NavSection } from './components/NavSection.svelte';
|
|
48
|
+
export { default as Spacer } from './components/Spacer.svelte';
|
|
49
|
+
export { default as Centered } from './components/Centered.svelte';
|
|
50
|
+
export { default as Prose } from './components/Prose.svelte';
|
|
51
|
+
export { default as CanvasStage } from './components/CanvasStage.svelte';
|
|
52
|
+
export { default as CalendarGrid } from './components/CalendarGrid.svelte';
|
|
53
|
+
export { default as DocumentViewer } from './components/DocumentViewer.svelte';
|
|
54
|
+
// Data display
|
|
55
|
+
export { default as DataTable } from './components/DataTable.svelte';
|
|
56
|
+
export { default as List } from './components/List.svelte';
|
|
57
|
+
export { default as ListItem } from './components/ListItem.svelte';
|
|
58
|
+
export { default as DescriptionList } from './components/DescriptionList.svelte';
|
|
59
|
+
export { default as FormRow } from './components/FormRow.svelte';
|
|
60
|
+
// Inputs
|
|
61
|
+
export { default as SearchPicker } from './components/SearchPicker.svelte';
|
|
62
|
+
export { default as FileButton } from './components/FileButton.svelte';
|
|
63
|
+
export { default as TitleInput } from './components/TitleInput.svelte';
|
|
64
|
+
export { default as RadioCards } from './components/RadioCards.svelte';
|
|
65
|
+
export { default as SegmentedControl } from './components/SegmentedControl.svelte';
|
|
66
|
+
// Overlays
|
|
67
|
+
export { default as ContextMenu } from './components/ContextMenu.svelte';
|
|
68
|
+
export { default as Drawer } from './components/Drawer.svelte';
|
|
69
|
+
export { addDays, calendarRange, eventsOn, sameDay, shiftCalendar, startOfDay, startOfWeek, } from './utils/calendar.js';
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
/** Wall-clock calendar helpers (local time zone) for week and month views. */
|
|
2
|
+
export type CalendarMode = 'week' | 'month';
|
|
3
|
+
export type CalendarEvent = {
|
|
4
|
+
id: string;
|
|
5
|
+
title: string;
|
|
6
|
+
start: Date;
|
|
7
|
+
end: Date;
|
|
8
|
+
allDay: boolean;
|
|
9
|
+
/** Dimmed (e.g. "free" / transparent events). */
|
|
10
|
+
muted?: boolean;
|
|
11
|
+
/** Accent colour (palette name or CSS colour). */
|
|
12
|
+
color?: string;
|
|
13
|
+
};
|
|
14
|
+
export declare const MINUTES_PER_DAY: number;
|
|
15
|
+
export declare function startOfDay(d: Date): Date;
|
|
16
|
+
/** Monday of the week containing `d`. */
|
|
17
|
+
export declare function startOfWeek(d: Date): Date;
|
|
18
|
+
export declare function addDays(d: Date, n: number): Date;
|
|
19
|
+
export declare function sameDay(a: Date, b: Date): boolean;
|
|
20
|
+
/** Visible range `[start, end)` around `anchor`: a Monday-start week or a calendar month. */
|
|
21
|
+
export declare function calendarRange(anchor: Date, mode: CalendarMode): {
|
|
22
|
+
start: Date;
|
|
23
|
+
end: Date;
|
|
24
|
+
};
|
|
25
|
+
/** Move the anchor by `delta` weeks or months. */
|
|
26
|
+
export declare function shiftCalendar(anchor: Date, mode: CalendarMode, delta: number): Date;
|
|
27
|
+
/** Six Monday-start weeks covering the month of `monthStart`. */
|
|
28
|
+
export declare function monthGrid(monthStart: Date): Date[];
|
|
29
|
+
/** Events starting on `day`, all-day first, then by start time. */
|
|
30
|
+
export declare function eventsOn(events: CalendarEvent[], day: Date): CalendarEvent[];
|
|
31
|
+
/** Vertical position of a timed event in a day column, as percentages of the day. */
|
|
32
|
+
export declare function dayLayout(event: CalendarEvent): {
|
|
33
|
+
top: number;
|
|
34
|
+
height: number;
|
|
35
|
+
};
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
/** Wall-clock calendar helpers (local time zone) for week and month views. */
|
|
2
|
+
export const MINUTES_PER_DAY = 24 * 60;
|
|
3
|
+
const MIN_EVENT_MINUTES = 15;
|
|
4
|
+
const MONTH_GRID_DAYS = 42;
|
|
5
|
+
export function startOfDay(d) {
|
|
6
|
+
const x = new Date(d);
|
|
7
|
+
x.setHours(0, 0, 0, 0);
|
|
8
|
+
return x;
|
|
9
|
+
}
|
|
10
|
+
/** Monday of the week containing `d`. */
|
|
11
|
+
export function startOfWeek(d) {
|
|
12
|
+
const x = startOfDay(d);
|
|
13
|
+
const day = x.getDay();
|
|
14
|
+
x.setDate(x.getDate() + (day === 0 ? -6 : 1 - day));
|
|
15
|
+
return x;
|
|
16
|
+
}
|
|
17
|
+
export function addDays(d, n) {
|
|
18
|
+
const x = new Date(d);
|
|
19
|
+
x.setDate(x.getDate() + n);
|
|
20
|
+
return x;
|
|
21
|
+
}
|
|
22
|
+
export function sameDay(a, b) {
|
|
23
|
+
return startOfDay(a).getTime() === startOfDay(b).getTime();
|
|
24
|
+
}
|
|
25
|
+
/** Visible range `[start, end)` around `anchor`: a Monday-start week or a calendar month. */
|
|
26
|
+
export function calendarRange(anchor, mode) {
|
|
27
|
+
if (mode === 'week') {
|
|
28
|
+
const start = startOfWeek(anchor);
|
|
29
|
+
return { start, end: addDays(start, 7) };
|
|
30
|
+
}
|
|
31
|
+
return {
|
|
32
|
+
start: new Date(anchor.getFullYear(), anchor.getMonth(), 1),
|
|
33
|
+
end: new Date(anchor.getFullYear(), anchor.getMonth() + 1, 1),
|
|
34
|
+
};
|
|
35
|
+
}
|
|
36
|
+
/** Move the anchor by `delta` weeks or months. */
|
|
37
|
+
export function shiftCalendar(anchor, mode, delta) {
|
|
38
|
+
if (mode === 'week')
|
|
39
|
+
return addDays(anchor, 7 * delta);
|
|
40
|
+
const x = new Date(anchor);
|
|
41
|
+
x.setMonth(x.getMonth() + delta);
|
|
42
|
+
return x;
|
|
43
|
+
}
|
|
44
|
+
/** Six Monday-start weeks covering the month of `monthStart`. */
|
|
45
|
+
export function monthGrid(monthStart) {
|
|
46
|
+
const first = startOfWeek(monthStart);
|
|
47
|
+
return Array.from({ length: MONTH_GRID_DAYS }, (_, i) => addDays(first, i));
|
|
48
|
+
}
|
|
49
|
+
/** Events starting on `day`, all-day first, then by start time. */
|
|
50
|
+
export function eventsOn(events, day) {
|
|
51
|
+
return events
|
|
52
|
+
.filter((e) => sameDay(e.start, day))
|
|
53
|
+
.sort((a, b) => Number(b.allDay) - Number(a.allDay) || a.start.getTime() - b.start.getTime());
|
|
54
|
+
}
|
|
55
|
+
/** Vertical position of a timed event in a day column, as percentages of the day. */
|
|
56
|
+
export function dayLayout(event) {
|
|
57
|
+
const minutes = (event.start.getTime() - startOfDay(event.start).getTime()) / 60000;
|
|
58
|
+
const duration = Math.max(MIN_EVENT_MINUTES, (event.end.getTime() - event.start.getTime()) / 60000);
|
|
59
|
+
const top = (minutes / MINUTES_PER_DAY) * 100;
|
|
60
|
+
return { top, height: Math.min((duration / MINUTES_PER_DAY) * 100, 100 - top) };
|
|
61
|
+
}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
export type CommandItem = {
|
|
2
|
+
id: string;
|
|
3
|
+
label: string;
|
|
4
|
+
/** Secondary text on the right, e.g. a type name or shortcut. */
|
|
5
|
+
hint?: string;
|
|
6
|
+
/** Extra words that match the query but are not shown. */
|
|
7
|
+
keywords?: string;
|
|
8
|
+
/** Rows with the same group are listed together under that heading. */
|
|
9
|
+
group?: string;
|
|
10
|
+
/** NavIcon name shown before the label. */
|
|
11
|
+
icon?: string;
|
|
12
|
+
iconColor?: string;
|
|
13
|
+
onSelect?: () => void;
|
|
14
|
+
};
|
|
15
|
+
export type CommandGroup = {
|
|
16
|
+
group: string | undefined;
|
|
17
|
+
items: CommandItem[];
|
|
18
|
+
};
|
|
19
|
+
/** Case-insensitive substring match on label + keywords; an empty query keeps everything. */
|
|
20
|
+
export declare function filterCommands(items: CommandItem[], query: string): CommandItem[];
|
|
21
|
+
/** Group rows by `group`, keeping first-seen group order and row order within groups. */
|
|
22
|
+
export declare function groupCommands(items: CommandItem[]): CommandGroup[];
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
/** Case-insensitive substring match on label + keywords; an empty query keeps everything. */
|
|
2
|
+
export function filterCommands(items, query) {
|
|
3
|
+
const needle = query.trim().toLowerCase();
|
|
4
|
+
if (!needle)
|
|
5
|
+
return items;
|
|
6
|
+
return items.filter((item) => `${item.label} ${item.keywords ?? ''}`.toLowerCase().includes(needle));
|
|
7
|
+
}
|
|
8
|
+
/** Group rows by `group`, keeping first-seen group order and row order within groups. */
|
|
9
|
+
export function groupCommands(items) {
|
|
10
|
+
const groups = new Map();
|
|
11
|
+
for (const item of items) {
|
|
12
|
+
const rows = groups.get(item.group) ?? [];
|
|
13
|
+
rows.push(item);
|
|
14
|
+
groups.set(item.group, rows);
|
|
15
|
+
}
|
|
16
|
+
return [...groups].map(([group, rows]) => ({ group, items: rows }));
|
|
17
|
+
}
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
export type DataColumn = {
|
|
2
|
+
key: string;
|
|
3
|
+
label: string;
|
|
4
|
+
/** CSS width, e.g. `8rem` or `30%`. */
|
|
5
|
+
width?: string;
|
|
6
|
+
align?: 'start' | 'end';
|
|
7
|
+
/** Hide below 700px so phone tables keep their key columns. */
|
|
8
|
+
hideOnMobile?: boolean;
|
|
9
|
+
};
|
|
10
|
+
export type PickerOption = {
|
|
11
|
+
id: string;
|
|
12
|
+
label: string;
|
|
13
|
+
description?: string;
|
|
14
|
+
/** NavIcon name. */
|
|
15
|
+
icon?: string;
|
|
16
|
+
iconColor?: string;
|
|
17
|
+
};
|
|
18
|
+
export type RadioCardOption = {
|
|
19
|
+
value: string;
|
|
20
|
+
label: string;
|
|
21
|
+
description?: string;
|
|
22
|
+
};
|
|
23
|
+
export type SegmentOption = {
|
|
24
|
+
value: string;
|
|
25
|
+
label: string;
|
|
26
|
+
};
|
|
27
|
+
export type DescriptionItem = {
|
|
28
|
+
term: string;
|
|
29
|
+
detail: string | number;
|
|
30
|
+
tone?: 'default' | 'danger' | 'success';
|
|
31
|
+
};
|
|
32
|
+
export type ViewerMark = {
|
|
33
|
+
id: string;
|
|
34
|
+
/** Position and size as fractions (0–1) of the page. */
|
|
35
|
+
x: number;
|
|
36
|
+
y: number;
|
|
37
|
+
w: number;
|
|
38
|
+
h: number;
|
|
39
|
+
color?: string;
|
|
40
|
+
label?: string;
|
|
41
|
+
};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
/** Move a highlighted row by `delta`, wrapping around a list of `length` rows (-1 when empty). */
|
|
2
|
+
export function moveIndex(current, delta, length) {
|
|
3
|
+
if (length <= 0)
|
|
4
|
+
return -1;
|
|
5
|
+
if (current < 0)
|
|
6
|
+
return delta > 0 ? 0 : length - 1;
|
|
7
|
+
return (((current + delta) % length) + length) % length;
|
|
8
|
+
}
|