@spaethtech/svelte-ui 0.21.5-dev.147.eb2f000 → 0.21.5-dev.150.7bf55da

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.
@@ -3,7 +3,7 @@
3
3
  import type { HTMLInputAttributes } from "svelte/elements";
4
4
  import type { Size } from "../types/sizes.js";
5
5
  import { responsiveClasses, type Responsive } from "../types/responsive.js";
6
- import type { Variant } from "../types/variants.js";
6
+ import { variantToken, type Variant } from "../types/variants.js";
7
7
  import FieldChrome, { nextFieldId } from "./FieldChrome.svelte";
8
8
 
9
9
  // Omit the native `size` attribute (character width, a number) — we repurpose `size` as the
@@ -191,22 +191,50 @@
191
191
  paddingClasses = "px-2";
192
192
  }
193
193
 
194
- // Border colour comes from the variant map (the shared tint scheme — token @ --ui-tint-border at
195
- // rest, @ --ui-tint-border-hover on hover/focus — same as Card/DataTable/TextArea, so every bordered
196
- // surface stays uniform under any theme). `borderless` overrides it with transparent (the field's
197
- // own background) — the 1px box stays, so the field never jumps, and the focus outline still fires.
198
- const frameStyles = borderless ? "[border-color:transparent]" : borderVariantClass[variant];
194
+ // Frame + fill follow the field's "liveness", ordered by the shared border-tint ladder — all from
195
+ // the variant's OWN token via `--field-accent` (set on the wrapper below; neutral/ghost → the
196
+ // neutral token), so there's NO `secondary` special-case: editable 50% > read-only 35% > disabled
197
+ // 15% (quiet → live). Read-only and disabled take the muted neutral fill; editable fills with the
198
+ // page background. `borderless` (editable only) drops the visible frame while keeping the 1px box.
199
+ const editableFrame = borderless ? "[border-color:transparent]" : borderVariantClass[variant];
199
200
  // Field background follows the variant axis: `ghost` is transparent (chromeless); every other
200
201
  // variant fills with --ui-color-background so the field reads as a field on a non-white page.
201
- const fieldBg =
202
+ const editableBg =
202
203
  variant === "ghost" ? "bg-transparent" : "[background-color:var(--ui-color-background)]";
204
+ const mutedFill =
205
+ "[background-color:color-mix(in_srgb,var(--ui-color-neutral)_var(--ui-tint-fill-muted),transparent)]";
206
+
207
+ let fillStyles: string;
208
+ let frameStyles: string;
209
+ let stateStyles = ""; // cursor + (for read-only) the inset focus ring
210
+ if (disabled) {
211
+ // Quietest frame; muted fill; not focusable (no ring). No more secondary-blue border.
212
+ fillStyles = mutedFill;
213
+ frameStyles =
214
+ "[border-color:color-mix(in_srgb,var(--field-accent)_var(--ui-tint-border-disabled),transparent)]";
215
+ stateStyles = "cursor-not-allowed";
216
+ } else if (readonly) {
217
+ // A distinct read-only look: quieter-than-editable frame (35% → 80% on hover/focus), muted fill,
218
+ // full-strength text, and the focus ring kept (keyboard users land here). The ring is drawn INSIDE
219
+ // the frame (outline-offset -2px) so a scrolling Card/Dialog can't clip it.
220
+ fillStyles = mutedFill;
221
+ frameStyles =
222
+ "[border-color:color-mix(in_srgb,var(--field-accent)_var(--ui-tint-border-readonly),transparent)] hover:[border-color:color-mix(in_srgb,var(--field-accent)_var(--ui-tint-border-hover),transparent)] focus-within:[border-color:color-mix(in_srgb,var(--field-accent)_var(--ui-tint-border-hover),transparent)]";
223
+ stateStyles =
224
+ "focus-within:[outline:2px_solid_color-mix(in_srgb,currentColor_70%,transparent)] focus-within:[outline-offset:-2px]";
225
+ } else {
226
+ fillStyles = editableBg;
227
+ frameStyles = editableFrame;
228
+ stateStyles =
229
+ "focus-within:[outline:2px_solid_color-mix(in_srgb,currentColor_70%,transparent)] focus-within:[outline-offset:-2px]";
230
+ }
231
+
203
232
  const themeStyles = [
204
- fieldBg,
233
+ fillStyles,
205
234
  "border", // 1px — matches --ui-border (List/TextArea); uniform across the library
206
235
  paddingClasses,
207
236
  frameStyles,
208
- "focus-within:[outline:2px_solid_color-mix(in_srgb,currentColor_70%,transparent)]",
209
- "focus-within:[outline-offset:0px]",
237
+ stateStyles,
210
238
  ].join(" ");
