kosui 0.1.2 → 0.4.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 (238) hide show
  1. package/README.md +34 -3
  2. package/dist/alert/alert.svelte +16 -157
  3. package/dist/alert/alert.svelte.d.ts +3 -26
  4. package/dist/alert/index.d.ts +1 -1
  5. package/dist/alert/index.js +1 -1
  6. package/dist/autocomplete/autocomplete.svelte +126 -12
  7. package/dist/autocomplete/autocomplete.svelte.d.ts +30 -6
  8. package/dist/autocomplete/index.d.ts +1 -5
  9. package/dist/autocomplete/index.js +1 -5
  10. package/dist/avatar/avatar.svelte +16 -10
  11. package/dist/badge/badge.svelte +31 -20
  12. package/dist/badge/badge.svelte.d.ts +8 -4
  13. package/dist/badge/index.d.ts +1 -1
  14. package/dist/base.d.ts +4 -8
  15. package/dist/base.js +14 -28
  16. package/dist/box/box.svelte +2 -14
  17. package/dist/box/box.svelte.d.ts +0 -2
  18. package/dist/breadcrumbs/breadcrumbs.svelte +38 -19
  19. package/dist/breadcrumbs/breadcrumbs.svelte.d.ts +6 -4
  20. package/dist/breadcrumbs/index.d.ts +1 -1
  21. package/dist/breadcrumbs/index.js +1 -1
  22. package/dist/button/button.svelte +96 -31
  23. package/dist/button/button.svelte.d.ts +11 -5
  24. package/dist/button/index.d.ts +1 -1
  25. package/dist/button/index.js +1 -1
  26. package/dist/chip/chip.svelte +62 -14
  27. package/dist/chip/chip.svelte.d.ts +2 -1
  28. package/dist/command/action.svelte.js +13 -18
  29. package/dist/command/command-palette.svelte +163 -0
  30. package/dist/command/command-palette.svelte.d.ts +11 -0
  31. package/dist/command/index.d.ts +1 -8
  32. package/dist/command/index.js +1 -8
  33. package/dist/common/divider.svelte +10 -5
  34. package/dist/common/divider.svelte.d.ts +3 -3
  35. package/dist/common/index.d.ts +0 -2
  36. package/dist/common/index.js +0 -2
  37. package/dist/dialog/dialog-provider.svelte +70 -0
  38. package/dist/dialog/dialog-provider.svelte.d.ts +7 -0
  39. package/dist/dialog/dialog.svelte +33 -35
  40. package/dist/dialog/dialog.svelte.d.ts +4 -8
  41. package/dist/dialog/dialogs.svelte.d.ts +49 -0
  42. package/dist/dialog/dialogs.svelte.js +73 -0
  43. package/dist/dialog/index.d.ts +2 -3
  44. package/dist/dialog/index.js +2 -3
  45. package/dist/fab/fab.svelte +30 -10
  46. package/dist/fab/fab.svelte.d.ts +3 -2
  47. package/dist/index.d.ts +0 -1
  48. package/dist/index.js +0 -1
  49. package/dist/input/field.d.ts +8 -0
  50. package/dist/input/field.js +7 -0
  51. package/dist/input/index.d.ts +2 -1
  52. package/dist/input/index.js +2 -1
  53. package/dist/input/input.svelte +21 -66
  54. package/dist/input/input.svelte.d.ts +6 -16
  55. package/dist/link/link.svelte +33 -42
  56. package/dist/link/link.svelte.d.ts +4 -3
  57. package/dist/markdown/index.d.ts +2 -25
  58. package/dist/markdown/index.js +0 -24
  59. package/dist/markdown/markdown-tokens.svelte +166 -6
  60. package/dist/markdown/markdown-tokens.svelte.d.ts +2 -0
  61. package/dist/markdown/markdown.svelte +62 -173
  62. package/dist/markdown/markdown.svelte.d.ts +7 -27
  63. package/dist/markdown/parse.d.ts +5 -0
  64. package/dist/markdown/parse.js +30 -0
  65. package/dist/markdown/types.d.ts +28 -0
  66. package/dist/markdown/types.js +1 -0
  67. package/dist/menu/index.d.ts +3 -6
  68. package/dist/menu/index.js +3 -6
  69. package/dist/menu/menu-actions.svelte +44 -38
  70. package/dist/menu/menu-context.d.ts +4 -0
  71. package/dist/menu/menu-context.js +2 -0
  72. package/dist/menu/menu-group.svelte +40 -0
  73. package/dist/menu/menu-group.svelte.d.ts +11 -0
  74. package/dist/menu/menu-item.svelte +31 -54
  75. package/dist/menu/menu-item.svelte.d.ts +7 -5
  76. package/dist/menu/menu.svelte +160 -15
  77. package/dist/menu/menu.svelte.d.ts +15 -4
  78. package/dist/merge-props.d.ts +1 -1
  79. package/dist/merge-props.js +10 -5
  80. package/dist/modal/modal.svelte +60 -83
  81. package/dist/modal/modal.svelte.d.ts +5 -4
  82. package/dist/popover/index.d.ts +1 -1
  83. package/dist/popover/index.js +1 -1
  84. package/dist/popover/popover.svelte +58 -111
  85. package/dist/popover/popover.svelte.d.ts +6 -8
  86. package/dist/progress/circular-progress.svelte +64 -30
  87. package/dist/progress/circular-progress.svelte.d.ts +7 -8
  88. package/dist/shortcut/index.d.ts +2 -2
  89. package/dist/shortcut/index.js +1 -1
  90. package/dist/shortcut/shortcut-hint.svelte +36 -0
  91. package/dist/shortcut/shortcut-hint.svelte.d.ts +9 -0
  92. package/dist/shortcut/shortcut.d.ts +19 -14
  93. package/dist/shortcut/shortcut.js +105 -52
  94. package/dist/skeleton/skeleton.svelte +13 -8
  95. package/dist/skeleton/skeleton.svelte.d.ts +2 -5
  96. package/dist/slider/index.d.ts +1 -8
  97. package/dist/slider/index.js +1 -8
  98. package/dist/slider/slider.svelte +180 -211
  99. package/dist/slider/slider.svelte.d.ts +11 -32
  100. package/dist/switch/index.d.ts +1 -2
  101. package/dist/switch/index.js +1 -2
  102. package/dist/switch/switch.svelte +36 -60
  103. package/dist/switch/switch.svelte.d.ts +6 -17
  104. package/dist/textarea/index.d.ts +1 -1
  105. package/dist/textarea/index.js +1 -1
  106. package/dist/textarea/textarea.svelte +23 -63
  107. package/dist/textarea/textarea.svelte.d.ts +8 -18
  108. package/dist/theme.css +191 -0
  109. package/dist/toggle/index.d.ts +0 -1
  110. package/dist/toggle/index.js +0 -1
  111. package/dist/toggle/toggle-button.svelte +72 -38
  112. package/dist/toggle/toggle-button.svelte.d.ts +4 -4
  113. package/dist/toggle/toggle-context.d.ts +10 -0
  114. package/dist/toggle/toggle-context.js +2 -0
  115. package/dist/toggle/toggle-group.svelte +41 -22
  116. package/dist/toggle/toggle-group.svelte.d.ts +7 -4
  117. package/dist/tooltip/tooltip.svelte +67 -26
  118. package/dist/tooltip/tooltip.svelte.d.ts +10 -4
  119. package/dist/utils.d.ts +9 -3
  120. package/dist/utils.js +10 -0
  121. package/package.json +21 -13
  122. package/dist/autocomplete/autocomplete-content.svelte +0 -47
  123. package/dist/autocomplete/autocomplete-content.svelte.d.ts +0 -10
  124. package/dist/autocomplete/autocomplete-context.svelte.d.ts +0 -12
  125. package/dist/autocomplete/autocomplete-context.svelte.js +0 -34
  126. package/dist/autocomplete/autocomplete-input.svelte +0 -36
  127. package/dist/autocomplete/autocomplete-input.svelte.d.ts +0 -5
  128. package/dist/autocomplete/autocomplete-item.svelte +0 -68
  129. package/dist/autocomplete/autocomplete-item.svelte.d.ts +0 -11
  130. package/dist/base.css +0 -71
  131. package/dist/bindable.svelte.d.ts +0 -7
  132. package/dist/bindable.svelte.js +0 -25
  133. package/dist/command/command-content.svelte +0 -15
  134. package/dist/command/command-content.svelte.d.ts +0 -8
  135. package/dist/command/command-context.svelte.d.ts +0 -5
  136. package/dist/command/command-context.svelte.js +0 -13
  137. package/dist/command/command-input.svelte +0 -44
  138. package/dist/command/command-input.svelte.d.ts +0 -7
  139. package/dist/command/command-item.svelte +0 -66
  140. package/dist/command/command-item.svelte.d.ts +0 -11
  141. package/dist/command/command-search.svelte +0 -28
  142. package/dist/command/command-search.svelte.d.ts +0 -5
  143. package/dist/command/command.svelte +0 -19
  144. package/dist/command/command.svelte.d.ts +0 -8
  145. package/dist/command/commander.svelte +0 -107
  146. package/dist/command/commander.svelte.d.ts +0 -9
  147. package/dist/common/header.svelte +0 -35
  148. package/dist/common/header.svelte.d.ts +0 -10
  149. package/dist/common/item-context.svelte.d.ts +0 -12
  150. package/dist/common/item-context.svelte.js +0 -77
  151. package/dist/dialog/dialog-button.svelte +0 -25
  152. package/dist/dialog/dialog-button.svelte.d.ts +0 -32
  153. package/dist/dialog/dialoguer-context.svelte.d.ts +0 -53
  154. package/dist/dialog/dialoguer-context.svelte.js +0 -85
  155. package/dist/dialog/dialoguer.svelte +0 -65
  156. package/dist/dialog/dialoguer.svelte.d.ts +0 -7
  157. package/dist/markdown/markdown-blockquote.svelte +0 -14
  158. package/dist/markdown/markdown-blockquote.svelte.d.ts +0 -7
  159. package/dist/markdown/markdown-br.svelte +0 -12
  160. package/dist/markdown/markdown-br.svelte.d.ts +0 -7
  161. package/dist/markdown/markdown-code.svelte +0 -14
  162. package/dist/markdown/markdown-code.svelte.d.ts +0 -7
  163. package/dist/markdown/markdown-codespan.svelte +0 -15
  164. package/dist/markdown/markdown-codespan.svelte.d.ts +0 -7
  165. package/dist/markdown/markdown-context.svelte.d.ts +0 -26
  166. package/dist/markdown/markdown-context.svelte.js +0 -30
  167. package/dist/markdown/markdown-def.svelte +0 -15
  168. package/dist/markdown/markdown-def.svelte.d.ts +0 -7
  169. package/dist/markdown/markdown-del.svelte +0 -14
  170. package/dist/markdown/markdown-del.svelte.d.ts +0 -7
  171. package/dist/markdown/markdown-em.svelte +0 -14
  172. package/dist/markdown/markdown-em.svelte.d.ts +0 -7
  173. package/dist/markdown/markdown-escape.svelte +0 -8
  174. package/dist/markdown/markdown-escape.svelte.d.ts +0 -5
  175. package/dist/markdown/markdown-heading.svelte +0 -16
  176. package/dist/markdown/markdown-heading.svelte.d.ts +0 -7
  177. package/dist/markdown/markdown-hr.svelte +0 -12
  178. package/dist/markdown/markdown-hr.svelte.d.ts +0 -7
  179. package/dist/markdown/markdown-html.svelte +0 -9
  180. package/dist/markdown/markdown-html.svelte.d.ts +0 -5
  181. package/dist/markdown/markdown-image.svelte +0 -12
  182. package/dist/markdown/markdown-image.svelte.d.ts +0 -7
  183. package/dist/markdown/markdown-link.svelte +0 -17
  184. package/dist/markdown/markdown-link.svelte.d.ts +0 -7
  185. package/dist/markdown/markdown-list-item.svelte +0 -14
  186. package/dist/markdown/markdown-list-item.svelte.d.ts +0 -7
  187. package/dist/markdown/markdown-list.svelte +0 -19
  188. package/dist/markdown/markdown-list.svelte.d.ts +0 -7
  189. package/dist/markdown/markdown-paragraph.svelte +0 -16
  190. package/dist/markdown/markdown-paragraph.svelte.d.ts +0 -7
  191. package/dist/markdown/markdown-space.svelte +0 -8
  192. package/dist/markdown/markdown-space.svelte.d.ts +0 -5
  193. package/dist/markdown/markdown-strong.svelte +0 -15
  194. package/dist/markdown/markdown-strong.svelte.d.ts +0 -7
  195. package/dist/markdown/markdown-table-cell.svelte +0 -16
  196. package/dist/markdown/markdown-table-cell.svelte.d.ts +0 -7
  197. package/dist/markdown/markdown-table.svelte +0 -36
  198. package/dist/markdown/markdown-table.svelte.d.ts +0 -7
  199. package/dist/markdown/markdown-text.svelte +0 -8
  200. package/dist/markdown/markdown-text.svelte.d.ts +0 -5
  201. package/dist/markdown/markdown-token.svelte +0 -25
  202. package/dist/markdown/markdown-token.svelte.d.ts +0 -7
  203. package/dist/menu/menu-content.svelte +0 -47
  204. package/dist/menu/menu-content.svelte.d.ts +0 -10
  205. package/dist/menu/menu-context.svelte.d.ts +0 -18
  206. package/dist/menu/menu-context.svelte.js +0 -118
  207. package/dist/menu/menu-trigger-button.svelte +0 -31
  208. package/dist/menu/menu-trigger-button.svelte.d.ts +0 -5
  209. package/dist/menu/menu-trigger.svelte +0 -42
  210. package/dist/menu/menu-trigger.svelte.d.ts +0 -10
  211. package/dist/ordered-html-elements.d.ts +0 -7
  212. package/dist/ordered-html-elements.js +0 -29
  213. package/dist/portal/index.d.ts +0 -2
  214. package/dist/portal/index.js +0 -2
  215. package/dist/portal/portal.svelte +0 -15
  216. package/dist/portal/portal.svelte.d.ts +0 -8
  217. package/dist/portal/proxy.svelte +0 -13
  218. package/dist/portal/proxy.svelte.d.ts +0 -7
  219. package/dist/shortcut/shortcut-badge.svelte +0 -41
  220. package/dist/shortcut/shortcut-badge.svelte.d.ts +0 -11
  221. package/dist/slider/slider-context.svelte.d.ts +0 -50
  222. package/dist/slider/slider-context.svelte.js +0 -198
  223. package/dist/slider/slider-handle-label-arrow.svelte +0 -18
  224. package/dist/slider/slider-handle-label-arrow.svelte.d.ts +0 -6
  225. package/dist/slider/slider-handle-label.svelte +0 -35
  226. package/dist/slider/slider-handle-label.svelte.d.ts +0 -6
  227. package/dist/slider/slider-handle.svelte +0 -54
  228. package/dist/slider/slider-handle.svelte.d.ts +0 -6
  229. package/dist/slider/slider-mark-dot.svelte +0 -25
  230. package/dist/slider/slider-mark-dot.svelte.d.ts +0 -6
  231. package/dist/slider/slider-mark-label.svelte +0 -37
  232. package/dist/slider/slider-mark-label.svelte.d.ts +0 -9
  233. package/dist/slider/slider-mark.svelte +0 -33
  234. package/dist/slider/slider-mark.svelte.d.ts +0 -9
  235. package/dist/switch/switch-thumb.svelte +0 -52
  236. package/dist/switch/switch-thumb.svelte.d.ts +0 -7
  237. package/dist/toggle/toggle-context.svelte.d.ts +0 -9
  238. package/dist/toggle/toggle-context.svelte.js +0 -32
