sheer-ui 0.4.2 → 0.4.3
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/package.json +1 -1
- package/src/lib/components/avatar/avatar.svelte.ts +34 -37
- package/src/lib/components/avatar/components/avatar-fallback.svelte +9 -6
- package/src/lib/components/avatar/components/avatar-image.svelte +18 -9
- package/src/lib/components/avatar/components/avatar.svelte +20 -16
- package/src/lib/components/checkbox/checkbox.svelte.ts +45 -55
- package/src/lib/components/checkbox/components/checkbox-group-label.svelte +9 -6
- package/src/lib/components/checkbox/components/checkbox-group.svelte +25 -16
- package/src/lib/components/checkbox/components/checkbox.svelte +39 -25
- package/src/lib/components/dialog/components/dialog-close.svelte +13 -8
- package/src/lib/components/dialog/components/dialog-content-headless.svelte +14 -11
- package/src/lib/components/dialog/components/dialog-description.svelte +9 -6
- package/src/lib/components/dialog/components/dialog-overlay.svelte +10 -7
- package/src/lib/components/dialog/components/dialog-title.svelte +12 -7
- package/src/lib/components/dialog/components/dialog-trigger.svelte +12 -7
- package/src/lib/components/dialog/components/dialog.svelte +10 -4
- package/src/lib/components/dialog/components/modal-surface.svelte +11 -8
- package/src/lib/components/dialog/dialog.svelte.ts +73 -61
- package/src/lib/components/drawer/drawer.svelte +8 -3
- package/src/lib/components/link-preview/components/link-preview-content.svelte +15 -8
- package/src/lib/components/link-preview/components/link-preview-trigger.svelte +9 -6
- package/src/lib/components/link-preview/components/link-preview.svelte +19 -11
- package/src/lib/components/link-preview/link-preview.svelte.ts +42 -43
- package/src/lib/components/menu/menu.svelte.ts +20 -1
- package/src/lib/components/meter/components/meter.svelte +18 -9
- package/src/lib/components/meter/meter.svelte.ts +15 -18
- package/src/lib/components/popover/components/popover-close.svelte +9 -6
- package/src/lib/components/popover/components/popover-content.svelte +12 -7
- package/src/lib/components/popover/components/popover-trigger.svelte +21 -10
- package/src/lib/components/popover/components/popover.svelte +9 -8
- package/src/lib/components/popover/popover.svelte.ts +68 -74
- package/src/lib/components/progress/components/progress.svelte +18 -9
- package/src/lib/components/progress/progress.svelte.ts +14 -17
- package/src/lib/components/separator/components/separator.svelte +15 -8
- package/src/lib/components/separator/separator.svelte.ts +12 -15
- package/src/lib/components/sidebar/sidebar-mobile-surface.svelte +8 -4
- package/src/lib/components/toggle/components/toggle.svelte +19 -14
- package/src/lib/components/toggle/toggle.svelte.ts +15 -20
- package/src/lib/components/tooltip/components/tooltip-content.svelte +15 -8
- package/src/lib/components/tooltip/components/tooltip-provider.svelte +18 -7
- package/src/lib/components/tooltip/components/tooltip-trigger.svelte +21 -10
- package/src/lib/components/tooltip/components/tooltip.svelte +34 -21
- package/src/lib/components/tooltip/tooltip.svelte.ts +96 -99
- package/src/lib/internal/escape-layer/use-escape-layer.svelte.ts +13 -29
- package/src/lib/internal/group-value.svelte.ts +11 -10
- package/src/lib/internal/native-popover.svelte.ts +6 -6
package/package.json
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import { createContext, untrack } from 'svelte';
|
|
2
|
-
import { DOMContext,
|
|
2
|
+
import { DOMContext, attachRef } from '../../internal/tools/index.js';
|
|
3
3
|
import type { HTMLImgAttributes } from 'svelte/elements';
|
|
4
4
|
import type { AvatarImageLoadingStatus } from './types.js';
|
|
5
|
-
import type { RefAttachment,
|
|
5
|
+
import type { RefAttachment, RefOpts } from '../../internal/types.js';
|
|
6
6
|
import { createBitsAttrs } from '../../internal/attrs.js';
|
|
7
7
|
|
|
8
8
|
const avatarAttrs = createBitsAttrs({
|
|
@@ -14,9 +14,9 @@ type CrossOrigin = HTMLImgAttributes['crossorigin'];
|
|
|
14
14
|
type ReferrerPolicy = HTMLImgAttributes['referrerpolicy'];
|
|
15
15
|
type AvatarImageSrc = string | null | undefined;
|
|
16
16
|
|
|
17
|
-
interface AvatarRootStateOpts extends
|
|
18
|
-
delayMs:
|
|
19
|
-
loadingStatus:
|
|
17
|
+
interface AvatarRootStateOpts extends RefOpts {
|
|
18
|
+
readonly delayMs: number;
|
|
19
|
+
loadingStatus: AvatarImageLoadingStatus;
|
|
20
20
|
}
|
|
21
21
|
|
|
22
22
|
const [getAvatarRoot, setAvatarRoot] = createContext<AvatarRootState>();
|
|
@@ -32,13 +32,13 @@ export class AvatarRootState {
|
|
|
32
32
|
|
|
33
33
|
constructor(opts: AvatarRootStateOpts) {
|
|
34
34
|
this.opts = opts;
|
|
35
|
-
this.domContext = new DOMContext(
|
|
35
|
+
this.domContext = new DOMContext(() => opts.ref);
|
|
36
36
|
this.loadImage = this.loadImage.bind(this);
|
|
37
|
-
this.attachment = attachRef(
|
|
37
|
+
this.attachment = attachRef<HTMLElement>((v) => (opts.ref = v));
|
|
38
38
|
}
|
|
39
39
|
|
|
40
40
|
loadImage(src: string, crossorigin?: CrossOrigin, referrerPolicy?: ReferrerPolicy) {
|
|
41
|
-
if (this.opts.loadingStatus
|
|
41
|
+
if (this.opts.loadingStatus === 'loaded') return;
|
|
42
42
|
let imageTimerId: number;
|
|
43
43
|
const image = new Image();
|
|
44
44
|
|
|
@@ -46,14 +46,14 @@ export class AvatarRootState {
|
|
|
46
46
|
if (crossorigin !== undefined) image.crossOrigin = crossorigin;
|
|
47
47
|
if (referrerPolicy) image.referrerPolicy = referrerPolicy;
|
|
48
48
|
|
|
49
|
-
this.opts.loadingStatus
|
|
49
|
+
this.opts.loadingStatus = 'loading';
|
|
50
50
|
image.onload = () => {
|
|
51
51
|
imageTimerId = this.domContext.setTimeout(() => {
|
|
52
|
-
this.opts.loadingStatus
|
|
53
|
-
}, this.opts.delayMs
|
|
52
|
+
this.opts.loadingStatus = 'loaded';
|
|
53
|
+
}, this.opts.delayMs);
|
|
54
54
|
};
|
|
55
55
|
image.onerror = () => {
|
|
56
|
-
this.opts.loadingStatus
|
|
56
|
+
this.opts.loadingStatus = 'error';
|
|
57
57
|
};
|
|
58
58
|
return () => {
|
|
59
59
|
if (!imageTimerId) return;
|
|
@@ -64,22 +64,19 @@ export class AvatarRootState {
|
|
|
64
64
|
props = $derived.by(
|
|
65
65
|
() =>
|
|
66
66
|
({
|
|
67
|
-
id: this.opts.id
|
|
67
|
+
id: this.opts.id,
|
|
68
68
|
[avatarAttrs.root]: '',
|
|
69
|
-
'data-status': this.opts.loadingStatus
|
|
69
|
+
'data-status': this.opts.loadingStatus,
|
|
70
70
|
...this.attachment,
|
|
71
71
|
}) as const,
|
|
72
72
|
);
|
|
73
73
|
}
|
|
74
74
|
|
|
75
|
-
interface AvatarImageStateOpts
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
crossOrigin: CrossOrigin;
|
|
81
|
-
referrerPolicy: ReferrerPolicy;
|
|
82
|
-
}> {}
|
|
75
|
+
interface AvatarImageStateOpts extends RefOpts {
|
|
76
|
+
readonly src: AvatarImageSrc;
|
|
77
|
+
readonly crossOrigin: CrossOrigin;
|
|
78
|
+
readonly referrerPolicy: ReferrerPolicy;
|
|
79
|
+
}
|
|
83
80
|
|
|
84
81
|
export class AvatarImageState {
|
|
85
82
|
static create(opts: AvatarImageStateOpts) {
|
|
@@ -92,17 +89,17 @@ export class AvatarImageState {
|
|
|
92
89
|
constructor(opts: AvatarImageStateOpts, root: AvatarRootState) {
|
|
93
90
|
this.opts = opts;
|
|
94
91
|
this.root = root;
|
|
95
|
-
this.attachment = attachRef(
|
|
92
|
+
this.attachment = attachRef<HTMLElement>((v) => (opts.ref = v));
|
|
96
93
|
|
|
97
94
|
$effect.pre(() => {
|
|
98
|
-
const src = this.opts.src
|
|
99
|
-
const crossOrigin = this.opts.crossOrigin
|
|
95
|
+
const src = this.opts.src;
|
|
96
|
+
const crossOrigin = this.opts.crossOrigin;
|
|
100
97
|
untrack(() => {
|
|
101
98
|
if (!src) {
|
|
102
|
-
this.root.opts.loadingStatus
|
|
99
|
+
this.root.opts.loadingStatus = 'error';
|
|
103
100
|
return;
|
|
104
101
|
}
|
|
105
|
-
this.root.loadImage(src, crossOrigin, this.opts.referrerPolicy
|
|
102
|
+
this.root.loadImage(src, crossOrigin, this.opts.referrerPolicy);
|
|
106
103
|
});
|
|
107
104
|
});
|
|
108
105
|
}
|
|
@@ -110,21 +107,21 @@ export class AvatarImageState {
|
|
|
110
107
|
readonly props = $derived.by(
|
|
111
108
|
() =>
|
|
112
109
|
({
|
|
113
|
-
id: this.opts.id
|
|
110
|
+
id: this.opts.id,
|
|
114
111
|
style: {
|
|
115
|
-
display: this.root.opts.loadingStatus
|
|
112
|
+
display: this.root.opts.loadingStatus === 'loaded' ? 'block' : 'none',
|
|
116
113
|
},
|
|
117
|
-
'data-status': this.root.opts.loadingStatus
|
|
114
|
+
'data-status': this.root.opts.loadingStatus,
|
|
118
115
|
[avatarAttrs.image]: '',
|
|
119
|
-
src: this.opts.src
|
|
120
|
-
crossorigin: this.opts.crossOrigin
|
|
121
|
-
referrerpolicy: this.opts.referrerPolicy
|
|
116
|
+
src: this.opts.src,
|
|
117
|
+
crossorigin: this.opts.crossOrigin,
|
|
118
|
+
referrerpolicy: this.opts.referrerPolicy,
|
|
122
119
|
...this.attachment,
|
|
123
120
|
}) as const,
|
|
124
121
|
);
|
|
125
122
|
}
|
|
126
123
|
|
|
127
|
-
interface AvatarFallbackStateOpts extends
|
|
124
|
+
interface AvatarFallbackStateOpts extends RefOpts {}
|
|
128
125
|
export class AvatarFallbackState {
|
|
129
126
|
static create(opts: AvatarFallbackStateOpts) {
|
|
130
127
|
return new AvatarFallbackState(opts, getAvatarRoot());
|
|
@@ -137,16 +134,16 @@ export class AvatarFallbackState {
|
|
|
137
134
|
constructor(opts: AvatarFallbackStateOpts, root: AvatarRootState) {
|
|
138
135
|
this.opts = opts;
|
|
139
136
|
this.root = root;
|
|
140
|
-
this.attachment = attachRef(
|
|
137
|
+
this.attachment = attachRef<HTMLElement>((v) => (opts.ref = v));
|
|
141
138
|
}
|
|
142
139
|
|
|
143
|
-
readonly style = $derived.by(() => (this.root.opts.loadingStatus
|
|
140
|
+
readonly style = $derived.by(() => (this.root.opts.loadingStatus === 'loaded' ? { display: 'none' } : undefined));
|
|
144
141
|
|
|
145
142
|
readonly props = $derived.by(
|
|
146
143
|
() =>
|
|
147
144
|
({
|
|
148
145
|
style: this.style,
|
|
149
|
-
'data-status': this.root.opts.loadingStatus
|
|
146
|
+
'data-status': this.root.opts.loadingStatus,
|
|
150
147
|
[avatarAttrs.fallback]: '',
|
|
151
148
|
...this.attachment,
|
|
152
149
|
}) as const,
|
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
<script lang="ts">
|
|
2
|
-
import { boxWith } from '../../../internal/tools/index.js';
|
|
3
2
|
import { mergeProps } from '../../../internal/merge-props.js';
|
|
4
3
|
import type { AvatarFallbackProps } from '../types.js';
|
|
5
4
|
import { AvatarFallbackState } from '../avatar.svelte.js';
|
|
@@ -10,11 +9,15 @@
|
|
|
10
9
|
let { children, child, id = createId(uid), ref = $bindable(null), ...restProps }: AvatarFallbackProps = $props();
|
|
11
10
|
|
|
12
11
|
const fallbackState = AvatarFallbackState.create({
|
|
13
|
-
id
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
12
|
+
get id() {
|
|
13
|
+
return id;
|
|
14
|
+
},
|
|
15
|
+
get ref() {
|
|
16
|
+
return ref;
|
|
17
|
+
},
|
|
18
|
+
set ref(v) {
|
|
19
|
+
ref = v;
|
|
20
|
+
},
|
|
18
21
|
});
|
|
19
22
|
|
|
20
23
|
const mergedProps = $derived(
|
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
<script lang="ts">
|
|
2
|
-
import { boxWith } from '../../../internal/tools/index.js';
|
|
3
2
|
import { mergeProps } from '../../../internal/merge-props.js';
|
|
4
3
|
import type { AvatarImageProps } from '../types.js';
|
|
5
4
|
import { AvatarImageState } from '../avatar.svelte.js';
|
|
@@ -18,14 +17,24 @@
|
|
|
18
17
|
}: AvatarImageProps = $props();
|
|
19
18
|
|
|
20
19
|
const imageState = AvatarImageState.create({
|
|
21
|
-
src
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
crossOrigin
|
|
28
|
-
|
|
20
|
+
get src() {
|
|
21
|
+
return src;
|
|
22
|
+
},
|
|
23
|
+
get id() {
|
|
24
|
+
return id;
|
|
25
|
+
},
|
|
26
|
+
get crossOrigin() {
|
|
27
|
+
return crossorigin;
|
|
28
|
+
},
|
|
29
|
+
get referrerPolicy() {
|
|
30
|
+
return referrerpolicy;
|
|
31
|
+
},
|
|
32
|
+
get ref() {
|
|
33
|
+
return ref;
|
|
34
|
+
},
|
|
35
|
+
set ref(v) {
|
|
36
|
+
ref = v;
|
|
37
|
+
},
|
|
29
38
|
});
|
|
30
39
|
|
|
31
40
|
const mergedProps = $derived(
|
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
<script lang="ts">
|
|
2
|
-
import { boxWith } from '../../../internal/tools/index.js';
|
|
3
2
|
import { mergeProps } from '../../../internal/merge-props.js';
|
|
4
3
|
import type { AvatarRootProps } from '../types.js';
|
|
5
4
|
import { AvatarRootState } from '../avatar.svelte.js';
|
|
@@ -19,21 +18,26 @@
|
|
|
19
18
|
}: AvatarRootProps = $props();
|
|
20
19
|
|
|
21
20
|
const rootState = AvatarRootState.create({
|
|
22
|
-
delayMs
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
)
|
|
21
|
+
get delayMs() {
|
|
22
|
+
return delayMs;
|
|
23
|
+
},
|
|
24
|
+
get loadingStatus() {
|
|
25
|
+
return loadingStatus;
|
|
26
|
+
},
|
|
27
|
+
set loadingStatus(v) {
|
|
28
|
+
if (loadingStatus === v) return;
|
|
29
|
+
loadingStatus = v;
|
|
30
|
+
onLoadingStatusChange?.(v);
|
|
31
|
+
},
|
|
32
|
+
get id() {
|
|
33
|
+
return id;
|
|
34
|
+
},
|
|
35
|
+
get ref() {
|
|
36
|
+
return ref;
|
|
37
|
+
},
|
|
38
|
+
set ref(v) {
|
|
39
|
+
ref = v;
|
|
40
|
+
},
|
|
37
41
|
});
|
|
38
42
|
|
|
39
43
|
const mergedProps = $derived(
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import { createContext } from 'svelte';
|
|
2
2
|
import { joinGroup } from '../../internal/group-value.svelte.js';
|
|
3
|
-
import { attachRef
|
|
3
|
+
import { attachRef } from '../../internal/tools/index.js';
|
|
4
4
|
import type { HTMLButtonAttributes } from 'svelte/elements';
|
|
5
|
-
import type { BitsKeyboardEvent, BitsMouseEvent, RefAttachment,
|
|
5
|
+
import type { BitsKeyboardEvent, BitsMouseEvent, RefAttachment, RefOpts } from '../../internal/types.js';
|
|
6
6
|
import { boolToStr, createBitsAttrs, getAriaChecked, boolToEmptyStrOrUndef } from '../../internal/attrs.js';
|
|
7
7
|
import { kbd } from '../../internal/kbd.js';
|
|
8
8
|
|
|
@@ -11,17 +11,12 @@ const checkboxAttrs = createBitsAttrs({
|
|
|
11
11
|
parts: ['root', 'group', 'group-label', 'input'],
|
|
12
12
|
});
|
|
13
13
|
|
|
14
|
-
interface CheckboxGroupStateOpts
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
readonly: boolean;
|
|
21
|
-
}>,
|
|
22
|
-
WritableBoxedValues<{
|
|
23
|
-
value: string[];
|
|
24
|
-
}> {}
|
|
14
|
+
interface CheckboxGroupStateOpts extends RefOpts {
|
|
15
|
+
readonly disabled: boolean;
|
|
16
|
+
readonly required: boolean;
|
|
17
|
+
readonly readonly: boolean;
|
|
18
|
+
value: string[];
|
|
19
|
+
}
|
|
25
20
|
|
|
26
21
|
const [getCheckboxGroup, setCheckboxGroup, hasCheckboxGroup] = createContext<CheckboxGroupState>();
|
|
27
22
|
|
|
@@ -33,27 +28,27 @@ export class CheckboxGroupState {
|
|
|
33
28
|
readonly opts: CheckboxGroupStateOpts;
|
|
34
29
|
readonly attachment: RefAttachment;
|
|
35
30
|
labelState = $state<CheckboxGroupLabelState | null>(null);
|
|
36
|
-
readonly labelId = $derived.by(() => this.labelState?.opts.id
|
|
31
|
+
readonly labelId = $derived.by(() => this.labelState?.opts.id);
|
|
37
32
|
|
|
38
33
|
constructor(opts: CheckboxGroupStateOpts) {
|
|
39
34
|
this.opts = opts;
|
|
40
|
-
this.attachment = attachRef(
|
|
35
|
+
this.attachment = attachRef<HTMLElement>((v) => (opts.ref = v));
|
|
41
36
|
}
|
|
42
37
|
|
|
43
38
|
readonly props = $derived.by(
|
|
44
39
|
() =>
|
|
45
40
|
({
|
|
46
|
-
id: this.opts.id
|
|
41
|
+
id: this.opts.id,
|
|
47
42
|
role: 'group',
|
|
48
43
|
'aria-labelledby': this.labelId,
|
|
49
|
-
'data-disabled': boolToEmptyStrOrUndef(this.opts.disabled
|
|
44
|
+
'data-disabled': boolToEmptyStrOrUndef(this.opts.disabled),
|
|
50
45
|
[checkboxAttrs.group]: '',
|
|
51
46
|
...this.attachment,
|
|
52
47
|
}) as const,
|
|
53
48
|
);
|
|
54
49
|
}
|
|
55
50
|
|
|
56
|
-
interface CheckboxGroupLabelStateOpts extends
|
|
51
|
+
interface CheckboxGroupLabelStateOpts extends RefOpts {}
|
|
57
52
|
|
|
58
53
|
export class CheckboxGroupLabelState {
|
|
59
54
|
static create(opts: CheckboxGroupLabelStateOpts) {
|
|
@@ -68,14 +63,14 @@ export class CheckboxGroupLabelState {
|
|
|
68
63
|
this.opts = opts;
|
|
69
64
|
this.group = group;
|
|
70
65
|
this.group.labelState = this;
|
|
71
|
-
this.attachment = attachRef(
|
|
66
|
+
this.attachment = attachRef<HTMLElement>((v) => (opts.ref = v));
|
|
72
67
|
}
|
|
73
68
|
|
|
74
69
|
readonly props = $derived.by(
|
|
75
70
|
() =>
|
|
76
71
|
({
|
|
77
|
-
id: this.opts.id
|
|
78
|
-
'data-disabled': boolToEmptyStrOrUndef(this.group.opts.disabled
|
|
72
|
+
id: this.opts.id,
|
|
73
|
+
'data-disabled': boolToEmptyStrOrUndef(this.group.opts.disabled),
|
|
79
74
|
[checkboxAttrs['group-label']]: '',
|
|
80
75
|
...this.attachment,
|
|
81
76
|
}) as const,
|
|
@@ -84,20 +79,15 @@ export class CheckboxGroupLabelState {
|
|
|
84
79
|
|
|
85
80
|
const [, setCheckboxRoot] = createContext<CheckboxRootState>();
|
|
86
81
|
|
|
87
|
-
interface CheckboxRootStateOpts
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
}>,
|
|
97
|
-
WritableBoxedValues<{
|
|
98
|
-
checked: boolean;
|
|
99
|
-
indeterminate: boolean;
|
|
100
|
-
}> {}
|
|
82
|
+
interface CheckboxRootStateOpts extends RefOpts {
|
|
83
|
+
readonly disabled: boolean;
|
|
84
|
+
readonly required: boolean;
|
|
85
|
+
readonly readonly: boolean;
|
|
86
|
+
readonly value: string | undefined;
|
|
87
|
+
readonly type: HTMLButtonAttributes['type'];
|
|
88
|
+
checked: boolean;
|
|
89
|
+
indeterminate: boolean;
|
|
90
|
+
}
|
|
101
91
|
|
|
102
92
|
export class CheckboxRootState {
|
|
103
93
|
static create(opts: CheckboxRootStateOpts) {
|
|
@@ -109,33 +99,33 @@ export class CheckboxRootState {
|
|
|
109
99
|
readonly group: CheckboxGroupState | null;
|
|
110
100
|
readonly groupChecked: () => boolean | undefined;
|
|
111
101
|
readonly trueRequired = $derived.by(() => {
|
|
112
|
-
if (this.group && this.group.opts.required
|
|
113
|
-
return this.opts.required
|
|
102
|
+
if (this.group && this.group.opts.required) return true;
|
|
103
|
+
return this.opts.required;
|
|
114
104
|
});
|
|
115
105
|
readonly trueDisabled = $derived.by(() => {
|
|
116
|
-
if (this.group && this.group.opts.disabled
|
|
117
|
-
return this.opts.disabled
|
|
106
|
+
if (this.group && this.group.opts.disabled) return true;
|
|
107
|
+
return this.opts.disabled;
|
|
118
108
|
});
|
|
119
109
|
readonly trueReadonly = $derived.by(() => {
|
|
120
|
-
if (this.group && this.group.opts.readonly
|
|
121
|
-
return this.opts.readonly
|
|
110
|
+
if (this.group && this.group.opts.readonly) return true;
|
|
111
|
+
return this.opts.readonly;
|
|
122
112
|
});
|
|
123
113
|
readonly attachment: RefAttachment;
|
|
124
114
|
|
|
125
115
|
constructor(opts: CheckboxRootStateOpts, group: CheckboxGroupState | null) {
|
|
126
116
|
this.opts = opts;
|
|
127
117
|
this.group = group;
|
|
128
|
-
this.attachment = attachRef(
|
|
118
|
+
this.attachment = attachRef<HTMLElement>((v) => (opts.ref = v));
|
|
129
119
|
this.onkeydown = this.onkeydown.bind(this);
|
|
130
120
|
this.onclick = this.onclick.bind(this);
|
|
131
|
-
this.groupChecked = joinGroup(group, opts);
|
|
121
|
+
this.groupChecked = joinGroup(group?.opts ?? null, opts);
|
|
132
122
|
}
|
|
133
123
|
|
|
134
124
|
onkeydown(e: BitsKeyboardEvent) {
|
|
135
125
|
if (this.trueDisabled || this.trueReadonly) return;
|
|
136
126
|
if (e.key === kbd.ENTER) {
|
|
137
127
|
e.preventDefault();
|
|
138
|
-
if (this.opts.type
|
|
128
|
+
if (this.opts.type === 'submit') {
|
|
139
129
|
const form = e.currentTarget.closest('form');
|
|
140
130
|
form?.requestSubmit();
|
|
141
131
|
}
|
|
@@ -148,17 +138,17 @@ export class CheckboxRootState {
|
|
|
148
138
|
}
|
|
149
139
|
|
|
150
140
|
#toggle() {
|
|
151
|
-
if (this.opts.indeterminate
|
|
152
|
-
this.opts.indeterminate
|
|
153
|
-
this.opts.checked
|
|
141
|
+
if (this.opts.indeterminate) {
|
|
142
|
+
this.opts.indeterminate = false;
|
|
143
|
+
this.opts.checked = true;
|
|
154
144
|
} else {
|
|
155
|
-
this.opts.checked
|
|
145
|
+
this.opts.checked = !this.opts.checked;
|
|
156
146
|
}
|
|
157
147
|
}
|
|
158
148
|
|
|
159
149
|
onclick(e: BitsMouseEvent) {
|
|
160
150
|
if (this.trueDisabled || this.trueReadonly) return;
|
|
161
|
-
if (this.opts.type
|
|
151
|
+
if (this.opts.type === 'submit') {
|
|
162
152
|
this.#toggle();
|
|
163
153
|
return;
|
|
164
154
|
}
|
|
@@ -167,23 +157,23 @@ export class CheckboxRootState {
|
|
|
167
157
|
}
|
|
168
158
|
|
|
169
159
|
readonly snippetProps = $derived.by(() => ({
|
|
170
|
-
checked: this.opts.checked
|
|
171
|
-
indeterminate: this.opts.indeterminate
|
|
160
|
+
checked: this.opts.checked,
|
|
161
|
+
indeterminate: this.opts.indeterminate,
|
|
172
162
|
}));
|
|
173
163
|
|
|
174
164
|
readonly props = $derived.by(
|
|
175
165
|
() =>
|
|
176
166
|
({
|
|
177
|
-
id: this.opts.id
|
|
167
|
+
id: this.opts.id,
|
|
178
168
|
role: 'checkbox',
|
|
179
|
-
type: this.opts.type
|
|
169
|
+
type: this.opts.type,
|
|
180
170
|
disabled: this.trueDisabled,
|
|
181
|
-
'aria-checked': getAriaChecked(this.opts.checked
|
|
171
|
+
'aria-checked': getAriaChecked(this.opts.checked, this.opts.indeterminate),
|
|
182
172
|
'aria-required': boolToStr(this.trueRequired),
|
|
183
173
|
'aria-readonly': boolToStr(this.trueReadonly),
|
|
184
174
|
'data-disabled': boolToEmptyStrOrUndef(this.trueDisabled),
|
|
185
175
|
'data-readonly': boolToEmptyStrOrUndef(this.trueReadonly),
|
|
186
|
-
'data-state': getCheckboxDataState(this.opts.checked
|
|
176
|
+
'data-state': getCheckboxDataState(this.opts.checked, this.opts.indeterminate),
|
|
187
177
|
[checkboxAttrs.root]: '',
|
|
188
178
|
//
|
|
189
179
|
onclick: this.onclick,
|
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
<script lang="ts">
|
|
2
|
-
import { boxWith } from '../../../internal/tools/index.js';
|
|
3
2
|
import { mergeProps } from '../../../internal/merge-props.js';
|
|
4
3
|
import type { CheckboxGroupLabelProps } from '../types.js';
|
|
5
4
|
import { CheckboxGroupLabelState } from '../checkbox.svelte.js';
|
|
@@ -10,11 +9,15 @@
|
|
|
10
9
|
let { ref = $bindable(null), id = createId(uid), child, children, ...restProps }: CheckboxGroupLabelProps = $props();
|
|
11
10
|
|
|
12
11
|
const labelState = CheckboxGroupLabelState.create({
|
|
13
|
-
id
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
12
|
+
get id() {
|
|
13
|
+
return id;
|
|
14
|
+
},
|
|
15
|
+
get ref() {
|
|
16
|
+
return ref;
|
|
17
|
+
},
|
|
18
|
+
set ref(v) {
|
|
19
|
+
ref = v;
|
|
20
|
+
},
|
|
18
21
|
});
|
|
19
22
|
|
|
20
23
|
const mergedProps = $derived(mergeProps(restProps, labelState.props));
|
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
<script lang="ts">
|
|
2
|
-
import { boxWith } from '../../../internal/tools/index.js';
|
|
3
2
|
import { mergeProps } from '../../../internal/merge-props.js';
|
|
4
3
|
import type { CheckboxGroupProps } from '../types.js';
|
|
5
4
|
import { CheckboxGroupState } from '../checkbox.svelte.js';
|
|
@@ -21,21 +20,31 @@
|
|
|
21
20
|
}: CheckboxGroupProps = $props();
|
|
22
21
|
|
|
23
22
|
const groupState = CheckboxGroupState.create({
|
|
24
|
-
id
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
required
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
(
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
23
|
+
get id() {
|
|
24
|
+
return id;
|
|
25
|
+
},
|
|
26
|
+
get disabled() {
|
|
27
|
+
return Boolean(disabled);
|
|
28
|
+
},
|
|
29
|
+
get required() {
|
|
30
|
+
return Boolean(required);
|
|
31
|
+
},
|
|
32
|
+
get readonly() {
|
|
33
|
+
return Boolean(readonly);
|
|
34
|
+
},
|
|
35
|
+
get value() {
|
|
36
|
+
return $state.snapshot(value);
|
|
37
|
+
},
|
|
38
|
+
set value(v) {
|
|
39
|
+
value = $state.snapshot(v);
|
|
40
|
+
onValueChange(v);
|
|
41
|
+
},
|
|
42
|
+
get ref() {
|
|
43
|
+
return ref;
|
|
44
|
+
},
|
|
45
|
+
set ref(v) {
|
|
46
|
+
ref = v;
|
|
47
|
+
},
|
|
39
48
|
});
|
|
40
49
|
|
|
41
50
|
const mergedProps = $derived(mergeProps(restProps, groupState.props));
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
// Checkbox (button): controlled / headless. A <button role=checkbox> for table
|
|
3
3
|
// select-all, JS-owned state, and Checkbox.Group. It does NOT submit in a form;
|
|
4
4
|
// use `CheckboxNative` (name/value) for form fields.
|
|
5
|
-
import {
|
|
5
|
+
import { repairBindable } from '../../../internal/tools/index.js';
|
|
6
6
|
import { mergeProps } from '../../../internal/merge-props.js';
|
|
7
7
|
import type { CheckboxRootProps } from '../types.js';
|
|
8
8
|
import { CheckboxRootState } from '../checkbox.svelte.js';
|
|
@@ -30,30 +30,44 @@
|
|
|
30
30
|
}: CheckboxRootProps = $props();
|
|
31
31
|
|
|
32
32
|
const rootState = CheckboxRootState.create({
|
|
33
|
-
checked
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
()
|
|
46
|
-
|
|
47
|
-
)
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
33
|
+
get checked() {
|
|
34
|
+
return checked;
|
|
35
|
+
},
|
|
36
|
+
set checked(v) {
|
|
37
|
+
checked = v;
|
|
38
|
+
onCheckedChange?.(v);
|
|
39
|
+
},
|
|
40
|
+
get indeterminate() {
|
|
41
|
+
return indeterminate;
|
|
42
|
+
},
|
|
43
|
+
set indeterminate(v) {
|
|
44
|
+
indeterminate = v;
|
|
45
|
+
onIndeterminateChange?.(v);
|
|
46
|
+
},
|
|
47
|
+
get disabled() {
|
|
48
|
+
return disabled ?? false;
|
|
49
|
+
},
|
|
50
|
+
get required() {
|
|
51
|
+
return required;
|
|
52
|
+
},
|
|
53
|
+
get readonly() {
|
|
54
|
+
return Boolean(readonly);
|
|
55
|
+
},
|
|
56
|
+
get value() {
|
|
57
|
+
return value;
|
|
58
|
+
},
|
|
59
|
+
get type() {
|
|
60
|
+
return type;
|
|
61
|
+
},
|
|
62
|
+
get id() {
|
|
63
|
+
return id;
|
|
64
|
+
},
|
|
65
|
+
get ref() {
|
|
66
|
+
return ref;
|
|
67
|
+
},
|
|
68
|
+
set ref(v) {
|
|
69
|
+
ref = v;
|
|
70
|
+
},
|
|
57
71
|
});
|
|
58
72
|
|
|
59
73
|
repairBindable(rootState.groupChecked, () => (checked = rootState.groupChecked() ?? checked));
|