@pzerelles/headlessui-svelte 2.1.2-next.22 → 2.1.2-next.23

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.
@@ -15,7 +15,7 @@ let {
15
15
  type = "button",
16
16
  ...theirProps
17
17
  } = $props();
18
- const disabled = $derived(providedDisabled.value || ownDisabled);
18
+ const disabled = $derived(providedDisabled.current || ownDisabled);
19
19
  const { isHovered: hover, hoverProps } = $derived(
20
20
  useHover({
21
21
  get disabled() {
@@ -45,7 +45,7 @@ const controllable = useControllable(
45
45
  defaultChecked ?? false
46
46
  );
47
47
  const { value: checked, onchange } = $derived(controllable);
48
- const disabled = $derived(providedDisabled?.value ?? theirDisabled);
48
+ const disabled = $derived(providedDisabled.current || theirDisabled);
49
49
  const { isHovered: hover, hoverProps } = $derived(
50
50
  useHover({
51
51
  get disabled() {
@@ -1,28 +1,33 @@
1
1
  <script lang="ts" module>let DEFAULT_DESCRIPTION_TAG = "p";
2
2
  </script>
3
3
 
4
- <script lang="ts" generics="TTag extends ElementType = typeof DEFAULT_DESCRIPTION_TAG">import { htmlid } from "../utils/id.js";
5
- import { stateFromSlot } from "../utils/state.js";
4
+ <script lang="ts" generics="TTag extends ElementType = typeof DEFAULT_DESCRIPTION_TAG">import { useId } from "../hooks/use-id.js";
6
5
  import { useDisabled } from "../hooks/use-disabled.js";
7
- import { onMount } from "svelte";
8
6
  import { useDescriptionContext } from "./context.svelte.js";
9
- const internalId = htmlid();
7
+ import ElementOrComponent from "../utils/ElementOrComponent.svelte";
8
+ import { untrack } from "svelte";
9
+ const internalId = useId();
10
10
  const providedDisabled = useDisabled();
11
11
  let {
12
- as,
12
+ ref = $bindable(),
13
13
  id = `headlessui-description-${internalId}`,
14
- children,
15
14
  ...theirProps
16
15
  } = $props();
17
- const context = useDescriptionContext();
18
- onMount(() => {
19
- context.register(id);
16
+ const { register } = useDescriptionContext();
17
+ $effect(() => {
18
+ id;
19
+ return untrack(() => register(id));
20
20
  });
21
- const disabled = $derived(providedDisabled.value || false);
21
+ const disabled = $derived(providedDisabled.current || false);
22
22
  const slot = $derived({ disabled });
23
- const ourProps = $derived({ id, ...stateFromSlot(slot) });
23
+ const ourProps = $derived({ id });
24
24
  </script>
25
25
 
26
- <svelte:element this={as ?? DEFAULT_DESCRIPTION_TAG} {...ourProps} {...theirProps}>
27
- {#if children}{@render children(slot, {})}{/if}
28
- </svelte:element>
26
+ <ElementOrComponent
27
+ {ourProps}
28
+ {theirProps}
29
+ slots={slot}
30
+ defaultTag={DEFAULT_DESCRIPTION_TAG}
31
+ name="Description"
32
+ bind:ref
33
+ />
@@ -14,7 +14,7 @@ declare class __sveltets_Render<TTag extends ElementType = typeof DEFAULT_DESCRI
14
14
  [evt: string]: CustomEvent<any>;
15
15
  };
16
16
  slots(): {};
17
- bindings(): "";
17
+ bindings(): "ref";
18
18
  exports(): {};
19
19
  }
20
20
  interface $$IsomorphicComponent {
@@ -1,8 +1,8 @@
1
1
  import { getContext, setContext } from "svelte";
2
2
  export function useDescriptionContext() {
3
- let context = getContext("DescriptionContext");
3
+ const context = getContext("DescriptionContext");
4
4
  if (!context) {
5
- let err = new Error("You used a <Description /> component, but it is not inside a relevant parent.");
5
+ const err = new Error("You used a <Description /> component, but it is not inside a relevant parent.");
6
6
  if (Error.captureStackTrace)
7
7
  Error.captureStackTrace(err, useDescriptionContext);
8
8
  throw err;
@@ -18,10 +18,19 @@ export function useDescribedBy() {
18
18
  };
19
19
  }
20
20
  export const useDescriptions = (options = {}) => {
21
- const { slot, name, props, inherit } = $derived(options);
22
- let descriptionIds = $state([]);
21
+ const { slot, name, props } = $derived(options);
22
+ const descriptionIds = $state([]);
23
+ const register = (value) => {
24
+ descriptionIds.push(value);
25
+ return () => {
26
+ const idx = descriptionIds.indexOf(value);
27
+ if (idx !== -1)
28
+ descriptionIds.splice(idx, 1);
29
+ };
30
+ };
23
31
  const value = $derived(descriptionIds.length > 0 ? descriptionIds.join(" ") : undefined);
24
32
  const context = {
33
+ register,
25
34
  get slot() {
26
35
  return slot;
27
36
  },
@@ -34,17 +43,6 @@ export const useDescriptions = (options = {}) => {
34
43
  get value() {
35
44
  return value;
36
45
  },
37
- register(value) {
38
- descriptionIds.push(value);
39
- return () => {
40
- const clone = descriptionIds.slice();
41
- const idx = clone.indexOf(value);
42
- if (idx !== -1)
43
- clone.splice(idx, 1);
44
- descriptionIds = clone;
45
- return descriptionIds;
46
- };
47
- },
48
46
  };
49
47
  setContext("DescriptionContext", context);
50
48
  return context;
@@ -1,10 +1,9 @@
1
1
  <script lang="ts" module>let DEFAULT_FIELD_TAG = "div";
2
2
  </script>
3
3
 
4
- <script lang="ts" generics="TTag extends ElementType = typeof DEFAULT_FIELD_TAG">import { useDisabled } from "../hooks/use-disabled.js";
4
+ <script lang="ts" generics="TTag extends ElementType = typeof DEFAULT_FIELD_TAG">import { provideDisabled } from "../hooks/use-disabled.js";
5
5
  import { createIdContext } from "../utils/id.js";
6
6
  import { nanoid } from "nanoid";
7
- import { setContext } from "svelte";
8
7
  import { useLabels } from "../label/context.svelte.js";
9
8
  import { useDescriptions } from "../description/context.svelte.js";
10
9
  import ElementOrComponent from "../utils/ElementOrComponent.svelte";
@@ -19,13 +18,8 @@ const inputId = `headlessui-control-${nanoid(8)}`;
19
18
  createIdContext(inputId);
20
19
  useLabels();
21
20
  useDescriptions();
22
- const providedDisabled = useDisabled();
23
- const disabled = $derived(providedDisabled.value || ownDisabled);
24
- setContext("DisabledContext", {
25
- get value() {
26
- return disabled;
27
- }
28
- });
21
+ const disabledContext = provideDisabled(() => ownDisabled);
22
+ const { current: disabled } = $derived(disabledContext);
29
23
  const slot = $derived({ disabled });
30
24
  const ourProps = $derived({
31
25
  disabled: disabled || void 0,
@@ -11,7 +11,7 @@ let {
11
11
  ...theirProps
12
12
  } = $props();
13
13
  const providedDisabled = useDisabled();
14
- const disabled = $derived(providedDisabled.value || ownDisabled);
14
+ const disabled = $derived(providedDisabled.current || ownDisabled);
15
15
  setContext("DisabledContext", {
16
16
  get value() {
17
17
  return disabled;
@@ -1,3 +1,6 @@
1
1
  export declare const useDisabled: () => {
2
- readonly value: boolean;
2
+ readonly current: boolean;
3
+ };
4
+ export declare const provideDisabled: (disabled: () => boolean) => {
5
+ readonly current: boolean;
3
6
  };
@@ -1,9 +1,14 @@
1
- import { getContext } from "svelte";
1
+ import { getContext, setContext } from "svelte";
2
2
  export const useDisabled = () => {
3
- const context = getContext("DisabledContext");
4
- return {
5
- get value() {
6
- return context?.value ?? false;
3
+ return getContext("DisabledContext") ?? { current: false };
4
+ };
5
+ export const provideDisabled = (disabled) => {
6
+ const parentDisabled = useDisabled();
7
+ const context = {
8
+ get current() {
9
+ return disabled() || parentDisabled.current;
7
10
  },
8
11
  };
12
+ setContext("DisabledContext", context);
13
+ return context;
9
14
  };
@@ -22,7 +22,7 @@ let {
22
22
  invalid = false,
23
23
  ...theirProps
24
24
  } = $props();
25
- const disabled = $derived(providedDisabled?.value ?? theirDisabled);
25
+ const disabled = $derived(providedDisabled.current || theirDisabled);
26
26
  const labelledBy = useLabelledBy();
27
27
  const describedBy = useDescribedBy();
28
28
  const { isHovered: hover, hoverProps } = $derived(
@@ -45,7 +45,7 @@ let handleClick = (e) => {
45
45
  }
46
46
  }
47
47
  };
48
- const disabled = $derived(providedDisabled.value ?? false);
48
+ const disabled = $derived(providedDisabled.current ?? false);
49
49
  const slot = $derived({ disabled });
50
50
  const ourProps = $derived({
51
51
  id,
@@ -213,7 +213,7 @@ let {
213
213
  ...theirProps
214
214
  } = $props();
215
215
  const providedDisabled = useDisabled();
216
- const disabled = $derived(providedDisabled.value || ownDisabled);
216
+ const disabled = $derived(providedDisabled.current || ownDisabled);
217
217
  const orientation = horizontal ? "horizontal" : "vertical";
218
218
  const controllable = useControllable(
219
219
  {
@@ -7,14 +7,9 @@ import { match } from "../utils/match.js";
7
7
  let DEFAULT_MENU_TAG = "svelte:fragment";
8
8
  </script>
9
9
 
10
- <script lang="ts" generics="TTag extends ElementType = typeof DEFAULT_MENU_TAG">import { setContext } from "svelte";
11
- import {
12
- ActivationTrigger,
13
- MenuStates,
14
- stateReducer
15
- } from "./context.svelte.js";
10
+ <script lang="ts" generics="TTag extends ElementType = typeof DEFAULT_MENU_TAG">import { ActivationTrigger, createMenuContext, MenuStates } from "./context.svelte.js";
16
11
  let { ref = $bindable(), __demoMode = false, ...theirProps } = $props();
17
- const _state = stateReducer({
12
+ const context = createMenuContext({
18
13
  __demoMode,
19
14
  menuState: __demoMode ? MenuStates.Open : MenuStates.Closed,
20
15
  buttonElement: null,
@@ -24,8 +19,7 @@ const _state = stateReducer({
24
19
  activeItemIndex: null,
25
20
  activationTrigger: ActivationTrigger.Other
26
21
  });
27
- const { menuState, itemsElement, buttonElement } = $derived(_state);
28
- setContext("MenuContext", _state);
22
+ const { menuState, itemsElement, buttonElement } = $derived(context);
29
23
  const outsideClickEnabled = $derived(menuState === MenuStates.Open);
30
24
  useOutsideClick({
31
25
  get enabled() {
@@ -35,7 +29,7 @@ useOutsideClick({
35
29
  return [buttonElement, itemsElement];
36
30
  },
37
31
  cb: (event, target) => {
38
- _state.closeMenu();
32
+ context.closeMenu();
39
33
  if (!isFocusableElement(target, FocusableMode.Loose)) {
40
34
  event.preventDefault();
41
35
  buttonElement?.focus();
@@ -43,8 +37,8 @@ useOutsideClick({
43
37
  }
44
38
  });
45
39
  const slot = $derived({
46
- open: _state.menuState === MenuStates.Open,
47
- close: _state.closeMenu
40
+ open: context.menuState === MenuStates.Open,
41
+ close: context.closeMenu
48
42
  });
49
43
  useFloatingProvider();
50
44
  const openClosed = $derived(
@@ -45,32 +45,4 @@ export type MenuContext = StateDefinition & {
45
45
  setItemsElement(element: HTMLElement | null): void;
46
46
  };
47
47
  export declare function useMenuContext(component: string): MenuContext;
48
- export declare const stateReducer: (initialState: StateDefinition) => {
49
- readonly menuState: MenuStates;
50
- readonly buttonElement: HTMLButtonElement | null;
51
- readonly itemsElement: HTMLElement | null;
52
- readonly items: {
53
- id: string;
54
- dataRef: MenuItemDataRef;
55
- }[];
56
- readonly searchQuery: string;
57
- readonly activeItemIndex: number | null;
58
- readonly activationTrigger: ActivationTrigger;
59
- readonly __demoMode: boolean;
60
- closeMenu(): StateDefinition;
61
- openMenu(): StateDefinition;
62
- goToItem(action: {
63
- focus: Focus.Specific;
64
- id: string;
65
- trigger?: ActivationTrigger;
66
- } | {
67
- focus: Exclude<Focus, Focus.Specific>;
68
- trigger?: ActivationTrigger;
69
- }): StateDefinition;
70
- search(value: string): StateDefinition;
71
- clearSearch(): StateDefinition;
72
- registerItem(id: string, dataRef: MenuItemDataRef): StateDefinition;
73
- unregisterItem(id: string): StateDefinition;
74
- setButtonElement(element: HTMLButtonElement | null): StateDefinition;
75
- setItemsElement(element: HTMLElement | null): StateDefinition;
76
- };
48
+ export declare const createMenuContext: (initialState: StateDefinition) => MenuContext;
@@ -1,6 +1,6 @@
1
1
  import { calculateActiveIndex, Focus } from "../utils/calculate-active-index.js";
2
2
  import { sortByDomNode } from "../utils/focus-management.js";
3
- import { getContext } from "svelte";
3
+ import { getContext, setContext } from "svelte";
4
4
  export var MenuStates;
5
5
  (function (MenuStates) {
6
6
  MenuStates[MenuStates["Open"] = 0] = "Open";
@@ -14,7 +14,7 @@ export var ActivationTrigger;
14
14
  export function useMenuContext(component) {
15
15
  const context = getContext("MenuContext");
16
16
  if (!context) {
17
- let err = new Error(`<${component} /> is missing a parent <Menu /> component.`);
17
+ const err = new Error(`<${component} /> is missing a parent <Menu /> component.`);
18
18
  if (Error.captureStackTrace)
19
19
  Error.captureStackTrace(err, useMenuContext);
20
20
  throw err;
@@ -22,8 +22,8 @@ export function useMenuContext(component) {
22
22
  return context;
23
23
  }
24
24
  function adjustOrderedState(state, adjustment = (i) => i) {
25
- let currentActiveItem = state.activeItemIndex !== null ? state.items[state.activeItemIndex] : null;
26
- let sortedItems = sortByDomNode(adjustment(state.items.slice()), (item) => item.dataRef.current.domRef.current);
25
+ const currentActiveItem = state.activeItemIndex !== null ? state.items[state.activeItemIndex] : null;
26
+ const sortedItems = sortByDomNode(adjustment(state.items.slice()), (item) => item.dataRef.current.domRef.current);
27
27
  // If we inserted an item before the current active item then the active item index
28
28
  // would be wrong. To fix this, we will re-lookup the correct index.
29
29
  let adjustedActiveItemIndex = currentActiveItem ? sortedItems.indexOf(currentActiveItem) : null;
@@ -36,9 +36,9 @@ function adjustOrderedState(state, adjustment = (i) => i) {
36
36
  activeItemIndex: adjustedActiveItemIndex,
37
37
  };
38
38
  }
39
- export const stateReducer = (initialState) => {
40
- let _state = $state(initialState);
41
- return {
39
+ export const createMenuContext = (initialState) => {
40
+ const _state = $state(initialState);
41
+ const context = {
42
42
  get menuState() {
43
43
  return _state.menuState;
44
44
  },
@@ -104,17 +104,17 @@ export const stateReducer = (initialState) => {
104
104
  // or if the previous DOM node is already the first DOM node, then we don't
105
105
  // have to sort all the DOM nodes.
106
106
  else if (action.focus === Focus.Previous) {
107
- let activeItemIdx = _state.activeItemIndex;
107
+ const activeItemIdx = _state.activeItemIndex;
108
108
  if (activeItemIdx !== null) {
109
- let currentDom = _state.items[activeItemIdx].dataRef.current.domRef;
110
- let previousItemIndex = calculateActiveIndex(action, {
109
+ const currentDom = _state.items[activeItemIdx].dataRef.current.domRef;
110
+ const previousItemIndex = calculateActiveIndex(action, {
111
111
  resolveItems: () => _state.items,
112
112
  resolveActiveIndex: () => _state.activeItemIndex,
113
113
  resolveId: (item) => item.id,
114
114
  resolveDisabled: (item) => item.dataRef.current.disabled,
115
115
  });
116
116
  if (previousItemIndex !== null) {
117
- let previousDom = _state.items[previousItemIndex].dataRef.current.domRef;
117
+ const previousDom = _state.items[previousItemIndex].dataRef.current.domRef;
118
118
  if (
119
119
  // Next to each other
120
120
  currentDom.current?.previousElementSibling === previousDom.current ||
@@ -132,17 +132,17 @@ export const stateReducer = (initialState) => {
132
132
  // if the next DOM node is already the last DOM node, then we don't have to
133
133
  // sort all the DOM nodes.
134
134
  else if (action.focus === Focus.Next) {
135
- let activeItemIdx = _state.activeItemIndex;
135
+ const activeItemIdx = _state.activeItemIndex;
136
136
  if (activeItemIdx !== null) {
137
- let currentDom = _state.items[activeItemIdx].dataRef.current.domRef;
138
- let nextItemIndex = calculateActiveIndex(action, {
137
+ const currentDom = _state.items[activeItemIdx].dataRef.current.domRef;
138
+ const nextItemIndex = calculateActiveIndex(action, {
139
139
  resolveItems: () => _state.items,
140
140
  resolveActiveIndex: () => _state.activeItemIndex,
141
141
  resolveId: (item) => item.id,
142
142
  resolveDisabled: (item) => item.dataRef.current.disabled,
143
143
  });
144
144
  if (nextItemIndex !== null) {
145
- let nextDom = _state.items[nextItemIndex].dataRef.current.domRef;
145
+ const nextDom = _state.items[nextItemIndex].dataRef.current.domRef;
146
146
  if (
147
147
  // Next to each other
148
148
  currentDom.current?.nextElementSibling === nextDom.current ||
@@ -157,8 +157,8 @@ export const stateReducer = (initialState) => {
157
157
  // Slow path:
158
158
  //
159
159
  // Ensure all the items are correctly sorted according to DOM position
160
- let adjustedState = adjustOrderedState(_state);
161
- let activeItemIndex = calculateActiveIndex(action, {
160
+ const adjustedState = adjustOrderedState(_state);
161
+ const activeItemIndex = calculateActiveIndex(action, {
162
162
  resolveItems: () => adjustedState.items,
163
163
  resolveActiveIndex: () => adjustedState.activeItemIndex,
164
164
  resolveId: (item) => item.id,
@@ -169,16 +169,16 @@ export const stateReducer = (initialState) => {
169
169
  return _state;
170
170
  },
171
171
  search(value) {
172
- let wasAlreadySearching = _state.searchQuery !== "";
173
- let offset = wasAlreadySearching ? 0 : 1;
174
- let searchQuery = _state.searchQuery + value.toLowerCase();
175
- let reOrderedItems = _state.activeItemIndex !== null
172
+ const wasAlreadySearching = _state.searchQuery !== "";
173
+ const offset = wasAlreadySearching ? 0 : 1;
174
+ const searchQuery = _state.searchQuery + value.toLowerCase();
175
+ const reOrderedItems = _state.activeItemIndex !== null
176
176
  ? _state.items
177
177
  .slice(_state.activeItemIndex + offset)
178
178
  .concat(_state.items.slice(0, _state.activeItemIndex + offset))
179
179
  : _state.items;
180
- let matchingItem = reOrderedItems.find((item) => item.dataRef.current.textValue?.startsWith(searchQuery) && !item.dataRef.current.disabled);
181
- let matchIdx = matchingItem ? _state.items.indexOf(matchingItem) : -1;
180
+ const matchingItem = reOrderedItems.find((item) => item.dataRef.current.textValue?.startsWith(searchQuery) && !item.dataRef.current.disabled);
181
+ const matchIdx = matchingItem ? _state.items.indexOf(matchingItem) : -1;
182
182
  if (matchIdx === -1 || matchIdx === _state.activeItemIndex) {
183
183
  _state.searchQuery = searchQuery;
184
184
  return _state;
@@ -195,15 +195,15 @@ export const stateReducer = (initialState) => {
195
195
  return _state;
196
196
  },
197
197
  registerItem(id, dataRef) {
198
- let item = { id, dataRef };
199
- let adjustedState = adjustOrderedState(_state, (items) => [...items, item]);
198
+ const item = { id, dataRef };
199
+ const adjustedState = adjustOrderedState(_state, (items) => [...items, item]);
200
200
  _state.items = adjustedState.items;
201
201
  _state.activeItemIndex = adjustedState.activeItemIndex;
202
202
  return _state;
203
203
  },
204
204
  unregisterItem(id) {
205
- let adjustedState = adjustOrderedState(_state, (items) => {
206
- let idx = items.findIndex((a) => a.id === id);
205
+ const adjustedState = adjustOrderedState(_state, (items) => {
206
+ const idx = items.findIndex((a) => a.id === id);
207
207
  if (idx !== -1)
208
208
  items.splice(idx, 1);
209
209
  return items;
@@ -226,4 +226,6 @@ export const stateReducer = (initialState) => {
226
226
  return _state;
227
227
  },
228
228
  };
229
+ setContext("MenuContext", context);
230
+ return context;
229
231
  };
@@ -22,7 +22,7 @@ let {
22
22
  autofocus = false,
23
23
  ...theirProps
24
24
  } = $props();
25
- const disabled = $derived(providedDisabled?.value ?? theirDisabled);
25
+ const disabled = $derived(providedDisabled.current ?? theirDisabled);
26
26
  const labelledBy = useLabelledBy();
27
27
  const describedBy = useDescribedBy();
28
28
  const { isFocusVisible: focus, focusProps } = $derived(
@@ -33,7 +33,7 @@ let {
33
33
  tabIndex,
34
34
  ...theirProps
35
35
  } = $props();
36
- const disabled = $derived(providedDisabled?.value ?? theirDisabled);
36
+ const disabled = $derived(providedDisabled.current ?? theirDisabled);
37
37
  const groupContext = getContext("GroupContext");
38
38
  $effect(() => {
39
39
  if (groupContext) groupContext.switchElement = ref ?? null;
@@ -22,7 +22,7 @@ let {
22
22
  invalid = false,
23
23
  ...theirProps
24
24
  } = $props();
25
- const disabled = $derived(providedDisabled?.value ?? theirDisabled);
25
+ const disabled = $derived(providedDisabled.current || theirDisabled);
26
26
  const labelledBy = useLabelledBy();
27
27
  const describedBy = useDescribedBy();
28
28
  const { isFocusVisible: focus, focusProps } = $derived(
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@pzerelles/headlessui-svelte",
3
- "version": "2.1.2-next.22",
3
+ "version": "2.1.2-next.23",
4
4
  "exports": {
5
5
  ".": {
6
6
  "types": "./dist/index.d.ts",
@@ -40,7 +40,7 @@
40
40
  "prettier-plugin-svelte": "^3.2.6",
41
41
  "prettier-plugin-tailwindcss": "^0.6.6",
42
42
  "publint": "^0.2.11",
43
- "svelte": "5.0.0-next.249",
43
+ "svelte": "5.0.0-next.252",
44
44
  "svelte-check": "^3.8.6",
45
45
  "tailwindcss": "^3.4.12",
46
46
  "tslib": "^2.7.0",