package/README.md CHANGED
@@ -1,12 +1,41 @@
1
1
  # Kosui
2
2
 
3
- A Svelte component library used by [Koso](https://koso.app) and [Cipherly](https://cipherly.app).
3
+ Accessible Svelte 5 components, styled with Material 3 and Tailwind CSS. Used by [Cipherly](https://cipherly.app).
4
+
5
+ **Docs and live examples: [kosui.kosolabs.com](https://kosui.kosolabs.com)**
6
+
7
+ ## Getting Started
8
+
9
+ Kosui needs Svelte 5 and Tailwind CSS 4.
10
+
11
+ ```
12
+ pnpm add kosui
13
+ ```
14
+
15
+ Import Kosui's theme after Tailwind in your app's CSS. It adds the Material 3 colors as utilities like `bg-m3-primary`, a default palette, and tells Tailwind to scan Kosui's components.
16
+
17
+ ```css
18
+ @import "tailwindcss";
19
+ @import "kosui/theme.css";
20
+ ```
21
+
22
+ Then use the components:
23
+
24
+ ```svelte
25
+ <script lang="ts">
26
+ import { Button } from "kosui";
27
+ </script>
28
+
29
+ <Button variant="filled">Save</Button>
30
+ ```
31
+
32
+ To use your own colors, override the `--md-sys-color-*` variables, for example with a palette from the [Material Theme Builder](https://material-foundation.github.io/material-theme-builder/). Add the `dark` class to `<html>` for the dark palette.
4
33
 
5
34
  ## Design Philosophy
6
35
 
7
36
  These principles are listed in order of priority. When they conflict, the higher principle wins.
8
37
 
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.
38
+ **Svelte First** — Write idiomatic, current Svelte. Use runes, snippets, and attachments, and reach for Svelte's built-ins before writing our own: `$derived` (writable when needed) over effects that sync state, `createContext` for context, `$props.id()` for ids. When Svelte adds a built-in for something we hand-rolled, adopt it.
10
39
 
11
40
  **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
41
 
@@ -14,7 +43,9 @@ These principles are listed in order of priority. When they conflict, the higher
14
43
 
15
44
  **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
45
 
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.
46
+ **Shared Vocabulary** — A concept has one name across the library. `variant`, `color`, `shape`, `size`, and `underline` take the same values and mean the same thing on every component that uses them, so a prop learned once works everywhere. A `size` is a row height (`xs` 28px, `sm` 36px, `md` 44px, `lg` 52px, `xl` 60px): components at the same size line up in a row, each choosing its own default. A `shape` is a corner radius on Material 3's scale (`none`, `xs` 4px, `sm` 8px, `md` 12px, `lg` 16px, `xl` 28px, `full`), and each component defaults to the shape Material 3 gives it. Components adopt a shared prop wherever its concept applies, and never reuse a shared name for something else.
47
+
48
+ **Transparent Props** — Components behave like the element they render. Every component spreads `...restProps` onto that element, attachments included, and provides an `el` binding. Props like `class` accept whatever the native element accepts.
18
49
 
19
50
  **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
51
 
@@ -1,168 +1,27 @@
1
1
  <script lang="ts" module>
2
- import {
3
- COLORS,
4
- RADII,
5
- type Color,
6
- type ColorProp,
7
- type Radius,
8
- type RadiusProp,
9
- } from "../base.js";
10
- import type { Snippet } from "svelte";
11
- import type { HTMLAttributes } from "svelte/elements";
2
+ import { Box, type BoxProps } from "../box/index.js";
3
+ import { cn } from "../utils.js";
12
4
 
13
- export const ALERT_VARIANT = ["filled", "tonal", "plain"] as const;
14
- export type AlertVariant = (typeof ALERT_VARIANT)[number];
15
- export type AlertVariantProp = { variant?: AlertVariant };
16
-
17
- export const ALERT_COLORS = COLORS;
18
- export type AlertColor = Color;
19
- export type AlertColorProp = ColorProp;
20
-
21
- export type AlertOutlined = boolean;
22
- export type AlertOutlinedProp = { outlined?: AlertOutlined };
23
-
24
- export type AlertElevated = boolean;
25
- export type AlertElevatedProp = { elevated?: AlertElevated };
26
-
27
- export const ALERT_RADII = RADII;
28
- export type AlertRadius = Radius;
29
- export type AlertRadiusProp = RadiusProp;
30
-
31
- export type AlertProps = {
32
- children: Snippet<[]>;
33
- } & AlertVariantProp &
34
- AlertColorProp &
35
- AlertRadiusProp &
36
- AlertOutlinedProp &
37
- AlertElevatedProp &
38
- HTMLAttributes<HTMLDivElement>;
5
+ export type AlertProps = BoxProps;
39
6
  </script>
40
7
 
41
8
  <script lang="ts">
42
- const {
9
+ let {
10
+ el = $bindable(),
11
+ class: className,
43
12
  variant = "tonal",
44
13
  color = "primary",
45
- radius = "sm",
46
- outlined = false,
47
- elevated = false,
48
- children,
49
- class: className,
50
- ...props
14
+ shape = "md",
15
+ ...restProps
51
16
  }: AlertProps = $props();
52
17
  </script>
53
18
 
54
- <div
19
+ <Box
20
+ bind:el
55
21
  role="alert"
56
- class={[
57
- "base",
58
- `variant-${variant}`,
59
- `color-${color}`,
60
- `radius-${radius}`,
61
- outlined && "outlined",
62
- elevated && "elevated",
63
- className,
64
- ]}
65
- {...props}
66
- >
67
- {@render children()}
68
- </div>
69
-
70
- <style>@layer components { .radius-none {
71
- --radius: none;
72
- }
73
-
74
- .radius-xs {
75
- --radius: 0.125rem;
76
- }
77
-
78
- .radius-sm {
79
- --radius: 0.25rem;
80
- }
81
-
82
- .radius-md {
83
- --radius: 0.375rem;
84
- }
85
-
86
- .radius-lg {
87
- --radius: 0.5rem;
88
- }
89
-
90
- .radius-xl {
91
- --radius: 0.75rem;
92
- }
93
-
94
- .radius-2xl {
95
- --radius: 1rem;
96
- }
97
-
98
- .radius-3xl {
99
- --radius: 1.5rem;
100
- }
101
-
102
- .radius-4xl {
103
- --radius: 2rem;
104
- }
105
-
106
- .radius-full {
107
- --radius: calc(infinity * 1px);
108
- }
109
-
110
- .color-primary {
111
- --color-main: var(--md-sys-color-primary);
112
- --color-on-main: var(--md-sys-color-on-primary);
113
- --color-tonal: var(--md-sys-color-primary-container);
114
- --color-on-tonal: var(--md-sys-color-on-primary-container);
115
- --color-shadow: var(--md-sys-color-shadow);
116
- }
117
-
118
- .color-secondary {
119
- --color-main: var(--md-sys-color-secondary);
120
- --color-on-main: var(--md-sys-color-on-secondary);
121
- --color-tonal: var(--md-sys-color-secondary-container);
122
- --color-on-tonal: var(--md-sys-color-on-secondary-container);
123
- --color-shadow: var(--md-sys-color-shadow);
124
- }
125
-
126
- .color-tertiary {
127
- --color-main: var(--md-sys-color-tertiary);
128
- --color-on-main: var(--md-sys-color-on-tertiary);
129
- --color-tonal: var(--md-sys-color-tertiary-container);
130
- --color-on-tonal: var(--md-sys-color-on-tertiary-container);
131
- --color-shadow: var(--md-sys-color-shadow);
132
- }
133
-
134
- .color-error {
135
- --color-main: var(--md-sys-color-error);
136
- --color-on-main: var(--md-sys-color-on-error);
137
- --color-tonal: var(--md-sys-color-error-container);
138
- --color-on-tonal: var(--md-sys-color-on-error-container);
139
- --color-shadow: var(--md-sys-color-shadow);
140
- }
141
-
142
- .base {
143
- padding: calc(var(--spacing) * 4);
144
- border-radius: var(--radius);
145
- }
146
-
147
- .variant-filled {
148
- background-color: var(--color-main);
149
- color: var(--color-on-main);
150
- }
151
-
152
- .variant-tonal {
153
- background-color: var(--color-tonal);
154
- color: var(--color-on-tonal);
155
- }
156
-
157
- .outlined {
158
- border-width: 1px;
159
- border-style: solid;
160
- border-color: var(--color-main);
161
- }
162
-
163
- .elevated {
164
- box-shadow:
165
- 0 1px 3px 0 rgb(from var(--color-shadow, rgb(0 0 0)) r g b / 0.2),
166
- 0 1px 2px -1px rgb(from var(--color-shadow, rgb(0 0 0)) r g b / 0.2);
167
- }
168
- }</style>
22
+ {variant}
23
+ {color}
24
+ {shape}
25
+ class={cn("p-4", className)}
26
+ {...restProps}
27
+ />
@@ -1,28 +1,5 @@
1
- import { type Color, type ColorProp, type Radius, type RadiusProp } from "../base.js";
2
- import type { Snippet } from "svelte";
3
- import type { HTMLAttributes } from "svelte/elements";
4
- export declare const ALERT_VARIANT: readonly ["filled", "tonal", "plain"];
5
- export type AlertVariant = (typeof ALERT_VARIANT)[number];
6
- export type AlertVariantProp = {
7
- variant?: AlertVariant;
8
- };
9
- export declare const ALERT_COLORS: readonly ["primary", "secondary", "tertiary", "error", "plain", "inherit"];
10
- export type AlertColor = Color;
11
- export type AlertColorProp = ColorProp;
12
- export type AlertOutlined = boolean;
13
- export type AlertOutlinedProp = {
14
- outlined?: AlertOutlined;
15
- };
16
- export type AlertElevated = boolean;
17
- export type AlertElevatedProp = {
18
- elevated?: AlertElevated;
19
- };
20
- export declare const ALERT_RADII: readonly ["none", "xs", "sm", "md", "lg", "xl", "2xl", "3xl", "4xl", "full"];
21
- export type AlertRadius = Radius;
22
- export type AlertRadiusProp = RadiusProp;
23
- export type AlertProps = {
24
- children: Snippet<[]>;
25
- } & AlertVariantProp & AlertColorProp & AlertRadiusProp & AlertOutlinedProp & AlertElevatedProp & HTMLAttributes<HTMLDivElement>;
26
- declare const Alert: import("svelte").Component<AlertProps, {}, "">;
1
+ import { type BoxProps } from "../box/index.js";
2
+ export type AlertProps = BoxProps;
3
+ declare const Alert: import("svelte").Component<BoxProps, {}, "el">;
27
4
  type Alert = ReturnType<typeof Alert>;
28
5
  export default Alert;
@@ -1 +1 @@
1
- export { default as Alert, ALERT_COLORS, ALERT_RADII, ALERT_VARIANT, type AlertColor, type AlertColorProp, type AlertElevated, type AlertElevatedProp, type AlertOutlined, type AlertOutlinedProp, type AlertProps, type AlertRadius, type AlertRadiusProp, type AlertVariant, type AlertVariantProp, } from "./alert.svelte";
1
+ export { default as Alert, type AlertProps } from "./alert.svelte";
@@ -1 +1 @@
1
- export { default as Alert, ALERT_COLORS, ALERT_RADII, ALERT_VARIANT, } from "./alert.svelte";
1
+ export { default as Alert } from "./alert.svelte";
@@ -1,20 +1,134 @@
1
1
  <script module lang="ts">
2
- import {
3
- AutocompleteContext,
4
- setAutocompleteContext,
5
- } from "./index.js";
6
- import type { ClassName } from "../utils.js";
2
+ import { Input, type InputProps } from "../input/index.js";
3
+ import { mergeComponentProps } from "../merge-props.js";
4
+ import { Popover } from "../popover/index.js";
5
+ import { Shortcut } from "../shortcut/index.js";
7
6
  import type { Snippet } from "svelte";
8
7
 
9
- export type AutocompleteProps = {
10
- children: Snippet;
11
- } & ClassName;
8
+ export type AutocompleteProps<T> = {
9
+ options: T[];
10
+ getOptionLabel?: (option: T) => string;
11
+ option?: Snippet<[T]>;
12
+ onSelect?: (option: T) => void;
13
+ } & InputProps;
12
14
  </script>
13
15
 
14
- <script lang="ts">
15
- let { children }: AutocompleteProps = $props();
16
+ <script lang="ts" generics="T">
17
+ let {
18
+ value = $bindable(""),
19
+ el = $bindable(),
20
+ options,
21
+ getOptionLabel = String,
22
+ option: optionSnippet,
23
+ onSelect,
24
+ ...restProps
25
+ }: AutocompleteProps<T> = $props();
16
26
 
17
- setAutocompleteContext(new AutocompleteContext());
27
+ const id = $props.id();
28
+ let expanded = $state(false);
29
+ let active = $state(-1);
30
+
31
+ const open = $derived(expanded && options.length > 0);
32
+ const current = $derived(open && active < options.length ? active : -1);
33
+
34
+ function choose(option: T) {
35
+ value = getOptionLabel(option);
36
+ expanded = false;
37
+ active = -1;
38
+ onSelect?.(option);
39
+ }
40
+
41
+ function move(step: 1 | -1) {
42
+ const count = options.length;
43
+ if (!open) {
44
+ expanded = true;
45
+ active = step === 1 ? 0 : count - 1;
46
+ } else if (current === -1) {
47
+ active = step === 1 ? 0 : count - 1;
48
+ } else {
49
+ active = (current + step + count) % count;
50
+ }
51
+ }
52
+
53
+ function onkeydown(event: KeyboardEvent) {
54
+ if (Shortcut.ARROW_DOWN.matches(event)) {
55
+ move(1);
56
+ } else if (Shortcut.ARROW_UP.matches(event)) {
57
+ move(-1);
58
+ } else if (Shortcut.ENTER.matches(event) && current !== -1) {
59
+ choose(options[current]);
60
+ } else if (Shortcut.ESCAPE.matches(event) && open) {
61
+ expanded = false;
62
+ event.stopPropagation();
63
+ } else {
64
+ if (event.key === "Tab") expanded = false;
65
+ return;
66
+ }
67
+ event.preventDefault();
68
+ }
69
+
70
+ $effect(() => {
71
+ if (current !== -1) {
72
+ document
73
+ .getElementById(`${id}-${current}`)
74
+ ?.scrollIntoView({ block: "nearest" });
75
+ }
76
+ });
18
77
  </script>
19
78
 
20
- {@render children()}
79
+ <Input
80
+ bind:value
81
+ bind:el
82
+ role="combobox"
83
+ autocomplete="off"
84
+ aria-autocomplete="list"
85
+ aria-expanded={open}
86
+ aria-controls={open ? `${id}-listbox` : undefined}
87
+ aria-activedescendant={current === -1 ? undefined : `${id}-${current}`}
88
+ {...mergeComponentProps(
89
+ Input,
90
+ {
91
+ oninput: () => {
92
+ expanded = true;
93
+ active = -1;
94
+ },
95
+ onkeydown,
96
+ onblur: () => (expanded = false),
97
+ },
98
+ restProps,
99
+ )}
100
+ />
101
+
102
+ <Popover
103
+ bind:open={
104
+ () => open,
105
+ (next) => {
106
+ if (!next) expanded = false;
107
+ }
108
+ }
109
+ anchorEl={el}
110
+ placement="bottom-start"
111
+ id="{id}-listbox"
112
+ role="listbox"
113
+ class="max-h-72 min-w-[anchor-size(width)] overflow-y-auto rounded-sm bg-m3-surface-container p-1 text-m3-on-surface shadow-md shadow-m3-shadow/20"
114
+ >
115
+ {#each options as option, index (index)}
116
+ <!-- svelte-ignore a11y_click_events_have_key_events -->
117
+ <div
118
+ id="{id}-{index}"
119
+ role="option"
120
+ tabindex="-1"
121
+ aria-selected={index === current}
122
+ class="flex min-h-8 cursor-pointer items-center gap-2 rounded-sm px-3 py-1 text-sm aria-selected:bg-m3-on-surface/10"
123
+ onmousedown={(event) => event.preventDefault()}
124
+ onpointermove={() => (active = index)}
125
+ onclick={() => choose(option)}
126
+ >
127
+ {#if optionSnippet}
128
+ {@render optionSnippet(option)}
129
+ {:else}
130
+ {getOptionLabel(option)}
131
+ {/if}
132
+ </div>
133
+ {/each}
134
+ </Popover>
@@ -1,8 +1,32 @@
1
- import type { ClassName } from "../utils.js";
1
+ import { type InputProps } from "../input/index.js";
2
2
  import type { Snippet } from "svelte";
3
- export type AutocompleteProps = {
4
- children: Snippet;
5
- } & ClassName;
6
- declare const Autocomplete: import("svelte").Component<AutocompleteProps, {}, "">;
7
- type Autocomplete = ReturnType<typeof Autocomplete>;
3
+ export type AutocompleteProps<T> = {
4
+ options: T[];
5
+ getOptionLabel?: (option: T) => string;
6
+ option?: Snippet<[T]>;
7
+ onSelect?: (option: T) => void;
8
+ } & InputProps;
9
+ declare function $$render<T>(): {
10
+ props: AutocompleteProps<T>;
11
+ exports: {};
12
+ bindings: "el" | "value";
13
+ slots: {};
14
+ events: {};
15
+ };
16
+ declare class __sveltets_Render<T> {
17
+ props(): ReturnType<typeof $$render<T>>['props'];
18
+ events(): ReturnType<typeof $$render<T>>['events'];
19
+ slots(): ReturnType<typeof $$render<T>>['slots'];
20
+ bindings(): "el" | "value";
21
+ exports(): {};
22
+ }
23
+ interface $$IsomorphicComponent {
24
+ new <T>(options: import('svelte').ComponentConstructorOptions<ReturnType<__sveltets_Render<T>['props']>>): import('svelte').SvelteComponent<ReturnType<__sveltets_Render<T>['props']>, ReturnType<__sveltets_Render<T>['events']>, ReturnType<__sveltets_Render<T>['slots']>> & {
25
+ $$bindings?: ReturnType<__sveltets_Render<T>['bindings']>;
26
+ } & ReturnType<__sveltets_Render<T>['exports']>;
27
+ <T>(internal: unknown, props: ReturnType<__sveltets_Render<T>['props']> & {}): ReturnType<__sveltets_Render<T>['exports']>;
28
+ z_$$bindings?: ReturnType<__sveltets_Render<any>['bindings']>;
29
+ }
30
+ declare const Autocomplete: $$IsomorphicComponent;
31
+ type Autocomplete<T> = InstanceType<typeof Autocomplete<T>>;
8
32
  export default Autocomplete;
@@ -1,5 +1 @@
1
- export { default as AutocompleteContent } from "./autocomplete-content.svelte";
2
- export { AutocompleteContext, getAutocompleteContext, setAutocompleteContext, } from "./autocomplete-context.svelte.js";
3
- export { default as AutocompleteInput } from "./autocomplete-input.svelte";
4
- export { default as AutocompleteItem } from "./autocomplete-item.svelte";
5
- export { default as Autocomplete } from "./autocomplete.svelte";
1
+ export { default as Autocomplete, type AutocompleteProps, } from "./autocomplete.svelte";
@@ -1,5 +1 @@
1
- export { default as AutocompleteContent } from "./autocomplete-content.svelte";
2
- export { AutocompleteContext, getAutocompleteContext, setAutocompleteContext, } from "./autocomplete-context.svelte.js";
3
- export { default as AutocompleteInput } from "./autocomplete-input.svelte";
4
- export { default as AutocompleteItem } from "./autocomplete-item.svelte";
5
- export { default as Autocomplete } from "./autocomplete.svelte";
1
+ export { default as Autocomplete, } from "./autocomplete.svelte";
@@ -1,6 +1,6 @@
1
1
  <script lang="ts" module>
2
2
  import { Box, type BoxProps } from "../box/index.js";
3
- import { twMerge } from "tailwind-merge";
3
+ import { cn } from "../utils.js";
4
4
 
5
5
  export type AvatarProps = {
6
6
  src?: string;
@@ -17,31 +17,37 @@
17
17
  class: className,
18
18
  variant = "tonal",
19
19
  color = "secondary",
20
- shape = "rounded",
21
- centered = true,
20
+ shape = "full",
22
21
  ...restProps
23
22
  }: AvatarProps = $props();
24
23
 
25
- let error: boolean = $state(false);
24
+ let failedSrc: string | undefined = $state();
26
25
  </script>
27
26
 
28
27
  <Box
29
28
  bind:el
29
+ role={alt ? "img" : undefined}
30
+ aria-label={alt || undefined}
30
31
  {variant}
31
32
  {color}
32
33
  {shape}
33
- {centered}
34
- class={twMerge("aspect-square h-9 overflow-clip text-xl", className)}
34
+ class={cn(
35
+ "@container flex aspect-square h-9 items-center justify-center overflow-clip",
36
+ className,
37
+ )}
35
38
  {...restProps}
36
39
  >
37
- {#if src && !error}
40
+ {#if src && src !== failedSrc}
38
41
  <img
42
+ class="size-full object-cover"
39
43
  {src}
40
- {alt}
41
- onerror={() => (error = true)}
44
+ alt=""
45
+ onerror={() => (failedSrc = src)}
42
46
  referrerpolicy="no-referrer"
43
47
  />
44
48
  {:else}
45
- {@render children?.()}
49
+ <span class="contents text-[50cqw] leading-none">
50
+ {@render children?.()}
51
+ </span>
46
52
  {/if}
47
53
  </Box>
@@ -1,43 +1,54 @@
1
1
  <script lang="ts">
2
- import { Box, type BoxProps } from "../box/index.js";
3
- import { twMerge } from "tailwind-merge";
2
+ import { baseClasses, type ColorProp, type VariantProp } from "../base.js";
3
+ import { cn, type ClassName, type ElementRef } from "../utils.js";
4
+ import type { Snippet } from "svelte";
5
+ import type { HTMLAttributes } from "svelte/elements";
4
6
 
5
7
  export type BadgeProps = {
8
+ content?: Snippet | string;
6
9
  verticalAlignment?: "top" | "bottom";
7
10
  horizontalAlignment?: "left" | "right";
8
- content?: string;
9
- } & BoxProps;
11
+ children?: Snippet;
12
+ } & ElementRef &
13
+ ClassName &
14
+ VariantProp &
15
+ ColorProp &
16
+ Omit<HTMLAttributes<HTMLSpanElement>, "content">;
10
17
 
11
18
  let {
19
+ content,
12
20
  verticalAlignment = "top",
13
21
  horizontalAlignment = "right",
14
- content,
15
22
  children,
23
+ el = $bindable(),
16
24
  class: className,
17
25
  variant = "filled",
18
- color = "primary",
19
- centered = true,
26
+ color = "error",
27
+ ...restProps
20
28
  }: BadgeProps = $props();
21
29
  </script>
22
30
 
23
- <div class="relative">
31
+ <span class="relative inline-flex">
32
+ {@render children?.()}
24
33
  {#if content}
25
- <Box
26
- {variant}
27
- {color}
28
- {centered}
29
- shape="circle"
30
- class={twMerge(
31
- "absolute z-10 size-5 p-1 text-xs",
32
-
34
+ <span
35
+ bind:this={el}
36
+ class={cn(
37
+ baseClasses({ variant, color, shape: "full" }),
38
+ "absolute inline-flex h-5 min-w-5 items-center justify-center px-1 text-xs tabular-nums",
33
39
  verticalAlignment === "top" && "top-0 -translate-y-1/2",
34
40
  verticalAlignment === "bottom" && "bottom-0 translate-y-1/2",
35
41
  horizontalAlignment === "left" && "left-0 -translate-x-1/2",
36
42
  horizontalAlignment === "right" && "right-0 translate-x-1/2",
37
-
38
43
  className,
39
- )}>{content}</Box
44
+ )}
45
+ {...restProps}
40
46
  >
47
+ {#if typeof content === "function"}
48
+ {@render content()}
49
+ {:else}
50
+ {content}
51
+ {/if}
52
+ </span>
41
53
  {/if}
42
- {@render children?.()}
43
- </div>
54
+ </span>
@@ -1,9 +1,13 @@
1
- import { type BoxProps } from "../box/index.js";
1
+ import { type ColorProp, type VariantProp } from "../base.js";
2
+ import { type ClassName, type ElementRef } from "../utils.js";
3
+ import type { Snippet } from "svelte";
4
+ import type { HTMLAttributes } from "svelte/elements";
2
5
  export type BadgeProps = {
6
+ content?: Snippet | string;
3
7
  verticalAlignment?: "top" | "bottom";
4
8
  horizontalAlignment?: "left" | "right";
5
- content?: string;
6
- } & BoxProps;
7
- declare const Badge: import("svelte").Component<BadgeProps, {}, "">;
9
+ children?: Snippet;
10
+ } & ElementRef & ClassName & VariantProp & ColorProp & Omit<HTMLAttributes<HTMLSpanElement>, "content">;
11
+ declare const Badge: import("svelte").Component<BadgeProps, {}, "el">;
8
12
  type Badge = ReturnType<typeof Badge>;
9
13
  export default Badge;
@@ -1 +1 @@
1
- export { default as Badge } from "./badge.svelte";
1
+ export { default as Badge, type BadgeProps } from "./badge.svelte";
package/dist/base.d.ts CHANGED
@@ -8,7 +8,7 @@ export type Color = (typeof COLORS)[number];
8
8
  export type ColorProp = {
9
9
  color?: Color;
10
10
  };
11
- export declare const SHAPES: readonly ["square", "rounded", "circle"];
11
+ export declare const SHAPES: readonly ["none", "xs", "sm", "md", "lg", "xl", "full"];
12
12
  export type Shape = (typeof SHAPES)[number];
13
13
  export type ShapeProp = {
14
14
  shape?: Shape;
@@ -18,18 +18,14 @@ export type Size = (typeof SIZES)[number];
18
18
  export type SizeProp = {
19
19
  size?: Size;
20
20
  };
21
- export declare const RADII: readonly ["none", "xs", "sm", "md", "lg", "xl", "2xl", "3xl", "4xl", "full"];
22
- export type Radius = (typeof RADII)[number];
23
- export type RadiusProp = {
24
- radius?: Radius;
25
- };
26
21
  export declare const UNDERLINES: readonly ["always", "hover", "none"];
27
22
  export type Underline = (typeof UNDERLINES)[number];
28
23
  export type UnderlineProp = {
29
24
  underline?: Underline;
30
25
  };
31
- export type Variants = VariantProp & ColorProp & ShapeProp & UnderlineProp & {
26
+ export type Variants = VariantProp & ColorProp & ShapeProp;
27
+ export type BaseClassOptions = Variants & UnderlineProp & {
32
28
  hover?: boolean;
33
29
  focus?: boolean;
34
30
  };
35
- export declare const baseClasses: ({ variant, color, shape, underline, hover, focus, }: Variants) => string;
31
+ export declare const baseClasses: ({ variant, color, shape, underline, hover, focus, }: BaseClassOptions) => string;