@valerius_petrini/corekit-ui 0.1.83 → 0.1.85

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 (26) hide show
  1. package/dist/actions/portal.d.ts +3 -0
  2. package/dist/actions/portal.js +9 -0
  3. package/dist/components/display/Accordion/AccordionItem.svelte +64 -0
  4. package/dist/components/display/Accordion/AccordionItem.svelte.d.ts +4 -0
  5. package/dist/components/display/Accordion/index.stories.svelte +26 -0
  6. package/dist/components/display/Accordion/index.stories.svelte.d.ts +18 -0
  7. package/dist/components/display/Accordion/index.svelte +43 -0
  8. package/dist/components/display/Accordion/index.svelte.d.ts +4 -0
  9. package/dist/components/display/Accordion/types.d.ts +16 -0
  10. package/dist/components/display/Accordion/types.js +1 -0
  11. package/dist/components/display/Tree/TreeNode.svelte +77 -0
  12. package/dist/components/display/Tree/TreeNode.svelte.d.ts +4 -0
  13. package/dist/components/display/Tree/index.stories.svelte +35 -0
  14. package/dist/components/display/Tree/index.stories.svelte.d.ts +18 -0
  15. package/dist/components/display/Tree/index.svelte +24 -0
  16. package/dist/components/display/Tree/index.svelte.d.ts +4 -0
  17. package/dist/components/display/Tree/types.d.ts +15 -0
  18. package/dist/components/display/Tree/types.js +1 -0
  19. package/dist/components/display/index.d.ts +6 -0
  20. package/dist/components/display/index.js +4 -0
  21. package/dist/components/inputs/ColorInput/index.svelte +4 -1
  22. package/dist/components/inputs/Combobox/index.svelte +7 -1
  23. package/dist/components/inputs/Combobox/types.d.ts +1 -0
  24. package/dist/components/navigation/Navbar/NavbarDropdown.svelte +4 -1
  25. package/dist/components/overlay/Tooltip/index.svelte +4 -1
  26. package/package.json +1 -1
