milk-lib 0.0.23 → 0.0.26
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/dist/components/SegmentedControl/SegmentedControl.svelte +200 -0
- package/dist/components/SegmentedControl/SegmentedControl.svelte.d.ts +4 -0
- package/dist/components/SegmentedControl/SegmentedControl.types.d.ts +55 -0
- package/dist/components/SegmentedControl/SegmentedControl.types.js +2 -0
- package/dist/components/SegmentedControl/SegmentedControlItem.svelte +111 -0
- package/dist/components/SegmentedControl/SegmentedControlItem.svelte.d.ts +4 -0
- package/dist/components/SegmentedControl/index.d.ts +8 -0
- package/dist/components/SegmentedControl/index.js +8 -0
- package/dist/components/Sheet/Sheet.svelte +52 -0
- package/dist/components/Sheet/Sheet.svelte.d.ts +4 -0
- package/dist/components/Sheet/Sheet.types.d.ts +23 -0
- package/dist/components/Sheet/Sheet.types.js +1 -0
- package/dist/components/Sheet/SheetActions.svelte +28 -0
- package/dist/components/Sheet/SheetActions.svelte.d.ts +4 -0
- package/dist/components/Sheet/SheetContent.svelte +13 -0
- package/dist/components/Sheet/SheetContent.svelte.d.ts +4 -0
- package/dist/components/Sheet/SheetDescription.svelte +13 -0
- package/dist/components/Sheet/SheetDescription.svelte.d.ts +4 -0
- package/dist/components/Sheet/SheetHeader.svelte +13 -0
- package/dist/components/Sheet/SheetHeader.svelte.d.ts +4 -0
- package/dist/components/Sheet/SheetTitle.svelte +13 -0
- package/dist/components/Sheet/SheetTitle.svelte.d.ts +4 -0
- package/dist/components/Sheet/index.d.ts +6 -0
- package/dist/components/Sheet/index.js +6 -0
- package/dist/components/index.d.ts +2 -0
- package/dist/components/index.js +2 -0
- package/package.json +1 -1
|
@@ -0,0 +1,200 @@
|
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
import { setContext } from 'svelte';
|
|
3
|
+
import { writable } from 'svelte/store';
|
|
4
|
+
import {
|
|
5
|
+
SEGMENTED_CONTROL_CONTEXT,
|
|
6
|
+
type ISegmentedControlContext,
|
|
7
|
+
type ISegmentedControlItemEntry,
|
|
8
|
+
type ISegmentedControlRootProps
|
|
9
|
+
} from './SegmentedControl.types';
|
|
10
|
+
|
|
11
|
+
let {
|
|
12
|
+
value = $bindable(),
|
|
13
|
+
defaultValue,
|
|
14
|
+
orientation = 'horizontal',
|
|
15
|
+
gap = '2px',
|
|
16
|
+
disabled = false,
|
|
17
|
+
classNames = '',
|
|
18
|
+
style,
|
|
19
|
+
dataVariant,
|
|
20
|
+
onValueChange,
|
|
21
|
+
children
|
|
22
|
+
}: ISegmentedControlRootProps = $props();
|
|
23
|
+
|
|
24
|
+
if (value === undefined && defaultValue !== undefined) {
|
|
25
|
+
value = defaultValue;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
const selectedValue = writable<string | null>(value ?? defaultValue ?? null);
|
|
29
|
+
const disabledState = writable<boolean>(disabled);
|
|
30
|
+
let items: ISegmentedControlItemEntry[] = [];
|
|
31
|
+
|
|
32
|
+
function registerItem(entry: ISegmentedControlItemEntry) {
|
|
33
|
+
const index = items.findIndex(item => item.id === entry.id);
|
|
34
|
+
if (index === -1) {
|
|
35
|
+
items = [...items, entry];
|
|
36
|
+
} else {
|
|
37
|
+
items = [
|
|
38
|
+
...items.slice(0, index),
|
|
39
|
+
entry,
|
|
40
|
+
...items.slice(index + 1)
|
|
41
|
+
];
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
function unregisterItem(id: symbol) {
|
|
46
|
+
items = items.filter(item => item.id !== id);
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
function selectValue(newValue: string) {
|
|
50
|
+
if (disabled) return;
|
|
51
|
+
if (value === newValue) return;
|
|
52
|
+
const target = items.find(item => item.value === newValue);
|
|
53
|
+
if (target?.disabled) return;
|
|
54
|
+
value = newValue;
|
|
55
|
+
selectedValue.set(newValue);
|
|
56
|
+
onValueChange?.(newValue);
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
const context: ISegmentedControlContext = {
|
|
60
|
+
orientation,
|
|
61
|
+
disabled: disabledState,
|
|
62
|
+
selectedValue,
|
|
63
|
+
selectValue,
|
|
64
|
+
registerItem,
|
|
65
|
+
unregisterItem
|
|
66
|
+
};
|
|
67
|
+
|
|
68
|
+
setContext(SEGMENTED_CONTROL_CONTEXT, context);
|
|
69
|
+
|
|
70
|
+
$effect(() => {
|
|
71
|
+
context.orientation = orientation;
|
|
72
|
+
});
|
|
73
|
+
|
|
74
|
+
$effect(() => {
|
|
75
|
+
disabledState.set(disabled);
|
|
76
|
+
});
|
|
77
|
+
|
|
78
|
+
$effect(() => {
|
|
79
|
+
selectedValue.set(value ?? defaultValue ?? null);
|
|
80
|
+
});
|
|
81
|
+
|
|
82
|
+
let rootStyle = $state('');
|
|
83
|
+
$effect(() => {
|
|
84
|
+
const normalized = style ? style.trim() : '';
|
|
85
|
+
const normalizedStyle = normalized
|
|
86
|
+
? normalized.endsWith(';')
|
|
87
|
+
? normalized
|
|
88
|
+
: `${normalized};`
|
|
89
|
+
: '';
|
|
90
|
+
rootStyle = `${normalizedStyle} --segmented-control-gap: ${gap};`;
|
|
91
|
+
});
|
|
92
|
+
|
|
93
|
+
function moveFocus(step: number) {
|
|
94
|
+
if (!items.length) return;
|
|
95
|
+
if (!items.some(entry => !entry.disabled)) return;
|
|
96
|
+
|
|
97
|
+
let nextIndex = items.findIndex(entry => entry.value === value);
|
|
98
|
+
if (nextIndex === -1) {
|
|
99
|
+
nextIndex = step > 0 ? -1 : 0;
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
for (let i = 0; i < items.length; i += 1) {
|
|
103
|
+
nextIndex = (nextIndex + step + items.length) % items.length;
|
|
104
|
+
const entry = items[nextIndex];
|
|
105
|
+
if (!entry?.disabled) {
|
|
106
|
+
selectValue(entry.value);
|
|
107
|
+
entry.el?.focus();
|
|
108
|
+
break;
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
function focusEdge(isFirst: boolean) {
|
|
114
|
+
if (!items.length) return;
|
|
115
|
+
const ordered = isFirst ? items : [...items].reverse();
|
|
116
|
+
for (const entry of ordered) {
|
|
117
|
+
if (!entry.disabled) {
|
|
118
|
+
selectValue(entry.value);
|
|
119
|
+
entry.el?.focus();
|
|
120
|
+
break;
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
function handleKeydown(event: KeyboardEvent) {
|
|
126
|
+
if (disabled) return;
|
|
127
|
+
const { key } = event;
|
|
128
|
+
if (orientation === 'horizontal') {
|
|
129
|
+
if (key === 'ArrowRight') {
|
|
130
|
+
event.preventDefault();
|
|
131
|
+
moveFocus(1);
|
|
132
|
+
return;
|
|
133
|
+
}
|
|
134
|
+
if (key === 'ArrowLeft') {
|
|
135
|
+
event.preventDefault();
|
|
136
|
+
moveFocus(-1);
|
|
137
|
+
return;
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
if (orientation === 'vertical') {
|
|
142
|
+
if (key === 'ArrowDown') {
|
|
143
|
+
event.preventDefault();
|
|
144
|
+
moveFocus(1);
|
|
145
|
+
return;
|
|
146
|
+
}
|
|
147
|
+
if (key === 'ArrowUp') {
|
|
148
|
+
event.preventDefault();
|
|
149
|
+
moveFocus(-1);
|
|
150
|
+
return;
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
if (key === 'Home') {
|
|
155
|
+
event.preventDefault();
|
|
156
|
+
focusEdge(true);
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
if (key === 'End') {
|
|
160
|
+
event.preventDefault();
|
|
161
|
+
focusEdge(false);
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
</script>
|
|
165
|
+
|
|
166
|
+
<div
|
|
167
|
+
class={`SegmentedControlRoot ${classNames}`}
|
|
168
|
+
role="group"
|
|
169
|
+
aria-orientation={orientation}
|
|
170
|
+
aria-disabled={disabled}
|
|
171
|
+
data-orientation={orientation}
|
|
172
|
+
style={rootStyle}
|
|
173
|
+
onkeydown={handleKeydown}
|
|
174
|
+
{...(dataVariant ? { 'data-variant': dataVariant } : {})}
|
|
175
|
+
>
|
|
176
|
+
{@render children?.()}
|
|
177
|
+
</div>
|
|
178
|
+
|
|
179
|
+
<style>.SegmentedControlRoot {
|
|
180
|
+
--segmented-control-padding: 2px;
|
|
181
|
+
--segmented-control-radius: var(--border-radius-button, 10px);
|
|
182
|
+
--segmented-control-border: 1px solid var(--line-base);
|
|
183
|
+
display: inline-flex;
|
|
184
|
+
gap: var(--segmented-control-gap, 2px);
|
|
185
|
+
padding: var(--segmented-control-padding);
|
|
186
|
+
border: var(--segmented-control-border);
|
|
187
|
+
border-radius: var(--segmented-control-radius);
|
|
188
|
+
background-color: var(--bg-base);
|
|
189
|
+
align-items: stretch;
|
|
190
|
+
justify-content: flex-start;
|
|
191
|
+
transition: border-color 0.2s ease-in-out, box-shadow 0.2s ease-in-out;
|
|
192
|
+
}
|
|
193
|
+
.SegmentedControlRoot[data-orientation=vertical] {
|
|
194
|
+
flex-direction: column;
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
.SegmentedControlRoot:focus-within {
|
|
198
|
+
border-color: var(--line-base);
|
|
199
|
+
box-shadow: 0 0 0 1px var(--line-base);
|
|
200
|
+
}</style>
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
import { type ISegmentedControlRootProps } from './SegmentedControl.types';
|
|
2
|
+
declare const SegmentedControl: import("svelte").Component<ISegmentedControlRootProps, {}, "value">;
|
|
3
|
+
type SegmentedControl = ReturnType<typeof SegmentedControl>;
|
|
4
|
+
export default SegmentedControl;
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
import type { Snippet } from 'svelte';
|
|
2
|
+
import type { Writable } from 'svelte/store';
|
|
3
|
+
/** Shared context key so items can find the current root instance. */
|
|
4
|
+
export declare const SEGMENTED_CONTROL_CONTEXT: unique symbol;
|
|
5
|
+
export type SegmentedControlOrientation = 'horizontal' | 'vertical';
|
|
6
|
+
export interface ISegmentedControlItemEntry {
|
|
7
|
+
id: symbol;
|
|
8
|
+
value: string;
|
|
9
|
+
el: HTMLButtonElement | null;
|
|
10
|
+
disabled?: boolean;
|
|
11
|
+
}
|
|
12
|
+
export interface ISegmentedControlContext {
|
|
13
|
+
orientation: SegmentedControlOrientation;
|
|
14
|
+
disabled: Writable<boolean>;
|
|
15
|
+
selectedValue: Writable<string | null>;
|
|
16
|
+
selectValue: (value: string) => void;
|
|
17
|
+
registerItem: (entry: ISegmentedControlItemEntry) => void;
|
|
18
|
+
unregisterItem: (id: symbol) => void;
|
|
19
|
+
}
|
|
20
|
+
export interface ISegmentedControlRootProps {
|
|
21
|
+
/** Controlled value. */
|
|
22
|
+
value?: string | null;
|
|
23
|
+
/** Fallback selection when `value` is not supplied. */
|
|
24
|
+
defaultValue?: string;
|
|
25
|
+
/** Exposed gap between items. */
|
|
26
|
+
gap?: string;
|
|
27
|
+
/** Direction of the control. */
|
|
28
|
+
orientation?: SegmentedControlOrientation;
|
|
29
|
+
/** Disable the whole control. */
|
|
30
|
+
disabled?: boolean;
|
|
31
|
+
/** Custom CSS class names for the root wrapper. */
|
|
32
|
+
classNames?: string;
|
|
33
|
+
/** Inline style helpers for the root wrapper. */
|
|
34
|
+
style?: string;
|
|
35
|
+
/** Arbitrary variant attribute. */
|
|
36
|
+
dataVariant?: string;
|
|
37
|
+
/** Callback that fires when the active value changes. */
|
|
38
|
+
onValueChange?: (value: string) => void;
|
|
39
|
+
children: Snippet;
|
|
40
|
+
}
|
|
41
|
+
export interface ISegmentedControlItemProps {
|
|
42
|
+
/** Unique identifier for the item (must be provided). */
|
|
43
|
+
value: string;
|
|
44
|
+
/** Disable just this item. */
|
|
45
|
+
disabled?: boolean;
|
|
46
|
+
/** Custom CSS class names applied to the item button. */
|
|
47
|
+
classNames?: string;
|
|
48
|
+
/** Inline styles for the item button. */
|
|
49
|
+
style?: string;
|
|
50
|
+
/** Arbitrary variant attribute. */
|
|
51
|
+
dataVariant?: string;
|
|
52
|
+
/** Click handler passed from the consumer. */
|
|
53
|
+
onClick?: (event: MouseEvent) => void;
|
|
54
|
+
children: Snippet;
|
|
55
|
+
}
|
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
import { getContext, onDestroy } from 'svelte';
|
|
3
|
+
import { writable } from 'svelte/store';
|
|
4
|
+
import {
|
|
5
|
+
SEGMENTED_CONTROL_CONTEXT,
|
|
6
|
+
type ISegmentedControlContext,
|
|
7
|
+
type ISegmentedControlItemProps
|
|
8
|
+
} from './SegmentedControl.types';
|
|
9
|
+
|
|
10
|
+
const fallbackSelectedValue = writable<string | null>(null);
|
|
11
|
+
const fallbackDisabled = writable(false);
|
|
12
|
+
|
|
13
|
+
let {
|
|
14
|
+
value,
|
|
15
|
+
disabled = false,
|
|
16
|
+
classNames = '',
|
|
17
|
+
style,
|
|
18
|
+
dataVariant,
|
|
19
|
+
onClick,
|
|
20
|
+
children
|
|
21
|
+
}: ISegmentedControlItemProps = $props();
|
|
22
|
+
|
|
23
|
+
const context = getContext<ISegmentedControlContext>(SEGMENTED_CONTROL_CONTEXT);
|
|
24
|
+
const selectedValueStore = context?.selectedValue ?? fallbackSelectedValue;
|
|
25
|
+
const disabledStore = context?.disabled ?? fallbackDisabled;
|
|
26
|
+
const itemId = Symbol(value);
|
|
27
|
+
let buttonEl: HTMLButtonElement | null = null;
|
|
28
|
+
let isDisabled = $derived(disabled || $disabledStore);
|
|
29
|
+
let isSelected = $derived($selectedValueStore === value);
|
|
30
|
+
let tabIndex = $derived(($selectedValueStore !== null) ? (isSelected ? 0 : -1) : 0);
|
|
31
|
+
|
|
32
|
+
$effect(() => {
|
|
33
|
+
if (context) {
|
|
34
|
+
context.registerItem({
|
|
35
|
+
id: itemId,
|
|
36
|
+
value,
|
|
37
|
+
el: buttonEl,
|
|
38
|
+
disabled: isDisabled
|
|
39
|
+
});
|
|
40
|
+
}
|
|
41
|
+
});
|
|
42
|
+
|
|
43
|
+
let buttonClass = $state('');
|
|
44
|
+
$effect(() => {
|
|
45
|
+
const base = ['SegmentedControlItem'];
|
|
46
|
+
if (isSelected) base.push('SegmentedControlItem--selected');
|
|
47
|
+
if (isDisabled) base.push('SegmentedControlItem--disabled');
|
|
48
|
+
if (classNames) base.push(classNames);
|
|
49
|
+
buttonClass = base.join(' ');
|
|
50
|
+
});
|
|
51
|
+
|
|
52
|
+
onDestroy(() => {
|
|
53
|
+
context?.unregisterItem(itemId);
|
|
54
|
+
});
|
|
55
|
+
|
|
56
|
+
function handleClick(event: MouseEvent) {
|
|
57
|
+
if (isDisabled) return;
|
|
58
|
+
context?.selectValue(value);
|
|
59
|
+
onClick?.(event);
|
|
60
|
+
}
|
|
61
|
+
</script>
|
|
62
|
+
|
|
63
|
+
<button
|
|
64
|
+
type="button"
|
|
65
|
+
class={buttonClass}
|
|
66
|
+
role="radio"
|
|
67
|
+
aria-checked={isSelected}
|
|
68
|
+
aria-disabled={isDisabled}
|
|
69
|
+
tabindex={tabIndex}
|
|
70
|
+
data-state={isSelected ? 'on' : 'off'}
|
|
71
|
+
{style}
|
|
72
|
+
onclick={handleClick}
|
|
73
|
+
bind:this={buttonEl}
|
|
74
|
+
disabled={isDisabled}
|
|
75
|
+
{...(dataVariant ? { 'data-variant': dataVariant } : {})}
|
|
76
|
+
>
|
|
77
|
+
{@render children?.()}
|
|
78
|
+
</button>
|
|
79
|
+
|
|
80
|
+
<style>.SegmentedControlItem {
|
|
81
|
+
flex: 1;
|
|
82
|
+
min-width: 0;
|
|
83
|
+
border: 0;
|
|
84
|
+
border-radius: 6px;
|
|
85
|
+
background: transparent;
|
|
86
|
+
color: var(--text-base-muted);
|
|
87
|
+
font-size: 0.875rem;
|
|
88
|
+
line-height: 1.3;
|
|
89
|
+
padding: 0.35rem 0.9rem;
|
|
90
|
+
cursor: pointer;
|
|
91
|
+
text-align: center;
|
|
92
|
+
transition: background 0.15s ease, color 0.15s ease, border-color 0.15s ease;
|
|
93
|
+
align-items: center;
|
|
94
|
+
display: inline-flex;
|
|
95
|
+
justify-content: center;
|
|
96
|
+
gap: 0.35rem;
|
|
97
|
+
outline: none;
|
|
98
|
+
}
|
|
99
|
+
.SegmentedControlItem:not(:disabled):hover:not([data-state=on]) {
|
|
100
|
+
background: var(--bg-base-200);
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
.SegmentedControlItem[data-state=on] {
|
|
104
|
+
background: var(--bg-base-emp-100);
|
|
105
|
+
color: var(--text-base-inv);
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
.SegmentedControlItem--disabled {
|
|
109
|
+
opacity: 0.5;
|
|
110
|
+
cursor: not-allowed;
|
|
111
|
+
}</style>
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
import { type ISegmentedControlItemProps } from './SegmentedControl.types';
|
|
2
|
+
declare const SegmentedControlItem: import("svelte").Component<ISegmentedControlItemProps, {}, "">;
|
|
3
|
+
type SegmentedControlItem = ReturnType<typeof SegmentedControlItem>;
|
|
4
|
+
export default SegmentedControlItem;
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import SegmentedControlRoot from './SegmentedControl.svelte';
|
|
2
|
+
import SegmentedControlItem from './SegmentedControlItem.svelte';
|
|
3
|
+
declare const SegmentedControl: import("svelte").Component<import("./SegmentedControl.types").ISegmentedControlRootProps, {}, "value"> & {
|
|
4
|
+
Root: import("svelte").Component<import("./SegmentedControl.types").ISegmentedControlRootProps, {}, "value">;
|
|
5
|
+
Item: import("svelte").Component<import("./SegmentedControl.types").ISegmentedControlItemProps, {}, "">;
|
|
6
|
+
};
|
|
7
|
+
export { SegmentedControl, SegmentedControlRoot, SegmentedControlItem };
|
|
8
|
+
export * from './SegmentedControl.types';
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import SegmentedControlRoot from './SegmentedControl.svelte';
|
|
2
|
+
import SegmentedControlItem from './SegmentedControlItem.svelte';
|
|
3
|
+
const SegmentedControl = Object.assign(SegmentedControlRoot, {
|
|
4
|
+
Root: SegmentedControlRoot,
|
|
5
|
+
Item: SegmentedControlItem
|
|
6
|
+
});
|
|
7
|
+
export { SegmentedControl, SegmentedControlRoot, SegmentedControlItem };
|
|
8
|
+
export * from './SegmentedControl.types';
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
import {clickOutsideObject} from '../..';
|
|
3
|
+
import Portal from '../Portal/Portal.svelte';
|
|
4
|
+
import type { ISheetProps } from './Sheet.types';
|
|
5
|
+
import {onDestroy, onMount} from "svelte";
|
|
6
|
+
import {browser} from "$app/environment";
|
|
7
|
+
|
|
8
|
+
let { children, isOpen, hide, hideOnClickOutside }: ISheetProps = $props();
|
|
9
|
+
|
|
10
|
+
let sheetElement = $state<HTMLDivElement | null>(null)
|
|
11
|
+
|
|
12
|
+
const handleClickOutside = (event: MouseEvent) => {
|
|
13
|
+
clickOutsideObject(event, sheetElement as HTMLElement, null, () => hide?.());
|
|
14
|
+
};
|
|
15
|
+
|
|
16
|
+
onMount(() => {
|
|
17
|
+
if (browser && hideOnClickOutside) {
|
|
18
|
+
document.addEventListener("mousedown", handleClickOutside);
|
|
19
|
+
}
|
|
20
|
+
});
|
|
21
|
+
|
|
22
|
+
onDestroy(() => {
|
|
23
|
+
if (browser && hideOnClickOutside) {
|
|
24
|
+
document.removeEventListener("mousedown", handleClickOutside);
|
|
25
|
+
}
|
|
26
|
+
});
|
|
27
|
+
</script>
|
|
28
|
+
|
|
29
|
+
<Portal>
|
|
30
|
+
<div class={`Sheet ${isOpen ? 'Sheet-open' : ''}`} bind:this={sheetElement}>
|
|
31
|
+
{@render children()}
|
|
32
|
+
</div>
|
|
33
|
+
</Portal>
|
|
34
|
+
|
|
35
|
+
<style>.Sheet {
|
|
36
|
+
position: fixed;
|
|
37
|
+
z-index: var(--zindex-sheet);
|
|
38
|
+
top: 0;
|
|
39
|
+
right: 0;
|
|
40
|
+
height: 100vh;
|
|
41
|
+
background: white;
|
|
42
|
+
width: 400px;
|
|
43
|
+
border-left: 1px solid var(--line-base);
|
|
44
|
+
box-shadow: 0 0 20px rgba(0, 0, 0, 0.1);
|
|
45
|
+
transform: translateX(110%);
|
|
46
|
+
opacity: 0;
|
|
47
|
+
transition: all 0.3s ease-in-out;
|
|
48
|
+
}
|
|
49
|
+
.Sheet.Sheet-open {
|
|
50
|
+
transform: translateX(0);
|
|
51
|
+
opacity: 1;
|
|
52
|
+
}</style>
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import type { Snippet } from "svelte";
|
|
2
|
+
export interface ISheetProps {
|
|
3
|
+
children: Snippet;
|
|
4
|
+
isOpen: boolean;
|
|
5
|
+
hide?: () => unknown;
|
|
6
|
+
hideOnClickOutside?: boolean;
|
|
7
|
+
}
|
|
8
|
+
export interface ISheetHeaderProps {
|
|
9
|
+
children: Snippet;
|
|
10
|
+
}
|
|
11
|
+
export interface ISheetDescriptionProps {
|
|
12
|
+
children: Snippet;
|
|
13
|
+
}
|
|
14
|
+
export interface ISheetContentProps {
|
|
15
|
+
children: Snippet;
|
|
16
|
+
}
|
|
17
|
+
export interface ISheetActionsProps {
|
|
18
|
+
children: Snippet;
|
|
19
|
+
hide?: () => unknown;
|
|
20
|
+
}
|
|
21
|
+
export interface ISheetTitleProps {
|
|
22
|
+
children: Snippet;
|
|
23
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
import { ButtonMilk } from "../..";
|
|
3
|
+
import type { ISheetActionsProps } from './Sheet.types';
|
|
4
|
+
import { CloseLargeLineSystem } from "svelte-remix";
|
|
5
|
+
let { children, hide }: ISheetActionsProps = $props();
|
|
6
|
+
|
|
7
|
+
</script>
|
|
8
|
+
|
|
9
|
+
<div class="SheetActions">
|
|
10
|
+
{@render children()}
|
|
11
|
+
{#if hide}
|
|
12
|
+
<div class="SheetActions-hide">
|
|
13
|
+
<ButtonMilk onClick={hide} iconButton variant="base-contained" size="sm">
|
|
14
|
+
<CloseLargeLineSystem size="1em"/>
|
|
15
|
+
</ButtonMilk>
|
|
16
|
+
</div>
|
|
17
|
+
{/if}
|
|
18
|
+
</div>
|
|
19
|
+
|
|
20
|
+
<style>.SheetActions {
|
|
21
|
+
padding: 0.5rem;
|
|
22
|
+
border-bottom: 1px solid var(--line-base);
|
|
23
|
+
}
|
|
24
|
+
.SheetActions .SheetActions-hide {
|
|
25
|
+
position: absolute;
|
|
26
|
+
right: 0.5rem;
|
|
27
|
+
top: 0.5rem;
|
|
28
|
+
}</style>
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
import type { ISheetContentProps } from "./Sheet.types";
|
|
3
|
+
|
|
4
|
+
let { children }: ISheetContentProps = $props();
|
|
5
|
+
</script>
|
|
6
|
+
|
|
7
|
+
<div class="SheetContent">
|
|
8
|
+
{@render children()}
|
|
9
|
+
</div>
|
|
10
|
+
|
|
11
|
+
<style>.SheetContent {
|
|
12
|
+
padding: 0.5rem 1.5rem;
|
|
13
|
+
}</style>
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
import type {ISheetDescriptionProps} from "./Sheet.types";
|
|
3
|
+
|
|
4
|
+
let { children }: ISheetDescriptionProps = $props();
|
|
5
|
+
</script>
|
|
6
|
+
|
|
7
|
+
<div class="SheetDescription">
|
|
8
|
+
{@render children()}
|
|
9
|
+
</div>
|
|
10
|
+
|
|
11
|
+
<style>.SheetDescription {
|
|
12
|
+
color: var(--text-base-muted);
|
|
13
|
+
}</style>
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
import type {ISheetHeaderProps} from "./Sheet.types";
|
|
3
|
+
|
|
4
|
+
let { children }: ISheetHeaderProps = $props();
|
|
5
|
+
</script>
|
|
6
|
+
|
|
7
|
+
<div class="SheetHeader">
|
|
8
|
+
{@render children()}
|
|
9
|
+
</div>
|
|
10
|
+
|
|
11
|
+
<style>.SheetHeader {
|
|
12
|
+
padding: 1.5rem 1.5rem 0.5rem;
|
|
13
|
+
}</style>
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
import type { ISheetTitleProps } from './Sheet.types';
|
|
3
|
+
let { children } : ISheetTitleProps = $props();
|
|
4
|
+
</script>
|
|
5
|
+
|
|
6
|
+
<h2 class="SheetTitle">
|
|
7
|
+
{@render children()}
|
|
8
|
+
</h2>
|
|
9
|
+
|
|
10
|
+
<style>.SheetTitle {
|
|
11
|
+
font-size: var(--font-size-h2);
|
|
12
|
+
font-weight: 500;
|
|
13
|
+
}</style>
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
export { default as Sheet } from './Sheet.svelte';
|
|
2
|
+
export { default as SheetHeader } from './SheetHeader.svelte';
|
|
3
|
+
export { default as SheetActions } from './SheetActions.svelte';
|
|
4
|
+
export { default as SheetTitle } from './SheetTitle.svelte';
|
|
5
|
+
export { default as SheetContent } from './SheetContent.svelte';
|
|
6
|
+
export { default as SheetDescription } from './SheetDescription.svelte';
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
export { default as Sheet } from './Sheet.svelte';
|
|
2
|
+
export { default as SheetHeader } from './SheetHeader.svelte';
|
|
3
|
+
export { default as SheetActions } from './SheetActions.svelte';
|
|
4
|
+
export { default as SheetTitle } from './SheetTitle.svelte';
|
|
5
|
+
export { default as SheetContent } from './SheetContent.svelte';
|
|
6
|
+
export { default as SheetDescription } from './SheetDescription.svelte';
|
|
@@ -13,7 +13,9 @@ export * from './TextInputBlock';
|
|
|
13
13
|
export * from './Command';
|
|
14
14
|
export * from './Portal';
|
|
15
15
|
export * from './Modal';
|
|
16
|
+
export * from './SegmentedControl';
|
|
16
17
|
export * from './Select';
|
|
17
18
|
export * from './Icon';
|
|
18
19
|
export * from './Checkbox';
|
|
19
20
|
export * from './CheckboxGroup';
|
|
21
|
+
export * from './Sheet';
|
package/dist/components/index.js
CHANGED
|
@@ -13,7 +13,9 @@ export * from './TextInputBlock';
|
|
|
13
13
|
export * from './Command';
|
|
14
14
|
export * from './Portal';
|
|
15
15
|
export * from './Modal';
|
|
16
|
+
export * from './SegmentedControl';
|
|
16
17
|
export * from './Select';
|
|
17
18
|
export * from './Icon';
|
|
18
19
|
export * from './Checkbox';
|
|
19
20
|
export * from './CheckboxGroup';
|
|
21
|
+
export * from './Sheet';
|