bits-ui 2.6.2 → 2.7.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.
@@ -18,6 +18,7 @@
18
18
  loop = true,
19
19
  name = undefined,
20
20
  required = false,
21
+ readonly = false,
21
22
  id = createId(uid),
22
23
  onValueChange = noop,
23
24
  ...restProps
@@ -29,6 +30,7 @@
29
30
  loop: box.with(() => loop),
30
31
  name: box.with(() => name),
31
32
  required: box.with(() => required),
33
+ readonly: box.with(() => readonly),
32
34
  id: box.with(() => id),
33
35
  value: box.with(
34
36
  () => value,
@@ -8,6 +8,7 @@ type RadioGroupRootStateProps = WithRefProps<ReadableBoxedValues<{
8
8
  loop: boolean;
9
9
  orientation: Orientation;
10
10
  name: string | undefined;
11
+ readonly: boolean;
11
12
  }> & WritableBoxedValues<{
12
13
  value: string;
13
14
  }>>;
@@ -22,7 +23,10 @@ declare class RadioGroupRootState {
22
23
  readonly id: string;
23
24
  readonly role: "radiogroup";
24
25
  readonly "aria-required": "true" | "false";
26
+ readonly "aria-disabled": "true" | "false";
27
+ readonly "aria-readonly": "true" | undefined;
25
28
  readonly "data-disabled": "" | undefined;
29
+ readonly "data-readonly": "" | undefined;
26
30
  readonly "data-orientation": Orientation;
27
31
  };
28
32
  }
