lithesome 0.6.2 → 0.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.
Files changed (56) hide show
  1. package/README.md +3 -3
  2. package/dist/components/Combobox/ComboboxArrow.svelte +22 -0
  3. package/dist/components/Combobox/ComboboxArrow.svelte.d.ts +17 -0
  4. package/dist/components/Combobox/{ComboboxDropdown.svelte → ComboboxContent.svelte} +19 -12
  5. package/dist/components/Combobox/ComboboxContent.svelte.d.ts +17 -0
  6. package/dist/components/Combobox/context.svelte.d.ts +1 -3
  7. package/dist/components/Combobox/context.svelte.js +1 -3
  8. package/dist/components/Combobox/index.d.ts +2 -1
  9. package/dist/components/Combobox/index.js +2 -1
  10. package/dist/components/Hovercard/HovercardArrow.svelte +22 -0
  11. package/dist/components/Hovercard/HovercardArrow.svelte.d.ts +17 -0
  12. package/dist/components/Hovercard/HovercardContent.svelte +12 -5
  13. package/dist/components/Hovercard/HovercardContent.svelte.d.ts +2 -2
  14. package/dist/components/Hovercard/context.svelte.d.ts +0 -2
  15. package/dist/components/Hovercard/context.svelte.js +0 -2
  16. package/dist/components/Hovercard/index.d.ts +1 -0
  17. package/dist/components/Hovercard/index.js +1 -0
  18. package/dist/components/Menu/MenuArrow.svelte +22 -0
  19. package/dist/components/Menu/MenuArrow.svelte.d.ts +17 -0
  20. package/dist/components/Menu/{MenuDropdown.svelte → MenuContent.svelte} +19 -12
  21. package/dist/components/Menu/MenuContent.svelte.d.ts +17 -0
  22. package/dist/components/Menu/MenuTrigger.svelte +1 -1
  23. package/dist/components/Menu/context.svelte.d.ts +0 -2
  24. package/dist/components/Menu/context.svelte.js +0 -2
  25. package/dist/components/Menu/index.d.ts +1 -1
  26. package/dist/components/Menu/index.js +1 -1
  27. package/dist/components/Pin/PinInput.svelte +3 -1
  28. package/dist/components/Pin/context.svelte.d.ts +1 -1
  29. package/dist/components/Pin/context.svelte.js +2 -2
  30. package/dist/components/Popover/PopoverArrow.svelte +22 -0
  31. package/dist/components/Popover/PopoverArrow.svelte.d.ts +17 -0
  32. package/dist/components/Popover/PopoverContent.svelte +12 -5
  33. package/dist/components/Popover/PopoverContent.svelte.d.ts +2 -2
  34. package/dist/components/Popover/context.svelte.d.ts +0 -2
  35. package/dist/components/Popover/context.svelte.js +0 -2
  36. package/dist/components/Popover/index.d.ts +1 -0
  37. package/dist/components/Popover/index.js +1 -0
  38. package/dist/components/Select/PopoverArrow.svelte +22 -0
  39. package/dist/components/Select/PopoverArrow.svelte.d.ts +17 -0
  40. package/dist/components/Select/{SelectDropdown.svelte → SelectContent.svelte} +19 -12
  41. package/dist/components/Select/SelectContent.svelte.d.ts +17 -0
  42. package/dist/components/Select/SelectTrigger.svelte +1 -1
  43. package/dist/components/Select/context.svelte.d.ts +0 -2
  44. package/dist/components/Select/context.svelte.js +1 -3
  45. package/dist/components/Select/index.d.ts +1 -1
  46. package/dist/components/Select/index.js +1 -1
  47. package/dist/internal/helpers/anchor.d.ts +6 -1
  48. package/dist/internal/helpers/anchor.js +27 -4
  49. package/dist/internal/helpers/context.svelte.d.ts +4 -1
  50. package/dist/internal/helpers/context.svelte.js +3 -0
  51. package/dist/internal/helpers/log.js +1 -1
  52. package/dist/internal/types.d.ts +5 -5
  53. package/package.json +1 -1
  54. package/dist/components/Combobox/ComboboxDropdown.svelte.d.ts +0 -17
  55. package/dist/components/Menu/MenuDropdown.svelte.d.ts +0 -17
  56. package/dist/components/Select/SelectDropdown.svelte.d.ts +0 -17
package/README.md CHANGED
@@ -17,18 +17,18 @@ pnpm i -D lithesome
17
17
 
18
18
  ```svelte
19
19
  <script>
20
- import { Menu, MenuTrigger, MenuDropdown, MenuItem } from 'lithesome';
20
+ import { Menu, MenuTrigger, MenuContent, MenuItem } from 'lithesome';
21
21
  </script>
22
22
 
23
23
  <Menu>
24
24
  <MenuTrigger>
25
25
  <button>Auth</button>
26
26
  </MenuTrigger>
27
- <MenuDropdown>
27
+ <MenuContent>
28
28
  <MenuItem>My Profile</MenuItem>
29
29
  <MenuItem>Account Settings</MenuItem>
30
30
  <MenuItem>Logout</MenuItem>
31
- </MenuDropdown>
31
+ </MenuContent>
32
32
  </Menu>
33
33
  ```
34
34
 
