bits-ui 2.8.14 → 2.9.1

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.
@@ -6,6 +6,7 @@ interface CheckboxGroupStateOpts extends WithRefOpts, ReadableBoxedValues<{
6
6
  name: string | undefined;
7
7
  disabled: boolean;
8
8
  required: boolean;
9
+ readonly: boolean;
9
10
  onValueChange: OnChangeFn<string[]>;
10
11
  }>, WritableBoxedValues<{
11
12
  value: string[];
@@ -43,6 +44,7 @@ export declare class CheckboxGroupLabelState {
43
44
  interface CheckboxRootStateOpts extends WithRefOpts, ReadableBoxedValues<{
44
45
  disabled: boolean;
45
46
  required: boolean;
47
+ readonly: boolean;
46
48
  name: string | undefined;
47
49
  value: string | undefined;
48
50
  type: HTMLButtonAttributes["type"];
@@ -59,6 +61,7 @@ export declare class CheckboxRootState {
59
61
  readonly trueName: string | undefined;
60
62
  readonly trueRequired: boolean;
61
63
  readonly trueDisabled: boolean;
64
+ readonly trueReadonly: boolean;
62
65
  readonly attachment: RefAttachment;
63
66
  constructor(opts: CheckboxRootStateOpts, group: CheckboxGroupState | null);
64
67
  onkeydown(e: BitsKeyboardEvent): void;
@@ -74,7 +77,9 @@ export declare class CheckboxRootState {
74
77
  readonly disabled: boolean;
75
78
  readonly "aria-checked": "true" | "false" | "mixed";
76
79
  readonly "aria-required": "true" | "false";
80
+ readonly "aria-readonly": "true" | "false";
77
81
  readonly "data-disabled": "" | undefined;
82
+ readonly "data-readonly": "" | undefined;
78
83
  readonly "data-state": "checked" | "indeterminate" | "unchecked";
79
84
  readonly onclick: (e: BitsMouseEvent) => void;
80
85
  readonly onkeydown: (e: BitsKeyboardEvent) => void;
@@ -93,6 +98,7 @@ export declare class CheckboxInputState {
93
98
  readonly required: boolean;
94
99
  readonly name: string | undefined;
95
100
  readonly value: string | undefined;
101
+ readonly readonly: boolean;
96
102
  };
97
103
  }
98
104
  export {};
@@ -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, getAriaReadonly, getAriaRequired, getDataDisabled, getDataReadonly, } from "../../internal/attrs.js";
4
4
  import { kbd } from "../../internal/kbd.js";
5
5
  import { arraysAreEqual } from "../../internal/arrays.js";
6
6
  const checkboxAttrs = createBitsAttrs({
@@ -82,25 +82,25 @@ export class CheckboxRootState {
82
82
  opts;
83
83
  group;
84
84
  trueName = $derived.by(() => {
85
- if (this.group && this.group.opts.name.current) {
85
+ if (this.group && this.group.opts.name.current)
86
86
  return this.group.opts.name.current;
87
- }
88
- else {
89
- return this.opts.name.current;
90
- }
87
+ return this.opts.name.current;
91
88
  });
92
89
  trueRequired = $derived.by(() => {
93
- if (this.group && this.group.opts.required.current) {
90
+ if (this.group && this.group.opts.required.current)
94
91
  return true;
95
- }
96
92
  return this.opts.required.current;
97
93
  });
98
94
  trueDisabled = $derived.by(() => {
99
- if (this.group && this.group.opts.disabled.current) {
95
+ if (this.group && this.group.opts.disabled.current)
100
96
  return true;
101
- }
102
97
  return this.opts.disabled.current;
103
98
  });
99
+ trueReadonly = $derived.by(() => {
100
+ if (this.group && this.group.opts.readonly.current)
101
+ return true;
102
+ return this.opts.readonly.current;
103
+ });
104
104
  attachment;
105
105
  constructor(opts, group) {
106
106
  this.opts = opts;
@@ -125,7 +125,7 @@ export class CheckboxRootState {
125
125
  });
126
126
  }
127
127
  onkeydown(e) {
128
- if (this.opts.disabled.current)
128
+ if (this.trueDisabled || this.trueReadonly)
129
129
  return;
130
130
  if (e.key === kbd.ENTER)
131
131
  e.preventDefault();
@@ -144,8 +144,12 @@ export class CheckboxRootState {
144
144
  }
145
145
  }
146
146
  onclick(e) {
147
- if (this.opts.disabled.current)
147
+ if (this.trueDisabled || this.trueReadonly)
148
148
  return;
149
+ if (this.opts.type.current === "submit") {
150
+ this.#toggle();
151
+ return;
152
+ }
149
153
  e.preventDefault();
150
154
  this.#toggle();
151
155
  }
@@ -160,7 +164,9 @@ export class CheckboxRootState {
160
164
  disabled: this.trueDisabled,
161
165
  "aria-checked": getAriaChecked(this.opts.checked.current, this.opts.indeterminate.current),
162
166
  "aria-required": getAriaRequired(this.trueRequired),
167
+ "aria-readonly": getAriaReadonly(this.trueReadonly),
163
168
  "data-disabled": getDataDisabled(this.trueDisabled),
169
+ "data-readonly": getDataReadonly(this.trueReadonly),
164
170
  "data-state": getCheckboxDataState(this.opts.checked.current, this.opts.indeterminate.current),
165
171
  [checkboxAttrs.root]: "",
166
172
  //
@@ -194,6 +200,7 @@ export class CheckboxInputState {
194
200
  required: this.root.trueRequired,
195
201
  name: this.root.trueName,
196
202
  value: this.root.opts.value.current,
203
+ readonly: this.root.trueReadonly,
197
204
  }));
198
205
  }
199
206
  function getCheckboxDataState(checked, indeterminate) {
@@ -18,6 +18,7 @@
18
18
  disabled,
19
19
  children,
20
20
  child,
21
+ readonly,
21
22
  ...restProps
22
23
  }: CheckboxGroupProps = $props();
23
24
 
@@ -29,6 +30,7 @@
29
30
  ),
30
31
  disabled: box.with(() => Boolean(disabled)),
31
32
  required: box.with(() => Boolean(required)),
33
+ readonly: box.with(() => Boolean(readonly)),
32
34
  name: box.with(() => name),
33
35
  value: box.with(
34
36
  () => $state.snapshot(value),
@@ -22,6 +22,7 @@
22
22
  onIndeterminateChange,
23
23
  child,
24
24
  type = "button",
25
+ readonly,
25
26
  ...restProps
26
27
  }: CheckboxRootProps = $props();
27
28
 
@@ -74,6 +75,7 @@
74
75
  }
75
76
  ),
