@kwiz/fluentui 1.0.57 → 1.0.60

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 (121) hide show
  1. package/.dependency-cruiser.js +399 -0
  2. package/dist/controls/ColorPickerDialog.js +1 -1
  3. package/dist/controls/ColorPickerDialog.js.map +1 -1
  4. package/dist/controls/button.js +1 -1
  5. package/dist/controls/button.js.map +1 -1
  6. package/dist/controls/canvas/DrawPad.js +1 -1
  7. package/dist/controls/canvas/DrawPad.js.map +1 -1
  8. package/dist/controls/date.js +2 -2
  9. package/dist/controls/date.js.map +1 -1
  10. package/dist/controls/diagram-picker.js +2 -2
  11. package/dist/controls/diagram-picker.js.map +1 -1
  12. package/dist/controls/dropdown.js +1 -1
  13. package/dist/controls/dropdown.js.map +1 -1
  14. package/dist/controls/file-upload.js +1 -2
  15. package/dist/controls/file-upload.js.map +1 -1
  16. package/dist/controls/index.d.ts +31 -0
  17. package/dist/controls/index.js +32 -0
  18. package/dist/controls/index.js.map +1 -0
  19. package/dist/controls/input.js +1 -1
  20. package/dist/controls/input.js.map +1 -1
  21. package/dist/controls/kwizoverflow.js +1 -1
  22. package/dist/controls/kwizoverflow.js.map +1 -1
  23. package/dist/controls/menu.js +2 -2
  24. package/dist/controls/menu.js.map +1 -1
  25. package/dist/controls/prompt.js +2 -2
  26. package/dist/controls/prompt.js.map +1 -1
  27. package/dist/controls/search.js +1 -1
  28. package/dist/controls/search.js.map +1 -1
  29. package/dist/controls/section.js +1 -1
  30. package/dist/controls/section.js.map +1 -1
  31. package/dist/controls/vertical-content.js +1 -1
  32. package/dist/controls/vertical-content.js.map +1 -1
  33. package/dist/helpers/block-nav.d.ts +11 -0
  34. package/dist/helpers/block-nav.js +79 -0
  35. package/dist/helpers/block-nav.js.map +1 -0
  36. package/dist/helpers/{context.d.ts → context-const.d.ts} +0 -1
  37. package/dist/helpers/context-const.js +4 -0
  38. package/dist/helpers/context-const.js.map +1 -0
  39. package/dist/helpers/context-export.d.ts +7 -0
  40. package/dist/helpers/context-export.js +25 -0
  41. package/dist/helpers/context-export.js.map +1 -0
  42. package/dist/helpers/context-internal.d.ts +1 -0
  43. package/dist/helpers/{context.js → context-internal.js} +2 -3
  44. package/dist/helpers/context-internal.js.map +1 -0
  45. package/dist/helpers/drag-drop/drag-drop-container.d.ts +1 -2
  46. package/dist/helpers/drag-drop/drag-drop-container.js.map +1 -1
  47. package/dist/helpers/drag-drop/drag-drop-context-internal.d.ts +4 -0
  48. package/dist/helpers/drag-drop/drag-drop-context-internal.js +9 -0
  49. package/dist/helpers/drag-drop/drag-drop-context-internal.js.map +1 -0
  50. package/dist/helpers/drag-drop/drag-drop-context.d.ts +1 -9
  51. package/dist/helpers/drag-drop/drag-drop-context.js +2 -9
  52. package/dist/helpers/drag-drop/drag-drop-context.js.map +1 -1
  53. package/dist/helpers/drag-drop/drag-drop.types.d.ts +19 -0
  54. package/dist/helpers/drag-drop/drag-drop.types.js +2 -0
  55. package/dist/helpers/drag-drop/drag-drop.types.js.map +1 -0
  56. package/dist/helpers/drag-drop/{exports.d.ts → index.d.ts} +2 -4
  57. package/dist/helpers/drag-drop/{exports.js → index.js} +1 -1
  58. package/dist/helpers/drag-drop/index.js.map +1 -0
  59. package/dist/helpers/drag-drop/use-draggable.d.ts +1 -8
  60. package/dist/helpers/drag-drop/use-draggable.js +1 -1
  61. package/dist/helpers/drag-drop/use-draggable.js.map +1 -1
  62. package/dist/helpers/drag-drop/use-droppable.d.ts +2 -9
  63. package/dist/helpers/drag-drop/use-droppable.js +1 -2
  64. package/dist/helpers/drag-drop/use-droppable.js.map +1 -1
  65. package/dist/helpers/hooks-events.d.ts +21 -0
  66. package/dist/helpers/hooks-events.js +146 -0
  67. package/dist/helpers/hooks-events.js.map +1 -0
  68. package/dist/helpers/hooks.d.ts +0 -69
  69. package/dist/helpers/hooks.js +1 -310
  70. package/dist/helpers/hooks.js.map +1 -1
  71. package/dist/helpers/index.d.ts +7 -0
  72. package/dist/helpers/index.js +8 -0
  73. package/dist/helpers/index.js.map +1 -0
  74. package/dist/helpers/use-alerts.d.ts +14 -0
  75. package/dist/helpers/use-alerts.js +65 -0
  76. package/dist/helpers/use-alerts.js.map +1 -0
  77. package/dist/helpers/use-toast.d.ts +18 -0
  78. package/dist/helpers/use-toast.js +17 -0
  79. package/dist/helpers/use-toast.js.map +1 -0
  80. package/dist/index.d.ts +3 -36
  81. package/dist/index.js +3 -35
  82. package/dist/index.js.map +1 -1
  83. package/dist/styles/index.d.ts +1 -0
  84. package/dist/styles/index.js +2 -0
  85. package/dist/styles/index.js.map +1 -0
  86. package/package.json +5 -3
  87. package/src/controls/ColorPickerDialog.tsx +1 -1
  88. package/src/controls/button.tsx +1 -1
  89. package/src/controls/canvas/DrawPad.tsx +1 -1
  90. package/src/controls/date.tsx +2 -2
  91. package/src/controls/diagram-picker.tsx +2 -2
  92. package/src/controls/dropdown.tsx +1 -1
  93. package/src/controls/file-upload.tsx +1 -3
  94. package/src/controls/index.ts +31 -0
  95. package/src/controls/input.tsx +1 -1
  96. package/src/controls/kwizoverflow.tsx +1 -1
  97. package/src/controls/menu.tsx +2 -2
  98. package/src/controls/prompt.tsx +2 -2
  99. package/src/controls/search.tsx +1 -1
  100. package/src/controls/section.tsx +1 -1
  101. package/src/controls/vertical-content.tsx +1 -1
  102. package/src/helpers/block-nav.tsx +89 -0
  103. package/src/helpers/{context.ts → context-const.ts} +1 -13
  104. package/src/helpers/context-export.tsx +31 -0
  105. package/src/helpers/context-internal.ts +14 -0
  106. package/src/helpers/drag-drop/drag-drop-container.tsx +1 -2
  107. package/src/helpers/drag-drop/drag-drop-context-internal.tsx +10 -0
  108. package/src/helpers/drag-drop/drag-drop-context.tsx +5 -15
  109. package/src/helpers/drag-drop/drag-drop.types.ts +21 -0
  110. package/src/helpers/drag-drop/{exports.ts → index.ts} +2 -4
  111. package/src/helpers/drag-drop/use-draggable.ts +2 -10
  112. package/src/helpers/drag-drop/use-droppable.ts +3 -12
  113. package/src/helpers/hooks-events.ts +153 -0
  114. package/src/helpers/hooks.tsx +1 -360
  115. package/src/helpers/index.ts +8 -0
  116. package/src/helpers/use-alerts.tsx +75 -0
  117. package/src/helpers/use-toast.tsx +30 -0
  118. package/src/index.ts +3 -37
  119. package/src/styles/index.ts +1 -0
  120. package/dist/helpers/context.js.map +0 -1
  121. package/dist/helpers/drag-drop/exports.js.map +0 -1