@@ -0,0 +1,22 @@
1
+ <script lang="ts">import { context } from "./Combobox.svelte";
2
+ import { useActions, classProp, log } from "../../internal/index.js";
3
+ import { onMount } from "svelte";
4
+ let { class: klass, use = [], self = $bindable(), ...props } = $props();
5
+ const ctx = context();
6
+ onMount(() => {
7
+ if (!ctx)
8
+ log.error("<ComboboxArrow /> must be a child element of <ComboboxContent />");
9
+ if (!self)
10
+ return;
11
+ ctx.arrow = self;
12
+ });
13
+ </script>
14
+
15
+ <div
16
+ bind:this={self}
17
+ use:useActions={use}
18
+ id={ctx.uid('arrow')}
19
+ class={classProp(klass, { visible: ctx.visible })}
20
+ data-popoverarrow=""
21
+ {...props}
22
+ />
@@ -0,0 +1,17 @@
1
+ import { SvelteComponent } from "svelte";
2
+ import { type BasePropsNoChildren } from '../../internal/index.js';
3
+ declare const __propDef: {
4
+ props: BasePropsNoChildren<HTMLDivElement, {
5
+ visible: boolean;
6
+ }>;
7
+ events: {
8
+ [evt: string]: CustomEvent<any>;
9
+ };
10
+ slots: {};
11
+ };
12
+ export type ComboboxArrowProps = typeof __propDef.props;
13
+ export type ComboboxArrowEvents = typeof __propDef.events;
14
+ export type ComboboxArrowSlots = typeof __propDef.slots;
15
+ export default class ComboboxArrow extends SvelteComponent<ComboboxArrowProps, ComboboxArrowEvents, ComboboxArrowSlots> {
16
+ }
17
+ export {};
@@ -22,34 +22,41 @@ let {
22
22
  ...props
23
23
  } = $props();
24
24
  const ctx = context();
25
- let dropdownCleanup = $state(void 0);
25
+ let contentCleanup = $state(void 0);
26
26
  const _transition = getTransition(transition);
27
27
  const attrs = $derived({
28
- id: ctx.uid("dropdown"),
28
+ id: ctx.uid("content"),
29
29
  "aria-labelledby": ctx.uid("trigger"),
30
30
  role: "listbox",
31
31
  class: classProp(klass, { visible: ctx.visible }),
32
- "data-comboboxdropdown": "",
32
+ "data-comboboxcontent": "",
33
33
  hidden: !ctx.mounted || void 0
34
34
  });
35
35
  onMount(() => {
36
36
  if (!ctx)
37
- log.error("<ComboboxDropdown> Must be a direct child of <Combobox />");
37
+ log.error("<ComboboxContent> Must be a direct child of <Combobox />");
38
38
  });
39
39
  $effect(() => {
40
40
  if (ctx.visible && self)
41
- ctx.dropdown = self;
41
+ ctx.content = self;
42
42
  });
43
43
  $effect(() => {
44
- if (ctx.visible && ctx.trigger && ctx.dropdown) {
45
- dropdownCleanup = anchorElement(ctx.trigger, ctx.dropdown, {
46
- placement,
47
- constrainViewport,
48
- sameWidth
49
- });
44
+ if (ctx.visible && ctx.trigger && ctx.content) {
45
+ contentCleanup = anchorElement(
46
+ {
47
+ anchor: ctx.trigger,
48
+ target: ctx.content,
49
+ arrow: ctx.arrow
50
+ },
51
+ {
52
+ placement,
53
+ constrainViewport,
54
+ sameWidth
55
+ }
56
+ );
50
57
  }
51
58
  return () => {
52
- dropdownCleanup?.();
59
+ contentCleanup?.();
53
60
  };
54
61
  });
55
62
  </script>
@@ -0,0 +1,17 @@
1
+ import { SvelteComponent } from "svelte";
2
+ import { type BaseProps, type ContentProps } from '../../internal/index.js';
3
+ declare const __propDef: {
4
+ props: BaseProps<HTMLDivElement, {
5
+ visible: boolean;
6
+ }> & ContentProps;
7
+ events: {
8
+ [evt: string]: CustomEvent<any>;
9
+ };
10
+ slots: {};
11
+ };
12
+ export type ComboboxContentProps = typeof __propDef.props;
13
+ export type ComboboxContentEvents = typeof __propDef.events;
14
+ export type ComboboxContentSlots = typeof __propDef.slots;
15
+ export default class ComboboxContent extends SvelteComponent<ComboboxContentProps, ComboboxContentEvents, ComboboxContentSlots> {
16
+ }
17
+ export {};
@@ -15,13 +15,11 @@ interface Hooks<ValueType> {
15
15
  newLabel?: string;
16
16
  }) => void;
17
17
  }