76
77
  type: box.with(() => type),
78
+ readonly: box.with(() => Boolean(readonly)),
77
79
  },
78
80
  group
79
81
  );
@@ -8,20 +8,29 @@ export type CheckboxRootPropsWithoutHTML = WithChild<{
8
8
  /**
9
9
  * Whether the checkbox is disabled.
10
10
  *
11
- * @defaultValue false
11
+ * @default false
12
12
  */
13
13
  disabled?: boolean | null | undefined;
14
14
  /**
15
15
  * Whether the checkbox is required (for form validation).
16
16
  *
17
- * @defaultValue false
17
+ * @default false
18
18
  */
19
19
  required?: boolean;
20
+ /**
21
+ * Whether the checkbox is read only.
22
+ *
23
+ * If readonly, the checkbox will be focusable by the user,
24
+ * but will not be able to be checked/unchecked.
25
+ *
26
+ * @default false
27
+ */
28
+ readonly?: boolean | null | undefined;
20
29
  /**
21
30
  * The name of the checkbox used in form submission.
22
31
  * If not provided, the hidden input will not be rendered.
23
32
  *
24
- * @defaultValue undefined
33
+ * @default undefined
25
34
  */
26
35
  name?: any;
27
36
  /**
@@ -29,7 +38,7 @@ export type CheckboxRootPropsWithoutHTML = WithChild<{
29
38
  * the checkbox when in a `Checkbox.Group`. If not provided while in a
30
39
  * `Checkbox.Group`, the checkbox will use a random identifier.
31
40
  *
32
- * @defaultValue undefined
41
+ * @default undefined
33
42
  */
34
43
  value?: string;
35
44
  /**
@@ -37,7 +46,7 @@ export type CheckboxRootPropsWithoutHTML = WithChild<{
37
46
  * - `true` for checked
38
47
  * - `false` for unchecked
39
48
  *
40
- * @defaultValue false
49
+ * @default false
41
50
  */
42
51
  checked?: boolean;
43
52
  /**
@@ -47,7 +56,7 @@ export type CheckboxRootPropsWithoutHTML = WithChild<{
47
56
  /**
48
57
  * Whether the checkbox is in an indeterminate state or not.
49
58
  *
50
- * @defaultValue false
59
+ * @default false
51
60
  */
52
61
  indeterminate?: boolean;
53
62
  /**
@@ -61,14 +70,23 @@ export type CheckboxGroupPropsWithoutHTML = WithChild<{
61
70
  * Whether the checkbox group is disabled.
62
71
  * This will disable all checkboxes in the group.
63
72
  *
64
- * @defaultValue false
73
+ * @default false
65
74
  */
66
75
  disabled?: boolean | null | undefined;
76
+ /**
77
+ * Whether the checkbox group is read only.
78
+ *
79
+ * If readonly, the group will be focusable by the user,
80
+ * but the checkboxes not be able to be checked/unchecked.
81
+ *
82
+ * @default false
83
+ */
84
+ readonly?: boolean | null | undefined;
67
85
  /**
68
86
  * Whether the checkbox group is required (for form validation).
69
87
  * This will mark all checkboxes in the group as required.
70
88
  *
71
- * @defaultValue false
89
+ * @default false
72
90
  */
73
91
  required?: boolean;
74
92
  /**
@@ -76,7 +94,7 @@ export type CheckboxGroupPropsWithoutHTML = WithChild<{
76
94
  * If not provided, the hidden input will not be rendered.
77
95
  * This will be used as the name for all checkboxes in the group.
78
96
  *
79
- * @defaultValue undefined
97
+ * @default undefined
80
98
  */
81
99
  name?: any;
82
100
  /**
@@ -84,7 +102,7 @@ export type CheckboxGroupPropsWithoutHTML = WithChild<{
84
102
  * of the checkboxes in the group are checked.
85
103
  *
86
104
  * @bindable
87
- * @defaultValue []
105
+ * @default []
88
106
  */
89
107
  value?: string[];
90
108
  /**
@@ -259,18 +259,19 @@ export function handleCalendarNextPage({ months, setMonths, numberOfMonths, page
259
259
  setPlaceholder(firstMonth.add({ months: numberOfMonths }));
260
260
  }
261
261
  else {
262
+ // Calculate the target date first, then update both months and placeholder
263
+ // to ensure they're synchronized and prevent useMonthViewPlaceholderSync from
264
+ // double-triggering
265
+ const targetDate = firstMonth.add({ months: 1 });
262
266
  const newMonths = createMonths({
263
- dateObj: firstMonth.add({ months: 1 }),
267
+ dateObj: targetDate,
264
268
  weekStartsOn,
265
269
  locale,
266
270
  fixedWeeks,
267
271
  numberOfMonths,
268
272
  });
273
+ setPlaceholder(targetDate);
269
274
  setMonths(newMonths);
270
- const firstNewMonth = newMonths[0];
271
- if (!firstNewMonth)
272
- return;
273
- setPlaceholder(firstNewMonth.value.set({ day: 1 }));
274
275
  }
275
276
  }
276
277
  export function handleCalendarPrevPage({ months, setMonths, numberOfMonths, pagedNavigation, weekStartsOn, locale, fixedWeeks, setPlaceholder, }) {
@@ -281,18 +282,19 @@ export function handleCalendarPrevPage({ months, setMonths, numberOfMonths, page
281
282
  setPlaceholder(firstMonth.subtract({ months: numberOfMonths }));
282
283
  }
283
284
  else {
285
+ // Calculate the target date first, then update both months and placeholder
286
+ // to ensure they're synchronized and prevent useMonthViewPlaceholderSync from
287
+ // double-triggering
288
+ const targetDate = firstMonth.subtract({ months: 1 });
284
289
  const newMonths = createMonths({
285
- dateObj: firstMonth.subtract({ months: 1 }),
290
+ dateObj: targetDate,
286
291
  weekStartsOn,
287
292
  locale,
288
293
  fixedWeeks,
289
294
  numberOfMonths,
290
295
  });
296
+ setPlaceholder(targetDate);
291
297
  setMonths(newMonths);
292
- const firstNewMonth = newMonths[0];
293
- if (!firstNewMonth)
294
- return;
295
- setPlaceholder(firstNewMonth.value.set({ day: 1 }));
296
298
  }
297
299
  }
298
300
  export function getWeekdays({ months, formatter, weekdayFormat }) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "bits-ui",
3
- "version": "2.8.14",
3
+ "version": "2.9.1",
4
4
  "license": "MIT",
5
5
  "repository": "github:huntabyte/bits-ui",
6
6
  "funding": "https://github.com/sponsors/huntabyte",