@@ -0,0 +1,3 @@
1
+ export declare function portal(node: HTMLElement, target?: string): {
2
+ destroy(): void;
3
+ };
@@ -0,0 +1,9 @@
1
+ export function portal(node, target = 'body') {
2
+ const targetEl = document.querySelector(target);
3
+ targetEl.appendChild(node);
4
+ return {
5
+ destroy() {
6
+ node.remove();
7
+ }
8
+ };
9
+ }
@@ -0,0 +1,64 @@
1
+ <script module>
2
+ let counter = 0;
3
+ </script>
4
+
5
+ <script lang="ts">
6
+ import { getContext } from "svelte";
7
+ import type { AccordionItemProps, AccordionContext } from "./types.js";
8
+ import { Button } from "$components/inputs";
9
+ import { slide } from "svelte/transition";
10
+ import ChevronRight from "@lucide/svelte/icons/chevron-right";
11
+ import { twMerge } from "tailwind-merge";
12
+
13
+ let {
14
+ children = undefined,
15
+ class: className = "",
16
+ title = "",
17
+ open = $bindable(false),
18
+ static: isStatic = false,
19
+ disabled = false,
20
+ ontoggle = undefined,
21
+ id = "accordion-item-" + counter++,
22
+ ...restProps
23
+ }: AccordionItemProps = $props();
24
+
25
+ const ctx = getContext<AccordionContext | undefined>('accordion');
26
+
27
+ const isOpen = $derived(ctx ? ctx.activeIds.has(id) : open);
28
+
29
+ function toggle() {
30
+ if (disabled || isStatic) return;
31
+ if (ctx)
32
+ ctx.setActive(id);
33
+ else
34
+ open = !open;
35
+ ontoggle?.(!isOpen);
36
+ }
37
+
38
+ const combinedClass = $derived(twMerge(
39
+ "w-full bg-sub-background rounded-none",
40
+ className
41
+ ));
42
+
43
+ const buttonClass = $derived(twMerge(
44
+ "justify-start p-2 w-full gap-1 rounded-none",
45
+ disabled ? "cursor-not-allowed opacity-50" : "",
46
+ isStatic ? "cursor-default" : "",
47
+ isOpen ? "border-b border-b-sub-background-border" : "",
48
+ ));
49
+ </script>
50
+
51
+ <div class={combinedClass} {...restProps}>
52
+ {#if !isStatic}
53
+ <Button aria-controls="content-{id}" id="trigger-{id}" class={buttonClass} size="full" color="sub" onclick={toggle} aria-expanded={isOpen}>
54
+ <ChevronRight size={18} class="transition-transform duration-200 {isOpen ? 'rotate-90' : ''}"/>
55
+ {title}
56
+ </Button>
57
+ {/if}
58
+
59
+ {#if isOpen || isStatic}
60
+ <div id="content-{id}" role="region" class="content p-2" transition:slide={{ duration: 200 }}>
61
+ {@render children?.()}
62
+ </div>
63
+ {/if}
64
+ </div>
@@ -0,0 +1,4 @@
1
+ import type { AccordionItemProps } from "./types.ts";
2
+ declare const AccordionItem: import("svelte").Component<AccordionItemProps, {}, "open">;
3
+ type AccordionItem = ReturnType<typeof AccordionItem>;
4
+ export default AccordionItem;
@@ -0,0 +1,26 @@
1
+ <script module lang="ts">
2
+ import { defineMeta } from "@storybook/addon-svelte-csf";
3
+ import Text from "../../typography/Text/index.svelte";
4
+ import Accordion from "./index.svelte";
5
+ import AccordionItem from "./AccordionItem.svelte";
6
+
7
+ const { Story } = defineMeta({
8
+ title: "Components/Display/Accordion",
9
+ component: Accordion,
10
+ argTypes: {
11
+
12
+ },
13
+ });
14
+ </script>
15
+
16
+ <Story name="Default" args={{ }}>
17
+ <AccordionItem title="Accordion Item 1">
18
+ <Text>This is the content of the first accordion item.</Text>
19
+ </AccordionItem>
20
+ <AccordionItem title="Accordion Item 2" static>
21
+ <Text>This is the content of the second accordion item.</Text>
22
+ </AccordionItem>
23
+ <AccordionItem title="Accordion Item 3">
24
+ <Text>This is the content of the third accordion item.</Text>
25
+ </AccordionItem>
26
+ </Story>
@@ -0,0 +1,18 @@
1
+ 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> {
2
+ new (options: import('svelte').ComponentConstructorOptions<Props>): import('svelte').SvelteComponent<Props, Events, Slots> & {
3
+ $$bindings?: Bindings;
4
+ } & Exports;
5
+ (internal: unknown, props: {
6
+ $$events?: Events;
7
+ $$slots?: Slots;
8
+ }): Exports & {
9
+ $set?: any;
10
+ $on?: any;
11
+ };
12
+ z_$$bindings?: Bindings;
13
+ }
14
+ declare const Index: $$__sveltets_2_IsomorphicComponent<Record<string, never>, {
15
+ [evt: string]: CustomEvent<any>;
16
+ }, {}, {}, string>;
17
+ type Index = InstanceType<typeof Index>;
18
+ export default Index;
@@ -0,0 +1,43 @@
1
+ <script lang="ts">
2
+ import { setContext } from "svelte";
3
+ import type { AccordionProps, AccordionContext } from "./types.js";
4
+ import { twMerge } from "tailwind-merge";
5
+
6
+ let {
7
+ children,
8
+ class: className = "",
9
+ exclusive = false,
10
+ ...restProps
11
+ }: AccordionProps = $props();
12
+
13
+ let activeIds = $state<Set<string>>(new Set());
14
+
15
+ function setActive(id: string | null) {
16
+ if (!id) {
17
+ activeIds = new Set();
18
+ return;
19
+ }
20
+ if (exclusive) {
21
+ activeIds = activeIds.has(id) ? new Set() : new Set([id]);
22
+ } else {
23
+ const next = new Set(activeIds);
24
+ next.has(id) ? next.delete(id) : next.add(id);
25
+ activeIds = next;
26
+ }
27
+ }
28
+
29
+ setContext<AccordionContext>('accordion', {
30
+ get exclusive() { return exclusive; },
31
+ get activeIds() { return activeIds; },
32
+ setActive
33
+ });
34
+
35
+ const combinedClass = $derived(twMerge(
36
+ "w-full rounded overflow-hidden divide-y divide-sub-background-border",
37
+ className
38
+ ));
39
+ </script>
40
+
41
+ <div class={combinedClass} {...restProps}>
42
+ {@render children?.()}
43
+ </div>
@@ -0,0 +1,4 @@
1
+ import type { AccordionProps } from "./types.ts";
2
+ declare const Index: import("svelte").Component<AccordionProps, {}, "">;
3
+ type Index = ReturnType<typeof Index>;
4
+ export default Index;
@@ -0,0 +1,16 @@
1
+ import type { BaseComponentProps } from "../../../types/BaseComponent";
2
+ export interface AccordionItemProps extends BaseComponentProps {
3
+ title: string;
4
+ open?: boolean;
5
+ disabled?: boolean;
6
+ static?: boolean;
7
+ ontoggle?: (open: boolean) => void;
8
+ }
9
+ export interface AccordionProps extends BaseComponentProps {
10
+ exclusive?: boolean;
11
+ }
12
+ export interface AccordionContext {
13
+ exclusive: boolean;
14
+ activeIds: Set<string>;
15
+ setActive: (id: string) => void;
16
+ }
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,77 @@
1
+ <script lang="ts">
2
+ import Text from "../../typography/Text/index.svelte";
3
+ import { getContext, setContext } from "svelte";
4
+ import type { TreeNodeProps, TreeContext } from "./types.js";
5
+ import { slide } from "svelte/transition";
6
+ import ChevronRight from "@lucide/svelte/icons/chevron-right";
7
+ import { twMerge } from "tailwind-merge";
8
+
9
+ let {
10
+ children = undefined,
11
+ class: className = "",
12
+ label = "",
13
+ open = $bindable(false),
14
+ disabled = false,
15
+ ...restProps
16
+ }: TreeNodeProps = $props();
17
+
18
+ const ctx = getContext<TreeContext>('tree');
19
+
20
+ const depth = ctx.depth;
21
+
22
+ setContext<TreeContext>('tree', {
23
+ depth: depth + 1
24
+ });
25
+
26
+ function toggle() {
27
+ if (disabled || !children) return;
28
+ open = !open;
29
+ }
30
+
31
+ const combinedClass = $derived(twMerge(
32
+ "w-full",
33
+ className
34
+ ));
35
+
36
+ const rowClass = $derived(twMerge(
37
+ "flex items-center gap-1 py-1 w-full text-sm",
38
+ disabled ? "opacity-50 cursor-not-allowed" : children ? "cursor-pointer hover:bg-sub-background" : "cursor-default",
39
+ ));
40
+ </script>
41
+
42
+ <li class={combinedClass} role="treeitem" aria-expanded={children ? open : undefined} {...restProps}>
43
+ <Text
44
+ class={rowClass}
45
+ style="padding-left: {depth * 1.25 / 2}rem"
46
+ onclick={toggle}
47
+ onkeydown={(e: KeyboardEvent) => e.key === 'Enter' && toggle()}
48
+ tabindex={disabled ? -1 : 0}
49
+ role="button">
50
+ <Text label="span" class="shrink-0 transition-transform duration-200 {open ? 'rotate-90' : ''} {children ? 'visible' : 'invisible'}">
51
+ <ChevronRight size={14} />
52
+ </Text>
53
+ {label}
54
+ </Text>
55
+
56
+ {#if open && children}
57
+ <ul class="vpcui-tree-list relative" style="--vpcui-tree-depth: {depth * 1.25}rem" role="group" transition:slide={{ duration: 200 }}>
58
+ {@render children()}
59
+ </ul>
60
+ {/if}
61
+ </li>
62
+
63
+ <style>
64
+ .vpcui-tree-list::before {
65
+ content: '';
66
+ position: absolute;
67
+ left: calc(var(--vpcui-tree-depth) / 2 + 0.375rem);
68
+ top: 0;
69
+ bottom: 0;
70
+ width: 1px;
71
+ background-color: var(--color-sub-background-border);
72
+ }
73
+
74
+ :global(.vpcui-tree-list > :not(li[role="treeitem"])) {
75
+ padding-left: calc(var(--vpcui-tree-depth) / 2 + 1rem);
76
+ }
77
+ </style>
@@ -0,0 +1,4 @@
1
+ import type { TreeNodeProps } from "./types.ts";
2
+ declare const TreeNode: import("svelte").Component<TreeNodeProps, {}, "open">;
3
+ type TreeNode = ReturnType<typeof TreeNode>;
4
+ export default TreeNode;
@@ -0,0 +1,35 @@
1
+ <script module lang="ts">
2
+ import { defineMeta } from "@storybook/addon-svelte-csf";
3
+ import Text from "../../typography/Text/index.svelte";
4
+ import Tree from "./index.svelte";
5
+ import TreeNode from "./TreeNode.svelte";
6
+
7
+ const { Story } = defineMeta({
8
+ title: "Components/Display/Tree",
9
+ component: Tree,
10
+ argTypes: {
11
+
12
+ },
13
+ });
14
+ </script>
15
+
16
+ <Story name="Default" args={{ }}>
17
+ <TreeNode label="Node 1">
18
+ <Text>This is the content of the first tree node.</Text>
19
+ <TreeNode label="Child Node 1">
20
+ <Text>This is the content of the first child node.</Text>
21
+ </TreeNode>
22
+ </TreeNode>
23
+ <TreeNode label="Node 2">
24
+ <Text>This is the content of the second tree node.</Text>
25
+ <TreeNode label="Child Node 2">
26
+ <Text>This is the content of the second child node.</Text>
27
+ <TreeNode label="Grandchild Node 1">
28
+ <Text>This is the content of the first grandchild node.</Text>
29
+ </TreeNode>
30
+ </TreeNode>
31
+ </TreeNode>
32
+ <TreeNode label="Node 3">
33
+ <Text>This is the content of the third tree node.</Text>
34
+ </TreeNode>
35
+ </Story>
@@ -0,0 +1,18 @@
1
+ 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> {
2
+ new (options: import('svelte').ComponentConstructorOptions<Props>): import('svelte').SvelteComponent<Props, Events, Slots> & {
3
+ $$bindings?: Bindings;
4
+ } & Exports;
5
+ (internal: unknown, props: {
6
+ $$events?: Events;
7
+ $$slots?: Slots;
8
+ }): Exports & {
9
+ $set?: any;
10
+ $on?: any;
11
+ };
12
+ z_$$bindings?: Bindings;
13
+ }
14
+ declare const Index: $$__sveltets_2_IsomorphicComponent<Record<string, never>, {
15
+ [evt: string]: CustomEvent<any>;
16
+ }, {}, {}, string>;
17
+ type Index = InstanceType<typeof Index>;
18
+ export default Index;
@@ -0,0 +1,24 @@
1
+ <script lang="ts">
2
+ import { setContext } from "svelte";
3
+ import type { TreeProps, TreeContext } from "./types.js";
4
+ import { twMerge } from "tailwind-merge";
5
+
6
+ let {
7
+ children,
8
+ class: className = "",
9
+ ...restProps
10
+ }: TreeProps = $props();
11
+
12
+ setContext<TreeContext>('tree', {
13
+ depth: 0
14
+ });
15
+
16
+ const combinedClass = $derived(twMerge(
17
+ "w-full",
18
+ className
19
+ ));
20
+ </script>
21
+
22
+ <ul class={combinedClass} role="tree" {...restProps}>
23
+ {@render children?.()}
24
+ </ul>
@@ -0,0 +1,4 @@
1
+ import type { TreeProps } from "./types.ts";
2
+ declare const Index: import("svelte").Component<TreeProps, {}, "">;
3
+ type Index = ReturnType<typeof Index>;
4
+ export default Index;
@@ -0,0 +1,15 @@
1
+ import type { BaseComponentProps } from "../../../types/BaseComponent";
2
+ import type { Snippet } from "svelte";
3
+ export interface TreeProps extends BaseComponentProps {
4
+ children?: Snippet;
5
+ }
6
+ export interface TreeNodeProps extends BaseComponentProps {
7
+ label: string;
8
+ children?: Snippet;
9
+ open?: boolean;
10
+ disabled?: boolean;
11
+ depth?: number;
12
+ }
13
+ export interface TreeContext {
14
+ depth: number;
15
+ }
@@ -0,0 +1 @@
1
+ export {};
@@ -2,6 +2,12 @@ export { default as Card } from "./Card/index.svelte";
2
2
  export { default as Table } from "./Table/index.svelte";
3
3
  export { default as KBD } from "./KBD/index.svelte";
4
4
  export { default as Skeleton } from "./Skeleton/index.svelte";
5
+ export { default as Accordion } from "./Accordion/index.svelte";
6
+ export { default as AccordionItem } from "./Accordion/AccordionItem.svelte";
7
+ export { default as Tree } from "./Tree/index.svelte";
8
+ export { default as TreeNode } from "./Tree/TreeNode.svelte";
5
9
  export type { CardProps } from "./Card/types.ts";
6
10
  export type { TableProps } from "./Table/types.ts";
7
11
  export type { SkeletonProps } from "./Skeleton/types.ts";
12
+ export type { AccordionProps, AccordionItemProps, AccordionContext } from "./Accordion/types.ts";
13
+ export type { TreeProps, TreeNodeProps, TreeContext } from "./Tree/types.ts";
@@ -2,3 +2,7 @@ export { default as Card } from "./Card/index.svelte";
2
2
  export { default as Table } from "./Table/index.svelte";
3
3
  export { default as KBD } from "./KBD/index.svelte";
4
4
  export { default as Skeleton } from "./Skeleton/index.svelte";
5
+ export { default as Accordion } from "./Accordion/index.svelte";
6
+ export { default as AccordionItem } from "./Accordion/AccordionItem.svelte";
7
+ export { default as Tree } from "./Tree/index.svelte";
8
+ export { default as TreeNode } from "./Tree/TreeNode.svelte";
@@ -19,6 +19,7 @@
19
19
  import { Input } from "..";
20
20
 
21
21
  import Pipette from "@lucide/svelte/icons/pipette";
22
+ import { portal } from "../../../actions/portal";
22
23
 
23
24
  let {
24
25
  children = undefined,
@@ -89,6 +90,7 @@
89
90
 
90
91
  const { x, y } = await computePosition(element, floatingEl, {
91
92
  placement: "bottom-start",
93
+ strategy: "absolute",
92
94
  middleware: [
93
95
  offset(8),
94
96
  flip(),
@@ -300,8 +302,9 @@
300
302
  {@const hsv = hexToHsv(value || "#000000")}
301
303
  <div
302
304
  bind:this={floatingEl}
305
+ use:portal
303
306
  transition:fly={{ y: -10, duration: 200 }}
304
- class="fixed z-999999 bg-sub-background rounded-md p-4 flex gap-2.5 flex-wrap"
307
+ class="absolute z-999999 bg-sub-background rounded-md p-4 flex gap-2.5 flex-wrap"
305
308
  style="top: {dropdownY}px; left: {dropdownX}px; min-width: {referenceWidth}px; max-width: calc(100vw - 16px);"
306
309
  >
307
310
  <div class="color-canvas relative rounded h-36 cursor-crosshair" style="background-color: hsl({hue}, 100%, 50%);" bind:this={canvasEl}>
@@ -11,6 +11,7 @@
11
11
  import BaseInput from "../helper/BaseInput.svelte";
12
12
  import Text from "../../typography/Text/index.svelte";
13
13
  import { fly } from "svelte/transition";
14
+ import { portal } from "../../../actions/portal";
14
15
 
15
16
  let {
16
17
  children = undefined,
@@ -26,6 +27,7 @@
26
27
  value = $bindable(),
27
28
  onfocus = undefined,
28
29
  onblur = undefined,
30
+ onselectitem = undefined,
29
31
  required = false,
30
32
  disabled = false,
31
33
  size = "md",
@@ -78,6 +80,7 @@
78
80
  value = option;
79
81
  isFocused = false;
80
82
  inputElement?.blur();
83
+ onselectitem?.(value);
81
84
  }
82
85
 
83
86
  function initFloating(node: HTMLDivElement) {
@@ -90,6 +93,7 @@
90
93
 
91
94
  const { x, y } = await computePosition(element!, node, {
92
95
  placement: "bottom-start",
96
+ strategy: "absolute",
93
97
  middleware: [offset(8), flip(), shift({ padding: 8 })]
94
98
  });
95
99
 
@@ -150,6 +154,7 @@
150
154
  if (option) {
151
155
  value = option;
152
156
  isFocused = false;
157
+ onselectitem?.(value);
153
158
  inputElement?.blur();
154
159
  }
155
160
  activeIndex = 0;
@@ -223,7 +228,8 @@
223
228
  {#if isFocused}
224
229
  <div
225
230
  use:initFloating
226
- style="position: fixed; top: {dropdownY}px; left: {dropdownX}px; width: {referenceWidth}px;"
231
+ use:portal
232
+ style="position: absolute; top: {dropdownY}px; left: {dropdownX}px; width: {referenceWidth}px;"
227
233
  style:visibility={ready ? "visible" : "hidden"}
228
234
  transition:fly={{ y: -10, duration: 200 }}
229
235
  class="z-999999 overflow-hidden border border-white/10 bg-sub-background shadow-xl shadow-black/40 {getSizeStyleClass(radius, 'radius')}"
@@ -4,5 +4,6 @@ export interface ComboboxProps extends BaseInputProps {
4
4
  placeholder?: string;
5
5
  onfocus?: (e?: FocusEvent) => void;
6
6
  onblur?: (e?: FocusEvent) => void;
7
+ onselectitem?: (value: string) => void;
7
8
  limit?: number;
8
9
  }
@@ -14,6 +14,7 @@
14
14
 
15
15
  import ChevronUp from "@lucide/svelte/icons/chevron-up";
16
16
  import ChevronDown from "@lucide/svelte/icons/chevron-down";
17
+ import { portal } from "../../../actions/portal.js";
17
18
 
18
19
  let {
19
20
  children = undefined,
@@ -46,6 +47,7 @@
46
47
  async function updatePosition() {
47
48
  const { x: fx, y: fy, placement } = await computePosition(element!, node, {
48
49
  placement: "bottom-start",
50
+ strategy: "absolute",
49
51
  middleware: [offset(4), flip(), shift({ padding: 12 })],
50
52
  });
51
53
  x = fx;
@@ -102,8 +104,9 @@
102
104
  {#if open}
103
105
  <div
104
106
  use:initDropdown
107
+ use:portal
105
108
  role="menu"
106
- style="position: fixed; top: {y}px; left: {x}px;"
109
+ style="position: absolute; top: {y}px; left: {x}px;"
107
110
  class="z-100 shadow-lg"
108
111
  style:visibility={ready ? "visible" : "hidden"}
109
112
  >
@@ -15,6 +15,7 @@
15
15
  autoUpdate
16
16
 
17
17
  } from "@floating-ui/dom";
18
+ import { portal } from "../../../actions/portal.js";
18
19
 
19
20
  let {
20
21
  text,
@@ -44,6 +45,7 @@
44
45
 
45
46
  const { x: fx, y: fy, placement, middlewareData } = await computePosition(trigger, tooltipEl, {
46
47
  placement: position,
48
+ strategy: "absolute",
47
49
  middleware: [
48
50
  offset(8),
49
51
  flip(),
@@ -156,8 +158,9 @@
156
158
  {#if visible}
157
159
  <div
158
160
  bind:this={tooltipEl}
161
+ use:portal
159
162
  role="tooltip"
160
- style="position: fixed; top: {y}px; left: {x}px;"
163
+ style="position: absolute; top: {y}px; left: {x}px;"
161
164
  class="z-999999 {interactive ? 'pointer-events-auto' : 'pointer-events-none'}"
162
165
  onmouseenter={onTooltipEnter}
163
166
  onmouseleave={onTooltipLeave}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@valerius_petrini/corekit-ui",
3
- "version": "0.1.83",
3
+ "version": "0.1.85",
4
4
  "description": "Component Library used across all my projects",
5
5
  "author": "Valerius Petrini Jr.",
6
6
  "license": "MIT",