@marianmeres/stuic 3.35.0 → 3.35.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/AGENTS.md CHANGED
@@ -25,7 +25,7 @@
25
25
  src/lib/
26
26
  ├── components/ # 45 UI components
27
27
  ├── actions/ # 14 Svelte actions
28
- ├── utils/ # 42 utility modules
28
+ ├── utils/ # 43 utility modules
29
29
  ├── themes/ # 29 theme definitions (.ts) + generated CSS (css/)
30
30
  ├── icons/ # Icon re-exports
31
31
  ├── index.css # Centralized CSS imports
package/API.md CHANGED
@@ -76,7 +76,18 @@ Overlay container with backdrop. Controlled programmatically.
76
76
 
77
77
  #### `ModalDialog`
78
78
 
79
- Pre-styled modal dialog with title and action buttons.
79
+ Pre-styled modal dialog with title and action buttons. Uses native `<dialog>` element with focus trap and backdrop.
80
+
81
+ | Prop | Type | Default | Description |
82
+ | ------------------ | ---------- | ----------- | ----------------------------------------------------- |
83
+ | `classDialog` | `string` | `undefined` | CSS class for the dialog element |
84
+ | `noClickOutsideClose` | `boolean` | `false` | Disable close on outside click |
85
+ | `noEscapeClose` | `boolean` | `false` | Disable close on Escape key |
86
+ | `noScrollLock` | `boolean` | `false` | Disable body scroll lock when open |
87
+ | `preEscapeClose` | `() => any` | — | Pre-close hook for Escape. Return false to prevent. |
88
+ | `preClose` | `() => any` | — | Pre-close hook. Return false to prevent. |
89
+
90
+ **Methods:** `open(openerOrEvent?)`, `close()`
80
91
 
81
92
  #### `Drawer`
82
93
 
@@ -714,7 +725,46 @@ Keyboard shortcut display.
714
725
 
715
726
  #### `Carousel`
716
727
 
717
- Image/content slider with navigation.
728
+ Image/content slider with scroll snap, keyboard navigation, wheel scroll, optional arrows, and active item tracking via IntersectionObserver.
729
+
730
+ | Prop | Type | Default | Description |
731
+ | ------------------- | ------------------------------------------------- | ----------- | -------------------------------------------------- |
732
+ | `items` | `CarouselItem[]` | required | Array of carousel items |
733
+ | `itemsPerView` | `number` | `1` | Number of items visible per view |
734
+ | `peekPercent` | `number` | `0` | Percentage of next item to show as peek (0-50) |
735
+ | `gap` | `number \| string` | `undefined` | Gap between items |
736
+ | `trackActive` | `boolean` | `false` | Enable active item tracking |
737
+ | `syncActiveOnScroll`| `boolean` | `false` | Sync active item based on scroll position |
738
+ | `activeIndex` | `number` | `0` | Currently active item index (bindable) |
739
+ | `value` | `string \| number` | `undefined` | Currently active item ID (bindable) |
740
+ | `snap` | `boolean` | `true` | Enable scroll snap behavior |
741
+ | `snapAlign` | `"start" \| "center" \| "end"` | `"start"` | Snap alignment |
742
+ | `keyboard` | `boolean` | `true` | Enable keyboard navigation (arrows, Home, End) |
743
+ | `loop` | `boolean` | `false` | Allow cycling from last to first and vice versa |
744
+ | `scrollBehavior` | `ScrollBehavior` | `"smooth"` | Scroll behavior for programmatic navigation |
745
+ | `scrollbar` | `boolean` | `true` | Show scrollbar on hover |
746
+ | `wheelScroll` | `boolean` | `true` | Enable horizontal scrolling via mouse wheel |
747
+ | `arrows` | `boolean` | `false` | Show prev/next arrow buttons |
748
+ | `minItemWidth` | `number` | `undefined` | Minimum item width (px) for auto-fit |
749
+ | `onActiveChange` | `(item: CarouselItem, index: number) => void` | — | Callback when active item changes |
750
+ | `renderItem` | `Snippet<[{ item, index, active }]>` | — | Custom render snippet for items |
751
+
752
+ **Methods:** `goTo(index)`, `goToId(id)`, `next()`, `previous()`
753
+
754
+ ```svelte
755
+ <Carousel
756
+ items={slides}
757
+ itemsPerView={3}
758
+ gap={16}
759
+ arrows
760
+ trackActive
761
+ syncActiveOnScroll
762
+ >
763
+ {#snippet renderItem({ item, index, active })}
764
+ <img src={item.data.src} alt={item.data.alt} />
765
+ {/snippet}
766
+ </Carousel>
767
+ ```
718
768
 
