@marianmeres/stuic 2.5.0 → 2.6.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.
@@ -0,0 +1,145 @@
1
+ # Popover Action
2
+
3
+ A Svelte action that displays an anchored popover using CSS Anchor Positioning, with fallback to a centered modal when not supported.
4
+
5
+ ## Options
6
+
7
+ | Option | Type | Default | Description |
8
+ |--------|------|---------|-------------|
9
+ | `enabled` | `boolean` | `true` | Enable/disable popover |
10
+ | `content` | `THC \| null` | - | Popover content (string, HTML, component, or snippet) |
11
+ | `position` | `PopoverPosition` | `"bottom"` | Placement relative to anchor |
12
+ | `trigger` | `"click" \| "hover"` | `"click"` | Trigger mode |
13
+ | `showDelay` | `number` | `100` | Delay before showing (ms) |
14
+ | `hideDelay` | `number` | `200` | Delay before hiding (ms) |
15
+ | `class` | `string` | - | Custom CSS for popover container |
16
+ | `offset` | `string` | `"0.25rem"` | Margin from anchor (CSS value) |
17
+ | `closeOthers` | `boolean` | `false` | Close other open popovers |
18
+ | `closeOnClickOutside` | `boolean` | `true` | Close on outside click (click trigger) |
19
+ | `closeOnEscape` | `boolean` | `true` | Close on Escape key |
20
+ | `showBackdrop` | `boolean` | `true` | Show backdrop in fallback mode |
21
+ | `forceFallback` | `boolean` | `false` | Force centered modal mode |
22
+ | `onShow` | `() => void` | - | Callback when popover opens |
23
+ | `onHide` | `() => void` | - | Callback when popover closes |
24
+
25
+ ## Positions
26
+
27
+ ```
28
+ top-left top top-right
29
+ top-span-left top-span-right
30
+
31
+ left [anchor] right
32
+
33
+ bottom-span-left bottom-span-right
34
+ bottom-left bottom bottom-right
35
+ ```
36
+
37
+ ## Usage
38
+
39
+ ### Click Trigger (Default)
40
+
41
+ ```svelte
42
+ <script lang="ts">
43
+ import { popover } from 'stuic';
44
+ </script>
45
+
46
+ <button use:popover={() => ({
47
+ content: "Hello! This is a popover."
48
+ })}>
49
+ Click Me
50
+ </button>
51
+ ```
52
+
53
+ ### Hover Trigger
54
+
55
+ ```svelte
56
+ <button use:popover={() => ({
57
+ content: "Hover content here",
58
+ trigger: "hover",
59
+ position: "top"
60
+ })}>
61
+ Hover Me
62
+ </button>
63
+ ```
64
+
65
+ ### HTML Content
66
+
67
+ ```svelte
68
+ <button use:popover={() => ({
69
+ content: { html: "<strong>Bold</strong> and <em>italic</em>" },
70
+ position: "right"
71
+ })}>
72
+ With HTML
73
+ </button>
74
+ ```
75
+
76
+ ### Component Content
77
+
78
+ ```svelte
79
+ <script lang="ts">
80
+ import MyPopoverContent from './MyPopoverContent.svelte';
81
+ </script>
82
+
83
+ <button use:popover={() => ({
84
+ content: { component: MyPopoverContent, props: { data: someData } }
85
+ })}>
86
+ With Component
87
+ </button>
88
+ ```
89
+
90
+ ### Dynamic Content
91
+
92
+ ```svelte
93
+ <script lang="ts">
94
+ let count = $state(0);
95
+ </script>
96
+
97
+ <button use:popover={() => ({
98
+ content: `Count: ${count}`,
99
+ position: "top"
100
+ })}>
101
+ Count: {count}
102
+ </button>
103
+ ```
104
+
105
+ ### With Callbacks
106
+
107
+ ```svelte
108
+ <button use:popover={() => ({
109
+ content: "Tracked popover",
110
+ onShow: () => console.log('Opened'),
111
+ onHide: () => console.log('Closed')
112
+ })}>
113
+ Tracked
114
+ </button>
115
+ ```
116
+
117
+ ### Close Others
118
+
119
+ ```svelte
120
+ <button use:popover={() => ({
121
+ content: "Only one at a time",
122
+ closeOthers: true
123
+ })}>
124
+ Exclusive
125
+ </button>
126
+ ```
127
+
128
+ ## Helper Function
129
+
130
+ ```ts
131
+ import { isPopoverSupported } from 'stuic';
132
+
133
+ if (isPopoverSupported()) {
134
+ // CSS Anchor Positioning is available
135
+ } else {
136
+ // Will use fallback centered modal
137
+ }
138
+ ```
139
+
140
+ ## Notes
141
+
142
+ - Uses CSS Anchor Positioning API when available
143
+ - Falls back to centered modal overlay when not supported
144
+ - For hover mode, popover persists when cursor moves to the popover itself
145
+ - ARIA attributes are automatically managed (`aria-haspopup`, `aria-expanded`, `aria-controls`)
@@ -0,0 +1,132 @@
1
+ # Tooltip Action
2
+
3
+ A Svelte action that displays a tooltip anchored to an element using CSS Anchor Positioning. Only works in browsers that support CSS Anchor Positioning.
4
+
5
+ ## Options
6
+
7
+ | Option | Type | Default | Description |
8
+ |--------|------|---------|-------------|
9
+ | `enabled` | `boolean` | `true` | Enable/disable tooltip |
10
+ | `content` | `string \| null` | - | Tooltip text (falls back to `aria-label`) |
11
+ | `position` | `TooltipPosition` | `"top"` | Placement relative to anchor |
12
+ | `class` | `string` | - | Custom CSS for tooltip |
13
+ | `onShow` | `() => void` | - | Callback when tooltip shows |
14
+ | `onHide` | `() => void` | - | Callback when tooltip hides |
15
+
16
+ ## Positions
17
+
18
+ ```
19
+ top-left top top-right
20
+
21
+ left [anchor] right
22
+
23
+ bottom-left bottom bottom-right
24
+ ```
25
+
26
+ ## Usage
27
+
28
+ ### Basic Tooltip
29
+
30
+ ```svelte
31
+ <script lang="ts">
32
+ import { tooltip } from 'stuic';
33
+ </script>
34
+
35
+ <button use:tooltip={() => ({ content: "Save your changes" })}>
36
+ Save
37
+ </button>
38
+ ```
39
+
40
+ ### Using aria-label
41
+
42
+ ```svelte
43
+ <!-- Content is taken from aria-label when not specified -->
44
+ <button
45
+ aria-label="Delete item"
46
+ use:tooltip
47
+ >
48
+ Delete
49
+ </button>
50
+ ```
51
+
52
+ ### Different Positions
53
+
54
+ ```svelte
55
+ <button use:tooltip={() => ({ content: "Top", position: "top" })}>
56
+ Top
57
+ </button>
58
+
59
+ <button use:tooltip={() => ({ content: "Bottom", position: "bottom" })}>
60
+ Bottom
61
+ </button>
62
+
63
+ <button use:tooltip={() => ({ content: "Left", position: "left" })}>
64
+ Left
65
+ </button>
66
+
67
+ <button use:tooltip={() => ({ content: "Right", position: "right" })}>
68
+ Right
69
+ </button>
70
+ ```
71
+
72
+ ### Custom Styling
73
+
74
+ ```svelte
75
+ <button use:tooltip={() => ({
76
+ content: "Custom styled tooltip",
77
+ class: "bg-blue-600 text-white"
78
+ })}>
79
+ Styled
80
+ </button>
81
+ ```
82
+
83
+ ### Conditional Tooltip
84
+
85
+ ```svelte
86
+ <script lang="ts">
87
+ let showTooltip = $state(true);
88
+ </script>
89
+
90
+ <button use:tooltip={() => ({
91
+ content: "Conditional tooltip",
92
+ enabled: showTooltip
93
+ })}>
94
+ Conditional
95
+ </button>
96
+ ```
97
+
98
+ ### With Callbacks
99
+
100
+ ```svelte
101
+ <button use:tooltip={() => ({
102
+ content: "Tracked tooltip",
103
+ onShow: () => console.log('Tooltip shown'),
104
+ onHide: () => console.log('Tooltip hidden')
105
+ })}>
106
+ Tracked
107
+ </button>
108
+ ```
109
+
110
+ ## Helper Function
111
+
112
+ ```ts
113
+ import { isTooltipSupported } from 'stuic';
114
+
115
+ if (isTooltipSupported()) {
116
+ // CSS Anchor Positioning is available
117
+ } else {
118
+ // Tooltip will not work
119
+ }
120
+ ```
121
+
122
+ ## Notes
123
+
124
+ - Requires CSS Anchor Positioning support (no fallback)
125
+ - Shows on hover or focus with 200ms delay
126
+ - Tooltip persists when hovering over it
127
+ - ARIA attributes are automatically managed (`aria-describedby`, `aria-expanded`)
128
+ - Maximum width is 16rem (256px) by default
129
+
130
+ ## Browser Support
131
+
132
+ Check [Can I Use - CSS Anchor Positioning](https://caniuse.com/css-anchor-positioning) for current browser support. As of 2025, supported in Chrome 125+ and Edge 125+.
@@ -0,0 +1,139 @@
1
+ # AlertConfirmPrompt
2
+
3
+ A modern, customizable replacement for native browser `alert()`, `confirm()`, and `prompt()` dialogs. Manages a FIFO queue of dialogs with visual variants and flexible content rendering.
4
+
5
+ ## Props
6
+
7
+ | Prop | Type | Default | Description |
8
+ |------|------|---------|-------------|
9
+ | `acp` | `AlertConfirmPromptStack` | - | Stack instance managing the dialog queue |
10
+ | `forceAsHtml` | `boolean` | `false` | Render all content as HTML |
11
+ | `class` | `string` | - | CSS classes for the modal dialog |
12
+ | `classWrap` | `string` | - | CSS for outer wrapper |
13
+ | `classIconBox` | `string` | - | CSS for icon container |
14
+ | `classTitle` | `string` | - | CSS for title text |
15
+ | `classContent` | `string` | - | CSS for content area |
16
+ | `classInput` | `string` | - | CSS for prompt input field |
17
+ | `classButton` | `string` | - | CSS for all buttons |
18
+ | `classButtonPrimary` | `string` | - | CSS for OK button |
19
+ | `classButtonCancel` | `string` | - | CSS for Cancel button |
20
+ | `defaultIcons` | `Record<variant, () => string>` | - | Custom icon functions per variant |
21
+
22
+ ## AlertConfirmPromptStack API
23
+
24
+ ### Constructor Options
25
+
26
+ | Option | Type | Default | Description |
27
+ |--------|------|---------|-------------|
28
+ | `labelOk` | `THC` | `"OK"` | Default OK button label |
29
+ | `labelCancel` | `THC` | `"Cancel"` | Default Cancel button label |
30
+ | `iconFn` | `(() => string) \| boolean` | `true` | Icon function or `true` for default icons |
31
+
32
+ ### Methods
33
+
34
+ - `alert(options)` - Show an alert dialog
35
+ - `confirm(onOk, options)` - Show a confirm dialog with callback
36
+ - `prompt(onOk, options)` - Show a prompt dialog with input field
37
+ - `shift()` - Remove current dialog from queue
38
+ - `reset()` - Clear all dialogs
39
+
40
+ ### Dialog Options
41
+
42
+ | Option | Type | Description |
43
+ |--------|------|-------------|
44
+ | `title` | `THC` | Dialog title |
45
+ | `content` | `THC` | Dialog message/content |
46
+ | `variant` | `"info" \| "success" \| "warn" \| "error"` | Visual style |
47
+ | `value` | `any` | Initial value for prompt |
48
+ | `labelOk` | `THC` | Custom OK button label |
49
+ | `labelCancel` | `THC` | Custom Cancel button label |
50
+ | `labelCustom` | `THC` | Optional third button label |
51
+ | `onCustom` | `(value) => void` | Custom button callback |
52
+
53
+ ## Usage
54
+
55
+ ### Basic Setup
56
+
57
+ ```svelte
58
+ <script lang="ts">
59
+ import { AlertConfirmPrompt, AlertConfirmPromptStack } from 'stuic';
60
+
61
+ const acp = new AlertConfirmPromptStack();
62
+ </script>
63
+
64
+ <AlertConfirmPrompt {acp} />
65
+ ```
66
+
67
+ ### Alert
68
+
69
+ ```svelte
70
+ <script lang="ts">
71
+ // Simple alert
72
+ acp.alert({ title: 'Notice', content: 'Operation completed!' });
73
+
74
+ // Alert with variant
75
+ acp.alert({
76
+ title: 'Error',
77
+ content: 'Something went wrong',
78
+ variant: 'error'
79
+ });
80
+ </script>
81
+ ```
82
+
83
+ ### Confirm
84
+
85
+ ```svelte
86
+ <script lang="ts">
87
+ acp.confirm(
88
+ () => {
89
+ console.log('User confirmed!');
90
+ acp.shift();
91
+ },
92
+ {
93
+ title: 'Delete Item?',
94
+ content: 'This action cannot be undone.',
95
+ variant: 'warn'
96
+ }
97
+ );
98
+ </script>
99
+ ```
100
+
101
+ ### Prompt
102
+
103
+ ```svelte
104
+ <script lang="ts">
105
+ acp.prompt(
106
+ (value) => {
107
+ console.log('User entered:', value);
108
+ acp.shift();
109
+ },
110
+ {
111
+ title: 'Enter Name',
112
+ content: 'Please provide your username',
113
+ value: 'default_user'
114
+ }
115
+ );
116
+ </script>
117
+ ```
118
+
119
+ ### Promise-based API
120
+
121
+ ```svelte
122
+ <script lang="ts">
123
+ import { createAlert, createConfirm, createPrompt } from 'stuic';
124
+
125
+ const alert = createAlert(acp);
126
+ const confirm = createConfirm(acp);
127
+ const prompt = createPrompt(acp);
128
+
129
+ // Use like native dialogs
130
+ await alert('Hello!');
131
+
132
+ if (await confirm('Are you sure?')) {
133
+ const name = await prompt('Enter name:', 'Anonymous');
134
+ if (name !== null) {
135
+ console.log('Name:', name);
136
+ }
137
+ }
138
+ </script>
139
+ ```
@@ -0,0 +1,42 @@
1
+ # AnimatedEllipsis
2
+
3
+ An animated loading indicator displaying three dots that fade in sequentially to create a pulsing ellipsis effect.
4
+
5
+ ## Props
6
+
7
+ | Prop | Type | Default | Description |
8
+ |------|------|---------|-------------|
9
+ | `class` | `string` | - | CSS classes for the wrapper span |
10
+ | `enabled` | `boolean` | `true` | When `false`, all dots are visible (no animation) |
11
+
12
+ ## Usage
13
+
14
+ ### Basic
15
+
16
+ ```svelte
17
+ <script lang="ts">
18
+ import { AnimatedEllipsis } from 'stuic';
19
+ </script>
20
+
21
+ <span>Loading<AnimatedEllipsis /></span>
22
+ ```
23
+
24
+ ### Controlled Animation
25
+
26
+ ```svelte
27
+ <script lang="ts">
28
+ import { AnimatedEllipsis } from 'stuic';
29
+
30
+ let isLoading = $state(true);
31
+ </script>
32
+
33
+ <span>
34
+ Processing<AnimatedEllipsis enabled={isLoading} />
35
+ </span>
36
+ ```
37
+
38
+ ### With Custom Styling
39
+
40
+ ```svelte
41
+ <AnimatedEllipsis class="text-blue-500 font-bold" />
42
+ ```
@@ -0,0 +1,99 @@
1
+ # AppShell
2
+
3
+ A complete application layout shell with flexible regions: rail, header, sidebars, main content area with page header/footer, and footer.
4
+
5
+ ## Props
6
+
7
+ | Prop | Type | Default | Description |
8
+ |------|------|---------|-------------|
9
+ | `id` | `string` | `"shell"` | Shell element ID |
10
+ | `scrollbarGutter` | `"auto" \| "stable" \| "both-edges"` | `"auto"` | Scrollbar gutter behavior |
11
+ | `pageFlexGrow` | `0-5` | `3` | Flex grow ratio for main page area |
12
+ | `class` | `string` | - | CSS for shell container |
13
+ | `railClass` | `string` | - | CSS for rail (vertical sidebar) |
14
+ | `headerClass` | `string` | - | CSS for top header |
15
+ | `sidebarLeftClass` | `string` | - | CSS for left sidebar |
16
+ | `pageClass` | `string` | - | CSS for page container |
17
+ | `pageHeaderClass` | `string` | - | CSS for page header |
18
+ | `pageMainClass` | `string` | - | CSS for main content |
19
+ | `pageFooterClass` | `string` | - | CSS for page footer |
20
+ | `sidebarRightClass` | `string` | - | CSS for right sidebar |
21
+ | `footerClass` | `string` | - | CSS for bottom footer |
22
+
23
+ ## Snippets
24
+
25
+ | Snippet | Description |
26
+ |---------|-------------|
27
+ | `rail` | Narrow vertical sidebar (icon navigation) |
28
+ | `header` | Top header bar |
29
+ | `sidebarLeft` | Left sidebar content |
30
+ | `pageHeader` | Header within main page area |
31
+ | `children` | Main page content |
32
+ | `pageFooter` | Footer within main page area |
33
+ | `sidebarRight` | Right sidebar content |
34
+ | `footer` | Bottom footer bar |
35
+
36
+ ## Bindable Elements
37
+
38
+ All regions expose bindable element refs: `elShell`, `elRail`, `elHeader`, `elSidebarLeft`, `elPage`, `elPageHeader`, `elPageMain`, `elPageFooter`, `elSidebarRight`, `elFooter`.
39
+
40
+ ## Usage
41
+
42
+ ### Basic Layout
43
+
44
+ ```svelte
45
+ <script lang="ts">
46
+ import { AppShell, appShellSetHtmlBodyHeight } from 'stuic';
47
+ import { onMount } from 'svelte';
48
+
49
+ onMount(appShellSetHtmlBodyHeight);
50
+ </script>
51
+
52
+ <AppShell>
53
+ {#snippet header()}
54
+ <nav class="p-4 border-b">My App</nav>
55
+ {/snippet}
56
+
57
+ {#snippet sidebarLeft()}
58
+ <aside class="w-64 p-4 border-r">Navigation</aside>
59
+ {/snippet}
60
+
61
+ <main class="p-4">
62
+ Main content goes here
63
+ </main>
64
+
65
+ {#snippet footer()}
66
+ <footer class="p-4 border-t">Footer</footer>
67
+ {/snippet}
68
+ </AppShell>
69
+ ```
70
+
71
+ ### With Rail Navigation
72
+
73
+ ```svelte
74
+ <AppShell pageFlexGrow={3}>
75
+ {#snippet rail()}
76
+ <div class="w-16 h-full bg-gray-900 flex flex-col items-center py-4">
77
+ <button>Icon 1</button>
78
+ <button>Icon 2</button>
79
+ </div>
80
+ {/snippet}
81
+
82
+ {#snippet sidebarLeft()}
83
+ <nav class="w-64">Expanded menu</nav>
84
+ {/snippet}
85
+
86
+ Content area
87
+ </AppShell>
88
+ ```
89
+
90
+ ## Helper Function
91
+
92
+ ```ts
93
+ import { appShellSetHtmlBodyHeight } from 'stuic';
94
+ import { onMount } from 'svelte';
95
+
96
+ // Sets body height to 100vh with overflow hidden
97
+ // Returns cleanup function automatically
98
+ onMount(appShellSetHtmlBodyHeight);
99
+ ```
@@ -0,0 +1,81 @@
1
+ # Backdrop
2
+
3
+ A semi-transparent overlay with focus trap and body scroll locking. Commonly used as the background layer for modals and drawers.
4
+
5
+ ## Props
6
+
7
+ | Prop | Type | Default | Description |
8
+ |------|------|---------|-------------|
9
+ | `visible` | `boolean` | `false` | Controls backdrop visibility (bindable) |
10
+ | `focusTrap` | `boolean \| FocusTrapOptions` | `true` | Enable focus trapping within backdrop |
11
+ | `fadeInDuration` | `number` | `50` | Fade in transition duration (ms) |
12
+ | `fadeOutDuration` | `number` | `150` | Fade out transition duration (ms) |
13
+ | `transitionEnabled` | `boolean` | `true` | Enable/disable transitions |
14
+ | `onEscape` | `() => void` | - | Callback when Escape key is pressed |
15
+ | `noScrollLock` | `boolean` | `false` | Disable body scroll locking |
16
+ | `el` | `HTMLDivElement` | - | Element reference (bindable) |
17
+ | `class` | `string` | - | CSS classes for backdrop |
18
+
19
+ ## Methods
20
+
21
+ | Method | Description |
22
+ |--------|-------------|
23
+ | `open(opener?)` | Show backdrop, optionally track opener element |
24
+ | `close()` | Hide backdrop |
25
+ | `setOpener(el)` | Set element to refocus when closed |
26
+ | `visibility()` | Returns object with `visible` getter |
27
+
28
+ ## Usage
29
+
30
+ ### Basic Backdrop
31
+
32
+ ```svelte
33
+ <script lang="ts">
34
+ import { Backdrop } from 'stuic';
35
+
36
+ let visible = $state(false);
37
+ </script>
38
+
39
+ <button onclick={() => visible = true}>Open</button>
40
+
41
+ <Backdrop
42
+ bind:visible
43
+ onEscape={() => visible = false}
44
+ class="bg-black/50"
45
+ >
46
+ <div class="m-auto p-8 bg-white rounded">
47
+ Modal content
48
+ <button onclick={() => visible = false}>Close</button>
49
+ </div>
50
+ </Backdrop>
51
+ ```
52
+
53
+ ### With Component Methods
54
+
55
+ ```svelte
56
+ <script lang="ts">
57
+ import { Backdrop } from 'stuic';
58
+
59
+ let backdrop: Backdrop;
60
+ </script>
61
+
62
+ <button onclick={(e) => backdrop.open(e)}>Open</button>
63
+
64
+ <Backdrop
65
+ bind:this={backdrop}
66
+ onEscape={() => backdrop.close()}
67
+ class="bg-black/50"
68
+ >
69
+ <div class="m-auto p-8 bg-white rounded">
70
+ Content here
71
+ </div>
72
+ </Backdrop>
73
+ ```
74
+
75
+ ### Without Scroll Lock
76
+
77
+ ```svelte
78
+ <Backdrop bind:visible noScrollLock class="bg-black/25">
79
+ <div>Overlay content - page still scrollable</div>
80
+ </Backdrop>
81
+ ```