kosui 0.1.0 → 0.1.2

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.
package/README.md CHANGED
@@ -2,6 +2,26 @@
2
2
 
3
3
  A Svelte component library used by [Koso](https://koso.app) and [Cipherly](https://cipherly.app).
4
4
 
5
+ ## Design Philosophy
6
+
7
+ These principles are listed in order of priority. When they conflict, the higher principle wins.
8
+
9
+ **Svelte First** — Write idiomatic Svelte. Prefer runes, snippets, and Svelte's built-in reactivity over external state management or patterns that fight the framework.
10
+
11
+ **Be Parsimonious** — Keep components as simple as possible. Reach for CSS first; use JavaScript only when CSS can't do it. Don't add abstractions that aren't earning their weight.
12
+
13
+ **Accessible by Default** — ARIA roles, keyboard navigation, and focus management are built in, not bolted on. A component isn't done until it works without a mouse.
14
+
15
+ **Convention over Invention** — If a component is standard across major platforms and frameworks — iOS, Android, Windows, macOS, and the web — it belongs in the library. Its behavior should be unsurprising: implement it the way those platforms do, not the way we imagine it might work.
16
+
17
+ **Transparent Props** — Components don't hide their underlying DOM element. Every component spreads `...restProps` and provides an `el` binding so consumers can always reach the element without fighting the component.
18
+
19
+ **Composable over Configurable** — Prefer Svelte snippets and composition over a proliferation of boolean props and string options. When a component needs customization, reach for `{#snippet}` before adding another prop.
20
+
21
+ **Minimal Dependencies** — As few external dependencies as possible. Every dependency is a maintenance burden and a potential breaking change. A little copied, well-understood code beats a large transitive dependency graph.
22
+
23
+ **Modern Baseline** — Target current, evergreen browsers. Dropping legacy browser support is acceptable in exchange for simpler code.
24
+
5
25
  ## Changesets
6
26
 
7
27
  Add a new changeset:
@@ -144,23 +144,23 @@
144
144
  border-radius: var(--radius);
145
145
  }
146
146
 