@@ -1,10 +1,6 @@
1
- import { Label, Link, makeStyles, Toast, ToastBody, Toaster, ToastFooter, ToastIntent, ToastTitle, useId, useToastController } from "@fluentui/react-components";
2
- import { IDictionary, isDebug, isFunction, isNotEmptyArray, isNullOrEmptyString, isPrimitiveValue, isString, jsonClone, jsonStringify, LoggerLevel, objectsEqual, wrapFunction } from "@kwiz/common";
1
+ import { isFunction, isNotEmptyArray, isNullOrEmptyString, isPrimitiveValue, jsonClone, jsonStringify, LoggerLevel, objectsEqual, wrapFunction } from "@kwiz/common";
3
2
  import { MutableRefObject, SetStateAction, useCallback, useEffect, useRef, useState } from "react";
4
3
  import { GetLogger } from "../_modules/config";
5
- import { IPrompterProps, Prompter } from "../controls/prompt";
6
- import { KnownClassNames } from "../styles/styles";
7
- import { iKWIZFluentContext, useKWIZFluentContext } from "./context";
8
4
 
9
5
  const logger = GetLogger("helpers/hooks");
10
6
  /** Empty array ensures that effect is only run on mount */
@@ -99,359 +95,4 @@ export function useStateEX<ValueType>(initialValue: ValueType, options?: {
99
95
  }), []);
