@turnipxenon/pineapple 2.4.13 → 2.4.15
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/.idea/discord.xml +1 -1
- package/.idea/workspace.xml +179 -149
- package/.svelte-kit/__package__/app.postcss +43 -3
- package/.svelte-kit/__package__/assets/icons/close.svg +1 -0
- package/.svelte-kit/__package__/components/Card.svelte +1 -1
- package/.svelte-kit/__package__/components/Chip.svelte +1 -0
- package/.svelte-kit/__package__/components/DialogOverlay.svelte +48 -47
- package/.svelte-kit/__package__/components/dialog_manager/DialogManager.d.ts +8 -3
- package/.svelte-kit/__package__/components/dialog_manager/DialogManager.js +35 -11
- package/.svelte-kit/__package__/components/dialog_manager/DialogManagerStore.js +1 -1
- package/.svelte-kit/__package__/components/layouts/SeaweedBaseLayout.svelte +2 -2
- package/.svelte-kit/__package__/components/{layouts → pineapple}/PineappleBaseLayout.svelte +66 -30
- package/.svelte-kit/__package__/components/pineapple/toast/DefaultToastBody.d.ts +8 -0
- package/.svelte-kit/__package__/components/pineapple/toast/DefaultToastBody.js +1 -0
- package/.svelte-kit/__package__/components/pineapple/toast/DefaultToastBody.svelte +48 -0
- package/.svelte-kit/__package__/components/pineapple/toast/DefaultToastBody.svelte.d.ts +20 -0
- package/.svelte-kit/__package__/components/pineapple/toast/Toast.d.ts +27 -0
- package/.svelte-kit/__package__/components/pineapple/toast/Toast.js +37 -0
- package/.svelte-kit/__package__/components/pineapple/toast/Toast.svelte +90 -0
- package/.svelte-kit/__package__/components/pineapple/toast/Toast.svelte.d.ts +14 -0
- package/.svelte-kit/__package__/components/pineapple/toast/custom-toast/TestCustomToast.d.ts +5 -0
- package/.svelte-kit/__package__/components/pineapple/toast/custom-toast/TestCustomToast.js +1 -0
- package/.svelte-kit/__package__/components/pineapple/toast/custom-toast/TestCustomToast.svelte +1 -0
- package/.svelte-kit/__package__/components/pineapple/toast/custom-toast/TestCustomToast.svelte.d.ts +23 -0
- package/.svelte-kit/__package__/index.d.ts +1 -1
- package/.svelte-kit/__package__/index.js +1 -1
- package/.svelte-kit/__package__/scripts/pineapple_fiber/PineappleFiberParser.d.ts +2 -0
- package/.svelte-kit/__package__/scripts/pineapple_fiber/PineappleFiberParser.js +137 -0
- package/.svelte-kit/__package__/scripts/pineapple_fiber/PineappleWeaver.js +3 -134
- package/.svelte-kit/__package__/types/pineapple_fiber/DialogState.d.ts +2 -1
- package/.svelte-kit/__package__/types/pineapple_fiber/DialogState.js +1 -0
- package/.svelte-kit/ambient.d.ts +2 -0
- package/.svelte-kit/generated/client/app.js +1 -1
- package/.svelte-kit/generated/client/nodes/5.js +1 -1
- package/.svelte-kit/generated/server/internal.js +1 -1
- package/.svelte-kit/types/route_meta_data.json +1 -1
- package/.svelte-kit/types/src/routes/$types.d.ts +1 -1
- package/.svelte-kit/types/src/routes/(pineapple)/$types.d.ts +1 -1
- package/.svelte-kit/types/src/routes/(pineapple)/{personal → pineapple}/$types.d.ts +1 -1
- package/dist/app.postcss +43 -3
- package/dist/assets/icons/close.svg +1 -0
- package/dist/components/Card.svelte +1 -1
- package/dist/components/Chip.svelte +1 -0
- package/dist/components/DialogOverlay.svelte +48 -47
- package/dist/components/dialog_manager/DialogManager.d.ts +8 -3
- package/dist/components/dialog_manager/DialogManager.js +35 -11
- package/dist/components/dialog_manager/DialogManagerStore.js +1 -1
- package/dist/components/layouts/SeaweedBaseLayout.svelte +2 -2
- package/dist/components/{layouts → pineapple}/PineappleBaseLayout.svelte +66 -30
- package/dist/components/pineapple/toast/DefaultToastBody.d.ts +8 -0
- package/dist/components/pineapple/toast/DefaultToastBody.js +1 -0
- package/dist/components/pineapple/toast/DefaultToastBody.svelte +48 -0
- package/dist/components/pineapple/toast/DefaultToastBody.svelte.d.ts +20 -0
- package/dist/components/pineapple/toast/Toast.d.ts +27 -0
- package/dist/components/pineapple/toast/Toast.js +37 -0
- package/dist/components/pineapple/toast/Toast.svelte +90 -0
- package/dist/components/pineapple/toast/Toast.svelte.d.ts +14 -0
- package/dist/components/pineapple/toast/custom-toast/TestCustomToast.d.ts +5 -0
- package/dist/components/pineapple/toast/custom-toast/TestCustomToast.js +1 -0
- package/dist/components/pineapple/toast/custom-toast/TestCustomToast.svelte +1 -0
- package/dist/components/pineapple/toast/custom-toast/TestCustomToast.svelte.d.ts +23 -0
- package/dist/index.d.ts +1 -1
- package/dist/index.js +1 -1
- package/dist/scripts/pineapple_fiber/PineappleFiberParser.d.ts +2 -0
- package/dist/scripts/pineapple_fiber/PineappleFiberParser.js +137 -0
- package/dist/scripts/pineapple_fiber/PineappleWeaver.js +3 -134
- package/dist/types/pineapple_fiber/DialogState.d.ts +2 -1
- package/dist/types/pineapple_fiber/DialogState.js +1 -0
- package/docs/OverlaySpec.md +23 -0
- package/docs/pull_request_template.md +34 -0
- package/package.json +1 -1
- package/src/lib/app.postcss +43 -3
- package/src/lib/assets/icons/close.svg +1 -0
- package/src/lib/components/Card.svelte +1 -1
- package/src/lib/components/Chip.svelte +1 -0
- package/src/lib/components/DialogOverlay.svelte +56 -54
- package/src/lib/components/dialog_manager/DialogManager.ts +38 -12
- package/src/lib/components/dialog_manager/DialogManagerStore.ts +1 -1
- package/src/lib/components/layouts/SeaweedBaseLayout.svelte +2 -2
- package/src/lib/components/pineapple/PineappleBaseLayout.svelte +220 -0
- package/src/lib/components/pineapple/toast/DefaultToastBody.svelte +43 -0
- package/src/lib/components/pineapple/toast/DefaultToastBody.ts +10 -0
- package/src/lib/components/pineapple/toast/Toast.svelte +114 -0
- package/src/lib/components/pineapple/toast/Toast.ts +57 -0
- package/src/lib/components/pineapple/toast/custom-toast/TestCustomToast.svelte +1 -0
- package/src/lib/components/pineapple/toast/custom-toast/TestCustomToast.ts +6 -0
- package/src/lib/index.ts +1 -1
- package/src/lib/scripts/pineapple_fiber/PineappleFiberParser.ts +177 -0
- package/src/lib/scripts/pineapple_fiber/PineappleWeaver.ts +3 -176
- package/src/lib/types/pineapple_fiber/DialogState.ts +2 -1
- package/src/routes/(pineapple)/+layout.svelte +1 -1
- package/src/routes/(pineapple)/+page.svelte +3 -3
- package/src/routes/(pineapple)/pineapple/+page.svelte +62 -0
- package/src/routes/(pineapple)/pineapple/TestDialog.yarn +7 -0
- package/vite.config.ts +2 -1
- package/src/lib/components/layouts/PineappleBaseLayout.svelte +0 -182
- package/src/routes/(pineapple)/personal/+page.svelte +0 -37
- /package/.svelte-kit/__package__/components/{layouts → pineapple}/PineappleBaseLayout.svelte.d.ts +0 -0
- /package/dist/components/{layouts → pineapple}/PineappleBaseLayout.svelte.d.ts +0 -0
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
import { writable } from "svelte/store";
|
|
5
5
|
import { DialogState } from "../../types/pineapple_fiber/DialogState";
|
|
6
6
|
import { tweened } from "svelte/motion";
|
|
7
|
-
import {
|
|
7
|
+
import { backOut } from "svelte/easing";
|
|
8
8
|
import { PortraitType } from "../../types/pineapple_fiber/PortraitType";
|
|
9
9
|
import AresHappy from "../../assets/characters/ares/ares_happy.webp";
|
|
10
10
|
import AresBlushing from "../../assets/characters/ares/ares_blushing.webp";
|
|
@@ -17,10 +17,11 @@ import AresSurprised from "../../assets/characters/ares/ares_surprised.webp";
|
|
|
17
17
|
import AresYay from "../../assets/characters/ares/ares_yay.webp";
|
|
18
18
|
import { defaultDialogMessage, dialogVariableStore, enableDialogueOverlay, updateRate } from "./DialogManagerStore";
|
|
19
19
|
import { DialogProcessor } from "./DialogProcessor";
|
|
20
|
+
import { parseYarn } from "../../scripts/pineapple_fiber/PineappleFiberParser";
|
|
20
21
|
const shouldDebugYarn = false;
|
|
21
22
|
export class DialogManager {
|
|
22
23
|
dialogMessageMap = new Map();
|
|
23
|
-
|
|
24
|
+
currentDialogTree = [];
|
|
24
25
|
fullCurrentMessage = defaultDialogMessage[0].textContent;
|
|
25
26
|
currentMessageMeta = defaultDialogMessage[0];
|
|
26
27
|
currentMessage = writable("");
|
|
@@ -30,9 +31,10 @@ export class DialogManager {
|
|
|
30
31
|
currentPortrait = writable();
|
|
31
32
|
portraitMap = new Map();
|
|
32
33
|
currentState = DialogState.Visible;
|
|
34
|
+
currentReadableState = writable(this.currentState);
|
|
33
35
|
hidePercent = tweened(100, {
|
|
34
36
|
duration: 400,
|
|
35
|
-
easing:
|
|
37
|
+
easing: backOut
|
|
36
38
|
}); // 100 = 100%
|
|
37
39
|
skipNextActiveTime = 0;
|
|
38
40
|
dialogProcessor = new DialogProcessor();
|
|
@@ -40,16 +42,23 @@ export class DialogManager {
|
|
|
40
42
|
_setDialogChoiceQueue = [];
|
|
41
43
|
_setDialogChoiceMutex = false;
|
|
42
44
|
onSetDialogListeners = [];
|
|
45
|
+
enableDialogueOverlayCache = false;
|
|
43
46
|
constructor() {
|
|
44
47
|
enableDialogueOverlay.subscribe((value) => {
|
|
45
48
|
// todo: investigate why we cant put setDialogDefault inside the then clause
|
|
46
49
|
// ISSUE #82 https://github.com/TurnipXenon/pineapple/issues/82
|
|
50
|
+
this.enableDialogueOverlayCache = value;
|
|
47
51
|
if (value) {
|
|
48
|
-
this.hidePercent.set(0)
|
|
49
|
-
|
|
52
|
+
this.hidePercent.set(0).then(() => {
|
|
53
|
+
this.currentState = DialogState.Visible;
|
|
54
|
+
this.currentReadableState.set(this.currentState);
|
|
55
|
+
});
|
|
50
56
|
}
|
|
51
57
|
else {
|
|
52
|
-
this.hidePercent.set(100)
|
|
58
|
+
this.hidePercent.set(100).then(() => {
|
|
59
|
+
this.currentState = DialogState.Invisible;
|
|
60
|
+
this.currentReadableState.set(this.currentState);
|
|
61
|
+
});
|
|
53
62
|
this.setDialogTree([{ textContent: "" }]);
|
|
54
63
|
}
|
|
55
64
|
});
|
|
@@ -78,12 +87,12 @@ export class DialogManager {
|
|
|
78
87
|
* sets the possible dialog that might appear on the Dialog UI
|
|
79
88
|
* note that it overwrites the previous tree and does not append on it due to the possibility
|
|
80
89
|
* of node name conflicts
|
|
81
|
-
* @param
|
|
90
|
+
* @param newDialogTree
|
|
82
91
|
*/
|
|
83
|
-
setDialogTree = (
|
|
84
|
-
this.
|
|
92
|
+
setDialogTree = (newDialogTree) => {
|
|
93
|
+
this.currentDialogTree = newDialogTree;
|
|
85
94
|
this.dialogMessageMap.clear();
|
|
86
|
-
|
|
95
|
+
newDialogTree.map((value) => {
|
|
87
96
|
if (value.dialogId) {
|
|
88
97
|
this.dialogMessageMap.set(value.dialogId, value);
|
|
89
98
|
}
|
|
@@ -100,7 +109,7 @@ export class DialogManager {
|
|
|
100
109
|
this.portraitMap.set(PortraitType.AresSurprised.toString(), AresSurprised);
|
|
101
110
|
this.portraitMap.set(PortraitType.AresYay.toString(), AresYay);
|
|
102
111
|
}
|
|
103
|
-
this.setDialogChoice(
|
|
112
|
+
this.setDialogChoice(newDialogTree[0]);
|
|
104
113
|
};
|
|
105
114
|
/**
|
|
106
115
|
* Remember to call this before SetDialogTree
|
|
@@ -236,4 +245,19 @@ export class DialogManager {
|
|
|
236
245
|
++this.currentIndex;
|
|
237
246
|
window.requestAnimationFrame(this.update);
|
|
238
247
|
};
|
|
248
|
+
enableDialogOverlay(enable) {
|
|
249
|
+
enableDialogueOverlay.set(enable);
|
|
250
|
+
}
|
|
251
|
+
toggleDialogOverlay() {
|
|
252
|
+
enableDialogueOverlay.set(!this.enableDialogueOverlayCache);
|
|
253
|
+
}
|
|
254
|
+
;
|
|
255
|
+
async parseAndSetDialogTree(dialogYarn) {
|
|
256
|
+
return parseYarn(dialogYarn)
|
|
257
|
+
.then((dialogTree) => {
|
|
258
|
+
console.log(dialogTree);
|
|
259
|
+
this.setDialogTree(dialogTree);
|
|
260
|
+
return dialogTree;
|
|
261
|
+
});
|
|
262
|
+
}
|
|
239
263
|
}
|
|
@@ -26,7 +26,7 @@ export const updateRate = 40 / 1000; // *at least* 40ms per letter
|
|
|
26
26
|
// todo: if we go through doing yarn to typescript, move this!
|
|
27
27
|
export const defaultDialogMessage = [
|
|
28
28
|
{
|
|
29
|
-
textContent: `<p>Have you drank water? Or perhaps, you've checked out <a target="_blank" class="external-link" href="http://crouton.net">one of the best webpages</a> out there?`
|
|
29
|
+
textContent: `<p>I don't really have anything to say. Have you drank water? Or perhaps, you've checked out <a target="_blank" class="external-link" href="http://crouton.net">one of the best webpages</a> out there?`
|
|
30
30
|
}
|
|
31
31
|
];
|
|
32
32
|
/**
|
|
@@ -56,8 +56,8 @@ let shouldDisplaySocialIcons = writable(false);
|
|
|
56
56
|
|
|
57
57
|
<style>
|
|
58
58
|
:root {
|
|
59
|
-
--dialog-
|
|
60
|
-
--dialog-box-width: min(calc(50em + 4em), calc(100vw - var(--dialog-
|
|
59
|
+
--dialog-start-pad: clamp(0em, 5vw, 2em);
|
|
60
|
+
--dialog-box-width: min(calc(50em + 4em), calc(100vw - var(--dialog-start-pad) - var(--theme-border-base)));
|
|
61
61
|
--dialog-box-height: clamp(15em, 50vw, 18em);
|
|
62
62
|
}
|
|
63
63
|
|
|
@@ -2,10 +2,12 @@
|
|
|
2
2
|
import RandomizedBackground from "../RandomizedBackground.svelte";
|
|
3
3
|
import { page } from "$app/stores";
|
|
4
4
|
import { enableBackground } from "../../store";
|
|
5
|
-
import DialogOverlay from "../DialogOverlay.svelte";
|
|
6
5
|
import AresLogo from "../../assets/characters/ares/ares_logo.webp";
|
|
7
6
|
import FABIcon from "../../assets/placeholder/placeholder_circle.png";
|
|
8
|
-
import
|
|
7
|
+
import CloseIcon from "../../assets/icons/close.svg";
|
|
8
|
+
import { dialogManager, enableDialogueOverlay } from "../dialog_manager/DialogManagerStore";
|
|
9
|
+
import Toast from "./toast/Toast.svelte";
|
|
10
|
+
import DialogOverlay from "../DialogOverlay.svelte";
|
|
9
11
|
let pages = [];
|
|
10
12
|
const updateBreadcrumb = (pathname) => {
|
|
11
13
|
pages = [];
|
|
@@ -40,6 +42,7 @@ let enableDialogueOverlayValue = true;
|
|
|
40
42
|
enableDialogueOverlay.subscribe((value) => {
|
|
41
43
|
enableDialogueOverlayValue = value;
|
|
42
44
|
});
|
|
45
|
+
enableDialogueOverlay.set(false);
|
|
43
46
|
</script>
|
|
44
47
|
|
|
45
48
|
<!-- App Shell -->
|
|
@@ -49,23 +52,30 @@ enableDialogueOverlay.subscribe((value) => {
|
|
|
49
52
|
|
|
50
53
|
<!--todo: turn off hidden when it's time-->
|
|
51
54
|
<button type="button" class="fab" on:click={()=>{
|
|
52
|
-
|
|
55
|
+
dialogManager.toggleDialogOverlay()
|
|
53
56
|
}}>
|
|
54
|
-
|
|
57
|
+
{#if (enableDialogueOverlayValue)}
|
|
58
|
+
<img class="img-icon" src={CloseIcon} alt="interactive floating action button represented as a turnip">
|
|
59
|
+
{:else }
|
|
60
|
+
<img src={FABIcon} alt="interactive floating action button represented as a turnip">
|
|
61
|
+
{/if}
|
|
55
62
|
</button>
|
|
56
63
|
|
|
57
64
|
<AppShell>
|
|
58
65
|
<svelte:fragment slot="header">
|
|
59
66
|
<!-- App Bar -->
|
|
60
|
-
<AppBar
|
|
67
|
+
<AppBar
|
|
68
|
+
background="app-shell-token"
|
|
69
|
+
slotDefault="place-content-start"
|
|
70
|
+
slotTrail="place-content-end">
|
|
61
71
|
<svelte:fragment slot="lead">
|
|
62
72
|
<!--TODO: add logo or something for the lead in layout-->
|
|
63
73
|
<img
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
74
|
+
alt="Ares's head titled towards the left with his tongue out and winking"
|
|
75
|
+
class="ares-logo"
|
|
76
|
+
src={AresLogo}
|
|
67
77
|
/>
|
|
68
|
-
<span class="mr-2"/>
|
|
78
|
+
<span class="mr-2" />
|
|
69
79
|
<ol class="breadcrumb">
|
|
70
80
|
{#each pages as crumb, i}
|
|
71
81
|
{#if i < pages.length - 1}
|
|
@@ -80,31 +90,52 @@ enableDialogueOverlay.subscribe((value) => {
|
|
|
80
90
|
</ol>
|
|
81
91
|
</svelte:fragment>
|
|
82
92
|
<svelte:fragment slot="trail">
|
|
83
|
-
<LightSwitch bgLight="bg-surface-400"/>
|
|
93
|
+
<LightSwitch bgLight="bg-surface-400" />
|
|
84
94
|
</svelte:fragment>
|
|
85
95
|
</AppBar>
|
|
86
96
|
</svelte:fragment>
|
|
87
97
|
|
|
88
|
-
<RandomizedBackground enable={enableBackgroundValue}/>
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
<
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
98
|
+
<RandomizedBackground enable={enableBackgroundValue} />
|
|
99
|
+
|
|
100
|
+
<Toast></Toast>
|
|
101
|
+
|
|
102
|
+
<DialogOverlay></DialogOverlay>
|
|
103
|
+
|
|
104
|
+
<div class="default-page-container">
|
|
105
|
+
<slot />
|
|
106
|
+
<div class="footer-space" />
|
|
107
|
+
</div>
|
|
108
|
+
<!--{#if enableDialogueOverlayValue}-->
|
|
109
|
+
<!-- <!– Page Route Content –>-->
|
|
110
|
+
<!-- <div class="default-page-container">-->
|
|
111
|
+
<!-- <slot />-->
|
|
112
|
+
<!-- <div class="footer-space" />-->
|
|
113
|
+
<!-- </div>-->
|
|
114
|
+
<!-- <DialogOverlay />-->
|
|
115
|
+
<!--{:else}-->
|
|
116
|
+
<!-- <DialogOverlay />-->
|
|
117
|
+
<!-- <slot />-->
|
|
118
|
+
<!--{/if}-->
|
|
101
119
|
</AppShell>
|
|
102
120
|
|
|
103
121
|
<style>
|
|
104
122
|
:root {
|
|
105
|
-
--dialog-
|
|
106
|
-
--dialog-box-width: min(calc(50em + 4em), calc(100vw - var(--dialog-
|
|
123
|
+
--dialog-start-pad: clamp(0em, 5vw, 2em);
|
|
124
|
+
--dialog-box-width: min(calc(50em + 4em), calc(100vw - var(--dialog-start-pad) - var(--theme-border-base)));
|
|
107
125
|
--dialog-box-height: clamp(15em, 50vw, 18em);
|
|
126
|
+
|
|
127
|
+
/** FAB icon margin/position calculation origin:
|
|
128
|
+
Criteria:
|
|
129
|
+
- We want at mobile (360px) our margin to be at 1em (16px)
|
|
130
|
+
- We want at web (1960px) our margin to be at 2em (32px)
|
|
131
|
+
|
|
132
|
+
A useful scaling factor might vw. At 360px, 16px would be around 4.44vw (360/16).
|
|
133
|
+
At 360px: margin is at 16px or 1em.
|
|
134
|
+
At 1960px: 4.44vw is at 87px but that will be clamped to 32px or 2em.
|
|
135
|
+
The calculation implies that the natural point that the margin becomes 2em is clamped on
|
|
136
|
+
wider screens is at 727px.
|
|
137
|
+
*/
|
|
138
|
+
--fab-margin: clamp(1em, 4.44vw, 2em);
|
|
108
139
|
}
|
|
109
140
|
|
|
110
141
|
.default-page-container {
|
|
@@ -112,7 +143,6 @@ enableDialogueOverlay.subscribe((value) => {
|
|
|
112
143
|
align-items: center;
|
|
113
144
|
justify-content: center;
|
|
114
145
|
margin-top: 4em;
|
|
115
|
-
margin-left: clamp(1em, 15vw, 10em);
|
|
116
146
|
margin-right: 1em;
|
|
117
147
|
flex-direction: column;
|
|
118
148
|
z-index: 0;
|
|
@@ -194,15 +224,21 @@ enableDialogueOverlay.subscribe((value) => {
|
|
|
194
224
|
}
|
|
195
225
|
|
|
196
226
|
.fab {
|
|
197
|
-
|
|
198
|
-
|
|
227
|
+
position: fixed;
|
|
228
|
+
bottom: var(--fab-margin);
|
|
229
|
+
width: 4em;
|
|
230
|
+
border-radius: 50%;
|
|
231
|
+
}
|
|
232
|
+
|
|
233
|
+
.fab > img {
|
|
234
|
+
width: 100%;
|
|
199
235
|
}
|
|
200
236
|
|
|
201
237
|
.fab:dir(ltr) {
|
|
202
|
-
|
|
238
|
+
right: var(--fab-margin);
|
|
203
239
|
}
|
|
204
240
|
|
|
205
241
|
.fab:dir(rtl) {
|
|
206
|
-
|
|
242
|
+
left: var(--fab-margin);
|
|
207
243
|
}
|
|
208
244
|
</style>
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import DefaultToastBody from "./DefaultToastBody.svelte";
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
<script>import CloseIcon from "../../../assets/icons/close.svg";
|
|
2
|
+
export let props;
|
|
3
|
+
export let dismissToastCallback;
|
|
4
|
+
export let shouldEnableButton = false;
|
|
5
|
+
</script>
|
|
6
|
+
|
|
7
|
+
<div class="body-container">
|
|
8
|
+
<!-- todo: support markdown? -->
|
|
9
|
+
<button class="btn"
|
|
10
|
+
disabled={!shouldEnableButton}
|
|
11
|
+
on:click={dismissToastCallback}>
|
|
12
|
+
<img class="img-icon" src={CloseIcon} alt="close button">
|
|
13
|
+
</button>
|
|
14
|
+
<div class="text-container">
|
|
15
|
+
<span>{props.message}</span>
|
|
16
|
+
</div>
|
|
17
|
+
</div>
|
|
18
|
+
|
|
19
|
+
<style>
|
|
20
|
+
.body-container {
|
|
21
|
+
display: flex;
|
|
22
|
+
gap: 1em;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
.text-container {
|
|
26
|
+
margin-top: 0.25lh;
|
|
27
|
+
margin-right: 1em;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
.text-container:dir(rtl) {
|
|
31
|
+
margin-left: 1em;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
.btn {
|
|
35
|
+
--tw-bg-opacity: 1;
|
|
36
|
+
background-color: rgb(var(--color-surface-100) / var(--tw-bg-opacity));
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
:is(.dark .btn) {
|
|
40
|
+
--tw-bg-opacity: 1;
|
|
41
|
+
background-color: rgb(var(--color-surface-900) / var(--tw-bg-opacity));
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
.btn {
|
|
45
|
+
border-radius: 8px;
|
|
46
|
+
padding: 0.5em;
|
|
47
|
+
}
|
|
48
|
+
</style>
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { SvelteComponent } from "svelte";
|
|
2
|
+
import type { Props } from "./DefaultToastBody";
|
|
3
|
+
import type { DismissToastCallback } from "./Toast";
|
|
4
|
+
declare const __propDef: {
|
|
5
|
+
props: {
|
|
6
|
+
props: Props;
|
|
7
|
+
dismissToastCallback: DismissToastCallback | undefined;
|
|
8
|
+
shouldEnableButton?: boolean | undefined;
|
|
9
|
+
};
|
|
10
|
+
events: {
|
|
11
|
+
[evt: string]: CustomEvent<any>;
|
|
12
|
+
};
|
|
13
|
+
slots: {};
|
|
14
|
+
};
|
|
15
|
+
export type DefaultToastBodyProps = typeof __propDef.props;
|
|
16
|
+
export type DefaultToastBodyEvents = typeof __propDef.events;
|
|
17
|
+
export type DefaultToastBodySlots = typeof __propDef.slots;
|
|
18
|
+
export default class DefaultToastBody extends SvelteComponent<DefaultToastBodyProps, DefaultToastBodyEvents, DefaultToastBodySlots> {
|
|
19
|
+
}
|
|
20
|
+
export {};
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
/// <reference types="svelte" />
|
|
2
|
+
import type { DefaultToastPair } from "./DefaultToastBody";
|
|
3
|
+
import type { TestCustomToastPair } from "./custom-toast/TestCustomToast";
|
|
4
|
+
/**
|
|
5
|
+
* Default toast duration is 5 seconds
|
|
6
|
+
*/
|
|
7
|
+
export declare const DefaultToastParamsDuration = 5000;
|
|
8
|
+
export type CustomToastPairs = DefaultToastPair | TestCustomToastPair;
|
|
9
|
+
export type DismissToastCallback = () => void;
|
|
10
|
+
export interface ToastParams {
|
|
11
|
+
componentAndProps: CustomToastPairs;
|
|
12
|
+
/**
|
|
13
|
+
* Time in millisecond. If undefined, defaults to DefaultToastParamsDuration
|
|
14
|
+
*/
|
|
15
|
+
duration?: number;
|
|
16
|
+
}
|
|
17
|
+
/**
|
|
18
|
+
* todo: do not call directly documentation
|
|
19
|
+
*/
|
|
20
|
+
export declare const activeToast: import("svelte/store").Writable<ToastParams | undefined>;
|
|
21
|
+
export declare const toastQueue: ToastParams[];
|
|
22
|
+
/**
|
|
23
|
+
*
|
|
24
|
+
* @param newToast
|
|
25
|
+
*/
|
|
26
|
+
export declare const showComponentInToast: (newToast: ToastParams) => void;
|
|
27
|
+
export declare const showTextInToast: (message: string) => void;
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import { writable } from "svelte/store";
|
|
2
|
+
import DefaultToastBody from "./DefaultToastBody.svelte";
|
|
3
|
+
/**
|
|
4
|
+
* Default toast duration is 5 seconds
|
|
5
|
+
*/
|
|
6
|
+
export const DefaultToastParamsDuration = 5000;
|
|
7
|
+
/**
|
|
8
|
+
* todo: do not call directly documentation
|
|
9
|
+
*/
|
|
10
|
+
export const activeToast = writable();
|
|
11
|
+
export const toastQueue = [];
|
|
12
|
+
/**
|
|
13
|
+
*
|
|
14
|
+
* @param newToast
|
|
15
|
+
*/
|
|
16
|
+
export const showComponentInToast = (newToast) => {
|
|
17
|
+
// todo: queue component
|
|
18
|
+
activeToast.update((currentToast) => {
|
|
19
|
+
if (currentToast !== undefined) {
|
|
20
|
+
toastQueue.push(newToast);
|
|
21
|
+
return currentToast;
|
|
22
|
+
}
|
|
23
|
+
else {
|
|
24
|
+
return newToast;
|
|
25
|
+
}
|
|
26
|
+
});
|
|
27
|
+
};
|
|
28
|
+
export const showTextInToast = (message) => {
|
|
29
|
+
showComponentInToast({
|
|
30
|
+
componentAndProps: {
|
|
31
|
+
component: DefaultToastBody,
|
|
32
|
+
props: {
|
|
33
|
+
message
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
});
|
|
37
|
+
};
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
<script>import {
|
|
2
|
+
activeToast,
|
|
3
|
+
DefaultToastParamsDuration,
|
|
4
|
+
toastQueue
|
|
5
|
+
} from "./Toast";
|
|
6
|
+
import {} from "svelte";
|
|
7
|
+
import Card from "../../Card.svelte";
|
|
8
|
+
import { spring, tweened } from "svelte/motion";
|
|
9
|
+
let localComponent;
|
|
10
|
+
let localProps;
|
|
11
|
+
const HIDDEN_VALUE = -15;
|
|
12
|
+
const SHOWN_VALUE = 0;
|
|
13
|
+
const progress = tweened(0, { duration: DefaultToastParamsDuration });
|
|
14
|
+
const position = spring(HIDDEN_VALUE);
|
|
15
|
+
position.damping = 0.4;
|
|
16
|
+
let isDismissed = false;
|
|
17
|
+
let shouldEnableButton = false;
|
|
18
|
+
const onToastDisappear = () => {
|
|
19
|
+
localComponent = void 0;
|
|
20
|
+
activeToast.update(() => {
|
|
21
|
+
if (toastQueue.length === 0) {
|
|
22
|
+
return void 0;
|
|
23
|
+
}
|
|
24
|
+
return toastQueue.shift();
|
|
25
|
+
});
|
|
26
|
+
};
|
|
27
|
+
activeToast.subscribe((params) => {
|
|
28
|
+
if (!params) {
|
|
29
|
+
return;
|
|
30
|
+
}
|
|
31
|
+
if (params.componentAndProps?.component === localComponent) {
|
|
32
|
+
return;
|
|
33
|
+
}
|
|
34
|
+
localComponent = params.componentAndProps.component;
|
|
35
|
+
localProps = params.componentAndProps.props;
|
|
36
|
+
progress.set(0, { duration: 0 }).then(() => {
|
|
37
|
+
position.set(SHOWN_VALUE).then(() => {
|
|
38
|
+
shouldEnableButton = true;
|
|
39
|
+
progress.set(100, { delay: 500, duration: params.duration ?? DefaultToastParamsDuration }).then(() => {
|
|
40
|
+
shouldEnableButton = false;
|
|
41
|
+
if (isDismissed) {
|
|
42
|
+
return;
|
|
43
|
+
}
|
|
44
|
+
position.set(HIDDEN_VALUE).then(onToastDisappear);
|
|
45
|
+
});
|
|
46
|
+
});
|
|
47
|
+
});
|
|
48
|
+
});
|
|
49
|
+
const dismissToast = () => {
|
|
50
|
+
shouldEnableButton = false;
|
|
51
|
+
isDismissed = true;
|
|
52
|
+
position.set(HIDDEN_VALUE).then(onToastDisappear);
|
|
53
|
+
};
|
|
54
|
+
</script>
|
|
55
|
+
|
|
56
|
+
{#if (localComponent !== undefined)}
|
|
57
|
+
<div class="toast-positioner" style={`bottom: ${$position}lh;`}>
|
|
58
|
+
<!-- todo: adjust shadow to be more dynamic or transparent -->
|
|
59
|
+
<Card marginBottom="1lh" overrideStyle="box-shadow: 3px 3px 3px var(--shadow-color);">
|
|
60
|
+
<div slot="content">
|
|
61
|
+
{#if (localProps !== undefined)}
|
|
62
|
+
<svelte:component this={localComponent}
|
|
63
|
+
props={localProps}
|
|
64
|
+
dismissToastCallback={dismissToast}
|
|
65
|
+
shouldEnableButton={shouldEnableButton} />
|
|
66
|
+
{:else }
|
|
67
|
+
<svelte:component this={localComponent} />
|
|
68
|
+
{/if}
|
|
69
|
+
<progress id="toast-progress" value={$progress/100}></progress>
|
|
70
|
+
</div>
|
|
71
|
+
</Card>
|
|
72
|
+
</div>
|
|
73
|
+
{/if}
|
|
74
|
+
|
|
75
|
+
<style>
|
|
76
|
+
.toast-positioner {
|
|
77
|
+
position: fixed;
|
|
78
|
+
/* 12em = this component's margin (4em) + fab margin + width (8em) */
|
|
79
|
+
max-width: calc(100vw - 12em);
|
|
80
|
+
z-index: 100;
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
.toast-positioner:dir(ltr) {
|
|
84
|
+
left: 2em;
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
.toast-positioner:dir(rtl) {
|
|
88
|
+
right: 2em;
|
|
89
|
+
}
|
|
90
|
+
</style>
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { SvelteComponent } from "svelte";
|
|
2
|
+
declare const __propDef: {
|
|
3
|
+
props: Record<string, never>;
|
|
4
|
+
events: {
|
|
5
|
+
[evt: string]: CustomEvent<any>;
|
|
6
|
+
};
|
|
7
|
+
slots: {};
|
|
8
|
+
};
|
|
9
|
+
export type ToastProps = typeof __propDef.props;
|
|
10
|
+
export type ToastEvents = typeof __propDef.events;
|
|
11
|
+
export type ToastSlots = typeof __propDef.slots;
|
|
12
|
+
export default class Toast extends SvelteComponent<ToastProps, ToastEvents, ToastSlots> {
|
|
13
|
+
}
|
|
14
|
+
export {};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import TestCustomToast from "./TestCustomToast.svelte";
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
<h1>Testing bad custom card</h1>
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
/** @typedef {typeof __propDef.props} TestCustomToastProps */
|
|
2
|
+
/** @typedef {typeof __propDef.events} TestCustomToastEvents */
|
|
3
|
+
/** @typedef {typeof __propDef.slots} TestCustomToastSlots */
|
|
4
|
+
export default class TestCustomToast extends SvelteComponent<{
|
|
5
|
+
[x: string]: never;
|
|
6
|
+
}, {
|
|
7
|
+
[evt: string]: CustomEvent<any>;
|
|
8
|
+
}, {}> {
|
|
9
|
+
}
|
|
10
|
+
export type TestCustomToastProps = typeof __propDef.props;
|
|
11
|
+
export type TestCustomToastEvents = typeof __propDef.events;
|
|
12
|
+
export type TestCustomToastSlots = typeof __propDef.slots;
|
|
13
|
+
import { SvelteComponent } from "svelte";
|
|
14
|
+
declare const __propDef: {
|
|
15
|
+
props: {
|
|
16
|
+
[x: string]: never;
|
|
17
|
+
};
|
|
18
|
+
events: {
|
|
19
|
+
[evt: string]: CustomEvent<any>;
|
|
20
|
+
};
|
|
21
|
+
slots: {};
|
|
22
|
+
};
|
|
23
|
+
export {};
|
package/dist/index.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
export { default as PineappleLayoutBase } from "./components/
|
|
1
|
+
export { default as PineappleLayoutBase } from "./components/pineapple/PineappleBaseLayout.svelte";
|
|
2
2
|
export { default as SeaweedTemplate } from "./template/SeaweedTemplate.svelte";
|
|
3
3
|
export { default as LazyAsset } from "./components/LazyAsset.svelte";
|
|
4
4
|
export * from "./components/dialog_manager/DialogManagerStore";
|
package/dist/index.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
export { default as PineappleLayoutBase } from "./components/
|
|
1
|
+
export { default as PineappleLayoutBase } from "./components/pineapple/PineappleBaseLayout.svelte";
|
|
2
2
|
export { default as SeaweedTemplate } from "./template/SeaweedTemplate.svelte";
|
|
3
3
|
export { default as LazyAsset } from "./components/LazyAsset.svelte";
|
|
4
4
|
export * from "./components/dialog_manager/DialogManagerStore";
|