@memori.ai/memori-react 7.22.0 → 7.23.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.
Files changed (86) hide show
  1. package/CHANGELOG.md +38 -0
  2. package/dist/components/CompletionProviderStatus/CompletionProviderStatus.css +33 -23
  3. package/dist/components/CompletionProviderStatus/CompletionProviderStatus.js +85 -8
  4. package/dist/components/CompletionProviderStatus/CompletionProviderStatus.js.map +1 -1
  5. package/dist/components/KnownFacts/KnownFacts.js +1 -1
  6. package/dist/components/KnownFacts/KnownFacts.js.map +1 -1
  7. package/dist/components/Typing/Typing.js +49 -47
  8. package/dist/components/Typing/Typing.js.map +1 -1
  9. package/dist/components/icons/Alert.d.ts +5 -0
  10. package/dist/components/icons/Alert.js +6 -0
  11. package/dist/components/icons/Alert.js.map +1 -0
  12. package/dist/components/icons/Info.d.ts +5 -0
  13. package/dist/components/icons/Info.js +6 -0
  14. package/dist/components/icons/Info.js.map +1 -0
  15. package/dist/components/icons/Warning.js +1 -1
  16. package/dist/components/icons/Warning.js.map +1 -1
  17. package/dist/components/ui/ConfirmDialog.css +42 -0
  18. package/dist/components/ui/ConfirmDialog.d.ts +11 -0
  19. package/dist/components/ui/ConfirmDialog.js +12 -0
  20. package/dist/components/ui/ConfirmDialog.js.map +1 -0
  21. package/dist/components/ui/Drawer.css +121 -96
  22. package/dist/components/ui/Drawer.d.ts +15 -6
  23. package/dist/components/ui/Drawer.js +44 -13
  24. package/dist/components/ui/Drawer.js.map +1 -1
  25. package/dist/locales/de.json +7 -0
  26. package/dist/locales/en.json +7 -0
  27. package/dist/locales/es.json +7 -0
  28. package/dist/locales/fr.json +7 -0
  29. package/dist/locales/it.json +7 -0
  30. package/dist/styles.css +6 -4
  31. package/esm/components/CompletionProviderStatus/CompletionProviderStatus.css +33 -23
  32. package/esm/components/CompletionProviderStatus/CompletionProviderStatus.js +85 -8
  33. package/esm/components/CompletionProviderStatus/CompletionProviderStatus.js.map +1 -1
  34. package/esm/components/KnownFacts/KnownFacts.js +1 -1
  35. package/esm/components/KnownFacts/KnownFacts.js.map +1 -1
  36. package/esm/components/Typing/Typing.js +49 -47
  37. package/esm/components/Typing/Typing.js.map +1 -1
  38. package/esm/components/icons/Alert.d.ts +5 -0
  39. package/esm/components/icons/Alert.js +4 -0
  40. package/esm/components/icons/Alert.js.map +1 -0
  41. package/esm/components/icons/Info.d.ts +5 -0
  42. package/esm/components/icons/Info.js +4 -0
  43. package/esm/components/icons/Info.js.map +1 -0
  44. package/esm/components/icons/Warning.js +1 -1
  45. package/esm/components/icons/Warning.js.map +1 -1
  46. package/esm/components/ui/ConfirmDialog.css +42 -0
  47. package/esm/components/ui/ConfirmDialog.d.ts +11 -0
  48. package/esm/components/ui/ConfirmDialog.js +9 -0
  49. package/esm/components/ui/ConfirmDialog.js.map +1 -0
  50. package/esm/components/ui/Drawer.css +121 -96
  51. package/esm/components/ui/Drawer.d.ts +15 -6
  52. package/esm/components/ui/Drawer.js +45 -14
  53. package/esm/components/ui/Drawer.js.map +1 -1
  54. package/esm/locales/de.json +7 -0
  55. package/esm/locales/en.json +7 -0
  56. package/esm/locales/es.json +7 -0
  57. package/esm/locales/fr.json +7 -0
  58. package/esm/locales/it.json +7 -0
  59. package/esm/styles.css +6 -4
  60. package/package.json +1 -1
  61. package/src/components/BlockedMemoriBadge/__snapshots__/BlockedMemoriBadge.test.tsx.snap +10 -0
  62. package/src/components/CompletionProviderStatus/CompletionProviderStatus.css +33 -23
  63. package/src/components/CompletionProviderStatus/CompletionProviderStatus.stories.tsx +274 -21
  64. package/src/components/CompletionProviderStatus/CompletionProviderStatus.tsx +117 -21
  65. package/src/components/CompletionProviderStatus/__snapshots__/CompletionProviderStatus.test.tsx.snap +39 -21
  66. package/src/components/KnownFacts/KnownFacts.tsx +1 -1
  67. package/src/components/StartPanel/__snapshots__/StartPanel.test.tsx.snap +13 -7
  68. package/src/components/Typing/Typing.tsx +52 -47
  69. package/src/components/icons/Alert.tsx +31 -0
  70. package/src/components/icons/Info.tsx +31 -0
  71. package/src/components/icons/Warning.tsx +2 -1
  72. package/src/components/ui/ConfirmDialog.css +42 -0
  73. package/src/components/ui/ConfirmDialog.stories.tsx +216 -0
  74. package/src/components/ui/ConfirmDialog.test.tsx +124 -0
  75. package/src/components/ui/ConfirmDialog.tsx +58 -0
  76. package/src/components/ui/Drawer.css +121 -96
  77. package/src/components/ui/Drawer.stories.tsx +152 -67
  78. package/src/components/ui/Drawer.test.tsx +6 -2
  79. package/src/components/ui/Drawer.tsx +195 -89
  80. package/src/components/ui/__snapshots__/ConfirmDialog.test.tsx.snap +35 -0
  81. package/src/locales/de.json +7 -0
  82. package/src/locales/en.json +7 -0
  83. package/src/locales/es.json +7 -0
  84. package/src/locales/fr.json +7 -0
  85. package/src/locales/it.json +7 -0
  86. package/src/styles.css +6 -4