18
- export declare class ComboboxContext<ValueType = any> extends Context<Hooks<ValueType>> {
18
+ export declare class ComboboxContext<ValueType = any> extends Context<Hooks<ValueType>, HTMLInputElement> {
19
19
  #private;
20
20
  visible: boolean;
21
21
  hoveredIndex: number;
22
22
  options: HTMLElement[];
23
- trigger: HTMLInputElement | null;
24
- dropdown: HTMLElement | null;
25
23
  selectedOptions: HTMLElement[];
26
24
  mounted: boolean;
27
25
  touched: boolean;
@@ -4,8 +4,6 @@ export class ComboboxContext extends Context {
4
4
  visible = $state(true);
5
5
  hoveredIndex = $state(-1);
6
6
  options = $state([]);
7
- trigger = $state(null);
8
- dropdown = $state(null);
9
7
  selectedOptions = $state([]);
10
8
  mounted = $state(false);
11
9
  touched = $state(false);
@@ -25,7 +23,7 @@ export class ComboboxContext extends Context {
25
23
  this.visible = !this.visible;
26
24
  }
27
25
  queryElements() {
28
- const elements = removeDisabledElements(`#${this.uid('dropdown')} [data-comboboxoption]`);
26
+ const elements = removeDisabledElements(`#${this.uid('content')} [data-comboboxoption]`);
29
27
  if (!elements)
30
28
  return;
31
29
  this.options = elements;
@@ -1,4 +1,5 @@
1
1
  export { default as Combobox } from './Combobox.svelte';
2
- export { default as ComboboxDropdown } from './ComboboxDropdown.svelte';
2
+ export { default as ComboboxContent } from './ComboboxContent.svelte';
3
3
  export { default as ComboboxInput } from './ComboboxInput.svelte';
4
4
  export { default as ComboboxOption } from './ComboboxOption.svelte';
5
+ export { default as ComboboxArrow } from './ComboboxArrow.svelte';
@@ -1,4 +1,5 @@
1
1
  export { default as Combobox } from './Combobox.svelte';
2
- export { default as ComboboxDropdown } from './ComboboxDropdown.svelte';
2
+ export { default as ComboboxContent } from './ComboboxContent.svelte';
3
3
  export { default as ComboboxInput } from './ComboboxInput.svelte';
4
4
  export { default as ComboboxOption } from './ComboboxOption.svelte';
5
+ export { default as ComboboxArrow } from './ComboboxArrow.svelte';
@@ -0,0 +1,22 @@
1
+ <script lang="ts">import { context } from "./Hovercard.svelte";
2
+ import { useActions, classProp, log } from "../../internal/index.js";
3
+ import { onMount } from "svelte";
4
+ let { class: klass, use = [], self = $bindable(), ...props } = $props();
5
+ const ctx = context();
6
+ onMount(() => {
7
+ if (!ctx)
8
+ log.error("<HovercardArrow /> must be a child element of <HovercardContent />");
9
+ if (!self)
10
+ return;
11
+ ctx.arrow = self;
12
+ });
13
+ </script>
14
+
15
+ <div
16
+ bind:this={self}
17
+ use:useActions={use}
18
+ id={ctx.uid('arrow')}
19
+ class={classProp(klass, { visible: ctx.visible })}
20
+ data-hovercardarrow=""
21
+ {...props}
22
+ />
@@ -0,0 +1,17 @@
1
+ import { SvelteComponent } from "svelte";
2
+ import { type BasePropsNoChildren } from '../../internal/index.js';
3
+ declare const __propDef: {
4
+ props: BasePropsNoChildren<HTMLDivElement, {
5
+ visible: boolean;
6
+ }>;
7
+ events: {
8
+ [evt: string]: CustomEvent<any>;
9
+ };
10
+ slots: {};
11
+ };
12
+ export type HovercardArrowProps = typeof __propDef.props;
13
+ export type HovercardArrowEvents = typeof __propDef.events;
14
+ export type HovercardArrowSlots = typeof __propDef.slots;
15
+ export default class HovercardArrow extends SvelteComponent<HovercardArrowProps, HovercardArrowEvents, HovercardArrowSlots> {
16
+ }
17
+ export {};
@@ -42,11 +42,18 @@ $effect(() => {
42
42
  });
43
43
  $effect(() => {
44
44
  if (ctx.visible && ctx.trigger && ctx.content) {
45
- contentCleanup = anchorElement(ctx.trigger, ctx.content, {
46
- placement,
47
- constrainViewport,
48
- sameWidth
49
- });
45
+ contentCleanup = anchorElement(
46
+ {
47
+ anchor: ctx.trigger,
48
+ target: ctx.content,
49
+ arrow: ctx.arrow
50
+ },
51
+ {
52
+ placement,
53
+ constrainViewport,
54
+ sameWidth
55
+ }
56
+ );
50
57
  }
51
58
  return () => {
52
59
  contentCleanup?.();
@@ -1,9 +1,9 @@
1
1
  import { SvelteComponent } from "svelte";
2
- import { type BaseProps, type Handler, type DropdownProps } from '../../internal/index.js';
2
+ import { type BaseProps, type Handler, type ContentProps } from '../../internal/index.js';
3
3
  declare const __propDef: {
4
4
  props: BaseProps<HTMLDivElement, {
5
5
  visible: boolean;
6
- }> & DropdownProps & {
6
+ }> & ContentProps & {
7
7
  onMouseenter?: Handler<MouseEvent, HTMLDivElement> | undefined;
8
8
  onMouseleave?: Handler<MouseEvent, HTMLDivElement> | undefined;
9
9
  };
@@ -8,8 +8,6 @@ interface Init {
8
8
  export declare class HovercardContext extends Context {
9
9
  #private;
10
10
  visible: boolean;
11
- trigger: HTMLElement | null;
12
- content: HTMLElement | null;
13
11
  timeout: number | null;
14
12
  delays: {
15
13
  in: number;
@@ -1,8 +1,6 @@
1
1
  import { Context, effects } from '../../internal/index.js';
2
2
  export class HovercardContext extends Context {
3
3
  visible = $state(false);
4
- trigger = $state(null);
5
- content = $state(null);
6
4
  timeout = $state(null);
7
5
  delays = $state({ in: 700, out: 700 });
8
6
  hovered = $state(false);
@@ -1,3 +1,4 @@
1
1
  export { default as Hovercard } from './Hovercard.svelte';
2
2
  export { default as HovercardTrigger } from './HovercardTrigger.svelte';
3
3
  export { default as HovercardContent } from './HovercardContent.svelte';
4
+ export { default as HovercardArrow } from './HovercardArrow.svelte';
@@ -1,3 +1,4 @@
1
1
  export { default as Hovercard } from './Hovercard.svelte';
2
2
  export { default as HovercardTrigger } from './HovercardTrigger.svelte';
3
3
  export { default as HovercardContent } from './HovercardContent.svelte';
4
+ export { default as HovercardArrow } from './HovercardArrow.svelte';
@@ -0,0 +1,22 @@
1
+ <script lang="ts">import { context } from "./Menu.svelte";
2
+ import { useActions, classProp, log } from "../../internal/index.js";
3
+ import { onMount } from "svelte";
4
+ let { class: klass, use = [], self = $bindable(), ...props } = $props();
5
+ const ctx = context();
6
+ onMount(() => {
7
+ if (!ctx)
8
+ log.error("<MenuArrow /> must be a child element of <MenuContent />");
9
+ if (!self)
10
+ return;
11
+ ctx.arrow = self;
12
+ });
13
+ </script>
14
+
15
+ <div
16
+ bind:this={self}
17
+ use:useActions={use}
18
+ id={ctx.uid('arrow')}
19
+ class={classProp(klass, { visible: ctx.visible })}
20
+ data-menuarrow=""
21
+ {...props}
22
+ />
@@ -0,0 +1,17 @@
1
+ import { SvelteComponent } from "svelte";
2
+ import { type BasePropsNoChildren } from '../../internal/index.js';
3
+ declare const __propDef: {
4
+ props: BasePropsNoChildren<HTMLDivElement, {
5
+ visible: boolean;
6
+ }>;
7
+ events: {
8
+ [evt: string]: CustomEvent<any>;
9
+ };
10
+ slots: {};
11
+ };
12
+ export type MenuArrowProps = typeof __propDef.props;
13
+ export type MenuArrowEvents = typeof __propDef.events;
14
+ export type MenuArrowSlots = typeof __propDef.slots;
15
+ export default class MenuArrow extends SvelteComponent<MenuArrowProps, MenuArrowEvents, MenuArrowSlots> {
16
+ }
17
+ export {};
@@ -22,33 +22,40 @@ let {
22
22
  ...props
23
23
  } = $props();
24
24
  const ctx = context();
25
- let dropdownCleanup = $state(void 0);
25
+ let contentCleanup = $state(void 0);
26
26
  const _transition = getTransition(transition);
27
27
  const attrs = $derived({
28
- id: ctx.uid("dropdown"),
28
+ id: ctx.uid("content"),
29
29
  "aria-labelledby": ctx.uid("trigger"),
30
30
  role: "menu",
31
31
  class: classProp(klass, { visible: ctx.visible }),
32
- "data-menudropdown": ""
32
+ "data-menucontent": ""
33
33
  });
34
34
  onMount(async () => {
35
35
  if (!ctx)
36
- log.error("<MenuDropdown> Must be a direct child of <Menu />");
36
+ log.error("<MenuContent> Must be a direct child of <Menu />");
37
37
  });
38
38
  $effect(() => {
39
39
  if (ctx.visible && self)
40
- ctx.dropdown = self;
40
+ ctx.content = self;
41
41
  });
42
42
  $effect(() => {
43
- if (ctx.visible && ctx.trigger && ctx.dropdown) {
44
- dropdownCleanup = anchorElement(ctx.trigger, ctx.dropdown, {
45
- placement,
46
- constrainViewport,
47
- sameWidth
48
- });
43
+ if (ctx.visible && ctx.trigger && ctx.content) {
44
+ contentCleanup = anchorElement(
45
+ {
46
+ anchor: ctx.trigger,
47
+ target: ctx.content,
48
+ arrow: ctx.arrow
49
+ },
50
+ {
51
+ placement,
52
+ constrainViewport,
53
+ sameWidth
54
+ }
55
+ );
49
56
  }
50
57
  return () => {
51
- dropdownCleanup?.();
58
+ contentCleanup?.();
52
59
  };
53
60
  });
54
61
  </script>
@@ -0,0 +1,17 @@
1
+ import { SvelteComponent } from "svelte";
2
+ import { type BaseProps, type ContentProps } from '../../internal/index.js';
3
+ declare const __propDef: {
4
+ props: BaseProps<HTMLDivElement, {
5
+ visible: boolean;
6
+ }> & ContentProps;
7
+ events: {
8
+ [evt: string]: CustomEvent<any>;
9
+ };
10
+ slots: {};
11
+ };
12
+ export type MenuContentProps = typeof __propDef.props;
13
+ export type MenuContentEvents = typeof __propDef.events;
14
+ export type MenuContentSlots = typeof __propDef.slots;
15
+ export default class MenuContent extends SvelteComponent<MenuContentProps, MenuContentEvents, MenuContentSlots> {
16
+ }
17
+ export {};
@@ -35,7 +35,7 @@ $effect(() => {
35
35
  if (ctx.visible) {
36
36
  setNodeProps(target, {
37
37
  "aria-expanded": "true",
38
- "aria-controls": ctx.uid("dropdown")
38
+ "aria-controls": ctx.uid("content")
39
39
  });
40
40
  }
41
41
  if (!ctx.visible) {
@@ -3,8 +3,6 @@ export declare class MenuContext extends Context {
3
3
  #private;
4
4
  visible: boolean;
5
5
  hoveredIndex: number;
6
- trigger: HTMLElement | null;
7
- dropdown: HTMLElement | null;
8
6
  items: string[];
9
7
  hoveredItem: string | undefined;
10
8
  constructor();
@@ -2,8 +2,6 @@ import { calculateIndex, disableScroll, Context, effects } from '../../internal/
2
2
  export class MenuContext extends Context {
3
3
  visible = $state(false);
4
4
  hoveredIndex = $state(-1);
5
- trigger = $state(null);
6
- dropdown = $state(null);
7
5
  items = $state([]);
8
6
  hoveredItem = $derived(this.items[this.hoveredIndex]);
9
7
  constructor() {
@@ -1,4 +1,4 @@
1
1
  export { default as Menu } from './Menu.svelte';
2
2
  export { default as MenuTrigger } from './MenuTrigger.svelte';
3
- export { default as MenuDropdown } from './MenuDropdown.svelte';
3
+ export { default as MenuContent } from './MenuContent.svelte';
4
4
  export { default as MenuItem } from './MenuItem.svelte';
@@ -1,4 +1,4 @@
1
1
  export { default as Menu } from './Menu.svelte';
2
2
  export { default as MenuTrigger } from './MenuTrigger.svelte';
3
- export { default as MenuDropdown } from './MenuDropdown.svelte';
3
+ export { default as MenuContent } from './MenuContent.svelte';
4
4
  export { default as MenuItem } from './MenuItem.svelte';
@@ -36,6 +36,8 @@ const handleInput = async (event) => {
36
36
  if (e.inputType !== "insertText" && e.inputType !== "deleteContentBackward")
37
37
  return;
38
38
  await tick();
39
+ if (e.target.value.length > 1)
40
+ e.target.value = e.data;
39
41
  ctx.setValue(index, e.data);
40
42
  if (value.length === 1) {
41
43
  moveFocus("next");
@@ -122,7 +124,7 @@ const moveFocus = (direction) => {
122
124
  disabled={ctx.disabled}
123
125
  placeholder={focused ? '' : ctx.placeholder}
124
126
  data-pininput=""
125
- data-filled={ctx.filled || undefined}
127
+ data-filled={ctx.filled}
126
128
  oninput={handleInput}
127
129
  onkeydown={handleKeyDown}
128
130
  onfocus={handleFocus}
@@ -6,7 +6,7 @@ interface Init {
6
6
  placeholder: string;
7
7
  }
8
8
  interface Hooks {
9
- onChange?: (value: string) => void;
9
+ onChange: (value: string) => void;
10
10
  }
11
11
  export declare class PinContext extends Context<Hooks> {
12
12
  #private;
@@ -6,7 +6,7 @@ export class PinContext extends Context {
6
6
  type = $state('text');
7
7
  placeholder = $state('');
8
8
  transformedValue = $derived(this.value.join());
9
- filled = $derived(this.value.every((el) => el?.length));
9
+ filled = $derived(this.value.length === this.inputs.length && this.value.every((el) => el?.length === 1));
10
10
  constructor(init, hooks) {
11
11
  super('pin', hooks);
12
12
  this.value = init.value;
@@ -22,7 +22,7 @@ export class PinContext extends Context {
22
22
  }
23
23
  #effects = effects(() => {
24
24
  $effect(() => {
25
- this.hooks?.onChange?.(this.transformedValue);
25
+ this.hooks?.onChange(this.transformedValue);
26
26
  });
27
27
  });
28
28
  }
@@ -0,0 +1,22 @@
1
+ <script lang="ts">import { context } from "./Popover.svelte";
2
+ import { useActions, classProp, log } from "../../internal/index.js";
3
+ import { onMount } from "svelte";
4
+ let { class: klass, use = [], self = $bindable(), ...props } = $props();
5
+ const ctx = context();
6
+ onMount(() => {
7
+ if (!ctx)
8
+ log.error("<PopoverArrow /> must be a child element of <PopoverContent />");
9
+ if (!self)
10
+ return;
11
+ ctx.arrow = self;
12
+ });
13
+ </script>
14
+
15
+ <div
16
+ bind:this={self}
17
+ use:useActions={use}
18
+ id={ctx.uid('arrow')}
19
+ class={classProp(klass, { visible: ctx.visible })}
20
+ data-popoverarrow=""
21
+ {...props}
22
+ />
@@ -0,0 +1,17 @@
1
+ import { SvelteComponent } from "svelte";
2
+ import { type BasePropsNoChildren } from '../../internal/index.js';
3
+ declare const __propDef: {
4
+ props: BasePropsNoChildren<HTMLDivElement, {
5
+ visible: boolean;
6
+ }>;
7
+ events: {
8
+ [evt: string]: CustomEvent<any>;
9
+ };
10
+ slots: {};
11
+ };
12
+ export type PopoverArrowProps = typeof __propDef.props;
13
+ export type PopoverArrowEvents = typeof __propDef.events;
14
+ export type PopoverArrowSlots = typeof __propDef.slots;
15
+ export default class PopoverArrow extends SvelteComponent<PopoverArrowProps, PopoverArrowEvents, PopoverArrowSlots> {
16
+ }
17
+ export {};
@@ -42,11 +42,18 @@ $effect(() => {
42
42
  });
43
43
  $effect(() => {
44
44
  if (ctx.visible && ctx.trigger && ctx.content) {
45
- contentCleanup = anchorElement(ctx.trigger, ctx.content, {
46
- placement,
47
- constrainViewport,
48
- sameWidth
49
- });
45
+ contentCleanup = anchorElement(
46
+ {
47
+ anchor: ctx.trigger,
48
+ target: ctx.content,
49
+ arrow: ctx.arrow
50
+ },
51
+ {
52
+ placement,
53
+ constrainViewport,
54
+ sameWidth
55
+ }
56
+ );
50
57
  }
51
58
  return () => {
52
59
  contentCleanup?.();
@@ -1,9 +1,9 @@
1
1
  import { SvelteComponent } from "svelte";
2
- import { type BaseProps, type DropdownProps } from '../../internal/index.js';
2
+ import { type BaseProps, type ContentProps } from '../../internal/index.js';
3
3
  declare const __propDef: {
4
4
  props: BaseProps<HTMLDivElement, {
5
5
  visible: boolean;
6
- }> & DropdownProps;
6
+ }> & ContentProps;
7
7
  events: {
8
8
  [evt: string]: CustomEvent<any>;
9
9
  };
@@ -8,8 +8,6 @@ interface Hooks {
8
8
  export declare class PopoverContext extends Context<Hooks> {
9
9
  #private;
10
10
  visible: boolean;
11
- trigger: HTMLElement | null;
12
- content: HTMLElement | null;
13
11
  constructor(init: Init, hooks: Hooks);
14
12
  close(): void;
15
13
  toggle(): void;
@@ -1,8 +1,6 @@
1
1
  import { Context, effects } from '../../internal/index.js';
2
2
  export class PopoverContext extends Context {
3
3
  visible = $state(false);
4
- trigger = $state(null);
5
- content = $state(null);
6
4
  constructor(init, hooks) {
7
5
  super('popover', hooks);
8
6
  this.visible = init.visible;
@@ -1,3 +1,4 @@
1
1
  export { default as Popover } from './Popover.svelte';
2
2
  export { default as PopoverTrigger } from './PopoverTrigger.svelte';
3
3
  export { default as PopoverContent } from './PopoverContent.svelte';
4
+ export { default as PopoverArrow } from './PopoverArrow.svelte';
@@ -1,3 +1,4 @@
1
1
  export { default as Popover } from './Popover.svelte';
2
2
  export { default as PopoverTrigger } from './PopoverTrigger.svelte';
3
3
  export { default as PopoverContent } from './PopoverContent.svelte';
4
+ export { default as PopoverArrow } from './PopoverArrow.svelte';
@@ -0,0 +1,22 @@
1
+ <script lang="ts">import { context } from "./Select.svelte";
2
+ import { useActions, classProp, log } from "../../internal/index.js";
3
+ import { onMount } from "svelte";
4
+ let { class: klass, use = [], self = $bindable(), ...props } = $props();
5
+ const ctx = context();
6
+ onMount(() => {
7
+ if (!ctx)
8
+ log.error("<SelectArrow /> must be a child element of <SelectContent />");
9
+ if (!self)
10
+ return;
11
+ ctx.arrow = self;
12
+ });
13
+ </script>
14
+
15
+ <div
16
+ bind:this={self}
17
+ use:useActions={use}
18
+ id={ctx.uid('arrow')}
19
+ class={classProp(klass, { visible: ctx.visible })}
20
+ data-selectarrow=""
21
+ {...props}
22
+ />
@@ -0,0 +1,17 @@
1
+ import { SvelteComponent } from "svelte";
2
+ import { type BasePropsNoChildren } from '../../internal/index.js';
3
+ declare const __propDef: {
4
+ props: BasePropsNoChildren<HTMLDivElement, {
5
+ visible: boolean;
6
+ }>;
7
+ events: {
8
+ [evt: string]: CustomEvent<any>;
9
+ };
10
+ slots: {};
11
+ };
12
+ export type PopoverArrowProps = typeof __propDef.props;
13
+ export type PopoverArrowEvents = typeof __propDef.events;
14
+ export type PopoverArrowSlots = typeof __propDef.slots;
15
+ export default class PopoverArrow extends SvelteComponent<PopoverArrowProps, PopoverArrowEvents, PopoverArrowSlots> {
16
+ }
17
+ export {};
@@ -22,34 +22,41 @@ let {
22
22
  ...props
23
23
  } = $props();
24
24
  const ctx = context();
25
- let dropdownCleanup = $state(void 0);
25
+ let contentCleanup = $state(void 0);
26
26
  const _transition = getTransition(transition);
27
27
  const attrs = $derived({
28
- id: ctx.uid("dropdown"),
28
+ id: ctx.uid("content"),
29
29
  "aria-labelledby": ctx.uid("trigger"),
30
30
  role: "listbox",
31
31
  class: classProp(klass, { visible: ctx.visible }),
32
- "data-selectdropdown": "",
32
+ "data-selectcontent": "",
33
33
  hidden: !ctx.mounted || void 0
34
34
  });
35
35
  onMount(() => {
36
36
  if (!ctx)
37
- log.error("<SelectDropdown> Must be a direct child of <Select />");
37
+ log.error("<SelectContent> Must be a direct child of <Select />");
38
38
  });
39
39
  $effect(() => {
40
40
  if (ctx.visible && self)
41
- ctx.dropdown = self;
41
+ ctx.content = self;
42
42
  });
43
43
  $effect(() => {
44
- if (ctx.visible && ctx.trigger && ctx.dropdown) {
45
- dropdownCleanup = anchorElement(ctx.trigger, ctx.dropdown, {
46
- placement,
47
- constrainViewport,
48
- sameWidth
49
- });
44
+ if (ctx.visible && ctx.trigger && ctx.content) {
45
+ contentCleanup = anchorElement(
46
+ {
47
+ anchor: ctx.trigger,
48
+ target: ctx.content,
49
+ arrow: ctx.arrow
50
+ },
51
+ {
52
+ placement,
53
+ constrainViewport,
54
+ sameWidth
55
+ }
56
+ );
50
57
  }
51
58
  return () => {
52
- dropdownCleanup?.();
59
+ contentCleanup?.();
53
60
  };
54
61
  });
55
62
  </script>
@@ -0,0 +1,17 @@
1
+ import { SvelteComponent } from "svelte";
2
+ import { type BaseProps, type ContentProps } from '../../internal/index.js';
3
+ declare const __propDef: {
4
+ props: BaseProps<HTMLDivElement, {
5
+ visible: boolean;
6
+ }> & ContentProps;
7
+ events: {
8
+ [evt: string]: CustomEvent<any>;
9
+ };
10
+ slots: {};
11
+ };
12
+ export type SelectContentProps = typeof __propDef.props;
13
+ export type SelectContentEvents = typeof __propDef.events;
14
+ export type SelectContentSlots = typeof __propDef.slots;
15
+ export default class SelectContent extends SvelteComponent<SelectContentProps, SelectContentEvents, SelectContentSlots> {
16
+ }
17
+ export {};
@@ -63,7 +63,7 @@ $effect(() => {
63
63
  if (ctx.visible) {
64
64
  setNodeProps(target, {
65
65
  "aria-expanded": "true",
66
- "aria-controls": ctx.uid("dropdown")
66
+ "aria-controls": ctx.uid("content")
67
67
  });
68
68
  }
69
69
  if (!ctx.visible) {
@@ -16,8 +16,6 @@ export declare class SelectContext<ValueType = any> extends Context<Hooks<ValueT
16
16
  visible: boolean;
17
17
  hoveredIndex: number;
18
18
  options: HTMLElement[];
19
- trigger: HTMLElement | null;
20
- dropdown: HTMLElement | null;
21
19
  selectedOptions: HTMLElement[];
22
20
  mounted: boolean;
23
21
  multiple: boolean;
@@ -4,8 +4,6 @@ export class SelectContext extends Context {
4
4
  visible = $state(true);
5
5
  hoveredIndex = $state(-1);
6
6
  options = $state([]);
7
- trigger = $state(null);
8
- dropdown = $state(null);
9
7
  selectedOptions = $state([]);
10
8
  mounted = $state(false);
11
9
  multiple = $state(false);
@@ -24,7 +22,7 @@ export class SelectContext extends Context {
24
22
  this.visible = !this.visible;
25
23
  }
26
24
  queryElements() {
27
- const elements = removeDisabledElements(`#${this.uid('dropdown')} [data-selectoption]`);
25
+ const elements = removeDisabledElements(`#${this.uid('content')} [data-selectoption]`);
28
26
  if (!elements)
29
27
  return;
30
28
  this.options = elements;
@@ -1,5 +1,5 @@
1
1
  export { default as Select } from './Select.svelte';
2
2
  export { default as SelectTrigger } from './SelectTrigger.svelte';
3
- export { default as SelectDropdown } from './SelectDropdown.svelte';
3
+ export { default as SelectContent } from './SelectContent.svelte';
4
4
  export { default as SelectOption } from './SelectOption.svelte';
5
5
  export { default as SelectValue } from './SelectValue.svelte';
@@ -1,5 +1,5 @@
1
1
  export { default as Select } from './Select.svelte';
2
2
  export { default as SelectTrigger } from './SelectTrigger.svelte';
3
- export { default as SelectDropdown } from './SelectDropdown.svelte';
3
+ export { default as SelectContent } from './SelectContent.svelte';
4
4
  export { default as SelectOption } from './SelectOption.svelte';
5
5
  export { default as SelectValue } from './SelectValue.svelte';
@@ -1,9 +1,14 @@
1
1
  import { type Placement } from '@floating-ui/dom';
2
2
  type AnchorElement = HTMLElement | undefined | null;
3
+ interface AnchorElements {
4
+ anchor: AnchorElement;
5
+ target: AnchorElement;
6
+ arrow?: AnchorElement;
7
+ }
3
8
  interface AnchorConfig {
4
9
  placement?: Placement;
5
10
  constrainViewport?: boolean;
6
11
  sameWidth?: boolean;
7
12
  }
8
- export declare const anchorElement: (anchor: AnchorElement, target: AnchorElement, config?: AnchorConfig) => (() => void) | undefined;
13
+ export declare const anchorElement: (elements: AnchorElements, config?: AnchorConfig) => (() => void) | undefined;
9
14
  export {};
@@ -1,17 +1,19 @@
1
- import { computePosition, flip, shift, autoUpdate, size } from '@floating-ui/dom';
1
+ import { computePosition, flip, shift, autoUpdate, size, arrow as floatingArrow } from '@floating-ui/dom';
2
2
  import { defaultConfig } from './utils.svelte.js';
3
- export const anchorElement = (anchor, target, config) => {
4
- if (!anchor || !target)
3
+ export const anchorElement = (elements, config) => {
4
+ if (!elements.anchor || !elements.target)
5
5
  return;
6
6
  const { placement, constrainViewport, sameWidth } = defaultConfig(config, {
7
7
  placement: 'bottom',
8
8
  constrainViewport: false,
9
9
  sameWidth: false
10
10
  });
11
+ const { anchor, target, arrow } = elements;
11
12
  const cleanup = autoUpdate(anchor, target, () => {
12
13
  computePosition(anchor, target, {
13
14
  placement,
14
15
  middleware: [
16
+ arrow ? floatingArrow({ element: arrow }) : undefined,
15
17
  flip(),
16
18
  shift({
17
19
  padding: 10
@@ -29,7 +31,7 @@ export const anchorElement = (anchor, target, config) => {
29
31
  }
30
32
  })
31
33
  ]
32
- }).then(({ x, y, placement }) => {
34
+ }).then(({ x, y, placement, middlewareData }) => {
33
35
  const [side, alignment] = placement.split('-');
34
36
  Object.assign(target.style, {
35
37
  left: `${x}px`,
@@ -38,6 +40,27 @@ export const anchorElement = (anchor, target, config) => {
38
40
  });
39
41
  target.setAttribute('data-side', side);
40
42
  target.setAttribute('data-alignment', alignment || 'center');
43
+ if (arrow) {
44
+ const arrowPos = middlewareData.arrow;
45
+ const side = {
46
+ top: 'bottom',
47
+ right: 'left',
48
+ bottom: 'top',
49
+ left: 'right'
50
+ }[placement.split('-')[0]];
51
+ if (!arrowPos || !side)
52
+ return;
53
+ const arrowSize = (arrow.getBoundingClientRect().width / 3).toFixed();
54
+ Object.assign(arrow.style, {
55
+ left: arrowPos.x != null ? `${arrowPos.x}px` : '',
56
+ top: arrowPos.y != null ? `${arrowPos.y}px` : '',
57
+ right: '',
58
+ bottom: '',
59
+ [side]: `-${arrowSize}px`,
60
+ position: 'absolute'
61
+ });
62
+ arrow.setAttribute('data-side', side);
63
+ }
41
64
  });
42
65
  });
43
66
  return cleanup;
@@ -1,7 +1,10 @@
1
1
  import { type UID } from './utils.svelte.js';
2
- export declare class Context<H = any> {
2
+ export declare class Context<H = any, T extends HTMLElement = any> {
3
3
  #private;
4
4
  uid: UID;
5
+ arrow: HTMLElement | null;
6
+ content: HTMLElement | null;
7
+ trigger: T | null;
5
8
  protected hooks: H | null;
6
9
  protected _mounted: boolean;
7
10
  constructor(name: string, hooks?: H);
@@ -2,6 +2,9 @@ import { createUID } from './utils.svelte.js';
2
2
  import { onDestroy, getContext, onMount } from 'svelte';
3
3
  export class Context {
4
4
  uid = $state();
5
+ arrow = $state(null);
6
+ content = $state(null);
7
+ trigger = $state(null);
5
8
  hooks = null;
6
9
  _mounted = $state(false);
7
10
  constructor(name, hooks) {
@@ -1,5 +1,5 @@
1
1
  export const log = {
2
2
  error(message) {
3
- throw Error(`[Lithesome] ${message}`);
3
+ throw new Error(`[Lithesome] ${message}`);
4
4
  }
5
5
  };
@@ -35,19 +35,19 @@ export interface BaseProps<T extends HTMLElement, C extends Record<string, any>
35
35
  self?: T;
36
36
  }
37
37
  export type BasePropsNoChildren<T extends HTMLElement, C extends Record<string, any> = any> = Omit<BaseProps<T, C>, 'children'>;
38
- export interface DropdownProps {
38
+ export interface ContentProps {
39
39
  /**
40
40
  * The `svelte/transtion` you wish to use.
41
41
  *
42
42
  * @see https://lithesome.dev/docs/api#transition-prop
43
43
  */
44
44
  transition?: Transition;
45
- /** The element to portal the dropdown menu to. */
45
+ /** The element to portal the content menu to. */
46
46
  portalTarget?: string | HTMLElement;
47
- /** The anchor point of the dropdown relative to the trigger. */
47
+ /** The anchor point of the content relative to the trigger. */
48
48
  placement?: Placement;
49
- /** Keeps the dropdown from ever growing outside of the viewport. */
49
+ /** Keeps the content from ever growing outside of the viewport. */
50
50
  constrainViewport?: boolean;
51
- /** Makes the dropdown the same width as the trigger. */
51
+ /** Makes the content the same width as the trigger. */
52
52
  sameWidth?: boolean;
53
53
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lithesome",
3
- "version": "0.6.2",
3
+ "version": "0.7.0",
4
4
  "repository": {
5
5
  "type": "git",
6
6
  "url": "https://github.com/Gibbu/lithesome.git"
@@ -1,17 +0,0 @@
1
- import { SvelteComponent } from "svelte";
2
- import { type BaseProps, type DropdownProps } from '../../internal/index.js';
3
- declare const __propDef: {
4
- props: BaseProps<HTMLDivElement, {
5
- visible: boolean;
6
- }> & DropdownProps;
7
- events: {
8
- [evt: string]: CustomEvent<any>;
9
- };
10
- slots: {};
11
- };
12
- export type ComboboxDropdownProps = typeof __propDef.props;
13
- export type ComboboxDropdownEvents = typeof __propDef.events;
14
- export type ComboboxDropdownSlots = typeof __propDef.slots;
15
- export default class ComboboxDropdown extends SvelteComponent<ComboboxDropdownProps, ComboboxDropdownEvents, ComboboxDropdownSlots> {
16
- }
17
- export {};
@@ -1,17 +0,0 @@
1
- import { SvelteComponent } from "svelte";
2
- import { type BaseProps, type DropdownProps } from '../../internal/index.js';
3
- declare const __propDef: {
4
- props: BaseProps<HTMLDivElement, {
5
- visible: boolean;
6
- }> & DropdownProps;
7
- events: {
8
- [evt: string]: CustomEvent<any>;
9
- };
10
- slots: {};
11
- };
12
- export type MenuDropdownProps = typeof __propDef.props;
13
- export type MenuDropdownEvents = typeof __propDef.events;
14
- export type MenuDropdownSlots = typeof __propDef.slots;
15
- export default class MenuDropdown extends SvelteComponent<MenuDropdownProps, MenuDropdownEvents, MenuDropdownSlots> {
16
- }
17
- export {};
@@ -1,17 +0,0 @@
1
- import { SvelteComponent } from "svelte";
2
- import { type BaseProps, type DropdownProps } from '../../internal/index.js';
3
- declare const __propDef: {
4
- props: BaseProps<HTMLDivElement, {
5
- visible: boolean;
6
- }> & DropdownProps;
7
- events: {
8
- [evt: string]: CustomEvent<any>;
9
- };
10
- slots: {};
11
- };
12
- export type SelectDropdownProps = typeof __propDef.props;
13
- export type SelectDropdownEvents = typeof __propDef.events;
14
- export type SelectDropdownSlots = typeof __propDef.slots;
15
- export default class SelectDropdown extends SvelteComponent<SelectDropdownProps, SelectDropdownEvents, SelectDropdownSlots> {
16
- }
17
- export {};