kosui 0.2.0 → 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 +6 -5
  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 -31
  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 -216
  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
@@ -0,0 +1,163 @@
1
+ <script module lang="ts">
2
+ import { events } from "../index.js";
3
+ import { Modal } from "../modal/index.js";
4
+ import { Shortcut, ShortcutHint } from "../shortcut/index.js";
5
+ import { match } from "../utils.js";
6
+ import { Check, Search } from "@lucide/svelte";
7
+ import type { Action, Registry } from "./action.svelte";
8
+
9
+ export type CommandPaletteProps = {
10
+ registry: Registry;
11
+ open?: boolean;
12
+ query?: string;
13
+ label?: string;
14
+ placeholder?: string;
15
+ };
16
+
17
+ function isTyping(event: KeyboardEvent) {
18
+ return (
19
+ event.target instanceof HTMLElement &&
20
+ (event.target.isContentEditable ||
21
+ event.target.matches("input, textarea, select"))
22
+ );
23
+ }
24
+ </script>
25
+
26
+ <script lang="ts">
27
+ let {
28
+ registry,
29
+ open = $bindable(false),
30
+ query = $bindable(""),
31
+ label = "Command palette",
32
+ placeholder = "Search commands",
33
+ }: CommandPaletteProps = $props();
34
+
35
+ const id = $props.id();
36
+ let active = $state(0);
37
+
38
+ const actions = $derived(
39
+ registry.actions.filter(
40
+ (action) =>
41
+ action.enabled() &&
42
+ (match(action.id, query) ||
43
+ (action.category && match(action.category, query)) ||
44
+ match(action.name, query) ||
45
+ match(action.description, query)),
46
+ ),
47
+ );
48
+ const current = $derived(Math.min(active, actions.length - 1));
49
+
50
+ function run(action: Action) {
51
+ open = false;
52
+ action.callback();
53
+ }
54
+
55
+ function onkeydown(event: KeyboardEvent) {
56
+ const count = actions.length;
57
+ if (Shortcut.ARROW_DOWN.matches(event)) {
58
+ active = (current + 1) % count;
59
+ } else if (Shortcut.ARROW_UP.matches(event)) {
60
+ active = (current - 1 + count) % count;
61
+ } else if (Shortcut.ENTER.matches(event) && current !== -1) {
62
+ run(actions[current]);
63
+ } else {
64
+ return;
65
+ }
66
+ event.preventDefault();
67
+ }
68
+
69
+ function runShortcut(event: KeyboardEvent) {
70
+ const shortcut = Shortcut.fromEvent(event);
71
+ if (isTyping(event) && !shortcut.ctrl && !shortcut.meta && !shortcut.alt) {
72
+ return;
73
+ }
74
+ const action = registry.getByShortcut(shortcut);
75
+ if (action?.enabled()) {
76
+ action.callback();
77
+ event.preventDefault();
78
+ event.stopImmediatePropagation();
79
+ }
80
+ }
81
+
82
+ $effect(() => events.on("keydown", runShortcut));
83
+
84
+ $effect(() => {
85
+ if (current !== -1) {
86
+ document
87
+ .getElementById(`${id}-${current}`)
88
+ ?.scrollIntoView({ block: "nearest" });
89
+ }
90
+ });
91
+ </script>
92
+
93
+ <Modal
94
+ bind:open
95
+ aria-label={label}
96
+ class="flex h-[min(60vh,32rem)] w-[min(calc(100%-1em),36rem)] flex-col p-0"
97
+ onoutroend={() => {
98
+ query = "";
99
+ active = 0;
100
+ }}
101
+ >
102
+ <div class="flex items-center gap-2 border-b border-m3-outline-variant px-4">
103
+ <Search size={16} class="shrink-0 text-m3-on-surface-variant" />
104
+ <!-- svelte-ignore a11y_autofocus -->
105
+ <input
106
+ bind:value={query}
107
+ role="combobox"
108
+ aria-label={placeholder}
109
+ aria-autocomplete="list"
110
+ aria-expanded="true"
111
+ aria-controls="{id}-listbox"
112
+ aria-activedescendant={current === -1 ? undefined : `${id}-${current}`}
113
+ autocomplete="off"
114
+ autofocus
115
+ {placeholder}
116
+ class="h-12 w-full bg-transparent outline-none placeholder:text-m3-on-surface-variant"
117
+ oninput={() => (active = 0)}
118
+ {onkeydown}
119
+ />
120
+ </div>
121
+ <div
122
+ id="{id}-listbox"
123
+ role="listbox"
124
+ aria-label={label}
125
+ class="grow overflow-y-auto p-2"
126
+ >
127
+ {#each actions as action, index (action.id)}
128
+ <!-- svelte-ignore a11y_click_events_have_key_events -->
129
+ <div
130
+ id="{id}-{index}"
131
+ role="option"
132
+ tabindex="-1"
133
+ aria-selected={index === current}
134
+ aria-checked={action.selected?.()}
135
+ title={action.description}
136
+ class="flex min-h-9 cursor-pointer items-center gap-3 rounded-sm px-3 text-sm aria-selected:bg-m3-on-surface/10"
137
+ onmousedown={(event) => event.preventDefault()}
138
+ onpointermove={() => (active = index)}
139
+ onclick={() => run(action)}
140
+ >
141
+ <action.icon size={16} class="shrink-0 text-m3-on-surface-variant" />
142
+ <span class="grow">
143
+ {#if action.category}
144
+ <span class="text-m3-on-surface-variant">{action.category}:</span>
145
+ {/if}
146
+ {action.name}
147
+ </span>
148
+ {#if action.selected?.()}
149
+ <Check size={16} class="shrink-0 text-m3-primary" />
150
+ {/if}
151
+ {#if action.shortcut}
152
+ <ShortcutHint shortcut={action.shortcut} />
153
+ {/if}
154
+ </div>
155
+ {/each}
156
+ </div>
157
+ <p
158
+ role="status"
159
+ class="absolute inset-x-0 top-1/2 text-center text-sm text-m3-on-surface-variant empty:hidden"
160
+ >
161
+ {actions.length === 0 ? "No matching commands" : ""}
162
+ </p>
163
+ </Modal>
@@ -0,0 +1,11 @@
1
+ import type { Registry } from "./action.svelte";
2
+ export type CommandPaletteProps = {
3
+ registry: Registry;
4
+ open?: boolean;
5
+ query?: string;
6
+ label?: string;
7
+ placeholder?: string;
8
+ };
9
+ declare const CommandPalette: import("svelte").Component<CommandPaletteProps, {}, "open" | "query">;
10
+ type CommandPalette = ReturnType<typeof CommandPalette>;
11
+ export default CommandPalette;
@@ -1,9 +1,2 @@
1
- export { Divider as CommandDivider, Header as CommandHeader, } from "../common/index.js";
2
1
  export { Action, Registry } from "./action.svelte";
3
- export { default as CommandContent } from "./command-content.svelte";
4
- export { CommandContext, getCommandContext, setCommandContext, } from "./command-context.svelte.js";
5
- export { default as CommandInput, type CommandInputProps, } from "./command-input.svelte";
6
- export { default as CommandItem, type CommandItemProps, } from "./command-item.svelte";
7
- export { default as CommandSearch, type CommandSearchProps, } from "./command-search.svelte";
8
- export { default as Command, type CommandProps } from "./command.svelte";
9
- export { default as Commander, type CommanderProps } from "./commander.svelte";
2
+ export { default as CommandPalette, type CommandPaletteProps, } from "./command-palette.svelte";
@@ -1,9 +1,2 @@
1
- export { Divider as CommandDivider, Header as CommandHeader, } from "../common/index.js";
2
1
  export { Action, Registry } from "./action.svelte";
3
- export { default as CommandContent } from "./command-content.svelte";
4
- export { CommandContext, getCommandContext, setCommandContext, } from "./command-context.svelte.js";
5
- export { default as CommandInput, } from "./command-input.svelte";
6
- export { default as CommandItem, } from "./command-item.svelte";
7
- export { default as CommandSearch, } from "./command-search.svelte";
8
- export { default as Command } from "./command.svelte";
9
- export { default as Commander } from "./commander.svelte";
2
+ export { default as CommandPalette, } from "./command-palette.svelte";
@@ -1,13 +1,18 @@
1
1
  <script module lang="ts">
2
- import type { ClassName } from "../utils.js";
2
+ import { cn, type ClassName, type ElementRef } from "../utils.js";
3
3
  import type { HTMLAttributes } from "svelte/elements";
4
- import { twMerge } from "tailwind-merge";
5
4
 
6
- export type DividerProps = {} & ClassName & HTMLAttributes<HTMLHRElement>;
5
+ export type DividerProps = ElementRef &
6
+ ClassName &
7
+ HTMLAttributes<HTMLHRElement>;
7
8
  </script>
8
9
 
9
10
  <script lang="ts">
10
- let { class: className, ...restProps }: DividerProps = $props();
11
+ let {
12
+ el = $bindable(),
13
+ class: className,
14
+ ...restProps
15
+ }: DividerProps = $props();
11
16
  </script>
12
17
 
13
- <hr class={twMerge("-mx-1 my-1", className)} {...restProps} />
18
+ <hr bind:this={el} class={cn("my-1", className)} {...restProps} />
@@ -1,6 +1,6 @@
1
- import type { ClassName } from "../utils.js";
1
+ import { type ClassName, type ElementRef } from "../utils.js";
2
2
  import type { HTMLAttributes } from "svelte/elements";
3
- export type DividerProps = {} & ClassName & HTMLAttributes<HTMLHRElement>;
4
- declare const Divider: import("svelte").Component<DividerProps, {}, "">;
3
+ export type DividerProps = ElementRef & ClassName & HTMLAttributes<HTMLHRElement>;
4
+ declare const Divider: import("svelte").Component<DividerProps, {}, "el">;
5
5
  type Divider = ReturnType<typeof Divider>;
6
6
  export default Divider;
@@ -1,3 +1 @@
1
1
  export { default as Divider, type DividerProps } from "./divider.svelte";
2
- export { default as Header, type HeaderProps } from "./header.svelte";
3
- export { ItemContext } from "./item-context.svelte";
@@ -1,3 +1 @@
1
1
  export { default as Divider } from "./divider.svelte";
2
- export { default as Header } from "./header.svelte";
3
- export { ItemContext } from "./item-context.svelte";
@@ -0,0 +1,70 @@
1
+ <script lang="ts">
2
+ import { Button } from "../button/index.js";
3
+ import { Input } from "../input/index.js";
4
+ import type { Snippet } from "svelte";
5
+ import Dialog from "./dialog.svelte";
6
+ import { Dialogs, setDialogs } from "./dialogs.svelte.js";
7
+
8
+ let { children }: { children: Snippet } = $props();
9
+
10
+ const id = $props.id();
11
+ const dialogs = setDialogs(new Dialogs());
12
+ const request = $derived(dialogs.current);
13
+ let value = $derived(request?.value ?? "");
14
+ </script>
15
+
16
+ <Dialog
17
+ bind:open={dialogs.open}
18
+ icon={request?.icon}
19
+ title={request?.title}
20
+ aria-describedby="{id}-message"
21
+ onSelect={(selected) => dialogs.settle(selected)}
22
+ >
23
+ {#key request}
24
+ <div id="{id}-message">
25
+ {#if typeof request?.message === "function"}
26
+ {@render request.message()}
27
+ {:else}
28
+ {request?.message}
29
+ {/if}
30
+ </div>
31
+ {#if request?.input}
32
+ <form
33
+ id="{id}-form"
34
+ class="mt-4"
35
+ onsubmit={(event) => {
36
+ event.preventDefault();
37
+ dialogs.settle(value);
38
+ }}
39
+ >
40
+ <Input
41
+ bind:value
42
+ aria-labelledby="{id}-message"
43
+ autofocus
44
+ {...request.input}
45
+ class={["w-full", request.input.class]}
46
+ />
47
+ </form>
48
+ {/if}
49
+ {/key}
50
+
51
+ {#snippet actions(select)}
52
+ {#key request}
53
+ {#each request?.actions ?? [] as action, i (i)}
54
+ <Button
55
+ variant={action.variant}
56
+ color={action.color}
57
+ shape={action.shape}
58
+ autofocus={action.default}
59
+ {...action.submit
60
+ ? { type: "submit", form: `${id}-form` }
61
+ : { onclick: () => select(action.value) }}
62
+ >
63
+ {action.text}
64
+ </Button>
65
+ {/each}
66
+ {/key}
67
+ {/snippet}
68
+ </Dialog>
69
+
70
+ {@render children()}
@@ -0,0 +1,7 @@
1
+ import type { Snippet } from "svelte";
2
+ type $$ComponentProps = {
3
+ children: Snippet;
4
+ };
5
+ declare const DialogProvider: import("svelte").Component<$$ComponentProps, {}, "">;
6
+ type DialogProvider = ReturnType<typeof DialogProvider>;
7
+ export default DialogProvider;
@@ -1,69 +1,67 @@
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 { cn } from "../utils.js";
4
5
  import type { LucideIcon } from "@lucide/svelte";
5
6
  import type { Snippet } from "svelte";
6
- import { twMerge } from "tailwind-merge";
7
7
 
8
8
  export type DialogProps<T> = {
9
- ref?: HTMLDialogElement;
10
- onSelect?: (value: T | undefined) => void;
11
9
  icon?: LucideIcon;
12
10
  title?: string;
13
- children: Snippet;
14
- actions?: Snippet<[{ onSelect: (value: T | undefined) => void }]>;
11
+ onSelect?: (value: T | undefined) => void;
12
+ actions?: Snippet<[select: (value: T | undefined) => void]>;
15
13
  } & ModalProps;
16
14
  </script>
17
15
 
18
16
  <script lang="ts" generics="T">
19
17
  let {
20
- ref = $bindable(),
18
+ el = $bindable(),
21
19
  open = $bindable(),
22
- onSelect,
23
- class: className,
24
- icon: IconComponent,
20
+ icon: Icon,
25
21
  title,
22
+ onSelect,
26
23
  children,
27
24
  actions,
25
+ class: className,
28
26
  ...restProps
29
27
  }: DialogProps<T> = $props();
30
28
 
31
- function handleSelect(value: T | undefined) {
32
- onSelect?.(value);
33
- open = false;
34
- }
29
+ const id = $props.id();
35
30
 
36
- function handleCancel() {
37
- onSelect?.(undefined);
31
+ function select(value: T | undefined) {
32
+ open = false;
33
+ onSelect?.(value);
38
34
  }
39
35
  </script>
40
36
 
41
37
  <Modal
42
- bind:ref
38
+ bind:el
43
39
  bind:open
44
- class={twMerge("w-[min(calc(100%-1em),36em)]", className)}
40
+ class={cn("flex w-[min(calc(100%-1em),36em)] flex-col gap-4", className)}
45
41
  {...mergeComponentProps(
46
42
  Modal,
47
- { role: "dialog", "aria-modal": "true", onCancel: handleCancel },
43
+ {
44
+ "aria-labelledby":
45
+ title && !restProps["aria-label"] ? `${id}-title` : undefined,
46
+ onCancel: () => onSelect?.(undefined),
47
+ },
48
48
  restProps,
49
49
  )}
50
50
  >
51
- <div class={twMerge("flex flex-col gap-4")}>
52
- {#if IconComponent}
53
- <IconComponent class="mx-auto" />
54
- {/if}
55
- {#if title}
56
- <div class={twMerge("text-xl", IconComponent ? "text-center" : "")}>
57
- {title}
58
- </div>
59
- {/if}
60
- <div>
61
- {@render children()}
62
- </div>
63
- {#if actions}
64
- <div class="mt-2 flex place-content-end gap-2">
65
- {@render actions({ onSelect: handleSelect })}
66
- </div>
67
- {/if}
51
+ {#if Icon}
52
+ <Icon class="mx-auto text-m3-secondary" />
53
+ {/if}
54
+ {#if title}
55
+ <h2 id="{id}-title" class={cn("text-2xl", Icon && "text-center")}>
56
+ {title}
57
+ </h2>
58
+ {/if}
59
+ <div class="text-sm text-m3-on-surface-variant">
60
+ {@render children()}
68
61
  </div>
62
+ {#if actions}
63
+ <div class="mt-2 flex flex-wrap justify-end gap-2">
64
+ {@render actions(select)}
65
+ </div>
66
+ {/if}
69
67
  </Modal>
@@ -2,19 +2,15 @@ import { type ModalProps } from "../modal/index.js";
2
2
  import type { LucideIcon } from "@lucide/svelte";
3
3
  import type { Snippet } from "svelte";
4
4
  export type DialogProps<T> = {
5
- ref?: HTMLDialogElement;
6
- onSelect?: (value: T | undefined) => void;
7
5
  icon?: LucideIcon;
8
6
  title?: string;
9
- children: Snippet;
10
- actions?: Snippet<[{
11
- onSelect: (value: T | undefined) => void;
12
- }]>;
7
+ onSelect?: (value: T | undefined) => void;
8
+ actions?: Snippet<[select: (value: T | undefined) => void]>;
13
9
  } & ModalProps;
14
10
  declare function $$render<T>(): {
15
11
  props: DialogProps<T>;
16
12
  exports: {};
17
- bindings: "open" | "ref";
13
+ bindings: "el" | "open";
18
14
  slots: {};
19
15
  events: {};
20
16
  };
@@ -22,7 +18,7 @@ declare class __sveltets_Render<T> {
22
18
  props(): ReturnType<typeof $$render<T>>['props'];
23
19
  events(): ReturnType<typeof $$render<T>>['events'];
24
20
  slots(): ReturnType<typeof $$render<T>>['slots'];
25
- bindings(): "open" | "ref";
21
+ bindings(): "el" | "open";
26
22
  exports(): {};
27
23
  }
28
24
  interface $$IsomorphicComponent {
@@ -0,0 +1,49 @@
1
+ import type { Variants } from "../base.js";
2
+ import type { InputProps } from "../input/index.js";
3
+ import type { LucideIcon } from "@lucide/svelte";
4
+ import { type Snippet } from "svelte";
5
+ export type DialogAction<T> = {
6
+ text: string;
7
+ value: T;
8
+ default?: boolean;
9
+ } & Variants;
10
+ type DialogContent = {
11
+ icon?: LucideIcon;
12
+ title?: string;
13
+ message: Snippet | string;
14
+ };
15
+ export type AlertOptions = DialogContent & {
16
+ acceptText?: string;
17
+ };
18
+ export type ConfirmOptions = DialogContent & {
19
+ cancelText?: string;
20
+ acceptText?: string;
21
+ };
22
+ export type PromptOptions = DialogContent & {
23
+ input?: InputProps;
24
+ cancelText?: string;
25
+ acceptText?: string;
26
+ };
27
+ export type ShowOptions<T> = DialogContent & {
28
+ actions: DialogAction<T>[];
29
+ };
30
+ export type DialogRequest = DialogContent & {
31
+ actions: (DialogAction<unknown> & {
32
+ submit?: boolean;
33
+ })[];
34
+ input?: Omit<InputProps, "value">;
35
+ value?: string;
36
+ resolve: (value: unknown) => void;
37
+ };
38
+ export declare class Dialogs {
39
+ #private;
40
+ current: DialogRequest | undefined;
41
+ open: boolean;
42
+ show<T>(options: ShowOptions<T>): Promise<T | undefined>;
43
+ alert({ acceptText, ...content }: AlertOptions): Promise<void>;
44
+ confirm({ cancelText, acceptText, ...content }: ConfirmOptions): Promise<boolean>;
45
+ prompt({ input: { value, ...input }, cancelText, acceptText, ...content }: PromptOptions): Promise<string | undefined>;
46
+ settle(value: unknown): void;
47
+ }
48
+ export declare const getDialogs: () => Dialogs, setDialogs: (context: Dialogs) => Dialogs;
49
+ export {};
@@ -0,0 +1,73 @@
1
+ import { createContext } from "svelte";
2
+ export class Dialogs {
3
+ current = $state.raw();
4
+ open = $state(false);
5
+ #active;
6
+ #queue = [];
7
+ show(options) {
8
+ return this.#request(options);
9
+ }
10
+ async alert({ acceptText, ...content }) {
11
+ await this.#request({
12
+ ...content,
13
+ actions: [
14
+ {
15
+ text: acceptText ?? "OK",
16
+ value: undefined,
17
+ variant: "filled",
18
+ default: true,
19
+ },
20
+ ],
21
+ });
22
+ }
23
+ async confirm({ cancelText, acceptText, ...content }) {
24
+ const accepted = await this.#request({
25
+ ...content,
26
+ actions: [
27
+ { text: cancelText ?? "Cancel", value: false, variant: "plain" },
28
+ {
29
+ text: acceptText ?? "OK",
30
+ value: true,
31
+ variant: "filled",
32
+ default: true,
33
+ },
34
+ ],
35
+ });
36
+ return accepted === true;
37
+ }
38
+ async prompt({ input: { value, ...input } = {}, cancelText, acceptText, ...content }) {
39
+ const text = await this.#request({
40
+ ...content,
41
+ input,
42
+ value: value == null ? "" : String(value),
43
+ actions: [
44
+ { text: cancelText ?? "Cancel", value: undefined, variant: "plain" },
45
+ {
46
+ text: acceptText ?? "OK",
47
+ value: undefined,
48
+ variant: "filled",
49
+ submit: true,
50
+ },
51
+ ],
52
+ });
53
+ return typeof text === "string" ? text : undefined;
54
+ }
55
+ settle(value) {
56
+ this.#active?.resolve(value);
57
+ this.#next();
58
+ }
59
+ #request(request) {
60
+ return new Promise((resolve) => {
61
+ this.#queue.push({ ...request, resolve });
62
+ if (!this.#active)
63
+ this.#next();
64
+ });
65
+ }
66
+ #next() {
67
+ this.#active = this.#queue.shift();
68
+ if (this.#active)
69
+ this.current = this.#active;
70
+ this.open = this.#active !== undefined;
71
+ }
72
+ }
73
+ export const [getDialogs, setDialogs] = createContext();
@@ -1,4 +1,3 @@
1
- export { default as DialogButton, type DialogButtonProps, } from "./dialog-button.svelte";
2
1
  export { default as Dialog, type DialogProps } from "./dialog.svelte";
3
- export { DialoguerContext, getDialoguerContext, setDialoguerContext, type DialoguerButtonProps, } from "./dialoguer-context.svelte";
4
- export { default as Dialoguer } from "./dialoguer.svelte";
2
+ export { default as DialogProvider } from "./dialog-provider.svelte";
3
+ export { Dialogs, getDialogs, type AlertOptions, type ConfirmOptions, type DialogAction, type PromptOptions, type ShowOptions, } from "./dialogs.svelte";
@@ -1,4 +1,3 @@
1
- export { default as DialogButton, } from "./dialog-button.svelte";
2
1
  export { default as Dialog } from "./dialog.svelte";
3
- export { DialoguerContext, getDialoguerContext, setDialoguerContext, } from "./dialoguer-context.svelte";
4
- export { default as Dialoguer } from "./dialoguer.svelte";
2
+ export { default as DialogProvider } from "./dialog-provider.svelte";
3
+ export { Dialogs, getDialogs, } from "./dialogs.svelte";
@@ -1,28 +1,48 @@
1
1
  <script lang="ts">
2
2
  import { Button, type ButtonProps } from "../button/index.js";
3
- import type { ElementRef } from "../utils.js";
4
- import { twMerge } from "tailwind-merge";
3
+ import { cn } from "../utils.js";
4
+ import type { Attachment } from "svelte/attachments";
5
5
 
6
- export type FabProps = {} & ElementRef & ButtonProps;
6
+ export type FabProps = ButtonProps & {
7
+ clear?: boolean;
8
+ };
7
9
 
8
10
  let {
9
11
  el = $bindable(),
10
12
  class: className,
11
- icon,
12
- size = 20,
13
+ style,
14
+ size = "lg",
15
+ shape = "lg",
13
16
  variant = "elevated",
14
- shape = "circle",
17
+ clear = false,
15
18
  ...restProps
16
19
  }: FabProps = $props();
20
+
21
+ let width = $state(0);
22
+ let height = $state(0);
23
+
24
+ const measure: Attachment<HTMLElement> = (node) => {
25
+ const observer = new ResizeObserver(() => {
26
+ width = node.offsetWidth;
27
+ height = node.offsetHeight;
28
+ });
29
+ observer.observe(node, { box: "border-box" });
30
+ return () => observer.disconnect();
31
+ };
17
32
  </script>
18
33
 
19
- <div class="grow"></div>
20
34
  <Button
21
35
  bind:el
22
- class={twMerge("sticky bottom-0 ml-auto p-4 backdrop-blur-sm", className)}
36
+ class={cn(
37
+ "sticky top-[calc(100%-var(--fab-height))] bottom-0 left-[calc(100%-var(--fab-width))] flex transition",
38
+ restProps.children && "w-fit",
39
+ !clear && "mt-[calc(-1*var(--fab-height))]",
40
+ className,
41
+ )}
42
+ style="--fab-width: {width}px; --fab-height: {height}px; {style ?? ''}"
23
43
  {variant}
24
- {shape}
25
- {icon}
26
44
  {size}
45
+ {shape}
27
46
  {...restProps}
47
+ {@attach measure}
28
48
  />
@@ -1,6 +1,7 @@
1
1
  import { type ButtonProps } from "../button/index.js";
2
- import type { ElementRef } from "../utils.js";
3
- export type FabProps = {} & ElementRef & ButtonProps;
2
+ export type FabProps = ButtonProps & {
3
+ clear?: boolean;
4
+ };
4
5
  declare const Fab: import("svelte").Component<FabProps, {}, "el">;
5
6
  type Fab = ReturnType<typeof Fab>;
6
7
  export default Fab;