@kayord/ui 0.18.5 → 0.19.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 (29) hide show
  1. package/dist/components/custom/copy-button/CopyButton.svelte +65 -0
  2. package/dist/components/custom/copy-button/CopyButton.svelte.d.ts +12 -0
  3. package/dist/components/custom/copy-button/index.d.ts +1 -0
  4. package/dist/components/custom/copy-button/index.js +1 -0
  5. package/dist/components/custom/index.d.ts +4 -1
  6. package/dist/components/custom/index.js +4 -1
  7. package/dist/components/custom/light-switch.svelte/LightSwitch.svelte +17 -0
  8. package/dist/components/custom/light-switch.svelte/LightSwitch.svelte.d.ts +6 -0
  9. package/dist/components/custom/light-switch.svelte/index.d.ts +1 -0
  10. package/dist/components/custom/light-switch.svelte/index.js +1 -0
  11. package/dist/components/custom/theme-selector/ThemeSelector.svelte +25 -0
  12. package/dist/components/custom/theme-selector/ThemeSelector.svelte.d.ts +6 -0
  13. package/dist/components/custom/theme-selector/index.d.ts +1 -0
  14. package/dist/components/custom/theme-selector/index.js +1 -0
  15. package/dist/components/custom/tree-view/TreeView.svelte +15 -0
  16. package/dist/components/custom/tree-view/TreeView.svelte.d.ts +8 -0
  17. package/dist/components/custom/tree-view/TreeViewFile.svelte +22 -0
  18. package/dist/components/custom/tree-view/TreeViewFile.svelte.d.ts +11 -0
  19. package/dist/components/custom/tree-view/TreeViewFolder.svelte +37 -0
  20. package/dist/components/custom/tree-view/TreeViewFolder.svelte.d.ts +14 -0
  21. package/dist/components/custom/tree-view/index.d.ts +4 -0
  22. package/dist/components/custom/tree-view/index.js +4 -0
  23. package/dist/hooks/use-clipboard.svelte.d.ts +49 -0
  24. package/dist/hooks/use-clipboard.svelte.js +70 -0
  25. package/package.json +6 -6
  26. package/dist/components/custom/theme-switch/ThemeSwitch.svelte +0 -20
  27. package/dist/components/custom/theme-switch/ThemeSwitch.svelte.d.ts +0 -6
  28. package/dist/components/custom/theme-switch/index.d.ts +0 -1
  29. package/dist/components/custom/theme-switch/index.js +0 -1