100
96
 
101
97
  return [value, setValue, currentValue];
102
- }
103
- export function useTrackFocus(props: { onFocus: () => void, onLoseFocus: () => void, ref?: MutableRefObject<HTMLElement> }) {
104
- const wrapperDiv = props.ref || useRef<HTMLDivElement>(null);
105
- useEffect(() => {
106
- function focusIn(e: FocusEvent) {
107
- let elm = e.target as HTMLElement;//document.activeElement;
108
- if (wrapperDiv.current) {
109
- while (elm && elm !== wrapperDiv.current) {
110
- elm = elm.parentElement;
111
- }
112
- } else elm = null;
113
- if (wrapperDiv.current && elm === wrapperDiv.current) props.onFocus();
114
- else props.onLoseFocus();
115
- }
116
-
117
- if (wrapperDiv.current) {
118
- if (wrapperDiv.current) wrapperDiv.current.tabIndex = 1;
119
- window.addEventListener("focusin", focusIn);
120
- // Remove event listener on cleanup
121
- return () => window.removeEventListener("focusin", focusIn);
122
- }
123
- }, [wrapperDiv.current]);
124
- return wrapperDiv;
125
- }
126
- export function useWindowSize() {
127
- // Initialize state with undefined width/height so server and client renders match
128
- // Learn more here: https://joshwcomeau.com/react/the-perils-of-rehydration/
129
- const [windowSize, setWindowSize] = useState<{
130
- width: number,
131
- height: number
132
- }>({
133
- width: undefined,
134
- height: undefined
135
- });
136
- useEffect(() => {
137
- // Handler to call on window resize
138
- function handleResize() {
139
-
140
- // Set window width/height to state
141
- setWindowSize({
142
- width: window.innerWidth,
143
- height: window.innerHeight
144
- });
145
- }
146
- // Add event listener
147
- window.addEventListener("resize", handleResize);
148
- // Call handler right away so state gets updated with initial window size
149
- handleResize();
150
- // Remove event listener on cleanup
151
- return () => window.removeEventListener("resize", handleResize);
152
- }, useEffectOnlyOnMount);
153
- return windowSize;
154
- }
155
- export function useElementSize(elm: HTMLElement) {
156
- // Initialize state with undefined width/height so server and client renders match
157
- // Learn more here: https://joshwcomeau.com/react/the-perils-of-rehydration/
158
- const [elmSize, setELmSize] = useState<{
159
- width: number,
160
- height: number
161
- }>({
162
- width: undefined,
163
- height: undefined
164
- });
165
- useEffect(() => {
166
- if (elm) {
167
- // Handler to call on elm resize
168
- function handleResize() {
169
- // Set elm width/height to state
170
- setELmSize({
171
- width: (elm instanceof Window) ? elm.innerWidth : elm.clientWidth,
172
- height: (elm instanceof Window) ? elm.innerHeight : elm.clientHeight,
173
- });
174
- }
175
- // Add event listener
176
- const observer = new ResizeObserver(handleResize);
177
- observer.observe(elm);
178
- // Call handler right away so state gets updated with initial elm size
179
- handleResize();
180
- // Remove event listener on cleanup
181
- return () => observer.disconnect();
182
- }
183
- }, [elm]);
184
- return elmSize;
185
- }
186
- export function useIsInPrint() {
187
- // Initialize state with false
188
- const [printMode, setPrintMode] = useState<boolean>(false);
189
- useEffect(() => {
190
- function forcePrint(e: KeyboardEvent) {
191
- if (e.ctrlKey && e.shiftKey && e.altKey) {
192
- if (e.key.toLocaleLowerCase() === "q") {
193
- document.body.classList.remove(KnownClassNames.print);
194
- handlePrint(e, false);
195
- }
196
- else {
197
- console.warn('forced print mode - to exit refresh to ctrl+shift+alt+q');
198
- document.body.classList.add(KnownClassNames.print);
199
- handlePrint(e, true);
200
- }
201
- }
202
- }
203
- // Handler to call on printing
204
- function handlePrint(e?: Event, force?: boolean) {
205
- if (force === true) setPrintMode(true);
206
- else if (window.matchMedia) {
207
- var mediaQueryList = window.matchMedia('print');
208
- if (mediaQueryList.matches) {
209
- setPrintMode(true);
210
- } else {
211
- setPrintMode(false);
212
- }
213
- }
214
- }
215
- // Add event listener
216
- window.addEventListener("print", handlePrint);
217
- if (isDebug())
218
- window.addEventListener("keydown", forcePrint);
219
- // Call handler right away so state gets updated with initial printing state
220
- handlePrint();
221
- // Remove event listener on cleanup
222
- return () => {
223
- window.removeEventListener("print", handlePrint);
224
- if (isDebug())
225
- window.removeEventListener("keydown", forcePrint);
226
- };
227
- }, useEffectOnlyOnMount);
228
- return printMode;
229
- }
230
- export interface iBlockNav {
231
- setMessage: (id: string, message?: string) => void;
232
- onNav: (nav: () => void) => void;
233
- navPrompt?: JSX.Element;
234
-
235
- }
236
- /** set block message if you want to block nav.
237
- * - call setMessage to add a blocker message
238
- * - call onNav when you have internal navigation (open / close popups)
239
- * - render the navPrompt control to your page
240
- * FYI for page unload, most modern browsers won't show your message but a generic one instead. */
241
- export function useBlockNav(): iBlockNav {
242
- const [, setBlockNavMessages, blockNavMessagesRef] = useStateEX<IDictionary<string>>({});
243
- const [_prompt, setPrompt] = useStateEX<IPrompterProps>(null);
244
-
245
- const getMessagesArr = useCallback(() => {
246
- return Object.keys(blockNavMessagesRef.current).map(id => blockNavMessagesRef.current[id]);
247
- }, useEffectOnlyOnMount);
248
-
249
- const getMessages = useCallback(() => {
250
- return getMessagesArr().join();
251
- }, useEffectOnlyOnMount);
252
-
253
- const onNav = useCallback((nav: () => void) => {
254
- let messages = getMessagesArr();
255
- if (isNotEmptyArray(messages)) {
256
- //need to release react to re-render the prompt
257
- window.setTimeout(() => {
258
- //prompt, if ok - clear messages and nav.
259
- setPrompt({
260
- okButtonText: "Leave",
261
- cancelButtonText: "Cancel",
262
- title: "Leave page?",
263
- children: messages.length > 1
264
- ? <ul>
265
- {messages.map((m, i) => <li key={`m${i}`}>{m}</li>)}
266
- </ul>
267
- : <p>{messages[0]}</p>,
268
- onCancel: () => setPrompt(null),
269
- onOK: () => {
270
- setPrompt(null);
271
- setBlockNavMessages({});//clear messages
272
- nav();
273
- }
274
- });
275
- }, 1);
276
- }
277
- else nav();
278
- }, useEffectOnlyOnMount);
279
-
280
-
281
- useEffect(() => {
282
- function handleBeforeUnload(e: BeforeUnloadEvent) {
283
- //todo: use blockMessageRef.current so that we don't have to re-register every time message changes.
284
- //otherwise we would have to add blockMessage as a dependency for this useEffect
285
- const message = getMessages();
286
- if (!isNullOrEmptyString(message)) {
287
- e.preventDefault();
288
- e.returnValue = message;
289
- }
290
- }
291
- // Add event listener
292
- window.addEventListener("beforeunload", handleBeforeUnload);
293
- // Remove event listener on cleanup
294
- return () => window.removeEventListener("beforeunload", handleBeforeUnload);
295
- }, useEffectOnlyOnMount);
296
- return {
297
- setMessage: (id: string, message?: string) => {
298
- let current = jsonClone(blockNavMessagesRef.current);
299
- if (isNullOrEmptyString(message))
300
- delete current[id];
301
- else current[id] = message;
302
- if (!objectsEqual(current, blockNavMessagesRef.current))
303
- setBlockNavMessages(current);
304
- },
305
- // clearMessages: () => {
306
- // setBlockNavMessages({});
307
- // },
308
- // getMessages,
309
- // getMessagesArr,
310
- onNav,
311
- navPrompt: _prompt ? <Prompter {..._prompt} /> : undefined
312
- };
313
- }
314
-
315
- export function useKeyDown(options: {
316
- //default use document
317
- elm?: HTMLElement | Document;
318
- onEnter?: (e: KeyboardEvent) => void;
319
- onEscape?: (e: KeyboardEvent) => void;
320
- onKeyDown?: (e: KeyboardEvent) => void;
321
- }) {
322
- let elm = options.elm || document;
323
-
324
- useEffect(() => {
325
- let handler = (e: KeyboardEvent) => {
326
- if (e.key === "Enter" && isFunction(options.onEnter)) options.onEnter(e);
327
- else if (e.key === "Escape" && isFunction(options.onEscape)) options.onEscape(e);
328
- if (isFunction(options.onKeyDown))
329
- options.onKeyDown(e);
330
- };
331
- elm.addEventListener("keydown", handler);
332
- return () => elm.removeEventListener("keydown", handler);
333
- }, [elm, options.onEnter, options.onEscape, options.onKeyDown]);
334
- }
335
-
336
-
337
- export function useToast() {
338
- const ctx = useKWIZFluentContext();
339
- const toasterId = useId("toaster");
340
- const { dispatchToast } = useToastController(toasterId);
341
- return {
342
- control: <Toaster mountNode={ctx.mountNode} toasterId={toasterId} />,
343
- dispatch: (info: {
344
- title?: string;
345
- body?: string;
346
- subtitle?: string;
347
- titleAction?: { text: string, onClick: () => void },
348
- footerActions?: { text: string, onClick: () => void }[],
349
- intent?: ToastIntent
350
- }) => {
351
- dispatchToast(<Toast>
352
- {info.title && <ToastTitle action={info.titleAction ? <Link onClick={info.titleAction.onClick}>{info.titleAction.text}</Link> : undefined}>{info.title}</ToastTitle>}
353
- {info.body && <ToastBody subtitle={info.subtitle}>{info.body}</ToastBody>}
354
- {isNotEmptyArray(info.footerActions) &&
355
- <ToastFooter>
356
- {info.footerActions.map((a, i) => <Link key={`l${i}`} onClick={a.onClick}>{a.text}</Link>)}
357
- </ToastFooter>
358
- }
359
- </Toast>, { intent: info.intent || "info" });
360
- }
361
- }
362
- }
363
-
364
- export const useContextStyles = makeStyles({
365
- root: {
366
- "& *": {
367
- scrollbarWidth: "thin"
368
- }
369
- },
370
- })
371
- export function useKWIZFluentContextProvider(options: {
372
- root?: React.MutableRefObject<HTMLDivElement>;
373
- ctx?: iKWIZFluentContext;
374
- }) {
375
- const classes = useContextStyles();
376
- let v: iKWIZFluentContext = options && options.ctx || {};
377
- const [kwizFluentContext, setKwizFluentContext] = useState<iKWIZFluentContext>(v);
378
- useEffect(() => {
379
- options.root?.current?.classList.add(...classes.root.split(' '));
380
- // ref only updates in useEffect, not in useMemo or anything else.
381
- // we need to set it into state so it will trigger a ui update
382
- setKwizFluentContext({
383
- ...v,
384
- mountNode: options.root.current
385
- });
386
- }, [options.root]);
387
- return kwizFluentContext;
388
- }
389
-
390
- export interface iAlerts {
391
- promptEX: (info: IPrompterProps) => void;
392
- confirmEX: (message: string | JSX.Element, onOK?: () => void, onCancel?: () => void) => Promise<boolean>;
393
- alertEX: (message: string | JSX.Element, onOK?: () => void) => Promise<void>;
394
- alertPrompt?: JSX.Element;
395
- close: () => void;
396
- }
397
- /** set block message if you want to block nav.
398
- * - call setMessage to add a blocker message
399
- * - call onNav when you have internal navigation (open / close popups)
400
- * - render the navPrompt control to your page
401
- * FYI for page unload, most modern browsers won't show your message but a generic one instead. */
402
- export function useAlerts(): iAlerts {
403
- const [_prompt, _setPrompt] = useStateEX<IPrompterProps>(null);
404
-
405
- const promptEX = useCallback((info: IPrompterProps) => {
406
- //need to release react to re-render the prompt
407
- window.setTimeout(() => {
408
- //prompt, if ok - clear messages and nav.
409
- _setPrompt({
410
- ...info,
411
- onCancel: () => {
412
- _setPrompt(null);
413
- if (isFunction(info.onCancel)) info.onCancel();
414
- },
415
- onOK: () => {
416
- _setPrompt(null);
417
- if (isFunction(info.onOK)) info.onOK();
418
- }
419
- });
420
- }, 1);
421
- }, useEffectOnlyOnMount);
422
-
423
- const confirmEX = useCallback((message: string | JSX.Element, onOK?: () => void, onCancel?: () => void) => {
424
- return new Promise<boolean>(resolve => {
425
- promptEX({
426
- children: isString(message) ? <Label>{message}</Label> : message,
427
- onCancel: () => {
428
- if (isFunction(onCancel)) onCancel();
429
- resolve(false);
430
- },
431
- onOK: () => {
432
- if (isFunction(onOK)) onOK();
433
- resolve(true);
434
- }
435
- });
436
- });
437
- }, useEffectOnlyOnMount);
438
-
439
- const alertEX = useCallback((message: string | JSX.Element, onOK: () => void) => {
440
- return new Promise<void>(resolve => {
441
- promptEX({
442
- children: isString(message) ? <Label>{message}</Label> : message,
443
- hideCancel: true,
444
- onOK: () => {
445
- if (isFunction(onOK)) onOK();
446
- resolve();
447
- }
448
- });
449
- });
450
- }, useEffectOnlyOnMount);
451
-
452
- return {
453
- promptEX, confirmEX, alertEX,
454
- alertPrompt: _prompt ? <Prompter {..._prompt} /> : undefined,
455
- close: () => _setPrompt(null)
456
- };
457
98
  }