147
- .variant-filled {
147
+ .variant-filled {
148
148
  background-color: var(--color-main);
149
149
  color: var(--color-on-main);
150
150
  }
151
151
 
152
- .variant-tonal {
152
+ .variant-tonal {
153
153
  background-color: var(--color-tonal);
154
154
  color: var(--color-on-tonal);
155
155
  }
156
156
 
157
- .outlined {
157
+ .outlined {
158
158
  border-width: 1px;
159
159
  border-style: solid;
160
160
  border-color: var(--color-main);
161
161
  }
162
162
 
163
- .elevated {
163
+ .elevated {
164
164
  box-shadow:
165
165
  0 1px 3px 0 rgb(from var(--color-shadow, rgb(0 0 0)) r g b / 0.2),
166
166
  0 1px 2px -1px rgb(from var(--color-shadow, rgb(0 0 0)) r g b / 0.2);
@@ -3,13 +3,13 @@
3
3
  import { mergeProps } from "../merge-props.js";
4
4
  import { Tooltip, type TooltipTriggerProps } from "../tooltip/index.js";
5
5
  import { noop, type ClassName, type ElementRef } from "../utils.js";
6
- import type { Icon } from "@lucide/svelte";
6
+ import type { LucideIcon } from "@lucide/svelte";
7
7
  import type { Snippet } from "svelte";
8
8
  import type { HTMLButtonAttributes } from "svelte/elements";
9
9
  import { twMerge } from "tailwind-merge";
10
10
 
11
11
  export type ButtonProps = {
12
- icon?: typeof Icon;
12
+ icon?: LucideIcon;
13
13
  size?: number;
14
14
  tooltip?: Snippet | string;
15
15
  } & ElementRef &
@@ -1,10 +1,10 @@
1
1
  import { type Variants } from "../base.js";
2
2
  import { type ClassName, type ElementRef } from "../utils.js";
3
- import type { Icon } from "@lucide/svelte";
3
+ import type { LucideIcon } from "@lucide/svelte";
4
4
  import type { Snippet } from "svelte";
5
5
  import type { HTMLButtonAttributes } from "svelte/elements";
6
6
  export type ButtonProps = {
7
- icon?: typeof Icon;
7
+ icon?: LucideIcon;
8
8
  size?: number;
9
9
  tooltip?: Snippet | string;
10
10
  } & ElementRef & ClassName & Variants & HTMLButtonAttributes;
@@ -1,12 +1,12 @@
1
1
  import type { Shortcut } from "../shortcut/index.js";
2
- import { type Icon } from "@lucide/svelte";
2
+ import { type LucideIcon } from "@lucide/svelte";
3
3
  type ActionProps = {
4
4
  id: string;
5
5
  callback: () => void;
6
6
  category?: string;
7
7
  name?: string;
8
8
  description?: string;
9
- icon?: typeof Icon;
9
+ icon?: LucideIcon;
10
10
  enabled?: () => boolean;
11
11
  selected?: () => boolean;
12
12
  shortcut?: Shortcut;
@@ -17,7 +17,7 @@ export declare class Action {
17
17
  category: string;
18
18
  name: string;
19
19
  description: string;
20
- icon: typeof Icon;
20
+ icon: LucideIcon;
21
21
  enabled: () => boolean;
22
22
  selected?: () => boolean;
23
23
  shortcut?: Shortcut;
@@ -1,14 +1,14 @@
1
1
  <script module lang="ts">
2
2
  import { mergeComponentProps } from "../merge-props.js";
3
3
  import { Modal, type ModalProps } from "../modal/index.js";
4
- import type { Icon } from "@lucide/svelte";
4
+ import type { LucideIcon } from "@lucide/svelte";
5
5
  import type { Snippet } from "svelte";
6
6
  import { twMerge } from "tailwind-merge";
7
7
 
8
8
  export type DialogProps<T> = {
9
9
  ref?: HTMLDialogElement;
10
10
  onSelect?: (value: T | undefined) => void;
11
- icon?: typeof Icon;
11
+ icon?: LucideIcon;
12
12
  title?: string;
13
13
  children: Snippet;
14
14
  actions?: Snippet<[{ onSelect: (value: T | undefined) => void }]>;
@@ -1,10 +1,10 @@
1
1
  import { type ModalProps } from "../modal/index.js";
2
- import type { Icon } from "@lucide/svelte";
2
+ import type { LucideIcon } from "@lucide/svelte";
3
3
  import type { Snippet } from "svelte";
4
4
  export type DialogProps<T> = {
5
5
  ref?: HTMLDialogElement;
6
6
  onSelect?: (value: T | undefined) => void;
7
- icon?: typeof Icon;
7
+ icon?: LucideIcon;
8
8
  title?: string;
9
9
  children: Snippet;
10
10
  actions?: Snippet<[{
@@ -1,6 +1,6 @@
1
1
  import type { Variants } from "../base.js";
2
2
  import type { InputProps } from "../input/index.js";
3
- import type { Icon } from "@lucide/svelte";
3
+ import type { LucideIcon } from "@lucide/svelte";
4
4
  import { type Snippet } from "svelte";
5
5
  export type DialoguerButtonProps<T> = {
6
6
  text: string;
@@ -8,27 +8,27 @@ export type DialoguerButtonProps<T> = {
8
8
  default?: boolean;
9
9
  } & Variants;
10
10
  type ShowDialogProps<T> = {
11
- icon?: typeof Icon;
11
+ icon?: LucideIcon;
12
12
  title?: string;
13
13
  inputProps?: InputProps;
14
14
  message: Snippet<[]> | string;
15
15
  buttons: DialoguerButtonProps<T>[];
16
16
  };
17
17
  type NoticeDialogProps = {
18
- icon?: typeof Icon;
18
+ icon?: LucideIcon;
19
19
  title?: string;
20
20
  message: Snippet<[]> | string;
21
21
  acceptText?: string;
22
22
  };
23
23
  type ConfirmDialogProps = {
24
- icon?: typeof Icon;
24
+ icon?: LucideIcon;
25
25
  title?: string;
26
26
  message: Snippet<[]> | string;
27
27
  cancelText?: string;
28
28
  acceptText?: string;
29
29
  };
30
30
  type InputDialogProps = {
31
- icon?: typeof Icon;
31
+ icon?: LucideIcon;
32
32
  title?: string;
33
33
  props: InputProps;
34
34
  message: Snippet<[]> | string;
@@ -37,7 +37,7 @@ type InputDialogProps = {
37
37
  };
38
38
  export declare class DialoguerContext {
39
39
  message: Snippet<[]> | string;
40
- icon: typeof Icon | undefined;
40
+ icon: LucideIcon | undefined;
41
41
  title: string | undefined;
42
42
  inputProps: InputProps | undefined;
43
43
  buttons: DialoguerButtonProps<unknown>[];
@@ -31,12 +31,21 @@
31
31
  ...props
32
32
  }: LinkProps = $props();
33
33
 
34
- const classes = twMerge(
35
- baseClasses({ variant, color, shape, underline, hover: true, focus: true }),
36
- variant !== "text" &&
37
- "flex h-9 items-center justify-center gap-2 text-nowrap transition-all active:scale-95",
38
- "cursor-pointer",
39
- className,
34
+ const classes = $derived(
35
+ twMerge(
36
+ baseClasses({
37
+ variant,
38
+ color,
39
+ shape,
40
+ underline,
41
+ hover: true,
42
+ focus: true,
43
+ }),
44
+ variant !== "text" &&
45
+ "flex h-9 items-center justify-center gap-2 text-nowrap transition-all active:scale-95",
46
+ "cursor-pointer",
47
+ className,
48
+ ),
40
49
  );
41
50
  </script>
42
51
 
@@ -9,7 +9,7 @@
9
9
 
10
10
  const ctx = getMarkdownContext();
11
11
 
12
- let renderer = ctx.getRenderer(token.type);
12
+ let renderer = $derived(ctx.getRenderer(token.type));
13
13
  </script>
14
14
 
15
15
  {#snippet children()}
@@ -4,6 +4,6 @@ export type MenuProps = {
4
4
  open?: boolean;
5
5
  children: Snippet;
6
6
  } & ElementRef;
7
- declare const Menu: import("svelte").Component<MenuProps, {}, "open" | "el">;
7
+ declare const Menu: import("svelte").Component<MenuProps, {}, "el" | "open">;
8
8
  type Menu = ReturnType<typeof Menu>;
9
9
  export default Menu;
@@ -156,10 +156,6 @@
156
156
  }
157
157
  }
158
158
  }
159
-
160
- if (!children) {
161
- console.log(children);
162
- }
163
159
  </script>
164
160
 
165
161
  {#if open}
@@ -13,6 +13,6 @@ export type PopoverProps = {
13
13
  onKeydownWhileOpen?: (event: KeyboardEvent) => void;
14
14
  children: Snippet;
15
15
  } & ClassName & ElementRef & HTMLAttributes<HTMLDivElement>;
16
- declare const Popover: import("svelte").Component<PopoverProps, {}, "open" | "el">;
16
+ declare const Popover: import("svelte").Component<PopoverProps, {}, "el" | "open">;
17
17
  type Popover = ReturnType<typeof Popover>;
18
18
  export default Popover;
@@ -111,15 +111,15 @@
111
111
  () => step,
112
112
  () => marks,
113
113
  () => disabled,
114
- label,
114
+ (val) => label(val),
115
115
  () => labelAlwaysOn,
116
116
  () => inverted,
117
117
  () => restrictToMarks,
118
118
  () => color,
119
119
  () => size,
120
120
  () => radius,
121
- onChange,
122
- onChangeEnd,
121
+ (val) => onChange?.(val),
122
+ (val) => onChangeEnd?.(val),
123
123
  sliderHandle,
124
124
  sliderHandleLabel,
125
125
  sliderHandleLabelArrow,
@@ -79,5 +79,4 @@
79
79
 
80
80
  className,
81
81
  )}
82
- {...restProps}
83
- ></textarea>
82
+ {...restProps}></textarea>
@@ -58,18 +58,20 @@
58
58
  open = false;
59
59
  }
60
60
 
61
- const triggerProps: TooltipTriggerProps = click
62
- ? {
63
- ref: (ref) => (anchorEl = ref),
64
- onclick: () => (open = true),
65
- }
66
- : {
67
- ref: (ref) => (anchorEl = ref),
68
- onmouseenter: () => !isTouchDevice() && show(),
69
- onmouseleave: () => hide(),
70
- ontouchstart: () => show(delay),
71
- ontouchend: () => cancel(),
72
- };
61
+ const triggerProps: TooltipTriggerProps = $derived(
62
+ click
63
+ ? {
64
+ ref: (ref) => (anchorEl = ref),
65
+ onclick: () => (open = true),
66
+ }
67
+ : {
68
+ ref: (ref) => (anchorEl = ref),
69
+ onmouseenter: () => !isTouchDevice() && show(),
70
+ onmouseleave: () => hide(),
71
+ ontouchstart: () => show(delay),
72
+ ontouchend: () => cancel(),
73
+ },
74
+ );
73
75
  </script>
74
76
 
75
77
  <Popover
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "kosui",
3
- "version": "0.1.0",
3
+ "version": "0.1.2",
4
4
  "type": "module",
5
5
  "license": "MIT",
6
6
  "repository": {
@@ -28,45 +28,45 @@
28
28
  },
29
29
  "dependencies": {
30
30
  "@floating-ui/dom": "^1.7.4",
31
- "@lucide/svelte": "^0.552.0",
32
- "marked": "^16.4.1"
31
+ "@lucide/svelte": "^1.1.0",
32
+ "marked": "^18.0.0"
33
33
  },
34
34
  "peerDependencies": {
35
35
  "svelte": "^5.0.0"
36
36
  },
37
37
  "devDependencies": {
38
- "@changesets/cli": "^2.29.7",
39
- "@eslint/compat": "^1.4.1",
40
- "@eslint/js": "^9.39.1",
41
- "@playwright/test": "^1.56.1",
42
- "@sveltejs/adapter-static": "^3.0.10",
43
- "@sveltejs/kit": "^2.48.4",
44
- "@sveltejs/package": "^2.5.4",
45
- "@sveltejs/vite-plugin-svelte": "^6.2.1",
46
- "@tailwindcss/forms": "^0.5.10",
47
- "@tailwindcss/postcss": "^4.1.16",
48
- "@tailwindcss/vite": "^4.1.16",
49
- "@types/node": "^24.10.0",
50
- "eslint": "^9.39.1",
51
- "eslint-config-prettier": "^10.1.8",
52
- "eslint-plugin-svelte": "^3.13.0",
53
- "globals": "^16.5.0",
54
- "highlight.js": "^11.11.1",
55
- "highlight.svelte": "^0.1.3",
56
- "jsdom": "^27.1.0",
57
- "postcss": "^8.5.6",
58
- "prettier": "^3.6.2",
59
- "prettier-plugin-svelte": "^3.4.0",
60
- "prettier-plugin-tailwindcss": "^0.7.1",
61
- "publint": "^0.3.15",
62
- "svelte": "^5.43.3",
63
- "svelte-check": "^4.3.3",
64
- "tailwind-merge": "^3.3.1",
65
- "tailwindcss": "^4.1.16",
66
- "typescript": "^5.9.3",
67
- "typescript-eslint": "^8.46.3",
68
- "vite": "^7.1.12",
69
- "vitest": "^4.0.7"
38
+ "@changesets/cli": "2.31.1",
39
+ "@eslint/compat": "2.1.1",
40
+ "@eslint/js": "10.0.1",
41
+ "@playwright/test": "1.64.1",
42
+ "@sveltejs/adapter-static": "3.0.10",
43
+ "@sveltejs/kit": "2.70.3",
44
+ "@sveltejs/package": "2.5.8",
45
+ "@sveltejs/vite-plugin-svelte": "7.3.1",
46
+ "@tailwindcss/forms": "0.5.11",
47
+ "@tailwindcss/postcss": "4.3.3",
48
+ "@tailwindcss/vite": "4.3.3",
49
+ "@types/node": "25.9.9",
50
+ "eslint": "10.14.0",
51
+ "eslint-config-prettier": "10.1.8",
52
+ "eslint-plugin-svelte": "3.23.1",
53
+ "globals": "17.14.0",
54
+ "highlight.js": "11.12.0",
55
+ "highlight.svelte": "0.1.3",
56
+ "jsdom": "29.1.1",
57
+ "postcss": "8.5.32",
58
+ "prettier": "3.9.10",
59
+ "prettier-plugin-svelte": "4.1.1",
60
+ "prettier-plugin-tailwindcss": "0.8.1",
61
+ "publint": "0.3.25",
62
+ "svelte": "^5.57.3",
63
+ "svelte-check": "4.7.8",
64
+ "tailwind-merge": "3.7.0",
65
+ "tailwindcss": "4.3.3",
66
+ "typescript": "6.0.3",
67
+ "typescript-eslint": "8.72.1",
68
+ "vite": "8.3.5",
69
+ "vitest": "4.1.12"
70
70
  },
71
71
  "keywords": [
72
72
  "svelte"