bref-ui 0.2.4 → 0.2.6
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 +1 -0
- package/dist/base/index.d.ts +2 -0
- package/dist/base/index.js +2 -0
- package/dist/base/pill/index.d.ts +1 -0
- package/dist/base/pill/index.js +1 -0
- package/dist/base/pill/pill.svelte +146 -0
- package/dist/base/pill/pill.svelte.d.ts +4 -0
- package/dist/base/pill/types.d.ts +9 -0
- package/dist/base/pill/types.js +1 -0
- package/dist/base/progress-bar/progress-bar.svelte +4 -2
- package/dist/base/select/index.d.ts +2 -0
- package/dist/base/select/index.js +2 -0
- package/dist/base/select/select.svelte +148 -0
- package/dist/base/select/select.svelte.d.ts +6 -0
- package/dist/base/select/types.d.ts +14 -0
- package/dist/base/select/types.js +1 -0
- package/package.json +1 -1
- package/dist/internal/layout/code-snippet.svelte +0 -71
- package/dist/internal/layout/code-snippet.svelte.d.ts +0 -6
- package/dist/internal/layout/header.svelte +0 -50
- package/dist/internal/layout/header.svelte.d.ts +0 -3
- package/dist/internal/layout/section.svelte +0 -43
- package/dist/internal/layout/section.svelte.d.ts +0 -10
- package/dist/internal/layout/sidebar/footer.svelte +0 -71
- package/dist/internal/layout/sidebar/footer.svelte.d.ts +0 -3
- package/dist/internal/layout/sidebar/logo.svelte +0 -42
- package/dist/internal/layout/sidebar/logo.svelte.d.ts +0 -18
- package/dist/internal/layout/sidebar/sidebar.svelte +0 -59
- package/dist/internal/layout/sidebar/sidebar.svelte.d.ts +0 -3
- package/dist/internal/layout/types.d.ts +0 -9
- package/dist/internal/layout/types.js +0 -116
- package/dist/internal/navigate.d.ts +0 -2
- package/dist/internal/navigate.js +0 -4
package/README.md
CHANGED
package/dist/base/index.d.ts
CHANGED
package/dist/base/index.js
CHANGED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { default as Pill } from './pill.svelte';
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { default as Pill } from './pill.svelte';
|
|
@@ -0,0 +1,146 @@
|
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
import type { SvelteHTMLElements } from 'svelte/elements';
|
|
3
|
+
import type { PillProps } from './types.js';
|
|
4
|
+
import Icon from '../icon/icon.svelte';
|
|
5
|
+
|
|
6
|
+
const {
|
|
7
|
+
label,
|
|
8
|
+
size = 'medium',
|
|
9
|
+
color = 'primary',
|
|
10
|
+
variant = 'filled',
|
|
11
|
+
icon
|
|
12
|
+
}: PillProps = $props();
|
|
13
|
+
</script>
|
|
14
|
+
|
|
15
|
+
<div class={`${size} ${color} ${variant}`}>
|
|
16
|
+
{#if icon}
|
|
17
|
+
<Icon contrastMode={variant === 'filled'} {color} {...icon} {size} />
|
|
18
|
+
{/if}
|
|
19
|
+
<span>{label}</span>
|
|
20
|
+
</div>
|
|
21
|
+
|
|
22
|
+
<style>
|
|
23
|
+
div {
|
|
24
|
+
/* Size defaults (medium) */
|
|
25
|
+
--internal-pill-padding-y: calc(var(--spacing) * 0.375);
|
|
26
|
+
--internal-pill-padding-x: calc(var(--spacing) * 0.75);
|
|
27
|
+
--internal-pill-font-size: 1rem;
|
|
28
|
+
|
|
29
|
+
display: inline-flex;
|
|
30
|
+
align-items: center;
|
|
31
|
+
justify-content: center;
|
|
32
|
+
border: none;
|
|
33
|
+
flex-shrink: 0;
|
|
34
|
+
width: fit-content;
|
|
35
|
+
min-width: fit-content;
|
|
36
|
+
height: fit-content;
|
|
37
|
+
min-height: fit-content;
|
|
38
|
+
gap: 0.35em;
|
|
39
|
+
padding: var(--internal-pill-padding-y) var(--internal-pill-padding-x);
|
|
40
|
+
font-size: var(--internal-pill-font-size);
|
|
41
|
+
border-radius: 4rem;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
span {
|
|
45
|
+
white-space: nowrap;
|
|
46
|
+
color: inherit;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
/* Sizes - compact padding that scales proportionally */
|
|
50
|
+
.x-small {
|
|
51
|
+
--internal-pill-padding-y: calc(var(--spacing) * 0.125);
|
|
52
|
+
--internal-pill-padding-x: calc(var(--spacing) * 0.375);
|
|
53
|
+
--internal-pill-font-size: 0.75rem;
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
.small {
|
|
57
|
+
--internal-pill-padding-y: calc(var(--spacing) * 0.25);
|
|
58
|
+
--internal-pill-padding-x: calc(var(--spacing) * 0.5);
|
|
59
|
+
--internal-pill-font-size: 0.875rem;
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
.medium {
|
|
63
|
+
--internal-pill-padding-y: calc(var(--spacing) * 0.375);
|
|
64
|
+
--internal-pill-padding-x: calc(var(--spacing) * 0.75);
|
|
65
|
+
--internal-pill-font-size: 1rem;
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
.large {
|
|
69
|
+
--internal-pill-padding-y: calc(var(--spacing) * 0.5);
|
|
70
|
+
--internal-pill-padding-x: calc(var(--spacing) * 1);
|
|
71
|
+
--internal-pill-font-size: 1.125rem;
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
.x-large {
|
|
75
|
+
--internal-pill-padding-y: calc(var(--spacing) * 0.625);
|
|
76
|
+
--internal-pill-padding-x: calc(var(--spacing) * 1.25);
|
|
77
|
+
--internal-pill-font-size: 1.25rem;
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
/* Color mappings - set current color variables per color class */
|
|
81
|
+
.primary {
|
|
82
|
+
--internal-current-color: var(--color-primary);
|
|
83
|
+
--internal-current-color-soft: var(--color-primary-soft);
|
|
84
|
+
--internal-current-contrast: var(--color-primary-contrast);
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
.secondary {
|
|
88
|
+
--internal-current-color: var(--color-secondary);
|
|
89
|
+
--internal-current-color-soft: var(--color-secondary-soft);
|
|
90
|
+
--internal-current-contrast: var(--color-secondary-contrast);
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
.success {
|
|
94
|
+
--internal-current-color: var(--color-success);
|
|
95
|
+
--internal-current-color-soft: var(--color-success-soft);
|
|
96
|
+
--internal-current-contrast: var(--color-success-contrast);
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
.warning {
|
|
100
|
+
--internal-current-color: var(--color-warning);
|
|
101
|
+
--internal-current-color-soft: var(--color-warning-soft);
|
|
102
|
+
--internal-current-contrast: var(--color-warning-contrast);
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
.danger {
|
|
106
|
+
--internal-current-color: var(--color-danger);
|
|
107
|
+
--internal-current-color-soft: var(--color-danger-soft);
|
|
108
|
+
--internal-current-contrast: var(--color-danger-contrast);
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
.info {
|
|
112
|
+
--internal-current-color: var(--color-info);
|
|
113
|
+
--internal-current-color-soft: var(--color-info-soft);
|
|
114
|
+
--internal-current-contrast: var(--color-info-contrast);
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
.foreground {
|
|
118
|
+
--internal-current-color: var(--color-foreground);
|
|
119
|
+
--internal-current-color-soft: var(--color-background-saturated);
|
|
120
|
+
--internal-current-contrast: var(--color-background);
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
.background {
|
|
124
|
+
--internal-current-color: var(--color-background);
|
|
125
|
+
--internal-current-color-soft: var(--color-foreground-saturated);
|
|
126
|
+
--internal-current-contrast: var(--color-foreground);
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
/* Filled variant */
|
|
130
|
+
.filled {
|
|
131
|
+
background-color: var(--internal-current-color);
|
|
132
|
+
color: var(--internal-current-contrast);
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
/* Soft variant */
|
|
136
|
+
.soft {
|
|
137
|
+
background-color: var(--internal-current-color-soft);
|
|
138
|
+
color: var(--internal-current-color);
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
/* Ghost variant */
|
|
142
|
+
.ghost {
|
|
143
|
+
background-color: transparent;
|
|
144
|
+
color: var(--internal-current-color);
|
|
145
|
+
}
|
|
146
|
+
</style>
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import type { IconProps } from '../icon/types.ts';
|
|
2
|
+
import type { Color, Size, Variant } from '../types.ts';
|
|
3
|
+
export interface PillProps {
|
|
4
|
+
label: string;
|
|
5
|
+
size?: Size;
|
|
6
|
+
color?: Color;
|
|
7
|
+
variant?: Variant;
|
|
8
|
+
icon?: Pick<IconProps, 'name' | 'filled' | 'ariaLabel'>;
|
|
9
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -28,7 +28,6 @@
|
|
|
28
28
|
|
|
29
29
|
<!-- svelte-ignore a11y_no_noninteractive_element_interactions -->
|
|
30
30
|
<!-- svelte-ignore a11y_click_events_have_key_events -->
|
|
31
|
-
<!-- aria-valuenow={isIndeterminate ? undefined : clampedValue} -->
|
|
32
31
|
<div
|
|
33
32
|
class={`${size} ${color}`}
|
|
34
33
|
class:wide
|
|
@@ -38,6 +37,7 @@
|
|
|
38
37
|
role="progressbar"
|
|
39
38
|
aria-valuemin={0}
|
|
40
39
|
aria-valuemax={100}
|
|
40
|
+
aria-valuetext={isIndeterminate ? 'Loading' : `${value}%`}
|
|
41
41
|
onclick={isClickable ? handleClick : undefined}
|
|
42
42
|
>
|
|
43
43
|
<span class:indeterminate={isIndeterminate} style:width={progressWidth}></span>
|
|
@@ -50,7 +50,9 @@
|
|
|
50
50
|
|
|
51
51
|
position: relative;
|
|
52
52
|
display: flex;
|
|
53
|
-
width:
|
|
53
|
+
min-width: 4rem;
|
|
54
|
+
width: 8rem;
|
|
55
|
+
max-width: 100%;
|
|
54
56
|
height: var(--internal-progress-height);
|
|
55
57
|
background-color: var(--internal-current-color-soft);
|
|
56
58
|
border-radius: var(--internal-progress-radius);
|
|
@@ -0,0 +1,148 @@
|
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
import Icon from '../icon/icon.svelte';
|
|
3
|
+
import type { SvelteHTMLElements } from 'svelte/elements';
|
|
4
|
+
import type { SelectProps } from './types.js';
|
|
5
|
+
|
|
6
|
+
const {
|
|
7
|
+
value,
|
|
8
|
+
options,
|
|
9
|
+
placeholder = 'Select...',
|
|
10
|
+
disabled = false,
|
|
11
|
+
onChange,
|
|
12
|
+
wide = false,
|
|
13
|
+
...rest
|
|
14
|
+
}: SelectProps & Omit<SvelteHTMLElements['select'], 'value'> = $props();
|
|
15
|
+
|
|
16
|
+
const handleChange = (e: Event) => {
|
|
17
|
+
const newValue = (e.currentTarget as HTMLSelectElement).value;
|
|
18
|
+
onChange(newValue);
|
|
19
|
+
};
|
|
20
|
+
|
|
21
|
+
const selectedOption = $derived(options.find((opt) => opt.value === value));
|
|
22
|
+
</script>
|
|
23
|
+
|
|
24
|
+
<div class="select-container" class:wide>
|
|
25
|
+
<div class="select-wrapper" class:wide class:disabled>
|
|
26
|
+
{#if selectedOption?.icon}
|
|
27
|
+
<Icon name={selectedOption.icon} size="small" />
|
|
28
|
+
{/if}
|
|
29
|
+
<select {...rest} {disabled} {value} onchange={handleChange}>
|
|
30
|
+
{#if placeholder && !value}
|
|
31
|
+
<option value="" disabled selected>{placeholder}</option>
|
|
32
|
+
{/if}
|
|
33
|
+
{#each options as option}
|
|
34
|
+
<option value={option.value}>
|
|
35
|
+
{option.label}
|
|
36
|
+
</option>
|
|
37
|
+
{/each}
|
|
38
|
+
</select>
|
|
39
|
+
<Icon name="keyboard_arrow_down" size="small" />
|
|
40
|
+
</div>
|
|
41
|
+
</div>
|
|
42
|
+
|
|
43
|
+
<style>
|
|
44
|
+
.select-container {
|
|
45
|
+
display: inline-flex;
|
|
46
|
+
flex-direction: column;
|
|
47
|
+
gap: 0.25rem;
|
|
48
|
+
margin: 3px;
|
|
49
|
+
flex-shrink: 0;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
.select-container.wide {
|
|
53
|
+
width: 100%;
|
|
54
|
+
flex-shrink: 1;
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
.select-wrapper {
|
|
58
|
+
--internal-select-bg-opacity: 5%;
|
|
59
|
+
--internal-select-hover-opacity: 7%;
|
|
60
|
+
--internal-select-disabled-opacity: 0.5;
|
|
61
|
+
--internal-select-padding-y: calc(var(--spacing) * 0.5);
|
|
62
|
+
--internal-select-padding-x: calc(var(--spacing) * 0.75);
|
|
63
|
+
--internal-select-radius: calc(var(--border-radius) * 1);
|
|
64
|
+
|
|
65
|
+
display: inline-flex;
|
|
66
|
+
align-items: center;
|
|
67
|
+
gap: 0.5rem;
|
|
68
|
+
padding: var(--internal-select-padding-y) var(--internal-select-padding-x);
|
|
69
|
+
border-radius: var(--internal-select-radius);
|
|
70
|
+
background-color: color-mix(
|
|
71
|
+
in srgb,
|
|
72
|
+
var(--color-foreground) var(--internal-select-bg-opacity),
|
|
73
|
+
transparent
|
|
74
|
+
);
|
|
75
|
+
transition:
|
|
76
|
+
background-color 0.15s ease,
|
|
77
|
+
outline-color 0.15s ease;
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
.select-wrapper:hover:not(.disabled) {
|
|
81
|
+
background-color: color-mix(
|
|
82
|
+
in srgb,
|
|
83
|
+
var(--color-foreground) var(--internal-select-hover-opacity),
|
|
84
|
+
transparent
|
|
85
|
+
);
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
.select-wrapper:focus-within {
|
|
89
|
+
outline: 2px solid var(--color-primary);
|
|
90
|
+
outline-offset: 1px;
|
|
91
|
+
background-color: color-mix(
|
|
92
|
+
in srgb,
|
|
93
|
+
var(--color-foreground) var(--internal-select-hover-opacity),
|
|
94
|
+
transparent
|
|
95
|
+
);
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
.select-wrapper.wide {
|
|
99
|
+
width: 100%;
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
.disabled {
|
|
103
|
+
opacity: var(--internal-select-disabled-opacity);
|
|
104
|
+
cursor: not-allowed;
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
.disabled select {
|
|
108
|
+
cursor: not-allowed;
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
select {
|
|
112
|
+
flex: 1;
|
|
113
|
+
border: none;
|
|
114
|
+
background: transparent;
|
|
115
|
+
color: var(--color-foreground);
|
|
116
|
+
font-size: 1rem;
|
|
117
|
+
outline: none;
|
|
118
|
+
min-width: 0;
|
|
119
|
+
cursor: pointer;
|
|
120
|
+
appearance: base-select;
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
select::picker(select) {
|
|
124
|
+
appearance: base-select;
|
|
125
|
+
border: none;
|
|
126
|
+
border-radius: var(--internal-select-radius);
|
|
127
|
+
background-color: var(--color-background);
|
|
128
|
+
box-shadow: 0 4px 16px color-mix(in srgb, var(--color-foreground) 15%, transparent);
|
|
129
|
+
padding: calc(var(--spacing) * 0.5);
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
select option {
|
|
133
|
+
padding: calc(var(--spacing) * 0.5) calc(var(--spacing) * 0.75);
|
|
134
|
+
border-radius: calc(var(--border-radius) * 0.5);
|
|
135
|
+
background-color: transparent;
|
|
136
|
+
color: var(--color-foreground);
|
|
137
|
+
cursor: pointer;
|
|
138
|
+
transition: background-color 0.1s ease;
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
select option:hover {
|
|
142
|
+
background-color: color-mix(in srgb, var(--color-foreground) 5%, transparent);
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
select option:checked {
|
|
146
|
+
background-color: color-mix(in srgb, var(--color-primary) 15%, transparent);
|
|
147
|
+
}
|
|
148
|
+
</style>
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import type { SvelteHTMLElements } from 'svelte/elements';
|
|
2
|
+
import type { SelectProps } from './types.ts';
|
|
3
|
+
type $$ComponentProps = SelectProps & Omit<SvelteHTMLElements['select'], 'value'>;
|
|
4
|
+
declare const Select: import("svelte").Component<$$ComponentProps, {}, "">;
|
|
5
|
+
type Select = ReturnType<typeof Select>;
|
|
6
|
+
export default Select;
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import type { IconName } from '../icon/types.ts';
|
|
2
|
+
export interface SelectOptionProps {
|
|
3
|
+
value: string;
|
|
4
|
+
label: string;
|
|
5
|
+
icon?: IconName;
|
|
6
|
+
}
|
|
7
|
+
export interface SelectProps {
|
|
8
|
+
value: string;
|
|
9
|
+
options: SelectOptionProps[];
|
|
10
|
+
placeholder?: string;
|
|
11
|
+
disabled?: boolean;
|
|
12
|
+
onChange: (value: string) => void;
|
|
13
|
+
wide?: boolean;
|
|
14
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
package/package.json
CHANGED
|
@@ -1,71 +0,0 @@
|
|
|
1
|
-
<script lang="ts">
|
|
2
|
-
import IconButton from '../../base/button/icon-button.svelte';
|
|
3
|
-
|
|
4
|
-
const {
|
|
5
|
-
snippet
|
|
6
|
-
}: {
|
|
7
|
-
snippet: string;
|
|
8
|
-
} = $props();
|
|
9
|
-
|
|
10
|
-
let hasCopied = $state(false);
|
|
11
|
-
|
|
12
|
-
const onClick = () => {
|
|
13
|
-
navigator.clipboard.writeText(snippet).then(() => {
|
|
14
|
-
hasCopied = true;
|
|
15
|
-
setTimeout(() => (hasCopied = false), 3000);
|
|
16
|
-
});
|
|
17
|
-
};
|
|
18
|
-
</script>
|
|
19
|
-
|
|
20
|
-
<div>
|
|
21
|
-
<pre>
|
|
22
|
-
<code>{snippet}</code>
|
|
23
|
-
</pre>
|
|
24
|
-
|
|
25
|
-
<IconButton
|
|
26
|
-
{onClick}
|
|
27
|
-
size="x-small"
|
|
28
|
-
color={hasCopied ? 'success' : 'foreground'}
|
|
29
|
-
variant={hasCopied ? 'filled' : 'ghost'}
|
|
30
|
-
rounded
|
|
31
|
-
name={hasCopied ? 'check' : 'copy_all'}
|
|
32
|
-
disabled={hasCopied}
|
|
33
|
-
/>
|
|
34
|
-
</div>
|
|
35
|
-
|
|
36
|
-
<style>
|
|
37
|
-
div {
|
|
38
|
-
display: flex;
|
|
39
|
-
width: 100%;
|
|
40
|
-
position: relative;
|
|
41
|
-
height: fit-content;
|
|
42
|
-
padding: 1rem;
|
|
43
|
-
gap: 0.5rem;
|
|
44
|
-
border-radius: 0.75rem;
|
|
45
|
-
background: color-mix(in srgb, var(--color-foreground) 5%, transparent);
|
|
46
|
-
border: 1px solid color-mix(in srgb, var(--color-border) 30%, transparent);
|
|
47
|
-
backdrop-filter: blur(8px);
|
|
48
|
-
}
|
|
49
|
-
code {
|
|
50
|
-
white-space: pre-wrap;
|
|
51
|
-
word-break: break-word;
|
|
52
|
-
flex-grow: 1;
|
|
53
|
-
font-family: monospace;
|
|
54
|
-
font-weight: 400;
|
|
55
|
-
text-align: left;
|
|
56
|
-
opacity: 60%;
|
|
57
|
-
font-size: small;
|
|
58
|
-
}
|
|
59
|
-
code,
|
|
60
|
-
pre {
|
|
61
|
-
width: 100%;
|
|
62
|
-
flex: 1;
|
|
63
|
-
align-self: center;
|
|
64
|
-
height: fit-content;
|
|
65
|
-
}
|
|
66
|
-
pre {
|
|
67
|
-
align-items: flex-start;
|
|
68
|
-
display: flex;
|
|
69
|
-
justify-content: flex-start;
|
|
70
|
-
}
|
|
71
|
-
</style>
|
|
@@ -1,50 +0,0 @@
|
|
|
1
|
-
<script lang="ts">
|
|
2
|
-
import Icon from '../../base/icon/icon.svelte';
|
|
3
|
-
import { PAGES, type PageProps } from '../layout/types.js';
|
|
4
|
-
import { page } from '$app/state';
|
|
5
|
-
|
|
6
|
-
const { title, description, icon } = $derived.by((): PageProps => {
|
|
7
|
-
if (page.status !== 200) {
|
|
8
|
-
return {
|
|
9
|
-
title: 'Error: ' + page.status,
|
|
10
|
-
description: page.error?.message || 'An unexpected error occurred.',
|
|
11
|
-
icon: 'error',
|
|
12
|
-
href: ''
|
|
13
|
-
};
|
|
14
|
-
}
|
|
15
|
-
const firstPage = PAGES[0];
|
|
16
|
-
const allPages = PAGES.flatMap((p) => [p, ...(p.children || [])]);
|
|
17
|
-
const currentPage = allPages.find((p) => page.url.pathname.endsWith(p.href));
|
|
18
|
-
return currentPage || firstPage;
|
|
19
|
-
});
|
|
20
|
-
</script>
|
|
21
|
-
|
|
22
|
-
<div class="container">
|
|
23
|
-
<div>
|
|
24
|
-
<Icon name={icon} size="large" color="primary" />
|
|
25
|
-
<h1>{title}</h1>
|
|
26
|
-
</div>
|
|
27
|
-
<p>{description}</p>
|
|
28
|
-
</div>
|
|
29
|
-
|
|
30
|
-
<style>
|
|
31
|
-
div {
|
|
32
|
-
display: flex;
|
|
33
|
-
align-items: center;
|
|
34
|
-
min-height: fit-content;
|
|
35
|
-
height: fit-content;
|
|
36
|
-
}
|
|
37
|
-
.container {
|
|
38
|
-
width: 100%;
|
|
39
|
-
padding: 2rem;
|
|
40
|
-
flex-direction: column;
|
|
41
|
-
align-items: flex-start;
|
|
42
|
-
flex-shrink: 0;
|
|
43
|
-
}
|
|
44
|
-
p {
|
|
45
|
-
opacity: 0.8;
|
|
46
|
-
}
|
|
47
|
-
h1 {
|
|
48
|
-
font-size: 3rem;
|
|
49
|
-
}
|
|
50
|
-
</style>
|
|
@@ -1,43 +0,0 @@
|
|
|
1
|
-
<script lang="ts">
|
|
2
|
-
import type { Snippet } from 'svelte';
|
|
3
|
-
|
|
4
|
-
let {
|
|
5
|
-
children,
|
|
6
|
-
title,
|
|
7
|
-
description,
|
|
8
|
-
id
|
|
9
|
-
}: {
|
|
10
|
-
children: Snippet;
|
|
11
|
-
title?: string;
|
|
12
|
-
description?: string;
|
|
13
|
-
id?: string;
|
|
14
|
-
} = $props();
|
|
15
|
-
</script>
|
|
16
|
-
|
|
17
|
-
<section {id} class="container">
|
|
18
|
-
{#if title}
|
|
19
|
-
<h2>{title}</h2>
|
|
20
|
-
{/if}
|
|
21
|
-
{#if description}
|
|
22
|
-
<p>{description}</p>
|
|
23
|
-
{/if}
|
|
24
|
-
{@render children()}
|
|
25
|
-
</section>
|
|
26
|
-
|
|
27
|
-
<style>
|
|
28
|
-
section {
|
|
29
|
-
display: flex;
|
|
30
|
-
gap: 1rem;
|
|
31
|
-
align-items: center;
|
|
32
|
-
flex-direction: column;
|
|
33
|
-
padding: 2rem;
|
|
34
|
-
width: 100%;
|
|
35
|
-
flex-shrink: 0;
|
|
36
|
-
}
|
|
37
|
-
h2 {
|
|
38
|
-
font-size: 2rem;
|
|
39
|
-
}
|
|
40
|
-
p {
|
|
41
|
-
font-size: 1.1rem;
|
|
42
|
-
}
|
|
43
|
-
</style>
|
|
@@ -1,10 +0,0 @@
|
|
|
1
|
-
import type { Snippet } from 'svelte';
|
|
2
|
-
type $$ComponentProps = {
|
|
3
|
-
children: Snippet;
|
|
4
|
-
title?: string;
|
|
5
|
-
description?: string;
|
|
6
|
-
id?: string;
|
|
7
|
-
};
|
|
8
|
-
declare const Section: import("svelte").Component<$$ComponentProps, {}, "">;
|
|
9
|
-
type Section = ReturnType<typeof Section>;
|
|
10
|
-
export default Section;
|
|
@@ -1,71 +0,0 @@
|
|
|
1
|
-
<script lang="ts">
|
|
2
|
-
import IconButton from '../../../base/button/icon-button.svelte';
|
|
3
|
-
import {
|
|
4
|
-
type ThemeMode,
|
|
5
|
-
initializeThemeMode,
|
|
6
|
-
toggleThemeMode
|
|
7
|
-
} from '../../../base/theme/index.js';
|
|
8
|
-
import { untrack } from 'svelte';
|
|
9
|
-
import Icon from '../../../base/icon/icon.svelte';
|
|
10
|
-
|
|
11
|
-
let themeMode: ThemeMode = $state('light');
|
|
12
|
-
|
|
13
|
-
$effect.pre(() => {
|
|
14
|
-
untrack(() => {
|
|
15
|
-
themeMode = initializeThemeMode();
|
|
16
|
-
});
|
|
17
|
-
});
|
|
18
|
-
|
|
19
|
-
const onClick = () => {
|
|
20
|
-
const newMode = themeMode === 'dark' ? 'light' : 'dark';
|
|
21
|
-
toggleThemeMode(newMode);
|
|
22
|
-
themeMode = newMode;
|
|
23
|
-
};
|
|
24
|
-
</script>
|
|
25
|
-
|
|
26
|
-
<div>
|
|
27
|
-
<IconButton
|
|
28
|
-
variant="ghost"
|
|
29
|
-
name={themeMode === 'dark' ? 'light_mode' : 'dark_mode'}
|
|
30
|
-
ariaLabel="Toggle theme"
|
|
31
|
-
{onClick}
|
|
32
|
-
/>
|
|
33
|
-
<span>
|
|
34
|
-
Made with <Icon name="favorite" color="danger" filled size="x-small" /> in Paris, by
|
|
35
|
-
<a href="https://github.com/feuersteiner" target="_blank" rel="noopener noreferrer"
|
|
36
|
-
>Feuerstein.</a
|
|
37
|
-
>
|
|
38
|
-
</span>
|
|
39
|
-
</div>
|
|
40
|
-
|
|
41
|
-
<style>
|
|
42
|
-
div {
|
|
43
|
-
display: flex;
|
|
44
|
-
justify-content: center;
|
|
45
|
-
align-items: center;
|
|
46
|
-
width: 100%;
|
|
47
|
-
height: fit-content;
|
|
48
|
-
flex-direction: column;
|
|
49
|
-
gap: 0.5rem;
|
|
50
|
-
padding: 1rem;
|
|
51
|
-
}
|
|
52
|
-
|
|
53
|
-
a {
|
|
54
|
-
text-decoration: none;
|
|
55
|
-
color: inherit;
|
|
56
|
-
display: inline-block;
|
|
57
|
-
width: 5rem;
|
|
58
|
-
height: 1.5rem;
|
|
59
|
-
}
|
|
60
|
-
|
|
61
|
-
a:hover {
|
|
62
|
-
font-weight: bold;
|
|
63
|
-
}
|
|
64
|
-
|
|
65
|
-
span {
|
|
66
|
-
font-size: 0.75rem;
|
|
67
|
-
text-align: center;
|
|
68
|
-
align-items: center;
|
|
69
|
-
color: color-mix(in srgb, var(--color-foreground) 50%, var(--color-background));
|
|
70
|
-
}
|
|
71
|
-
</style>
|
|
@@ -1,42 +0,0 @@
|
|
|
1
|
-
<script lang="ts">
|
|
2
|
-
import { asset } from '$app/paths';
|
|
3
|
-
</script>
|
|
4
|
-
|
|
5
|
-
<div class="logo">
|
|
6
|
-
<div class="icon">
|
|
7
|
-
<img src={asset('/favicon.svg')} alt="Logo" />
|
|
8
|
-
<span>Bref</span>
|
|
9
|
-
</div>
|
|
10
|
-
|
|
11
|
-
<p>A truly Svelte-esque UI Component Library.</p>
|
|
12
|
-
</div>
|
|
13
|
-
|
|
14
|
-
<style>
|
|
15
|
-
div {
|
|
16
|
-
display: flex;
|
|
17
|
-
gap: 1rem;
|
|
18
|
-
}
|
|
19
|
-
.icon {
|
|
20
|
-
align-items: center;
|
|
21
|
-
}
|
|
22
|
-
.logo {
|
|
23
|
-
padding: 1rem;
|
|
24
|
-
flex-direction: column;
|
|
25
|
-
width: 100%;
|
|
26
|
-
height: fit-content;
|
|
27
|
-
background-color: color-mix(in srgb, var(--color-foreground) 5%, transparent);
|
|
28
|
-
}
|
|
29
|
-
span {
|
|
30
|
-
font-size: 2rem;
|
|
31
|
-
font-family: 'Meow Script', cursive;
|
|
32
|
-
}
|
|
33
|
-
p {
|
|
34
|
-
font-size: 0.75rem;
|
|
35
|
-
opacity: 0.7;
|
|
36
|
-
font-weight: 300;
|
|
37
|
-
}
|
|
38
|
-
img {
|
|
39
|
-
width: 3rem;
|
|
40
|
-
height: 3rem;
|
|
41
|
-
}
|
|
42
|
-
</style>
|
|
@@ -1,18 +0,0 @@
|
|
|
1
|
-
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> {
|
|
2
|
-
new (options: import('svelte').ComponentConstructorOptions<Props>): import('svelte').SvelteComponent<Props, Events, Slots> & {
|
|
3
|
-
$$bindings?: Bindings;
|
|
4
|
-
} & Exports;
|
|
5
|
-
(internal: unknown, props: {
|
|
6
|
-
$$events?: Events;
|
|
7
|
-
$$slots?: Slots;
|
|
8
|
-
}): Exports & {
|
|
9
|
-
$set?: any;
|
|
10
|
-
$on?: any;
|
|
11
|
-
};
|
|
12
|
-
z_$$bindings?: Bindings;
|
|
13
|
-
}
|
|
14
|
-
declare const Logo: $$__sveltets_2_IsomorphicComponent<Record<string, never>, {
|
|
15
|
-
[evt: string]: CustomEvent<any>;
|
|
16
|
-
}, {}, {}, string>;
|
|
17
|
-
type Logo = InstanceType<typeof Logo>;
|
|
18
|
-
export default Logo;
|
|
@@ -1,59 +0,0 @@
|
|
|
1
|
-
<script lang="ts">
|
|
2
|
-
import Logo from './logo.svelte';
|
|
3
|
-
import Footer from './footer.svelte';
|
|
4
|
-
import { PAGES, type PageProps } from '../types.js';
|
|
5
|
-
import { page } from '$app/state';
|
|
6
|
-
import TreeView from '../../../base/tree-view/tree-view.svelte';
|
|
7
|
-
import type { NodeDataProps } from '../../../index.js';
|
|
8
|
-
import navigateTo from '../../../internal/navigate.js';
|
|
9
|
-
|
|
10
|
-
const pageToNode = (page: PageProps): NodeDataProps => ({
|
|
11
|
-
id: page.href,
|
|
12
|
-
label: page.title,
|
|
13
|
-
icon: page.icon,
|
|
14
|
-
children: page.children?.map(pageToNode)
|
|
15
|
-
});
|
|
16
|
-
const selectedPage = $derived.by(() => {
|
|
17
|
-
const allPages = PAGES.flatMap((p) => [p, ...(p.children || [])]);
|
|
18
|
-
return allPages.find((p) => page.url.pathname.endsWith(p.href)) ?? PAGES[0];
|
|
19
|
-
});
|
|
20
|
-
const selectedIds = $derived(new Set([selectedPage.href]));
|
|
21
|
-
const onSelect = (href: string) => navigateTo(href);
|
|
22
|
-
</script>
|
|
23
|
-
|
|
24
|
-
<div class="container">
|
|
25
|
-
<Logo />
|
|
26
|
-
<div class="content">
|
|
27
|
-
<TreeView
|
|
28
|
-
wide
|
|
29
|
-
size="small"
|
|
30
|
-
{selectedIds}
|
|
31
|
-
{onSelect}
|
|
32
|
-
data={PAGES.map(pageToNode)}
|
|
33
|
-
expandOnSelect
|
|
34
|
-
/>
|
|
35
|
-
</div>
|
|
36
|
-
<Footer />
|
|
37
|
-
</div>
|
|
38
|
-
|
|
39
|
-
<style>
|
|
40
|
-
div {
|
|
41
|
-
display: flex;
|
|
42
|
-
justify-content: center;
|
|
43
|
-
align-items: center;
|
|
44
|
-
height: 100%;
|
|
45
|
-
width: 100%;
|
|
46
|
-
}
|
|
47
|
-
.container {
|
|
48
|
-
max-width: 15rem;
|
|
49
|
-
width: 15rem;
|
|
50
|
-
/* height: 100%; */
|
|
51
|
-
}
|
|
52
|
-
.content {
|
|
53
|
-
flex: 1;
|
|
54
|
-
width: 100%;
|
|
55
|
-
justify-content: flex-start;
|
|
56
|
-
align-items: flex-start;
|
|
57
|
-
padding: 1rem;
|
|
58
|
-
}
|
|
59
|
-
</style>
|
|
@@ -1,116 +0,0 @@
|
|
|
1
|
-
export const PAGES = [
|
|
2
|
-
{
|
|
3
|
-
title: 'Getting Started',
|
|
4
|
-
description: 'Installation and setup guide',
|
|
5
|
-
href: '/',
|
|
6
|
-
icon: 'rocket_launch'
|
|
7
|
-
},
|
|
8
|
-
{
|
|
9
|
-
title: 'Theming',
|
|
10
|
-
description: "Bref's theming system uses CSS custom properties for complete flexibility",
|
|
11
|
-
href: '/theming',
|
|
12
|
-
icon: 'palette'
|
|
13
|
-
},
|
|
14
|
-
{
|
|
15
|
-
title: 'Generic Types',
|
|
16
|
-
description: 'Shared TypeScript types used across components for consistent styling and behavior',
|
|
17
|
-
href: '/types',
|
|
18
|
-
icon: 'data_object'
|
|
19
|
-
},
|
|
20
|
-
{
|
|
21
|
-
title: 'Icon',
|
|
22
|
-
description: 'Icons with customizable size, color, and fill. Based on Google Material Symbols',
|
|
23
|
-
href: '/icon',
|
|
24
|
-
icon: 'emoji_symbols'
|
|
25
|
-
},
|
|
26
|
-
{
|
|
27
|
-
title: 'Buttons',
|
|
28
|
-
description: 'Full-featured buttons with labels and icons, or compact icon-only buttons',
|
|
29
|
-
href: '/buttons',
|
|
30
|
-
icon: 'touch_app',
|
|
31
|
-
children: [
|
|
32
|
-
{
|
|
33
|
-
title: 'Button',
|
|
34
|
-
description: 'Buttons with customizable size, color, variant, and optional icons',
|
|
35
|
-
href: '/buttons/button',
|
|
36
|
-
icon: 'buttons_alt'
|
|
37
|
-
},
|
|
38
|
-
{
|
|
39
|
-
title: 'Icon Button',
|
|
40
|
-
description: 'Icon buttons with customizable size, color, variant, and shape',
|
|
41
|
-
href: '/buttons/icon-button',
|
|
42
|
-
icon: 'adjust'
|
|
43
|
-
}
|
|
44
|
-
]
|
|
45
|
-
},
|
|
46
|
-
{
|
|
47
|
-
title: 'Inputs',
|
|
48
|
-
description: 'Input fields for text, numbers, and selections',
|
|
49
|
-
href: '/inputs',
|
|
50
|
-
icon: 'input',
|
|
51
|
-
children: [
|
|
52
|
-
{
|
|
53
|
-
title: 'Text Input',
|
|
54
|
-
description: 'Single-line text input fields with labels, placeholders, and icons',
|
|
55
|
-
href: '/inputs/text-input',
|
|
56
|
-
icon: 'short_text'
|
|
57
|
-
},
|
|
58
|
-
{
|
|
59
|
-
title: 'Area Text Input',
|
|
60
|
-
description: 'Multi-line text area input fields with labels and placeholders',
|
|
61
|
-
href: '/inputs/area-text-input',
|
|
62
|
-
icon: 'notes'
|
|
63
|
-
},
|
|
64
|
-
{
|
|
65
|
-
title: 'Slider',
|
|
66
|
-
description: 'Range slider for selecting numeric values within a range',
|
|
67
|
-
href: '/inputs/slider',
|
|
68
|
-
icon: 'tune'
|
|
69
|
-
}
|
|
70
|
-
]
|
|
71
|
-
},
|
|
72
|
-
{
|
|
73
|
-
title: 'Progress / Loading',
|
|
74
|
-
description: 'Progress indicators and loading animations',
|
|
75
|
-
href: '/progress',
|
|
76
|
-
icon: 'hourglass_empty',
|
|
77
|
-
children: [
|
|
78
|
-
{
|
|
79
|
-
title: 'Progress Bar',
|
|
80
|
-
description: 'A progress bar with determinate and indeterminate states',
|
|
81
|
-
href: '/progress/progress-bar',
|
|
82
|
-
icon: 'linear_scale'
|
|
83
|
-
},
|
|
84
|
-
{
|
|
85
|
-
title: 'Circular',
|
|
86
|
-
description: 'A classic spinning circle indicator for loading states',
|
|
87
|
-
href: '/progress/circular',
|
|
88
|
-
icon: 'autorenew'
|
|
89
|
-
},
|
|
90
|
-
{
|
|
91
|
-
title: 'Pulsing Dots',
|
|
92
|
-
description: 'Three dots that pulse in sequence to indicate loading',
|
|
93
|
-
href: '/progress/pulsing-dots',
|
|
94
|
-
icon: 'more_horiz'
|
|
95
|
-
},
|
|
96
|
-
{
|
|
97
|
-
title: 'Morphing Shapes',
|
|
98
|
-
description: 'A shape that transforms through organic forms while rotating',
|
|
99
|
-
href: '/progress/morphing-shapes',
|
|
100
|
-
icon: 'animation'
|
|
101
|
-
},
|
|
102
|
-
{
|
|
103
|
-
title: 'Textual',
|
|
104
|
-
description: 'Animated text with a typewriter effect that cycles through words',
|
|
105
|
-
href: '/progress/textual',
|
|
106
|
-
icon: 'text_fields'
|
|
107
|
-
}
|
|
108
|
-
]
|
|
109
|
-
},
|
|
110
|
-
{
|
|
111
|
-
title: 'Tree View',
|
|
112
|
-
description: 'A hierarchical tree component for displaying nested data structures',
|
|
113
|
-
href: '/tree-view',
|
|
114
|
-
icon: 'account_tree'
|
|
115
|
-
}
|
|
116
|
-
];
|