@@ -3,14 +3,14 @@
3
3
  exports[`renders CompletionProviderStatus errored unchanged 1`] = `
4
4
  <div>
5
5
  <div
6
- class="memori-tooltip memori-tooltip--align-topLeft memori--completion-provider-status--tooltip"
6
+ class="memori-tooltip memori-tooltip--align-right memori--completion-provider-status--tooltip"
7
7
  >
8
8
  <div
9
9
  class="memori-tooltip--content"
10
10
  >
11
11
  <div>
12
12
  <p>
13
- completionProviderDown
13
+ completionProviderMajorOutage
14
14
  </p>
15
15
  <p>
16
16
  <a
@@ -28,14 +28,20 @@ exports[`renders CompletionProviderStatus errored unchanged 1`] = `
28
28
  >
29
29
  <svg
30
30
  aria-hidden="true"
31
- class="memori--completion-provider-status--icon"
32
- focusable="false"
33
- role="img"
34
- viewBox="0 0 1024 1024"
31
+ class="memori--completion-provider-status--icon memori--completion-provider-status--icon-error"
32
+ color="currentColor"
33
+ fill="none"
34
+ height="800px"
35
+ viewBox="0 0 24 24"
36
+ width="800px"
35
37
  xmlns="http://www.w3.org/2000/svg"
36
38
  >
37
39
  <path
38
- d="M464 720a48 48 0 1096 0 48 48 0 10-96 0zm16-304v184c0 4.4 3.6 8 8 8h48c4.4 0 8-3.6 8-8V416c0-4.4-3.6-8-8-8h-48c-4.4 0-8 3.6-8 8zm475.7 440l-416-720c-6.2-10.7-16.9-16-27.7-16s-21.6 5.3-27.7 16l-416 720C56 877.4 71.4 904 96 904h832c24.6 0 40-26.6 27.7-48zm-783.5-27.9L512 239.9l339.8 588.2H172.2z"
40
+ d="M12 16H12.01M12 8V12M12 21C16.9706 21 21 16.9706 21 12C21 7.02944 16.9706 3 12 3C7.02944 3 3 7.02944 3 12C3 16.9706 7.02944 21 12 21Z"
41
+ stroke="currentColor"
42
+ stroke-linecap="round"
43
+ stroke-linejoin="round"
44
+ stroke-width="2"
39
45
  />
40
46
  </svg>
41
47
  </div>
@@ -46,14 +52,14 @@ exports[`renders CompletionProviderStatus errored unchanged 1`] = `
46
52
  exports[`renders CompletionProviderStatus errored with provider specified unchanged 1`] = `
47
53
  <div>
48
54
  <div
49
- class="memori-tooltip memori-tooltip--align-topLeft memori--completion-provider-status--tooltip"
55
+ class="memori-tooltip memori-tooltip--align-right memori--completion-provider-status--tooltip"
50
56
  >
