svelte-fluentui 1.3.3 → 1.4.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -2,17 +2,23 @@
2
2
 
3
3
  A comprehensive Svelte wrapper library for Microsoft FluentUI web components (v2.6.x), providing a seamless way to use FluentUI components in Svelte applications.
4
4
 
5
- ## What's New in v1.3.3
5
+ ## What's New in v1.4.1
6
6
 
7
- - **Custom-element attribute bindings stop stringifying `undefined` / `null` / `false`** Recurring regression (last fixed ~5 months ago, reintroduced during the structural rework) that affected 22 wrappers including `TextField`, `Textarea`, `Switch`, `Slider`, `Checkbox`, `Button`, `Anchor`, `Accordion(Item)`, `BreadcrumbItem`, `DataGrid(Row/Cell)`, `Dialog`, `Listbox`, `MenuButton`, `Option`, `TabPanel`, `Toolbar`, `NumberField`, `Combobox`, plus `Paginator` and `QuickGrid` sub-buttons. Svelte 5 sets properties on custom elements rather than attributes, and FAST's `@attr` decorators stringify whatever they receive so unset props were rendering as `title="undefined"`, `readonly="false"`, `disabled="false"`, etc. The `readonly`/`disabled` cases were the worst symptom because `[readonly]` and `[disabled]` CSS attribute-presence selectors match regardless of value, leaving an enabled field with a not-allowed cursor. All affected wrappers converted to the conditional-spread pattern (`{...(title ? { title } : {})}`) which physically omits the attribute from the template when unset. Variants `{...(value != null ? { value } : {})}` for inputs (so `value=""` still renders) and `{...(attr !== undefined ? { attr } : {})}` for numeric props (so `0` survives) are used where falsy values are meaningful.
7
+ - **`MultiSplitter` splitters mounted inside hidden tab panels now render at proper widths on first reveal** When a splitter mounted inside an inactive `<Tab>` (or any `display: none` parent), `clientWidth` was 0 at construction time, so the previous code assigned `flex-basis: 0px` to every pane and the `ResizeObserver` then short-circuited the first reveal leaving panes smashed at 0 width with no path back to their declared `min` / `size`. The fix splits init into two phases: `scheduleInit` always installs the observer immediately (even when hidden), and `applyInitialSizes` defers its work until `totalAvailable() > 0`. The observer's callback runs the deferred init on the first 0 non-zero transition via a new `!initApplied` branch. Bonus: hide-then-show cycles now preserve sizes instead of zeroing them via the destructive `clampToConstraints(0, ...)` path, and a reveal-after-resize-while-hidden falls through to the existing scale path so panes re-scale proportionally to the new container width. Demo added under "Inside tabs (deferred initial sizing)".
8
8
 
9
- - **`TextField` demo page new Readonly and Disabled example sections** — The `/components/forms/text-field` showcase previously demonstrated only the basic input and `autocomplete` variants; the readonly and disabled states (the surface that exposed the bug above) had no live example. Added Readonly with outline + filled variants and Disabled with three variants (outline + placeholder, outline + value, filled + value).
9
+ - **`TopNav` the pinned desktop drawer no longer collapses on every link click** — `closeMobileMenu` was unconditionally writing `mobileMenuOpen = false`, so the documented pattern of wiring `onClick={closeDrawer}` on every `NavLinkItem` (needed for the mobile overlay to dismiss on tap) accidentally closed the pinned desktop rail too. The sync `$effect` only re-ran when `drawerPinned` itself changed, so once collapsed the rail stayed collapsed until the consumer toggled the prop. Added an early-return guard in `closeMobileMenu` it's now a no-op when `drawerPinned` is true, matching the documented contract. Mobile overlay behaviour is unchanged.
10
10
 
11
- ## What's New in v1.3.2
11
+ - **`CommandPalette` keyboard-shortcut chips in the footer are legible again** — The `.cp-footer` rule set `color: var(--neutral-foreground-hint)` for the "navigate" / "open" / "toggle" labels (reads fine on the panel background), but `.cp-footer kbd` carries its own opaque `--neutral-layer-2` background for the boxed-key look — so the hint color cascaded into the kbd boxes, giving #888 text on #f5f5f5 at 0.7 rem and the arrow / Ctrl / K glyphs effectively vanished. Added explicit `color: var(--neutral-foreground-rest)` on `.cp-footer kbd` so the kbd contents resolve against full foreground-on-layer-2 contrast.
12
12
 