@@ -48,6 +52,7 @@ declare class RadioGroupItemState {
48
52
  readonly "data-value": string;
49
53
  readonly "data-orientation": Orientation;
50
54
  readonly "data-disabled": "" | undefined;
55
+ readonly "data-readonly": "" | undefined;
51
56
  readonly "data-state": "checked" | "unchecked";
52
57
  readonly "aria-checked": "true" | "false" | "mixed";
53
58
  readonly type: "button";
@@ -1,6 +1,6 @@
1
1
  import { attachRef } from "svelte-toolbelt";
2
2
  import { Context, watch } from "runed";
3
- import { createBitsAttrs, getAriaChecked, getAriaRequired, getDataDisabled, } from "../../internal/attrs.js";
3
+ import { createBitsAttrs, getAriaChecked, getAriaRequired, getDataDisabled, getDataReadonly, getAriaDisabled, } from "../../internal/attrs.js";
4
4
  import { useRovingFocus, } from "../../internal/use-roving-focus.svelte.js";
5
5
  import { kbd } from "../../internal/kbd.js";
6
6
  const radioGroupAttrs = createBitsAttrs({
@@ -30,7 +30,10 @@ class RadioGroupRootState {
30
30
  id: this.opts.id.current,
31
31
  role: "radiogroup",
32
32
  "aria-required": getAriaRequired(this.opts.required.current),
33
+ "aria-disabled": getAriaDisabled(this.opts.disabled.current),
34
+ "aria-readonly": this.opts.readonly.current ? "true" : undefined,
33
35
  "data-disabled": getDataDisabled(this.opts.disabled.current),
36
+ "data-readonly": getDataReadonly(this.opts.readonly.current),
34
37
  "data-orientation": this.opts.orientation.current,
35
38
  [radioGroupAttrs.root]: "",
36
39
  ...attachRef(this.opts.ref),
@@ -41,6 +44,7 @@ class RadioGroupItemState {
41
44
  root;
42
45
  checked = $derived.by(() => this.root.opts.value.current === this.opts.value.current);
43
46
  #isDisabled = $derived.by(() => this.opts.disabled.current || this.root.opts.disabled.current);
47
+ #isReadonly = $derived.by(() => this.root.opts.readonly.current);
44
48
  #isChecked = $derived.by(() => this.root.isChecked(this.opts.value.current));
45
49
  #tabIndex = $state(-1);
46
50
  constructor(opts, root) {
@@ -67,12 +71,12 @@ class RadioGroupItemState {
67
71
  this.onfocus = this.onfocus.bind(this);
68
72
  }
69
73
  onclick(_) {
70
- if (this.opts.disabled.current)
74
+ if (this.opts.disabled.current || this.#isReadonly)
71
75
  return;
72
76
  this.root.setValue(this.opts.value.current);
73
77
  }
74
78
  onfocus(_) {
75
- if (!this.root.hasValue)
79
+ if (!this.root.hasValue || this.#isReadonly)
76
80
  return;
77
81
  this.root.setValue(this.opts.value.current);
78
82
  }
@@ -81,7 +85,9 @@ class RadioGroupItemState {
81
85
  return;
82
86
  if (e.key === kbd.SPACE) {
83
87
  e.preventDefault();
84
- this.root.setValue(this.opts.value.current);
88
+ if (!this.#isReadonly) {
89
+ this.root.setValue(this.opts.value.current);
90
+ }
85
91
  return;
86
92
  }
87
93
  this.root.rovingFocusGroup.handleKeydown(this.opts.ref.current, e, true);
@@ -93,6 +99,7 @@ class RadioGroupItemState {
93
99
  "data-value": this.opts.value.current,
94
100
  "data-orientation": this.root.opts.orientation.current,
95
101
  "data-disabled": getDataDisabled(this.#isDisabled),
102
+ "data-readonly": getDataReadonly(this.#isReadonly),
96
103
  "data-state": this.#isChecked ? "checked" : "unchecked",
97
104
  "aria-checked": getAriaChecked(this.#isChecked, false),
98
105
  [radioGroupAttrs.item]: "",
@@ -6,20 +6,20 @@ export type RadioGroupRootPropsWithoutHTML = WithChild<{
6
6
  * The orientation of the radio group. Used to determine
7
7
  * how keyboard navigation should work.
8
8
  *
9
- * @defaultValue "vertical"
9
+ * @default "vertical"
10
10
  */
11
11
  orientation?: Orientation;
12
12
  /**
13
13
  * Whether to loop around the radio items when navigating
14
14
  * with the keyboard.
15
15
  *
16
- * @defaultValue true
16
+ * @default true
17
17
  */
18
18
  loop?: boolean;
19
19
  /**
20
20
  * The value of the selected radio item.
21
21
  *
22
- * @defaultValue ""
22
+ * @default ""
23
23
  */
24
24
  value?: string;
25
25
  /**
@@ -31,13 +31,13 @@ export type RadioGroupRootPropsWithoutHTML = WithChild<{
31
31
  * form submission. If not provided, a hidden input will not
32
32
  * be rendered and the radio group will not be part of a form.
33
33
  *
34
- * @defaultValue undefined
34
+ * @default undefined
35
35
  */
36
36
  name?: string;
37
37
  /**
38
38
  * Whether the radio group is disabled.
39
39
  *
40
- * @defaultValue false
40
+ * @default false
41
41
  */
42
42
  disabled?: boolean;
43
43
  /**
@@ -46,6 +46,13 @@ export type RadioGroupRootPropsWithoutHTML = WithChild<{
46
46
  * input is rendered.
47
47
  */
48
48
  required?: boolean;
49
+ /**
50
+ * Whether the radio group is readonly. When readonly, users can
51
+ * focus and navigate through items but cannot change the value.
52
+ *
53
+ * @default false
54
+ */
55
+ readonly?: boolean;
49
56
  }>;
50
57
  export type RadioGroupRootProps = RadioGroupRootPropsWithoutHTML & Without<BitsPrimitiveDivAttributes, RadioGroupRootPropsWithoutHTML>;
51
58
  export type RadioGroupItemSnippetProps = {
@@ -59,7 +66,7 @@ export type RadioGroupItemPropsWithoutHTML = WithChild<{
59
66
  /**
60
67
  * Whether the radio item is disabled.
61
68
  *
62
- * @defaultValue false
69
+ * @default false
63
70
  */
64
71
  disabled?: boolean | null | undefined;
65
72
  }, RadioGroupItemSnippetProps>;
@@ -615,6 +615,8 @@ class SelectTriggerState {
615
615
  }
616
616
  }
617
617
  onpointerup(e) {
618
+ if (this.root.opts.disabled.current)
619
+ return;
618
620
  e.preventDefault();
619
621
  if (e.pointerType === "touch") {
620
622
  if (this.root.opts.open.current === false) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "bits-ui",
3
- "version": "2.6.2",
3
+ "version": "2.7.0",
4
4
  "license": "MIT",
5
5
  "repository": "github:huntabyte/bits-ui",
6
6
  "funding": "https://github.com/sponsors/huntabyte",