bits-ui 1.2.0 → 1.2.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.
@@ -41,13 +41,6 @@ export declare class DateRangeFieldRootState {
41
41
  startValueComplete: boolean;
42
42
  endValueComplete: boolean;
43
43
  rangeComplete: boolean;
44
- mergedValues: {
45
- start: undefined;
46
- end: undefined;
47
- } | {
48
- start: DateValue;
49
- end: DateValue;
50
- };
51
44
  constructor(opts: DateRangeFieldRootStateProps);
52
45
  validationStatus: false | {
53
46
  readonly reason: "custom";
@@ -1,6 +1,5 @@
1
- import { untrack } from "svelte";
2
1
  import { box, onDestroyEffect, useRefById } from "svelte-toolbelt";
3
- import { Context } from "runed";
2
+ import { Context, watch } from "runed";
4
3
  import { DateFieldInputState, useDateFieldRoot } from "../date-field/date-field.svelte.js";
5
4
  import { useId } from "../../internal/use-id.js";
6
5
  import { getDataDisabled, getDataInvalid } from "../../internal/attrs.js";
@@ -22,21 +21,6 @@ export class DateRangeFieldRootState {
22
21
  startValueComplete = $derived.by(() => this.opts.startValue.current !== undefined);
23
22
  endValueComplete = $derived.by(() => this.opts.endValue.current !== undefined);
24
23
  rangeComplete = $derived(this.startValueComplete && this.endValueComplete);
25
- mergedValues = $derived.by(() => {
26
- if (this.opts.startValue.current === undefined ||
27
- this.opts.endValue.current === undefined) {
28
- return {
29
- start: undefined,
30
- end: undefined,
31
- };
32
- }
33
- else {
34
- return {
35
- start: this.opts.startValue.current,
36
- end: this.opts.endValue.current,
37
- };
38
- }
39
- });
40
24
  constructor(opts) {
41
25
  this.opts = opts;
42
26
  this.formatter = createFormatter(this.opts.locale.current);
@@ -54,48 +38,65 @@ export class DateRangeFieldRootState {
54
38
  return;
55
39
  this.formatter.setLocale(this.opts.locale.current);
56
40
  });
57
- $effect(() => {
58
- const startValue = this.opts.value.current.start;
59
- untrack(() => {
60
- if (startValue)
61
- this.opts.placeholder.current = startValue;
62
- });
63
- });
64
- $effect(() => {
65
- const endValue = this.opts.value.current.end;
66
- untrack(() => {
67
- if (endValue)
68
- this.opts.placeholder.current = endValue;
69
- });
41
+ /**
42
+ * Synchronize the start and end values with the `value` in case
43
+ * it is updated externally.
44
+ */
45
+ watch(() => this.opts.value.current, (value) => {
46
+ if (value.start && value.end) {
47
+ this.opts.startValue.current = value.start;
48
+ this.opts.endValue.current = value.end;
49
+ }
50
+ else if (value.start) {
51
+ this.opts.startValue.current = value.start;
52
+ this.opts.endValue.current = undefined;
53
+ }
54
+ else if (value.start === undefined && value.end === undefined) {
55
+ this.opts.startValue.current = undefined;
56
+ this.opts.endValue.current = undefined;
57
+ }
70
58
  });
71
59
  /**
72
- * Sync values set programatically with the `startValue` and `endValue`
60
+ * Synchronize the placeholder value with the current start value
73
61
  */
74
- $effect(() => {
75
- const value = this.opts.value.current;
76
- untrack(() => {
77
- if (value.start !== undefined && value.start !== this.opts.startValue.current) {
78
- this.#setStartValue(value.start);
79
- }
80
- if (value.end !== undefined && value.end !== this.opts.endValue.current) {
81
- this.#setEndValue(value.end);
82
- }
83
- });
62
+ watch(() => this.opts.value.current, (value) => {
63
+ const startValue = value.start;
64
+ if (startValue && this.opts.placeholder.current !== startValue) {
65
+ this.opts.placeholder.current = startValue;
66
+ }
84
67
  });
85
- // TODO: Handle description element
86
- $effect(() => {
87
- const placeholder = untrack(() => this.opts.placeholder.current);
88
- const startValue = untrack(() => this.opts.startValue.current);
89
- if (this.startValueComplete && placeholder !== startValue) {
90
- untrack(() => {
91
- if (startValue) {
92
- this.opts.placeholder.current = startValue;
68
+ watch([() => this.opts.startValue.current, () => this.opts.endValue.current], ([startValue, endValue]) => {
69
+ if (this.opts.value.current &&
70
+ this.opts.value.current.start === startValue &&
71
+ this.opts.value.current.end === endValue) {
72
+ return;
73
+ }
74
+ if (startValue && endValue) {
75
+ this.#updateValue((prev) => {
76
+ if (prev.start === startValue && prev.end === endValue) {
77
+ return prev;
78
+ }
79
+ if (isBefore(endValue, startValue)) {
80
+ const start = startValue;
81
+ const end = endValue;
82
+ this.#setStartValue(end);
83
+ this.#setEndValue(start);
84
+ return { start: endValue, end: startValue };
85
+ }
86
+ else {
87
+ return {
88
+ start: startValue,
89
+ end: endValue,
90
+ };
93
91
  }
94
92
  });
95
93
  }
96
- });
97
- $effect(() => {
98
- this.opts.value.current = this.mergedValues;
94
+ else if (this.opts.value.current &&
95
+ this.opts.value.current.start &&
96
+ this.opts.value.current.end) {
97
+ this.opts.value.current.start = undefined;
98
+ this.opts.value.current.end = undefined;
99
+ }
99
100
  });
100
101
  }
101
102
  validationStatus = $derived.by(() => {
@@ -134,6 +135,11 @@ export class DateRangeFieldRootState {
134
135
  return false;
135
136
  return true;
136
137
  });
138
+ #updateValue(cb) {
139
+ const value = this.opts.value.current;
140
+ const newValue = cb(value);
141
+ this.opts.value.current = newValue;
142
+ }
137
143
  #setStartValue(value) {
138
144
  this.opts.startValue.current = value;
139
145
  }
@@ -1,5 +1,5 @@
1
1
  import type { ReadableBoxedValues, WritableBoxedValues } from "../../internal/box.svelte.js";
2
- import type { BitsKeyboardEvent, BitsMouseEvent, BitsPointerEvent, WithRefProps } from "../../internal/types.js";
2
+ import type { BitsKeyboardEvent, BitsMouseEvent, WithRefProps } from "../../internal/types.js";
3
3
  type DialogVariant = "alert-dialog" | "dialog";
4
4
  type DialogRootStateProps = WritableBoxedValues<{
5
5
  open: boolean;
@@ -42,7 +42,6 @@ declare class DialogTriggerState {
42
42
  readonly root: DialogRootState;
43
43
  constructor(opts: DialogTriggerStateProps, root: DialogRootState);
44
44
  onclick(e: BitsMouseEvent): void;
45
- onpointerdown(e: BitsPointerEvent): void;
46
45
  onkeydown(e: BitsKeyboardEvent): void;
47
46
  props: {
48
47
  readonly "data-state": "open" | "closed";
@@ -50,7 +49,6 @@ declare class DialogTriggerState {
50
49
  readonly "aria-haspopup": "dialog";
51
50
  readonly "aria-expanded": "true" | "false";
52
51
  readonly "aria-controls": string | undefined;
53
- readonly onpointerdown: (e: BitsPointerEvent) => void;
54
52
  readonly onkeydown: (e: BitsKeyboardEvent) => void;
55
53
  readonly onclick: (e: BitsMouseEvent) => void;
56
54
  readonly disabled: true | undefined;
@@ -51,9 +51,6 @@ class DialogTriggerState {
51
51
  constructor(opts, root) {
52
52
  this.opts = opts;
53
53
  this.root = root;
54
- this.onclick = this.onclick.bind(this);
55
- this.onpointerdown = this.onpointerdown.bind(this);
56
- this.onkeydown = this.onkeydown.bind(this);
57
54
  useRefById({
58
55
  ...opts,
59
56
  onRefChange: (node) => {
@@ -62,7 +59,6 @@ class DialogTriggerState {
62
59
  },
63
60
  });
64
61
  this.onclick = this.onclick.bind(this);
65
- this.onpointerdown = this.onpointerdown.bind(this);
66
62
  this.onkeydown = this.onkeydown.bind(this);
67
63
  }
68
64
  onclick(e) {
@@ -72,15 +68,6 @@ class DialogTriggerState {
72
68
  return;
73
69
  this.root.handleOpen();
74
70
  }
75
- onpointerdown(e) {
76
- if (this.opts.disabled.current)
77
- return;
78
- if (e.button > 0)
79
- return;
80
- // by default, it will attempt to focus this trigger on pointerdown
81
- // since this also opens the dialog we want to prevent that behavior
82
- e.preventDefault();
83
- }
84
71
  onkeydown(e) {
85
72
  if (this.opts.disabled.current)
86
73
  return;
@@ -95,7 +82,6 @@ class DialogTriggerState {
95
82
  "aria-expanded": getAriaExpanded(this.root.opts.open.current),
96
83
  "aria-controls": this.root.contentId,
97
84
  [this.root.attrs.trigger]: "",
98
- onpointerdown: this.onpointerdown,
99
85
  onkeydown: this.onkeydown,
100
86
  onclick: this.onclick,
101
87
  disabled: this.opts.disabled.current ? true : undefined,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "bits-ui",
3
- "version": "1.2.0",
3
+ "version": "1.2.1",
4
4
  "license": "MIT",
5
5
  "repository": "github:huntabyte/bits-ui",
6
6
  "funding": "https://github.com/sponsors/huntabyte",