51
57
  <div
52
58
  class="memori-tooltip--content"
53
59
  >
54
60
  <div>
55
61
  <p>
56
- completionProviderDown
62
+ completionProviderMajorOutage
57
63
  </p>
58
64
  <p>
59
65
  <a
@@ -71,14 +77,20 @@ exports[`renders CompletionProviderStatus errored with provider specified unchan
71
77
  >
72
78
  <svg
73
79
  aria-hidden="true"
74
- class="memori--completion-provider-status--icon"
75
- focusable="false"
76
- role="img"
77
- viewBox="0 0 1024 1024"
80
+ class="memori--completion-provider-status--icon memori--completion-provider-status--icon-error"
81
+ color="currentColor"
82
+ fill="none"
83
+ height="800px"
84
+ viewBox="0 0 24 24"
85
+ width="800px"
78
86
  xmlns="http://www.w3.org/2000/svg"
79
87
  >
80
88
  <path
81
- d="M464 720a48 48 0 1096 0 48 48 0 10-96 0zm16-304v184c0 4.4 3.6 8 8 8h48c4.4 0 8-3.6 8-8V416c0-4.4-3.6-8-8-8h-48c-4.4 0-8 3.6-8 8zm475.7 440l-416-720c-6.2-10.7-16.9-16-27.7-16s-21.6 5.3-27.7 16l-416 720C56 877.4 71.4 904 96 904h832c24.6 0 40-26.6 27.7-48zm-783.5-27.9L512 239.9l339.8 588.2H172.2z"
89
+ d="M12 16H12.01M12 8V12M12 21C16.9706 21 21 16.9706 21 12C21 7.02944 16.9706 3 12 3C7.02944 3 3 7.02944 3 12C3 16.9706 7.02944 21 12 21Z"
90
+ stroke="currentColor"
91
+ stroke-linecap="round"
92
+ stroke-linejoin="round"
93
+ stroke-width="2"
82
94
  />
83
95
  </svg>
84
96
  </div>
@@ -89,14 +101,14 @@ exports[`renders CompletionProviderStatus errored with provider specified unchan
89
101
  exports[`renders CompletionProviderStatus unchanged 1`] = `
90
102
  <div>
91
103
  <div
92
- class="memori-tooltip memori-tooltip--align-topLeft memori--completion-provider-status--tooltip"
104
+ class="memori-tooltip memori-tooltip--align-right memori--completion-provider-status--tooltip"
93
105
  >
94
106
  <div
95
107
  class="memori-tooltip--content"
96
108
  >
97
109
  <div>
98
110
  <p>
99
- completionProviderDown
111
+ completionProviderMajorOutage
100
112
  </p>
101
113
  <p>
102
114
  <a
@@ -114,14 +126,20 @@ exports[`renders CompletionProviderStatus unchanged 1`] = `
114
126
  >
115
127
  <svg
116
128
  aria-hidden="true"
117
- class="memori--completion-provider-status--icon"
118
- focusable="false"
119
- role="img"
120
- viewBox="0 0 1024 1024"
129
+ class="memori--completion-provider-status--icon memori--completion-provider-status--icon-error"
130
+ color="currentColor"
131
+ fill="none"
132
+ height="800px"
133
+ viewBox="0 0 24 24"
134
+ width="800px"
121
135
  xmlns="http://www.w3.org/2000/svg"
122
136
  >
123
137
  <path
124
- d="M464 720a48 48 0 1096 0 48 48 0 10-96 0zm16-304v184c0 4.4 3.6 8 8 8h48c4.4 0 8-3.6 8-8V416c0-4.4-3.6-8-8-8h-48c-4.4 0-8 3.6-8 8zm475.7 440l-416-720c-6.2-10.7-16.9-16-27.7-16s-21.6 5.3-27.7 16l-416 720C56 877.4 71.4 904 96 904h832c24.6 0 40-26.6 27.7-48zm-783.5-27.9L512 239.9l339.8 588.2H172.2z"
138
+ d="M12 16H12.01M12 8V12M12 21C16.9706 21 21 16.9706 21 12C21 7.02944 16.9706 3 12 3C7.02944 3 3 7.02944 3 12C3 16.9706 7.02944 21 12 21Z"
139
+ stroke="currentColor"
140
+ stroke-linecap="round"
141
+ stroke-linejoin="round"
142
+ stroke-width="2"
125
143
  />
126
144
  </svg>
127
145
  </div>
@@ -60,7 +60,7 @@ const KnownFacts = ({
60
60
  howMany ?? numberOfResults
61
61
  );
62
62
 
63
- setKnownFacts(knownFacts ?? []);
63
+ setKnownFacts(knownFacts ?? initialKnownFacts);
64
64
  setKnownFactsCount(count ?? 0);
65
65
 
66
66
  if (response.resultCode !== 0) {
@@ -751,14 +751,14 @@ exports[`renders StartPanel with completion provider down unchanged 1`] = `
751
751
  write_and_speak.tryMeButton
752
752
  </button>
753
753
  <div
754
- class="memori-tooltip memori-tooltip--align-topLeft memori--completion-provider-status--tooltip"
754
+ class="memori-tooltip memori-tooltip--align-right memori--completion-provider-status--tooltip"
755
755
  >
756
756
  <div
757
757
  class="memori-tooltip--content"
758
758
  >
759
759
  <div>
760
760
  <p>
761
- completionProviderDown
761
+ completionProviderMajorOutage
762
762
  </p>
763
763
  <p>
764
764
  <a
@@ -776,14 +776,20 @@ exports[`renders StartPanel with completion provider down unchanged 1`] = `
776
776
  >
777
777
  <svg
778
778
  aria-hidden="true"
779
- class="memori--completion-provider-status--icon"
780
- focusable="false"
781
- role="img"
782
- viewBox="0 0 1024 1024"
779
+ class="memori--completion-provider-status--icon memori--completion-provider-status--icon-error"
780
+ color="currentColor"
781
+ fill="none"
782
+ height="800px"
783
+ viewBox="0 0 24 24"
784
+ width="800px"
783
785
  xmlns="http://www.w3.org/2000/svg"
784
786
  >
785
787
  <path
786
- d="M464 720a48 48 0 1096 0 48 48 0 10-96 0zm16-304v184c0 4.4 3.6 8 8 8h48c4.4 0 8-3.6 8-8V416c0-4.4-3.6-8-8-8h-48c-4.4 0-8 3.6-8 8zm475.7 440l-416-720c-6.2-10.7-16.9-16-27.7-16s-21.6 5.3-27.7 16l-416 720C56 877.4 71.4 904 96 904h832c24.6 0 40-26.6 27.7-48zm-783.5-27.9L512 239.9l339.8 588.2H172.2z"
788
+ d="M12 16H12.01M12 8V12M12 21C16.9706 21 21 16.9706 21 12C21 7.02944 16.9706 3 12 3C7.02944 3 3 7.02944 3 12C3 16.9706 7.02944 21 12 21Z"
789
+ stroke="currentColor"
790
+ stroke-linecap="round"
791
+ stroke-linejoin="round"
792
+ stroke-width="2"
787
793
  />
788
794
  </svg>
789
795
  </div>
@@ -1,55 +1,53 @@
1
1
  import { useEffect, useState } from 'react';
2
2
 
3
3
  const separator = ' ';
4
- const defaultDelay = 3;
4
+ const defaultDelay = 15;
5
+ const timeoutMs = 20 * 1000;
6
+ const newWordInterval = 50;
5
7
  const defaultSentences = {
6
8
  en: [
7
- {
8
- delayAfter: defaultDelay,
9
- text: 'Generating an accurate and fancy response...',
10
- },
11
- {
12
- delayAfter: defaultDelay,
13
- text: 'Generating a response that will blow your mind...',
14
- },
15
- {
16
- delayAfter: defaultDelay,
17
- text: 'Generating a response that will make you smile...',
18
- },
19
- { delayAfter: defaultDelay, text: 'Thinking of a response...' },
20
- {
21
- delayAfter: defaultDelay,
22
- text: 'Thinking of a response that will make you smile...',
23
- },
24
- { delayAfter: defaultDelay, text: 'Gathering my thoughts...' },
25
- {
26
- delayAfter: defaultDelay,
27
- text: 'Gathering my thoughts to give you a response...',
28
- },
9
+ { delayAfter: defaultDelay, text: 'Processing in progress...' },
10
+ { delayAfter: defaultDelay, text: "I'm thinking..." },
11
+ { delayAfter: defaultDelay, text: 'Analysing the request...' },
12
+ { delayAfter: defaultDelay, text: 'Preparing the reply...' },
13
+ { delayAfter: defaultDelay, text: 'Gathering information...' },
14
+ { delayAfter: defaultDelay, text: 'Formulating ideas...' },
15
+ { delayAfter: defaultDelay, text: 'One moment please...' },
16
+ { delayAfter: defaultDelay, text: 'Almost ready...' },
17
+ { delayAfter: defaultDelay, text: 'Connecting concepts...' },
18
+ { delayAfter: defaultDelay, text: 'Organising ideas...' },
19
+ { delayAfter: defaultDelay, text: 'Evaluating options...' },
20
+ { delayAfter: defaultDelay, text: 'Looking for the best solution...' },
21
+ { delayAfter: defaultDelay, text: 'Working for you...' },
22
+ { delayAfter: defaultDelay, text: 'Please wait...' },
23
+ { delayAfter: defaultDelay, text: 'Processing data...' },
24
+ { delayAfter: defaultDelay, text: 'Calculating response...' },
25
+ { delayAfter: defaultDelay, text: 'Synthesising information...' },
26
+ { delayAfter: defaultDelay, text: 'Generating content...' },
27
+ { delayAfter: defaultDelay, text: 'Reflecting on question...' },
28
+ { delayAfter: defaultDelay, text: 'Refining the answer' },
29
29
  ],
30
30
  it: [
31
- {
32
- delayAfter: defaultDelay,
33
- text: 'Sto generando una risposta accurata e fantasiosa...',
34
- },
35
- {
36
- delayAfter: defaultDelay,
37
- text: 'Sto generando una risposta che ti farà impazzire...',
38
- },
39
- {
40
- delayAfter: defaultDelay,
41
- text: 'Sto generando una risposta che ti farà sorridere...',
42
- },
43
- { delayAfter: defaultDelay, text: 'Sto pensando ad una risposta...' },
44
- {
45
- delayAfter: defaultDelay,
46
- text: 'Sto pensando ad una risposta che ti farà sorridere...',
47
- },
48
- { delayAfter: defaultDelay, text: 'Sto raccogliendo i miei pensieri...' },
49
- {
50
- delayAfter: defaultDelay,
51
- text: 'Sto raccogliendo i miei pensieri per darti una risposta...',
52
- },
31
+ { delayAfter: defaultDelay, text: 'Elaborazione in corso...' },
32
+ { delayAfter: defaultDelay, text: 'Sto pensando...' },
33
+ { delayAfter: defaultDelay, text: 'Analizzando la richiesta...' },
34
+ { delayAfter: defaultDelay, text: 'Preparando la risposta...' },
35
+ { delayAfter: defaultDelay, text: 'Raccogliendo informazioni...' },
36
+ { delayAfter: defaultDelay, text: 'Formulando idee...' },
37
+ { delayAfter: defaultDelay, text: 'Un momento per favore...' },
38
+ { delayAfter: defaultDelay, text: 'Quasi pronto...' },
39
+ { delayAfter: defaultDelay, text: 'Connettendo i concetti...' },
40
+ { delayAfter: defaultDelay, text: 'Organizzando le idee...' },
41
+ { delayAfter: defaultDelay, text: 'Valutando le opzioni...' },
42
+ { delayAfter: defaultDelay, text: 'Cercando la soluzione migliore...' },
43
+ { delayAfter: defaultDelay, text: 'Sto lavorando per te...' },
44
+ { delayAfter: defaultDelay, text: 'Attendere prego...' },
45
+ { delayAfter: defaultDelay, text: 'Elaborazione dati in corso...' },
46
+ { delayAfter: defaultDelay, text: 'Calcolando la risposta...' },
47
+ { delayAfter: defaultDelay, text: 'Sintetizzando informazioni...' },
48
+ { delayAfter: defaultDelay, text: 'Generando contenuti...' },
49
+ { delayAfter: defaultDelay, text: 'Sto riflettendo sulla domanda...' },
50
+ { delayAfter: defaultDelay, text: 'Perfezionando la risposta...' },
53
51
  ],
54
52
  };
55
53
 
@@ -98,9 +96,12 @@ const Typing = ({
98
96
  : ''
99
97
  );
100
98
  const [shownText, setShownText] = useState('');
99
+ const [elapsedTime, setElapsedTime] = useState(0);
101
100
 
102
101
  useEffect(() => {
103
102
  const interval = setInterval(() => {
103
+ setElapsedTime(prev => prev + newWordInterval);
104
+
104
105
  const letter = text[shownText.length];
105
106
  if (letter !== undefined && text.length > 0) {
106
107
  setShownText(prev => prev + letter);
@@ -119,7 +120,11 @@ const Typing = ({
119
120
  );
120
121
  setShownText('');
121
122
  setIndex(nextIndex);
122
- } else if (!sentences && !sentence && useDefaultSentences) {
123
+ } else if (
124
+ !sentences &&
125
+ !sentence &&
126
+ (useDefaultSentences || elapsedTime > timeoutMs)
127
+ ) {
123
128
  const sentence =
124
129
  defaultSentences[lang][
125
130
  Math.floor(Math.random() * defaultSentences[lang].length)
@@ -127,7 +132,7 @@ const Typing = ({
127
132
  setText(`${sentence.text}${getSeparatorString(sentence.delayAfter)}`);
128
133
  setShownText('');
129
134
  }
130
- }, 50);
135
+ }, newWordInterval);
131
136
 
132
137
  return () => clearInterval(interval);
133
138
  });
@@ -0,0 +1,31 @@
1
+ import React from 'react';
2
+
3
+ const Alert = ({
4
+ className,
5
+ title,
6
+ }: {
7
+ className?: string;
8
+ title?: string;
9
+ }) => (
10
+ <svg
11
+ width="800px"
12
+ height="800px"
13
+ viewBox="0 0 24 24"
14
+ fill="none"
15
+ {...(!title ? { 'aria-hidden': 'true' } : {})}
16
+ xmlns="http://www.w3.org/2000/svg"
17
+ className={className}
18
+ aria-label={title}
19
+ color="currentColor"
20
+ >
21
+ <path
22
+ d="M12 16H12.01M12 8V12M12 21C16.9706 21 21 16.9706 21 12C21 7.02944 16.9706 3 12 3C7.02944 3 3 7.02944 3 12C3 16.9706 7.02944 21 12 21Z"
23
+ stroke="currentColor"
24
+ strokeWidth="2"
25
+ strokeLinecap="round"
26
+ strokeLinejoin="round"
27
+ />
28
+ </svg>
29
+ );
30
+
31
+ export default Alert;
@@ -0,0 +1,31 @@
1
+ import React from 'react';
2
+
3
+ const Info = ({ className, title }: { className?: string; title?: string }) => (
4
+ <svg
5
+ width="800px"
6
+ height="800px"
7
+ viewBox="0 0 24 24"
8
+ fill="none"
9
+ {...(!title ? { 'aria-hidden': 'true' } : {})}
10
+ xmlns="http://www.w3.org/2000/svg"
11
+ className={className}
12
+ aria-label={title}
13
+ >
14
+ <circle cx="12" cy="12" r="10" stroke="currentColor" strokeWidth="1.5" />
15
+ <path
16
+ d="M12 17V11"
17
+ stroke="currentColor"
18
+ strokeWidth="1.5"
19
+ strokeLinecap="round"
20
+ />
21
+ <circle
22
+ cx="1"
23
+ cy="1"
24
+ r="1"
25
+ transform="matrix(1 0 0 -1 11 9)"
26
+ fill="currentColor"
27
+ />
28
+ </svg>
29
+ );
30
+
31
+ export default Info;
@@ -15,8 +15,9 @@ const Warning = ({
15
15
  viewBox="0 0 1024 1024"
16
16
  className={className}
17
17
  aria-label={title}
18
+ color="currentColor"
18
19
  >
19
- <path d="M464 720a48 48 0 1096 0 48 48 0 10-96 0zm16-304v184c0 4.4 3.6 8 8 8h48c4.4 0 8-3.6 8-8V416c0-4.4-3.6-8-8-8h-48c-4.4 0-8 3.6-8 8zm475.7 440l-416-720c-6.2-10.7-16.9-16-27.7-16s-21.6 5.3-27.7 16l-416 720C56 877.4 71.4 904 96 904h832c24.6 0 40-26.6 27.7-48zm-783.5-27.9L512 239.9l339.8 588.2H172.2z"></path>
20
+ <path fill="currentColor" d="M464 720a48 48 0 1096 0 48 48 0 10-96 0zm16-304v184c0 4.4 3.6 8 8 8h48c4.4 0 8-3.6 8-8V416c0-4.4-3.6-8-8-8h-48c-4.4 0-8 3.6-8 8zm475.7 440l-416-720c-6.2-10.7-16.9-16-27.7-16s-21.6 5.3-27.7 16l-416 720C56 877.4 71.4 904 96 904h832c24.6 0 40-26.6 27.7-48zm-783.5-27.9L512 239.9l339.8 588.2H172.2z"></path>
20
21
  </svg>
21
22
  );
22
23
 
@@ -0,0 +1,42 @@
1
+ /* Confirmation dialog styles */
2
+ .memori-confirm-dialog--backdrop {
3
+ position: fixed;
4
+ z-index: 100;
5
+ background-color: rgba(0, 0, 0, 0.5);
6
+ inset: 0;
7
+ }
8
+
9
+ .memori-confirm-dialog--container {
10
+ position: fixed;
11
+ z-index: 101;
12
+ display: flex;
13
+ align-items: center;
14
+ justify-content: center;
15
+ padding: 1rem;
16
+ inset: 0;
17
+ }
18
+
19
+ .memori-confirm-dialog--panel {
20
+ width: 100%;
21
+ max-width: 28rem;
22
+ padding: 1.5rem;
23
+ border-radius: 0.5rem;
24
+ background-color: white;
25
+ box-shadow: 0 20px 25px -5px rgba(0, 0, 0, 0.1), 0 10px 10px -5px rgba(0, 0, 0, 0.04);
26
+ }
27
+
28
+ .memori-confirm-dialog--title {
29
+ margin-bottom: 0.75rem;
30
+ font-size: 1.25rem;
31
+ font-weight: 600;
32
+ }
33
+
34
+ .memori-confirm-dialog--message {
35
+ margin-bottom: 1.5rem;
36
+ }
37
+
38
+ .memori-confirm-dialog--actions {
39
+ display: flex;
40
+ justify-content: flex-end;
41
+ gap: 0.5rem;
42
+ }
@@ -0,0 +1,216 @@
1
+ import React from 'react';
2
+ import { Meta, Story } from '@storybook/react';
3
+ import ConfirmDialog from './ConfirmDialog';
4
+ import Button from './Button';
5
+
6
+ import './ConfirmDialog.css';
7
+
8
+ type Props = React.ComponentProps<typeof ConfirmDialog>;
9
+
10
+ const meta: Meta = {
11
+ title: 'UI/ConfirmDialog',
12
+ component: ConfirmDialog,
13
+ argTypes: {
14
+ isOpen: {
15
+ control: {
16
+ type: 'boolean',
17
+ },
18
+ },
19
+ title: {
20
+ control: {
21
+ type: 'text',
22
+ },
23
+ },
24
+ message: {
25
+ control: {
26
+ type: 'text',
27
+ },
28
+ },
29
+ confirmText: {
30
+ control: {
31
+ type: 'text',
32
+ },
33
+ },
34
+ cancelText: {
35
+ control: {
36
+ type: 'text',
37
+ },
38
+ },
39
+ },
40
+ parameters: {
41
+ controls: { expanded: true },
42
+ },
43
+ };
44
+
45
+ export default meta;
46
+
47
+ const Template: Story<Props> = args => {
48
+ const [isOpen, setIsOpen] = React.useState(!!args.isOpen || false);
49
+
50
+ return (
51
+ <>
52
+ <Button onClick={() => setIsOpen(true)}>Open Confirm Dialog</Button>
53
+ <ConfirmDialog
54
+ {...args}
55
+ isOpen={isOpen}
56
+ onClose={() => setIsOpen(false)}
57
+ onConfirm={() => {
58
+ console.log('Confirmed!');
59
+ setIsOpen(false);
60
+ }}
61
+ />
62
+ </>
63
+ );
64
+ };
65
+
66
+ // Basic examples
67
+ export const Default = Template.bind({});
68
+ Default.args = {
69
+ isOpen: false,
70
+ title: 'Confirm Action',
71
+ message: 'Are you sure you want to proceed with this action?',
72
+ confirmText: 'Confirm',
73
+ cancelText: 'Cancel',
74
+ };
75
+
76
+ export const Open = Template.bind({});
77
+ Open.args = {
78
+ isOpen: true,
79
+ title: 'Confirm Action',
80
+ message: 'Are you sure you want to proceed with this action?',
81
+ confirmText: 'Confirm',
82
+ cancelText: 'Cancel',
83
+ };
84
+
85
+ export const WithCustomTitle = Template.bind({});
86
+ WithCustomTitle.args = {
87
+ isOpen: true,
88
+ title: 'Delete Item',
89
+ message: 'Are you sure you want to proceed with this action?',
90
+ confirmText: 'Confirm',
91
+ cancelText: 'Cancel',
92
+ };
93
+
94
+ export const WithCustomMessage = Template.bind({});
95
+ WithCustomMessage.args = {
96
+ isOpen: true,
97
+ title: 'Confirm Action',
98
+ message: 'This action cannot be undone. All associated data will be permanently deleted from the system.',
99
+ confirmText: 'Confirm',
100
+ cancelText: 'Cancel',
101
+ };
102
+
103
+ export const WithCustomButtonText = Template.bind({});
104
+ WithCustomButtonText.args = {
105
+ isOpen: true,
106
+ title: 'Delete Item',
107
+ message: 'Are you sure you want to delete this item? This action cannot be undone.',
108
+ confirmText: 'Yes, Delete',
109
+ cancelText: 'No, Keep It',
110
+ };
111
+
112
+ // Use case examples
113
+ const DeleteTemplate: Story<Props> = args => {
114
+ const [isOpen, setIsOpen] = React.useState(false);
115
+ const [isDeleted, setIsDeleted] = React.useState(false);
116
+
117
+ const handleConfirm = () => {
118
+ setIsDeleted(true);
119
+ setIsOpen(false);
120
+ console.log('Item deleted!');
121
+ };
122
+
123
+ return (
124
+ <>
125
+ {isDeleted ? (
126
+ <div style={{
127
+ padding: '12px',
128
+ background: '#f8d7da',
129
+ color: '#721c24',
130
+ borderRadius: '4px',
131
+ marginBottom: '20px'
132
+ }}>
133
+ Item has been deleted successfully!
134
+ </div>
135
+ ) : (
136
+ <Button onClick={() => setIsOpen(true)}>Delete Item</Button>
137
+ )}
138
+
139
+ <ConfirmDialog
140
+ {...args}
141
+ isOpen={isOpen}
142
+ onClose={() => setIsOpen(false)}
143
+ onConfirm={handleConfirm}
144
+ />
145
+ </>
146
+ );
147
+ };
148
+
149
+ export const DeleteConfirmation = DeleteTemplate.bind({});
150
+ DeleteConfirmation.args = {
151
+ title: 'Delete Item',
152
+ message: 'Are you sure you want to delete this item? This action cannot be undone.',
153
+ confirmText: 'Delete',
154
+ cancelText: 'Cancel',
155
+ };
156
+
157
+ const SaveTemplate: Story<Props> = args => {
158
+ const [isOpen, setIsOpen] = React.useState(false);
159
+ const [navigatedAway, setNavigatedAway] = React.useState(false);
160
+
161
+ const handleTryNavigate = () => {
162
+ setIsOpen(true);
163
+ };
164
+
165
+ const handleConfirm = () => {
166
+ setNavigatedAway(true);
167
+ setIsOpen(false);
168
+ console.log('Navigated without saving!');
169
+ };
170
+
171
+ return (
172
+ <>
173
+ {navigatedAway ? (
174
+ <div style={{
175
+ padding: '12px',
176
+ background: '#d4edda',
177
+ color: '#155724',
178
+ borderRadius: '4px',
179
+ marginBottom: '20px'
180
+ }}>
181
+ Navigated away without saving changes.
182
+ </div>
183
+ ) : (
184
+ <div>
185
+ <div style={{
186
+ padding: '20px',
187
+ border: '1px solid #ddd',
188
+ borderRadius: '4px',
189
+ marginBottom: '20px'
190
+ }}>
191
+ <h3>Unsaved Form</h3>
192
+ <p>This is a form with unsaved changes.</p>
193
+ <input type="text" placeholder="Your name" style={{ padding: '8px', marginBottom: '10px', width: '100%' }} />
194
+ <textarea placeholder="Your message" style={{ padding: '8px', width: '100%', height: '100px' }} />
195
+ </div>
196
+ <Button onClick={handleTryNavigate}>Navigate Away</Button>
197
+ </div>
198
+ )}
199
+
200
+ <ConfirmDialog
201
+ {...args}
202
+ isOpen={isOpen}
203
+ onClose={() => setIsOpen(false)}
204
+ onConfirm={handleConfirm}
205
+ />
206
+ </>
207
+ );
208
+ };
209
+
210
+ export const UnsavedChanges = SaveTemplate.bind({});
211
+ UnsavedChanges.args = {
212
+ title: 'Unsaved Changes',
213
+ message: 'You have unsaved changes. Are you sure you want to leave without saving?',
214
+ confirmText: 'Leave',
215
+ cancelText: 'Stay',
216
+ };