@marianmeres/stuic 2.66.0 → 3.0.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.
- package/README.md +292 -4
- package/dist/README.md +41 -18
- package/dist/actions/popover/README.md +19 -0
- package/dist/actions/popover/index.css +6 -9
- package/dist/actions/popover/popover.svelte.js +2 -2
- package/dist/actions/tooltip/README.md +18 -0
- package/dist/actions/tooltip/index.css +5 -8
- package/dist/actions/tooltip/tooltip.svelte.js +1 -1
- package/dist/components/AlertConfirmPrompt/AlertConfirmPrompt.svelte +9 -10
- package/dist/components/AlertConfirmPrompt/AlertConfirmPrompt.svelte.d.ts +3 -3
- package/dist/components/AlertConfirmPrompt/Current.svelte +15 -17
- package/dist/components/AlertConfirmPrompt/Current.svelte.d.ts +5 -3
- package/dist/components/AlertConfirmPrompt/acp-icons.js +5 -4
- package/dist/components/AlertConfirmPrompt/index.css +62 -0
- package/dist/components/AssetsPreview/AssetsPreview.svelte +92 -73
- package/dist/components/AssetsPreview/AssetsPreview.svelte.d.ts +1 -0
- package/dist/components/AssetsPreview/index.css +59 -0
- package/dist/components/Avatar/Avatar.svelte +32 -18
- package/dist/components/Avatar/Avatar.svelte.d.ts +1 -0
- package/dist/components/Avatar/README.md +166 -0
- package/dist/components/Avatar/index.css +128 -0
- package/dist/components/Backdrop/Backdrop.svelte +8 -2
- package/dist/components/Backdrop/Backdrop.svelte.d.ts +1 -0
- package/dist/components/Backdrop/README.md +71 -6
- package/dist/components/Backdrop/index.css +29 -0
- package/dist/components/Button/Button.svelte +117 -124
- package/dist/components/Button/Button.svelte.d.ts +35 -23
- package/dist/components/Button/README.md +87 -21
- package/dist/components/Button/index.css +473 -9
- package/dist/components/Button/index.d.ts +1 -1
- package/dist/components/Button/index.js +1 -1
- package/dist/components/ButtonGroupRadio/ButtonGroupRadio.svelte +7 -38
- package/dist/components/ButtonGroupRadio/README.md +82 -4
- package/dist/components/ButtonGroupRadio/index.css +152 -14
- package/dist/components/Collapsible/Collapsible.svelte +7 -7
- package/dist/components/Collapsible/Collapsible.svelte.d.ts +2 -2
- package/dist/components/Collapsible/README.md +34 -2
- package/dist/components/Collapsible/index.css +38 -0
- package/dist/components/CommandMenu/CommandMenu.svelte +13 -24
- package/dist/components/CommandMenu/README.md +39 -0
- package/dist/components/CommandMenu/index.css +45 -2
- package/dist/components/DismissibleMessage/DismissibleMessage.svelte +53 -50
- package/dist/components/DismissibleMessage/DismissibleMessage.svelte.d.ts +6 -5
- package/dist/components/DismissibleMessage/README.md +93 -11
- package/dist/components/DismissibleMessage/index.css +122 -8
- package/dist/components/DismissibleMessage/index.d.ts +1 -1
- package/dist/components/DropdownMenu/DropdownMenu.svelte +14 -50
- package/dist/components/DropdownMenu/DropdownMenu.svelte.d.ts +6 -6
- package/dist/components/DropdownMenu/README.md +132 -0
- package/dist/components/DropdownMenu/index.css +231 -27
- package/dist/components/Input/FieldAssets.svelte +8 -5
- package/dist/components/Input/FieldCheckbox.svelte +7 -44
- package/dist/components/Input/FieldFile.svelte +1 -6
- package/dist/components/Input/FieldInput.svelte +1 -1
- package/dist/components/Input/FieldOptions.svelte +41 -38
- package/dist/components/Input/FieldRadios.svelte +7 -16
- package/dist/components/Input/FieldSelect.svelte +1 -1
- package/dist/components/Input/FieldSwitch.svelte +1 -5
- package/dist/components/Input/FieldTextarea.svelte +1 -1
- package/dist/components/Input/README.md +194 -0
- package/dist/components/Input/_internal/FieldRadioInternal.svelte +2 -40
- package/dist/components/Input/_internal/InputWrap.svelte +8 -48
- package/dist/components/Input/index.css +522 -127
- package/dist/components/ListItemButton/ListItemButton.svelte +37 -73
- package/dist/components/ListItemButton/ListItemButton.svelte.d.ts +1 -9
- package/dist/components/ListItemButton/README.md +100 -45
- package/dist/components/ListItemButton/index.css +175 -56
- package/dist/components/ListItemButton/index.d.ts +1 -1
- package/dist/components/ListItemButton/index.js +1 -1
- package/dist/components/Modal/Modal.svelte +2 -8
- package/dist/components/Modal/Modal.svelte.d.ts +1 -0
- package/dist/components/Modal/README.md +29 -0
- package/dist/components/Modal/index.css +36 -0
- package/dist/components/ModalDialog/ModalDialog.svelte +2 -21
- package/dist/components/ModalDialog/README.md +35 -0
- package/dist/components/ModalDialog/index.css +57 -0
- package/dist/components/Notifications/Notifications.svelte +44 -128
- package/dist/components/Notifications/Notifications.svelte.d.ts +9 -17
- package/dist/components/Notifications/README.md +186 -70
- package/dist/components/Notifications/index.css +212 -15
- package/dist/components/Progress/README.md +15 -0
- package/dist/components/Progress/_internal/Bar.svelte +2 -2
- package/dist/components/Progress/index.css +4 -4
- package/dist/components/Skeleton/Skeleton.svelte +3 -2
- package/dist/components/Skeleton/index.css +11 -14
- package/dist/components/Spinner/Spinner.svelte +2 -2
- package/dist/components/Spinner/SpinnerCircle.svelte +1 -1
- package/dist/components/Switch/README.md +15 -0
- package/dist/components/Switch/Switch.svelte +4 -7
- package/dist/components/Switch/Switch.svelte.d.ts +1 -1
- package/dist/components/Switch/SwitchButton.svelte +4 -5
- package/dist/components/Switch/index.css +3 -4
- package/dist/components/TabbedMenu/README.md +26 -21
- package/dist/components/TabbedMenu/TabbedMenu.svelte +5 -5
- package/dist/components/TabbedMenu/index.css +7 -22
- package/dist/components/ThemePreview/README.md +289 -0
- package/dist/components/ThemePreview/ThemePreview.svelte +341 -0
- package/dist/components/ThemePreview/ThemePreview.svelte.d.ts +33 -0
- package/dist/components/ThemePreview/index.css +493 -0
- package/dist/components/ThemePreview/index.d.ts +1 -0
- package/dist/components/ThemePreview/index.js +1 -0
- package/dist/components/TwCheck/TwCheck.svelte +4 -4
- package/dist/components/TwCheck/index.css +3 -2
- package/dist/components/TypeaheadInput/TypeaheadInput.svelte +1 -1
- package/dist/components/X/X.svelte +12 -5
- package/dist/components/X/X.svelte.d.ts +1 -0
- package/dist/icons/index.d.ts +1 -0
- package/dist/icons/index.js +1 -0
- package/dist/index.css +31 -16
- package/dist/index.d.ts +1 -0
- package/dist/index.js +1 -0
- package/dist/themes/blue-orange.css +163 -0
- package/dist/themes/blue-orange.d.ts +6 -0
- package/dist/themes/blue-orange.js +151 -0
- package/dist/themes/cyan-red.css +163 -0
- package/dist/themes/cyan-red.d.ts +6 -0
- package/dist/themes/cyan-red.js +151 -0
- package/dist/themes/cyan-slate.css +163 -0
- package/dist/themes/cyan-slate.d.ts +6 -0
- package/dist/themes/cyan-slate.js +151 -0
- package/dist/themes/emerald-pink.css +163 -0
- package/dist/themes/emerald-pink.d.ts +6 -0
- package/dist/themes/emerald-pink.js +151 -0
- package/dist/themes/fuchsia-emerald.css +163 -0
- package/dist/themes/fuchsia-emerald.d.ts +6 -0
- package/dist/themes/fuchsia-emerald.js +151 -0
- package/dist/themes/gray.css +163 -0
- package/dist/themes/gray.d.ts +6 -0
- package/dist/themes/gray.js +151 -0
- package/dist/themes/indigo-amber.css +163 -0
- package/dist/themes/indigo-amber.d.ts +6 -0
- package/dist/themes/indigo-amber.js +151 -0
- package/dist/themes/neutral.css +163 -0
- package/dist/themes/neutral.d.ts +6 -0
- package/dist/themes/neutral.js +151 -0
- package/dist/themes/pink-emerald.css +163 -0
- package/dist/themes/pink-emerald.d.ts +6 -0
- package/dist/themes/pink-emerald.js +151 -0
- package/dist/themes/purple-yellow.css +163 -0
- package/dist/themes/purple-yellow.d.ts +6 -0
- package/dist/themes/purple-yellow.js +151 -0
- package/dist/themes/rainbow.css +163 -0
- package/dist/themes/rainbow.d.ts +6 -0
- package/dist/themes/rainbow.js +156 -0
- package/dist/themes/red-blue.css +163 -0
- package/dist/themes/red-blue.d.ts +6 -0
- package/dist/themes/red-blue.js +151 -0
- package/dist/themes/red-cyan.css +163 -0
- package/dist/themes/red-cyan.d.ts +6 -0
- package/dist/themes/red-cyan.js +151 -0
- package/dist/themes/rose-teal.css +163 -0
- package/dist/themes/rose-teal.d.ts +6 -0
- package/dist/themes/rose-teal.js +151 -0
- package/dist/themes/sky-amber.css +163 -0
- package/dist/themes/sky-amber.d.ts +6 -0
- package/dist/themes/sky-amber.js +151 -0
- package/dist/themes/slate-cyan.css +163 -0
- package/dist/themes/slate-cyan.d.ts +6 -0
- package/dist/themes/slate-cyan.js +151 -0
- package/dist/themes/tailwind-color-pairs.md +31 -0
- package/dist/themes/teal-rose.css +163 -0
- package/dist/themes/teal-rose.d.ts +6 -0
- package/dist/themes/teal-rose.js +151 -0
- package/dist/themes/violet-lime.css +163 -0
- package/dist/themes/violet-lime.d.ts +6 -0
- package/dist/themes/violet-lime.js +151 -0
- package/dist/utils/design-tokens.d.ts +43 -0
- package/dist/utils/design-tokens.js +100 -0
- package/dist/utils/index.d.ts +1 -0
- package/dist/utils/index.js +1 -0
- package/package.json +22 -2
|
@@ -118,6 +118,35 @@ By default, Modal is:
|
|
|
118
118
|
- **Mobile**: Full screen with 1rem margins from viewport edges
|
|
119
119
|
- **Desktop (md+)**: Centered, max-width 768px, auto height with max 80vh
|
|
120
120
|
|
|
121
|
+
## CSS Variables
|
|
122
|
+
|
|
123
|
+
Override to customize appearance:
|
|
124
|
+
|
|
125
|
+
| Variable | Default | Description |
|
|
126
|
+
|----------|---------|-------------|
|
|
127
|
+
| `--stuic-modal-bg` | `--stuic-color-surface` | Modal background color |
|
|
128
|
+
| `--stuic-modal-text` | `--stuic-color-surface-foreground` | Modal text color |
|
|
129
|
+
| `--stuic-modal-radius` | `--radius-md` | Border radius (desktop only) |
|
|
130
|
+
|
|
131
|
+
### Customization Examples
|
|
132
|
+
|
|
133
|
+
```css
|
|
134
|
+
/* Global override */
|
|
135
|
+
:root {
|
|
136
|
+
--stuic-modal-bg: var(--stuic-color-background);
|
|
137
|
+
--stuic-modal-radius: var(--radius-lg);
|
|
138
|
+
}
|
|
139
|
+
```
|
|
140
|
+
|
|
141
|
+
```svelte
|
|
142
|
+
<!-- Local override -->
|
|
143
|
+
<Modal style="--stuic-modal-bg: var(--stuic-color-muted);">
|
|
144
|
+
Content with muted background
|
|
145
|
+
</Modal>
|
|
146
|
+
```
|
|
147
|
+
|
|
148
|
+
Note: Modal inherits backdrop styling from ModalDialog. See ModalDialog documentation for backdrop customization (`--stuic-modal-dialog-backdrop`).
|
|
149
|
+
|
|
121
150
|
## Relationship to ModalDialog
|
|
122
151
|
|
|
123
152
|
Modal is a higher-level component built on `ModalDialog`. It provides:
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
/* ============================================================================
|
|
2
|
+
MODAL COMPONENT TOKENS
|
|
3
|
+
Override globally: :root { --stuic-modal-radius: 0; }
|
|
4
|
+
Override locally: <Modal style="--stuic-modal-radius: var(--radius-lg);">
|
|
5
|
+
============================================================================ */
|
|
6
|
+
|
|
7
|
+
:root {
|
|
8
|
+
/* Background & text - reference theme tokens */
|
|
9
|
+
--stuic-modal-bg: var(--stuic-color-surface);
|
|
10
|
+
--stuic-modal-text: var(--stuic-color-surface-foreground);
|
|
11
|
+
|
|
12
|
+
/* Border radius (desktop only - mobile is fullscreen) */
|
|
13
|
+
--stuic-modal-radius: var(--radius-md);
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
/* ============================================================================
|
|
17
|
+
BASE STYLES
|
|
18
|
+
============================================================================ */
|
|
19
|
+
|
|
20
|
+
.stuic-modal {
|
|
21
|
+
background: var(--stuic-modal-bg);
|
|
22
|
+
color: var(--stuic-modal-text);
|
|
23
|
+
border-radius: 0; /* Mobile: fullscreen, no radius */
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
@media (min-width: 48rem) {
|
|
27
|
+
/* md breakpoint */
|
|
28
|
+
.stuic-modal {
|
|
29
|
+
border-radius: var(--stuic-modal-radius);
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
/* Thin scrollbar for main content area */
|
|
34
|
+
.stuic-modal .main {
|
|
35
|
+
scrollbar-width: thin;
|
|
36
|
+
}
|
|
@@ -137,7 +137,7 @@
|
|
|
137
137
|
"fixed inset-4 m-auto size-auto",
|
|
138
138
|
"flex justify-center items-center",
|
|
139
139
|
"focus:outline-none focus-visible:outline-none",
|
|
140
|
-
"bg-transparent
|
|
140
|
+
"bg-transparent",
|
|
141
141
|
classDialog
|
|
142
142
|
)}
|
|
143
143
|
onclick={(e) => {
|
|
@@ -181,28 +181,9 @@
|
|
|
181
181
|
onpointerdown={stopPropagation()}
|
|
182
182
|
onclick={stopPropagation()}
|
|
183
183
|
data-type={type}
|
|
184
|
-
class={twMerge(
|
|
185
|
-
`box relative size-full overflow-auto
|
|
186
|
-
text-black dark:text-white bg-white dark:bg-neutral-800`,
|
|
187
|
-
classProp
|
|
188
|
-
)}
|
|
184
|
+
class={twMerge("box relative size-full overflow-auto", classProp)}
|
|
189
185
|
>
|
|
190
186
|
{@render children?.()}
|
|
191
187
|
</div>
|
|
192
188
|
</dialog>
|
|
193
189
|
{/if}
|
|
194
|
-
|
|
195
|
-
<style>
|
|
196
|
-
dialog[open]::backdrop {
|
|
197
|
-
animation: fadeIn 0.15s ease-out;
|
|
198
|
-
}
|
|
199
|
-
|
|
200
|
-
@keyframes fadeIn {
|
|
201
|
-
from {
|
|
202
|
-
opacity: 0;
|
|
203
|
-
}
|
|
204
|
-
to {
|
|
205
|
-
opacity: 1;
|
|
206
|
-
}
|
|
207
|
-
}
|
|
208
|
-
</style>
|
|
@@ -108,6 +108,41 @@ A modal component using the native HTML `<dialog>` element with `showModal()`. P
|
|
|
108
108
|
</script>
|
|
109
109
|
```
|
|
110
110
|
|
|
111
|
+
## CSS Variables
|
|
112
|
+
|
|
113
|
+
### Component Tokens
|
|
114
|
+
|
|
115
|
+
Override to customize appearance:
|
|
116
|
+
|
|
117
|
+
| Variable | Default | Description |
|
|
118
|
+
|----------|---------|-------------|
|
|
119
|
+
| `--stuic-modal-dialog-radius` | `--radius-lg` | Border radius of content box |
|
|
120
|
+
| `--stuic-modal-dialog-transition` | `150ms` | Animation/transition duration |
|
|
121
|
+
| `--stuic-modal-dialog-backdrop` | `rgb(0 0 0 / 0.4)` | Backdrop overlay color |
|
|
122
|
+
| `--stuic-modal-dialog-bg` | `--stuic-color-surface` | Content box background |
|
|
123
|
+
| `--stuic-modal-dialog-text` | `--stuic-color-surface-foreground` | Content box text color |
|
|
124
|
+
| `--stuic-modal-dialog-shadow` | `--shadow-xl` | Content box shadow |
|
|
125
|
+
|
|
126
|
+
### Customization Examples
|
|
127
|
+
|
|
128
|
+
```css
|
|
129
|
+
/* Global override - all dialogs */
|
|
130
|
+
:root {
|
|
131
|
+
--stuic-modal-dialog-radius: 0;
|
|
132
|
+
--stuic-modal-dialog-backdrop: rgb(0 0 0 / 0.7);
|
|
133
|
+
}
|
|
134
|
+
```
|
|
135
|
+
|
|
136
|
+
```svelte
|
|
137
|
+
<!-- Local override - single dialog -->
|
|
138
|
+
<ModalDialog
|
|
139
|
+
bind:this={dialog}
|
|
140
|
+
style="--stuic-modal-dialog-radius: 9999px;"
|
|
141
|
+
>
|
|
142
|
+
Content with pill-shaped radius
|
|
143
|
+
</ModalDialog>
|
|
144
|
+
```
|
|
145
|
+
|
|
111
146
|
## Relationship to Modal
|
|
112
147
|
|
|
113
148
|
`Modal` is a higher-level component built on top of `ModalDialog`.
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
/* ============================================================================
|
|
2
|
+
MODAL DIALOG COMPONENT TOKENS
|
|
3
|
+
Override globally: :root { --stuic-modal-dialog-radius: 0; }
|
|
4
|
+
Override locally: <ModalDialog style="--stuic-modal-dialog-radius: 9999px;">
|
|
5
|
+
============================================================================ */
|
|
6
|
+
|
|
7
|
+
:root {
|
|
8
|
+
/* Core customization */
|
|
9
|
+
--stuic-modal-dialog-radius: var(--radius-lg);
|
|
10
|
+
--stuic-modal-dialog-transition: 150ms;
|
|
11
|
+
|
|
12
|
+
/* Backdrop */
|
|
13
|
+
--stuic-modal-dialog-backdrop: rgb(0 0 0 / 0.4);
|
|
14
|
+
|
|
15
|
+
/* Content box - reference theme tokens */
|
|
16
|
+
--stuic-modal-dialog-bg: var(--stuic-color-surface);
|
|
17
|
+
--stuic-modal-dialog-text: var(--stuic-color-surface-foreground);
|
|
18
|
+
|
|
19
|
+
/* Optional shadow for elevation */
|
|
20
|
+
--stuic-modal-dialog-shadow: var(--shadow-xl);
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
/* ============================================================================
|
|
24
|
+
BACKDROP STYLES
|
|
25
|
+
============================================================================ */
|
|
26
|
+
|
|
27
|
+
.stuic-modal-dialog::backdrop {
|
|
28
|
+
background: var(--stuic-modal-dialog-backdrop);
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
/* ============================================================================
|
|
32
|
+
CONTENT BOX STYLES
|
|
33
|
+
============================================================================ */
|
|
34
|
+
|
|
35
|
+
.stuic-modal-dialog .box {
|
|
36
|
+
background: var(--stuic-modal-dialog-bg);
|
|
37
|
+
color: var(--stuic-modal-dialog-text);
|
|
38
|
+
border-radius: var(--stuic-modal-dialog-radius);
|
|
39
|
+
box-shadow: var(--stuic-modal-dialog-shadow);
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
/* ============================================================================
|
|
43
|
+
ANIMATIONS
|
|
44
|
+
============================================================================ */
|
|
45
|
+
|
|
46
|
+
.stuic-modal-dialog[open]::backdrop {
|
|
47
|
+
animation: stuic-modal-dialog-fadeIn var(--stuic-modal-dialog-transition) ease-out;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
@keyframes stuic-modal-dialog-fadeIn {
|
|
51
|
+
from {
|
|
52
|
+
opacity: 0;
|
|
53
|
+
}
|
|
54
|
+
to {
|
|
55
|
+
opacity: 1;
|
|
56
|
+
}
|
|
57
|
+
}
|
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
<script lang="ts" module>
|
|
2
|
-
import type { TW_COLORS } from "../../types.js";
|
|
3
2
|
import type { NotificationsStack } from "./notifications-stack.svelte.js";
|
|
4
3
|
import { notificationsDefaultIcons } from "./notifications-icons.js";
|
|
5
4
|
|
|
@@ -15,39 +14,34 @@
|
|
|
15
14
|
posXMobile?: NOTIFICATIONS_POSX;
|
|
16
15
|
posY?: NOTIFICATIONS_POSY;
|
|
17
16
|
posYMobile?: NOTIFICATIONS_POSY;
|
|
18
|
-
themeInfo?: TW_COLORS;
|
|
19
|
-
themeError?: TW_COLORS;
|
|
20
|
-
themeWarn?: TW_COLORS;
|
|
21
|
-
themeSuccess?: TW_COLORS;
|
|
22
|
-
noTheme?: boolean;
|
|
23
17
|
noIcons?: boolean;
|
|
18
|
+
noProgress?: boolean;
|
|
19
|
+
noXButton?: boolean;
|
|
20
|
+
forceAsHtml?: boolean;
|
|
21
|
+
ariaCloseLabel?: string;
|
|
22
|
+
duration?: number;
|
|
23
|
+
iconFns?: Partial<Record<keyof typeof notificationsDefaultIcons, CallableFunction>>;
|
|
24
|
+
// Class overrides
|
|
25
|
+
class?: string;
|
|
24
26
|
classWrapY?: string;
|
|
25
27
|
classWrapX?: string;
|
|
26
|
-
class?: string;
|
|
27
28
|
classNotifCount?: string;
|
|
28
29
|
classNotifIcon?: string;
|
|
29
30
|
classNotifContent?: string;
|
|
30
|
-
classNotifButton?: string;
|
|
31
|
-
classNotifButtonX?: string;
|
|
32
|
-
buttonXStrokeWidth?: 0.5 | 1 | 1.5 | 2 | 2.5 | 3 | 3.5 | 4;
|
|
33
31
|
classProgress?: string;
|
|
34
32
|
classProgressBar?: string;
|
|
35
|
-
|
|
36
|
-
ariaCloseLabel?: string;
|
|
37
|
-
duration?: number;
|
|
38
|
-
noProgress?: boolean;
|
|
39
|
-
noXButton?: boolean;
|
|
40
|
-
iconFns?: Partial<Record<keyof typeof notificationsDefaultIcons, CallableFunction>>;
|
|
33
|
+
el?: HTMLDivElement;
|
|
41
34
|
}
|
|
42
35
|
</script>
|
|
43
36
|
|
|
44
37
|
<script lang="ts">
|
|
45
38
|
import { fade } from "svelte/transition";
|
|
46
39
|
import { twMerge } from "../../utils/tw-merge.js";
|
|
40
|
+
import Button from "../Button/Button.svelte";
|
|
47
41
|
import Thc from "../Thc/Thc.svelte";
|
|
48
42
|
import X from "../X/X.svelte";
|
|
49
43
|
import "./index.css";
|
|
50
|
-
import type { Notification
|
|
44
|
+
import type { Notification } from "./notifications-stack.svelte.js";
|
|
51
45
|
import Progress from "../Progress/Progress.svelte";
|
|
52
46
|
|
|
53
47
|
const DEFAULT: {
|
|
@@ -81,33 +75,23 @@
|
|
|
81
75
|
posY = DEFAULT.posY,
|
|
82
76
|
posYMobile = DEFAULT.posYMobile,
|
|
83
77
|
//
|
|
84
|
-
themeInfo = "neutral",
|
|
85
|
-
themeError = "red",
|
|
86
|
-
themeWarn = "yellow",
|
|
87
|
-
themeSuccess = "green",
|
|
88
|
-
// use truthy `noTheme` if manual css-only var customization is needed
|
|
89
|
-
noTheme,
|
|
90
78
|
noIcons,
|
|
79
|
+
noProgress,
|
|
80
|
+
noXButton,
|
|
81
|
+
forceAsHtml,
|
|
82
|
+
ariaCloseLabel = "Close",
|
|
83
|
+
duration = 200,
|
|
84
|
+
iconFns = {},
|
|
91
85
|
//
|
|
86
|
+
class: classNotifBox,
|
|
92
87
|
classWrapY,
|
|
93
88
|
classWrapX,
|
|
94
|
-
class: classNotifBox,
|
|
95
89
|
classNotifCount,
|
|
96
90
|
classNotifIcon,
|
|
97
91
|
classNotifContent,
|
|
98
|
-
classNotifButton,
|
|
99
|
-
classNotifButtonX,
|
|
100
|
-
buttonXStrokeWidth = 3,
|
|
101
|
-
//
|
|
102
92
|
classProgress,
|
|
103
93
|
classProgressBar,
|
|
104
|
-
|
|
105
|
-
forceAsHtml,
|
|
106
|
-
ariaCloseLabel = "Close",
|
|
107
|
-
duration = 200,
|
|
108
|
-
noProgress,
|
|
109
|
-
noXButton,
|
|
110
|
-
iconFns = {},
|
|
94
|
+
el = $bindable(),
|
|
111
95
|
}: Props = $props();
|
|
112
96
|
|
|
113
97
|
let popoverEl: HTMLDivElement | null = $state(null);
|
|
@@ -128,79 +112,6 @@
|
|
|
128
112
|
return (_iconFns?.[n.type] as any)?.();
|
|
129
113
|
};
|
|
130
114
|
|
|
131
|
-
const _classWrapX = `
|
|
132
|
-
fixed z-50 flex flex-row inset-0
|
|
133
|
-
pointer-events-none bg-transparent`;
|
|
134
|
-
|
|
135
|
-
const _classWrapY = `
|
|
136
|
-
p-4 space-y-4
|
|
137
|
-
flex flex-col inset-0
|
|
138
|
-
w-full sm:w-auto
|
|
139
|
-
pointer-events-none bg-transparent`;
|
|
140
|
-
|
|
141
|
-
const _classNotifBox = `
|
|
142
|
-
relative flex
|
|
143
|
-
pointer-events-auto
|
|
144
|
-
w-full sm:w-sm max-w-full sm:max-w-sm
|
|
145
|
-
rounded-lg
|
|
146
|
-
shadow-lg
|
|
147
|
-
border border-notif-border dark:border-notif-border-dark
|
|
148
|
-
bg-notif-bg text-notif-text
|
|
149
|
-
dark:bg-notif-bg-dark dark:text-notif-text-dark`;
|
|
150
|
-
|
|
151
|
-
const _classNotifCount = `
|
|
152
|
-
absolute -top-2 -right-2
|
|
153
|
-
w-auto h-auto
|
|
154
|
-
flex items-center justify-center
|
|
155
|
-
px-2 py-1 rounded-full
|
|
156
|
-
leading-none text-xs
|
|
157
|
-
bg-neutral-950 text-neutral-50`;
|
|
158
|
-
|
|
159
|
-
const _classNotifIcon = `
|
|
160
|
-
flex items-center justify-center
|
|
161
|
-
pt-4 pr-0 pb-4 pl-4
|
|
162
|
-
text-neutral-200`;
|
|
163
|
-
|
|
164
|
-
const _classNotifContent = `
|
|
165
|
-
flex-1
|
|
166
|
-
flex flex-col justify-center
|
|
167
|
-
tracking-tight
|
|
168
|
-
pl-4 pr-1 py-3`;
|
|
169
|
-
|
|
170
|
-
const _classNotifButton = `
|
|
171
|
-
flex flex-col items-center justify-center
|
|
172
|
-
leading-none
|
|
173
|
-
px-3
|
|
174
|
-
hover:bg-neutral-950/10
|
|
175
|
-
focus-visible:bg-neutral-950/10 focus-visible:outline-none focus-visible:ring-0
|
|
176
|
-
group
|
|
177
|
-
rounded-tr-md rounded-br-md`;
|
|
178
|
-
|
|
179
|
-
const _classNotifButtonX = `opacity-75 group-hover:opacity-100`;
|
|
180
|
-
|
|
181
|
-
const _classProgress = `absolute inset-0 size-full bg-transparent rounded-tl-md rounded-bl-md`;
|
|
182
|
-
const _classProgressBar = `bg-white/10 dark:bg-white/10 size-full rounded-tl-md rounded-bl-md`;
|
|
183
|
-
|
|
184
|
-
const _buildTheme = (type: NotificationType) => {
|
|
185
|
-
if (noTheme) return "";
|
|
186
|
-
let theme =
|
|
187
|
-
{
|
|
188
|
-
info: themeInfo,
|
|
189
|
-
error: themeError,
|
|
190
|
-
success: themeSuccess,
|
|
191
|
-
warn: themeWarn,
|
|
192
|
-
}[type] || "info";
|
|
193
|
-
return [
|
|
194
|
-
`--color-notif-bg: var(--color-bg-${type}, var(--color-${theme}-700));`,
|
|
195
|
-
`--color-notif-text: var(--color-text-${type}, var(--color-${theme}-50));`,
|
|
196
|
-
`--color-notif-border: var(--color-border-${type}, var(--color-${theme}-800));`,
|
|
197
|
-
//
|
|
198
|
-
`--color-notif-bg-dark: var(--color-bg-dark-${type}, var(--color-${theme}-800));`,
|
|
199
|
-
`--color-notif-text-dark: var(--color-text-dark-${type}, var(--color-${theme}-200));`,
|
|
200
|
-
`--color-notif-border-dark: var(--color-border-dark-${type}, var(--color-${theme}-700));`,
|
|
201
|
-
].join("");
|
|
202
|
-
};
|
|
203
|
-
|
|
204
115
|
// Manage popover visibility based on notifications
|
|
205
116
|
$effect(() => {
|
|
206
117
|
if (!popoverEl) return;
|
|
@@ -227,39 +138,48 @@
|
|
|
227
138
|
>
|
|
228
139
|
<div
|
|
229
140
|
class={twMerge(
|
|
230
|
-
"stuic-notifs
|
|
231
|
-
_classWrapX,
|
|
141
|
+
"stuic-notifs fixed z-50 flex flex-row inset-0 pointer-events-none bg-transparent",
|
|
232
142
|
XMAP[x],
|
|
233
143
|
XMAP_M[xMobile],
|
|
234
144
|
classWrapX
|
|
235
145
|
)}
|
|
236
146
|
>
|
|
237
|
-
<div
|
|
147
|
+
<div
|
|
148
|
+
class={twMerge(
|
|
149
|
+
"flex flex-col inset-0 w-full sm:w-auto pointer-events-none bg-transparent",
|
|
150
|
+
"p-4",
|
|
151
|
+
YMAP_M[yMobile],
|
|
152
|
+
YMAP[y],
|
|
153
|
+
classWrapY
|
|
154
|
+
)}
|
|
155
|
+
style="gap: var(--stuic-notification-gap);"
|
|
156
|
+
>
|
|
238
157
|
{#each notifications.stack as n (n.id)}
|
|
239
158
|
{@const iconHtml = maybeIcon(n)}
|
|
240
159
|
{@const showXButton = !noXButton || n.ttl > 1000}
|
|
241
160
|
<div
|
|
242
|
-
|
|
161
|
+
bind:this={el}
|
|
162
|
+
class={twMerge("stuic-notification", classNotifBox)}
|
|
163
|
+
data-type={n.type}
|
|
243
164
|
transition:fade|global={{ duration }}
|
|
244
165
|
role="alert"
|
|
245
|
-
style={_buildTheme(n.type)}
|
|
246
166
|
>
|
|
247
167
|
{#if n.ttl && !noProgress}
|
|
248
168
|
<Progress
|
|
249
169
|
progress={100 - n._ttlProgress * 100}
|
|
250
|
-
class={twMerge(
|
|
251
|
-
classBar={twMerge(
|
|
170
|
+
class={twMerge("progress", classProgress)}
|
|
171
|
+
classBar={twMerge("progress-bar", classProgressBar)}
|
|
252
172
|
styleBar="transition-duration: {notifications.options.disposeInterval}ms;"
|
|
253
173
|
/>
|
|
254
174
|
{/if}
|
|
255
175
|
|
|
256
176
|
{#if n.count > 1}
|
|
257
|
-
<div class={twMerge("count",
|
|
177
|
+
<div class={twMerge("count", classNotifCount)}>
|
|
258
178
|
{n.count}
|
|
259
179
|
</div>
|
|
260
180
|
{/if}
|
|
261
181
|
{#if !noIcons && iconHtml}
|
|
262
|
-
<div class={twMerge("icon",
|
|
182
|
+
<div class={twMerge("icon hidden! sm:block!", classNotifIcon)}>
|
|
263
183
|
{@html iconHtml}
|
|
264
184
|
</div>
|
|
265
185
|
{/if}
|
|
@@ -267,9 +187,8 @@
|
|
|
267
187
|
<div
|
|
268
188
|
class={twMerge(
|
|
269
189
|
"content",
|
|
270
|
-
|
|
271
|
-
classNotifContent
|
|
272
|
-
!showXButton && "pr-4"
|
|
190
|
+
!showXButton && "no-close-button",
|
|
191
|
+
classNotifContent
|
|
273
192
|
)}
|
|
274
193
|
>
|
|
275
194
|
<Thc
|
|
@@ -281,9 +200,9 @@
|
|
|
281
200
|
</div>
|
|
282
201
|
|
|
283
202
|
{#if showXButton}
|
|
284
|
-
<
|
|
285
|
-
|
|
286
|
-
class=
|
|
203
|
+
<Button
|
|
204
|
+
unstyled
|
|
205
|
+
class="close-button"
|
|
287
206
|
aria-label={ariaCloseLabel}
|
|
288
207
|
onclick={(e) => {
|
|
289
208
|
e.preventDefault();
|
|
@@ -292,11 +211,8 @@
|
|
|
292
211
|
notifications.removeById(n.id);
|
|
293
212
|
}}
|
|
294
213
|
>
|
|
295
|
-
<X
|
|
296
|
-
|
|
297
|
-
strokeWidth={buttonXStrokeWidth}
|
|
298
|
-
/>
|
|
299
|
-
</button>
|
|
214
|
+
<X />
|
|
215
|
+
</Button>
|
|
300
216
|
{/if}
|
|
301
217
|
</div>
|
|
302
218
|
{/each}
|
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
import type { TW_COLORS } from "../../types.js";
|
|
2
1
|
import type { NotificationsStack } from "./notifications-stack.svelte.js";
|
|
3
2
|
import { notificationsDefaultIcons } from "./notifications-icons.js";
|
|
4
3
|
declare const X_POSITIONS: readonly ["left", "center", "right"];
|
|
@@ -11,31 +10,24 @@ export interface Props {
|
|
|
11
10
|
posXMobile?: NOTIFICATIONS_POSX;
|
|
12
11
|
posY?: NOTIFICATIONS_POSY;
|
|
13
12
|
posYMobile?: NOTIFICATIONS_POSY;
|
|
14
|
-
themeInfo?: TW_COLORS;
|
|
15
|
-
themeError?: TW_COLORS;
|
|
16
|
-
themeWarn?: TW_COLORS;
|
|
17
|
-
themeSuccess?: TW_COLORS;
|
|
18
|
-
noTheme?: boolean;
|
|
19
13
|
noIcons?: boolean;
|
|
14
|
+
noProgress?: boolean;
|
|
15
|
+
noXButton?: boolean;
|
|
16
|
+
forceAsHtml?: boolean;
|
|
17
|
+
ariaCloseLabel?: string;
|
|
18
|
+
duration?: number;
|
|
19
|
+
iconFns?: Partial<Record<keyof typeof notificationsDefaultIcons, CallableFunction>>;
|
|
20
|
+
class?: string;
|
|
20
21
|
classWrapY?: string;
|
|
21
22
|
classWrapX?: string;
|
|
22
|
-
class?: string;
|
|
23
23
|
classNotifCount?: string;
|
|
24
24
|
classNotifIcon?: string;
|
|
25
25
|
classNotifContent?: string;
|
|
26
|
-
classNotifButton?: string;
|
|
27
|
-
classNotifButtonX?: string;
|
|
28
|
-
buttonXStrokeWidth?: 0.5 | 1 | 1.5 | 2 | 2.5 | 3 | 3.5 | 4;
|
|
29
26
|
classProgress?: string;
|
|
30
27
|
classProgressBar?: string;
|
|
31
|
-
|
|
32
|
-
ariaCloseLabel?: string;
|
|
33
|
-
duration?: number;
|
|
34
|
-
noProgress?: boolean;
|
|
35
|
-
noXButton?: boolean;
|
|
36
|
-
iconFns?: Partial<Record<keyof typeof notificationsDefaultIcons, CallableFunction>>;
|
|
28
|
+
el?: HTMLDivElement;
|
|
37
29
|
}
|
|
38
30
|
import "./index.css";
|
|
39
|
-
declare const Notifications: import("svelte").Component<Props, {}, "">;
|
|
31
|
+
declare const Notifications: import("svelte").Component<Props, {}, "el">;
|
|
40
32
|
type Notifications = ReturnType<typeof Notifications>;
|
|
41
33
|
export default Notifications;
|