@@ -0,0 +1,8 @@
1
+ export * from './block-nav';
2
+ export * from './context-export';
3
+ export * from './drag-drop';
4
+ export * from './hooks';
5
+ export * from './hooks-events';
6
+ export * from './use-alerts';
7
+ export * from './use-toast';
8
+
@@ -0,0 +1,75 @@
1
+ import { Label } from "@fluentui/react-components";
2
+ import { isFunction, isString } from "@kwiz/common";
3
+ import { useCallback } from "react";
4
+ import { IPrompterProps, Prompter } from "../controls/prompt";
5
+ import { useEffectOnlyOnMount, useStateEX } from "./hooks";
6
+
7
+ export interface iAlerts {
8
+ promptEX: (info: IPrompterProps) => void;
9
+ confirmEX: (message: string | JSX.Element, onOK?: () => void, onCancel?: () => void) => Promise<boolean>;
10
+ alertEX: (message: string | JSX.Element, onOK?: () => void) => Promise<void>;
11
+ alertPrompt?: JSX.Element;
12
+ close: () => void;
13
+ }
14
+
15
+ /** set block message if you want to block nav.
16
+ * - call setMessage to add a blocker message
17
+ * - call onNav when you have internal navigation (open / close popups)
18
+ * - render the navPrompt control to your page
19
+ * FYI for page unload, most modern browsers won't show your message but a generic one instead. */
20
+ export function useAlerts(): iAlerts {
21
+ const [_prompt, _setPrompt] = useStateEX<IPrompterProps>(null);
22
+
23
+ const promptEX = useCallback((info: IPrompterProps) => {
24
+ //need to release react to re-render the prompt
25
+ window.setTimeout(() => {
26
+ //prompt, if ok - clear messages and nav.
27
+ _setPrompt({
28
+ ...info,
29
+ onCancel: () => {
30
+ _setPrompt(null);
31
+ if (isFunction(info.onCancel)) info.onCancel();
32
+ },
33
+ onOK: () => {
34
+ _setPrompt(null);
35
+ if (isFunction(info.onOK)) info.onOK();
36
+ }
37
+ });
38
+ }, 1);
39
+ }, useEffectOnlyOnMount);
40
+
41
+ const confirmEX = useCallback((message: string | JSX.Element, onOK?: () => void, onCancel?: () => void) => {
42
+ return new Promise<boolean>(resolve => {
43
+ promptEX({
44
+ children: isString(message) ? <Label>{message}</Label> : message,
45
+ onCancel: () => {
46
+ if (isFunction(onCancel)) onCancel();
47
+ resolve(false);
48
+ },
49
+ onOK: () => {
50
+ if (isFunction(onOK)) onOK();
51
+ resolve(true);
52
+ }
53
+ });
54
+ });
55
+ }, useEffectOnlyOnMount);
56
+
57
+ const alertEX = useCallback((message: string | JSX.Element, onOK: () => void) => {
58
+ return new Promise<void>(resolve => {
59
+ promptEX({
60
+ children: isString(message) ? <Label>{message}</Label> : message,
61
+ hideCancel: true,
62
+ onOK: () => {
63
+ if (isFunction(onOK)) onOK();
64
+ resolve();
65
+ }
66
+ });
67
+ });
68
+ }, useEffectOnlyOnMount);
69
+
70
+ return {
71
+ promptEX, confirmEX, alertEX,
72
+ alertPrompt: _prompt ? <Prompter {..._prompt} /> : undefined,
73
+ close: () => _setPrompt(null)
74
+ };
75
+ }
@@ -0,0 +1,30 @@
1
+ import { Link, Toast, ToastBody, Toaster, ToastFooter, ToastIntent, ToastTitle, useId, useToastController } from "@fluentui/react-components";
2
+ import { isNotEmptyArray } from "@kwiz/common";
3
+ import { useKWIZFluentContext } from "./context-internal";
4
+
5
+ export function useToast() {
6
+ const ctx = useKWIZFluentContext();
7
+ const toasterId = useId("toaster");
8
+ const { dispatchToast } = useToastController(toasterId);
9
+ return {
10
+ control: <Toaster mountNode={ctx.mountNode} toasterId={toasterId} />,
11
+ dispatch: (info: {
12
+ title?: string;
13
+ body?: string;
14
+ subtitle?: string;
15
+ titleAction?: { text: string, onClick: () => void },
16
+ footerActions?: { text: string, onClick: () => void }[],
17
+ intent?: ToastIntent
18
+ }) => {
19
+ dispatchToast(<Toast>
20
+ {info.title && <ToastTitle action={info.titleAction ? <Link onClick={info.titleAction.onClick}>{info.titleAction.text}</Link> : undefined}>{info.title}</ToastTitle>}
21
+ {info.body && <ToastBody subtitle={info.subtitle}>{info.body}</ToastBody>}
22
+ {isNotEmptyArray(info.footerActions) &&
23
+ <ToastFooter>
24
+ {info.footerActions.map((a, i) => <Link key={`l${i}`} onClick={a.onClick}>{a.text}</Link>)}
25
+ </ToastFooter>
26
+ }
27
+ </Toast>, { intent: info.intent || "info" });
28
+ }
29
+ }
30
+ }
package/src/index.ts CHANGED
@@ -1,37 +1,3 @@
1
- export * from './controls/accordion';
2
- export * from './controls/button';
3
- export * from './controls/canvas/DrawPad';
4
- export * from './controls/card';
5
- export * from './controls/card-list';
6
- export * from './controls/centered';
7
- export * from './controls/ColorPickerDialog';
8
- export * from './controls/date';
9
- export * from './controls/diagram-picker';
10
- export * from './controls/divider';
11
- export * from './controls/dropdown';
12
- export * from './controls/error-boundary';
13
- export * from './controls/field-editor';
14
- export * from './controls/file-upload';
15
- export * from './controls/horizontal';
16
- export * from './controls/html-editor/editor';
17
- export * from './controls/input';
18
- export * from './controls/kwizoverflow';
19
- export * from './controls/list';
20
- export * from './controls/loading';
21
- export * from './controls/menu';
22
- export * from './controls/please-wait';
23
- export * from './controls/progress-bar';
24
- export * from './controls/prompt';
25
- export * from './controls/qrcode';
26
- export * from './controls/search';
27
- export * from './controls/section';
28
- export * from './controls/svg';
29
- export * from './controls/toolbar';
30
- export * from './controls/vertical';
31
- export * from './controls/vertical-content';
32
- export { KWIZFluentContext, useKWIZFluentContext } from './helpers/context';
33
- export type { iKWIZFluentContext } from './helpers/context';
34
- export * from './helpers/drag-drop/exports';
35
- export * from './helpers/hooks';
36
- export { commonSizes, KnownClassNames } from './styles/styles';
37
-
1
+ export * from './controls';
2
+ export * from './helpers';
3
+ export * from './styles';
@@ -0,0 +1 @@
1
+ export { commonSizes, KnownClassNames } from './styles';
@@ -1 +0,0 @@
1
- {"version":3,"file":"context.js","sourceRoot":"","sources":["../../src/helpers/context.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,iBAAiB,EAAE,MAAM,cAAc,CAAC;AACjD,OAAO,KAAK,MAAM,OAAO,CAAC;AA2B1B,gBAAgB;AAChB,MAAM,CAAC,MAAM,iBAAiB,GAAG,KAAK,CAAC,aAAa,CAAqB,IAAI,CAAC,CAAC;AAC/E,kCAAkC;AAClC,MAAM,UAAU,oBAAoB;IAChC,IAAI,GAAG,GAAG,KAAK,CAAC,UAAU,CAAC,iBAAiB,CAAC,IAAI,EAAE,CAAC;IACpD,cAAc;IACd,IAAI,iBAAiB,CAAC,GAAG,CAAC,eAAe,CAAC;QACtC,GAAG,CAAC,eAAe,GAAG,WAAW,CAAC;IACtC,IAAI,iBAAiB,CAAC,GAAG,CAAC,WAAW,CAAC;QAClC,GAAG,CAAC,WAAW,GAAG,UAAU,CAAC;IACjC,OAAO,GAAG,CAAC;AACf,CAAC"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"exports.js","sourceRoot":"","sources":["../../../src/helpers/drag-drop/exports.ts"],"names":[],"mappings":"AAIA,OAAO,EAAE,iBAAiB,EAAE,MAAM,uBAAuB,CAAC;AAC1D,OAAO,EAAE,uBAAuB,EAAE,kBAAkB,EAAE,MAAM,qBAAqB,CAAC"}