@nqmcreative/ui 0.2.1 → 0.2.2
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 +7 -5
- package/dist/styles/sprout/Accordion.svelte +17 -0
- package/dist/styles/sprout/Accordion.svelte.d.ts +8 -0
- package/dist/styles/sprout/AccordionItem.svelte +46 -0
- package/dist/styles/sprout/AccordionItem.svelte.d.ts +14 -0
- package/dist/styles/sprout/Alert.svelte +100 -0
- package/dist/styles/sprout/Alert.svelte.d.ts +18 -0
- package/dist/styles/sprout/Avatar.svelte +60 -0
- package/dist/styles/sprout/Avatar.svelte.d.ts +16 -0
- package/dist/styles/sprout/AvatarGroup.svelte +17 -0
- package/dist/styles/sprout/AvatarGroup.svelte.d.ts +8 -0
- package/dist/styles/sprout/Badge.svelte +58 -0
- package/dist/styles/sprout/Badge.svelte.d.ts +16 -0
- package/dist/styles/sprout/Breadcrumb.svelte +49 -0
- package/dist/styles/sprout/Breadcrumb.svelte.d.ts +14 -0
- package/dist/styles/sprout/Button.svelte +105 -0
- package/dist/styles/sprout/Button.svelte.d.ts +21 -0
- package/dist/styles/sprout/CTASection.svelte +77 -0
- package/dist/styles/sprout/CTASection.svelte.d.ts +18 -0
- package/dist/styles/sprout/Calendar.svelte +202 -0
- package/dist/styles/sprout/Calendar.svelte.d.ts +22 -0
- package/dist/styles/sprout/Card.svelte +82 -0
- package/dist/styles/sprout/Card.svelte.d.ts +21 -0
- package/dist/styles/sprout/Checkbox.svelte +76 -0
- package/dist/styles/sprout/Checkbox.svelte.d.ts +15 -0
- package/dist/styles/sprout/CheckboxGroup.svelte +112 -0
- package/dist/styles/sprout/CheckboxGroup.svelte.d.ts +30 -0
- package/dist/styles/sprout/Combobox.svelte +267 -0
- package/dist/styles/sprout/Combobox.svelte.d.ts +29 -0
- package/dist/styles/sprout/CommandPalette.svelte +210 -0
- package/dist/styles/sprout/CommandPalette.svelte.d.ts +32 -0
- package/dist/styles/sprout/ConfirmDialog.svelte +97 -0
- package/dist/styles/sprout/ConfirmDialog.svelte.d.ts +22 -0
- package/dist/styles/sprout/ContextMenu.svelte +89 -0
- package/dist/styles/sprout/ContextMenu.svelte.d.ts +15 -0
- package/dist/styles/sprout/DatePicker.svelte +193 -0
- package/dist/styles/sprout/DatePicker.svelte.d.ts +23 -0
- package/dist/styles/sprout/Divider.svelte +30 -0
- package/dist/styles/sprout/Divider.svelte.d.ts +10 -0
- package/dist/styles/sprout/Drawer.svelte +166 -0
- package/dist/styles/sprout/Drawer.svelte.d.ts +20 -0
- package/dist/styles/sprout/Dropdown.svelte +95 -0
- package/dist/styles/sprout/Dropdown.svelte.d.ts +23 -0
- package/dist/styles/sprout/Dropzone.svelte +211 -0
- package/dist/styles/sprout/Dropzone.svelte.d.ts +29 -0
- package/dist/styles/sprout/EmptyState.svelte +71 -0
- package/dist/styles/sprout/EmptyState.svelte.d.ts +18 -0
- package/dist/styles/sprout/FeatureCard.svelte +61 -0
- package/dist/styles/sprout/FeatureCard.svelte.d.ts +16 -0
- package/dist/styles/sprout/FeatureGrid.svelte +62 -0
- package/dist/styles/sprout/FeatureGrid.svelte.d.ts +16 -0
- package/dist/styles/sprout/Field.svelte +42 -0
- package/dist/styles/sprout/Field.svelte.d.ts +16 -0
- package/dist/styles/sprout/Footer.svelte +91 -0
- package/dist/styles/sprout/Footer.svelte.d.ts +25 -0
- package/dist/styles/sprout/HeroSection.svelte +86 -0
- package/dist/styles/sprout/HeroSection.svelte.d.ts +21 -0
- package/dist/styles/sprout/Input.svelte +61 -0
- package/dist/styles/sprout/Input.svelte.d.ts +18 -0
- package/dist/styles/sprout/InputGroup.svelte +20 -0
- package/dist/styles/sprout/InputGroup.svelte.d.ts +11 -0
- package/dist/styles/sprout/Kbd.svelte +18 -0
- package/dist/styles/sprout/Kbd.svelte.d.ts +8 -0
- package/dist/styles/sprout/Label.svelte +16 -0
- package/dist/styles/sprout/Label.svelte.d.ts +9 -0
- package/dist/styles/sprout/Link.svelte +44 -0
- package/dist/styles/sprout/Link.svelte.d.ts +16 -0
- package/dist/styles/sprout/LocaleProvider.svelte +24 -0
- package/dist/styles/sprout/LocaleProvider.svelte.d.ts +10 -0
- package/dist/styles/sprout/LogoCloud.svelte +61 -0
- package/dist/styles/sprout/LogoCloud.svelte.d.ts +19 -0
- package/dist/styles/sprout/MenuItem.svelte +64 -0
- package/dist/styles/sprout/MenuItem.svelte.d.ts +18 -0
- package/dist/styles/sprout/MenuSeparator.svelte +22 -0
- package/dist/styles/sprout/MenuSeparator.svelte.d.ts +8 -0
- package/dist/styles/sprout/Modal.svelte +119 -0
- package/dist/styles/sprout/Modal.svelte.d.ts +21 -0
- package/dist/styles/sprout/MultiSelect.svelte +288 -0
- package/dist/styles/sprout/MultiSelect.svelte.d.ts +31 -0
- package/dist/styles/sprout/Navbar.svelte +201 -0
- package/dist/styles/sprout/Navbar.svelte.d.ts +33 -0
- package/dist/styles/sprout/NumberInput.svelte +97 -0
- package/dist/styles/sprout/NumberInput.svelte.d.ts +15 -0
- package/dist/styles/sprout/Pagination.svelte +84 -0
- package/dist/styles/sprout/Pagination.svelte.d.ts +15 -0
- package/dist/styles/sprout/PasswordInput.svelte +101 -0
- package/dist/styles/sprout/PasswordInput.svelte.d.ts +12 -0
- package/dist/styles/sprout/Popover.svelte +90 -0
- package/dist/styles/sprout/Popover.svelte.d.ts +19 -0
- package/dist/styles/sprout/PricingCard.svelte +109 -0
- package/dist/styles/sprout/PricingCard.svelte.d.ts +25 -0
- package/dist/styles/sprout/Progress.svelte +59 -0
- package/dist/styles/sprout/Progress.svelte.d.ts +17 -0
- package/dist/styles/sprout/Radio.svelte +56 -0
- package/dist/styles/sprout/Radio.svelte.d.ts +15 -0
- package/dist/styles/sprout/RadioGroup.svelte +96 -0
- package/dist/styles/sprout/RadioGroup.svelte.d.ts +27 -0
- package/dist/styles/sprout/SegmentedControl.svelte +89 -0
- package/dist/styles/sprout/SegmentedControl.svelte.d.ts +25 -0
- package/dist/styles/sprout/Select.svelte +62 -0
- package/dist/styles/sprout/Select.svelte.d.ts +20 -0
- package/dist/styles/sprout/Sidebar.svelte +206 -0
- package/dist/styles/sprout/Sidebar.svelte.d.ts +36 -0
- package/dist/styles/sprout/Skeleton.svelte +46 -0
- package/dist/styles/sprout/Skeleton.svelte.d.ts +13 -0
- package/dist/styles/sprout/Slider.svelte +80 -0
- package/dist/styles/sprout/Slider.svelte.d.ts +19 -0
- package/dist/styles/sprout/Spinner.svelte +34 -0
- package/dist/styles/sprout/Spinner.svelte.d.ts +13 -0
- package/dist/styles/sprout/Stat.svelte +51 -0
- package/dist/styles/sprout/Stat.svelte.d.ts +16 -0
- package/dist/styles/sprout/StatsBand.svelte +64 -0
- package/dist/styles/sprout/StatsBand.svelte.d.ts +20 -0
- package/dist/styles/sprout/Steps.svelte +143 -0
- package/dist/styles/sprout/Steps.svelte.d.ts +24 -0
- package/dist/styles/sprout/Switch.svelte +65 -0
- package/dist/styles/sprout/Switch.svelte.d.ts +14 -0
- package/dist/styles/sprout/Table.svelte +218 -0
- package/dist/styles/sprout/Table.svelte.d.ts +66 -0
- package/dist/styles/sprout/Tabs.svelte +103 -0
- package/dist/styles/sprout/Tabs.svelte.d.ts +23 -0
- package/dist/styles/sprout/Testimonial.svelte +65 -0
- package/dist/styles/sprout/Testimonial.svelte.d.ts +19 -0
- package/dist/styles/sprout/Textarea.svelte +55 -0
- package/dist/styles/sprout/Textarea.svelte.d.ts +12 -0
- package/dist/styles/sprout/ThemeToggle.svelte +131 -0
- package/dist/styles/sprout/ThemeToggle.svelte.d.ts +16 -0
- package/dist/styles/sprout/Toaster.svelte +133 -0
- package/dist/styles/sprout/Toaster.svelte.d.ts +8 -0
- package/dist/styles/sprout/Tooltip.svelte +34 -0
- package/dist/styles/sprout/Tooltip.svelte.d.ts +12 -0
- package/dist/styles/sprout/fonts.css +78 -0
- package/dist/styles/sprout/index.d.ts +109 -0
- package/dist/styles/sprout/index.js +83 -0
- package/dist/styles/sprout/lift.d.ts +40 -0
- package/dist/styles/sprout/lift.js +36 -0
- package/dist/styles/sprout/theme.css +255 -0
- package/package.json +269 -3
- package/registry.json +137 -65
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
import type { Snippet } from 'svelte';
|
|
3
|
+
import type { HTMLAttributes } from 'svelte/elements';
|
|
4
|
+
import { toneSoft, type Tone } from '../../core/tones.js';
|
|
5
|
+
|
|
6
|
+
interface Props extends HTMLAttributes<HTMLElement> {
|
|
7
|
+
/** Small line above the headline. */
|
|
8
|
+
eyebrow?: string;
|
|
9
|
+
title: string;
|
|
10
|
+
description?: string;
|
|
11
|
+
tone?: Tone;
|
|
12
|
+
/** `center` also centres the actions. Ignored when `media` is set. */
|
|
13
|
+
align?: 'left' | 'center';
|
|
14
|
+
/** Buttons under the copy. */
|
|
15
|
+
actions?: Snippet;
|
|
16
|
+
/** Anything on the right — a screenshot, an illustration, a form. */
|
|
17
|
+
media?: Snippet;
|
|
18
|
+
/** Extra content between the description and the actions. */
|
|
19
|
+
children?: Snippet;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
let {
|
|
23
|
+
eyebrow,
|
|
24
|
+
title,
|
|
25
|
+
description,
|
|
26
|
+
tone = 'brand',
|
|
27
|
+
align = 'left',
|
|
28
|
+
actions,
|
|
29
|
+
media,
|
|
30
|
+
class: className = '',
|
|
31
|
+
children,
|
|
32
|
+
...rest
|
|
33
|
+
}: Props = $props();
|
|
34
|
+
|
|
35
|
+
// A media column only makes sense next to left-aligned copy.
|
|
36
|
+
const centred = $derived(align === 'center' && !media);
|
|
37
|
+
</script>
|
|
38
|
+
|
|
39
|
+
<section class="w-full px-6 py-20 sm:py-28 {className}" {...rest}>
|
|
40
|
+
<div
|
|
41
|
+
class="mx-auto flex w-full max-w-6xl gap-16
|
|
42
|
+
{media ? 'flex-col lg:flex-row lg:items-center' : 'flex-col'}"
|
|
43
|
+
>
|
|
44
|
+
<div
|
|
45
|
+
class="flex min-w-0 flex-1 flex-col gap-6 {centred
|
|
46
|
+
? 'items-center text-center'
|
|
47
|
+
: 'items-start'}"
|
|
48
|
+
>
|
|
49
|
+
{#if eyebrow}
|
|
50
|
+
<span
|
|
51
|
+
class="inline-flex rounded-full px-3 py-1 font-sans text-[13px] font-medium {toneSoft[
|
|
52
|
+
tone
|
|
53
|
+
]}"
|
|
54
|
+
>
|
|
55
|
+
{eyebrow}
|
|
56
|
+
</span>
|
|
57
|
+
{/if}
|
|
58
|
+
|
|
59
|
+
<h1
|
|
60
|
+
class="max-w-2xl font-heading text-4xl leading-[1.1] font-semibold tracking-tight text-balance text-text sm:text-5xl"
|
|
61
|
+
>
|
|
62
|
+
{title}
|
|
63
|
+
</h1>
|
|
64
|
+
|
|
65
|
+
{#if description}
|
|
66
|
+
<p class="max-w-xl font-sans text-lg leading-relaxed text-pretty text-text-secondary">
|
|
67
|
+
{description}
|
|
68
|
+
</p>
|
|
69
|
+
{/if}
|
|
70
|
+
|
|
71
|
+
{#if children}
|
|
72
|
+
{@render children()}
|
|
73
|
+
{/if}
|
|
74
|
+
|
|
75
|
+
{#if actions}
|
|
76
|
+
<div class="flex flex-wrap items-center gap-3 pt-2 {centred ? 'justify-center' : ''}">
|
|
77
|
+
{@render actions()}
|
|
78
|
+
</div>
|
|
79
|
+
{/if}
|
|
80
|
+
</div>
|
|
81
|
+
|
|
82
|
+
{#if media}
|
|
83
|
+
<div class="min-w-0 flex-1">{@render media()}</div>
|
|
84
|
+
{/if}
|
|
85
|
+
</div>
|
|
86
|
+
</section>
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import type { Snippet } from 'svelte';
|
|
2
|
+
import type { HTMLAttributes } from 'svelte/elements';
|
|
3
|
+
import { type Tone } from '../../core/tones.js';
|
|
4
|
+
interface Props extends HTMLAttributes<HTMLElement> {
|
|
5
|
+
/** Small line above the headline. */
|
|
6
|
+
eyebrow?: string;
|
|
7
|
+
title: string;
|
|
8
|
+
description?: string;
|
|
9
|
+
tone?: Tone;
|
|
10
|
+
/** `center` also centres the actions. Ignored when `media` is set. */
|
|
11
|
+
align?: 'left' | 'center';
|
|
12
|
+
/** Buttons under the copy. */
|
|
13
|
+
actions?: Snippet;
|
|
14
|
+
/** Anything on the right — a screenshot, an illustration, a form. */
|
|
15
|
+
media?: Snippet;
|
|
16
|
+
/** Extra content between the description and the actions. */
|
|
17
|
+
children?: Snippet;
|
|
18
|
+
}
|
|
19
|
+
declare const HeroSection: import("svelte").Component<Props, {}, "">;
|
|
20
|
+
type HeroSection = ReturnType<typeof HeroSection>;
|
|
21
|
+
export default HeroSection;
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
import type { Snippet } from 'svelte';
|
|
3
|
+
import type { HTMLInputAttributes } from 'svelte/elements';
|
|
4
|
+
import { toneFocusWithinBorder, type Tone } from '../../core/tones.js';
|
|
5
|
+
import { edge } from './lift.js';
|
|
6
|
+
|
|
7
|
+
export type InputSize = 'sm' | 'md' | 'lg';
|
|
8
|
+
|
|
9
|
+
interface Props extends Omit<HTMLInputAttributes, 'size' | 'prefix' | 'suffix'> {
|
|
10
|
+
value?: string;
|
|
11
|
+
size?: InputSize;
|
|
12
|
+
tone?: Tone;
|
|
13
|
+
/** Paints the field red and sets `aria-invalid`. */
|
|
14
|
+
invalid?: boolean;
|
|
15
|
+
/** Leading adornment — an icon, a currency symbol, `https://` … */
|
|
16
|
+
prefix?: Snippet;
|
|
17
|
+
/** Trailing adornment. */
|
|
18
|
+
suffix?: Snippet;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
let {
|
|
22
|
+
value = $bindable(''),
|
|
23
|
+
size = 'md',
|
|
24
|
+
tone = 'brand',
|
|
25
|
+
invalid = false,
|
|
26
|
+
disabled = false,
|
|
27
|
+
prefix,
|
|
28
|
+
suffix,
|
|
29
|
+
class: className = '',
|
|
30
|
+
...rest
|
|
31
|
+
}: Props = $props();
|
|
32
|
+
|
|
33
|
+
const sizes: Record<InputSize, string> = {
|
|
34
|
+
sm: 'h-8 text-[13px]',
|
|
35
|
+
md: 'h-10 text-sm',
|
|
36
|
+
lg: 'h-11 text-[15px]'
|
|
37
|
+
};
|
|
38
|
+
</script>
|
|
39
|
+
|
|
40
|
+
<span
|
|
41
|
+
class="inline-flex w-full items-center gap-2 rounded-xl border bg-bg px-3 {edge} transition-colors duration-150 ease-brand-out
|
|
42
|
+
{sizes[size]}
|
|
43
|
+
{invalid
|
|
44
|
+
? 'border-danger focus-within:border-danger'
|
|
45
|
+
: `border-hairline-strong ${toneFocusWithinBorder[tone]}`}
|
|
46
|
+
{disabled ? 'pointer-events-none opacity-50' : ''} {className}"
|
|
47
|
+
>
|
|
48
|
+
{#if prefix}
|
|
49
|
+
<span class="shrink-0 text-text-muted">{@render prefix()}</span>
|
|
50
|
+
{/if}
|
|
51
|
+
<input
|
|
52
|
+
bind:value
|
|
53
|
+
{disabled}
|
|
54
|
+
aria-invalid={invalid ? 'true' : undefined}
|
|
55
|
+
class="w-full min-w-0 bg-transparent font-sans text-text placeholder:text-text-muted focus:outline-none"
|
|
56
|
+
{...rest}
|
|
57
|
+
/>
|
|
58
|
+
{#if suffix}
|
|
59
|
+
<span class="shrink-0 text-text-muted">{@render suffix()}</span>
|
|
60
|
+
{/if}
|
|
61
|
+
</span>
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import type { Snippet } from 'svelte';
|
|
2
|
+
import type { HTMLInputAttributes } from 'svelte/elements';
|
|
3
|
+
import { type Tone } from '../../core/tones.js';
|
|
4
|
+
export type InputSize = 'sm' | 'md' | 'lg';
|
|
5
|
+
interface Props extends Omit<HTMLInputAttributes, 'size' | 'prefix' | 'suffix'> {
|
|
6
|
+
value?: string;
|
|
7
|
+
size?: InputSize;
|
|
8
|
+
tone?: Tone;
|
|
9
|
+
/** Paints the field red and sets `aria-invalid`. */
|
|
10
|
+
invalid?: boolean;
|
|
11
|
+
/** Leading adornment — an icon, a currency symbol, `https://` … */
|
|
12
|
+
prefix?: Snippet;
|
|
13
|
+
/** Trailing adornment. */
|
|
14
|
+
suffix?: Snippet;
|
|
15
|
+
}
|
|
16
|
+
declare const Input: import("svelte").Component<Props, {}, "value">;
|
|
17
|
+
type Input = ReturnType<typeof Input>;
|
|
18
|
+
export default Input;
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
import type { Snippet } from 'svelte';
|
|
3
|
+
import type { HTMLAttributes } from 'svelte/elements';
|
|
4
|
+
|
|
5
|
+
interface Props extends HTMLAttributes<HTMLDivElement> {
|
|
6
|
+
/** Children sit flush against each other with shared borders — an Input
|
|
7
|
+
* plus a Button, a Select plus an Input, and so on. The outer corners
|
|
8
|
+
* keep the style's radius; the joins inside are squared off. */
|
|
9
|
+
children: Snippet;
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
let { class: className = '', children, ...rest }: Props = $props();
|
|
13
|
+
</script>
|
|
14
|
+
|
|
15
|
+
<div
|
|
16
|
+
class="flex w-full items-stretch [&>*]:min-w-0 [&>*]:rounded-none [&>*:first-child]:rounded-l-xl [&>*:focus-within]:relative [&>*:focus-within]:z-10 [&>*:last-child]:rounded-r-xl [&>*:not(:first-child)]:-ml-px {className}"
|
|
17
|
+
{...rest}
|
|
18
|
+
>
|
|
19
|
+
{@render children()}
|
|
20
|
+
</div>
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import type { Snippet } from 'svelte';
|
|
2
|
+
import type { HTMLAttributes } from 'svelte/elements';
|
|
3
|
+
interface Props extends HTMLAttributes<HTMLDivElement> {
|
|
4
|
+
/** Children sit flush against each other with shared borders — an Input
|
|
5
|
+
* plus a Button, a Select plus an Input, and so on. The outer corners
|
|
6
|
+
* keep the style's radius; the joins inside are squared off. */
|
|
7
|
+
children: Snippet;
|
|
8
|
+
}
|
|
9
|
+
declare const InputGroup: import("svelte").Component<Props, {}, "">;
|
|
10
|
+
type InputGroup = ReturnType<typeof InputGroup>;
|
|
11
|
+
export default InputGroup;
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
import type { Snippet } from 'svelte';
|
|
3
|
+
import type { HTMLAttributes } from 'svelte/elements';
|
|
4
|
+
import { edge } from './lift.js';
|
|
5
|
+
|
|
6
|
+
interface Props extends HTMLAttributes<HTMLElement> {
|
|
7
|
+
children: Snippet;
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
let { class: className = '', children, ...rest }: Props = $props();
|
|
11
|
+
</script>
|
|
12
|
+
|
|
13
|
+
<kbd
|
|
14
|
+
class="inline-flex h-6 min-w-6 items-center justify-center rounded-xl border border-hairline bg-bg-alt px-1.5 font-sans text-[11px] font-medium text-text-secondary {edge} {className}"
|
|
15
|
+
{...rest}
|
|
16
|
+
>
|
|
17
|
+
{@render children()}
|
|
18
|
+
</kbd>
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import type { Snippet } from 'svelte';
|
|
2
|
+
import type { HTMLAttributes } from 'svelte/elements';
|
|
3
|
+
interface Props extends HTMLAttributes<HTMLElement> {
|
|
4
|
+
children: Snippet;
|
|
5
|
+
}
|
|
6
|
+
declare const Kbd: import("svelte").Component<Props, {}, "">;
|
|
7
|
+
type Kbd = ReturnType<typeof Kbd>;
|
|
8
|
+
export default Kbd;
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
import type { Snippet } from 'svelte';
|
|
3
|
+
import type { HTMLLabelAttributes } from 'svelte/elements';
|
|
4
|
+
|
|
5
|
+
interface Props extends HTMLLabelAttributes {
|
|
6
|
+
required?: boolean;
|
|
7
|
+
children: Snippet;
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
let { required = false, class: className = '', children, ...rest }: Props = $props();
|
|
11
|
+
</script>
|
|
12
|
+
|
|
13
|
+
<label class="font-sans text-sm font-medium text-text {className}" {...rest}>
|
|
14
|
+
{@render children()}
|
|
15
|
+
{#if required}<span class="ml-0.5 text-danger" aria-hidden="true">*</span>{/if}
|
|
16
|
+
</label>
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import type { Snippet } from 'svelte';
|
|
2
|
+
import type { HTMLLabelAttributes } from 'svelte/elements';
|
|
3
|
+
interface Props extends HTMLLabelAttributes {
|
|
4
|
+
required?: boolean;
|
|
5
|
+
children: Snippet;
|
|
6
|
+
}
|
|
7
|
+
declare const Label: import("svelte").Component<Props, {}, "">;
|
|
8
|
+
type Label = ReturnType<typeof Label>;
|
|
9
|
+
export default Label;
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
import type { Snippet } from 'svelte';
|
|
3
|
+
import type { HTMLAnchorAttributes } from 'svelte/elements';
|
|
4
|
+
import { focusRing, toneHoverText, toneRing, toneText, type Tone } from '../../core/tones.js';
|
|
5
|
+
|
|
6
|
+
interface Props extends HTMLAnchorAttributes {
|
|
7
|
+
tone?: Tone;
|
|
8
|
+
/** `'hover'` shows the rule only on hover. */
|
|
9
|
+
underline?: 'always' | 'hover' | 'none';
|
|
10
|
+
/** Adds `target="_blank" rel="noreferrer"` and an arrow glyph. */
|
|
11
|
+
external?: boolean;
|
|
12
|
+
/** Inherit the surrounding text colour instead of the tone. */
|
|
13
|
+
muted?: boolean;
|
|
14
|
+
children: Snippet;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
let {
|
|
18
|
+
tone = 'brand',
|
|
19
|
+
underline = 'hover',
|
|
20
|
+
external = false,
|
|
21
|
+
muted = false,
|
|
22
|
+
class: className = '',
|
|
23
|
+
children,
|
|
24
|
+
...rest
|
|
25
|
+
}: Props = $props();
|
|
26
|
+
|
|
27
|
+
const underlines = {
|
|
28
|
+
always: 'underline underline-offset-2 decoration-current/40',
|
|
29
|
+
hover: 'hover:underline underline-offset-2 decoration-current/40',
|
|
30
|
+
none: ''
|
|
31
|
+
};
|
|
32
|
+
</script>
|
|
33
|
+
|
|
34
|
+
<a
|
|
35
|
+
target={external ? '_blank' : undefined}
|
|
36
|
+
rel={external ? 'noreferrer' : undefined}
|
|
37
|
+
class="inline-flex items-center gap-1 rounded-md font-sans transition-colors duration-150 ease-brand-out
|
|
38
|
+
{muted ? `text-text-secondary ${toneHoverText[tone]}` : toneText[tone]}
|
|
39
|
+
{underlines[underline]} {focusRing} {toneRing[tone]} {className}"
|
|
40
|
+
{...rest}
|
|
41
|
+
>
|
|
42
|
+
{@render children()}
|
|
43
|
+
{#if external}<span aria-hidden="true" class="text-[0.85em]">↗</span>{/if}
|
|
44
|
+
</a>
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import type { Snippet } from 'svelte';
|
|
2
|
+
import type { HTMLAnchorAttributes } from 'svelte/elements';
|
|
3
|
+
import { type Tone } from '../../core/tones.js';
|
|
4
|
+
interface Props extends HTMLAnchorAttributes {
|
|
5
|
+
tone?: Tone;
|
|
6
|
+
/** `'hover'` shows the rule only on hover. */
|
|
7
|
+
underline?: 'always' | 'hover' | 'none';
|
|
8
|
+
/** Adds `target="_blank" rel="noreferrer"` and an arrow glyph. */
|
|
9
|
+
external?: boolean;
|
|
10
|
+
/** Inherit the surrounding text colour instead of the tone. */
|
|
11
|
+
muted?: boolean;
|
|
12
|
+
children: Snippet;
|
|
13
|
+
}
|
|
14
|
+
declare const Link: import("svelte").Component<Props, {}, "">;
|
|
15
|
+
type Link = ReturnType<typeof Link>;
|
|
16
|
+
export default Link;
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
import type { Snippet } from 'svelte';
|
|
3
|
+
import { provideLocale, type Locale } from '../../core/locale.svelte.js';
|
|
4
|
+
|
|
5
|
+
interface Props {
|
|
6
|
+
/** Full locale or just the keys you want to change. */
|
|
7
|
+
locale: Partial<Locale>;
|
|
8
|
+
children: Snippet;
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
let { locale, children }: Props = $props();
|
|
12
|
+
|
|
13
|
+
// Seeded during init so the first render already has the right strings —
|
|
14
|
+
// an effect would leave one frame (and the SSR output) in the default
|
|
15
|
+
// language. The effect below only handles later changes, e.g. a switcher.
|
|
16
|
+
// svelte-ignore state_referenced_locally
|
|
17
|
+
const store = provideLocale(locale);
|
|
18
|
+
|
|
19
|
+
$effect(() => {
|
|
20
|
+
store.replace(locale);
|
|
21
|
+
});
|
|
22
|
+
</script>
|
|
23
|
+
|
|
24
|
+
{@render children()}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import type { Snippet } from 'svelte';
|
|
2
|
+
import { type Locale } from '../../core/locale.svelte.js';
|
|
3
|
+
interface Props {
|
|
4
|
+
/** Full locale or just the keys you want to change. */
|
|
5
|
+
locale: Partial<Locale>;
|
|
6
|
+
children: Snippet;
|
|
7
|
+
}
|
|
8
|
+
declare const LocaleProvider: import("svelte").Component<Props, {}, "">;
|
|
9
|
+
type LocaleProvider = ReturnType<typeof LocaleProvider>;
|
|
10
|
+
export default LocaleProvider;
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
import type { Snippet } from 'svelte';
|
|
3
|
+
import type { HTMLAttributes } from 'svelte/elements';
|
|
4
|
+
|
|
5
|
+
export interface Logo {
|
|
6
|
+
name: string;
|
|
7
|
+
src?: string;
|
|
8
|
+
href?: string;
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
interface Props extends HTMLAttributes<HTMLElement> {
|
|
12
|
+
title?: string;
|
|
13
|
+
/** Without `src` the name is set in the heading face — fine for wordmarks. */
|
|
14
|
+
logos?: Logo[];
|
|
15
|
+
/** Dim until hovered, so the row does not compete with the headline. */
|
|
16
|
+
muted?: boolean;
|
|
17
|
+
/** Your own markup instead of `logos`. */
|
|
18
|
+
children?: Snippet;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
let {
|
|
22
|
+
title,
|
|
23
|
+
logos = [],
|
|
24
|
+
muted = true,
|
|
25
|
+
class: className = '',
|
|
26
|
+
children,
|
|
27
|
+
...rest
|
|
28
|
+
}: Props = $props();
|
|
29
|
+
</script>
|
|
30
|
+
|
|
31
|
+
<section class="w-full px-6 py-14 {className}" {...rest}>
|
|
32
|
+
<div class="mx-auto flex w-full max-w-6xl flex-col items-center gap-8">
|
|
33
|
+
{#if title}
|
|
34
|
+
<p class="text-center font-sans text-[13px] font-medium text-text-muted">{title}</p>
|
|
35
|
+
{/if}
|
|
36
|
+
|
|
37
|
+
<div class="flex flex-wrap items-center justify-center gap-x-12 gap-y-8">
|
|
38
|
+
{#if children}
|
|
39
|
+
{@render children()}
|
|
40
|
+
{:else}
|
|
41
|
+
{#each logos as logo (logo.name)}
|
|
42
|
+
<svelte:element
|
|
43
|
+
this={logo.href ? 'a' : 'div'}
|
|
44
|
+
href={logo.href}
|
|
45
|
+
class="flex items-center rounded transition-all duration-200 ease-brand-out {muted
|
|
46
|
+
? 'opacity-60 grayscale hover:opacity-100 hover:grayscale-0'
|
|
47
|
+
: ''}"
|
|
48
|
+
>
|
|
49
|
+
{#if logo.src}
|
|
50
|
+
<img src={logo.src} alt={logo.name} class="h-7 w-auto object-contain" />
|
|
51
|
+
{:else}
|
|
52
|
+
<span class="font-heading text-lg font-semibold tracking-tight text-text-secondary">
|
|
53
|
+
{logo.name}
|
|
54
|
+
</span>
|
|
55
|
+
{/if}
|
|
56
|
+
</svelte:element>
|
|
57
|
+
{/each}
|
|
58
|
+
{/if}
|
|
59
|
+
</div>
|
|
60
|
+
</div>
|
|
61
|
+
</section>
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import type { Snippet } from 'svelte';
|
|
2
|
+
import type { HTMLAttributes } from 'svelte/elements';
|
|
3
|
+
export interface Logo {
|
|
4
|
+
name: string;
|
|
5
|
+
src?: string;
|
|
6
|
+
href?: string;
|
|
7
|
+
}
|
|
8
|
+
interface Props extends HTMLAttributes<HTMLElement> {
|
|
9
|
+
title?: string;
|
|
10
|
+
/** Without `src` the name is set in the heading face — fine for wordmarks. */
|
|
11
|
+
logos?: Logo[];
|
|
12
|
+
/** Dim until hovered, so the row does not compete with the headline. */
|
|
13
|
+
muted?: boolean;
|
|
14
|
+
/** Your own markup instead of `logos`. */
|
|
15
|
+
children?: Snippet;
|
|
16
|
+
}
|
|
17
|
+
declare const LogoCloud: import("svelte").Component<Props, {}, "">;
|
|
18
|
+
type LogoCloud = ReturnType<typeof LogoCloud>;
|
|
19
|
+
export default LogoCloud;
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
import type { Snippet } from 'svelte';
|
|
3
|
+
import type { HTMLButtonAttributes } from 'svelte/elements';
|
|
4
|
+
import { toneSoftHover, toneText, type Tone } from '../../core/tones.js';
|
|
5
|
+
|
|
6
|
+
interface Props extends HTMLButtonAttributes {
|
|
7
|
+
/** Renders an `<a>` instead of a `<button>`. */
|
|
8
|
+
href?: string;
|
|
9
|
+
tone?: Tone;
|
|
10
|
+
/** Leading glyph. */
|
|
11
|
+
icon?: Snippet;
|
|
12
|
+
/** Right-aligned hint — a keyboard shortcut, a count. */
|
|
13
|
+
shortcut?: string;
|
|
14
|
+
/** Shows a check on the left and marks the item as chosen. */
|
|
15
|
+
selected?: boolean;
|
|
16
|
+
children: Snippet;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
let {
|
|
20
|
+
href,
|
|
21
|
+
tone = 'neutral',
|
|
22
|
+
icon,
|
|
23
|
+
shortcut,
|
|
24
|
+
selected = false,
|
|
25
|
+
disabled = false,
|
|
26
|
+
class: className = '',
|
|
27
|
+
children,
|
|
28
|
+
...rest
|
|
29
|
+
}: Props = $props();
|
|
30
|
+
</script>
|
|
31
|
+
|
|
32
|
+
<svelte:element
|
|
33
|
+
this={href ? 'a' : 'button'}
|
|
34
|
+
{href}
|
|
35
|
+
type={href ? undefined : 'button'}
|
|
36
|
+
role="menuitem"
|
|
37
|
+
disabled={href ? undefined : disabled}
|
|
38
|
+
aria-disabled={disabled ? 'true' : undefined}
|
|
39
|
+
tabindex={disabled ? undefined : -1}
|
|
40
|
+
class="mx-1 flex items-center gap-2.5 rounded-xl px-2.5 py-1.5 text-left text-sm transition-colors duration-100 ease-brand-out focus:outline-none disabled:pointer-events-none disabled:opacity-40
|
|
41
|
+
{tone === 'neutral'
|
|
42
|
+
? 'text-text-secondary hover:bg-bg-inset focus-visible:bg-bg-inset'
|
|
43
|
+
: `${toneText[tone]} ${toneSoftHover[tone]}`}
|
|
44
|
+
{className}"
|
|
45
|
+
{...rest}
|
|
46
|
+
>
|
|
47
|
+
{#if selected}
|
|
48
|
+
<svg class="size-3.5 shrink-0" viewBox="0 0 14 14" fill="none" aria-hidden="true">
|
|
49
|
+
<path
|
|
50
|
+
d="m2 7 3.2 3.2L12 3.6"
|
|
51
|
+
stroke="currentColor"
|
|
52
|
+
stroke-width="1.8"
|
|
53
|
+
stroke-linecap="round"
|
|
54
|
+
stroke-linejoin="round"
|
|
55
|
+
/>
|
|
56
|
+
</svg>
|
|
57
|
+
{:else if icon}
|
|
58
|
+
<span class="flex size-3.5 shrink-0 items-center justify-center">{@render icon()}</span>
|
|
59
|
+
{/if}
|
|
60
|
+
<span class="min-w-0 flex-1 truncate">{@render children()}</span>
|
|
61
|
+
{#if shortcut}
|
|
62
|
+
<span class="shrink-0 text-[11px] text-text-muted">{shortcut}</span>
|
|
63
|
+
{/if}
|
|
64
|
+
</svelte:element>
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import type { Snippet } from 'svelte';
|
|
2
|
+
import type { HTMLButtonAttributes } from 'svelte/elements';
|
|
3
|
+
import { type Tone } from '../../core/tones.js';
|
|
4
|
+
interface Props extends HTMLButtonAttributes {
|
|
5
|
+
/** Renders an `<a>` instead of a `<button>`. */
|
|
6
|
+
href?: string;
|
|
7
|
+
tone?: Tone;
|
|
8
|
+
/** Leading glyph. */
|
|
9
|
+
icon?: Snippet;
|
|
10
|
+
/** Right-aligned hint — a keyboard shortcut, a count. */
|
|
11
|
+
shortcut?: string;
|
|
12
|
+
/** Shows a check on the left and marks the item as chosen. */
|
|
13
|
+
selected?: boolean;
|
|
14
|
+
children: Snippet;
|
|
15
|
+
}
|
|
16
|
+
declare const MenuItem: import("svelte").Component<Props, {}, "">;
|
|
17
|
+
type MenuItem = ReturnType<typeof MenuItem>;
|
|
18
|
+
export default MenuItem;
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
import type { HTMLAttributes } from 'svelte/elements';
|
|
3
|
+
|
|
4
|
+
interface Props extends HTMLAttributes<HTMLDivElement> {
|
|
5
|
+
/** Optional caption, rendered as a section heading above the rule. */
|
|
6
|
+
label?: string;
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
let { label, class: className = '', ...rest }: Props = $props();
|
|
10
|
+
</script>
|
|
11
|
+
|
|
12
|
+
{#if label}
|
|
13
|
+
<div
|
|
14
|
+
class="mt-1 px-3 pt-2 pb-1 font-sans text-[11px] font-semibold text-text-muted {className}"
|
|
15
|
+
role="presentation"
|
|
16
|
+
{...rest}
|
|
17
|
+
>
|
|
18
|
+
{label}
|
|
19
|
+
</div>
|
|
20
|
+
{:else}
|
|
21
|
+
<div role="separator" class="my-1 h-px bg-hairline {className}" {...rest}></div>
|
|
22
|
+
{/if}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import type { HTMLAttributes } from 'svelte/elements';
|
|
2
|
+
interface Props extends HTMLAttributes<HTMLDivElement> {
|
|
3
|
+
/** Optional caption, rendered as a section heading above the rule. */
|
|
4
|
+
label?: string;
|
|
5
|
+
}
|
|
6
|
+
declare const MenuSeparator: import("svelte").Component<Props, {}, "">;
|
|
7
|
+
type MenuSeparator = ReturnType<typeof MenuSeparator>;
|
|
8
|
+
export default MenuSeparator;
|