719
769
  #### `AnimatedElipsis`
720
770
 
@@ -789,7 +839,65 @@ Theme color swatch preview.
789
839
 
790
840
  #### `Book`
791
841
 
792
- Interactive book/flipbook reader with 3D CSS page flip animation, zoom, pan, swipe, and responsive single-page mode.
842
+ Interactive book/flipbook reader with 3D CSS page flip animation, zoom, pan, swipe, clickable areas, and responsive single-page mode.
843
+
844
+ | Prop | Type | Default | Description |
845
+ | ---------------- | ------------------------------------------------------------- | -------------- | --------------------------------------------- |
846
+ | `pages` | `BookPage[]` | required | Ordered array of book pages |
847
+ | `baseUrl` | `string` | `undefined` | Fallback base URL for relative page src |
848
+ | `activeSpread` | `number` | `0` | Currently active spread index (bindable) |
849
+ | `keyboard` | `boolean` | `true` | Enable keyboard navigation |
850
+ | `swipe` | `boolean` | `true` | Enable swipe gesture navigation |
851
+ | `duration` | `number` | `500` | Flip animation duration in ms |
852
+ | `zoom` | `boolean` | `true` | Enable zoom capability |
853
+ | `zoomLevels` | `readonly number[]` | `[1,1.5,2,3]` | Discrete zoom levels |
854
+ | `clampPan` | `boolean` | `false` | Clamp panning within bounds |
855
+ | `singlePage` | `boolean` | `false` | Force single-page layout |
856
+ | `responsive` | `boolean` | `true` | Auto-switch to single-page when narrow |
857
+ | `onSpreadChange` | `(spread: BookSpread, index: number) => void` | — | Callback when active spread changes |
858
+ | `onPageClick` | `(data: { page: BookPage; x: number; y: number }) => void` | — | Callback on page click (coordinates 0–1) |
859
+ | `onAreaClick` | `(data: { area: BookPageArea; page: BookPage }) => void` | — | Callback when clickable area is clicked |
860
+ | `renderPage` | `Snippet<[{ page, position }]>` | — | Custom page render snippet |
861
+
862
+ **Exported helpers:** `buildSpreads(pages)`, `buildSinglePageSpreads(pages)`, `buildSheets(spreads)`, `computeBookPageSize(pages)`
863
+
864
+ **Types:** `BookPage`, `BookPageArea`, `BookSpread`, `BookSheet`, `BookCollection`
865
+
866
+ ```svelte
867
+ <Book
868
+ pages={[
869
+ { id: 1, src: "/cover.jpg", width: 800, height: 1100 },
870
+ { id: 2, src: "/page1.jpg", width: 800, height: 1100 },
871
+ { id: 3, src: "/page2.jpg", width: 800, height: 1100 },
872
+ ]}
873
+ bind:activeSpread
874
+ />
875
+ ```
876
+
877
+ #### `BookResponsive`
878
+
879
+ Responsive wrapper around Book that intelligently switches between book mode (dual/single-page) and an inline asset preview mode based on container width. Inherits all Book props except `responsive` and `singlePage` (managed internally).
880
+
881
+ | Prop | Type | Default | Description |
882
+ | ----------------- | --------------------- | ----------- | ------------------------------------------------------- |
883
+ | `minPageWidth` | `number` | `150` | Min page width (px) before switching to single-page |
884
+ | `debounce` | `number` | `150` | Resize debounce delay in ms |
885
+ | `inlineThreshold` | `number` | `480` | Container width (px) below which switches to inline (0 = disabled) |
886
+ | `forceInline` | `boolean` | `false` | Force inline asset preview mode |
887
+ | `noPrevNext` | `boolean` | `false` | Hide prev/next arrow buttons |
888
+ | `classControls` | `string` | `undefined` | Custom class for prev/next buttons |
889
+ | `noModeSwitch` | `boolean` | `false` | Hide the book/inline toggle button |
890
+ | `initialMode` | `"book" \| "inline"` | `undefined` | Override auto-detection on mount |
891
+
892
+ **Exported utility:** `bookPagesToAssets(pages)` — Converts `BookPage[]` to `AssetPreview[]` for inline mode.
893
+
894
+ ```svelte
895
+ <BookResponsive
896
+ pages={bookPages}
897
+ inlineThreshold={600}
898
+ onAreaClick={handleAreaClick}
899
+ />
900
+ ```
793
901
 
