@dryui/ui 0.4.1 → 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/dist/button/button.svelte +6 -2
- package/dist/index.d.ts +2 -0
- package/dist/index.js +1 -0
- package/dist/mega-menu/mega-menu-link.svelte +47 -7
- package/dist/mega-menu/mega-menu-panel.svelte +1 -1
- package/dist/option-picker/index.d.ts +33 -0
- package/dist/option-picker/index.js +14 -0
- package/dist/option-picker/option-picker-description.svelte +25 -0
- package/dist/option-picker/option-picker-description.svelte.d.ts +8 -0
- package/dist/option-picker/option-picker-item.svelte +215 -0
- package/dist/option-picker/option-picker-item.svelte.d.ts +13 -0
- package/dist/option-picker/option-picker-label.svelte +24 -0
- package/dist/option-picker/option-picker-label.svelte.d.ts +8 -0
- package/dist/option-picker/option-picker-meta.svelte +24 -0
- package/dist/option-picker/option-picker-meta.svelte.d.ts +8 -0
- package/dist/option-picker/option-picker-preview.svelte +137 -0
- package/dist/option-picker/option-picker-preview.svelte.d.ts +11 -0
- package/dist/option-picker/option-picker-root.svelte +82 -0
- package/dist/option-picker/option-picker-root.svelte.d.ts +12 -0
- package/dist/option-swatch-group/index.d.ts +8 -2
- package/dist/option-swatch-group/option-swatch-group-item-button.svelte +155 -17
- package/dist/option-swatch-group/option-swatch-group-item-button.svelte.d.ts +1 -0
- package/dist/option-swatch-group/option-swatch-group-root.svelte +20 -2
- package/dist/option-swatch-group/option-swatch-group-root.svelte.d.ts +1 -0
- package/dist/option-swatch-group/option-swatch-group-swatch.svelte +12 -11
- package/dist/sidebar/sidebar-item.svelte +1 -2
- package/package.json +1 -1
|
@@ -351,8 +351,12 @@
|
|
|
351
351
|
}
|
|
352
352
|
|
|
353
353
|
&[aria-expanded='true'] {
|
|
354
|
-
--_dry-btn-bg: var(--dry-btn-bg, var(--dry-color-fill));
|
|
355
|
-
--_dry-btn-color: var(
|
|
354
|
+
--_dry-btn-bg: var(--dry-btn-trigger-open-bg, var(--dry-btn-bg, var(--dry-color-fill)));
|
|
355
|
+
--_dry-btn-color: var(
|
|
356
|
+
--dry-btn-trigger-open-color,
|
|
357
|
+
var(--dry-btn-color, var(--dry-color-text-brand))
|
|
358
|
+
);
|
|
359
|
+
--_dry-btn-border: var(--dry-btn-trigger-open-border, var(--dry-btn-border, transparent));
|
|
356
360
|
}
|
|
357
361
|
}
|
|
358
362
|
|
package/dist/index.d.ts
CHANGED
|
@@ -56,6 +56,8 @@ export { InputGroup } from './input-group/index.js';
|
|
|
56
56
|
export type { InputGroupRootProps, InputGroupPrefixProps, InputGroupInputProps, InputGroupSuffixProps, InputGroupSelectProps, InputGroupSeparatorProps, InputGroupActionProps } from './input-group/index.js';
|
|
57
57
|
export { OptionSwatchGroup } from './option-swatch-group/index.js';
|
|
58
58
|
export type { OptionSwatchGroupRootProps, OptionSwatchGroupItemProps, OptionSwatchGroupSwatchProps, OptionSwatchGroupLabelProps, OptionSwatchGroupMetaProps } from './option-swatch-group/index.js';
|
|
59
|
+
export { OptionPicker } from './option-picker/index.js';
|
|
60
|
+
export type { OptionPickerRootProps, OptionPickerItemProps, OptionPickerPreviewProps, OptionPickerLabelProps, OptionPickerDescriptionProps, OptionPickerMetaProps } from './option-picker/index.js';
|
|
59
61
|
export { Container } from './container/index.js';
|
|
60
62
|
export type { ContainerProps } from './container/index.js';
|
|
61
63
|
export { Separator } from './separator/index.js';
|
package/dist/index.js
CHANGED
|
@@ -28,6 +28,7 @@ export { Toggle } from './toggle/index.js';
|
|
|
28
28
|
export { ToggleGroup } from './toggle-group/index.js';
|
|
29
29
|
export { InputGroup } from './input-group/index.js';
|
|
30
30
|
export { OptionSwatchGroup } from './option-swatch-group/index.js';
|
|
31
|
+
export { OptionPicker } from './option-picker/index.js';
|
|
31
32
|
// Phase 4 — Layout Primitives
|
|
32
33
|
export { Container } from './container/index.js';
|
|
33
34
|
export { Separator } from './separator/index.js';
|
|
@@ -58,12 +58,11 @@
|
|
|
58
58
|
<style>
|
|
59
59
|
[data-mega-menu-link] {
|
|
60
60
|
display: grid;
|
|
61
|
-
grid-
|
|
62
|
-
grid-auto-columns: max-content;
|
|
61
|
+
grid-template-columns: max-content minmax(0, 1fr);
|
|
63
62
|
align-items: start;
|
|
64
63
|
gap: var(--dry-space-3, 0.75rem);
|
|
65
64
|
padding: var(--dry-space-2, 0.5rem) var(--dry-space-3, 0.75rem);
|
|
66
|
-
border:
|
|
65
|
+
border: 1px solid var(--dry-mega-menu-link-border, transparent);
|
|
67
66
|
border-radius: var(--dry-radius-md, 0.375rem);
|
|
68
67
|
background: none;
|
|
69
68
|
font: inherit;
|
|
@@ -72,26 +71,67 @@
|
|
|
72
71
|
color: inherit;
|
|
73
72
|
cursor: pointer;
|
|
74
73
|
appearance: none;
|
|
75
|
-
|
|
74
|
+
box-shadow: var(--dry-mega-menu-link-shadow, none);
|
|
75
|
+
transition:
|
|
76
|
+
background var(--dry-duration-fast, 100ms) ease,
|
|
77
|
+
border-color var(--dry-duration-fast, 100ms) ease,
|
|
78
|
+
box-shadow var(--dry-duration-fast, 100ms) ease;
|
|
76
79
|
}
|
|
77
80
|
|
|
78
|
-
[data-mega-menu-link]:hover
|
|
79
|
-
|
|
81
|
+
[data-mega-menu-link]:hover,
|
|
82
|
+
[data-mega-menu-link]:focus-visible {
|
|
83
|
+
background: var(--dry-mega-menu-link-hover-bg, var(--dry-color-bg-overlay, #f3f4f6));
|
|
84
|
+
border-color: var(--dry-mega-menu-link-hover-border, var(--dry-color-stroke-weak, #e2e8f0));
|
|
85
|
+
box-shadow: var(--dry-mega-menu-link-hover-shadow, none);
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
[data-mega-menu-link][data-selected],
|
|
89
|
+
[data-mega-menu-link][aria-pressed='true'],
|
|
90
|
+
[data-mega-menu-link][aria-current='true'] {
|
|
91
|
+
background: var(
|
|
92
|
+
--dry-mega-menu-link-selected-bg,
|
|
93
|
+
var(--dry-mega-menu-link-hover-bg, var(--dry-color-bg-overlay, #f3f4f6))
|
|
94
|
+
);
|
|
95
|
+
border-color: var(
|
|
96
|
+
--dry-mega-menu-link-selected-border,
|
|
97
|
+
var(--dry-mega-menu-link-hover-border, var(--dry-color-stroke-weak, #e2e8f0))
|
|
98
|
+
);
|
|
99
|
+
box-shadow: var(
|
|
100
|
+
--dry-mega-menu-link-selected-shadow,
|
|
101
|
+
var(--dry-mega-menu-link-hover-shadow, none)
|
|
102
|
+
);
|
|
80
103
|
}
|
|
81
104
|
|
|
82
105
|
[data-mega-menu-link] [data-part='link-icon'] {
|
|
83
106
|
color: var(--dry-color-text-weak);
|
|
84
107
|
}
|
|
85
108
|
|
|
109
|
+
[data-mega-menu-link][data-selected] [data-part='link-icon'],
|
|
110
|
+
[data-mega-menu-link][aria-pressed='true'] [data-part='link-icon'],
|
|
111
|
+
[data-mega-menu-link][aria-current='true'] [data-part='link-icon'] {
|
|
112
|
+
color: var(--dry-color-text-strong, #1a1a2e);
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
[data-mega-menu-link] [data-part='link-content'] {
|
|
116
|
+
display: grid;
|
|
117
|
+
gap: var(--dry-space-0_5, 0.125rem);
|
|
118
|
+
}
|
|
119
|
+
|
|
86
120
|
[data-mega-menu-link] [data-part='link-text'] {
|
|
87
121
|
font-size: var(--dry-type-ui-control-size, var(--dry-text-sm-size, 0.875rem));
|
|
88
122
|
font-weight: 500;
|
|
89
123
|
color: var(--dry-color-text-strong, #1a1a2e);
|
|
90
124
|
}
|
|
91
125
|
|
|
126
|
+
[data-mega-menu-link][data-selected] [data-part='link-text'],
|
|
127
|
+
[data-mega-menu-link][aria-pressed='true'] [data-part='link-text'],
|
|
128
|
+
[data-mega-menu-link][aria-current='true'] [data-part='link-text'] {
|
|
129
|
+
font-weight: 600;
|
|
130
|
+
}
|
|
131
|
+
|
|
92
132
|
[data-mega-menu-link] [data-part='link-description'] {
|
|
133
|
+
display: block;
|
|
93
134
|
font-size: var(--dry-type-ui-caption-size, var(--dry-text-xs-size, 0.75rem));
|
|
94
135
|
color: var(--dry-color-text-weak, #64748b);
|
|
95
|
-
margin-top: var(--dry-space-0_5, 0.125rem);
|
|
96
136
|
}
|
|
97
137
|
</style>
|
|
@@ -78,7 +78,7 @@
|
|
|
78
78
|
inset: unset;
|
|
79
79
|
margin: 0;
|
|
80
80
|
z-index: var(--dry-layer-overlay, 50);
|
|
81
|
-
background: var(--dry-color-bg-overlay, white);
|
|
81
|
+
background: var(--dry-mega-menu-panel-bg, var(--dry-color-bg-overlay, white));
|
|
82
82
|
border: 1px solid var(--dry-color-stroke-weak, #e2e8f0);
|
|
83
83
|
border-radius: var(--dry-radius-lg, 0.5rem);
|
|
84
84
|
box-shadow: var(--dry-shadow-lg, 0 10px 15px -3px rgba(0, 0, 0, 0.1));
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import type { Snippet } from 'svelte';
|
|
2
|
+
import type { HTMLAttributes } from 'svelte/elements';
|
|
3
|
+
import type { SelectableTileGroupDescriptionProps, SelectableTileGroupItemProps as PrimitiveOptionPickerItemProps, SelectableTileGroupLabelProps as OptionPickerLabelProps, SelectableTileGroupMetaProps as OptionPickerMetaProps, SelectableTileGroupRootProps as PrimitiveOptionPickerRootProps } from '@dryui/primitives';
|
|
4
|
+
export interface OptionPickerRootProps extends PrimitiveOptionPickerRootProps {
|
|
5
|
+
columns?: 1 | 2 | 3 | 4;
|
|
6
|
+
}
|
|
7
|
+
export interface OptionPickerItemProps extends PrimitiveOptionPickerItemProps {
|
|
8
|
+
layout?: 'inline' | 'stacked';
|
|
9
|
+
size?: 'default' | 'compact' | 'visual';
|
|
10
|
+
unavailable?: boolean;
|
|
11
|
+
}
|
|
12
|
+
export interface OptionPickerPreviewProps extends HTMLAttributes<HTMLSpanElement> {
|
|
13
|
+
color?: string;
|
|
14
|
+
shape?: 'circle' | 'rounded' | 'square' | 'pill';
|
|
15
|
+
variant?: 'default' | 'preset' | 'font' | 'shape';
|
|
16
|
+
children?: Snippet;
|
|
17
|
+
}
|
|
18
|
+
export type { OptionPickerLabelProps, OptionPickerMetaProps };
|
|
19
|
+
export type { SelectableTileGroupDescriptionProps as OptionPickerDescriptionProps };
|
|
20
|
+
import OptionPickerRoot from './option-picker-root.svelte';
|
|
21
|
+
import OptionPickerItem from './option-picker-item.svelte';
|
|
22
|
+
import OptionPickerPreview from './option-picker-preview.svelte';
|
|
23
|
+
import OptionPickerLabel from './option-picker-label.svelte';
|
|
24
|
+
import OptionPickerDescription from './option-picker-description.svelte';
|
|
25
|
+
import OptionPickerMeta from './option-picker-meta.svelte';
|
|
26
|
+
export declare const OptionPicker: {
|
|
27
|
+
Root: typeof OptionPickerRoot;
|
|
28
|
+
Item: typeof OptionPickerItem;
|
|
29
|
+
Preview: typeof OptionPickerPreview;
|
|
30
|
+
Label: typeof OptionPickerLabel;
|
|
31
|
+
Description: typeof OptionPickerDescription;
|
|
32
|
+
Meta: typeof OptionPickerMeta;
|
|
33
|
+
};
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import OptionPickerRoot from './option-picker-root.svelte';
|
|
2
|
+
import OptionPickerItem from './option-picker-item.svelte';
|
|
3
|
+
import OptionPickerPreview from './option-picker-preview.svelte';
|
|
4
|
+
import OptionPickerLabel from './option-picker-label.svelte';
|
|
5
|
+
import OptionPickerDescription from './option-picker-description.svelte';
|
|
6
|
+
import OptionPickerMeta from './option-picker-meta.svelte';
|
|
7
|
+
export const OptionPicker = {
|
|
8
|
+
Root: OptionPickerRoot,
|
|
9
|
+
Item: OptionPickerItem,
|
|
10
|
+
Preview: OptionPickerPreview,
|
|
11
|
+
Label: OptionPickerLabel,
|
|
12
|
+
Description: OptionPickerDescription,
|
|
13
|
+
Meta: OptionPickerMeta
|
|
14
|
+
};
|
|
@@ -0,0 +1,25 @@
|
|
|
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?: Snippet;
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
let { class: className, children, ...rest }: Props = $props();
|
|
10
|
+
</script>
|
|
11
|
+
|
|
12
|
+
<div data-part="description" data-option-picker-description class={className} {...rest}>
|
|
13
|
+
{@render children?.()}
|
|
14
|
+
</div>
|
|
15
|
+
|
|
16
|
+
<style>
|
|
17
|
+
[data-option-picker-description] {
|
|
18
|
+
grid-column: var(--dry-option-picker-description-column, 2);
|
|
19
|
+
grid-row: var(--dry-option-picker-description-row, 2);
|
|
20
|
+
font-size: var(--dry-type-small-size);
|
|
21
|
+
line-height: 1.35;
|
|
22
|
+
color: var(--dry-color-text-weak);
|
|
23
|
+
text-wrap: pretty;
|
|
24
|
+
}
|
|
25
|
+
</style>
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import type { Snippet } from 'svelte';
|
|
2
|
+
import type { HTMLAttributes } from 'svelte/elements';
|
|
3
|
+
interface Props extends HTMLAttributes<HTMLDivElement> {
|
|
4
|
+
children?: Snippet;
|
|
5
|
+
}
|
|
6
|
+
declare const OptionPickerDescription: import("svelte").Component<Props, {}, "">;
|
|
7
|
+
type OptionPickerDescription = ReturnType<typeof OptionPickerDescription>;
|
|
8
|
+
export default OptionPickerDescription;
|
|
@@ -0,0 +1,215 @@
|
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
import type { Snippet } from 'svelte';
|
|
3
|
+
import type { HTMLButtonAttributes } from 'svelte/elements';
|
|
4
|
+
import Button from '../button/button.svelte';
|
|
5
|
+
import { getSelectableTileGroupCtx } from '../option-swatch-group/context.svelte.js';
|
|
6
|
+
|
|
7
|
+
interface Props extends Omit<HTMLButtonAttributes, 'value'> {
|
|
8
|
+
value: string;
|
|
9
|
+
disabled?: boolean;
|
|
10
|
+
unavailable?: boolean;
|
|
11
|
+
layout?: 'inline' | 'stacked';
|
|
12
|
+
size?: 'default' | 'compact' | 'visual';
|
|
13
|
+
children: Snippet;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
let {
|
|
17
|
+
value,
|
|
18
|
+
disabled = false,
|
|
19
|
+
unavailable = false,
|
|
20
|
+
layout = 'inline',
|
|
21
|
+
size = 'default',
|
|
22
|
+
children,
|
|
23
|
+
...rest
|
|
24
|
+
}: Props = $props();
|
|
25
|
+
|
|
26
|
+
const ctx = getSelectableTileGroupCtx();
|
|
27
|
+
const isDisabled = $derived(disabled || unavailable || ctx.disabled);
|
|
28
|
+
const isSelected = $derived(ctx.isSelected(value));
|
|
29
|
+
|
|
30
|
+
function moveFocus(current: HTMLButtonElement, direction: -1 | 1) {
|
|
31
|
+
const group = current.closest('[role="radiogroup"]');
|
|
32
|
+
if (!(group instanceof HTMLElement)) return;
|
|
33
|
+
|
|
34
|
+
const items = Array.from(
|
|
35
|
+
group.querySelectorAll<HTMLButtonElement>('[role="radio"]:not([disabled])')
|
|
36
|
+
);
|
|
37
|
+
const index = items.indexOf(current);
|
|
38
|
+
if (index === -1) return;
|
|
39
|
+
|
|
40
|
+
const target = items[(index + direction + items.length) % items.length];
|
|
41
|
+
target?.focus();
|
|
42
|
+
const nextValue = target?.dataset.value;
|
|
43
|
+
if (nextValue) ctx.select(nextValue);
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
function handleKeydown(event: KeyboardEvent) {
|
|
47
|
+
if (isDisabled || !(event.currentTarget instanceof HTMLButtonElement)) return;
|
|
48
|
+
|
|
49
|
+
const isHorizontal = ctx.orientation === 'horizontal';
|
|
50
|
+
if (
|
|
51
|
+
(isHorizontal && event.key === 'ArrowRight') ||
|
|
52
|
+
(!isHorizontal && event.key === 'ArrowDown')
|
|
53
|
+
) {
|
|
54
|
+
event.preventDefault();
|
|
55
|
+
moveFocus(event.currentTarget, 1);
|
|
56
|
+
}
|
|
57
|
+
if ((isHorizontal && event.key === 'ArrowLeft') || (!isHorizontal && event.key === 'ArrowUp')) {
|
|
58
|
+
event.preventDefault();
|
|
59
|
+
moveFocus(event.currentTarget, -1);
|
|
60
|
+
}
|
|
61
|
+
if (event.key === ' ' || event.key === 'Enter') {
|
|
62
|
+
event.preventDefault();
|
|
63
|
+
ctx.select(value);
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
</script>
|
|
67
|
+
|
|
68
|
+
<span
|
|
69
|
+
class="root"
|
|
70
|
+
data-layout={layout}
|
|
71
|
+
data-size={size !== 'default' ? size : undefined}
|
|
72
|
+
data-state={isSelected ? 'checked' : 'unchecked'}
|
|
73
|
+
data-selected={isSelected ? '' : undefined}
|
|
74
|
+
data-disabled={isDisabled || undefined}
|
|
75
|
+
data-unavailable={unavailable || undefined}
|
|
76
|
+
>
|
|
77
|
+
<Button
|
|
78
|
+
variant="bare"
|
|
79
|
+
type="button"
|
|
80
|
+
role="radio"
|
|
81
|
+
aria-checked={isSelected}
|
|
82
|
+
disabled={isDisabled}
|
|
83
|
+
data-option-picker-item
|
|
84
|
+
data-state={isSelected ? 'checked' : 'unchecked'}
|
|
85
|
+
data-selected={isSelected ? '' : undefined}
|
|
86
|
+
data-unavailable={unavailable || undefined}
|
|
87
|
+
data-value={value}
|
|
88
|
+
tabindex={isSelected ? 0 : -1}
|
|
89
|
+
{...rest}
|
|
90
|
+
onclick={() => {
|
|
91
|
+
if (!isDisabled) ctx.select(value);
|
|
92
|
+
}}
|
|
93
|
+
onkeydown={handleKeydown}
|
|
94
|
+
>
|
|
95
|
+
<span class="content">
|
|
96
|
+
{@render children()}
|
|
97
|
+
</span>
|
|
98
|
+
</Button>
|
|
99
|
+
</span>
|
|
100
|
+
|
|
101
|
+
<style>
|
|
102
|
+
.root {
|
|
103
|
+
--_option-picker-selected-bg: var(
|
|
104
|
+
--dry-option-picker-selected-bg,
|
|
105
|
+
color-mix(in srgb, var(--dry-color-fill-selected) 12%, var(--dry-color-bg-raised) 88%)
|
|
106
|
+
);
|
|
107
|
+
--_option-picker-selected-bg-hover: var(
|
|
108
|
+
--dry-option-picker-selected-bg-hover,
|
|
109
|
+
color-mix(in srgb, var(--dry-color-fill-selected) 16%, var(--dry-color-bg-raised) 84%)
|
|
110
|
+
);
|
|
111
|
+
--_option-picker-selected-border: var(
|
|
112
|
+
--dry-option-picker-selected-border,
|
|
113
|
+
var(--dry-color-stroke-selected)
|
|
114
|
+
);
|
|
115
|
+
|
|
116
|
+
display: grid;
|
|
117
|
+
background: var(--dry-option-picker-bg, var(--dry-color-bg-base));
|
|
118
|
+
border: 1px solid var(--dry-option-picker-border, var(--dry-color-stroke-weak));
|
|
119
|
+
border-radius: var(--dry-option-picker-radius, var(--dry-radius-lg));
|
|
120
|
+
box-shadow: var(--dry-option-picker-shadow, none);
|
|
121
|
+
transition:
|
|
122
|
+
background var(--dry-duration-fast, 100ms) ease,
|
|
123
|
+
border-color var(--dry-duration-fast, 100ms) ease,
|
|
124
|
+
box-shadow var(--dry-duration-fast, 100ms) ease,
|
|
125
|
+
transform var(--dry-duration-fast, 100ms) ease;
|
|
126
|
+
|
|
127
|
+
--dry-btn-bg: transparent;
|
|
128
|
+
--dry-btn-border: transparent;
|
|
129
|
+
--dry-btn-color: var(--dry-option-picker-color, var(--dry-color-text-strong));
|
|
130
|
+
--dry-btn-padding-x: 0;
|
|
131
|
+
--dry-btn-padding-y: 0;
|
|
132
|
+
--dry-btn-radius: var(--dry-option-picker-radius, var(--dry-radius-lg));
|
|
133
|
+
--dry-btn-justify: stretch;
|
|
134
|
+
--dry-btn-align: stretch;
|
|
135
|
+
--dry-btn-min-height: 0;
|
|
136
|
+
|
|
137
|
+
--dry-option-picker-preview-size: 2.25rem;
|
|
138
|
+
--dry-option-picker-preview-radius: var(--dry-radius-md);
|
|
139
|
+
--dry-option-picker-preview-column: 1;
|
|
140
|
+
--dry-option-picker-preview-row: 1 / span 3;
|
|
141
|
+
--dry-option-picker-label-column: 2;
|
|
142
|
+
--dry-option-picker-label-row: 1;
|
|
143
|
+
--dry-option-picker-description-column: 2;
|
|
144
|
+
--dry-option-picker-description-row: 2;
|
|
145
|
+
--dry-option-picker-meta-column: 2;
|
|
146
|
+
--dry-option-picker-meta-row: 3;
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
.root:hover:not([data-disabled]) {
|
|
150
|
+
border-color: color-mix(
|
|
151
|
+
in srgb,
|
|
152
|
+
var(--dry-color-stroke-strong) 72%,
|
|
153
|
+
var(--dry-color-stroke-weak) 28%
|
|
154
|
+
);
|
|
155
|
+
background: var(
|
|
156
|
+
--dry-option-picker-bg-hover,
|
|
157
|
+
color-mix(in srgb, var(--dry-color-bg-raised) 92%, var(--dry-color-fill-selected) 8%)
|
|
158
|
+
);
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
.root[data-state='checked'] {
|
|
162
|
+
border-color: var(--_option-picker-selected-border);
|
|
163
|
+
background: var(--_option-picker-selected-bg);
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
.root[data-state='checked']:hover:not([data-disabled]) {
|
|
167
|
+
background: var(--_option-picker-selected-bg-hover);
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
.root:focus-within {
|
|
171
|
+
outline: 2px solid var(--dry-color-focus-ring);
|
|
172
|
+
outline-offset: 2px;
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
.content {
|
|
176
|
+
display: grid;
|
|
177
|
+
grid-template-columns: auto minmax(0, 1fr);
|
|
178
|
+
align-items: center;
|
|
179
|
+
justify-items: start;
|
|
180
|
+
gap: var(--dry-option-picker-item-gap, var(--dry-space-3));
|
|
181
|
+
padding: var(--dry-option-picker-padding-y, var(--dry-space-3))
|
|
182
|
+
var(--dry-option-picker-padding-x, var(--dry-space-3));
|
|
183
|
+
min-block-size: var(--dry-option-picker-min-block-size, 3.5rem);
|
|
184
|
+
text-align: left;
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
.root[data-layout='stacked'] .content {
|
|
188
|
+
grid-template-columns: 1fr;
|
|
189
|
+
justify-items: center;
|
|
190
|
+
text-align: center;
|
|
191
|
+
--dry-option-picker-preview-size: 3rem;
|
|
192
|
+
--dry-option-picker-preview-column: 1;
|
|
193
|
+
--dry-option-picker-preview-row: 1;
|
|
194
|
+
--dry-option-picker-label-column: 1;
|
|
195
|
+
--dry-option-picker-label-row: 2;
|
|
196
|
+
--dry-option-picker-description-column: 1;
|
|
197
|
+
--dry-option-picker-description-row: 3;
|
|
198
|
+
--dry-option-picker-meta-column: 1;
|
|
199
|
+
--dry-option-picker-meta-row: 4;
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
.root[data-size='compact'] .content {
|
|
203
|
+
min-block-size: 2.75rem;
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
.root[data-size='visual'] .content {
|
|
207
|
+
min-block-size: var(--dry-option-picker-visual-min-block-size, 5.5rem);
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
.root[data-disabled] {
|
|
211
|
+
opacity: 0.6;
|
|
212
|
+
border-color: var(--dry-color-stroke-disabled);
|
|
213
|
+
box-shadow: none;
|
|
214
|
+
}
|
|
215
|
+
</style>
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import type { Snippet } from 'svelte';
|
|
2
|
+
import type { HTMLButtonAttributes } from 'svelte/elements';
|
|
3
|
+
interface Props extends Omit<HTMLButtonAttributes, 'value'> {
|
|
4
|
+
value: string;
|
|
5
|
+
disabled?: boolean;
|
|
6
|
+
unavailable?: boolean;
|
|
7
|
+
layout?: 'inline' | 'stacked';
|
|
8
|
+
size?: 'default' | 'compact' | 'visual';
|
|
9
|
+
children: Snippet;
|
|
10
|
+
}
|
|
11
|
+
declare const OptionPickerItem: import("svelte").Component<Props, {}, "">;
|
|
12
|
+
type OptionPickerItem = ReturnType<typeof OptionPickerItem>;
|
|
13
|
+
export default OptionPickerItem;
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
import type { Snippet } from 'svelte';
|
|
3
|
+
import type { HTMLAttributes } from 'svelte/elements';
|
|
4
|
+
|
|
5
|
+
interface Props extends HTMLAttributes<HTMLSpanElement> {
|
|
6
|
+
children?: Snippet;
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
let { class: className, children, ...rest }: Props = $props();
|
|
10
|
+
</script>
|
|
11
|
+
|
|
12
|
+
<span data-part="label" data-option-picker-label class={className} {...rest}>
|
|
13
|
+
{@render children?.()}
|
|
14
|
+
</span>
|
|
15
|
+
|
|
16
|
+
<style>
|
|
17
|
+
[data-option-picker-label] {
|
|
18
|
+
grid-column: var(--dry-option-picker-label-column, 2);
|
|
19
|
+
grid-row: var(--dry-option-picker-label-row, 1);
|
|
20
|
+
font-size: var(--dry-type-small-size);
|
|
21
|
+
font-weight: 600;
|
|
22
|
+
line-height: 1.2;
|
|
23
|
+
}
|
|
24
|
+
</style>
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import type { Snippet } from 'svelte';
|
|
2
|
+
import type { HTMLAttributes } from 'svelte/elements';
|
|
3
|
+
interface Props extends HTMLAttributes<HTMLSpanElement> {
|
|
4
|
+
children?: Snippet;
|
|
5
|
+
}
|
|
6
|
+
declare const OptionPickerLabel: import("svelte").Component<Props, {}, "">;
|
|
7
|
+
type OptionPickerLabel = ReturnType<typeof OptionPickerLabel>;
|
|
8
|
+
export default OptionPickerLabel;
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
import type { Snippet } from 'svelte';
|
|
3
|
+
import type { HTMLAttributes } from 'svelte/elements';
|
|
4
|
+
|
|
5
|
+
interface Props extends HTMLAttributes<HTMLSpanElement> {
|
|
6
|
+
children?: Snippet;
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
let { class: className, children, ...rest }: Props = $props();
|
|
10
|
+
</script>
|
|
11
|
+
|
|
12
|
+
<span data-part="meta" data-option-picker-meta class={className} {...rest}>
|
|
13
|
+
{@render children?.()}
|
|
14
|
+
</span>
|
|
15
|
+
|
|
16
|
+
<style>
|
|
17
|
+
[data-option-picker-meta] {
|
|
18
|
+
grid-column: var(--dry-option-picker-meta-column, 2);
|
|
19
|
+
grid-row: var(--dry-option-picker-meta-row, 3);
|
|
20
|
+
font-size: var(--dry-type-tiny-size);
|
|
21
|
+
line-height: 1.2;
|
|
22
|
+
color: var(--dry-color-text-weaker, var(--dry-color-text-weak));
|
|
23
|
+
}
|
|
24
|
+
</style>
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import type { Snippet } from 'svelte';
|
|
2
|
+
import type { HTMLAttributes } from 'svelte/elements';
|
|
3
|
+
interface Props extends HTMLAttributes<HTMLSpanElement> {
|
|
4
|
+
children?: Snippet;
|
|
5
|
+
}
|
|
6
|
+
declare const OptionPickerMeta: import("svelte").Component<Props, {}, "">;
|
|
7
|
+
type OptionPickerMeta = ReturnType<typeof OptionPickerMeta>;
|
|
8
|
+
export default OptionPickerMeta;
|
|
@@ -0,0 +1,137 @@
|
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
import type { Snippet } from 'svelte';
|
|
3
|
+
import type { HTMLAttributes } from 'svelte/elements';
|
|
4
|
+
|
|
5
|
+
interface Props extends HTMLAttributes<HTMLSpanElement> {
|
|
6
|
+
color?: string;
|
|
7
|
+
shape?: 'circle' | 'rounded' | 'square' | 'pill';
|
|
8
|
+
variant?: 'default' | 'preset' | 'font' | 'shape';
|
|
9
|
+
children?: Snippet;
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
let { color, shape = 'rounded', variant = 'default', children, ...rest }: Props = $props();
|
|
13
|
+
|
|
14
|
+
function attachPreviewVars(previewColor: string | undefined) {
|
|
15
|
+
return (node: HTMLSpanElement) => {
|
|
16
|
+
if (previewColor) {
|
|
17
|
+
node.style.setProperty('--dry-option-picker-preview-bg', previewColor);
|
|
18
|
+
} else {
|
|
19
|
+
node.style.removeProperty('--dry-option-picker-preview-bg');
|
|
20
|
+
}
|
|
21
|
+
};
|
|
22
|
+
}
|
|
23
|
+
</script>
|
|
24
|
+
|
|
25
|
+
<span
|
|
26
|
+
{@attach attachPreviewVars(color)}
|
|
27
|
+
data-option-picker-preview
|
|
28
|
+
data-option-picker-preview-shape={shape}
|
|
29
|
+
data-variant={variant !== 'default' ? variant : undefined}
|
|
30
|
+
{...rest}
|
|
31
|
+
>
|
|
32
|
+
{@render children?.()}
|
|
33
|
+
</span>
|
|
34
|
+
|
|
35
|
+
<style>
|
|
36
|
+
[data-option-picker-preview] {
|
|
37
|
+
display: inline-grid;
|
|
38
|
+
grid-column: var(--dry-option-picker-preview-column, 1);
|
|
39
|
+
grid-row: var(--dry-option-picker-preview-row, 1 / span 3);
|
|
40
|
+
place-items: center;
|
|
41
|
+
align-self: center;
|
|
42
|
+
block-size: var(--dry-option-picker-preview-size, 2.25rem);
|
|
43
|
+
aspect-ratio: 1;
|
|
44
|
+
padding: var(--dry-option-picker-preview-padding, 0);
|
|
45
|
+
border: 1px solid var(--dry-option-picker-preview-border, var(--dry-color-stroke-weak));
|
|
46
|
+
border-radius: var(--dry-option-picker-preview-radius, var(--dry-radius-md));
|
|
47
|
+
background: var(
|
|
48
|
+
--dry-option-picker-preview-bg,
|
|
49
|
+
color-mix(in srgb, var(--dry-color-fill-weak) 72%, var(--dry-color-bg-base) 28%)
|
|
50
|
+
);
|
|
51
|
+
color: var(--dry-option-picker-preview-color, var(--dry-color-text-strong));
|
|
52
|
+
box-shadow: var(--dry-option-picker-preview-shadow, none);
|
|
53
|
+
overflow: hidden;
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
[data-option-picker-preview-shape='circle'] {
|
|
57
|
+
border-radius: 999px;
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
[data-option-picker-preview-shape='square'] {
|
|
61
|
+
border-radius: var(--dry-radius-sm);
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
[data-option-picker-preview-shape='pill'] {
|
|
65
|
+
border-radius: 999px;
|
|
66
|
+
padding-inline: var(--dry-space-3);
|
|
67
|
+
aspect-ratio: auto;
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
[data-option-picker-preview][data-variant='preset'] {
|
|
71
|
+
--dry-option-picker-preview-color: white;
|
|
72
|
+
--dry-option-picker-preview-border: color-mix(
|
|
73
|
+
in srgb,
|
|
74
|
+
var(--_preset-color) 46%,
|
|
75
|
+
var(--dry-color-stroke-weak) 54%
|
|
76
|
+
);
|
|
77
|
+
--dry-option-picker-preview-size: 2.75rem;
|
|
78
|
+
background: linear-gradient(
|
|
79
|
+
155deg,
|
|
80
|
+
color-mix(in srgb, white 18%, var(--_preset-color) 82%) 0%,
|
|
81
|
+
var(--_preset-color) 58%,
|
|
82
|
+
color-mix(in srgb, black 12%, var(--_preset-color) 88%) 100%
|
|
83
|
+
);
|
|
84
|
+
box-shadow:
|
|
85
|
+
inset 0 1px 0 color-mix(in srgb, white 22%, transparent),
|
|
86
|
+
inset 0 -1px 0 color-mix(in srgb, black 10%, transparent);
|
|
87
|
+
transition: border-radius var(--dry-duration-fast, 100ms) ease;
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
[data-option-picker-preview][data-variant='font'] {
|
|
91
|
+
--dry-option-picker-preview-size: 2.75rem;
|
|
92
|
+
--dry-option-picker-preview-bg: color-mix(
|
|
93
|
+
in srgb,
|
|
94
|
+
var(--dry-color-fill-weak) 58%,
|
|
95
|
+
var(--dry-color-bg-base) 42%
|
|
96
|
+
);
|
|
97
|
+
--dry-option-picker-preview-border: color-mix(
|
|
98
|
+
in srgb,
|
|
99
|
+
var(--dry-color-stroke-weak) 72%,
|
|
100
|
+
transparent
|
|
101
|
+
);
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
[data-option-picker-preview][data-variant='shape'] {
|
|
105
|
+
--dry-option-picker-preview-bg: var(--dry-color-bg-base);
|
|
106
|
+
--dry-option-picker-preview-border: color-mix(
|
|
107
|
+
in srgb,
|
|
108
|
+
var(--dry-color-stroke-strong) 82%,
|
|
109
|
+
transparent
|
|
110
|
+
);
|
|
111
|
+
--dry-option-picker-preview-size: 2rem;
|
|
112
|
+
transition: border-radius var(--dry-duration-fast, 100ms) ease;
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
[data-option-picker-preview][data-variant='preset'][data-shape='sharp'],
|
|
116
|
+
[data-option-picker-preview][data-variant='shape'][data-shape='sharp'] {
|
|
117
|
+
--dry-option-picker-preview-radius: 2px;
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
[data-option-picker-preview][data-variant='preset'][data-shape='soft'],
|
|
121
|
+
[data-option-picker-preview][data-variant='shape'][data-shape='soft'] {
|
|
122
|
+
--dry-option-picker-preview-radius: 6px;
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
[data-option-picker-preview][data-variant='preset'][data-shape='rounded'] {
|
|
126
|
+
--dry-option-picker-preview-radius: 10px;
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
[data-option-picker-preview][data-variant='shape'][data-shape='rounded'] {
|
|
130
|
+
--dry-option-picker-preview-radius: 16px;
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
[data-option-picker-preview][data-variant='preset'][data-shape='pill'],
|
|
134
|
+
[data-option-picker-preview][data-variant='shape'][data-shape='pill'] {
|
|
135
|
+
--dry-option-picker-preview-radius: 9999px;
|
|
136
|
+
}
|
|
137
|
+
</style>
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import type { Snippet } from 'svelte';
|
|
2
|
+
import type { HTMLAttributes } from 'svelte/elements';
|
|
3
|
+
interface Props extends HTMLAttributes<HTMLSpanElement> {
|
|
4
|
+
color?: string;
|
|
5
|
+
shape?: 'circle' | 'rounded' | 'square' | 'pill';
|
|
6
|
+
variant?: 'default' | 'preset' | 'font' | 'shape';
|
|
7
|
+
children?: Snippet;
|
|
8
|
+
}
|
|
9
|
+
declare const OptionPickerPreview: import("svelte").Component<Props, {}, "">;
|
|
10
|
+
type OptionPickerPreview = ReturnType<typeof OptionPickerPreview>;
|
|
11
|
+
export default OptionPickerPreview;
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
import type { Snippet } from 'svelte';
|
|
3
|
+
import type { HTMLAttributes } from 'svelte/elements';
|
|
4
|
+
import { setSelectableTileGroupCtx } from '../option-swatch-group/context.svelte.js';
|
|
5
|
+
|
|
6
|
+
interface Props extends HTMLAttributes<HTMLDivElement> {
|
|
7
|
+
value?: string;
|
|
8
|
+
disabled?: boolean;
|
|
9
|
+
orientation?: 'horizontal' | 'vertical';
|
|
10
|
+
columns?: 1 | 2 | 3 | 4;
|
|
11
|
+
children: Snippet;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
let {
|
|
15
|
+
value = $bindable(''),
|
|
16
|
+
disabled = false,
|
|
17
|
+
orientation = 'horizontal',
|
|
18
|
+
columns,
|
|
19
|
+
class: className,
|
|
20
|
+
children,
|
|
21
|
+
...rest
|
|
22
|
+
}: Props = $props();
|
|
23
|
+
|
|
24
|
+
setSelectableTileGroupCtx({
|
|
25
|
+
get value() {
|
|
26
|
+
return value;
|
|
27
|
+
},
|
|
28
|
+
get disabled() {
|
|
29
|
+
return disabled;
|
|
30
|
+
},
|
|
31
|
+
get orientation() {
|
|
32
|
+
return orientation;
|
|
33
|
+
},
|
|
34
|
+
select(nextValue: string) {
|
|
35
|
+
value = nextValue;
|
|
36
|
+
},
|
|
37
|
+
isSelected(itemValue: string) {
|
|
38
|
+
return value === itemValue;
|
|
39
|
+
}
|
|
40
|
+
});
|
|
41
|
+
</script>
|
|
42
|
+
|
|
43
|
+
<div
|
|
44
|
+
role="radiogroup"
|
|
45
|
+
aria-orientation={orientation}
|
|
46
|
+
data-orientation={orientation}
|
|
47
|
+
data-disabled={disabled || undefined}
|
|
48
|
+
data-columns={columns}
|
|
49
|
+
data-option-picker-root
|
|
50
|
+
class={className}
|
|
51
|
+
{...rest}
|
|
52
|
+
>
|
|
53
|
+
{@render children()}
|
|
54
|
+
</div>
|
|
55
|
+
|
|
56
|
+
<style>
|
|
57
|
+
[data-option-picker-root] {
|
|
58
|
+
display: grid;
|
|
59
|
+
grid-template-columns: repeat(
|
|
60
|
+
auto-fit,
|
|
61
|
+
minmax(var(--dry-option-picker-min-column, 10rem), 1fr)
|
|
62
|
+
);
|
|
63
|
+
gap: var(--dry-option-picker-gap, var(--dry-space-3));
|
|
64
|
+
align-items: stretch;
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
[data-option-picker-root][data-orientation='vertical'] {
|
|
68
|
+
grid-template-columns: 1fr;
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
[data-option-picker-root][data-columns='2'] {
|
|
72
|
+
grid-template-columns: repeat(2, minmax(0, 1fr));
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
[data-option-picker-root][data-columns='3'] {
|
|
76
|
+
grid-template-columns: repeat(3, minmax(0, 1fr));
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
[data-option-picker-root][data-columns='4'] {
|
|
80
|
+
grid-template-columns: repeat(4, minmax(0, 1fr));
|
|
81
|
+
}
|
|
82
|
+
</style>
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import type { Snippet } from 'svelte';
|
|
2
|
+
import type { HTMLAttributes } from 'svelte/elements';
|
|
3
|
+
interface Props extends HTMLAttributes<HTMLDivElement> {
|
|
4
|
+
value?: string;
|
|
5
|
+
disabled?: boolean;
|
|
6
|
+
orientation?: 'horizontal' | 'vertical';
|
|
7
|
+
columns?: 1 | 2 | 3 | 4;
|
|
8
|
+
children: Snippet;
|
|
9
|
+
}
|
|
10
|
+
declare const OptionPickerRoot: import("svelte").Component<Props, {}, "value">;
|
|
11
|
+
type OptionPickerRoot = ReturnType<typeof OptionPickerRoot>;
|
|
12
|
+
export default OptionPickerRoot;
|
|
@@ -1,9 +1,15 @@
|
|
|
1
1
|
import type { Snippet } from 'svelte';
|
|
2
2
|
import type { HTMLAttributes } from 'svelte/elements';
|
|
3
|
-
|
|
4
|
-
export type { SelectableTileGroupItemProps as OptionSwatchGroupItemProps } from '@dryui/primitives';
|
|
3
|
+
import type { SelectableTileGroupItemProps as PrimitiveOptionSwatchGroupItemProps, SelectableTileGroupRootProps as PrimitiveOptionSwatchGroupRootProps } from '@dryui/primitives';
|
|
5
4
|
export type { SelectableTileGroupLabelProps as OptionSwatchGroupLabelProps } from '@dryui/primitives';
|
|
6
5
|
export type { SelectableTileGroupMetaProps as OptionSwatchGroupMetaProps } from '@dryui/primitives';
|
|
6
|
+
export interface OptionSwatchGroupRootProps extends PrimitiveOptionSwatchGroupRootProps {
|
|
7
|
+
columns?: 1 | 2 | 3 | 4;
|
|
8
|
+
}
|
|
9
|
+
export interface OptionSwatchGroupItemProps extends PrimitiveOptionSwatchGroupItemProps {
|
|
10
|
+
size?: 'default' | 'compact';
|
|
11
|
+
unavailable?: boolean;
|
|
12
|
+
}
|
|
7
13
|
export interface OptionSwatchGroupSwatchProps extends HTMLAttributes<HTMLSpanElement> {
|
|
8
14
|
color?: string;
|
|
9
15
|
shape?: 'circle' | 'rounded';
|
|
@@ -8,10 +8,18 @@
|
|
|
8
8
|
value: string;
|
|
9
9
|
disabled?: boolean;
|
|
10
10
|
unavailable?: boolean;
|
|
11
|
+
size?: 'default' | 'compact';
|
|
11
12
|
children: Snippet;
|
|
12
13
|
}
|
|
13
14
|
|
|
14
|
-
let {
|
|
15
|
+
let {
|
|
16
|
+
value,
|
|
17
|
+
disabled = false,
|
|
18
|
+
unavailable = false,
|
|
19
|
+
size = 'default',
|
|
20
|
+
children,
|
|
21
|
+
...rest
|
|
22
|
+
}: Props = $props();
|
|
15
23
|
|
|
16
24
|
const ctx = getSelectableTileGroupCtx();
|
|
17
25
|
const isDisabled = $derived(disabled || unavailable || ctx.disabled);
|
|
@@ -55,22 +63,152 @@
|
|
|
55
63
|
}
|
|
56
64
|
</script>
|
|
57
65
|
|
|
58
|
-
<
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
role="radio"
|
|
62
|
-
aria-checked={isSelected}
|
|
63
|
-
disabled={isDisabled}
|
|
64
|
-
data-option-swatch-group-item
|
|
66
|
+
<span
|
|
67
|
+
class="root"
|
|
68
|
+
data-size={size !== 'default' ? size : undefined}
|
|
65
69
|
data-state={isSelected ? 'checked' : 'unchecked'}
|
|
70
|
+
data-selected={isSelected ? '' : undefined}
|
|
71
|
+
data-disabled={isDisabled || undefined}
|
|
66
72
|
data-unavailable={unavailable || undefined}
|
|
67
|
-
data-value={value}
|
|
68
|
-
tabindex={isSelected ? 0 : -1}
|
|
69
|
-
{...rest}
|
|
70
|
-
onclick={() => {
|
|
71
|
-
if (!isDisabled) ctx.select(value);
|
|
72
|
-
}}
|
|
73
|
-
onkeydown={handleKeydown}
|
|
74
73
|
>
|
|
75
|
-
|
|
76
|
-
|
|
74
|
+
<Button
|
|
75
|
+
variant="bare"
|
|
76
|
+
type="button"
|
|
77
|
+
role="radio"
|
|
78
|
+
aria-checked={isSelected}
|
|
79
|
+
disabled={isDisabled}
|
|
80
|
+
data-option-swatch-group-item
|
|
81
|
+
data-state={isSelected ? 'checked' : 'unchecked'}
|
|
82
|
+
data-selected={isSelected ? '' : undefined}
|
|
83
|
+
data-unavailable={unavailable || undefined}
|
|
84
|
+
data-value={value}
|
|
85
|
+
tabindex={isSelected ? 0 : -1}
|
|
86
|
+
{...rest}
|
|
87
|
+
onclick={() => {
|
|
88
|
+
if (!isDisabled) ctx.select(value);
|
|
89
|
+
}}
|
|
90
|
+
onkeydown={handleKeydown}
|
|
91
|
+
>
|
|
92
|
+
<span class="content">
|
|
93
|
+
{@render children()}
|
|
94
|
+
</span>
|
|
95
|
+
</Button>
|
|
96
|
+
</span>
|
|
97
|
+
|
|
98
|
+
<style>
|
|
99
|
+
.root {
|
|
100
|
+
--_swatch-item-selected-bg: var(
|
|
101
|
+
--dry-option-swatch-group-selected-bg,
|
|
102
|
+
color-mix(in srgb, var(--dry-color-fill-selected) 12%, var(--dry-color-bg-raised) 88%)
|
|
103
|
+
);
|
|
104
|
+
--_swatch-item-selected-bg-hover: var(
|
|
105
|
+
--dry-option-swatch-group-selected-bg-hover,
|
|
106
|
+
color-mix(in srgb, var(--dry-color-fill-selected) 16%, var(--dry-color-bg-raised) 84%)
|
|
107
|
+
);
|
|
108
|
+
--_swatch-item-selected-border: var(
|
|
109
|
+
--dry-option-swatch-group-selected-border,
|
|
110
|
+
var(--dry-color-stroke-selected)
|
|
111
|
+
);
|
|
112
|
+
|
|
113
|
+
display: grid;
|
|
114
|
+
background: var(--dry-option-swatch-group-bg, var(--dry-color-bg-base));
|
|
115
|
+
border: 1px solid var(--dry-option-swatch-group-border, var(--dry-color-stroke-weak));
|
|
116
|
+
border-radius: var(--dry-option-swatch-group-radius, var(--dry-radius-lg));
|
|
117
|
+
box-shadow: var(--dry-option-swatch-group-shadow, none);
|
|
118
|
+
transition:
|
|
119
|
+
background var(--dry-duration-fast, 100ms) ease,
|
|
120
|
+
border-color var(--dry-duration-fast, 100ms) ease,
|
|
121
|
+
box-shadow var(--dry-duration-fast, 100ms) ease,
|
|
122
|
+
transform var(--dry-duration-fast, 100ms) ease;
|
|
123
|
+
|
|
124
|
+
--dry-btn-bg: transparent;
|
|
125
|
+
--dry-btn-border: transparent;
|
|
126
|
+
--dry-btn-color: var(--dry-option-swatch-group-color, var(--dry-color-text-strong));
|
|
127
|
+
--dry-btn-padding-x: 0;
|
|
128
|
+
--dry-btn-padding-y: 0;
|
|
129
|
+
--dry-btn-radius: var(--dry-option-swatch-group-radius, var(--dry-radius-lg));
|
|
130
|
+
--dry-btn-justify: stretch;
|
|
131
|
+
--dry-btn-align: stretch;
|
|
132
|
+
--dry-btn-min-height: 0;
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
.root:hover:not([data-disabled]) {
|
|
136
|
+
border-color: color-mix(
|
|
137
|
+
in srgb,
|
|
138
|
+
var(--dry-color-stroke-strong) 72%,
|
|
139
|
+
var(--dry-color-stroke-weak) 28%
|
|
140
|
+
);
|
|
141
|
+
background: var(
|
|
142
|
+
--dry-option-swatch-group-bg-hover,
|
|
143
|
+
color-mix(in srgb, var(--dry-color-bg-raised) 92%, var(--dry-color-fill-selected) 8%)
|
|
144
|
+
);
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
.root[data-state='checked'] {
|
|
148
|
+
border-color: var(--_swatch-item-selected-border);
|
|
149
|
+
background: var(--_swatch-item-selected-bg);
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
.root[data-state='checked']:hover:not([data-disabled]) {
|
|
153
|
+
background: var(--_swatch-item-selected-bg-hover);
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
.root:focus-within {
|
|
157
|
+
outline: 2px solid var(--dry-color-focus-ring);
|
|
158
|
+
outline-offset: 2px;
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
.content {
|
|
162
|
+
display: grid;
|
|
163
|
+
grid-template-columns: auto minmax(0, 1fr);
|
|
164
|
+
align-items: center;
|
|
165
|
+
justify-items: start;
|
|
166
|
+
gap: var(--dry-option-swatch-group-item-gap, var(--dry-space-2_5));
|
|
167
|
+
padding: var(--dry-option-swatch-group-padding-y, var(--dry-space-2))
|
|
168
|
+
var(--dry-option-swatch-group-padding-x, var(--dry-space-2_5));
|
|
169
|
+
min-block-size: var(--dry-option-swatch-group-min-block-size, 3rem);
|
|
170
|
+
text-align: left;
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
.root[data-size='compact'] .content {
|
|
174
|
+
grid-template-columns: auto;
|
|
175
|
+
justify-items: center;
|
|
176
|
+
gap: 0;
|
|
177
|
+
min-block-size: 0;
|
|
178
|
+
padding: var(--dry-option-swatch-group-compact-padding, var(--dry-space-0_5));
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
.root[data-size='compact'] {
|
|
182
|
+
background: transparent;
|
|
183
|
+
border-color: transparent;
|
|
184
|
+
border-radius: 999px;
|
|
185
|
+
box-shadow: none;
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
.root[data-size='compact']:hover:not([data-disabled]) {
|
|
189
|
+
background: color-mix(in srgb, var(--dry-color-fill-selected) 6%, transparent);
|
|
190
|
+
border-color: transparent;
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
.root[data-size='compact'][data-state='checked'] {
|
|
194
|
+
--dry-option-swatch-group-swatch-border: color-mix(
|
|
195
|
+
in srgb,
|
|
196
|
+
var(--_swatch-item-selected-border) 34%,
|
|
197
|
+
var(--dry-color-stroke-weak) 66%
|
|
198
|
+
);
|
|
199
|
+
|
|
200
|
+
background: color-mix(in srgb, var(--dry-color-fill-selected) 6%, transparent);
|
|
201
|
+
border-color: transparent;
|
|
202
|
+
box-shadow: 0 0 0 1px var(--_swatch-item-selected-border);
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
.root[data-size='compact'][data-state='checked']:hover:not([data-disabled]) {
|
|
206
|
+
background: color-mix(in srgb, var(--dry-color-fill-selected) 8%, transparent);
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
.root[data-disabled] {
|
|
210
|
+
opacity: 0.6;
|
|
211
|
+
border-color: var(--dry-color-stroke-disabled);
|
|
212
|
+
box-shadow: none;
|
|
213
|
+
}
|
|
214
|
+
</style>
|
|
@@ -4,6 +4,7 @@ interface Props extends Omit<HTMLButtonAttributes, 'value'> {
|
|
|
4
4
|
value: string;
|
|
5
5
|
disabled?: boolean;
|
|
6
6
|
unavailable?: boolean;
|
|
7
|
+
size?: 'default' | 'compact';
|
|
7
8
|
children: Snippet;
|
|
8
9
|
}
|
|
9
10
|
declare const OptionSwatchGroupItemButton: import("svelte").Component<Props, {}, "">;
|
|
@@ -7,6 +7,7 @@
|
|
|
7
7
|
value?: string;
|
|
8
8
|
disabled?: boolean;
|
|
9
9
|
orientation?: 'horizontal' | 'vertical';
|
|
10
|
+
columns?: 1 | 2 | 3 | 4;
|
|
10
11
|
children: Snippet;
|
|
11
12
|
}
|
|
12
13
|
|
|
@@ -14,6 +15,7 @@
|
|
|
14
15
|
value = $bindable(''),
|
|
15
16
|
disabled = false,
|
|
16
17
|
orientation = 'horizontal',
|
|
18
|
+
columns,
|
|
17
19
|
class: className,
|
|
18
20
|
children,
|
|
19
21
|
...rest
|
|
@@ -43,6 +45,7 @@
|
|
|
43
45
|
aria-orientation={orientation}
|
|
44
46
|
data-orientation={orientation}
|
|
45
47
|
data-disabled={disabled || undefined}
|
|
48
|
+
data-columns={columns}
|
|
46
49
|
data-option-swatch-group-root
|
|
47
50
|
class={className}
|
|
48
51
|
{...rest}
|
|
@@ -53,11 +56,26 @@
|
|
|
53
56
|
<style>
|
|
54
57
|
[data-option-swatch-group-root] {
|
|
55
58
|
display: grid;
|
|
56
|
-
grid-template-columns: repeat(
|
|
57
|
-
|
|
59
|
+
grid-template-columns: repeat(
|
|
60
|
+
auto-fit,
|
|
61
|
+
minmax(var(--dry-option-swatch-group-min-column, 4rem), max-content)
|
|
62
|
+
);
|
|
63
|
+
gap: var(--dry-option-swatch-group-gap, var(--dry-space-3));
|
|
58
64
|
}
|
|
59
65
|
|
|
60
66
|
[data-option-swatch-group-root][data-orientation='vertical'] {
|
|
61
67
|
grid-template-columns: 1fr;
|
|
62
68
|
}
|
|
69
|
+
|
|
70
|
+
[data-option-swatch-group-root][data-columns='2'] {
|
|
71
|
+
grid-template-columns: repeat(2, max-content);
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
[data-option-swatch-group-root][data-columns='3'] {
|
|
75
|
+
grid-template-columns: repeat(3, max-content);
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
[data-option-swatch-group-root][data-columns='4'] {
|
|
79
|
+
grid-template-columns: repeat(4, max-content);
|
|
80
|
+
}
|
|
63
81
|
</style>
|
|
@@ -4,6 +4,7 @@ interface Props extends HTMLAttributes<HTMLDivElement> {
|
|
|
4
4
|
value?: string;
|
|
5
5
|
disabled?: boolean;
|
|
6
6
|
orientation?: 'horizontal' | 'vertical';
|
|
7
|
+
columns?: 1 | 2 | 3 | 4;
|
|
7
8
|
children: Snippet;
|
|
8
9
|
}
|
|
9
10
|
declare const OptionSwatchGroupRoot: import("svelte").Component<Props, {}, "value">;
|
|
@@ -8,17 +8,21 @@
|
|
|
8
8
|
children?: Snippet;
|
|
9
9
|
}
|
|
10
10
|
|
|
11
|
-
let { color, shape = 'circle', class: className,
|
|
11
|
+
let { color, shape = 'circle', class: className, children, ...rest }: Props = $props();
|
|
12
12
|
|
|
13
|
-
function setSwatchChip(
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
13
|
+
function setSwatchChip(swatchColor: string | undefined) {
|
|
14
|
+
return (node: HTMLSpanElement) => {
|
|
15
|
+
if (swatchColor) {
|
|
16
|
+
node.style.setProperty('--dry-option-swatch-chip', swatchColor);
|
|
17
|
+
} else {
|
|
18
|
+
node.style.removeProperty('--dry-option-swatch-chip');
|
|
19
|
+
}
|
|
20
|
+
};
|
|
17
21
|
}
|
|
18
22
|
</script>
|
|
19
23
|
|
|
20
24
|
<span
|
|
21
|
-
{@attach setSwatchChip}
|
|
25
|
+
{@attach setSwatchChip(color)}
|
|
22
26
|
data-option-swatch-group-swatch
|
|
23
27
|
data-option-swatch-group-rounded={shape === 'rounded' || undefined}
|
|
24
28
|
class={className}
|
|
@@ -36,13 +40,10 @@
|
|
|
36
40
|
grid-row: 1 / span 2;
|
|
37
41
|
align-self: center;
|
|
38
42
|
aspect-ratio: 1;
|
|
39
|
-
height: 1.5rem;
|
|
43
|
+
height: var(--dry-option-swatch-group-swatch-size, 1.5rem);
|
|
40
44
|
border-radius: 999px;
|
|
41
|
-
border: 1px solid
|
|
45
|
+
border: 1px solid var(--dry-option-swatch-group-swatch-border, var(--dry-color-stroke-weak));
|
|
42
46
|
background: var(--dry-option-swatch-chip);
|
|
43
|
-
box-shadow:
|
|
44
|
-
inset 0 0 0 1px rgb(255 255 255 / 0.24),
|
|
45
|
-
0 1px 3px rgb(15 23 42 / 0.15);
|
|
46
47
|
}
|
|
47
48
|
|
|
48
49
|
[data-option-swatch-group-rounded] {
|
|
@@ -18,8 +18,7 @@
|
|
|
18
18
|
[data-sidebar-item] {
|
|
19
19
|
position: relative;
|
|
20
20
|
display: grid;
|
|
21
|
-
grid-
|
|
22
|
-
grid-auto-columns: max-content;
|
|
21
|
+
grid-template-columns: max-content minmax(0, 1fr) max-content;
|
|
23
22
|
align-items: center;
|
|
24
23
|
gap: var(--dry-space-3);
|
|
25
24
|
min-height: var(--dry-sidebar-item-height, var(--dry-space-12));
|