@valerius_petrini/corekit-ui 0.1.62 → 0.1.63

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.
@@ -0,0 +1,82 @@
1
+ <script lang="ts">
2
+ import { fly } from "svelte/transition";
3
+ import NavbarElement from "./NavbarElement.svelte";
4
+ import { tick } from "svelte";
5
+ import type { NavbarDropdownProps } from "../types/Navbar.js";
6
+
7
+ let {
8
+ children = undefined,
9
+ class: className = "",
10
+ wrapperClass = "",
11
+ label = "",
12
+ element = undefined,
13
+ ...restProps
14
+ }: NavbarDropdownProps = $props();
15
+
16
+ let open = $state(false);
17
+ let dropdownRef: HTMLButtonElement | null = $state(null);
18
+ let wrapperRef: HTMLDivElement | null = $state(null);
19
+ let offsetX = $state(0);
20
+ let flipUp = $state(false);
21
+
22
+ function calculateOverflow() {
23
+ if (!dropdownRef) return;
24
+
25
+ offsetX = 0;
26
+
27
+ const menuRect = dropdownRef.getBoundingClientRect();
28
+ const vw = window.innerWidth;
29
+ const padding = 12;
30
+
31
+ flipUp = menuRect.bottom > window.innerHeight - padding;
32
+
33
+ if (menuRect.right > vw - padding)
34
+ offsetX = -(menuRect.right - (vw - padding));
35
+ else if (menuRect.left < padding)
36
+ offsetX = padding - menuRect.left;
37
+ else
38
+ offsetX = 0;
39
+ }
40
+
41
+ async function toggle() {
42
+ open = !open;
43
+ if (open) {
44
+ await tick();
45
+ calculateOverflow();
46
+ } else {
47
+ offsetX = 0;
48
+ }
49
+ }
50
+
51
+ function handleClickOutside(event: MouseEvent) {
52
+ if (dropdownRef && !dropdownRef.contains(event.target as Node) && wrapperRef && !wrapperRef.contains(event.target as Node)) {
53
+ open = false;
54
+ offsetX = 0;
55
+ }
56
+ }
57
+ </script>
58
+
59
+ <svelte:window onclick={handleClickOutside}/>
60
+
61
+ <div class="relative" bind:this={wrapperRef}>
62
+ <NavbarElement onclick={toggle} class={className} {...restProps} aria-haspopup="true" aria-expanded={open}>
63
+ {label}
64
+ {#if element}
65
+ {@render element()}
66
+ {/if}
67
+ </NavbarElement>
68
+
69
+ {#if open}
70
+ <div
71
+ class="absolute {flipUp ? 'bottom-full' : 'top-full'} left-0 z-100 mt-1 overflow-hidden shadow-lg"
72
+ style="transform: translateX({offsetX}px); visibility: {open ? 'visible' : 'hidden'};">
73
+ <button
74
+ bind:this={dropdownRef}
75
+ transition:fly={{ y: flipUp ? 5 : -5, duration: 200 }}
76
+ class="bg-sub-background p-2 min-w-max flex flex-col *:px-0 rounded border-sub-background-hover border"
77
+ onclick={() => open = false}>
78
+ {@render children?.()}
79
+ </button>
80
+ </div>
81
+ {/if}
82
+ </div>
@@ -0,0 +1,4 @@
1
+ import type { NavbarDropdownProps } from "../types/Navbar.js";
2
+ declare const NavbarDropdown: import("svelte").Component<NavbarDropdownProps, {}, "">;
3
+ type NavbarDropdown = ReturnType<typeof NavbarDropdown>;
4
+ export default NavbarDropdown;
@@ -1 +1,11 @@
1
- <div class="ml-auto"></div>
1
+ <script lang="ts">
2
+ import { NavbarSeparatorClasses, type NavbarSeparatorProps } from "../types/Navbar.js";
3
+
4
+ let {
5
+ variant = "dynamic",
6
+ class: className = "",
7
+ ...restProps
8
+ }: NavbarSeparatorProps = $props();
9
+ </script>
10
+
11
+ <div class={NavbarSeparatorClasses[variant]} {...restProps}></div>
@@ -1,26 +1,4 @@
1
+ import { type NavbarSeparatorProps } from "../types/Navbar.js";
2
+ declare const NavbarSeparator: import("svelte").Component<NavbarSeparatorProps, {}, "">;
3
+ type NavbarSeparator = ReturnType<typeof NavbarSeparator>;
1
4
  export default NavbarSeparator;
2
- type NavbarSeparator = SvelteComponent<{
3
- [x: string]: never;
4
- }, {
5
- [evt: string]: CustomEvent<any>;
6
- }, {}> & {
7
- $$bindings?: string | undefined;
8
- };
9
- declare const NavbarSeparator: $$__sveltets_2_IsomorphicComponent<{
10
- [x: string]: never;
11
- }, {
12
- [evt: string]: CustomEvent<any>;
13
- }, {}, {}, string>;
14
- interface $$__sveltets_2_IsomorphicComponent<Props extends Record<string, any> = any, Events extends Record<string, any> = any, Slots extends Record<string, any> = any, Exports = {}, Bindings = string> {
15
- new (options: import("svelte").ComponentConstructorOptions<Props>): import("svelte").SvelteComponent<Props, Events, Slots> & {
16
- $$bindings?: Bindings;
17
- } & Exports;
18
- (internal: unknown, props: {
19
- $$events?: Events;
20
- $$slots?: Slots;
21
- }): Exports & {
22
- $set?: any;
23
- $on?: any;
24
- };
25
- z_$$bindings?: Bindings;
26
- }
@@ -0,0 +1,124 @@
1
+ <script lang="ts">
2
+ import type { TooltipComponent } from "../types/Tooltip.js";
3
+ import { type Snippet } from "svelte";
4
+ import { fly } from "svelte/transition";
5
+
6
+ let {
7
+ text,
8
+ position = "top",
9
+ delay = 0,
10
+ children
11
+ }: TooltipComponent = $props();
12
+
13
+ let visible = $state(false);
14
+ let resolvedPosition: string | null = $state(null);
15
+ let offsetX = $state(0);
16
+ let trigger: HTMLDivElement;
17
+ let tooltip: HTMLDivElement | null = $state(null);
18
+ let timeout: ReturnType<typeof setTimeout>;
19
+ let arrowX = $derived(-offsetX);
20
+
21
+ function calculatePosition() {
22
+ resolvedPosition = position;
23
+ if (!trigger) return;
24
+
25
+ const rect = trigger.getBoundingClientRect();
26
+ const vw = window.innerWidth;
27
+ const vh = window.innerHeight;
28
+
29
+ if (position === "top" && rect.top < 40) resolvedPosition = "bottom";
30
+ else if (position === "bottom" && rect.bottom > vh - 40) resolvedPosition = "top";
31
+ else if (position === "left" && rect.left < 120) resolvedPosition = "right";
32
+ else if (position === "right" && rect.right > vw - 120) resolvedPosition = "left";
33
+ else resolvedPosition = position;
34
+ }
35
+
36
+ function calculateOverflow() {
37
+ if (!tooltip || !trigger) return;
38
+
39
+ const triggerRect = trigger.getBoundingClientRect();
40
+ const tooltipRect = tooltip.getBoundingClientRect();
41
+ const vw = window.innerWidth;
42
+
43
+ const triggerCenter = triggerRect.left + triggerRect.width / 2;
44
+
45
+ const tooltipLeft = triggerCenter - tooltipRect.width / 2;
46
+ const tooltipRight = triggerCenter + tooltipRect.width / 2;
47
+
48
+ const padding = 8;
49
+
50
+ if (tooltipRight > vw - padding)
51
+ offsetX = -(tooltipRight - (vw - padding));
52
+ else if (tooltipLeft < padding)
53
+ offsetX = padding - tooltipLeft;
54
+ else
55
+ offsetX = 0;
56
+ }
57
+
58
+ function show() {
59
+ calculatePosition();
60
+ timeout = setTimeout(() => {
61
+ visible = true;
62
+ requestAnimationFrame(calculateOverflow);
63
+ }, delay);
64
+ }
65
+
66
+ function hide() {
67
+ clearTimeout(timeout);
68
+ visible = false;
69
+ }
70
+
71
+ const positionClasses: Record<string, string> = {
72
+ top: "bottom-full left-1/2 -translate-x-1/2 mb-2",
73
+ bottom: "top-full left-1/2 -translate-x-1/2 mt-2",
74
+ left: "right-full top-1/2 -translate-y-1/2 mr-2",
75
+ right: "left-full top-1/2 -translate-y-1/2 ml-2"
76
+ };
77
+
78
+ const arrowClasses: Record<string, string> = {
79
+ top: "top-full left-1/2 -translate-x-1/2 border-t-form-background",
80
+ bottom: "bottom-full left-1/2 -translate-x-1/2 border-b-form-background",
81
+ left: "left-full top-1/2 -translate-y-1/2 border-l-form-background",
82
+ right: "right-full top-1/2 -translate-y-1/2 border-r-form-background"
83
+ };
84
+
85
+ const flyParams = $derived.by(() => {
86
+ const pos = resolvedPosition || position;
87
+
88
+ const duration = 100;
89
+ const distance = 8;
90
+ if (pos == "top")
91
+ return { y: distance, duration };
92
+ else if (pos == "bottom")
93
+ return { y: -distance, duration };
94
+ const x = pos == "right" ? -distance : distance;
95
+ return { x, duration };
96
+ });
97
+ </script>
98
+
99
+ <div
100
+ bind:this={trigger}
101
+ class="relative inline-flex w-fit h-fit"
102
+ onmouseenter={show}
103
+ onmouseleave={hide}
104
+ role="tooltip">
105
+ {@render children()}
106
+
107
+ {#if visible}
108
+ <div
109
+ bind:this={tooltip}
110
+ style="transform: translateX(calc(-50% + {offsetX}px));"
111
+ class="absolute z-999999 {positionClasses[resolvedPosition || position]} translate-x-0! pointer-events-none">
112
+ <div
113
+ transition:fly={flyParams}
114
+ class="px-2 py-1 text-xs text-main-text bg-form-background rounded whitespace-nowrap">
115
+ {text}
116
+
117
+ <div
118
+ class="absolute {arrowClasses[resolvedPosition || position]} border-4 border-transparent w-0 h-0"
119
+ style="transform: translateX(calc(-50% + {arrowX}px));"
120
+ ></div>
121
+ </div>
122
+ </div>
123
+ {/if}
124
+ </div>
@@ -0,0 +1,4 @@
1
+ import type { TooltipComponent } from "../types/Tooltip.js";
2
+ declare const Tooltip: import("svelte").Component<TooltipComponent, {}, "">;
3
+ type Tooltip = ReturnType<typeof Tooltip>;
4
+ export default Tooltip;
package/dist/index.d.ts CHANGED
@@ -5,6 +5,7 @@ export { default as SEO } from "./components/SEO.svelte";
5
5
  export { default as Navbar } from "./components/Navbar.svelte";
6
6
  export { default as NavbarSeparator } from "./components/NavbarSeparator.svelte";
7
7
  export { default as NavbarElement } from "./components/NavbarElement.svelte";
8
+ export { default as NavbarDropdown } from "./components/NavbarDropdown.svelte";
8
9
  export { default as Input } from "./components/Input.svelte";
9
10
  export { default as FileInput } from "./components/FileInput.svelte";
10
11
  export { default as Select } from "./components/Select.svelte";
@@ -17,6 +18,7 @@ export { default as Table } from "./components/Table.svelte";
17
18
  export { default as Toast } from "./components/Toast.svelte";
18
19
  export { default as Toaster } from "./components/Toaster.svelte";
19
20
  export { default as SideNavbar } from "./components/SideNavbar.svelte";
21
+ export { default as Tooltip } from "./components/Tooltip.svelte";
20
22
  export { fbmBackground } from "./actions/fbm.ts";
21
23
  export { toast } from "./actions/toast.svelte.ts";
22
24
  export type { TypewriterAction, DisplaySegment } from "./types/Typewriter.ts";
package/dist/index.js CHANGED
@@ -5,6 +5,7 @@ export { default as SEO } from "./components/SEO.svelte";
5
5
  export { default as Navbar } from "./components/Navbar.svelte";
6
6
  export { default as NavbarSeparator } from "./components/NavbarSeparator.svelte";
7
7
  export { default as NavbarElement } from "./components/NavbarElement.svelte";
8
+ export { default as NavbarDropdown } from "./components/NavbarDropdown.svelte";
8
9
  export { default as Input } from "./components/Input.svelte";
9
10
  export { default as FileInput } from "./components/FileInput.svelte";
10
11
  export { default as Select } from "./components/Select.svelte";
@@ -17,5 +18,6 @@ export { default as Table } from "./components/Table.svelte";
17
18
  export { default as Toast } from "./components/Toast.svelte";
18
19
  export { default as Toaster } from "./components/Toaster.svelte";
19
20
  export { default as SideNavbar } from "./components/SideNavbar.svelte";
21
+ export { default as Tooltip } from "./components/Tooltip.svelte";
20
22
  export { fbmBackground } from "./actions/fbm.js";
21
23
  export { toast } from "./actions/toast.svelte.js";
@@ -99,4 +99,5 @@ input[type="number"]::-webkit-inner-spin-button {
99
99
 
100
100
  input[type="number"] {
101
101
  -moz-appearance: textfield;
102
+ appearance: textfield;
102
103
  }
@@ -1,2 +1,3 @@
1
1
  export type PositionStyle = "top" | "right" | "bottom" | "left" | "top-left" | "top-right" | "bottom-left" | "bottom-right" | "center";
2
+ export type TooltipPosition = "top" | "right" | "bottom" | "left";
2
3
  export declare const positionParts: Record<PositionStyle, string>;
@@ -1,4 +1,4 @@
1
- import type { Component } from "svelte";
1
+ import type { Component, Snippet } from "svelte";
2
2
  import type { BaseComponentProps } from "./BaseComponent.ts";
3
3
  export interface NavbarProps extends BaseComponentProps {
4
4
  classTop?: string;
@@ -13,8 +13,21 @@ export interface NavbarElementProps extends BaseComponentProps {
13
13
  export interface SideNavbarProps extends BaseComponentProps {
14
14
  items?: SideNavbarItem[];
15
15
  }
16
+ export type NavbarSeparatorVariant = "vertical" | "horizontal" | "dynamic";
17
+ export declare const NavbarSeparatorClasses: Record<NavbarSeparatorVariant, string>;
18
+ export interface NavbarSeparatorProps extends BaseComponentProps {
19
+ variant?: NavbarSeparatorVariant;
20
+ }
16
21
  export interface SideNavbarItem {
17
22
  href: string;
18
23
  label: string;
19
24
  icon: Component;
20
25
  }
26
+ export interface NavbarDropdownProps extends BaseComponentProps {
27
+ label?: string;
28
+ element?: Snippet;
29
+ classTop?: string;
30
+ wrapperClass?: string;
31
+ activeClass?: string;
32
+ threshold?: number;
33
+ }
@@ -1,3 +1,7 @@
1
1
  ;
2
2
  ;
3
- export {};
3
+ export const NavbarSeparatorClasses = {
4
+ "vertical": "w-0.5 h-full py-3 bg-sub-background-hover bg-clip-content",
5
+ "horizontal": "h-0.5 w-full px-3 my-1 bg-sub-background-hover bg-clip-content",
6
+ "dynamic": "ml-auto"
7
+ };
@@ -0,0 +1,7 @@
1
+ import type { TooltipPosition } from "../styles/posititon.js";
2
+ import type { BaseComponentProps } from "./BaseComponent.ts";
3
+ export interface TooltipComponent extends BaseComponentProps {
4
+ text?: string;
5
+ position?: TooltipPosition;
6
+ delay?: number;
7
+ }
@@ -0,0 +1 @@
1
+ export {};
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@valerius_petrini/corekit-ui",
3
- "version": "0.1.62",
3
+ "version": "0.1.63",
4
4
  "description": "Component Library used across all my projects",
5
5
  "author": "Valerius Petrini Jr.",
6
6
  "license": "MIT",