794
902
  #### `Circle`
795
903
 
@@ -831,7 +939,75 @@ Element that expands width on hover with delayed transitions and shadow effects.
831
939
 
832
940
  #### `AssetsPreview`
833
941
 
834
- Modal-based asset/file preview gallery with zoom, pan, pinch-zoom, and download controls.
942
+ Modal-based asset/file preview gallery with zoom, pan, pinch-zoom, swipe navigation, clickable area overlays, and download controls. Opens in a full-screen ModalDialog.
943
+
944
+ | Prop | Type | Default | Description |
945
+ | ----------------- | ----------------------------------------------------------------- | ----------- | -------------------------------------------- |
946
+ | `assets` | `string[] \| AssetPreview[]` | required | Asset URLs or asset objects |
947
+ | `baseUrl` | `string` | `undefined` | Fallback base URL for relative asset URLs |
948
+ | `modalClassDialog`| `string` | `undefined` | CSS class for the modal dialog |
949
+ | `modalClass` | `string` | `undefined` | CSS class for the modal container |
950
+ | `classControls` | `string` | `undefined` | CSS class for control buttons |
951
+ | `t` | `TranslateFn` | built-in | Translation function |
952
+ | `onDelete` | `(asset: AssetPreview, index: number, { close }) => void` | — | Delete handler (shows delete button) |
953
+ | `onAreaClick` | `(data: { area: AssetArea; asset: AssetPreviewNormalized }) => void` | — | Callback for clickable area on image |
954
+ | `noName` | `boolean` | `false` | Hide file name display |
955
+ | `clampPan` | `boolean` | `true` | Clamp panning within image bounds |
956
+ | `noDownload` | `boolean` | `false` | Hide download button |
957
+ | `noPrevNext` | `boolean` | `false` | Hide prev/next arrows |
958
+ | `noZoom` | `boolean` | `false` | Disable all zooming |
959
+ | `noZoomButtons` | `boolean` | `false` | Hide zoom buttons (gestures still work) |
960
+ | `noDots` | `boolean` | `false` | Never show pagination dots |
961
+ | `noCurrentOfTotal`| `boolean` | `false` | Never show "x / y" counter |
962
+
963
+ **Methods:** `open(index?)`, `close()`
964
+
965
+ **Types:** `AssetPreview`, `AssetPreviewUrlObj`, `AssetArea`
966
+
967
+ **Utility:** `getAssetIcon(ext)` — Returns icon function for file extension.
968
+
969
+ ```svelte
970
+ <AssetsPreview
971
+ assets={[
972
+ { url: { full: "/photo.jpg", thumb: "/photo-thumb.jpg" }, name: "Photo", type: "image/jpeg" },
973
+ "/document.pdf",
974
+ ]}
975
+ onDelete={(asset, i, { close }) => { deleteAsset(i); close(); }}
976
+ />
977
+ ```
978
+
979
+ #### `AssetsPreviewInline`
980
+
981
+ Always-visible (non-modal) variant of AssetsPreview with the same zoom, pan, swipe, and area clicking features. For embedding asset galleries directly in layouts.
982
+
983
+ | Prop | Type | Default | Description |
984
+ | ----------------- | ----------------------------------------------------------------- | ----------- | -------------------------------------------- |
985
+ | `assets` | `string[] \| AssetPreview[]` | required | Asset URLs or asset objects |
986
+ | `baseUrl` | `string` | `undefined` | Fallback base URL for relative asset URLs |
987
+ | `initialIndex` | `number` | `0` | Starting asset index |
988
+ | `currentIndex` | `number` | `0` | Current display index (bindable) |
989
+ | `class` | `string` | `undefined` | Container CSS class |
990
+ | `classControls` | `string` | `undefined` | CSS class for control buttons |
991
+ | `t` | `TranslateFn` | built-in | Translation function |
992
+ | `onDelete` | `(asset, index, { close }) => void` | — | Delete handler |
993
+ | `onAreaClick` | `(data: { area: AssetArea; asset: AssetPreviewNormalized }) => void` | — | Callback for clickable area on image |
994
+ | `noName` | `boolean` | `false` | Hide file name display |
995
+ | `clampPan` | `boolean` | `true` | Clamp panning within bounds |
996
+ | `noDownload` | `boolean` | `false` | Hide download button |
997
+ | `noPrevNext` | `boolean` | `false` | Hide prev/next arrows |
998
+ | `noZoom` | `boolean` | `false` | Disable all zooming |
999
+ | `noZoomButtons` | `boolean` | `false` | Hide zoom buttons (gestures still work) |
1000
+ | `noDots` | `boolean` | `false` | Never show pagination dots |
1001
+ | `noCurrentOfTotal`| `boolean` | `false` | Never show "x / y" counter |
1002
+
1003
+ **Methods:** `goTo(index)`, `next()`, `previous()`
1004
+
1005
+ ```svelte
1006
+ <AssetsPreviewInline
1007
+ assets={imageUrls}
1008
+ bind:currentIndex
1009
+ />
1010
+ ```
835
1011
 
