@spaethtech/svelte-ui 0.21.1-dev.120.d0d8cfa → 0.21.1-dev.121.3e3f7cf

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/MIGRATION.md CHANGED
@@ -58,3 +58,32 @@ grep -rl 'Select' src | xargs sed -i \
58
58
 
59
59
  Verify: the field lines up with its siblings, submits in your form with JS disabled, and shows the
60
60
  right option on first paint (view source — the `selected` attribute is server-rendered).
61
+
62
+ ### `Disclosure2` / `Accordion2` vs `Disclosure` / `Accordion`
63
+
64
+ `Disclosure2` is a real `<details>/<summary>`; `Accordion2` groups them with a shared native
65
+ `<details name>`. The **header is pixel-identical** to `Disclosure`'s `Button` header. Differences:
66
+
67
+ | `Disclosure`/`Accordion` prop | `*2` behaviour |
68
+ | --- | --- |
69
+ | `title`, `header`, `icon`, `size`, `variant`, `disabled`, `id`, `class`, `children` | ✅ Honoured (identical look). `disabled` makes the summary non-interactive + `aria-disabled` (a native `<details>` has no real disabled state). |
70
+ | `open` (Disclosure) | ✅ Sets the initial `open` attribute (SSR-correct) and is kept in sync on `toggle`. With JS off, the browser owns subsequent toggles. |
71
+ | `value` (Disclosure, Accordion) | ✅ Used to compute which panel starts open inside `Accordion2`. In `Accordion2` the group `value` is **initial state only** — with JS off the binding doesn't track user toggles (the browser does, via `name`). |
72
+ | `multiple` (Accordion) | ✅ `false` → shared `<details name>` (browser single-open); `true` → no name (independent). |
73
+ | panel height **animation** (`grid-template-rows: 0fr→1fr`) | ⚠️ Open/close is **instant** — a native `<details>` doesn't height-animate (pre-`::details-content`). The chevron still rotates. Matches reduced-motion behaviour. |
74
+ | `collapsible={false}` (Accordion single mode) | ❌ Best-effort — "never zero open" can't be enforced without JS. |
75
+ | panel stays **mounted when closed** (`inert`) | ⚠️ A closed `<details>` hides its content natively; it is not kept in the a11y tree the same way. Don't rely on closed-panel DOM state. |
76
+
77
+ `Disclosure2` adds one prop over `Disclosure`: **`name`** (the native `<details name>` — set it
78
+ yourself for a no-JS group without `Accordion2`, or let `Accordion2` provide it).
79
+
80
+ **When NOT to swap:** if you depend on the height animation or on reading open state back through the
81
+ binding without JS, stay on `Disclosure`/`Accordion`.
82
+
83
+ **Codemod (per app, when adopting):**
84
+
85
+ ```bash
86
+ grep -rl 'Disclosure\|Accordion' src | xargs sed -i \
87
+ -e 's/\b\(Disclosure\|Accordion\)\b/\12/g'
88
+ # Review: this also rewrites import specifiers and any prose; check each hit.
89
+ ```
@@ -0,0 +1,76 @@
1
+ <!--
2
+ /**
3
+ * Accordion2 — a native-first, no-JS sibling of `Accordion` (transitional `*2`, see MIGRATION.md).
4
+ * It groups `Disclosure2` (`<details>`) children. In single-open mode (`multiple={false}`, default)
5
+ * it hands every child the SAME `<details name>`, so the BROWSER enforces "opening one closes the
6
+ * rest" — with no JavaScript, no context callbacks, correct in SSR. `multiple` drops the shared name
7
+ * so each panel toggles independently. `size`/`variant`/`disabled` propagate to children; the group's
8
+ * `value` sets which panel(s) start open.
9
+ *
10
+ * Differences from `Accordion` (see MIGRATION.md): `value` is INITIAL state only — with JS off the
11
+ * browser owns subsequent open/close, so the binding doesn't track user toggles. `collapsible={false}`
12
+ * (never allow zero open) can't be enforced without JS and is treated as best-effort.
13
+ */
14
+ -->
15
+ <script lang="ts">
16
+ import type { Snippet } from "svelte";
17
+ import type { Size } from "../types/sizes.js";
18
+ import type { Variant } from "../types/variants.js";
19
+ import type { Responsive } from "../types/responsive.js";
20
+ import { nextFieldId } from "./FieldChrome.svelte";
21
+ import { setDisclosure2Group } from "./disclosure2.js";
22
+
23
+ let {
24
+ multiple = false,
25
+ value = $bindable(),
26
+ collapsible: _collapsible = true,
27
+ size = "md",
28
+ variant,
29
+ disabled = false,
30
+ class: cls = "",
31
+ children,
32
+ }: {
33
+ /** false (default) = single-open (native `<details name>`); true = independent multi-open. */
34
+ multiple?: boolean;
35
+ /** Open key (single) or keys (multiple). INITIAL state only in the native variant. Bindable. */
36
+ value?: string | string[];
37
+ /** Accepted for Accordion compatibility; not enforceable without JS (best-effort). */
38
+ collapsible?: boolean;
39
+ size?: Responsive<Size>;
40
+ variant?: Variant;
41
+ disabled?: boolean;
42
+ class?: string;
43
+ children: Snippet;
44
+ } = $props();
45
+
46
+ // One shared <details name> per Accordion2 instance → browser-enforced single-open.
47
+ const groupName = nextFieldId();
48
+
49
+ setDisclosure2Group({
50
+ inGroup: true,
51
+ get name() {
52
+ return multiple ? undefined : groupName;
53
+ },
54
+ get value() {
55
+ return value;
56
+ },
57
+ get multiple() {
58
+ return multiple;
59
+ },
60
+ get size() {
61
+ return size;
62
+ },
63
+ get variant() {
64
+ return variant;
65
+ },
66
+ get disabled() {
67
+ return disabled;
68
+ },
69
+ });
70
+ </script>
71
+
72
+ <div
73
+ class="flex flex-col [&>*:not(:last-child)]:border-b [&>*]:[border-color:var(--ui-border-color)] {cls}"
74
+ >
75
+ {@render children()}
76
+ </div>
@@ -0,0 +1,20 @@
1
+ import type { Snippet } from "svelte";
2
+ import type { Size } from "../types/sizes.js";
3
+ import type { Variant } from "../types/variants.js";
4
+ import type { Responsive } from "../types/responsive.js";
5
+ type $$ComponentProps = {
6
+ /** false (default) = single-open (native `<details name>`); true = independent multi-open. */
7
+ multiple?: boolean;
8
+ /** Open key (single) or keys (multiple). INITIAL state only in the native variant. Bindable. */
9
+ value?: string | string[];
10
+ /** Accepted for Accordion compatibility; not enforceable without JS (best-effort). */
11
+ collapsible?: boolean;
12
+ size?: Responsive<Size>;
13
+ variant?: Variant;
14
+ disabled?: boolean;
15
+ class?: string;
16
+ children: Snippet;
17
+ };
18
+ declare const Accordion2: import("svelte").Component<$$ComponentProps, {}, "value">;
19
+ type Accordion2 = ReturnType<typeof Accordion2>;
20
+ export default Accordion2;
@@ -0,0 +1,198 @@
1
+ <!--
2
+ /**
3
+ * Disclosure2 — a native-first, no-JS/SSR-correct sibling of `Disclosure` (transitional `*2`, see
4
+ * MIGRATION.md). It is a real `<details>/<summary>`: it expands/collapses with NO JavaScript, is
5
+ * open on first paint when `open` is set (SSR-correct), and gets correct button/expanded semantics
6
+ * from the browser for free. The `<summary>` wears `Button`'s exact ghost-header classes (copied
7
+ * verbatim), so the header is pixel-identical to `Disclosure`'s `<Button>` header — including the
8
+ * resting look, hover tint (native `:hover`), focus ring, and the chevron that rotates on open (pure
9
+ * CSS via `details[open]`).
10
+ *
11
+ * Differences from `Disclosure` (inherent to `<details>`, see MIGRATION.md):
12
+ * - The open/close is INSTANT (no `grid-template-rows` height animation) except on browsers with
13
+ * `::details-content` + `interpolate-size` support, where it eases. Reduced-motion → instant,
14
+ * same as `Disclosure`.
15
+ * - Grouping is native: pass the same `name` to several `Disclosure2`s (what `Accordion2` does) for
16
+ * a browser-enforced single-open accordion — no context/JS. `value` is accepted but unused.
17
+ * - `disabled` makes the summary non-interactive (pointer-events-none + aria-disabled); a native
18
+ * `<details>` has no real disabled state.
19
+ */
20
+ -->
21
+ <script lang="ts">
22
+ import type { Snippet } from "svelte";
23
+ import ChevronDown from "~icons/mdi/chevron-down";
24
+ import type { Size } from "../types/sizes.js";
25
+ import { responsiveClasses, type Responsive } from "../types/responsive.js";
26
+ import type { Variant } from "../types/variants.js";
27
+ import { nextFieldId } from "./FieldChrome.svelte";
28
+ import { getDisclosure2Group } from "./disclosure2.js";
29
+
30
+ let {
31
+ title = null,
32
+ header,
33
+ open = $bindable(false),
34
+ value,
35
+ disabled = false,
36
+ size,
37
+ variant,
38
+ name,
39
+ icon,
40
+ id,
41
+ class: cls = "",
42
+ children,
43
+ }: {
44
+ /** Header text. Use the `header` snippet instead for full custom header content. */
45
+ title?: string | null;
46
+ header?: Snippet;
47
+ /** Initial + bindable open state. Sets the `open` attribute (SSR-correct); kept in sync on toggle.
48
+ Inside an `Accordion2`, the group's `value` matching this panel's `value` also opens it. */
49
+ open?: boolean;
50
+ /** This panel's key — matched against an `Accordion2` group's `value` to set the initial open. */
51
+ value?: string;
52
+ disabled?: boolean;
53
+ size?: Responsive<Size>;
54
+ /** Header hover/accent (default `ghost`; inherits the Accordion2's variant). */
55
+ variant?: Variant;
56
+ /** Native `<details name>` — same `name` across siblings = browser-enforced single-open group. */
57
+ name?: string;
58
+ icon?: Snippet;
59
+ id?: string;
60
+ class?: string;
61
+ children: Snippet;
62
+ } = $props();
63
+
64
+ const grp = getDisclosure2Group();
65
+ // Resolve axes: explicit prop → group → default (mirrors Disclosure's precedence).
66
+ const effSize = $derived(size ?? grp?.size ?? "md");
67
+ const effVariant = $derived(variant ?? grp?.variant ?? "ghost");
68
+ const effDisabled = $derived(disabled || !!grp?.disabled);
69
+ // Single-open group → share the browser-enforced `<details name>`; multiple/standalone → own name.
70
+ const effName = $derived(name ?? (grp && !grp.multiple ? grp.name : undefined));
71
+ // Initial open: explicit `open`, or (in a group) this panel's `value` matching the group value.
72
+ const groupOpen = $derived(
73
+ grp == null || value == null
74
+ ? false
75
+ : grp.multiple
76
+ ? Array.isArray(grp.value) && grp.value.includes(value)
77
+ : grp.value === value,
78
+ );
79
+ const effOpen = $derived(open || groupOpen);
80
+
81
+ const uid = nextFieldId();
82
+ const headerId = $derived(id ?? uid);
83
+ const panelId = $derived(`${headerId}-panel`);
84
+
85
+ // ── Header chrome — mirrors a <Button variant size> (borderless=true, the Disclosure default). ──
86
+ const baseClasses =
87
+ "flex w-full items-center [border-radius:var(--ui-border-radius)] font-medium transition-colors cursor-pointer border focus-visible:[outline:2px_solid_color-mix(in_srgb,var(--ui-color-text)_70%,transparent)] focus-visible:[outline-offset:0px]";
88
+ const padMap: Record<Size, string> = { sm: "h-6 px-2.5", md: "h-8 px-4", lg: "h-10 px-6" };
89
+ const textMap: Record<Size, string> = { sm: "text-xs", md: "text-sm", lg: "text-base" };
90
+ const svgMap: Record<Size, string> = {
91
+ sm: "[&_svg]:w-3.5 [&_svg]:h-3.5",
92
+ md: "[&_svg]:w-4 [&_svg]:h-4",
93
+ lg: "[&_svg]:w-5 [&_svg]:h-5",
94
+ };
95
+ // FILL — copied VERBATIM from Button.fillClasses.
96
+ const fillClasses: Record<Variant, string> = {
97
+ primary:
98
+ "[background-color:var(--ui-color-primary)] text-white hover:[background-color:color-mix(in_srgb,var(--ui-color-primary)_90%,black)] [&_svg]:fill-current",
99
+ secondary:
100
+ "[background-color:var(--ui-color-secondary)] text-white hover:[background-color:color-mix(in_srgb,var(--ui-color-secondary)_90%,black)] [&_svg]:fill-current",
101
+ danger:
102
+ "[background-color:var(--ui-color-error)] text-white hover:[background-color:color-mix(in_srgb,var(--ui-color-error)_90%,black)] [&_svg]:fill-current",
103
+ info: "[background-color:var(--ui-color-info)] text-white hover:[background-color:color-mix(in_srgb,var(--ui-color-info)_90%,black)] [&_svg]:fill-current",
104
+ success:
105
+ "[background-color:var(--ui-color-success)] text-white hover:[background-color:color-mix(in_srgb,var(--ui-color-success)_90%,black)] [&_svg]:fill-current",
106
+ warning:
107
+ "[background-color:var(--ui-color-warning)] text-white hover:[background-color:color-mix(in_srgb,var(--ui-color-warning)_90%,black)] [&_svg]:fill-current",
108
+ ghost:
109
+ "bg-transparent [color:var(--ui-color-text)] hover:[background-color:var(--ui-color-hover)] [&_svg]:fill-current",
110
+ neutral:
111
+ "[background-color:var(--ui-color-text)] [color:var(--ui-color-background)] hover:[background-color:color-mix(in_srgb,var(--ui-color-text)_85%,var(--ui-color-background))] [&_svg]:fill-current",
112
+ };
113
+ // BORDER (borderless=true: tracks the fill) — copied VERBATIM from Button.borderMatchClasses.
114
+ const borderMatchClasses: Record<Variant, string> = {
115
+ primary:
116
+ "[border-color:var(--ui-color-primary)] hover:[border-color:color-mix(in_srgb,var(--ui-color-primary)_90%,black)]",
117
+ secondary:
118
+ "[border-color:var(--ui-color-secondary)] hover:[border-color:color-mix(in_srgb,var(--ui-color-secondary)_90%,black)]",
119
+ danger:
120
+ "[border-color:var(--ui-color-error)] hover:[border-color:color-mix(in_srgb,var(--ui-color-error)_90%,black)]",
121
+ info: "[border-color:var(--ui-color-info)] hover:[border-color:color-mix(in_srgb,var(--ui-color-info)_90%,black)]",
122
+ success:
123
+ "[border-color:var(--ui-color-success)] hover:[border-color:color-mix(in_srgb,var(--ui-color-success)_90%,black)]",
124
+ warning:
125
+ "[border-color:var(--ui-color-warning)] hover:[border-color:color-mix(in_srgb,var(--ui-color-warning)_90%,black)]",
126
+ ghost: "border-transparent hover:[border-color:var(--ui-color-hover)]",
127
+ neutral:
128
+ "[border-color:var(--ui-color-text)] hover:[border-color:color-mix(in_srgb,var(--ui-color-text)_85%,var(--ui-color-background))]",
129
+ };
130
+
131
+ const labelText = $derived(responsiveClasses(effSize, textMap));
132
+ const svgClass = $derived(responsiveClasses(effSize, svgMap));
133
+ const summaryClasses = $derived(
134
+ [
135
+ baseClasses,
136
+ responsiveClasses(effSize, padMap),
137
+ labelText,
138
+ responsiveClasses(effVariant, fillClasses),
139
+ responsiveClasses(effVariant, borderMatchClasses),
140
+ effDisabled ? "pointer-events-none opacity-50 cursor-not-allowed" : "",
141
+ "ui-disc2-summary",
142
+ ]
143
+ .filter(Boolean)
144
+ .join(" "),
145
+ );
146
+
147
+ // Keep `open` in sync for JS consumers (harmless with JS off — the browser toggles natively).
148
+ function onToggle(event: Event & { currentTarget: HTMLDetailsElement }) {
149
+ open = event.currentTarget.open;
150
+ }
151
+ </script>
152
+
153
+ <details class="ui-disc2 {cls}" name={effName} open={effOpen} ontoggle={onToggle}>
154
+ <summary
155
+ class={summaryClasses}
156
+ id={headerId}
157
+ aria-controls={panelId}
158
+ aria-disabled={effDisabled || undefined}
159
+ >
160
+ {#if icon}<span class="inline-flex shrink-0 {svgClass}">{@render icon()}</span>{/if}
161
+ {#if header}
162
+ <span class="flex-1 text-left">{@render header()}</span>
163
+ {:else}
164
+ <span class="flex-1 text-left">{title}</span>
165
+ {/if}
166
+ <ChevronDown class="ui-disc2-chevron shrink-0 {svgClass}" />
167
+ </summary>
168
+
169
+ <div
170
+ id={panelId}
171
+ role="region"
172
+ aria-labelledby={headerId}
173
+ class="ui-disc2-panel px-1 pt-1 pb-3 {labelText} [color:var(--ui-color-text)]"
174
+ >
175
+ {@render children()}
176
+ </div>
177
+ </details>
178
+
179
+ <style>
180
+ /* Hide the native disclosure triangle — we draw our own chevron. */
181
+ .ui-disc2 > summary {
182
+ list-style: none;
183
+ }
184
+ .ui-disc2 > summary::-webkit-details-marker {
185
+ display: none;
186
+ }
187
+ /* Chevron rotates on open — pure CSS, so it's correct with JS off and in SSR. Open/close itself is
188
+ instant (a native <details> doesn't height-animate pre-`::details-content`); documented in
189
+ MIGRATION.md. Reduced-motion skips the chevron transition, matching Disclosure. */
190
+ .ui-disc2[open] > summary :global(.ui-disc2-chevron) {
191
+ transform: rotate(180deg);
192
+ }
193
+ @media (prefers-reduced-motion: no-preference) {
194
+ .ui-disc2 :global(.ui-disc2-chevron) {
195
+ transition: transform 200ms;
196
+ }
197
+ }
198
+ </style>
@@ -0,0 +1,27 @@
1
+ import type { Snippet } from "svelte";
2
+ import type { Size } from "../types/sizes.js";
3
+ import { type Responsive } from "../types/responsive.js";
4
+ import type { Variant } from "../types/variants.js";
5
+ type $$ComponentProps = {
6
+ /** Header text. Use the `header` snippet instead for full custom header content. */
7
+ title?: string | null;
8
+ header?: Snippet;
9
+ /** Initial + bindable open state. Sets the `open` attribute (SSR-correct); kept in sync on toggle.
10
+ Inside an `Accordion2`, the group's `value` matching this panel's `value` also opens it. */
11
+ open?: boolean;
12
+ /** This panel's key — matched against an `Accordion2` group's `value` to set the initial open. */
13
+ value?: string;
14
+ disabled?: boolean;
15
+ size?: Responsive<Size>;
16
+ /** Header hover/accent (default `ghost`; inherits the Accordion2's variant). */
17
+ variant?: Variant;
18
+ /** Native `<details name>` — same `name` across siblings = browser-enforced single-open group. */
19
+ name?: string;
20
+ icon?: Snippet;
21
+ id?: string;
22
+ class?: string;
23
+ children: Snippet;
24
+ };
25
+ declare const Disclosure2: import("svelte").Component<$$ComponentProps, {}, "open">;
26
+ type Disclosure2 = ReturnType<typeof Disclosure2>;
27
+ export default Disclosure2;
@@ -0,0 +1,16 @@
1
+ import type { Size } from "../types/sizes.js";
2
+ import type { Variant } from "../types/variants.js";
3
+ import type { Responsive } from "../types/responsive.js";
4
+ export interface Disclosure2GroupContext {
5
+ inGroup: true;
6
+ /** Shared `<details name>` for single-open mode; `undefined` in multiple mode (independent). */
7
+ name?: string;
8
+ /** The group's open key (single) or keys (multiple) — used to compute each child's initial `open`. */
9
+ value?: string | string[];
10
+ multiple: boolean;
11
+ size?: Responsive<Size>;
12
+ variant?: Variant;
13
+ disabled?: boolean;
14
+ }
15
+ export declare function setDisclosure2Group(ctx: Disclosure2GroupContext): void;
16
+ export declare function getDisclosure2Group(): Disclosure2GroupContext | undefined;
@@ -0,0 +1,15 @@
1
+ /**
2
+ * Shared context for `Accordion2` → `Disclosure2` — the native-first sibling of `disclosure.ts`.
3
+ * Unlike the JS group (which owns `isOpen`/`toggle`), this one carries only STATIC data the child
4
+ * reads at render: a shared `<details name>` (single-open mode → the browser enforces exclusivity
5
+ * with no JS) and the group's initial `value`/axes. There is no runtime toggle callback — the native
6
+ * `<details>` elements coordinate themselves.
7
+ */
8
+ import { getContext, setContext } from "svelte";
9
+ const KEY = Symbol("svelte-ui-disclosure2-group");
10
+ export function setDisclosure2Group(ctx) {
11
+ setContext(KEY, ctx);
12
+ }
13
+ export function getDisclosure2Group() {
14
+ return getContext(KEY);
15
+ }
package/dist/index.d.ts CHANGED
@@ -70,6 +70,8 @@ export { Stepper } from "./components/Stepper/index.js";
70
70
  export type { StepItem } from "./components/Stepper/index.js";
71
71
  export { default as Disclosure } from "./components/Disclosure.svelte";
72
72
  export { default as Accordion } from "./components/Accordion.svelte";
73
+ export { default as Disclosure2 } from "./components/Disclosure2.svelte";
74
+ export { default as Accordion2 } from "./components/Accordion2.svelte";
73
75
  export { default as SideBarMenu } from "./components/SideBarMenu/SideBarMenu.svelte";
74
76
  export type { SideBarMenuItem, SideBarMenuBadge, SideBarMenuBadgeVariant, SideBarMenuApi, SideBarMenuMode, SideBarMenuActiveRule, } from "./components/SideBarMenu/SideBarMenu.svelte";
75
77
  export { Breadcrumbs } from "./components/Breadcrumbs/index.js";
package/dist/index.js CHANGED
@@ -68,6 +68,9 @@ export { Carousel } from "./components/Carousel/index.js";
68
68
  export { Stepper } from "./components/Stepper/index.js";
69
69
  export { default as Disclosure } from "./components/Disclosure.svelte";
70
70
  export { default as Accordion } from "./components/Accordion.svelte";
71
+ // Native-first, no-JS/SSR-correct variants (transitional `*2` — see MIGRATION.md).
72
+ export { default as Disclosure2 } from "./components/Disclosure2.svelte";
73
+ export { default as Accordion2 } from "./components/Accordion2.svelte";
71
74
  // Navigation Components
72
75
  export { default as SideBarMenu } from "./components/SideBarMenu/SideBarMenu.svelte";
73
76
  export { Breadcrumbs } from "./components/Breadcrumbs/index.js";
@@ -308,6 +308,24 @@ independent. Propagates `size`/`variant`/`disabled` to children.
308
308
  - **Props**: `multiple` (default `false`), `value` (bindable — `string` single / `string[]` multiple),
309
309
  `collapsible` (single mode, default `true`), `size`, `variant`, `disabled`, `class`, `children`.
310
310
 
311
+ ### Disclosure2 / Accordion2 (native-first)
312
+
313
+ **No-JS / SSR-correct** siblings built on real `<details>/<summary>`: they expand, rotate the chevron,
314
+ and (via `Accordion2`'s shared `<details name>`) enforce single-open **with no JavaScript**, correct
315
+ in SSR. The `<summary>` wears `Button`'s ghost-header classes, so the header is **pixel-identical** to
316
+ `Disclosure` at every `size`/`variant`.
317
+
318
+ - **Location**: `src/lib/components/Disclosure2.svelte`, `src/lib/components/Accordion2.svelte`
319
+ - **Props**: a drop-in **superset** of `Disclosure`/`Accordion` — same `title`/`header`/`open`/`value`/
320
+ `size`/`variant`/`disabled`/`icon`/`class`/`children` and `multiple`/`value`. `Disclosure2` also
321
+ takes a native `name` (shared → browser single-open group).
322
+ - **Intentional divergences** (native `<details>`): open/close is **instant** (no height animation —
323
+ reduced-motion parity), the group `value` is **initial state only** (with JS off the browser owns
324
+ toggles, so the binding doesn't track), and `collapsible={false}` is best-effort. Full matrix:
325
+ `MIGRATION.md`.
326
+ - **Use when**: expandable content must work server-side / without JS (FAQs, nav sections).
327
+ - **Transitional**: ships alongside the originals under the `2` suffix; see `MIGRATION.md`.
328
+
311
329
  ### Rating
312
330
 
313
331
  Star rating in two modes: a read-only display, or an interactive picker.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@spaethtech/svelte-ui",
3
- "version": "0.21.1-dev.120.d0d8cfa",
3
+ "version": "0.21.1-dev.121.3e3f7cf",
4
4
  "repository": {
5
5
  "type": "git",
6
6
  "url": "git+https://github.com/spaethtech/svelte-ui.git"
@@ -301,6 +301,14 @@
301
301
  "types": "./dist/components/Accordion.svelte.d.ts",
302
302
  "svelte": "./dist/components/Accordion.svelte"
303
303
  },
304
+ "./disclosure2": {
305
+ "types": "./dist/components/Disclosure2.svelte.d.ts",
306
+ "svelte": "./dist/components/Disclosure2.svelte"
307
+ },
308
+ "./accordion2": {
309
+ "types": "./dist/components/Accordion2.svelte.d.ts",
310
+ "svelte": "./dist/components/Accordion2.svelte"
311
+ },
304
312
  "./side-bar-menu": {
305
313
  "types": "./dist/components/SideBarMenu/SideBarMenu.svelte.d.ts",
306
314
  "svelte": "./dist/components/SideBarMenu/SideBarMenu.svelte"