@@ -0,0 +1,65 @@
1
+ <script lang="ts">
2
+ import { Button, type ButtonProps } from "../../ui/button";
3
+ import { UseClipboard } from "../../../hooks/use-clipboard.svelte";
4
+ import { cn } from "../../../utils";
5
+ import { Check, Copy, X } from "@lucide/svelte";
6
+ import type { Snippet } from "svelte";
7
+ import { scale } from "svelte/transition";
8
+
9
+ // omit href so you can't create a link
10
+ interface Props extends Omit<ButtonProps, "href"> {
11
+ text: string;
12
+ icon?: Snippet<[]>;
13
+ animationDuration?: number;
14
+ onCopy?: (status: UseClipboard["status"]) => void;
15
+ }
16
+
17
+ let {
18
+ text,
19
+ icon,
20
+ animationDuration = 500,
21
+ variant = "ghost",
22
+ size = "icon",
23
+ onCopy,
24
+ class: className,
25
+ ...restProps
26
+ }: Props = $props();
27
+
28
+ const clipboard = new UseClipboard();
29
+ </script>
30
+
31
+ <Button
32
+ {...restProps}
33
+ {variant}
34
+ {size}
35
+ class={cn(className)}
36
+ type="button"
37
+ name="copy"
38
+ tabindex={-1}
39
+ onclick={async () => {
40
+ const status = await clipboard.copy(text);
41
+
42
+ onCopy?.(status);
43
+ }}
44
+ >
45
+ {#if clipboard.status === "success"}
46
+ <div in:scale={{ duration: animationDuration, start: 0.85 }}>
47
+ <Check />
48
+ <span class="sr-only">Copied</span>
49
+ </div>
50
+ {:else if clipboard.status === "failure"}
51
+ <div in:scale={{ duration: animationDuration, start: 0.85 }}>
52
+ <X />
53
+ <span class="sr-only">Failed to copy</span>
54
+ </div>
55
+ {:else}
56
+ <div in:scale={{ duration: animationDuration, start: 0.85 }}>
57
+ {#if icon}
58
+ {@render icon()}
59
+ {:else}
60
+ <Copy />
61
+ {/if}
62
+ <span class="sr-only">Copy</span>
63
+ </div>
64
+ {/if}
65
+ </Button>
@@ -0,0 +1,12 @@
1
+ import { type ButtonProps } from "../../ui/button";
2
+ import { UseClipboard } from "../../../hooks/use-clipboard.svelte";
3
+ import type { Snippet } from "svelte";
4
+ interface Props extends Omit<ButtonProps, "href"> {
5
+ text: string;
6
+ icon?: Snippet<[]>;
7
+ animationDuration?: number;
8
+ onCopy?: (status: UseClipboard["status"]) => void;
9
+ }
10
+ declare const CopyButton: import("svelte").Component<Props, {}, "">;
11
+ type CopyButton = ReturnType<typeof CopyButton>;
12
+ export default CopyButton;
@@ -0,0 +1 @@
1
+ export { default as CopyButton } from "./CopyButton.svelte";
@@ -0,0 +1 @@
1
+ export { default as CopyButton } from "./CopyButton.svelte";
@@ -1,6 +1,9 @@
1
1
  export { Loader } from "./loader/index.js";
2
- export { ThemeSwitch } from "./theme-switch/index.js";
3
2
  export * from "./data-table/index.js";
4
3
  export { ProgressLoading } from "./progress-loading/index.js";
5
4
  export { Combobox } from "./combobox/index.js";
6
5
  export * from "./action/index.js";
6
+ export { CopyButton } from "./copy-button/index.js";
7
+ export * as TreeView from "./tree-view/index.js";
8
+ export { ThemeSelector } from "./theme-selector/index.js";
9
+ export { LightSwitch } from "./light-switch.svelte/index.js";
@@ -1,6 +1,9 @@
1
1
  export { Loader } from "./loader/index.js";
2
- export { ThemeSwitch } from "./theme-switch/index.js";
3
2
  export * from "./data-table/index.js";
4
3
  export { ProgressLoading } from "./progress-loading/index.js";
5
4
  export { Combobox } from "./combobox/index.js";
6
5
  export * from "./action/index.js";
6
+ export { CopyButton } from "./copy-button/index.js";
7
+ export * as TreeView from "./tree-view/index.js";
8
+ export { ThemeSelector } from "./theme-selector/index.js";
9
+ export { LightSwitch } from "./light-switch.svelte/index.js";
@@ -0,0 +1,17 @@
1
+ <script lang="ts">
2
+ import { Sun, Moon } from "@lucide/svelte";
3
+ import { toggleMode } from "mode-watcher";
4
+ import { Button } from "../../ui/button/index.js";
5
+
6
+ type Props = {
7
+ variant?: "outline" | "ghost";
8
+ };
9
+
10
+ let { variant = "outline" }: Props = $props();
11
+ </script>
12
+
13
+ <Button onclick={toggleMode} {variant} size="icon">
14
+ <Sun class="h-[1.2rem] w-[1.2rem] scale-100 rotate-0 transition-all dark:scale-0 dark:-rotate-90" />
15
+ <Moon class="absolute h-[1.2rem] w-[1.2rem] scale-0 rotate-90 transition-all dark:scale-100 dark:rotate-0" />
16
+ <span class="sr-only">Toggle theme</span>
17
+ </Button>
@@ -0,0 +1,6 @@
1
+ type Props = {
2
+ variant?: "outline" | "ghost";
3
+ };
4
+ declare const LightSwitch: import("svelte").Component<Props, {}, "">;
5
+ type LightSwitch = ReturnType<typeof LightSwitch>;
6
+ export default LightSwitch;
@@ -0,0 +1 @@
1
+ export { default as LightSwitch } from "./LightSwitch.svelte";
@@ -0,0 +1 @@
1
+ export { default as LightSwitch } from "./LightSwitch.svelte";
@@ -0,0 +1,25 @@
1
+ <script lang="ts">
2
+ import { Sun, Moon } from "@lucide/svelte";
3
+ import { resetMode, setMode } from "mode-watcher";
4
+ import * as DropdownMenu from "../../ui/dropdown-menu/index.js";
5
+ import { buttonVariants } from "../../ui/button/index.js";
6
+
7
+ type Props = {
8
+ variant?: "outline" | "ghost";
9
+ };
10
+
11
+ let { variant = "outline" }: Props = $props();
12
+ </script>
13
+
14
+ <DropdownMenu.Root>
15
+ <DropdownMenu.Trigger class={buttonVariants({ variant, size: "icon" })}>
16
+ <Sun class="h-[1.2rem] w-[1.2rem] scale-100 rotate-0 transition-all dark:scale-0 dark:-rotate-90" />
17
+ <Moon class="absolute h-[1.2rem] w-[1.2rem] scale-0 rotate-90 transition-all dark:scale-100 dark:rotate-0" />
18
+ <span class="sr-only">Toggle theme</span>
19
+ </DropdownMenu.Trigger>
20
+ <DropdownMenu.Content align="end">
21
+ <DropdownMenu.Item onclick={() => setMode("light")}>Light</DropdownMenu.Item>
22
+ <DropdownMenu.Item onclick={() => setMode("dark")}>Dark</DropdownMenu.Item>
23
+ <DropdownMenu.Item onclick={() => resetMode()}>System</DropdownMenu.Item>
24
+ </DropdownMenu.Content>
25
+ </DropdownMenu.Root>
@@ -0,0 +1,6 @@
1
+ type Props = {
2
+ variant?: "outline" | "ghost";
3
+ };
4
+ declare const ThemeSelector: import("svelte").Component<Props, {}, "">;
5
+ type ThemeSelector = ReturnType<typeof ThemeSelector>;
6
+ export default ThemeSelector;
@@ -0,0 +1 @@
1
+ export { default as ThemeSelector } from "./ThemeSelector.svelte";
@@ -0,0 +1 @@
1
+ export { default as ThemeSelector } from "./ThemeSelector.svelte";
@@ -0,0 +1,15 @@
1
+ <script lang="ts">
2
+ import { cn } from "../../../utils";
3
+ import type { Snippet } from "svelte";
4
+
5
+ type Props = {
6
+ class?: string;
7
+ children?: Snippet<[]>;
8
+ };
9
+
10
+ let { children, class: className }: Props = $props();
11
+ </script>
12
+
13
+ <div class={cn("flex flex-col", className)}>
14
+ {@render children?.()}
15
+ </div>
@@ -0,0 +1,8 @@
1
+ import type { Snippet } from "svelte";
2
+ type Props = {
3
+ class?: string;
4
+ children?: Snippet<[]>;
5
+ };
6
+ declare const TreeView: import("svelte").Component<Props, {}, "">;
7
+ type TreeView = ReturnType<typeof TreeView>;
8
+ export default TreeView;
@@ -0,0 +1,22 @@
1
+ <script lang="ts">
2
+ import type { Snippet } from "svelte";
3
+ import { File } from "@lucide/svelte";
4
+ import type { HTMLButtonAttributes } from "svelte/elements";
5
+ import { cn } from "../../../utils";
6
+
7
+ interface Props extends HTMLButtonAttributes {
8
+ name: string;
9
+ icon?: Snippet<[{ name: string }]>;
10
+ }
11
+
12
+ let { name, icon, type = "button", class: className, ...rest }: Props = $props();
13
+ </script>
14
+
15
+ <button {type} class={cn("flex place-items-center gap-1 pl-[3px]", className)} {...rest}>
16
+ {#if icon}
17
+ {@render icon({ name })}
18
+ {:else}
19
+ <File class="size-4" />
20
+ {/if}
21
+ <span>{name}</span>
22
+ </button>
@@ -0,0 +1,11 @@
1
+ import type { Snippet } from "svelte";
2
+ import type { HTMLButtonAttributes } from "svelte/elements";
3
+ interface Props extends HTMLButtonAttributes {
4
+ name: string;
5
+ icon?: Snippet<[{
6
+ name: string;
7
+ }]>;
8
+ }
9
+ declare const TreeViewFile: import("svelte").Component<Props, {}, "">;
10
+ type TreeViewFile = ReturnType<typeof TreeViewFile>;
11
+ export default TreeViewFile;
@@ -0,0 +1,37 @@
1
+ <script lang="ts">
2
+ import type { Snippet } from "svelte";
3
+ import * as Collapsible from "../../ui/collapsible/index.js";
4
+ import { Folder, FolderOpen } from "@lucide/svelte";
5
+ import { cn } from "../../../utils";
6
+
7
+ type Props = {
8
+ name: string;
9
+ open?: boolean;
10
+ class?: string;
11
+ icon?: Snippet<[{ name: string; open: boolean }]>;
12
+ children?: Snippet<[]>;
13
+ };
14
+
15
+ let { name, open = $bindable(true), class: className, icon, children }: Props = $props();
16
+ </script>
17
+
18
+ <Collapsible.Root bind:open>
19
+ <Collapsible.Trigger class={cn("flex place-items-center gap-1", className)}>
20
+ {#if icon}
21
+ {@render icon({ name, open })}
22
+ {:else if open}
23
+ <FolderOpen class="size-4" />
24
+ {:else}
25
+ <Folder class="size-4" />
26
+ {/if}
27
+ <span>{name}</span>
28
+ </Collapsible.Trigger>
29
+ <Collapsible.Content class="mx-2 border-l">
30
+ <div class="relative flex place-items-start">
31
+ <div class="bg-border mx-2 h-full w-[1px]"></div>
32
+ <div class="flex flex-col">
33
+ {@render children?.()}
34
+ </div>
35
+ </div>
36
+ </Collapsible.Content>
37
+ </Collapsible.Root>
@@ -0,0 +1,14 @@
1
+ import type { Snippet } from "svelte";
2
+ type Props = {
3
+ name: string;
4
+ open?: boolean;
5
+ class?: string;
6
+ icon?: Snippet<[{
7
+ name: string;
8
+ open: boolean;
9
+ }]>;
10
+ children?: Snippet<[]>;
11
+ };
12
+ declare const TreeViewFolder: import("svelte").Component<Props, {}, "open">;
13
+ type TreeViewFolder = ReturnType<typeof TreeViewFolder>;
14
+ export default TreeViewFolder;
@@ -0,0 +1,4 @@
1
+ import TreeView from "./TreeView.svelte";
2
+ import TreeViewFile from "./TreeViewFile.svelte";
3
+ import TreeViewFolder from "./TreeViewFolder.svelte";
4
+ export { TreeView, TreeViewFile, TreeViewFolder, TreeView as Root, TreeViewFile as File, TreeViewFolder as Folder };
@@ -0,0 +1,4 @@
1
+ import TreeView from "./TreeView.svelte";
2
+ import TreeViewFile from "./TreeViewFile.svelte";
3
+ import TreeViewFolder from "./TreeViewFolder.svelte";
4
+ export { TreeView, TreeViewFile, TreeViewFolder, TreeView as Root, TreeViewFile as File, TreeViewFolder as Folder };
@@ -0,0 +1,49 @@
1
+ type Options = {
2
+ /** The time before the copied status is reset. */
3
+ delay: number;
4
+ };
5
+ /** Use this hook to copy text to the clipboard and show a copied state.
6
+ *
7
+ * ## Usage
8
+ * ```svelte
9
+ * <script lang="ts">
10
+ * import { UseClipboard } from "./use-clipboard.svelte";
11
+ *
12
+ * const clipboard = new UseClipboard();
13
+ * </script>
14
+ *
15
+ * <button onclick={clipboard.copy('Hello, World!')}>
16
+ * {#if clipboard.copied === 'success'}
17
+ * Copied!
18
+ * {:else if clipboard.copied === 'failure'}
19
+ * Failed to copy!
20
+ * {:else}
21
+ * Copy
22
+ * {/if}
23
+ * </button>
24
+ * ```
25
+ *
26
+ */
27
+ export declare class UseClipboard {
28
+ #private;
29
+ private delay;
30
+ private timeout;
31
+ constructor({ delay }?: Partial<Options>);
32
+ /** Copies the given text to the users clipboard.
33
+ *
34
+ * ## Usage
35
+ * ```ts
36
+ * clipboard.copy('Hello, World!');
37
+ * ```
38
+ *
39
+ * @param text
40
+ * @returns
41
+ */
42
+ copy(text: string): Promise<"success" | "failure">;
43
+ /** True when the user has just copied to the clipboard. */
44
+ get copied(): boolean;
45
+ /** Indicates whether a copy has occurred
46
+ * and gives a status of either `success` or `failure`. */
47
+ get status(): "success" | "failure" | undefined;
48
+ }
49
+ export {};
@@ -0,0 +1,70 @@
1
+ /** Use this hook to copy text to the clipboard and show a copied state.
2
+ *
3
+ * ## Usage
4
+ * ```svelte
5
+ * <script lang="ts">
6
+ * import { UseClipboard } from "./use-clipboard.svelte";
7
+ *
8
+ * const clipboard = new UseClipboard();
9
+ * </script>
10
+ *
11
+ * <button onclick={clipboard.copy('Hello, World!')}>
12
+ * {#if clipboard.copied === 'success'}
13
+ * Copied!
14
+ * {:else if clipboard.copied === 'failure'}
15
+ * Failed to copy!
16
+ * {:else}
17
+ * Copy
18
+ * {/if}
19
+ * </button>
20
+ * ```
21
+ *
22
+ */
23
+ export class UseClipboard {
24
+ #copiedStatus = $state();
25
+ delay;
26
+ timeout = undefined;
27
+ constructor({ delay = 500 } = {}) {
28
+ this.delay = delay;
29
+ }
30
+ /** Copies the given text to the users clipboard.
31
+ *
32
+ * ## Usage
33
+ * ```ts
34
+ * clipboard.copy('Hello, World!');
35
+ * ```
36
+ *
37
+ * @param text
38
+ * @returns
39
+ */
40
+ async copy(text) {
41
+ if (this.timeout) {
42
+ this.#copiedStatus = undefined;
43
+ clearTimeout(this.timeout);
44
+ }
45
+ try {
46
+ await navigator.clipboard.writeText(text);
47
+ this.#copiedStatus = "success";
48
+ this.timeout = setTimeout(() => {
49
+ this.#copiedStatus = undefined;
50
+ }, this.delay);
51
+ }
52
+ catch {
53
+ // an error can occur when not in the browser or if the user hasn't given clipboard access
54
+ this.#copiedStatus = "failure";
55
+ this.timeout = setTimeout(() => {
56
+ this.#copiedStatus = undefined;
57
+ }, this.delay);
58
+ }
59
+ return this.#copiedStatus;
60
+ }
61
+ /** True when the user has just copied to the clipboard. */
62
+ get copied() {
63
+ return this.#copiedStatus === "success";
64
+ }
65
+ /** Indicates whether a copy has occurred
66
+ * and gives a status of either `success` or `failure`. */
67
+ get status() {
68
+ return this.#copiedStatus;
69
+ }
70
+ }
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@kayord/ui",
3
3
  "private": false,
4
- "version": "0.18.5",
4
+ "version": "0.19.0",
5
5
  "exports": {
6
6
  ".": {
7
7
  "types": "./dist/index.d.ts",
@@ -46,7 +46,7 @@
46
46
  "vaul-svelte": "1.0.0-next.7"
47
47
  },
48
48
  "devDependencies": {
49
- "@lucide/svelte": "^0.510.0",
49
+ "@lucide/svelte": "^0.511.0",
50
50
  "@sveltejs/adapter-auto": "^6.0.1",
51
51
  "@sveltejs/kit": "^2.21.0",
52
52
  "@sveltejs/package": "^2.3.11",
@@ -56,19 +56,19 @@
56
56
  "@testing-library/svelte": "^5.2.7",
57
57
  "@typescript-eslint/eslint-plugin": "^8.32.1",
58
58
  "@typescript-eslint/parser": "^8.32.1",
59
- "eslint": "^9.26.0",
59
+ "eslint": "^9.27.0",
60
60
  "eslint-config-prettier": "^10.1.5",
61
- "eslint-plugin-svelte": "^3.6.0",
61
+ "eslint-plugin-svelte": "^3.8.1",
62
62
  "happy-dom": "^17.4.7",
63
63
  "prettier": "^3.5.3",
64
64
  "prettier-plugin-svelte": "^3.4.0",
65
65
  "prettier-plugin-tailwindcss": "^0.6.11",
66
66
  "publint": "^0.3.12",
67
- "svelte": "^5.30.1",
67
+ "svelte": "^5.30.2",
68
68
  "svelte-check": "^4.2.1",
69
69
  "tailwindcss": "^4.1.7",
70
70
  "tslib": "^2.8.1",
71
- "tw-animate-css": "1.2.9",
71
+ "tw-animate-css": "1.3.0",
72
72
  "typescript": "^5.8.3",
73
73
  "vite": "^6.3.5",
74
74
  "vitest": "^3.1.3",
@@ -1,20 +0,0 @@
1
- <script lang="ts">
2
- import { toggleMode, mode } from "mode-watcher";
3
- import Moon from "@lucide/svelte/icons/moon";
4
- import Sun from "@lucide/svelte/icons/sun";
5
- import { cn } from "../../../utils";
6
-
7
- interface Props {
8
- class?: string | undefined | null;
9
- }
10
-
11
- let { class: className = undefined }: Props = $props();
12
- </script>
13
-
14
- <button onclick={toggleMode} class={cn("text-primary", className)}>
15
- {#if mode.current == "dark"}
16
- <Moon />
17
- {:else}
18
- <Sun />
19
- {/if}
20
- </button>
@@ -1,6 +0,0 @@
1
- interface Props {
2
- class?: string | undefined | null;
3
- }
4
- declare const ThemeSwitch: import("svelte").Component<Props, {}, "">;
5
- type ThemeSwitch = ReturnType<typeof ThemeSwitch>;
6
- export default ThemeSwitch;
@@ -1 +0,0 @@
1
- export { default as ThemeSwitch } from "./ThemeSwitch.svelte";
@@ -1 +0,0 @@
1
- export { default as ThemeSwitch } from "./ThemeSwitch.svelte";