836
1012
  #### `X`
837
1013
 
@@ -1289,6 +1465,36 @@ Generate SVG circle path data.
1289
1465
 
1290
1466
  Value oscillation for animations.
1291
1467
 
1468
+ ### URL
1469
+
1470
+ #### `resolveUrl(url, baseUrl?)`
1471
+
1472
+ Resolve a possibly relative URL against an optional base URL. Returns the original URL if no baseUrl or on error.
1473
+
1474
+ **Parameters:**
1475
+
1476
+ - `url` (string) — URL to resolve
1477
+ - `baseUrl` (string, optional) — Base URL to resolve against
1478
+
1479
+ **Returns:** `string`
1480
+
1481
+ ```ts
1482
+ import { resolveUrl } from "@marianmeres/stuic";
1483
+ resolveUrl("images/photo.jpg", "https://example.com/books/1/");
1484
+ // => "https://example.com/books/1/images/photo.jpg"
1485
+ ```
1486
+
1487
+ #### `resolveSrcset(srcset, baseUrl?)`
1488
+
1489
+ Resolve all URLs within a srcset string against an optional base URL.
1490
+
1491
+ **Parameters:**
1492
+
1493
+ - `srcset` (string) — Srcset string with relative URLs
1494
+ - `baseUrl` (string, optional) — Base URL to resolve against
1495
+
1496
+ **Returns:** `string`
1497
+
1292
1498
  ### Files
1293
1499
 
1294
1500
  #### `fileFromBlobUrl(blobUrl, filename)`
@@ -1388,6 +1594,10 @@ Re-exported icon render functions from `@marianmeres/icons-fns`. Import from `@m
1388
1594
 
1389
1595
  `iconFile`, `iconFileBinary`, `iconFileCode`, `iconFileImage`, `iconFileMusic`, `iconFilePdf`, `iconFileRichtext`, `iconFileSlides`, `iconFileSpreadsheet`, `iconFileText`, `iconFileWord`, `iconFileZip`
1390
1596
 
1597
+ ### Book Icons
1598
+
1599
+ `iconBookOpen`
1600
+
1391
1601
  ### Alert Icons
1392
1602
 
1393
1603
  `iconAlertSuccess`, `iconAlertInfo`, `iconAlertError`, `iconAlertWarning`, `iconRefresh`
@@ -1398,7 +1608,11 @@ Re-exported icon render functions from `@marianmeres/icons-fns`. Import from `@m
1398
1608
 
1399
1609
  ### UI Control Icons
1400
1610
 
1401
- `iconCheck`, `iconChevronDown`, `iconChevronLeft`, `iconChevronRight`, `iconChevronUp`, `iconCircle`, `iconDot`, `iconEllipsisVertical`, `iconLanguages`, `iconMenu`, `iconSearch`, `iconSettings`, `iconSquare`, `iconUser`, `iconX`
1611
+ `iconCheck`, `iconChevronDown`, `iconChevronLeft`, `iconChevronRight`, `iconChevronUp`, `iconCircle`, `iconCircleCheckBig`, `iconDot`, `iconEllipsisVertical`, `iconGrip`, `iconGripHorizontal`, `iconGripVertical`, `iconLanguages`, `iconMenu`, `iconPencil`, `iconSearch`, `iconSettings`, `iconSquare`, `iconUser`, `iconX`
1612
+
1613
+ ### Brand Icons
1614
+
1615
+ `iconApple`, `iconFacebook`, `iconGithub`, `iconGoogle`, `iconInstagram`, `iconMicrosoft`, `iconTwitterX`, `iconXbox`, `iconYoutube`
1402
1616
 