13
- - **`TopNav`hamburger flexibility via `menuToggleSize` + `menuToggleTemplate`**`menuToggleSize` (default `42`) flows through a `--topnav-toggle-size` CSS variable so the glyph and close-icon scale proportionally with the box. `menuToggleTemplate: Snippet<[{open, toggle}]>` lets consumers render any button shape text + chevron, brand-styled accent button, custom SVG and still wire up state correctly. Both paths render inside a wrapper that owns the visibility/order/collapse rules, so custom templates automatically inherit hide-when-wide / show-when-narrow / stay-visible-when-pinned behavior.
14
- - **`TopNav` — default hamburger is now a plain `<button>` instead of a fluent-button** — the previous default rendered `<Button appearance="stealth">` which still carried button chrome (hover background fill, boxed visual weight). Replaced with a vanilla `<button>` styled `background: transparent; border: none; padding: 0`, with `opacity: 0.7` on hover and a `:focus-visible` accent outline for keyboard nav. Reads as just the icon, not a button containing an icon. Click target still fills the full `menuToggleSize` box for touch reachability.
15
- - **`Badge`new `radius` prop overrides the binary rounded-rect / pill shape with an arbitrary border-radius** Badge had exactly two shape modes (default 4px corner / `circular={true}` pill) mirroring Microsoft's FluentUI Badge `shape` prop. The new `radius?: string` accepts any CSS length (`8px`, `0.5rem`, `var(--my-radius)`) and emits inline `border-radius`, winning over both class rules via CSS specificity. Plays nicely with `circular={true}` the circular sizing wins, the radius wins, so you get pill-sized badges with non-pill corners if you want.
13
+ - **Securitynpm audit cleaned up, 8 of 9 advisories resolved** Dev/build dependency chain refreshed: `ws`, `devalue`, `vite`, `postcss`, `qs`, `brace-expansion`, `svelte`, `@sveltejs/kit`, and the nested `cookie` chain all bumped past their respective advisories (3 high, 5 moderate, plus the cookie chain). Only `esbuild` 0.27.x's Windows dev-server file-read low remains, deferred because 0.28.x mis-emits output in this project's pipeline. All resolved packages are devDeps in `svelte-fluentui` consumers don't get runtime changes, but anyone building from source no longer trips the audit gate.
14
+
15
+ - **Build pipeline `vitePreprocess({ script: true })` restored in `docs/svelte.config.js`** Newer `@sveltejs/vite-plugin-svelte` made `vitePreprocess()` skip TypeScript by default; Svelte 5's native parser handles most TS but tripped on curried arrow functions with typed optional params + return-type annotation and let raw `?.` / `??` operators through to the browser. Switching to `vitePreprocess({ script: true })` re-enables explicit script preprocessing. If you fork this repo or use the same config in your own project and see `SyntaxError: Unexpected token '?'` in the browser after a `@sveltejs/vite-plugin-svelte` bump this is the fix.
16
+
17
+ ## What's New in v1.4.0
18
+
19
+ - **`MultiSplitter` — full rewrite as a Svelte 5 port of pureadmin.io's `pa-splitter`** — The old wrapper was a near-empty shell; the new component (`src/lib/components/layout/MultiSplitter.svelte` + `MultiSplitterPane.svelte`) is a real N-pane resizable container with drag-to-resize using a REBALANCE model (CLASSIC + TUNNEL absorbers so slack can punch through a rail wall), minimize-to-rail via the `minimize` prop with a configurable snap threshold, full keyboard nav + ARIA on the gutter, `localStorage` persistence via the `id` prop, and auto-accordion mode when the container can't fit all panes' mins. Drag math is rAF-throttled with a 2px jitter floor; pane Cards auto-adapt to railed state with the first child becoming a rotated rail title in horizontal orientation. Three callbacks (`onresize`, `oncollapse`, `onexpand`) and full type exports (`MultiSplitterResizeDetail`, `MultiSplitterToggleDetail`).
20
+ - **`MultiSplitter` — gutter drag against a railed pane is a one-way valve: inward inert, outward expands** — Earlier iterations either flipped the rail open instantly on `pointerdown` (the user saw the card "expand" just from pressing the gutter) or refused to expand from any drag at all. Final behaviour: inward drag (toward the rail) bails before reaching the drag math so the gutter doesn't move; outward drag past 2px releases the rail, fires `onexpand`, and grows the pane following the cursor with the rail floor clamping until `primary.min` is reached. Dblclick and rail-body click stay as alternative expand gestures. The result matches what users actually expect from a collapsed pane — you can pull it open but you can't accidentally crush it further.
21
+ - **`Select` — encapsulated in a single render root via `display: contents`** — The component renders 2-4 sibling elements at root depending on mode (label + hidden source mirror + trigger + optional hidden form input in single mode; label + inline listbox in multi mode). That meant a consumer dropping `<Select>` into a flex or grid had to reason about the internal sibling structure to align it. Wrapped everything in `<div class="select-root">` with `display: contents` so the wrapper is invisible to flex/grid layout (children still participate as direct items of the consumer's container), but the component now reads as a single logical root from the outside. Zero behaviour change for existing layout code.
16
22
 
17
23
  ## Features
18
24