211
239
 
212
240
  // Error state (shared): chrome `error` set OR a failing `validate` (once touched).
@@ -216,15 +244,7 @@
216
244
  "[border-color:var(--ui-color-error)] focus-within:[ring-color:var(--ui-color-error)]";
217
245
  }
218
246
 
219
- // Disabled state — borders are uniformly 1px now, so no padding compensation is needed.
220
- // (readonly renders like a normal field: same 1px frame + hover/focus glow, e.g. Select's trigger.)
221
- let disabledStyles = "";
222
- if (disabled) {
223
- disabledStyles =
224
- "![background-color:color-mix(in_srgb,var(--ui-color-text)_5%,transparent)] [border-color:color-mix(in_srgb,var(--ui-color-secondary)_var(--ui-tint-border),transparent)] cursor-not-allowed";
225
- }
226
-
227
- return `${base} ${themeStyles} ${validationStyles} ${disabledStyles}`.trim();
247
+ return `${base} ${themeStyles} ${validationStyles}`.trim();
228
248
  });
229
249
 
230
250
  let inputClasses = $derived.by(() => {
@@ -240,6 +260,10 @@
240
260
  "disabled:bg-transparent",
241
261
  "disabled:[color:color-mix(in_srgb,var(--ui-color-text)_40%,transparent)]",
242
262
  "disabled:cursor-not-allowed",
263
+ // Read-only keeps full-strength text but reads as non-editable: a text cursor (it's selectable)
264
+ // and no blinking caret (nothing to type).
265
+ "read-only:cursor-text",
266
+ "read-only:[caret-color:transparent]",
243
267
  ].join(" ");
244
268
 
245
269
  return `${base} ${themeStyles} ${inputClass}`.trim();
@@ -323,7 +347,11 @@
323
347
  class={containerClass}
324
348
  >
325
349
  {#snippet control({ describedBy })}
326
- <div bind:this={fieldElement} class="relative {wrapperClasses}" style="user-select: none;">
350
+ <div
351
+ bind:this={fieldElement}
352
+ class="relative {wrapperClasses}"
353
+ style="user-select: none; --field-accent: var({variantToken[variant]});"
354
+ >
327
355
  {#if icon && iconPosition === "left"}
328
356
  {#if iconClickable}
329
357
  <div
@@ -2,7 +2,7 @@ import type { Snippet } from "svelte";
2
2
  import type { HTMLInputAttributes } from "svelte/elements";
3
3
  import type { Size } from "../types/sizes.js";
4
4
  import { type Responsive } from "../types/responsive.js";
5
- import type { Variant } from "../types/variants.js";
5
+ import { type Variant } from "../types/variants.js";
6
6
  interface Props extends Omit<HTMLInputAttributes, "size"> {
7
7
  /** Accepts number too so remote-form field spreads (`{...field.as(...)}`) type-check. */
8
8
  value?: string | number;
@@ -0,0 +1,104 @@
1
+ <script lang="ts">
2
+ /**
3
+ * One toast row: a filled Alert plus (optionally) an action button and a close button. Owns its own
4
+ * auto-dismiss countdown so it can PAUSE while the pointer is over it or keyboard focus is inside it
5
+ * (a `holds` counter handles pointer + focus overlapping) — that keeps the `action` reachable by
6
+ * mouse AND keyboard. `timeout: 0` is sticky (no countdown). Controls are our <Button>, never raw
7
+ * <button>, per the composition standard.
8
+ */
9
+ import { onMount } from "svelte";
10
+ import Alert from "../Alert.svelte";
11
+ import Button from "../Button.svelte";
12
+ import IconClose from "~icons/mdi/close";
13
+ import { uiI18n } from "../../i18n.js";
14
+ import { dismissToast, type ToastItem } from "./toast.svelte.js";
15
+ import type { Variant } from "../../types/variants.js";
16
+ import type { Responsive } from "../../types/responsive.js";
17
+ import type { Size } from "../../types/sizes.js";
18
+
19
+ const i18n = uiI18n();
20
+
21
+ let {
22
+ item,
23
+ fallbackVariant,
24
+ fallbackSize,
25
+ }: {
26
+ item: ToastItem;
27
+ /** Toaster-level defaults for toasts that didn't set their own. */
28
+ fallbackVariant?: Variant;
29
+ fallbackSize?: Responsive<Size>;
30
+ } = $props();
31
+
32
+ // Auto-dismiss countdown with pause/resume. `remaining` ms is decremented by whatever has elapsed
33
+ // each time we pause; while `holds > 0` (hovered and/or focused) no timer runs.
34
+ let remaining = item.timeout;
35
+ let startedAt = 0;
36
+ let handle: ReturnType<typeof setTimeout> | undefined;
37
+ let holds = 0;
38
+
39
+ function clear() {
40
+ if (handle !== undefined) {
41
+ clearTimeout(handle);
42
+ handle = undefined;
43
+ }
44
+ }
45
+ function run() {
46
+ clear();
47
+ if (item.timeout <= 0 || typeof window === "undefined") return;
48
+ startedAt = Date.now();
49
+ handle = window.setTimeout(() => dismissToast(item.id), remaining);
50
+ }
51
+ function hold() {
52
+ if (item.timeout <= 0) return;
53
+ if (handle !== undefined) remaining -= Date.now() - startedAt; // bank elapsed time once
54
+ clear();
55
+ holds++;
56
+ }
57
+ function release() {
58
+ if (item.timeout <= 0) return;
59
+ holds = Math.max(0, holds - 1);
60
+ if (holds > 0) return;
61
+ if (remaining > 0) run();
62
+ else dismissToast(item.id);
63
+ }
64
+
65
+ onMount(() => {
66
+ run();
67
+ return clear;
68
+ });
69
+
70
+ function runAction() {
71
+ // Run the handler, then dismiss — unless the action opted out with `dismiss: false` (keep open).
72
+ item.action?.onclick();
73
+ if (item.action?.dismiss !== false) dismissToast(item.id);
74
+ }
75
+ </script>
76
+
77
+ <!-- svelte-ignore a11y_no_noninteractive_element_interactions -->
78
+ <div
79
+ class="pointer-events-auto flex min-w-56 items-start gap-1 rounded shadow-lg [background-color:var(--ui-color-background)]"
80
+ role="status"
81
+ onpointerenter={hold}
82
+ onpointerleave={release}
83
+ onfocusin={hold}
84
+ onfocusout={release}
85
+ >
86
+ <Alert variant={item.variant ?? fallbackVariant} size={item.size ?? fallbackSize} filled class="grow"
87
+ >{item.message}</Alert
88
+ >
89
+ {#if item.action}
90
+ <Button variant="ghost" size="sm" class="shrink-0 self-center" onclick={runAction}>
91
+ {item.action.label}
92
+ </Button>
93
+ {/if}
94
+ <Button
95
+ variant="ghost"
96
+ size="sm"
97
+ class="shrink-0 self-center"
98
+ aria-label={i18n.messages.dismiss}
99
+ title={i18n.messages.dismiss}
100
+ onclick={() => dismissToast(item.id)}
101
+ >
102
+ {#snippet icon()}<IconClose />{/snippet}
103
+ </Button>
104
+ </div>
@@ -0,0 +1,13 @@
1
+ import { type ToastItem } from "./toast.svelte.js";
2
+ import type { Variant } from "../../types/variants.js";
3
+ import type { Responsive } from "../../types/responsive.js";
4
+ import type { Size } from "../../types/sizes.js";
5
+ type $$ComponentProps = {
6
+ item: ToastItem;
7
+ /** Toaster-level defaults for toasts that didn't set their own. */
8
+ fallbackVariant?: Variant;
9
+ fallbackSize?: Responsive<Size>;
10
+ };
11
+ declare const ToastRow: import("svelte").Component<$$ComponentProps, {}, "">;
12
+ type ToastRow = ReturnType<typeof ToastRow>;
13
+ export default ToastRow;
@@ -1,13 +1,11 @@
1
1
  <script lang="ts">
2
- import { uiI18n } from "../../i18n.js";
3
- const i18n = uiI18n();
4
2
  /**
5
3
  * Renders the toast store's items in a fixed, top-layer stack. Mount ONCE at the app root; push with
6
- * `toast.*` from anywhere. Each toast is an Alert (filled) honouring its variant + size.
4
+ * `toast.*` from anywhere. Each toast is a <ToastRow> (filled Alert + optional action + close),
5
+ * which owns its own pausable auto-dismiss countdown.
7
6
  */
8
- import Alert from "../Alert.svelte";
9
- import IconClose from "~icons/mdi/close";
10
- import { getToasts, dismissToast } from "./toast.svelte.js";
7
+ import ToastRow from "./ToastRow.svelte";
8
+ import { getToasts } from "./toast.svelte.js";
11
9
  import type { Size } from "../../types/sizes.js";
12
10
  import type { Responsive } from "../../types/responsive.js";
13
11
  import type { Variant } from "../../types/variants.js";
@@ -35,19 +33,7 @@
35
33
  {#if items.length}
36
34
  <div class="pointer-events-none fixed z-[100] flex max-w-[90vw] flex-col gap-2 {posClass}">
37
35
  {#each items as t (t.id)}
38
- <div
39
- class="pointer-events-auto flex min-w-56 items-start gap-2 rounded shadow-lg [background-color:var(--ui-color-background)]"
40
- >
41
- <Alert variant={t.variant ?? variant} size={t.size ?? size} filled class="grow"
42
- >{t.message}</Alert
43
- >
44
- <button
45
- type="button"
46
- aria-label={i18n.messages.dismiss}
47
- class="shrink-0 self-center pr-2 opacity-60 hover:opacity-100"
48
- onclick={() => dismissToast(t.id)}><IconClose class="size-4" /></button
49
- >
50
- </div>
36
+ <ToastRow item={t} fallbackVariant={variant} fallbackSize={size} />
51
37
  {/each}
52
38
  </div>
53
39
  {/if}
@@ -5,16 +5,31 @@ import type { Size } from "../../types/sizes.js";
5
5
  * shared Variant (status subset) + Size axes. Auto-dismisses after `timeout` ms (0 = sticky).
6
6
  */
7
7
  export type ToastVariant = "danger" | "success" | "warning" | "info" | "primary";
8
+ /**
9
+ * An optional action rendered as a small button inside the toast (e.g. "Undo"). Clicking it runs
10
+ * `onclick`, then the toast is dismissed. Set `dismiss: false` to KEEP the toast open instead (e.g.
11
+ * to show progress) and close it later via the id returned from `toast.*` + `dismissToast`.
12
+ */
13
+ export type ToastAction = {
14
+ /** Button label, e.g. "Undo". */
15
+ label: string;
16
+ /** Click handler (its return value is ignored). */
17
+ onclick: () => void;
18
+ /** Dismiss the toast after `onclick` runs. Default `true`; `false` keeps it open. */
19
+ dismiss?: boolean;
20
+ };
8
21
  export type ToastItem = {
9
22
  id: number;
10
23
  variant: ToastVariant;
11
24
  message: string;
12
25
  size: Size;
13
26
  timeout: number;
27
+ action?: ToastAction;
14
28
  };
15
29
  export type ToastOptions = {
16
30
  timeout?: number;
17
31
  size?: Size;
32
+ action?: ToastAction;
18
33
  };
19
34
  /** The live toast list (read in <Toaster>; mutations are reactive). */
20
35
  export declare function getToasts(): ToastItem[];
@@ -9,12 +9,13 @@ export function dismissToast(id) {
9
9
  if (i >= 0)
10
10
  items.splice(i, 1);
11
11
  }
12
+ // NOTE: auto-dismiss timing lives in <Toaster> (per toast row), NOT here — the row can then PAUSE the
13
+ // countdown while the pointer is over it or keyboard focus is inside it, so an `action` button stays
14
+ // reachable. `push` only records `timeout` (0 = sticky); the row reads it and owns the timer.
12
15
  function push(variant, message, opts = {}) {
13
16
  const id = ++seq;
14
17
  const timeout = opts.timeout ?? 4000;
15
- items.push({ id, variant, message, size: opts.size ?? "md", timeout });
16
- if (timeout > 0 && typeof window !== "undefined")
17
- window.setTimeout(() => dismissToast(id), timeout);
18
+ items.push({ id, variant, message, size: opts.size ?? "md", timeout, action: opts.action });
18
19
  return id;
19
20
  }
20
21
  export const toast = {
package/dist/index.d.ts CHANGED
@@ -15,7 +15,7 @@ export { Stat } from "./components/Stat/index.js";
15
15
  export { Timeline } from "./components/Timeline/index.js";
16
16
  export type { TimelineItem } from "./components/Timeline/index.js";
17
17
  export { default as Toaster } from "./components/Toast/Toaster.svelte";
18
- export { toast, getToasts, dismissToast, type ToastVariant, type ToastItem, } from "./components/Toast/toast.svelte.js";
18
+ export { toast, getToasts, dismissToast, type ToastVariant, type ToastItem, type ToastOptions, type ToastAction, } from "./components/Toast/toast.svelte.js";
19
19
  export { default as Dialog } from "./components/Dialog.svelte";
20
20
  export { Drawer } from "./components/Drawer/index.js";
21
21
  export { default as ConfirmDialog } from "./components/ConfirmDialog.svelte";
package/dist/theme.css CHANGED
@@ -124,7 +124,10 @@
124
124
  * TextArea, an outline Button) moves to on hover/focus. Theme-independent constants (no colour → no
125
125
  * per-theme scope needed) — but a theme MAY override these to tune the whole tint language. */
126
126
  --ui-tint-soft: 12%;
127
+ --ui-tint-fill-muted: 5%; /* disabled / read-only field fill — a faint neutral wash (quieter than soft) */
128
+ --ui-tint-border-disabled: 15%; /* disabled field frame — the QUIETEST frame (a disabled control recedes) */
127
129
  --ui-tint-divider: 30%; /* soft internal dividers — deliberately lighter than the 50% frame/field border */
130
+ --ui-tint-border-readonly: 35%; /* read-only field frame — quieter than editable (50%), louder than a divider */
128
131
  --ui-tint-border: 50%;
129
132
  --ui-tint-border-hover: 80%;
130
133
  --ui-tint-strong: 80%;
package/dist/utils.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- export { toast, getToasts, dismissToast, type ToastVariant, type ToastItem, } from "./components/Toast/toast.svelte.js";
1
+ export { toast, getToasts, dismissToast, type ToastVariant, type ToastItem, type ToastOptions, type ToastAction, } from "./components/Toast/toast.svelte.js";
2
2
  export { anchored, computePlacement, resolveBoundary } from "./positioning/anchored.js";
3
3
  export type { Side, Align, Boundary, PlaceOptions, Placement, AnchoredParams, } from "./positioning/anchored.js";
4
4
  export { tooltip } from "./positioning/tooltip.js";
package/docs/themes.md CHANGED
@@ -65,6 +65,27 @@ theme-independent** (identical in light and dark) — only the accent color flip
65
65
  `color-mix(in srgb, var(--ui-color-neutral) var(--ui-tint-border), transparent)` for a frame edge,
66
66
  `--ui-tint-border-hover` for its hover.)
67
67
 
68
+ ### Field states — the border-tint ladder
69
+
70
+ A field's frame reflects how "live" it is, all from the **variant's own token** (so a `neutral` field is
71
+ monochrome, a `primary` field tints blue — there is **no `secondary` special-case** for disabled):
72
+
73
+ | state | border tint | fill |
74
+ |---|---|---|
75
+ | editable | `--ui-tint-border` (50%) → `--ui-tint-border-hover` (80%) on hover/focus | page background |
76
+ | **read-only** | `--ui-tint-border-readonly` (**35%**) → 80% on hover/focus | `--ui-tint-fill-muted` |
77
+ | **disabled** | `--ui-tint-border-disabled` (**15%**) | `--ui-tint-fill-muted` |
78
+
79
+ - `--ui-tint-border-readonly` — `35%` — read-only frame (quieter than editable, louder than a divider).
80
+ - `--ui-tint-border-disabled` — `15%` — disabled frame, the **quietest** (a disabled control recedes).
81
+ - `--ui-tint-fill-muted` — `5%` — the faint neutral wash behind a read-only or disabled field
82
+ (`color-mix(in srgb, var(--ui-color-neutral) var(--ui-tint-fill-muted), transparent)`).
83
+
84
+ Read-only keeps **full-strength text**, a text cursor, and the focus ring (it's selectable/focusable),
85
+ but hides the caret; disabled dims its text to 40%. The focus ring is drawn **inside** the frame
86
+ (`outline-offset: -2px`) so a scrolling `Card`/`Dialog` can't clip it. Overriding these percentages
87
+ per theme retunes read-only/disabled everywhere at once.
88
+
68
89
  ## Sizing — the `size` axis (`sm` / `md` / `lg`)
69
90
 
70
91
  ### Control heights
package/docs/usage.md CHANGED
@@ -1169,6 +1169,49 @@ reads `GridState.group` (`{ key, dir }`) and does `ORDER BY <group>, <sort>`.
1169
1169
  client-side counterpart to a remote `query()`; `matchesRow(row, ast)` is the underlying AST evaluator if
1170
1170
  you need to filter an array yourself. See the live demo for the full DataTable + Query walkthrough.
1171
1171
 
1172
+ ### Toasts
1173
+
1174
+ Mount a single `<Toaster />` once at the app root, then push from anywhere with `toast.*`. The push
1175
+ functions (`toast`, `dismissToast`, `getToasts`) are component-free values, so import them from the
1176
+ dedicated **`@spaethtech/svelte-ui/toast`** subpath (or `/utils`, or the root barrel) to stay barrel-free.
1177
+
1178
+ ```svelte
1179
+ <script>
1180
+ import { Toaster } from "@spaethtech/svelte-ui/toaster"; // mount once (e.g. +layout.svelte)
1181
+ import { toast } from "@spaethtech/svelte-ui/toast"; // push from anywhere
1182
+ </script>
1183
+
1184
+ <Toaster position="bottom-right" />
1185
+
1186
+ <!-- status variants; each returns an id you can toast.dismiss(id) -->
1187
+ toast.success("Saved");
1188
+ toast.info("Heads up", { timeout: 0 }); // 0 = sticky (dismiss with the × button)
1189
+ toast.warning("Almost full", { size: "lg" });
1190
+ ```
1191
+
1192
+ **Action button (e.g. Undo).** Pass an `action`; it renders a small button that runs `onclick` and then
1193
+ dismisses the toast. The auto-dismiss countdown pauses while the pointer is over the toast or keyboard
1194
+ focus is inside it, so the action stays reachable. Set `dismiss: false` to keep the toast open instead
1195
+ (close it later by id).
1196
+
1197
+ ```svelte
1198
+ let archived = $state(false);
1199
+
1200
+ function archive() {
1201
+ archived = true;
1202
+ toast.info("Archived “Breaking Bad”", {
1203
+ action: { label: "Undo", onclick: () => (archived = false) },
1204
+ });
1205
+ }
1206
+
1207
+ // Keep-open variant (show progress, then dismiss yourself):
1208
+ const id = toast.info("Uploading…", {
1209
+ timeout: 0,
1210
+ action: { label: "Cancel", onclick: cancelUpload, dismiss: false },
1211
+ });
1212
+ // … later: toast.dismiss(id);
1213
+ ```
1214
+
1172
1215
  ## Theme Integration
1173
1216
 
1174
1217
  ### Using CSS Variables
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@spaethtech/svelte-ui",
3
- "version": "0.21.5-dev.147.eb2f000",
3
+ "version": "0.21.5-dev.150.7bf55da",
4
4
  "repository": {
5
5
  "type": "git",
6
6
  "url": "git+https://github.com/spaethtech/svelte-ui.git"
@@ -109,6 +109,11 @@
109
109
  "types": "./dist/components/Toast/Toaster.svelte.d.ts",
110
110
  "svelte": "./dist/components/Toast/Toaster.svelte"
111
111
  },
112
+ "./toast": {
113
+ "types": "./dist/components/Toast/toast.svelte.d.ts",
114
+ "svelte": "./dist/components/Toast/toast.svelte.js",
115
+ "default": "./dist/components/Toast/toast.svelte.js"
116
+ },
112
117
  "./dialog": {
113
118
  "types": "./dist/components/Dialog.svelte.d.ts",
114
119
  "svelte": "./dist/components/Dialog.svelte"