1403
1617
  ---
1404
1618
 
@@ -1419,6 +1633,9 @@ Naming pattern: `{ComponentName}Props`
1419
1633
 
1420
1634
  Additional exported types include:
1421
1635
 
1636
+ - `BookPage`, `BookPageArea`, `BookSpread`, `BookSheet`, `BookCollection` — Book component types
1637
+ - `AssetPreview`, `AssetPreviewUrlObj`, `AssetArea` — AssetPreview types
1638
+ - `CarouselItem` — Carousel item type
1422
1639
  - `LoginFormData`, `LoginFormValidationError` — Login form types
1423
1640
  - `CartComponentItem`, `CartVariant` — Cart component types
1424
1641
  - `CheckoutStep`, `CheckoutAddressData`, `CheckoutCustomerFormData`, `CheckoutLoginFormData`, `CheckoutOrderLineItem`, `CheckoutOrderTotals`, `CheckoutDeliveryOption`, `CheckoutDeliverySnapshot`, `CheckoutOrderData`, `CheckoutValidationError`, `CheckoutFormMode` — Checkout types
package/README.md CHANGED
@@ -143,7 +143,7 @@ CommandMenu, DropdownMenu, TabbedMenu, TypeaheadInput, KbdShortcut
143
143
 
144
144
  ### Display & Utility
145
145
 
146
- Avatar, Book, Carousel, Circle, AnimatedElipsis, H, IconSwap, Separator, ThemePreview, ColorScheme, Thc, HoverExpandableWidth, AssetsPreview, DataTable
146
+ Avatar, Book, BookResponsive, Carousel, Circle, AnimatedElipsis, H, IconSwap, Separator, ThemePreview, ColorScheme, Thc, HoverExpandableWidth, AssetsPreview, AssetsPreviewInline, DataTable
147
147
 
148
148
  ### E-commerce
149
149
 
@@ -63,14 +63,16 @@
63
63
  | --------------- | ------------------------------------------------------------------- |
64
64
  | Avatar | User avatars with fallback |
65
65
  | KbdShortcut | Keyboard shortcut hints |
66
- | Carousel | Image/content slider |
66
+ | Carousel | Image/content slider with snap, keyboard nav, wheel scroll, arrows |
67
67
  | ListItemButton | List item with actions |
68
68
  | AnimatedElipsis | Loading dots animation |
69
69
  | IconSwap | N-state visibility swap with opacity transitions (e.g. hamburger/X) |
70
70
  | DataTable | Responsive data table with paging, selection, batch actions |
71
71
  | ThemePreview | Theme color swatches |
72
- | AssetsPreview | Modal-based asset/file preview with zoom, pan, download |
73
- | Book | Interactive book/flipbook reader with 3D page-flip animation |
72
+ | AssetsPreview | Modal-based asset/file preview with zoom, pan, swipe, area clicking |
73
+ | AssetsPreviewInline | Always-visible (non-modal) asset preview with same feature set |
74
+ | Book | Interactive book/flipbook with 3D page-flip, zoom, pan, areas |
75
+ | BookResponsive | Responsive Book wrapper: auto single/dual-page + inline mode |
74
76
  | Circle | SVG circular progress indicator |
75
77
  | H | Semantic heading (h1-h6) with separate visual/semantic levels |
76
78
  | Separator | Horizontal/vertical separator line |
@@ -2,7 +2,7 @@
2
2
 
3
3
  ## Overview
4
4
 
5
- 42 utility modules for common tasks. Organized by category.
5
+ 43 utility modules for common tasks. Organized by category.
6
6
 
7
7
  ---
8
8
 
@@ -124,6 +124,15 @@ twMerge("px-4 py-2", "px-6"); // => "py-2 px-6"
124
124
 
125
125
  ---
126
126
 
127
+ ## URL
128
+
129
+ | Util | Purpose |
130
+ | --------------- | -------------------------------------------- |
131
+ | `resolveUrl` | Resolve relative URL against base URL |
132
+ | `resolveSrcset` | Resolve all URLs within a srcset string |
133
+
134
+ ---
135
+
127
136
  ## Files
128
137
 
129
138
  | Util | Purpose |
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@marianmeres/stuic",
3
- "version": "3.35.0",
3
+ "version": "3.35.1",
4
4
  "files": [
5
5
  "dist",
6
6
  "!dist/**/*.test.*",